1
mirror of https://github.com/Shiewk/Widgets.git synced 2026-04-28 11:34:17 +02:00

Add helpful context menus (right click) to the position editing screen

- Right click on widget: Opening widget settings, setting anchor or deactivating the widget
- Right click on empty space: Enabling widgets
This commit is contained in:
Shy
2025-11-24 11:41:08 +01:00
parent 2c51b05b22
commit df5b83a3f7
8 changed files with 304 additions and 22 deletions
+1 -1
View File
@@ -56,6 +56,6 @@ public enum Anchor {
return anchor;
}
}
return Anchor.TOP_LEFT;
return null;
}
}
@@ -59,4 +59,20 @@ public abstract class ModWidget {
settings.offsetX += dx;
settings.offsetY += dy;
}
public void setPos(Anchor anchor, int offsetX, int offsetY){
getSettings().setPos(anchor, offsetX, offsetY);
}
public void setAbsolutePos(int x, int y, int scaledWindowWidth, int scaledWindowHeight) {
Anchor anchor = Anchor.getAnchor(scaledWindowWidth, scaledWindowHeight, x, y);
if (anchor == null) {
throw new IllegalArgumentException("Provided coordinates have no corresponding anchor");
}
settings.setPos(
anchor,
x - anchor.getAlignStartPosX(scaledWindowWidth),
y - anchor.getAlignStartPosY(scaledWindowHeight)
);
}
}
@@ -0,0 +1,136 @@
package de.shiewk.widgets.client.screen;
import de.shiewk.widgets.utils.WidgetUtils;
import net.minecraft.client.gui.Click;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.cursor.StandardCursors;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.sound.SoundEvents;
import net.minecraft.text.Text;
import java.util.List;
public class ContextMenuScreen extends Screen {
public record Option(Text title, boolean highlighted, Runnable action){
public Option(Text title, Runnable action){
this(title, false, action);
}
}
private final Screen parent;
private int menuX;
private int menuY;
private final List<Option> options;
private int menuWidth;
private int menuHeight;
public ContextMenuScreen(Text title, Screen parent, int menuX, int menuY, List<Option> options) {
super(title);
this.parent = parent;
this.menuX = menuX;
this.menuY = menuY;
this.options = options;
}
@Override
public void tick() {
menuWidth = computeMenuWidth();
menuHeight = computeMenuHeight();
if (menuX + menuWidth > width){
menuX = width - menuWidth;
}
if (menuY + menuHeight > height){
menuY = height - menuHeight;
}
}
private int computeMenuHeight() {
return options.size() * (9 + 6) + 1;
}
private int computeMenuWidth() {
int max = 0;
for (Option option : options) {
int width = textRenderer.getWidth(option.title);
if (width > max){
max = width;
}
}
return max + 10;
}
@Override
protected void init() {
tick();
}
@Override
public void close() {
client.setScreen(parent);
}
@Override
public boolean mouseClicked(Click click, boolean doubled) {
if (!isInBounds(click.x(), click.y())){
close();
return false;
}
int opt = (int) (click.y() - menuY - 1) / 15;
if (opt < options.size()){
Option option = options.get(opt);
close();
WidgetUtils.playSound(SoundEvents.BLOCK_COPPER_BULB_TURN_OFF);
option.action.run();
}
return false;
}
private boolean isInBounds(double x, double y) {
return x > menuX && y > menuY && x < menuX + menuWidth && y < menuY + menuHeight;
}
@Override
public void render(DrawContext context, int mouseX, int mouseY, float deltaTicks) {
super.render(context, mouseX, mouseY, deltaTicks);
parent.render(context, -67, -67, deltaTicks);
context.drawStrokedRectangle(
menuX,
menuY,
menuWidth,
menuHeight,
0x67ffffff
);
context.fill(
menuX,
menuY,
menuX + menuWidth,
menuY + menuHeight,
0xff000000
);
renderMenu(context, mouseX, mouseY);
}
public void renderMenu(DrawContext context, int mouseX, int mouseY){
int y = menuY + 1;
for (Option option : options) {
boolean hover = isInBounds(mouseX, mouseY) && mouseY >= y && mouseY < y + 15;
if (hover){
context.fill(
menuX,
y,
menuX + menuWidth,
y + 15,
0x30_ff_ff_ff
);
context.setCursor(StandardCursors.POINTING_HAND);
}
context.drawText(textRenderer, option.title, menuX + 5, y + 3, option.highlighted ? 0xff_00_ff_ff : 0xff_ff_ff_ff, false);
y += 15;
}
}
}
@@ -4,17 +4,21 @@ import de.shiewk.widgets.Anchor;
import de.shiewk.widgets.ModWidget;
import de.shiewk.widgets.WidgetSettings;
import de.shiewk.widgets.client.WidgetManager;
import de.shiewk.widgets.utils.WidgetUtils;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.minecraft.client.gui.Click;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.cursor.StandardCursors;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.tooltip.Tooltip;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.sound.SoundEvents;
import net.minecraft.text.Text;
import net.minecraft.util.Util;
import org.joml.Vector2i;
import java.awt.*;
import java.util.List;
import java.util.function.Consumer;
public class EditWidgetPositionsScreen extends AnimatedScreen {
@@ -202,6 +206,7 @@ public class EditWidgetPositionsScreen extends AnimatedScreen {
mouseX,
mouseY
);
if (anchor != null) {
Vector2i topLeft = anchor.getTopLeft(scaledWindowWidth, scaledWindowHeight);
context.fill(
topLeft.x,
@@ -211,6 +216,7 @@ public class EditWidgetPositionsScreen extends AnimatedScreen {
0x08ffffff
);
}
}
@Override
public boolean mouseReleased(Click click) {
@@ -245,6 +251,99 @@ public class EditWidgetPositionsScreen extends AnimatedScreen {
selectedWidget = hoveredWidget;
focusedExtraX = (int) (click.x() - hoveredWidget.getX(scaledWindowWidth));
focusedExtraY = (int) (click.y() - hoveredWidget.getY(scaledWindowHeight));
} else if (click.button() == 1){
int x = (int) click.x();
int y = (int) click.y();
ModWidget hovered = hoveredWidget;
WidgetUtils.playSound(SoundEvents.BLOCK_COPPER_BULB_TURN_ON);
if (hovered != null){
client.setScreen(new ContextMenuScreen(
Text.empty(),
this,
x,
y,
List.of(
new ContextMenuScreen.Option(
Text.translatable("widgets.ui.editPositions.menu.widgetSettings"),
() -> client.setScreen(new WidgetSettingsScreen(
this,
hovered,
this.onEdit
))
),
new ContextMenuScreen.Option(
Text.translatable("widgets.ui.editPositions.menu.setAnchor"),
() -> {
List<ContextMenuScreen.Option> options = new ObjectArrayList<>(Anchor.values().length);
for (Anchor anchor : Anchor.values()) {
options.add(new ContextMenuScreen.Option(
Text.translatable("widgets.ui.anchor." + anchor.name().toLowerCase()),
hovered.getSettings().anchor == anchor,
() -> {
hovered.setPos(
anchor,
hovered.getX(scaledWindowWidth) - anchor.getAlignStartPosX(scaledWindowWidth),
hovered.getY(scaledWindowHeight) - anchor.getAlignStartPosY(scaledWindowHeight)
);
onEdit.accept(hovered);
}
));
}
// Add widget context menu
client.setScreen(new ContextMenuScreen(
Text.empty(),
this,
x,
y,
options
));
}
),
new ContextMenuScreen.Option(
Text.translatable("widgets.ui.editPositions.menu.removeWidget"),
() -> {
hovered.getSettings().toggleEnabled(hovered);
onEdit.accept(hovered);
}
)
)
));
} else {
client.setScreen(new ContextMenuScreen(
Text.empty(),
this,
x,
y,
List.of(
new ContextMenuScreen.Option(
Text.translatable("widgets.ui.editPositions.menu.addWidget"),
() -> {
List<ContextMenuScreen.Option> options = new ObjectArrayList<>();
for (ModWidget widget : WidgetManager.getAllWidgets()) {
if (!widget.getSettings().isEnabled()){
options.add(new ContextMenuScreen.Option(
widget.getName(),
() -> {
widget.getSettings().setEnabled(widget, true);
widget.setAbsolutePos(x, y, scaledWindowWidth, scaledWindowHeight);
onEdit.accept(widget);
}
));
}
}
// Add widget context menu
client.setScreen(new ContextMenuScreen(
Text.empty(),
this,
x,
y,
options
));
}
)
)
));
}
}
return super.mouseClicked(click, doubled);
}
@@ -263,6 +362,9 @@ public class EditWidgetPositionsScreen extends AnimatedScreen {
if (click.x() <= wx + ww + deltaX && click.x() >= wx + deltaX){
if (click.y() <= wy + wh + deltaY && click.y() >= wy + deltaY){
Anchor anchor = Anchor.getAnchor(scaledWindowWidth, scaledWindowHeight, (int) click.x(), (int) click.y());
if (anchor == null) {
return false;
}
int newOffX = (int) (click.x() - anchor.getAlignStartPosX(scaledWindowWidth)) - focusedExtraX;
int newOffY = (int) (click.y() - anchor.getAlignStartPosY(scaledWindowHeight)) - focusedExtraY;
@@ -2,24 +2,26 @@ package de.shiewk.widgets.client.screen;
import de.shiewk.widgets.ModWidget;
import de.shiewk.widgets.client.screen.components.WidgetSettingsEditWidget;
import net.minecraft.client.gui.*;
import net.minecraft.client.gui.Click;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.Element;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.ClickableWidget;
import net.minecraft.text.Text;
import net.minecraft.util.Util;
import java.util.function.Consumer;
public class WidgetSettingsScreen extends AnimatedScreen {
private static final Text previewText = Text.translatable("widgets.ui.preview");
private final ModWidget widget;
private final Runnable onChange;
public WidgetSettingsScreen(Screen parent, ModWidget widget) {
public WidgetSettingsScreen(Screen parent, ModWidget widget, Consumer<ModWidget> changedWidgetConsumer) {
super(Text.translatable("widgets.ui.widgetSettings", widget.getName()), parent, 500);
this.widget = widget;
onChange = () -> {
widget.onSettingsChanged(widget.getSettings());
if (parent instanceof WidgetConfigScreen widgetConfigScreen){
widgetConfigScreen.changedSettings(widget);
}
changedWidgetConsumer.accept(widget);
};
}
@@ -82,7 +82,7 @@ public class WidgetWidget extends ClickableWidget {
@Override
public boolean mouseClicked(Click click, boolean doubled) {
if (isMouseOver(click.x(), click.y())){
client.setScreen(new WidgetSettingsScreen(client.currentScreen, widget));
client.setScreen(new WidgetSettingsScreen(client.currentScreen, widget, onEdit));
return true;
} else if (isMouseOverToggle(click.x(), click.y())){
this.toggleWidget();
@@ -1,9 +1,22 @@
{
"widgets.key.category": "Widgets",
"widgets.key.config": "Öffne Widget-Einstellungen",
"widgets.key.config": "Öffne Widgets-Einstellungen",
"widgets.ui.anchor.bottom_center": "Unten mittig",
"widgets.ui.anchor.bottom_left": "Unten links",
"widgets.ui.anchor.bottom_right": "Unten rechts",
"widgets.ui.anchor.center": "Mitte",
"widgets.ui.anchor.center_left": "Mitte links",
"widgets.ui.anchor.center_right": "Mitte rechts",
"widgets.ui.anchor.top_center": "Oben mittig",
"widgets.ui.anchor.top_left": "Oben links",
"widgets.ui.anchor.top_right": "Oben rechts",
"widgets.ui.config": "Widgets-Konfiguration",
"widgets.ui.disabled": "Deaktiviert",
"widgets.ui.editPositions": "Layout bearbeiten",
"widgets.ui.editPositions.menu.addWidget": "Widget hinzufügen",
"widgets.ui.editPositions.menu.removeWidget": "Widget deaktivieren",
"widgets.ui.editPositions.menu.setAnchor": "Anker versetzen",
"widgets.ui.editPositions.menu.widgetSettings": "Widget-Einstellungen",
"widgets.ui.editPositions.snap": "Positionen ausrichten: %s",
"widgets.ui.editPositions.snap.help": "Richtet die Position des Widgets mit Positionen der anderen Widgets aus",
"widgets.ui.enabled": "Aktiviert",
@@ -77,6 +90,7 @@
"widgets.widgets.fps": "FPS",
"widgets.widgets.fps.description": "Zeigt deine aktuellen FPS an.",
"widgets.widgets.inventory": "Inventar",
"widgets.widgets.inventory.boxColor": "Zellenfarbe",
"widgets.widgets.inventory.description": "Zeigt dein Inventar.",
"widgets.widgets.inventory.gridColor": "Farbe des Gitters",
"widgets.widgets.inventory.mode": "Modus",
@@ -85,7 +99,9 @@
"widgets.widgets.inventory.mode.texture_pack": "Texturenpaket",
"widgets.widgets.inventory.mode.transparent": "Transparent",
"widgets.widgets.inventory.mode.vanilla": "Standard",
"widgets.widgets.inventory.rainbowBoxes": "Regenbogenzellen",
"widgets.widgets.inventory.rainbowGrid": "Regenbogengitter",
"widgets.widgets.inventory.showHotbar": "Schnellzugriffsleiste anzeigen",
"widgets.widgets.keystrokes": "Keystrokes",
"widgets.widgets.keystrokes.colorBackgroundPressed": "Hintergrundfarbe (Taste gedrückt)",
"widgets.widgets.keystrokes.colorBackgroundUnpressed": "Hintergrundfarbe (Taste nicht gedrückt)",
@@ -130,8 +146,5 @@
"widgets.widgets.tps": "TPS",
"widgets.widgets.tps.description": "Zeigt die TPS im Einzelspielermodus an oder schätzt die TPS im Mehrspielermodus",
"widgets.widgets.tps.dynamicColor": "Farbe dynamisch anzeigen",
"widgets.widgets.tps.tps": "%s TPS",
"widgets.widgets.inventory.boxColor": "Zellenfarbe",
"widgets.widgets.inventory.rainbowBoxes": "Regenbogenzellen",
"widgets.widgets.inventory.showHotbar": "Schnellzugriffsleiste anzeigen"
"widgets.widgets.tps.tps": "%s TPS"
}
@@ -1,9 +1,22 @@
{
"widgets.key.category": "Widgets",
"widgets.key.config": "Open Widget Management",
"widgets.ui.anchor.bottom_center": "Bottom center",
"widgets.ui.anchor.bottom_left": "Bottom left",
"widgets.ui.anchor.bottom_right": "Bottom right",
"widgets.ui.anchor.center": "Center",
"widgets.ui.anchor.center_left": "Center left",
"widgets.ui.anchor.center_right": "Center right",
"widgets.ui.anchor.top_center": "Top center",
"widgets.ui.anchor.top_left": "Top left",
"widgets.ui.anchor.top_right": "Top right",
"widgets.ui.config": "Widgets Config",
"widgets.ui.disabled": "Disabled",
"widgets.ui.editPositions": "Edit Layout",
"widgets.ui.editPositions.menu.addWidget": "Add widget",
"widgets.ui.editPositions.menu.removeWidget": "Disable widget",
"widgets.ui.editPositions.menu.setAnchor": "Set anchor",
"widgets.ui.editPositions.menu.widgetSettings": "Widget settings",
"widgets.ui.editPositions.snap": "Align positions: %s",
"widgets.ui.editPositions.snap.help": "Aligns the widget with positions of other widgets",
"widgets.ui.enabled": "Enabled",
@@ -88,6 +101,7 @@
"widgets.widgets.inventory.mode.vanilla": "Vanilla",
"widgets.widgets.inventory.rainbowBoxes": "Rainbow boxes",
"widgets.widgets.inventory.rainbowGrid": "Rainbow Grid",
"widgets.widgets.inventory.showHotbar": "Show hotbar",
"widgets.widgets.keystrokes": "Keystrokes",
"widgets.widgets.keystrokes.colorBackgroundPressed": "Background color (key pressed)",
"widgets.widgets.keystrokes.colorBackgroundUnpressed": "Background color (key not pressed)",
@@ -132,6 +146,5 @@
"widgets.widgets.tps": "TPS",
"widgets.widgets.tps.description": "Shows the current TPS when in singleplayer and estimates server TPS when in multiplayer.",
"widgets.widgets.tps.dynamicColor": "Dynamic Color",
"widgets.widgets.tps.tps": "%s TPS",
"widgets.widgets.inventory.showHotbar": "Show hotbar"
"widgets.widgets.tps.tps": "%s TPS"
}