Skip to content

Commit

Permalink
Add search all classes popup (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
tth05 authored Jan 13, 2022
1 parent eb8774b commit dd28948
Show file tree
Hide file tree
Showing 9 changed files with 222 additions and 12 deletions.
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ version = "1.6.0"
repositories {
mavenCentral()
maven { url 'https://jitpack.io' }
maven { url "https://packagecloud.io/tth05/repo/maven2" }
}

dependencies {
implementation("com.github.tth05:jindex:0.0.3")
implementation("com.github.tth05:SCNet:18bc6c5")

implementation('com.formdev:flatlaf:1.6.5')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ private static void startUI() {
UIManager.put("Slider.focusedColor", new ColorUIResource(new Color(0, 0, 0, 0)));
UIManager.put("Table.focusSelectedCellHighlightBorder", new BorderUIResource(BorderFactory.createEmptyBorder(0, 5, 0, 0)));
UIManager.put("Table.focusCellHighlightBorder", new BorderUIResource(BorderFactory.createEmptyBorder(0, 3, 0, 0)));
UIManager.put("Tree.selectionBackground", new ColorUIResource(new Color(5 / 255f, 127 / 255f, 242 / 255f, 0.5f)));
UIManager.put("List.selectionBackground", new ColorUIResource(new Color(5 / 255f, 127 / 255f, 242 / 255f, 0.5f)));

var mainWindow = new MainWindow();
mainWindow.setSize(1280, 720);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.github.minecraft_ta.totalDebugCompanion.messages.script;

import com.formdev.flatlaf.extras.FlatSVGIcon;
import com.github.minecraft_ta.totalDebugCompanion.util.TextUtils;
import com.github.tth05.scnet.message.AbstractMessageOutgoing;
import com.github.tth05.scnet.util.ByteBufferOutputStream;

Expand Down Expand Up @@ -29,9 +30,9 @@ public void write(ByteBufferOutputStream messageStream) {
}

public enum ExecutionEnvironment {
THREAD(html("Thread", "Run on a separate thread"), null),
PRE_TICK(html("Pre Tick", "Run on main thread, pre game loop tick"), new FlatSVGIcon("icons/warning.svg")),
POST_TICK(html("Post Tick", "Run on main thread, post game loop tick"), new FlatSVGIcon("icons/warning.svg"));
THREAD(TextUtils.htmlHighlightString("Thread", " - ", "Run on a separate thread"), null),
PRE_TICK(TextUtils.htmlHighlightString("Pre Tick", " - ", "Run on main thread, pre game loop tick"), new FlatSVGIcon("icons/warning.svg")),
POST_TICK(TextUtils.htmlHighlightString("Post Tick", " - ", "Run on main thread, post game loop tick"), new FlatSVGIcon("icons/warning.svg"));

private final String label;
private final Icon icon;
Expand All @@ -48,9 +49,5 @@ public String getLabel() {
public Icon getIcon() {
return this.icon;
}

private static String html(String label, String desc) {
return "<html><span style='color: rgb(187, 187, 187)'>%s</span> - <span style='color: rgb(150, 150, 150)'>%s</span></html>".formatted(label, desc);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.github.minecraft_ta.totalDebugCompanion.model.ScriptView;
import com.github.minecraft_ta.totalDebugCompanion.ui.components.global.EditorTabs;
import com.github.minecraft_ta.totalDebugCompanion.util.FileUtils;
import com.github.minecraft_ta.totalDebugCompanion.util.TextUtils;

import javax.swing.*;
import javax.swing.event.TreeExpansionEvent;
Expand Down Expand Up @@ -111,7 +112,12 @@ public Component getTreeCellRendererComponent(JTree tree, Object value, boolean
if (!(value instanceof LazyTreeNode treeNode))
return this;

setText(((TreeItem) treeNode.getUserObject()).fileName);
var fileName = ((TreeItem) treeNode.getUserObject()).fileName;
var splitIndex = fileName.lastIndexOf('.', fileName.length() - ".java".length() - 1);
if (splitIndex != -1)
setText(TextUtils.htmlHighlightString(fileName.substring(splitIndex + 1), " ", fileName.substring(0, splitIndex)));
else
setText(fileName);
return this;
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.formdev.flatlaf.extras.FlatSVGIcon;
import com.github.minecraft_ta.totalDebugCompanion.ui.components.editors.AbstractCodeViewPanel;
import com.github.minecraft_ta.totalDebugCompanion.util.TextUtils;
import org.eclipse.lsp4j.CompletionItem;

import javax.swing.*;
Expand Down Expand Up @@ -34,9 +35,8 @@ public Component getListCellRendererComponent(JList<?> list, Object value, int i
if (dividerIndex == -1)
dividerIndex = label.indexOf(':');

var renderText = dividerIndex == -1 ? label : """
<html><span style='color: rgb(187, 187, 187)'>%s</span> <span style='color: rgb(150, 150, 150)'>%s</span></html>
""".formatted(label.substring(0, dividerIndex - 1), label.substring(dividerIndex + 2));
var renderText = dividerIndex == -1 ? label :
TextUtils.htmlHighlightString(label.substring(0, dividerIndex - 1), " ", label.substring(dividerIndex + 2));
var component = super.getListCellRendererComponent(list, renderText, index, isSelected, cellHasFocus);

setIcon(switch (item.getKind()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,19 @@
import com.github.minecraft_ta.totalDebugCompanion.util.UIUtils;

import javax.swing.*;
import java.awt.*;
import java.awt.event.AWTEventListener;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.lang.reflect.Field;
import java.util.function.Consumer;

public class MainWindow extends JFrame {
public class MainWindow extends JFrame implements AWTEventListener {

private final EditorTabs editorTabs = new EditorTabs();

private long lastShiftReleasedTime = 0;

public MainWindow() {
var root = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);

Expand Down Expand Up @@ -68,6 +73,27 @@ public void actionPerformed(ActionEvent e) {
setJMenuBar(menuBar);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setTitle("TotalDebugCompanion");

Toolkit.getDefaultToolkit().addAWTEventListener(this, AWTEvent.KEY_EVENT_MASK);
}

@Override
public void eventDispatched(AWTEvent event) {
if (!(event instanceof KeyEvent))
return;

KeyEvent keyEvent = (KeyEvent) event;
if (keyEvent.getID() != 402 || keyEvent.getKeyCode() != KeyEvent.VK_SHIFT)
return;

long currentTime = System.currentTimeMillis();
if (currentTime - this.lastShiftReleasedTime > 300) {
this.lastShiftReleasedTime = currentTime;
return;
}

this.lastShiftReleasedTime = 0;
SearchEverywherePopup.open(this.getGraphicsConfiguration());
}

public EditorTabs getEditorTabs() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
package com.github.minecraft_ta.totalDebugCompanion.ui.views;

import com.formdev.flatlaf.extras.FlatSVGIcon;
import com.github.minecraft_ta.totalDebugCompanion.CompanionApp;
import com.github.minecraft_ta.totalDebugCompanion.messages.codeView.DecompileAndOpenRequestMessage;
import com.github.minecraft_ta.totalDebugCompanion.ui.components.FlatIconTextField;
import com.github.minecraft_ta.totalDebugCompanion.util.DocumentChangeListener;
import com.github.minecraft_ta.totalDebugCompanion.util.TextUtils;
import com.github.minecraft_ta.totalDebugCompanion.util.UIUtils;
import com.github.tth05.jindex.ClassIndex;
import com.github.tth05.jindex.IndexedClass;

import javax.swing.*;
import javax.swing.border.CompoundBorder;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.lang.reflect.Modifier;
import java.util.Arrays;

public class SearchEverywherePopup extends JFrame {

private static final ClassIndex CLASS_INDEX = new ClassIndex(CompanionApp.getRootPath().resolve("index").toAbsolutePath().normalize().toString());

private static final SearchEverywherePopup INSTANCE = new SearchEverywherePopup();

private final JList<IndexedClass> resultList = new JList<>(new DefaultListModel<>());
{
resultList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
resultList.addListSelectionListener(e -> {
var rect = resultList.getCellBounds(e.getFirstIndex(), e.getLastIndex());
if (rect == null)
return;

resultList.scrollRectToVisible(rect);
});

resultList.setCellRenderer(new DefaultListCellRenderer() {
@Override
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
var indexedClass = (IndexedClass) value;
var renderText = TextUtils.htmlHighlightString(indexedClass.getName(), " ",
indexedClass.getNameWithPackage().substring(0, indexedClass.getNameWithPackage().lastIndexOf('.')));

var component = (JLabel) super.getListCellRendererComponent(list, renderText, index, isSelected, cellHasFocus);
component.setBorder(new CompoundBorder(BorderFactory.createEmptyBorder(2, 0, 2, 0), component.getBorder()));

if (Modifier.isInterface(indexedClass.getAccessFlags()))
setIcon(CodeCompletionPopup.INTERFACE_ICON);
else if ((indexedClass.getAccessFlags() & 0x00004000) != 0)
setIcon(CodeCompletionPopup.ENUM_ICON);
else
setIcon(CodeCompletionPopup.CLASS_ICON);

return component;
}
});
resultList.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() < 2 || !SwingUtilities.isLeftMouseButton(e))
return;

var clickedIndex = resultList.locationToIndex(e.getPoint());
if (clickedIndex == -1 || !resultList.getCellBounds(0, resultList.getLastVisibleIndex()).contains(e.getPoint()))
return;

openClass(clickedIndex);
}
});
}
private final JScrollPane resultListScrollPane = new JScrollPane(this.resultList);
{
resultListScrollPane.setPreferredSize(new Dimension(500, 500));
}

private final FlatIconTextField searchTextField = new FlatIconTextField(new FlatSVGIcon("icons/search.svg"));
{
searchTextField.getDocument().addDocumentListener((DocumentChangeListener) e -> {
var query = searchTextField.getText();
var model = (DefaultListModel<IndexedClass>) resultList.getModel();
if (query == null || query.isBlank()) {
model.clear();
return;
}

var classes = CLASS_INDEX.findClasses(query, 40);
var selectedClass = resultList.getSelectedIndex() == -1 ? null : model.get(resultList.getSelectedIndex()).getNameWithPackage();

model.clear();
model.addAll(Arrays.asList(classes));

for (int i = 0; i < classes.length && selectedClass != null; i++) {
if (!classes[i].getNameWithPackage().equals(selectedClass))
continue;

resultList.setSelectedIndex(i);
return;
}

resultList.setSelectedIndex(0);
});
((AbstractDocument) searchTextField.getDocument()).setDocumentFilter(new DocumentFilter() {
@Override
public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException {
if (!string.chars().allMatch(i -> i < 128))
return;

super.insertString(fb, offset, string, attr);
}

@Override
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
if (!text.chars().allMatch(i -> i < 128))
return;

super.replace(fb, offset, length, text, attrs);
}
});

searchTextField.registerKeyboardAction((e) -> resultList.setSelectedIndex(Math.max(0, resultList.getSelectedIndex() - 1)), KeyStroke.getKeyStroke("UP"), JComponent.WHEN_IN_FOCUSED_WINDOW);
searchTextField.registerKeyboardAction((e) -> resultList.setSelectedIndex(Math.min(resultList.getModel().getSize() - 1, resultList.getSelectedIndex() + 1)), KeyStroke.getKeyStroke("DOWN"), JComponent.WHEN_IN_FOCUSED_WINDOW);
}
public SearchEverywherePopup() {
setLayout(new BorderLayout());
getRootPane().registerKeyboardAction(e -> INSTANCE.setVisible(false), KeyStroke.getKeyStroke("ESCAPE"), JComponent.WHEN_IN_FOCUSED_WINDOW);
getRootPane().registerKeyboardAction(e -> openClass(resultList.getSelectedIndex()), KeyStroke.getKeyStroke("ENTER"), JComponent.WHEN_IN_FOCUSED_WINDOW);

add(this.searchTextField, BorderLayout.NORTH);
add(this.resultListScrollPane, BorderLayout.CENTER);

setUndecorated(true);
pack();
addWindowFocusListener(new WindowAdapter() {
@Override
public void windowLostFocus(WindowEvent e) {
INSTANCE.setVisible(false);
}
});
}

public static void open(GraphicsConfiguration graphicsConfiguration) {
if (INSTANCE.isVisible()) {
INSTANCE.toFront();
return;
}

INSTANCE.setVisible(true);
UIUtils.centerJFrame(INSTANCE, graphicsConfiguration);

INSTANCE.searchTextField.grabFocus();
INSTANCE.searchTextField.selectAll();
}

private void openClass(int index) {
if (index < 0)
return;

CompanionApp.SERVER.getMessageProcessor().enqueueMessage(new DecompileAndOpenRequestMessage(resultList.getModel().getElementAt(index).getNameWithPackage()));
setVisible(false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,8 @@ public static int countNewLines(String s) {

return count;
}

public static String htmlHighlightString(String primary, String divider, String secondary) {
return "<html><span style='color: rgb(187, 187, 187)'>%s</span>%s<span style='color: rgb(150, 150, 150)'>%s</span></html>".formatted(primary, divider, secondary);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -124,4 +124,9 @@ public static void centerJFrame(JFrame frame) {
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
frame.setLocation(dim.width / 2 - frame.getSize().width / 2, dim.height / 2 - frame.getSize().height / 2);
}

public static void centerJFrame(JFrame frame, GraphicsConfiguration gc) {
Rectangle dim = gc.getBounds();
frame.setLocation(dim.x + (dim.width / 2 - frame.getSize().width / 2), dim.height / 2 - frame.getSize().height / 2);
}
}

0 comments on commit dd28948

Please sign in to comment.