Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added ExpandableResultsEntry #6

Merged
merged 7 commits into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package io.wispforest.limelight.api.entry;

import org.jetbrains.annotations.ApiStatus;

import java.util.List;

/**
* A result entry which contain child entries that will show when this entry is selected.
*
* @apiNote This entry type is experimental, and may be removed in a later update.
*/
@ApiStatus.Experimental
public non-sealed interface ExpandableResultEntry extends ResultEntry {
List<ResultEntry> children();
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
/**
* Represents a result entry in the Limelight GUI.
*/
public sealed interface ResultEntry permits InvokeResultEntry, SetSearchTextEntry, ToggleResultEntry {
public sealed interface ResultEntry permits InvokeResultEntry, SetSearchTextEntry, ToggleResultEntry, ExpandableResultEntry {
/**
* @return the extension that generated this entry
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,16 @@ public int sourceExtensionColor() {
public int resultEntryTextColor() {
return 0x000000;
}

@Override
public int childBackgroundColor() {
return 0x33000000;
}

@Override
public int childSourceExtensionColor() {
return 0xFFEEEEEE;
}
};

LimelightTheme DARK = new LimelightTheme() {
Expand Down Expand Up @@ -55,6 +65,16 @@ public int sourceExtensionColor() {
public int resultEntryTextColor() {
return 0xFFFFFF;
}

@Override
public int childBackgroundColor() {
return 0x33000000;
}

@Override
public int childSourceExtensionColor() {
return 0xFF999999;
}
};

static LimelightTheme current() {
Expand All @@ -73,4 +93,8 @@ static LimelightTheme current() {
int sourceExtensionColor();

int resultEntryTextColor();

int childBackgroundColor();

int childSourceExtensionColor();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package io.wispforest.limelight.impl.ui;

import io.wispforest.owo.ui.component.LabelComponent;
import io.wispforest.owo.ui.core.CursorStyle;
import io.wispforest.owo.ui.core.OwoUIDrawContext;
import io.wispforest.owo.ui.util.Delta;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.math.RotationAxis;

class ExpandIndicatorComponent extends LabelComponent {

protected float rotation = 0;
protected float targetRotation = 0;

public ExpandIndicatorComponent(int color) {
super(Text.literal(">").withColor(color).formatted(Formatting.BOLD));
this.cursorStyle(CursorStyle.HAND);
}

public void toggle() {
targetRotation = targetRotation == 0 ? 90 : 0;
}

@Override
public void update(float delta, int mouseX, int mouseY) {
super.update(delta, mouseX, mouseY);
this.rotation += Delta.compute(this.rotation, this.targetRotation, delta * .65);
}

@Override
public void draw(OwoUIDrawContext context, int mouseX, int mouseY, float partialTicks, float delta) {
var matrices = context.getMatrices();

matrices.push();
matrices.translate(this.x + this.width / 2f - 1, this.y + this.height / 2f - 1, 0);
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(this.rotation));
matrices.translate(-(this.x + this.width / 2f - 1), -(this.y + this.height / 2f - 1), 0);

super.draw(context, mouseX, mouseY, partialTicks, delta);
matrices.pop();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ protected void build(FlowLayout rootComponent) {
// TODO: actually use our own texture instead of piggy-backing off owo-lib
.child(Components.texture(Identifier.of("owo:textures/gui/config_search.png"), 0, 0, 16, 16, 16, 16));

this.searchBox = new SearchBoxComponent(Sizing.fill(), () -> {
this.searchBox = new SearchBoxComponent(Sizing.expand(), () -> {
if (firstResult != null) firstResult.run();
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
package io.wispforest.limelight.impl.ui;

import io.wispforest.limelight.api.entry.*;
import io.wispforest.limelight.impl.config.LimelightTheme;
import io.wispforest.owo.ui.component.Components;
import io.wispforest.owo.ui.component.SmallCheckboxComponent;
import io.wispforest.owo.ui.container.FlowLayout;
import io.wispforest.owo.ui.core.Insets;
import io.wispforest.owo.ui.core.Sizing;
import io.wispforest.owo.ui.core.Surface;
import io.wispforest.limelight.api.entry.SetSearchTextEntry;
import io.wispforest.limelight.api.entry.ToggleResultEntry;
import io.wispforest.limelight.api.entry.ResultEntry;
import io.wispforest.limelight.api.entry.InvokeResultEntry;
import io.wispforest.limelight.impl.Limelight;
import net.minecraft.client.MinecraftClient;
import net.minecraft.text.HoverEvent;
Expand All @@ -23,13 +20,21 @@ public class ResultEntryComponent extends FlowLayout {
private final LimelightScreen screen;
private final ResultEntry entry;
private final @Nullable SmallCheckboxComponent toggleBox;
private final @Nullable ExpandIndicatorComponent expandIndicator;
private final Surface baseSurface;
private final boolean isChild;

public ResultEntryComponent(LimelightScreen screen, ResultEntry entry) {
super(Sizing.fill(), Sizing.content(), Algorithm.LTR_TEXT);
public ResultEntryComponent(LimelightScreen screen, ResultEntry entry, boolean isChild) {
super(Sizing.fill(), Sizing.content(), Algorithm.HORIZONTAL);
this.screen = screen;
this.entry = entry;
this.isChild = isChild;

LimelightTheme theme = LimelightTheme.current();

padding(Insets.both(2, 4));
baseSurface = !isChild ? Surface.BLANK : Surface.flat(theme.childBackgroundColor());
surface(baseSurface);

MutableText labelBuilder = Text.empty();

Expand All @@ -46,15 +51,15 @@ public ResultEntryComponent(LimelightScreen screen, ResultEntry entry) {
labelBuilder.append(
Text.empty()
.append(entry.extension().name())
.styled(x -> x.withColor(LimelightTheme.current().sourceExtensionColor()))
.styled(x -> x.withColor(isChild ? theme.childSourceExtensionColor() : theme.sourceExtensionColor()))
.styled(x -> x.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, tooltipText)))
);

labelBuilder.append(" ");

labelBuilder.append(Text.empty()
.append(entry.text())
.styled(x -> x.withColor(LimelightTheme.current().resultEntryTextColor())));
.styled(x -> x.withColor(theme.resultEntryTextColor())));

child(new WrappingLabelComponent(labelBuilder));

Expand All @@ -69,6 +74,15 @@ public ResultEntryComponent(LimelightScreen screen, ResultEntry entry) {
} else {
this.toggleBox = null;
}

if (entry instanceof ExpandableResultEntry && !isChild) {
child(Components.spacer().verticalSizing(Sizing.fixed(0)));
this.expandIndicator = new ExpandIndicatorComponent(isChild ? theme.childSourceExtensionColor() : theme.sourceExtensionColor());
child(this.expandIndicator);
}
else {
this.expandIndicator = null;
}
}

public void run() {
Expand All @@ -80,7 +94,7 @@ public void run() {
invoke.run();
}
case SetSearchTextEntry setSearchText -> {
// hey guys did you know I love ConcurrentModificationExceptions
// hey guys did you know I love ConcurrentModificationExceptions; same
MinecraftClient.getInstance().send(() -> {
screen.searchBox.setText(setSearchText.newSearchText());
screen.searchBox.root().focusHandler().focus(screen.searchBox, FocusSource.KEYBOARD_CYCLE);
Expand All @@ -89,6 +103,12 @@ public void run() {
case ToggleResultEntry ignored -> {
toggleBox.checked(!toggleBox.checked());
}
case ExpandableResultEntry expanded -> {
if (parent != null && !isChild) {
((ResultsContainerComponent) parent).toggleExpanded(this, expanded);
expandIndicator.toggle();
}
}
}
}

Expand All @@ -115,7 +135,7 @@ public boolean onMouseDown(double mouseX, double mouseY, int button) {
public boolean onKeyPress(int keyCode, int scanCode, int modifiers) {
if (keyCode == GLFW.GLFW_KEY_ENTER) {
run();
} else {
} else if (root() != null){
root().focusHandler().focus(screen.searchBox, FocusSource.MOUSE_CLICK);
screen.searchBox.onKeyPress(keyCode, scanCode, modifiers);
return true;
Expand All @@ -126,24 +146,27 @@ public boolean onKeyPress(int keyCode, int scanCode, int modifiers) {

@Override
public boolean onCharTyped(char chr, int modifiers) {
root().focusHandler().focus(screen.searchBox, FocusSource.MOUSE_CLICK);
screen.searchBox.onCharTyped(chr, modifiers);

return true;
if (root() != null) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why would root() be null here? aren't input events only routed to components if they're mounted?

Copy link
Collaborator Author

@Minenash Minenash Sep 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why would root() be null here?

IDK. I just now that it can, because it crashed. I'll see if this still happens after my aforementioned changes

root().focusHandler().focus(screen.searchBox, FocusSource.MOUSE_CLICK);
screen.searchBox.onCharTyped(chr, modifiers);
return true;
}
return false;
}

@Override
public void onFocusGained(FocusSource source) {
super.onFocusGained(source);
surface(Surface.outline(LimelightTheme.current().focusOutlineColor()));
surface(baseSurface.and(Surface.outline(LimelightTheme.current().focusOutlineColor())));

applySuggestion();
}

@Override
public void onFocusLost() {
super.onFocusLost();
surface(Surface.BLANK);
surface(baseSurface);

screen.searchBox.setSuggestion(null);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.wispforest.limelight.impl.ui;

import io.wispforest.limelight.api.entry.ExpandableResultEntry;
import io.wispforest.owo.ui.container.Containers;
import io.wispforest.owo.ui.container.FlowLayout;
import io.wispforest.owo.ui.core.Sizing;
import io.wispforest.limelight.api.entry.ResultEntry;
Expand All @@ -8,9 +10,7 @@
import io.wispforest.limelight.impl.ResultGatherer;
import net.minecraft.client.MinecraftClient;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Consumer;

Expand All @@ -19,6 +19,7 @@ public class ResultsContainerComponent extends FlowLayout {
private List<ResultEntry> results = new ArrayList<>();
private boolean hasInitialized = false;
private volatile boolean sentReload = false;
private final Map<ExpandableResultEntry,Boolean> expanded = new HashMap<>();

public ResultsContainerComponent(LimelightScreen screen, ResultGatherContext ctx) {
super(Sizing.fill(), Sizing.content(), Algorithm.VERTICAL);
Expand All @@ -44,6 +45,24 @@ public ResultsContainerComponent(LimelightScreen screen, ResultGatherContext ctx
rebuildContents();
}

void toggleExpanded(ResultEntryComponent component, ExpandableResultEntry resultEntry) {
MinecraftClient.getInstance().send( () -> {
int index = children.indexOf(component)+1;
if (expanded.getOrDefault(resultEntry, false)) {
expanded.put(resultEntry, false);
removeChild(children.get(index));
}
else {
expanded.put(resultEntry, true);
var col = Containers.verticalFlow(Sizing.fill(), Sizing.content());
for (ResultEntry childEntry : resultEntry.children())
col.child(new ResultEntryComponent(screen, childEntry, true));
child(index, col);
component.root().focusHandler().focus(component, FocusSource.KEYBOARD_CYCLE);
}
} );
}

private void rebuildContents() {
results.sort(Comparator.comparing(entry -> {
var id = entry.entryId();
Expand All @@ -58,11 +77,12 @@ private void rebuildContents() {
clearChildren();

for (var entry : results) {
var result = new ResultEntryComponent(screen, entry);
var result = new ResultEntryComponent(screen, entry, false);

if (screen.firstResult == null) screen.firstResult = result;

child(result);

}
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ private int noShadow(DrawContext instance, TextRenderer textRenderer, OrderedTex
if (limelight$drawShadow) {
return original.call(instance, textRenderer, text, x, y, color);
} else {
return instance.drawText(textRenderer, text, x, y, color, false);
return instance.drawText(textRenderer, text, x, y, color, false) + 1;
}
}
}