Skip to content

Commit

Permalink
Initial horizontal scroll bars
Browse files Browse the repository at this point in the history
Affects: #14
Affects: #13
  • Loading branch information
io7m committed Nov 25, 2023
1 parent c225d6f commit ef2f5f5
Show file tree
Hide file tree
Showing 101 changed files with 2,375 additions and 29 deletions.
Expand Up @@ -36,8 +36,6 @@
import java.util.Optional;
import java.util.function.Predicate;

import static java.lang.Math.min;

/**
* The type of components.
*/
Expand Down Expand Up @@ -81,22 +79,39 @@ default PAreaSizeI<SySpaceParentRelativeType> layout(
Objects.requireNonNull(layoutContext, "layoutContext");
Objects.requireNonNull(constraints, "constraints");

/*
* First, consult the theme to see if there are size constraints specified
* for this component. Derive a new set of constraints that try to
* satisfy the theme whilst also satisfying the passed in constraints.
*/

var limitedConstraints =
layoutContext.deriveThemeConstraints(constraints, this);

/*
* Then, limit the derived constraints further by the component's size
* limit.
*/

final var sizeLimit =
this.sizeUpperLimit().get();

final var limitedConstraints =
new SyConstraints(
constraints.sizeMinimumX(),
constraints.sizeMinimumY(),
min(constraints.sizeMaximumX(), sizeLimit.sizeX()),
min(constraints.sizeMaximumY(), sizeLimit.sizeY())
);
limitedConstraints = limitedConstraints.deriveLimitedBy(sizeLimit);

/*
* Now, lay out all child components according to the derived constraints.
*/

final var childNodes = this.node().children();
for (final var childNode : childNodes) {
childNode.value().layout(layoutContext, limitedConstraints);
}

/*
* Finally, resize this component to the maximum size allowed by the
* constraints.
*/

final PAreaSizeI<SySpaceParentRelativeType> newSize =
limitedConstraints.sizeMaximum();
this.setSize(newSize);
Expand Down
Expand Up @@ -146,10 +146,10 @@ public boolean isSatisfiedBy(
{
final var xOk =
size.sizeX() >= this.sizeMinimumX
&& size.sizeX() <= this.sizeMaximumX;
&& size.sizeX() <= this.sizeMaximumX;
final var yOk =
size.sizeY() >= this.sizeMinimumY
&& size.sizeY() <= this.sizeMaximumY;
&& size.sizeY() <= this.sizeMaximumY;
return xOk && yOk;
}

Expand All @@ -166,4 +166,24 @@ public SyConstraints withoutMinimum()
this.sizeMaximumY
);
}

/**
* Derive a new set of constraints that obey the current constraints whilst
* attempting to constrain to the given size.
*
* @param size The size
*
* @return A new set of constraints
*/

public SyConstraints deriveLimitedBy(
final PAreaSizeI<?> size)
{
return new SyConstraints(
this.sizeMinimumX(),
this.sizeMinimumY(),
min(this.sizeMaximumX(), size.sizeX()),
min(this.sizeMaximumY(), size.sizeY())
);
}
}
Expand Up @@ -34,4 +34,28 @@ public interface SyImageViewType

@Override
AttributeType<Optional<URI>> imageURI();

/**
* A convenience method to set the image URI.
*
* @param uri The image URI
*/

default void setImageURI(
final URI uri)
{
this.imageURI().set(Optional.of(uri));
}

/**
* A convenience method to set the image URI.
*
* @param uri The image URI
*/

default void setImageURI(
final String uri)
{
this.setImageURI(URI.create(uri));
}
}
@@ -0,0 +1,77 @@
/*
* Copyright © 2023 Mark Raynsford <code@io7m.com> https://www.io7m.com
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/


package com.io7m.jsycamore.api.components;

import java.util.Objects;

import static java.lang.StrictMath.clamp;

/**
* A drag operation being performed on a scrollbar.
*
* @param dragKind The kind of operation
* @param dragStart The scroll position at the start of the operation
* @param dragNow The scroll position now
*/

public record SyScrollBarDrag(
Kind dragKind,
double dragStart,
double dragNow)
{
/**
* The kind of drag operation.
*/

public enum Kind
{
/**
* Dragging just started.
*/

DRAG_STARTED,

/**
* Dragging is being continued.
*/

DRAG_CONTINUED,

/**
* Dragging just ended.
*/

DRAG_ENDED
}

/**
* A drag operation being performed on a scrollbar.
*
* @param dragKind The kind of operation
* @param dragStart The scroll position at the start of the operation
* @param dragNow The scroll position now
*/

public SyScrollBarDrag
{
Objects.requireNonNull(dragKind, "dragKind");

dragStart = clamp(dragStart, 0.0, 1.0);
dragNow = clamp(dragNow, 0.0, 1.0);
}
}
Expand Up @@ -20,18 +20,30 @@

import java.util.List;

import static com.io7m.jsycamore.api.themes.SyThemeClassNameStandard.SCROLLBAR;
import static com.io7m.jsycamore.api.themes.SyThemeClassNameStandard.SCROLLBAR_HORIZONTAL;

/**
* Read-only access to scrollbars.
*/

public interface SyScrollbarReadableType
extends SyComponentReadableType
public interface SyScrollBarHorizontalReadableType
extends SyScrollBarReadableType
{
@Override
default List<SyThemeClassNameType> themeClassesDefaultForComponent()
{
return List.of(SCROLLBAR);
return List.of(SCROLLBAR_HORIZONTAL);
}

/**
* @return The scrollbar left button
*/

SyButtonReadableType buttonLeft();

/**
* @return The scrollbar right button
*/

SyButtonReadableType buttonRight();
}
@@ -0,0 +1,107 @@
/*
* Copyright © 2021 Mark Raynsford <code@io7m.com> https://www.io7m.com
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

package com.io7m.jsycamore.api.components;

import java.util.function.Consumer;

/**
* Write access to scrollbars.
*/

public interface SyScrollBarHorizontalType
extends SyScrollBarHorizontalReadableType, SyScrollBarType
{
/**
* Set a listener that will be executed when the left scroll button is clicked.
*
* @param runnable The listener
*/

void setOnClickLeftListener(Runnable runnable);

/**
* Remove any listeners that are executed when the left button is clicked.
*
* @see #setOnClickLeftListener(Runnable)
*/

void removeOnClickLeftListener();

/**
* Set a listener that will be executed when the right scroll button is clicked.
*
* @param runnable The listener
*/

void setOnClickRightListener(Runnable runnable);

/**
* Remove any listeners that are executed when the right button is clicked.
*
* @see #setOnClickRightListener(Runnable)
*/

void removeOnClickRightListener();

/**
* Set a listener that will be executed when the left scroll button is clicked.
*
* @param listener The listener
*/

void setOnThumbDragListener(Consumer<SyScrollBarDrag> listener);

/**
* Remove any listeners that are executed when the left button is clicked.
*
* @see #setOnThumbDragListener(Consumer)
*/

void removeOnThumbDragListener();

/**
* Set the scroll position in the range {@code [0, 1]}.
*
* @param position The position
*/

void setScrollPosition(double position);

/**
* Set the scroll position snapping value in the range {@code [0, 1]}. The
* given fraction is used to determine how many divisions will be used within
* the scrolling space. For example, a value of {@code 1.0 / 4.0} will yield
* four possible snapped position values.
*
* @param fraction The fraction
*/

void setScrollPositionSnapping(double fraction);

/**
* Scrollbars are typically used to scroll a visible portion of some larger
* structure. Some implementations might want to scale the scrollbar thumb
* based on the portion of the visible space that is visible. A value of
* {@code 0.0} means that an infinitely small piece of the larger structure
* is visible. A value of {@code 1.0} means that the entirety of the larger
* structure is visible.
*
* @param amount The amount shown
*/

void setScrollAmountShown(double amount);
}
@@ -0,0 +1,50 @@
/*
* Copyright © 2021 Mark Raynsford <code@io7m.com> https://www.io7m.com
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

package com.io7m.jsycamore.api.components;

/**
* Read-only access to scrollbars.
*/

public interface SyScrollBarReadableType
extends SyComponentReadableType
{
/**
* @return The scrollbar thumb
*/

SyComponentReadableType thumb();

/**
*
* @return The scrollbar track
*/

SyComponentReadableType track();

/**
* @return The scroll position in the range {@code [0, 1]}
*/

double scrollPosition();

/**
* @return The scroll position snapping value in the range {@code [0, 1]}
*/

double scrollPositionSnapping();
}

0 comments on commit ef2f5f5

Please sign in to comment.