Redesign client settings
ClientSettings replaces ConfigEditor: a section list on the left (General, UI Style, Animations) and the chosen section's settings on the right, each with a Reset for that section. UI Style shows four theme presets, the theme colors as a two-column grid, then the radii and font. New pieces: SectionNav, ThemePresetCard, ColorGrid and Theme.PRESETS. Theme keeps its config like AnimationConfig does, Divider can be vertical, and PropertyList's section titles are public. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -1,11 +1,15 @@
|
||||
package org.saturnclient.config;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.saturnclient.config.property.ColorProperty;
|
||||
import org.saturnclient.config.property.IntProperty;
|
||||
import org.saturnclient.config.property.Property;
|
||||
import org.saturnclient.config.property.SelectProperty;
|
||||
|
||||
public class Theme {
|
||||
public static ConfigManager config;
|
||||
|
||||
// Main UI background (slightly warm dark to match Saturn tone)
|
||||
public static final ColorProperty BACKGROUND = Property.color(0xFF12100D);
|
||||
|
||||
@@ -34,8 +38,37 @@ public class Theme {
|
||||
// Font
|
||||
public static final SelectProperty FONT = Property.font(2);
|
||||
|
||||
/**
|
||||
* A full set of theme colors that can be applied in one go.
|
||||
*/
|
||||
public record Preset(String name, int background, int foreground, int primary, int primaryFg, int accent,
|
||||
int accentFg, int scroll) {
|
||||
|
||||
public void apply() {
|
||||
BACKGROUND.value = background;
|
||||
FOREGROUND.value = foreground;
|
||||
PRIMARY.value = primary;
|
||||
PRIMARY_FG.value = primaryFg;
|
||||
ACCENT.value = accent;
|
||||
ACCENT_FG.value = accentFg;
|
||||
SCROLL.value = scroll;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return BACKGROUND.value == background && FOREGROUND.value == foreground && PRIMARY.value == primary
|
||||
&& PRIMARY_FG.value == primaryFg && ACCENT.value == accent && ACCENT_FG.value == accentFg
|
||||
&& SCROLL.value == scroll;
|
||||
}
|
||||
}
|
||||
|
||||
public static final List<Preset> PRESETS = List.of(
|
||||
new Preset("Saturn", 0xFF12100D, 0xFFF2E6D2, 0xFF1C1915, 0xFFEAD9B8, 0xFFE2BF7D, 0xFF1A140A, 0xFFE2BF7D),
|
||||
new Preset("Midnight", 0xFF0E1117, 0xFFE4EAF5, 0xFF171C26, 0xFFC9D4E8, 0xFF8FB3FF, 0xFF0A1224, 0xFF8FB3FF),
|
||||
new Preset("Amethyst", 0xFF120F17, 0xFFEDE4F7, 0xFF1C1724, 0xFFD8C9EB, 0xFFC79BFF, 0xFF1A0F2A, 0xFFC79BFF),
|
||||
new Preset("Emerald", 0xFF0D1210, 0xFFE2F2EA, 0xFF16201B, 0xFFC4E0D2, 0xFF7FD1A8, 0xFF0A1F15, 0xFF7FD1A8));
|
||||
|
||||
public static void init(ConfigManager parent) {
|
||||
ConfigManager config = new ConfigManager(parent, "UI Style");
|
||||
config = new ConfigManager(parent, "UI Style");
|
||||
config.property("Background", BACKGROUND);
|
||||
config.property("Foreground", FOREGROUND);
|
||||
config.property("Primary", PRIMARY);
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
package org.saturnclient.ui.components;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.saturnclient.config.Theme;
|
||||
import org.saturnclient.config.property.ColorProperty;
|
||||
import org.saturnclient.config.property.Property;
|
||||
import org.saturnclient.ui.Element;
|
||||
import org.saturnclient.ui.ElementContext;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
import org.saturnclient.ui.components.inputs.ColorInput;
|
||||
import org.saturnclient.ui.elements.Scroll;
|
||||
import org.saturnclient.ui.resources.Fonts;
|
||||
|
||||
/**
|
||||
* Lays out the color properties of a config as a two-column grid of tiles,
|
||||
* each with the color's name and its input.
|
||||
*/
|
||||
public final class ColorGrid {
|
||||
private static final int COLUMNS = 2;
|
||||
private static final int TILE_HEIGHT = 48;
|
||||
private static final int GAP = 8;
|
||||
private static final int INSET = 8;
|
||||
|
||||
private ColorGrid() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a tile for every {@link ColorProperty} in {@code properties} to
|
||||
* {@code scroll}, starting at {@code y}.
|
||||
*
|
||||
* @return the y below the grid
|
||||
*/
|
||||
public static int draw(Scroll scroll, Map<String, Property> properties, int width, int y) {
|
||||
int tileWidth = (width - GAP * (COLUMNS - 1)) / COLUMNS;
|
||||
List<Element> inputs = new ArrayList<>();
|
||||
int i = 0;
|
||||
|
||||
for (Map.Entry<String, Property> entry : properties.entrySet()) {
|
||||
if (!(entry.getValue() instanceof ColorProperty color)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int x = (i % COLUMNS) * (tileWidth + GAP);
|
||||
int tileY = y + (i / COLUMNS) * (TILE_HEIGHT + GAP);
|
||||
|
||||
ColorInput input = new ColorInput(color);
|
||||
scroll.draw(new Tile(entry.getKey(), tileWidth, input.width).position(x, tileY));
|
||||
inputs.add(input.position(x + tileWidth - INSET - input.width, tileY + (TILE_HEIGHT - input.height) / 2));
|
||||
i++;
|
||||
}
|
||||
|
||||
// Inputs go on after every tile, so an open color picker covers the tiles below it.
|
||||
inputs.forEach(scroll::draw);
|
||||
|
||||
int rows = (i + COLUMNS - 1) / COLUMNS;
|
||||
return y + rows * TILE_HEIGHT + Math.max(0, rows - 1) * GAP;
|
||||
}
|
||||
|
||||
private static class Tile extends Element {
|
||||
private static final float NAME_SCALE = 0.7f;
|
||||
|
||||
private final String name;
|
||||
private final int inputWidth;
|
||||
|
||||
Tile(String name, int width, int inputWidth) {
|
||||
this.name = name;
|
||||
this.inputWidth = inputWidth;
|
||||
this.width = width;
|
||||
this.height = TILE_HEIGHT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(RenderScope renderScope, ElementContext ctx) {
|
||||
renderScope.drawRoundedRectangle(0, 0, width, height, Theme.WIDGET_RADIUS.value, 1,
|
||||
Theme.withAlpha(0.72f, Theme.PRIMARY.value), Theme.withAlpha(0.06f, Theme.FOREGROUND.value));
|
||||
|
||||
String text = Fonts.ellipsize(name, Theme.FONT.value, NAME_SCALE, width - inputWidth - INSET * 2 - 12);
|
||||
int nameY = (height - (int) (Fonts.getHeight() * NAME_SCALE)) / 2;
|
||||
renderScope.drawText(NAME_SCALE, text, 12, nameY, Theme.FONT.value, Theme.FOREGROUND.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -66,11 +66,7 @@ public final class PropertyList {
|
||||
}
|
||||
|
||||
if (prop instanceof NamespaceProperty namespace) {
|
||||
y += SECTION_GAP;
|
||||
String title = name.toUpperCase(Locale.ROOT);
|
||||
scroll.draw(new Label(() -> title, SECTION_SCALE, () -> Theme.FONT.value, Theme::getMutedFg)
|
||||
.position(0, y));
|
||||
y += (int) (Fonts.getHeight() * SECTION_SCALE) + 4;
|
||||
y = drawSection(scroll, name, y + SECTION_GAP) + 4;
|
||||
y = drawRows(scroll, namespace.value, Set.of(), width, y, controls);
|
||||
continue;
|
||||
}
|
||||
@@ -88,6 +84,17 @@ public final class PropertyList {
|
||||
return y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a section title, such as a namespace's name, at {@code y}.
|
||||
*
|
||||
* @return the y below the title
|
||||
*/
|
||||
public static int drawSection(Scroll scroll, String name, int y) {
|
||||
String title = name.toUpperCase(Locale.ROOT);
|
||||
scroll.draw(new Label(() -> title, SECTION_SCALE, () -> Theme.FONT.value, Theme::getMutedFg).position(0, y));
|
||||
return y + (int) (Fonts.getHeight() * SECTION_SCALE);
|
||||
}
|
||||
|
||||
/**
|
||||
* The input for a property, or null for types without one (strings).
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
package org.saturnclient.ui.components;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.IntConsumer;
|
||||
|
||||
import org.saturnclient.common.ref.asset.IdentifierRef;
|
||||
import org.saturnclient.config.Theme;
|
||||
import org.saturnclient.ui.Element;
|
||||
import org.saturnclient.ui.ElementContext;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
import org.saturnclient.ui.elements.Field;
|
||||
import org.saturnclient.ui.resources.Fonts;
|
||||
|
||||
/**
|
||||
* A vertical list of a screen's sections under a small heading, with the
|
||||
* current one highlighted.
|
||||
*/
|
||||
public class SectionNav extends Element {
|
||||
public record Item(IdentifierRef icon, String name) {
|
||||
}
|
||||
|
||||
private static final float HEADING_SCALE = 0.6f;
|
||||
private static final int HEADING_HEIGHT = 26;
|
||||
private static final int ITEM_HEIGHT = 40;
|
||||
private static final int ITEM_GAP = 4;
|
||||
private static final int ICON = 17;
|
||||
private static final float TEXT_SCALE = 0.7f;
|
||||
|
||||
private final String heading;
|
||||
private final List<Item> items;
|
||||
private final int active;
|
||||
private final IntConsumer onSelect;
|
||||
|
||||
public SectionNav(String heading, List<Item> items, int active, int width, IntConsumer onSelect) {
|
||||
this.heading = heading;
|
||||
this.items = items;
|
||||
this.active = active;
|
||||
this.onSelect = onSelect;
|
||||
this.width = width;
|
||||
this.height = HEADING_HEIGHT + items.size() * (ITEM_HEIGHT + ITEM_GAP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(RenderScope renderScope, ElementContext ctx) {
|
||||
renderScope.drawText(HEADING_SCALE, heading, 10, 0, Theme.FONT.value, Theme.getMutedFg());
|
||||
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
Item item = items.get(i);
|
||||
int y = getItemY(i);
|
||||
boolean selected = i == active;
|
||||
boolean hovered = ctx.isHovering(0, y, width, ITEM_HEIGHT);
|
||||
|
||||
if (selected || hovered) {
|
||||
renderScope.drawRoundedRectangle(0, y, width, ITEM_HEIGHT, Theme.WIDGET_RADIUS.value,
|
||||
Theme.withAlpha(selected ? 0.08f : 0.04f, Theme.FOREGROUND.value));
|
||||
}
|
||||
|
||||
renderScope.drawTexture(item.icon(), 12, y + (ITEM_HEIGHT - ICON) / 2, 0, 0, ICON, ICON,
|
||||
selected ? Theme.ACCENT.value : Theme.getMutedFg());
|
||||
|
||||
String name = Fonts.ellipsize(item.name(), Theme.FONT.value, TEXT_SCALE, width - 12 - ICON - 10 - 8);
|
||||
renderScope.drawText(TEXT_SCALE, name, 12 + ICON + 10, y + Field.textY(ITEM_HEIGHT, TEXT_SCALE),
|
||||
Theme.FONT.value, selected ? Theme.FOREGROUND.value : Theme.PRIMARY_FG.value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void click(int mouseX, int mouseY) {
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
int y = getItemY(i);
|
||||
|
||||
if (mouseY >= y && mouseY <= y + ITEM_HEIGHT) {
|
||||
if (i != active) {
|
||||
onSelect.accept(i);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int getItemY(int index) {
|
||||
return HEADING_HEIGHT + index * (ITEM_HEIGHT + ITEM_GAP);
|
||||
}
|
||||
}
|
||||
@@ -2,14 +2,13 @@ package org.saturnclient.ui.components;
|
||||
|
||||
import org.saturnclient.common.provider.Providers;
|
||||
import org.saturnclient.common.ref.asset.IdentifierRef;
|
||||
import org.saturnclient.config.Config;
|
||||
import org.saturnclient.config.Theme;
|
||||
import org.saturnclient.ui.Element;
|
||||
import org.saturnclient.ui.ElementContext;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
import org.saturnclient.ui.elements.Panel;
|
||||
import org.saturnclient.ui.resources.Textures;
|
||||
import org.saturnclient.ui.screens.ConfigEditor;
|
||||
import org.saturnclient.ui.screens.ClientSettings;
|
||||
import org.saturnclient.ui.screens.HudEditor;
|
||||
import org.saturnclient.ui.screens.ModMenu;
|
||||
import org.saturnclient.ui.screens.cosmetics.CloakMenu;
|
||||
@@ -40,8 +39,7 @@ public class Sidebar extends Element {
|
||||
new Item(Textures.ICON_MODS, () -> Providers.saturn.getClient().setScreen(new ModMenu())),
|
||||
new Item(Textures.ICON_COSMETICS, () -> Providers.saturn.getClient().setScreen(new CloakMenu())),
|
||||
new Item(Textures.ICON_HUD_EDITOR, () -> Providers.saturn.getClient().setScreen(new HudEditor())),
|
||||
new Item(Textures.ICON_SETTINGS,
|
||||
() -> Providers.saturn.getClient().setScreen(new ConfigEditor(Config.config))),
|
||||
new Item(Textures.ICON_SETTINGS, () -> Providers.saturn.getClient().setScreen(new ClientSettings())),
|
||||
};
|
||||
|
||||
private final int active;
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
package org.saturnclient.ui.components;
|
||||
|
||||
import org.saturnclient.config.Theme;
|
||||
import org.saturnclient.ui.Element;
|
||||
import org.saturnclient.ui.ElementContext;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
import org.saturnclient.ui.resources.Fonts;
|
||||
|
||||
/**
|
||||
* A theme preset: a small mock-up of a panel in its colors, and its name.
|
||||
* Clicking it applies the preset.
|
||||
*/
|
||||
public class ThemePresetCard extends Element {
|
||||
public static final int HEIGHT = 92;
|
||||
|
||||
private static final int PADDING = 10;
|
||||
private static final int PREVIEW_HEIGHT = 44;
|
||||
private static final float NAME_SCALE = 0.68f;
|
||||
|
||||
private final Theme.Preset preset;
|
||||
private final Runnable onApply;
|
||||
|
||||
/**
|
||||
* @param onApply runs after the preset is applied, to refresh what shows the
|
||||
* old colors
|
||||
*/
|
||||
public ThemePresetCard(Theme.Preset preset, int width, Runnable onApply) {
|
||||
this.preset = preset;
|
||||
this.onApply = onApply;
|
||||
this.width = width;
|
||||
this.height = HEIGHT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(RenderScope renderScope, ElementContext ctx) {
|
||||
boolean active = preset.isActive();
|
||||
int border = active ? Theme.ACCENT.value
|
||||
: Theme.withAlpha(ctx.isHovering() ? 0.22f : 0.06f, Theme.FOREGROUND.value);
|
||||
|
||||
renderScope.drawRoundedRectangle(0, 0, width, height, Theme.WIDGET_RADIUS.value, active ? 2 : 1,
|
||||
Theme.withAlpha(0.72f, Theme.PRIMARY.value), border);
|
||||
|
||||
// A panel in the preset's colors: a line of text over an accent and a widget
|
||||
int previewWidth = width - PADDING * 2;
|
||||
renderScope.drawRoundedRectangle(PADDING, PADDING, previewWidth, PREVIEW_HEIGHT, 8, preset.background());
|
||||
renderScope.drawRoundedRectangle(PADDING + 8, PADDING + 8, previewWidth * 6 / 10, 5, 3,
|
||||
Theme.withAlpha(0.8f, preset.foreground()));
|
||||
renderScope.drawRoundedRectangle(PADDING + 8, PADDING + PREVIEW_HEIGHT - 20, 34, 12, 4, preset.accent());
|
||||
renderScope.drawRoundedRectangle(PADDING + 47, PADDING + PREVIEW_HEIGHT - 20, 22, 12, 4, preset.primary());
|
||||
|
||||
int nameY = PADDING + PREVIEW_HEIGHT + (height - PADDING - PREVIEW_HEIGHT - (int) (Fonts.getHeight() * NAME_SCALE)) / 2;
|
||||
renderScope.drawText(NAME_SCALE, preset.name(), PADDING, nameY, Theme.FONT.value, Theme.FOREGROUND.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void click(int mouseX, int mouseY) {
|
||||
preset.apply();
|
||||
onApply.run();
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,8 @@ import org.saturnclient.ui.ElementContext;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
|
||||
/**
|
||||
* A faint horizontal line across the element's width.
|
||||
* A faint line filling the element: horizontal by default, or vertical when
|
||||
* given a width of 1 and a height.
|
||||
*/
|
||||
public class Divider extends Element {
|
||||
|
||||
@@ -17,6 +18,6 @@ public class Divider extends Element {
|
||||
|
||||
@Override
|
||||
public void render(RenderScope renderScope, ElementContext ctx) {
|
||||
renderScope.drawRectangle(0, 0, width, 1, Theme.getBorder());
|
||||
renderScope.drawRectangle(0, 0, width, height, Theme.getBorder());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,9 @@ public class Textures {
|
||||
public static final IdentifierRef ICON_CLOSE = IdentifierRef.ofSaturn("textures/gui/components/close.svg");
|
||||
public static final IdentifierRef ICON_SEARCH = IdentifierRef.ofSaturn("textures/gui/components/search.svg");
|
||||
public static final IdentifierRef ICON_SLIDERS = IdentifierRef.ofSaturn("textures/gui/components/sliders.svg");
|
||||
public static final IdentifierRef ICON_PALETTE = IdentifierRef.ofSaturn("textures/gui/components/palette.svg");
|
||||
public static final IdentifierRef ICON_ANIMATIONS = IdentifierRef
|
||||
.ofSaturn("textures/gui/components/animations.svg");
|
||||
public static final IdentifierRef ICON_RESET = IdentifierRef.ofSaturn("textures/gui/components/reset.svg");
|
||||
public static final IdentifierRef ICON_CHEVRON_LEFT = IdentifierRef
|
||||
.ofSaturn("textures/gui/components/chevron_left.svg");
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
package org.saturnclient.ui.screens;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.saturnclient.common.ref.asset.IdentifierRef;
|
||||
import org.saturnclient.config.AnimationConfig;
|
||||
import org.saturnclient.config.Config;
|
||||
import org.saturnclient.config.Theme;
|
||||
import org.saturnclient.config.property.ColorProperty;
|
||||
import org.saturnclient.config.property.NamespaceProperty;
|
||||
import org.saturnclient.config.property.Property;
|
||||
import org.saturnclient.ui.PanelScreen;
|
||||
import org.saturnclient.ui.components.ColorGrid;
|
||||
import org.saturnclient.ui.components.PropertyList;
|
||||
import org.saturnclient.ui.components.SectionNav;
|
||||
import org.saturnclient.ui.components.Sidebar;
|
||||
import org.saturnclient.ui.components.ThemePresetCard;
|
||||
import org.saturnclient.ui.elements.ActionButton;
|
||||
import org.saturnclient.ui.elements.Divider;
|
||||
import org.saturnclient.ui.elements.Label;
|
||||
import org.saturnclient.ui.elements.Scroll;
|
||||
import org.saturnclient.ui.resources.Textures;
|
||||
|
||||
/**
|
||||
* The client's own settings, split into sections picked from a list on the left.
|
||||
*/
|
||||
public class ClientSettings extends PanelScreen {
|
||||
private enum Section {
|
||||
GENERAL("General", "Title screen, emotes and cosmetics", Textures.ICON_SLIDERS),
|
||||
UI_STYLE("UI Style", "Colors, corners and font for every Saturn screen", Textures.ICON_PALETTE),
|
||||
ANIMATIONS("Animations", "How long menu animations take, and their easing", Textures.ICON_ANIMATIONS);
|
||||
|
||||
final String title;
|
||||
final String description;
|
||||
final IdentifierRef icon;
|
||||
|
||||
Section(String title, String description, IdentifierRef icon) {
|
||||
this.title = title;
|
||||
this.description = description;
|
||||
this.icon = icon;
|
||||
}
|
||||
}
|
||||
|
||||
private static final int NAV_WIDTH = 170;
|
||||
private static final int NAV_GAP = 16;
|
||||
private static final int LIST_Y = 58;
|
||||
private static final int SECTION_GAP = 22;
|
||||
private static final int PRESET_GAP = 10;
|
||||
private static final int SCROLLBAR_SPACE = 14;
|
||||
|
||||
private Section section = Section.GENERAL;
|
||||
|
||||
public ClientSettings() {
|
||||
super("Settings", Sidebar.SETTINGS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void panel() {
|
||||
List<SectionNav.Item> items = Stream.of(Section.values())
|
||||
.map(s -> new SectionNav.Item(s.icon, s.title))
|
||||
.toList();
|
||||
|
||||
draw(new SectionNav("SATURN CLIENT", items, section.ordinal(), NAV_WIDTH, i -> {
|
||||
section = Section.values()[i];
|
||||
init();
|
||||
}).position(contentX, contentY + 4));
|
||||
|
||||
int dividerX = contentX + NAV_WIDTH + NAV_GAP;
|
||||
draw(new Divider(1).dimensions(1, panelHeight).position(dividerX, panelY));
|
||||
|
||||
int x = dividerX + 1 + NAV_GAP + 4;
|
||||
int width = contentX + contentWidth - x;
|
||||
|
||||
// Header
|
||||
draw(new Label(() -> section.title, 1.15f, () -> Theme.FONT.value, () -> Theme.FOREGROUND.value)
|
||||
.position(x, contentY + 2));
|
||||
draw(new Label(() -> section.description, 0.66f, Theme::getBodyFont, Theme::getMutedFg)
|
||||
.position(x, contentY + 28));
|
||||
|
||||
ActionButton reset = new ActionButton(Textures.ICON_RESET, "Reset", true, this::reset);
|
||||
draw(reset.position(x + width - reset.width, contentY + 4));
|
||||
|
||||
// The section's settings
|
||||
Scroll scroll = new Scroll(0).noBackground();
|
||||
|
||||
switch (section) {
|
||||
case GENERAL -> PropertyList.draw(scroll, getGeneralProperties(), Set.of(), width, 0);
|
||||
case UI_STYLE -> drawUiStyle(scroll, width);
|
||||
case ANIMATIONS -> PropertyList.draw(scroll, AnimationConfig.config.getProperties(), Set.of(), width, 0);
|
||||
}
|
||||
|
||||
draw(scroll.dimensions(width + SCROLLBAR_SPACE, contentHeight - LIST_Y).position(x, contentY + LIST_Y));
|
||||
}
|
||||
|
||||
private void drawUiStyle(Scroll scroll, int width) {
|
||||
Map<String, Property> properties = Theme.config.getProperties();
|
||||
|
||||
int y = PropertyList.drawSection(scroll, "Presets", 0) + 10;
|
||||
int cardWidth = (width - PRESET_GAP * (Theme.PRESETS.size() - 1)) / Theme.PRESETS.size();
|
||||
|
||||
for (int i = 0; i < Theme.PRESETS.size(); i++) {
|
||||
// Rebuild so the color inputs show the preset's colors
|
||||
scroll.draw(new ThemePresetCard(Theme.PRESETS.get(i), cardWidth, this::init)
|
||||
.position(i * (cardWidth + PRESET_GAP), y));
|
||||
}
|
||||
|
||||
y += ThemePresetCard.HEIGHT + SECTION_GAP;
|
||||
y = PropertyList.drawSection(scroll, "Colors", y) + 10;
|
||||
y = ColorGrid.draw(scroll, properties, width, y) + SECTION_GAP;
|
||||
|
||||
y = PropertyList.drawSection(scroll, "Shape & type", y) + 4;
|
||||
PropertyList.draw(scroll, properties, getNames(properties, p -> p instanceof ColorProperty), width, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* The top-level settings. The namespaces have sections of their own.
|
||||
*/
|
||||
private static Map<String, Property> getGeneralProperties() {
|
||||
return Config.config.getProperties().entrySet().stream()
|
||||
.filter(e -> !(e.getValue() instanceof NamespaceProperty))
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> a,
|
||||
LinkedHashMap::new));
|
||||
}
|
||||
|
||||
private static Set<String> getNames(Map<String, Property> properties, Predicate<Property> filter) {
|
||||
return properties.entrySet().stream()
|
||||
.filter(e -> filter.test(e.getValue()))
|
||||
.map(Map.Entry::getKey)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the current section's settings back to their defaults.
|
||||
*/
|
||||
private void reset() {
|
||||
Map<String, Property> properties = switch (section) {
|
||||
case GENERAL -> getGeneralProperties();
|
||||
case UI_STYLE -> Theme.config.getProperties();
|
||||
case ANIMATIONS -> AnimationConfig.config.getProperties();
|
||||
};
|
||||
|
||||
properties.values().forEach(Property::reset);
|
||||
init();
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package org.saturnclient.ui.screens;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.saturnclient.config.ConfigManager;
|
||||
import org.saturnclient.config.Theme;
|
||||
import org.saturnclient.ui.PanelScreen;
|
||||
import org.saturnclient.ui.components.PropertyList;
|
||||
import org.saturnclient.ui.components.Sidebar;
|
||||
import org.saturnclient.ui.elements.Label;
|
||||
import org.saturnclient.ui.elements.Scroll;
|
||||
|
||||
/**
|
||||
* Edits every property of a config, such as the client's own settings.
|
||||
*/
|
||||
public class ConfigEditor extends PanelScreen {
|
||||
private static final int SCROLLBAR_SPACE = 14;
|
||||
private static final int LIST_Y = 44;
|
||||
|
||||
private final ConfigManager config;
|
||||
|
||||
public ConfigEditor(ConfigManager config) {
|
||||
super("Config Editor", Sidebar.SETTINGS);
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void panel() {
|
||||
draw(new Label(() -> "Settings", 1.15f, () -> Theme.FONT.value, () -> Theme.FOREGROUND.value)
|
||||
.position(contentX, contentY + 2));
|
||||
|
||||
Scroll scroll = new Scroll(0).noBackground();
|
||||
PropertyList.draw(scroll, config.getProperties(), Set.of(), contentWidth, 0);
|
||||
draw(scroll.dimensions(contentWidth + SCROLLBAR_SPACE, contentHeight - LIST_Y)
|
||||
.position(contentX, contentY + LIST_Y));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2"/></svg>
|
||||
|
After Width: | Height: | Size: 317 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="13.5" cy="6.5" r="1.5"/><circle cx="17.5" cy="10.5" r="1.5"/><circle cx="8.5" cy="7.5" r="1.5"/><circle cx="6.5" cy="12.5" r="1.5"/><path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.012 17.461 2 12 2z"/></svg>
|
||||
|
After Width: | Height: | Size: 555 B |
Reference in New Issue
Block a user