Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
a4174a6
change default KeyBinds.EDITOR_SHOW_CALLS to ctrl + alt + c because c…
supersaiyansubtlety Sep 21, 2025
531a6b3
add all KeyBind combinations in InputUtil::putKeybindAction
supersaiyansubtlety Sep 21, 2025
ff4fbc3
putKeybindAction -> putKeyBindAction
supersaiyansubtlety Sep 21, 2025
f6960cb
use InputMap instead of key listener in EnigmaQuickFindDialogue
supersaiyansubtlety Sep 21, 2025
0e8c8bb
separate MULTILINE_DIALOG_SAVE from KeyBinds.DIALOG_SAVE
supersaiyansubtlety Sep 21, 2025
a763d3a
use InputMap instead of key listener in ClassSelector
supersaiyansubtlety Sep 21, 2025
3bcff3a
use InputMap instead of key listener in ChangeDialog
supersaiyansubtlety Sep 21, 2025
3b80b51
use InputMap instead of key listener in SearchDialog
supersaiyansubtlety Sep 21, 2025
a04f6c6
use InputMap instead of key listener in StructureDocker
supersaiyansubtlety Sep 21, 2025
32fe644
use InputMap instead of key listener in ConvertingTextField
supersaiyansubtlety Sep 21, 2025
42af866
use InputMap instead of key listener in EditorTabbedPane
supersaiyansubtlety Sep 22, 2025
35fd4d9
javadoc and deprecate KeyBind::matches
supersaiyansubtlety Sep 22, 2025
d073a8b
merge InputUtil into GuiUtil
supersaiyansubtlety Sep 22, 2025
2b73ffe
use local syntaxpain version
supersaiyansubtlety Sep 23, 2025
9fbbb36
add KeyBinds.QUICK_FIND_DIALOG_CLOSE
supersaiyansubtlety Sep 23, 2025
e6f132f
make EnigmaQuickFindToolBar.persistentCheckBox selected state persistent
supersaiyansubtlety Sep 23, 2025
2f1f990
keep EnigmaQuickFindToolBar.persistentCheckBox in sync with Config.pe…
supersaiyansubtlety Sep 23, 2025
76849b3
make EDITOR_QUICK_FIND keybind configurable
supersaiyansubtlety Sep 23, 2025
a4c6c1c
checkstyle
supersaiyansubtlety Sep 23, 2025
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
Expand Up @@ -19,6 +19,8 @@
import java.util.Comparator;
import java.util.List;

import static org.quiltmc.enigma.gui.util.GuiUtil.putKeyBindAction;

public class ClassSelector extends JTree {
public static final Comparator<ClassEntry> DEOBF_CLASS_COMPARATOR = Comparator.comparing(ClassEntry::getFullName);

Expand Down Expand Up @@ -49,27 +51,29 @@ public ClassSelector(Gui gui, Comparator<ClassEntry> comparator) {
}
}));

this.addKeyListener(GuiUtil.onKeyPress(e -> {
TreePath[] paths = this.getSelectionPaths();

putKeyBindAction(KeyBinds.EDITOR_TOGGLE_MAPPING, this, e -> {
final TreePath[] paths = this.getSelectionPaths();
if (paths != null) {
if (KeyBinds.EDITOR_TOGGLE_MAPPING.matches(e)) {
for (TreePath path : paths) {
if (path.getLastPathComponent() instanceof ClassSelectorClassNode node) {
gui.toggleMappingFromEntry(node.getObfEntry());
}
for (final TreePath path : paths) {
if (path.getLastPathComponent() instanceof ClassSelectorClassNode node) {
gui.toggleMappingFromEntry(node.getObfEntry());
}
}
}
});

if (this.selectionListener != null && KeyBinds.SELECT.matches(e)) {
for (TreePath path : paths) {
putKeyBindAction(KeyBinds.SELECT, this, e -> {
if (this.selectionListener != null) {
final TreePath[] paths = this.getSelectionPaths();
if (paths != null) {
for (final TreePath path : paths) {
if (path.getLastPathComponent() instanceof ClassSelectorClassNode node) {
this.selectionListener.onSelectClass(node.getObfEntry());
}
}
}
}
}));
});

this.setCellRenderer(new ClassTreeCellRenderer(gui, this));
ToolTipManager.sharedInstance().registerComponent(this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import org.quiltmc.enigma.gui.config.theme.properties.NoneThemeProperties;
import org.quiltmc.enigma.gui.config.theme.properties.SystemThemeProperties;
import org.quiltmc.enigma.gui.config.theme.properties.composite.SyntaxPaneProperties;
import org.quiltmc.enigma.gui.dialog.EnigmaQuickFindDialog;
import org.quiltmc.enigma.util.I18n;
import org.quiltmc.syntaxpain.SyntaxpainConfiguration;

Expand Down Expand Up @@ -78,6 +77,9 @@ public final class Config extends ReflectiveConfig {
@Comment("You shouldn't enable options in this section unless you know what you're doing!")
public final DevSection development = new DevSection();

@Comment("Whether editors' quick find toolbars should remain visible when they lose focus.")
public final TrackedValue<Boolean> persistentEditorQuickFind = this.value(true);

/**
* The look and feel stored in the config: do not use this unless setting! Use {@link #activeThemeChoice} instead,
* since look and feel is final once loaded.
Expand Down Expand Up @@ -252,7 +254,8 @@ public static void updateSyntaxpain() {
SyntaxPaneProperties.Colors colors = getCurrentSyntaxPaneColors();

SyntaxpainConfiguration.setEditorFont(fonts.editor.value());
SyntaxpainConfiguration.setQuickFindDialogFactory(EnigmaQuickFindDialog::new);
// disable dialog; EditorPanel uses a tool bar component instead
SyntaxpainConfiguration.setQuickFindDialogFactory(null);

SyntaxpainConfiguration.setLineRulerPrimaryColor(colors.lineNumbersForeground.value());
SyntaxpainConfiguration.setLineRulerSecondaryColor(colors.lineNumbersBackground.value());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
package org.quiltmc.enigma.gui.config.keybind;

import org.quiltmc.enigma.gui.util.GuiUtil;
import org.quiltmc.enigma.util.I18n;
import org.tinylog.Logger;

import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.KeyStroke;

public record KeyBind(String name, String category, List<Combination> combinations) {
Expand Down Expand Up @@ -42,6 +48,12 @@ public void setFrom(KeyBind other) {
this.combinations.addAll(other.combinations);
}

/**
* Prefer using component's {@link InputMap}s and {@link ActionMap}s to checking this in {@link KeyListener}s.
*
* @see GuiUtil#putKeyBindAction(KeyBind, JComponent, GuiUtil.FocusCondition, ActionListener)
*/
@Deprecated
public boolean matches(KeyEvent e) {
return this.combinations.stream().anyMatch(c -> c.matches(e));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ public final class KeyBinds {
public static final KeyBind EXIT = KeyBind.builder("close").key(KeyEvent.VK_ESCAPE).build();
public static final KeyBind SELECT = KeyBind.builder("select").key(KeyEvent.VK_ENTER).build();
public static final KeyBind DIALOG_SAVE = KeyBind.builder("dialog_save").key(KeyEvent.VK_ENTER).build();
public static final KeyBind MULTILINE_DIALOG_SAVE = KeyBind.builder("multiline_dialog_save").mod(InputEvent.CTRL_DOWN_MASK).key(KeyEvent.VK_ENTER).build();

public static final KeyBind QUICK_FIND_DIALOG_IGNORE_CASE = KeyBind.builder("ignore_case", QUICK_FIND_DIALOG_CATEGORY).key(KeyEvent.VK_C).build();
public static final KeyBind QUICK_FIND_DIALOG_REGEX = KeyBind.builder("regex", QUICK_FIND_DIALOG_CATEGORY).key(KeyEvent.VK_R).build();
public static final KeyBind QUICK_FIND_DIALOG_WRAP = KeyBind.builder("wrap", QUICK_FIND_DIALOG_CATEGORY).key(KeyEvent.VK_W).build();
public static final KeyBind QUICK_FIND_DIALOG_NEXT = KeyBind.builder("next", QUICK_FIND_DIALOG_CATEGORY).key(KeyEvent.VK_ENTER).build();
public static final KeyBind QUICK_FIND_DIALOG_PREVIOUS = KeyBind.builder("previous", QUICK_FIND_DIALOG_CATEGORY).mod(InputEvent.SHIFT_DOWN_MASK).key(KeyEvent.VK_ENTER).build();
public static final KeyBind QUICK_FIND_DIALOG_CLOSE = KeyBind.builder("close_quick_find", QUICK_FIND_DIALOG_CATEGORY).key(KeyEvent.VK_ESCAPE).build();
public static final KeyBind SEARCH_DIALOG_NEXT = KeyBind.builder("next", SEARCH_DIALOG_CATEGORY).key(KeyEvent.VK_DOWN).build();
public static final KeyBind SEARCH_DIALOG_PREVIOUS = KeyBind.builder("previous", SEARCH_DIALOG_CATEGORY).key(KeyEvent.VK_UP).build();

Expand All @@ -35,7 +37,7 @@ public final class KeyBinds {
public static final KeyBind EDITOR_SEARCH_STRUCTURE = KeyBind.builder("search_structure", EDITOR_CATEGORY).mod(InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK).key(KeyEvent.VK_T).build();
public static final KeyBind EDITOR_SHOW_INHERITANCE = KeyBind.builder("show_inheritance", EDITOR_CATEGORY).mod(InputEvent.CTRL_DOWN_MASK).key(KeyEvent.VK_I).build();
public static final KeyBind EDITOR_SHOW_IMPLEMENTATIONS = KeyBind.builder("show_implementations", EDITOR_CATEGORY).mod(InputEvent.CTRL_DOWN_MASK).key(KeyEvent.VK_M).build();
public static final KeyBind EDITOR_SHOW_CALLS = KeyBind.builder("show_calls", EDITOR_CATEGORY).mod(InputEvent.CTRL_DOWN_MASK).key(KeyEvent.VK_C).build();
public static final KeyBind EDITOR_SHOW_CALLS = KeyBind.builder("show_calls", EDITOR_CATEGORY).mod(InputEvent.CTRL_DOWN_MASK | InputEvent.ALT_DOWN_MASK).key(KeyEvent.VK_C).build();
public static final KeyBind EDITOR_SHOW_CALLS_SPECIFIC = KeyBind.builder("show_calls_specific", EDITOR_CATEGORY).mod(InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK).key(KeyEvent.VK_C).build();
public static final KeyBind EDITOR_OPEN_ENTRY = KeyBind.builder("open_entry", EDITOR_CATEGORY).mod(InputEvent.CTRL_DOWN_MASK).key(KeyEvent.VK_N).build();
public static final KeyBind EDITOR_OPEN_PREVIOUS = KeyBind.builder("open_previous", EDITOR_CATEGORY).mod(InputEvent.CTRL_DOWN_MASK).key(KeyEvent.VK_P).build();
Expand All @@ -61,20 +63,21 @@ public final class KeyBinds {
public static final KeyBind SEARCH_METHOD = KeyBind.builder("search_method", MENU_CATEGORY).build();
public static final KeyBind SEARCH_FIELD = KeyBind.builder("search_field", MENU_CATEGORY).build();

private static final List<KeyBind> DEFAULT_KEY_BINDS = Stream.of(EXIT, SELECT, DIALOG_SAVE, QUICK_FIND_DIALOG_NEXT,
QUICK_FIND_DIALOG_PREVIOUS, SEARCH_DIALOG_NEXT, SEARCH_DIALOG_PREVIOUS, EDITOR_RENAME, EDITOR_PASTE,
EDITOR_EDIT_JAVADOC, EDITOR_SHOW_INHERITANCE, EDITOR_SHOW_IMPLEMENTATIONS, EDITOR_SHOW_CALLS,
EDITOR_SHOW_CALLS_SPECIFIC, EDITOR_OPEN_ENTRY, EDITOR_OPEN_PREVIOUS, EDITOR_OPEN_NEXT,
private static final List<KeyBind> DEFAULT_KEY_BINDS = Stream.of(EXIT, SELECT, DIALOG_SAVE, MULTILINE_DIALOG_SAVE,
QUICK_FIND_DIALOG_NEXT, QUICK_FIND_DIALOG_PREVIOUS, QUICK_FIND_DIALOG_CLOSE, SEARCH_DIALOG_NEXT, SEARCH_DIALOG_PREVIOUS,
EDITOR_RENAME, EDITOR_PASTE, EDITOR_EDIT_JAVADOC, EDITOR_SHOW_INHERITANCE, EDITOR_SHOW_IMPLEMENTATIONS,
EDITOR_SHOW_CALLS, EDITOR_SHOW_CALLS_SPECIFIC, EDITOR_OPEN_ENTRY, EDITOR_OPEN_PREVIOUS, EDITOR_OPEN_NEXT,
EDITOR_TOGGLE_MAPPING, EDITOR_ZOOM_IN, EDITOR_ZOOM_OUT, EDITOR_CLOSE_TAB, EDITOR_RELOAD_CLASS,
EDITOR_QUICK_FIND, EDITOR_SHOW_STRUCTURE, EDITOR_SEARCH_STRUCTURE, SAVE_MAPPINGS, DROP_MAPPINGS,
RELOAD_MAPPINGS, RELOAD_ALL, MAPPING_STATS, SEARCH, SEARCH_ALL, SEARCH_CLASS, SEARCH_METHOD, SEARCH_FIELD).map(KeyBind::toImmutable).toList();

private static final List<KeyBind> CONFIGURABLE_KEY_BINDS = List.of(EDITOR_RENAME, EDITOR_PASTE, EDITOR_EDIT_JAVADOC,
EDITOR_SHOW_INHERITANCE, EDITOR_SHOW_IMPLEMENTATIONS, EDITOR_SHOW_CALLS, EDITOR_SHOW_CALLS_SPECIFIC,
EDITOR_OPEN_ENTRY, EDITOR_OPEN_PREVIOUS, EDITOR_OPEN_NEXT, EDITOR_TOGGLE_MAPPING, EDITOR_ZOOM_IN,
EDITOR_ZOOM_OUT, EDITOR_CLOSE_TAB, EDITOR_RELOAD_CLASS, EDITOR_SHOW_STRUCTURE, EDITOR_SEARCH_STRUCTURE,
SAVE_MAPPINGS, DROP_MAPPINGS, RELOAD_MAPPINGS, RELOAD_ALL, MAPPING_STATS, SEARCH, SEARCH_ALL, SEARCH_CLASS,
SEARCH_METHOD, SEARCH_FIELD);
EDITOR_ZOOM_OUT, EDITOR_CLOSE_TAB, EDITOR_RELOAD_CLASS, EDITOR_QUICK_FIND, EDITOR_SHOW_STRUCTURE,
EDITOR_SEARCH_STRUCTURE, SAVE_MAPPINGS, DROP_MAPPINGS, RELOAD_MAPPINGS, RELOAD_ALL, MAPPING_STATS, SEARCH,
SEARCH_ALL, SEARCH_CLASS, SEARCH_METHOD, SEARCH_FIELD
);
// Editing entries in CONFIGURABLE_KEY_BINDS directly wouldn't allow to revert the changes instead of saving
private static List<KeyBind> editableKeyBinds;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.quiltmc.enigma.gui.dialog;

import org.quiltmc.enigma.gui.config.keybind.KeyBinds;
import org.quiltmc.enigma.gui.util.GuiUtil;
import org.quiltmc.enigma.util.I18n;

import java.awt.BorderLayout;
Expand All @@ -12,6 +11,8 @@
import javax.swing.JLabel;
import javax.swing.JPanel;

import static org.quiltmc.enigma.gui.util.GuiUtil.putKeyBindAction;

public class ChangeDialog {
public static void show(Window parent) {
// init frame
Expand All @@ -31,11 +32,7 @@ public static void show(Window parent) {
JButton okButton = new JButton(I18n.translate("prompt.ok"));
buttonPanel.add(okButton);
okButton.addActionListener(event -> frame.dispose());
okButton.addKeyListener(GuiUtil.onKeyPress(e -> {
if (KeyBinds.EXIT.matches(e)) {
frame.dispose();
}
}));
putKeyBindAction(KeyBinds.EXIT, okButton, e -> frame.dispose());

// show the frame
frame.pack();
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* Copyright 2008 Ayman Al-Sairafi [email protected]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.quiltmc.enigma.gui.dialog;

import org.quiltmc.enigma.gui.config.Config;
import org.quiltmc.enigma.gui.config.keybind.KeyBinds;
import org.quiltmc.enigma.gui.util.GuiUtil;
import org.quiltmc.enigma.gui.util.GuiUtil.FocusCondition;
import org.quiltmc.enigma.util.I18n;
import org.quiltmc.syntaxpain.QuickFindToolBar;

import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.SwingConstants;

import static org.quiltmc.enigma.gui.util.GuiUtil.putKeyBindAction;

/**
* Extension of {@link QuickFindToolBar} to allow using keybindings, and improve UI.
*/
public class EnigmaQuickFindToolBar extends QuickFindToolBar {
protected JCheckBox persistentCheckBox;
protected JButton closeButton;

public EnigmaQuickFindToolBar() {
super();
// keybinding support
this.reloadKeyBinds();

// configure parent components
this.ignoreCaseCheckBox.setMnemonic(KeyBinds.QUICK_FIND_DIALOG_IGNORE_CASE.getKeyCode());
this.regexCheckBox.setMnemonic(KeyBinds.QUICK_FIND_DIALOG_REGEX.getKeyCode());
this.wrapCheckBox.setMnemonic(KeyBinds.QUICK_FIND_DIALOG_WRAP.getKeyCode());

// make buttons icon-only
this.nextButton.setText("");
this.nextButton.setIcon(GuiUtil.getDownChevron());
this.prevButton.setText("");
this.prevButton.setIcon(GuiUtil.getUpChevron());

// add custom components
// push the rest of the components to the right
this.add(Box.createHorizontalGlue());

this.addSeparator();

this.persistentCheckBox = new JCheckBox();
this.persistentCheckBox.setFocusable(false);
this.persistentCheckBox.setOpaque(false);
this.persistentCheckBox.setVerticalTextPosition(SwingConstants.BOTTOM);
this.persistentCheckBox.setHorizontalTextPosition(SwingConstants.LEADING);
this.persistentCheckBox.addActionListener(this);
this.persistentCheckBox.addItemListener(e -> {
final boolean selected = this.persistentCheckBox.isSelected();
if (selected != Config.main().persistentEditorQuickFind.value()) {
Config.main().persistentEditorQuickFind.setValue(selected);
}

// request focus so when it's lost this may be dismissed
this.requestFocus();
});
this.persistentCheckBox.setSelected(Config.main().persistentEditorQuickFind.value());
Config.main().persistentEditorQuickFind.registerCallback(callback -> {
final Boolean configured = callback.value();
if (this.persistentCheckBox.isSelected() != configured) {
this.persistentCheckBox.setSelected(configured);
}
});
this.add(this.persistentCheckBox);

this.addSeparator();

this.closeButton = new JButton();
this.closeButton.setIcon(GuiUtil.getCloseIcon());
this.closeButton.setFocusable(false);
this.closeButton.setOpaque(false);
this.closeButton.addActionListener(e -> this.dismiss());
this.add(this.closeButton);

this.translate();
}

@Override
protected boolean dismissOnFocusLost() {
return !this.persistentCheckBox.isSelected();
}

public void translate() {
this.notFound = I18n.translate("editor.quick_find.not_found");

this.ignoreCaseCheckBox.setText(I18n.translate("editor.quick_find.ignore_case"));
this.regexCheckBox.setText(I18n.translate("editor.quick_find.use_regex"));
this.wrapCheckBox.setText(I18n.translate("editor.quick_find.wrap"));

this.persistentCheckBox.setText(I18n.translate("editor.quick_find.persistent"));
}

public void reloadKeyBinds() {
putKeyBindAction(KeyBinds.QUICK_FIND_DIALOG_PREVIOUS, this.searchField, e -> this.prevButton.doClick());
putKeyBindAction(KeyBinds.QUICK_FIND_DIALOG_NEXT, this.searchField, e -> this.nextButton.doClick());
putKeyBindAction(
KeyBinds.QUICK_FIND_DIALOG_CLOSE, this, FocusCondition.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
e -> this.setVisible(false)
);
}
}
Loading
Loading