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 1 commit
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> getChildren();
}
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 expandedResultChildEntryBackgroundColor() {
return 0x33000000;
}

@Override
public int expandedResultChildEntrySourceExtensionColor() {
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 expandedResultChildEntryBackgroundColor() {
return 0x33000000;
}

@Override
public int expandedResultChildEntrySourceExtensionColor() {
return 0xFF666666;
}
};

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

int resultEntryTextColor();

int expandedResultChildEntryBackgroundColor();

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

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

class ExpandIndicatorComponent extends LabelComponent {

public final boolean isExpanded;

public ExpandIndicatorComponent(boolean isExpanded) {
super(Text.literal(">").withColor(LimelightTheme.current().sourceExtensionColor()).formatted(Formatting.BOLD));
this.cursorStyle(CursorStyle.HAND);
this.isExpanded = isExpanded;
}


@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);
if (isExpanded)
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(90));
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
@@ -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,19 @@ public class ResultEntryComponent extends FlowLayout {
private final LimelightScreen screen;
private final ResultEntry entry;
private final @Nullable SmallCheckboxComponent toggleBox;
private final boolean expandedChild;

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

LimelightTheme theme = LimelightTheme.current();

padding(Insets.both(2, 4));
if (expandedChild)
surface(Surface.flat(theme.expandedResultChildEntryBackgroundColor()));

MutableText labelBuilder = Text.empty();

Expand All @@ -46,15 +49,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(expandedChild ? theme.expandedResultChildEntrySourceExtensionColor() : 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 +72,11 @@ public ResultEntryComponent(LimelightScreen screen, ResultEntry entry) {
} else {
this.toggleBox = null;
}

if (entry instanceof ExpandableResultEntry) {
child(Components.spacer().verticalSizing(Sizing.fixed(0)).horizontalSizing(Sizing.expand(100)));
child(new ExpandIndicatorComponent(expanded));
}
}

public void run() {
Expand All @@ -80,7 +88,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 +97,10 @@ public void run() {
case ToggleResultEntry ignored -> {
toggleBox.checked(!toggleBox.checked());
}
case ExpandableResultEntry expanded -> {
if (parent != null)
((ResultsContainerComponent)parent).toggleExpanded(expanded.entryId());
}
}
}

Expand All @@ -115,7 +127,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 +138,32 @@ 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 s = Surface.outline(LimelightTheme.current().focusOutlineColor());
if (expandedChild)
s = s.and(Surface.flat(LimelightTheme.current().expandedResultChildEntryBackgroundColor()));
surface(s);

applySuggestion();
}

@Override
public void onFocusLost() {
super.onFocusLost();
surface(Surface.BLANK);
if (expandedChild)
surface(Surface.flat(LimelightTheme.current().expandedResultChildEntryBackgroundColor()));
else
surface(Surface.BLANK);
screen.searchBox.setSuggestion(null);
}

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

import io.wispforest.limelight.api.entry.ExpandableResultEntry;
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 +9,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 +18,7 @@ public class ResultsContainerComponent extends FlowLayout {
private List<ResultEntry> results = new ArrayList<>();
private boolean hasInitialized = false;
private volatile boolean sentReload = false;
private Map<String,Boolean> expanded = new HashMap<>();

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

void toggleExpanded(String id) {
expanded.put(id, !expanded.getOrDefault(id, false));
MinecraftClient.getInstance().send(this::rebuildContents);
}

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

for (var entry : results) {
var result = new ResultEntryComponent(screen, entry);
boolean isExpanded = entry instanceof ExpandableResultEntry && expanded.getOrDefault(entry.entryId(), false);
var result = new ResultEntryComponent(screen, entry, false, isExpanded);

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

child(result);

if (isExpanded) {
for (ResultEntry e : ((ExpandableResultEntry)entry).getChildren())
child(new ResultEntryComponent(screen, e, true, false));
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I assume this just doesn't do anything if a child entry of an expandable entry is also expandable?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, I probably should have documented somewhere, but this behavior is intentional. There isn't a good way to distinguish child-child entries visually (especially not one that scales to the theoretical infinite nesting), and it would greatly complicate things

}
});

Expand Down