Create VScrollable container

This commit is contained in:
2021-03-17 20:25:27 +01:00
parent 4fb80d2c5a
commit e7b66d4d50
8 changed files with 163 additions and 5 deletions

View File

@@ -113,4 +113,6 @@ public interface GUI extends Renderable, Disposable, KeyEventHandler {
void imagePattern(float x, float y, float width, float height, float angle, float alpha, Image image, Paint target);
void clip(float x, float y, float width, float height);
void resetClip();
}

View File

@@ -8,6 +8,7 @@ import java.util.LinkedList;
import java.util.List;
import static java.util.Collections.unmodifiableList;
import static java.util.Objects.requireNonNull;
public abstract class BaseContainer extends BaseComponent implements Container {
protected final List<Component> children = new LinkedList<>();
@@ -24,13 +25,13 @@ public abstract class BaseContainer extends BaseComponent implements Container {
@Override
public void add(Component component) {
this.children.add(component);
this.children.add(requireNonNull(component));
component.setParent(this);
}
@Override
public void remove(Component component) {
this.children.remove(component);
this.children.remove(requireNonNull(component));
component.setParent(null);
}

View File

@@ -0,0 +1,25 @@
package com.bartlomiejpluta.base.api.game.gui.component;
import com.bartlomiejpluta.base.api.game.context.Context;
import com.bartlomiejpluta.base.api.game.gui.base.GUI;
public abstract class SingleChildContainer extends BaseContainer {
protected Component child;
protected SingleChildContainer(Context context, GUI gui) {
super(context, gui);
}
@Override
public void add(Component component) {
children.clear();
super.add(component);
this.child = component;
}
@Override
public void remove(Component component) {
super.remove(component);
this.child = null;
}
}

View File

@@ -0,0 +1,125 @@
package com.bartlomiejpluta.base.api.game.gui.component;
import com.bartlomiejpluta.base.api.game.context.Context;
import com.bartlomiejpluta.base.api.game.gui.base.GUI;
import com.bartlomiejpluta.base.api.game.gui.base.SizeMode;
import com.bartlomiejpluta.base.api.game.input.Key;
import com.bartlomiejpluta.base.api.game.input.KeyAction;
import com.bartlomiejpluta.base.api.game.input.KeyEvent;
import com.bartlomiejpluta.base.api.game.screen.Screen;
import static com.bartlomiejpluta.base.api.util.math.MathUtil.clamp;
import static java.lang.Math.*;
public class VScrollable extends SingleChildContainer {
private float scroll = 0.0f;
private float scrollStep = 0.25f;
private float scrollSpeed = 0.1f;
private float scrollTarget = 0.0f;
private float scrollPosition = 0.0f;
public VScrollable(Context context, GUI gui) {
super(context, gui);
}
public float getScroll() {
return scroll;
}
public void setScroll(Float scroll) {
this.scroll = clamp(scroll, 0, 1);
}
public float getScrollStep() {
return scrollStep;
}
public void setScrollStep(Float scrollStep) {
this.scrollStep = clamp(scrollStep, 0, 1);
}
public float getScrollSpeed() {
return scrollSpeed;
}
public void setScrollSpeed(Float scrollSpeed) {
this.scrollSpeed = clamp(scrollSpeed, 0, 1);
}
@Override
public void remove(Component component) {
throw new UnsupportedOperationException();
}
@Override
public void setSizeMode(SizeMode widthMode, SizeMode heightMode) {
if (widthMode == SizeMode.AUTO || heightMode == SizeMode.AUTO) {
throw new IllegalStateException("Scrollable component size mode must be other than AUTO");
}
super.setSizeMode(widthMode, heightMode);
}
@Override
public void setWidthMode(SizeMode mode) {
if (mode == SizeMode.AUTO) {
throw new IllegalStateException("Scrollable component size mode must be other than AUTO");
}
super.setWidthMode(mode);
}
@Override
public void setHeightMode(SizeMode mode) {
if (mode == SizeMode.AUTO) {
throw new IllegalStateException("Scrollable component size mode must be other than AUTO");
}
super.setHeightMode(mode);
}
@Override
protected float getContentWidth() {
return child.getMarginLeft() + child.getActualWidth() + child.getMarginRight();
}
@Override
protected float getContentHeight() {
return child.getMarginTop() + child.getActualHeight() + child.getMarginBottom();
}
@Override
public void handleKeyEvent(KeyEvent event) {
super.handleKeyEvent(event);
if (event.isConsumed()) {
return;
}
if (event.getKey() == Key.KEY_DOWN && (event.getAction() == KeyAction.PRESS || event.getAction() == KeyAction.REPEAT)) {
scroll = min(scroll + scrollStep, 1);
scrollTarget = scroll * max(getContentHeight() - getHeight(), 0);
event.consume();
}
if (event.getKey() == Key.KEY_UP && (event.getAction() == KeyAction.PRESS || event.getAction() == KeyAction.REPEAT)) {
scroll = max(scroll - scrollStep, 0);
scrollTarget = scroll * max(getContentHeight() - getHeight(), 0);
event.consume();
}
}
@Override
public void draw(Screen screen, GUI gui) {
var remainingDistance = scrollTarget - scrollPosition;
if (abs(remainingDistance) > scrollSpeed) {
scrollPosition += scrollSpeed * remainingDistance;
}
gui.clip(x, y, getWidth(), getHeight());
child.setPosition(x + paddingLeft + child.getMarginLeft(), y + paddingTop + child.getMarginTop() - scrollPosition);
child.draw(screen, gui);
gui.resetClip();
}
}

View File

@@ -0,0 +1,32 @@
package com.bartlomiejpluta.base.api.util.math;
import static java.lang.Math.max;
import static java.lang.Math.min;
public class MathUtil {
public static int gcdEuclidean(int a, int b) {
int x = a;
int y = b;
int z;
while(y != 0) {
z = x % y;
x = y;
y = z;
}
return x;
}
public static int clamp(int value, int min, int max) {
return min(max, max(value, min));
}
public static float clamp(float value, float min, float max) {
return min(max, max(value, min));
}
public static double clamp(double value, double min, double max) {
return min(max, max(value, min));
}
}