Skip to content

Instantly share code, notes, and snippets.

@audinue
Created August 11, 2023 04:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save audinue/a0ac7df9d5e2464c29f376068fd696e8 to your computer and use it in GitHub Desktop.
Save audinue/a0ac7df9d5e2464c29f376068fd696e8 to your computer and use it in GitHub Desktop.
package sketch;
import java.awt.Rectangle;
import java.util.HashMap;
public class Ui {
//////////////////////////////////// STATE /////////////////////////////////////
private static class State {
State parent;
HashMap<Object, State> children = new HashMap<Object, State>();
Object value;
int key;
}
private static State state = new State();
private static State nextChildState(Object initialValue, Object key) {
if (initialValue == null) {
throw new IllegalArgumentException("Initial value must not be null.");
}
if (key == null) {
key = ++state.key;
}
State child = state.children.get(key);
if (child == null) {
child = new State();
child.parent = state;
child.value = initialValue;
state.children.put(key, child);
} else {
if (child.value.getClass() != initialValue.getClass()) {
child.value = initialValue;
}
}
return child;
}
public static <T> T nextState(T initialValue, Object key) {
return (T) nextChildState(initialValue, key).value;
}
public static <T> T nextState(T initialValue) {
return nextState(initialValue, null);
}
public static <T> T pushState(T initialValue, Object key) {
return (T) (state = nextChildState(initialValue, key)).value;
}
public static <T> T pushState(T initialValue) {
return pushState(initialValue, null);
}
public static void popState() {
if (state.parent == null) {
throw new IllegalStateException("Too many `popState()`.");
}
state = state.parent;
}
private static void resetState(State state) {
state.key = 0;
for (State child : state.children.values()) {
resetState(child);
}
}
static void resetState() {
assert (state.parent == null); // This must be root state.
resetState(state);
}
/////////////////////////////////// LAYOUT /////////////////////////////////////
private static class Layout {
Layout previous;
Layout next;
Rectangle bounds;
int spacing;
int padding;
int[] columnWidths;
int rowHeight;
int x;
int y;
int column;
int row;
}
private static Layout layout = new Layout();
public static void setBounds(Rectangle bounds) {
layout.bounds = bounds;
}
public static void setPadding(int padding) {
layout.padding = padding;
}
public static void setSpacing(int spacing) {
layout.spacing = spacing;
}
public static void setColumnWidths(int[] columnWidths) {
layout.columnWidths = columnWidths;
}
public static void setRowHeight(int rowHeight) {
layout.rowHeight = rowHeight;
}
public static Rectangle nextLayout() {
if (layout.column == 0 && layout.row == 0) {
layout.x = layout.bounds.x + layout.padding;
layout.y = layout.bounds.y + layout.padding;
}
int width = layout.columnWidths[layout.column];
int height = layout.rowHeight;
if (width == -1) {
width = layout.bounds.width - layout.padding * 2;
} else if (width < 0) {
width = layout.bounds.width - layout.padding * 2 + width;
}
if (height == -1) {
height = layout.bounds.height - layout.padding * 2;
} else if (height < 0) {
height = layout.bounds.height - layout.padding * 2 + height;
}
Rectangle next = new Rectangle(layout.x, layout.y, width, height);
layout.x = layout.x + width + layout.spacing;
layout.column++;
if (layout.column >= layout.columnWidths.length) {
layout.x = layout.bounds.x + layout.padding;
layout.y = layout.y + height + layout.spacing;
layout.column = 0;
layout.row++;
}
return next;
}
public static Rectangle pushLayout() {
Rectangle bounds = nextLayout();
if (layout.next == null) {
layout.next = new Layout();
layout.next.previous = layout;
}
layout = layout.next;
layout.bounds = bounds;
layout.column = 0;
layout.row = 0;
return bounds;
}
public static void popLayout() {
if (layout.previous == null) {
throw new IllegalStateException("Too many `popLayout()`.");
}
layout = layout.previous;
}
static void resetLayout() {
assert (layout.previous == null);
layout.column = 0;
layout.row = 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment