Skip to content

Commit b3bd7b1

Browse files
Entry tooltips (#307)
* add POC tooltip to EditorPanel editor that shows full name of entry under cursor * update tooltip content when mouse moves, but can't get JToolTip to resize+move * replace EditorPanel's use of JToolTip and TooltipManager with JWindow and timers, respectively * check if same token instead of same entry when updating tooltip * replace complex Optional composition with consumer methods * extract BaseEditorPanel without tooltip, navigator, or listeners * display entries' entire outer source class in their tooltips * always set tooltipEditor classhandle instead of setting source when it's the same class (editor bounds were 0x0 when setting source) navigate to tooltip target entry declaration when showing tooltip * add javaparser dep matching #308 * implement source trimming for classes using javaparser * minor improvements * minor cleanup * make trimFactor a param instead of a field * implement source trimming for methods * match declarations only by range and extract findDeclaration * inline variable * implement field source trimming stop excluding curly braces from method and class sources * fix tooltip source trimming for static record fields add "No source available" label when there's no classhandle * update TODOs centralize target name reporting * extract TooltipEditorPanel * trim param tooltip target source to parent method refine error messages * fail early when target declaration token is missing add local source trimming * fix tooltip source trimming for constructors * minor refactor * show record component parent instead of just component; matches param showing parent method * when excluding implements from record component parent, find token instead of assuming offset * close and destroy tooltip when source changes * silently ignore missing declaration tokens (until #252 is fixed) * restore quickFindToolbar to ui stop closing tooltip's class handles as tabs may still need them; remove ClassHandleListener instead rename TooltipEditorPanel -> DeclarationSnippetPanel extract EditorTooltip add test input for easier manual tooltip testing * restore EditorPanel popupMenu functionality * improve caret pos logic in BaseEditorPanel::setSource * replace source with message if the declaration token could be found * implement source snippet unindenting * replace entry simple name label with formatted parent name label * add 'From: ' prefix to parent label left-align tooltip rows * add javadocs to tooltip * allow disabling tooltip * make tooltip optionally interactable implement dragging to move tooltip * prevent hiding tooltip when cursor is over a token or the tooltip * fix parent label for top-level classes and add missing dot separator for package format labels use GridBagLayout for param javadocs (currently takes up extra space) * allow clicking entries withing tooltip to populate tooltip with that entry's information * fix calculation for offsetting multiline snippet pos to un-trimmed pos allow clicking parent entries in tooltips to populate tooltip when ctrl+clicking entries in tooltips, open entry tab * minor improvements, add TODOs * resolve references when finding tooltip targets * customize tooltip target highlighting * update TODOs regarding records * polish tooltip positioning fix exception when consumeMousePosition... methods where passed a component that wasn't showing fix several cases where the tooltip would hide when it shouldn't or hiden't when it should * increase padding at outer edges of tooltip rows add tooltip border * use a JPanel with a GridBagLayout instead of a Box as the content pane for EditorTooltip; allows elements to expand to fill their space double-pack in EditorTooltip's declarationSnippet source set listener to eliminate extra space, because swing </3 * reject some TODOs * ctrl+click on parent package label to naviage to package * fix tooltip separators improve "No source available" message formatting * respect tooltip ineractable config for parent package clicking add z_ prefix to tooltip test input to avoid changing SearchMappingsTest * use global focus listener to ensure tooltip is closed when neither it nor its editor has focus * move consumeMousePosition... methods to GuiUtil * rename EditorTooltip -> EntryTooltip use GridBagConstraintsBuilder in EntryTooltip respect scale config in EntryTooltip * use GridBagConstraintsBuilder in initEditorPane * make tooltip focusable; enables copying tooltip content * fix hiding tooltip immediately after re-populating it simplify tooltip focus and hiding logic * remove tooltip to editor click forward as it didn't work consistently remove unecessary insteractable tooltip click listener * add EntryTooltip.repopulated field for workaround * deobfuscate parent package * focus class selector when navigating to parent package from tooltip * scroll to class selector path when navigating from entry tooltip parent * move Config.persistentEditorQuickFind to EditorConfig.persistentQuickFind * rename config getter methods to match their ids and update Config javadoc * fix another tooltip focus issue * fix bug preventing RecordGetterFindingVisitor from finding inner records' getters make RecordGetterFindingVisitor's getter map accessible fix DeclarationSnippetPanel for record component getters * rename RecordGetterFindingVisitor -> RecordIndexingVisitor expand RecordGetterFindingVisitor to provide maps of record classes to their fields and methods make EntryTooltip show record field javadocs for record classes make EntryTooltip show record field javadocs for record getters if they don't have their own javadocs * clear things in visitEnd instead of visit clear fields and methods * fix for java 17 * tighten RecordIndexingVisitor encapsulation * make navigating to a record component getter with no explicit declaration navigate to its field instead * add nullable annotation * only set BaseEditorPanel.editor text once * fix typo * tweak moveMaintainingAnchor * close entry tooltip on key press * close tooltip on KEY_TYPED instead of KEY_PRESSED so ctrl+c can copy * add javaparser to lib list in README * cleanup createSnippet * fix swapped un/bounded names * make LineIndexer::getIndex return -1 for out-of-bounds positions, add LineIndexerTest * rename EditorTooltipSection -> EntryTooltipSection * limit EntryTooltip size * put main tooltip content in a scroll pane * focus snippet editor ui on source set remove main content scroll pane border * checkstyle * replace AtomicInteger gridY's with primitive ints * hard cap tooltip width at 600px (scaled) * expand parent package path when navigating from tooltip * explicitly check if source is bounded when setting 'Unable to locate declaration' message show <init> for constructor simple names * improve constructor name check * use 'inherited from' label for tooltip labels for entries that resolved to a parent * dispatch key events that close the entry tooltip to the previously focused component * close entry tooltip with global mouse listener * add gui for entry tooltip config * deduplicate check box sync logic * javadoc createSyncedCheckBox * javadoc syncStateWithConfig override * move tooltip management to EnitorPanel.TooltipManager add/remove EntryTooltip's global listeners on open/close reset TooltipManager on key presses * minor refactor * make 'tooltips' consistently plural in user-facing strings * dispatch KEY_PRESSED events that close entry tooltips (with exception for ctrl+c) * rework moveMaintainingAnchor when tooltip shrunk * move FeaturesSection.enableClassTreeStatIcons to StatsSection move FeaturesSection.autoSaveMappings to EditorConfig eliminate FeaturesSection * ensure RecordIndexingVisitor is cleared in visitEnd * make several tooltip string translatable * make a snippet string translatable
1 parent eaaa158 commit b3bd7b1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+3113
-601
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Enigma includes the following open-source libraries:
1515
- [FlatLaf](https://github.com/JFormDesigner/FlatLaf) (Apache-2.0)
1616
- [jopt-simple](https://github.com/jopt-simple/jopt-simple) (MIT)
1717
- [ASM](https://asm.ow2.io/) (BSD-3-Clause)
18+
- [JavaParser](https://javaparser.org/) (Apache-2.0)
1819

1920
## Usage
2021

enigma-swing/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ dependencies {
3232
implementation libs.bundles.quilt.config
3333
implementation libs.swing.dpi
3434
implementation libs.fontchooser
35+
implementation libs.javaparser
3536
testImplementation(testFixtures(project(':enigma')))
3637
}
3738

enigma-swing/src/main/java/org/quiltmc/enigma/gui/Gui.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.quiltmc.enigma.gui.element.EditorTabbedPane;
2929
import org.quiltmc.enigma.gui.element.MainWindow;
3030
import org.quiltmc.enigma.gui.element.menu_bar.MenuBar;
31+
import org.quiltmc.enigma.gui.panel.BaseEditorPanel;
3132
import org.quiltmc.enigma.gui.panel.EditorPanel;
3233
import org.quiltmc.enigma.gui.panel.IdentifierPanel;
3334
import org.quiltmc.enigma.gui.renderer.MessageListCellRenderer;
@@ -170,8 +171,8 @@ private void setupDockers() {
170171
this.dockerManager.registerDocker(new AllClassesDocker(this));
171172
this.dockerManager.registerDocker(new DeobfuscatedClassesDocker(this));
172173

173-
if (Config.dockers().buttonLocations.value().isEmpty()) {
174-
Config.dockers().updateButtonLocations(this.dockerManager);
174+
if (Config.docker().buttonLocations.value().isEmpty()) {
175+
Config.docker().updateButtonLocations(this.dockerManager);
175176
}
176177

177178
// set default docker sizes
@@ -402,7 +403,7 @@ public void setMappingsFile(Path path) {
402403
this.updateUiState();
403404
}
404405

405-
public void showTokens(EditorPanel editor, List<Token> tokens) {
406+
public void showTokens(BaseEditorPanel editor, List<Token> tokens) {
406407
if (tokens.size() > 1) {
407408
this.openDocker(CallsTreeDocker.class);
408409
this.controller.setTokenHandle(editor.getClassHandle().copy());

enigma-swing/src/main/java/org/quiltmc/enigma/gui/GuiController.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ public void openMappings(EntryTree<EntryMapping> mappings) {
197197
}
198198

199199
public void regenerateAndUpdateStatIcons() {
200-
if (Config.main().features.enableClassTreeStatIcons.value()) {
200+
if (Config.stats().enableClassTreeStatIcons.value()) {
201201
ProgressListener progressListener = ProgressListener.createEmpty();
202202
this.gui.getMainWindow().getStatusBar().syncWith(progressListener);
203203

@@ -570,7 +570,7 @@ public void applyChange(ValidationContext vc, EntryChange<?> change, boolean upd
570570
return;
571571
}
572572

573-
if (autosave && Config.main().features.autoSaveMappings.value() && this.gui.mappingsFileChooser.getSelectedFile() != null) {
573+
if (autosave && Config.editor().autoSaveMappings.value() && this.gui.mappingsFileChooser.getSelectedFile() != null) {
574574
this.gui.getController().saveMappings(this.gui.mappingsFileChooser.getSelectedFile().toPath(), true);
575575
}
576576

enigma-swing/src/main/java/org/quiltmc/enigma/gui/NestedPackages.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import java.util.Comparator;
1313
import java.util.HashMap;
1414
import java.util.Map;
15+
import java.util.Optional;
1516

1617
public class NestedPackages {
1718
private final SortedMutableTreeNode root;
@@ -75,9 +76,16 @@ public SortedMutableTreeNode getRoot() {
7576
return this.root;
7677
}
7778

79+
/**
80+
* @return the path to the passed {@code packageName} if present, or the path the {@link #root} otherwise
81+
*/
7882
public TreePath getPackagePath(String packageName) {
79-
var node = this.packageToNode.getOrDefault(packageName, this.root);
80-
return new TreePath(node.getPath());
83+
return this.getPackagePathOrEmpty(packageName).orElseGet(() -> new TreePath(this.root.getPath()));
84+
}
85+
86+
public Optional<TreePath> getPackagePathOrEmpty(String packageName) {
87+
return Optional.ofNullable(this.packageToNode.get(packageName))
88+
.map(node -> new TreePath(node.getPath()));
8189
}
8290

8391
public ClassSelectorClassNode getClassNode(ClassEntry entry) {

enigma-swing/src/main/java/org/quiltmc/enigma/gui/config/Config.java

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,18 @@
3434
import java.nio.file.Paths;
3535

3636
/**
37-
* The Enigma config is separated into five different files: {@link Config the main config (this one)},
38-
* {@link NetConfig the networking configuration}, {@link KeyBindConfig the keybinding configuration},
39-
* {@link DockerConfig the docker configuration}, and {@link DecompilerConfig the decompiler configuration}.
37+
* Enigma config is separated into several {@value #FORMAT} files with names matching the methods used to access them:
38+
* <ul>
39+
* <li> {@link #main()} (this one)
40+
* <li> {@link #net()} (networking)
41+
* <li> {@link #keybind()}
42+
* <li> {@link #docker()}
43+
* <li> {@link #decompiler()}
44+
* <li> {@link #editor()}
45+
* </ul>
46+
*
47+
* {@value #THEME_FAMILY} also holds a config file for each theme;
48+
* the active theme is accessible via {@link #currentTheme()}.
4049
*/
4150
@SerializedNameConvention(NamingSchemes.SNAKE_CASE)
4251
@Processor("processChange")
@@ -52,6 +61,7 @@ public final class Config extends ReflectiveConfig {
5261
private static final NetConfig NET = ConfigFactory.create(ENVIRONMENT, FAMILY, "net", NetConfig.class);
5362
private static final DockerConfig DOCKER = ConfigFactory.create(ENVIRONMENT, FAMILY, "docker", DockerConfig.class);
5463
private static final DecompilerConfig DECOMPILER = ConfigFactory.create(ENVIRONMENT, FAMILY, "decompiler", DecompilerConfig.class);
64+
private static final EditorConfig EDITOR = ConfigFactory.create(ENVIRONMENT, FAMILY, "editor", EditorConfig.class);
5565

5666
@Comment("The currently assigned UI language. This will be an ISO-639 two-letter language code, followed by an underscore and an ISO 3166-1 alpha-2 two-letter country code.")
5767
@Processor("grabPossibleLanguages")
@@ -71,15 +81,9 @@ public final class Config extends ReflectiveConfig {
7181
@Comment("The settings for the statistics window.")
7282
public final StatsSection stats = new StatsSection();
7383

74-
@Comment("Contains all features that can be toggled on or off.")
75-
public final FeaturesSection features = new FeaturesSection();
76-
7784
@Comment("You shouldn't enable options in this section unless you know what you're doing!")
7885
public final DevSection development = new DevSection();
7986

80-
@Comment("Whether editors' quick find toolbars should remain visible when they lose focus.")
81-
public final TrackedValue<Boolean> persistentEditorQuickFind = this.value(true);
82-
8387
/**
8488
* The look and feel stored in the config: do not use this unless setting! Use {@link #activeThemeChoice} instead,
8589
* since look and feel is final once loaded.
@@ -115,11 +119,11 @@ public static StatsSection stats() {
115119
return main().stats;
116120
}
117121

118-
public static DockerConfig dockers() {
122+
public static DockerConfig docker() {
119123
return DOCKER;
120124
}
121125

122-
public static KeyBindConfig keyBinds() {
126+
public static KeyBindConfig keybind() {
123127
return KEYBIND;
124128
}
125129

@@ -131,6 +135,10 @@ public static DecompilerConfig decompiler() {
131135
return DECOMPILER;
132136
}
133137

138+
public static EditorConfig editor() {
139+
return EDITOR;
140+
}
141+
134142
public static Theme currentTheme() {
135143
return activeThemeChoice.theme;
136144
}

enigma-swing/src/main/java/org/quiltmc/enigma/gui/config/FeaturesSection.java renamed to enigma-swing/src/main/java/org/quiltmc/enigma/gui/config/EditorConfig.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,13 @@
77
import org.quiltmc.config.api.values.TrackedValue;
88

99
@SerializedNameConvention(NamingSchemes.SNAKE_CASE)
10-
public class FeaturesSection extends ReflectiveConfig.Section {
11-
@Comment("Enables statistic icons in the class tree. This has a major performance impact on JAR files with lots of classes.")
12-
public final TrackedValue<Boolean> enableClassTreeStatIcons = this.value(true);
10+
public class EditorConfig extends ReflectiveConfig {
1311
@Comment("Enables auto save functionality, which will automatically save mappings when a change is made.")
1412
public final TrackedValue<Boolean> autoSaveMappings = this.value(false);
13+
14+
@Comment("Whether editors' quick find toolbars should remain visible when they lose focus.")
15+
public final TrackedValue<Boolean> persistentQuickFind = this.value(true);
16+
17+
@Comment("Settings for editors' entry tooltips.")
18+
public final EntryTooltipsSection entryTooltips = new EntryTooltipsSection();
1519
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package org.quiltmc.enigma.gui.config;
2+
3+
import org.quiltmc.config.api.ReflectiveConfig;
4+
import org.quiltmc.config.api.annotations.Comment;
5+
import org.quiltmc.config.api.annotations.SerializedNameConvention;
6+
import org.quiltmc.config.api.metadata.NamingSchemes;
7+
import org.quiltmc.config.api.values.TrackedValue;
8+
9+
@SerializedNameConvention(NamingSchemes.SNAKE_CASE)
10+
public class EntryTooltipsSection extends ReflectiveConfig.Section {
11+
@Comment("Whether tooltips are enabled.")
12+
public final TrackedValue<Boolean> enable = this.value(true);
13+
14+
@Comment("Whether tooltips can be clicked and interacted with to navigate their content.")
15+
public final TrackedValue<Boolean> interactable = this.value(true);
16+
}

enigma-swing/src/main/java/org/quiltmc/enigma/gui/config/StatsSection.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ public class StatsSection extends ReflectiveConfig.Section {
2222
public final TrackedValue<Boolean> shouldIncludeSyntheticParameters = this.value(false);
2323
public final TrackedValue<Boolean> shouldCountFallbackNames = this.value(false);
2424

25+
@Comment("Enables statistic icons in the class tree. This has a major performance impact on JAR files with lots of classes.")
26+
public final TrackedValue<Boolean> enableClassTreeStatIcons = this.value(true);
27+
2528
public Set<StatType> getIncludedTypesForIcons(Set<StatType> editableTypes) {
2629
var types = new HashSet<>(editableTypes);
2730
types.removeIf(type -> !this.includedStatTypes.value().contains(type));

enigma-swing/src/main/java/org/quiltmc/enigma/gui/config/keybind/KeyBinds.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ public static Map<String, List<KeyBind>> getEditableKeyBindsByCategory() {
9595

9696
public static void loadConfig() {
9797
for (KeyBind keyBind : CONFIGURABLE_KEY_BINDS) {
98-
keyBind.deserializeCombinations(Config.keyBinds().getKeyCodes(keyBind));
98+
keyBind.deserializeCombinations(Config.keybind().getKeyCodes(keyBind));
9999
}
100100

101101
resetEditableKeyBinds();
@@ -107,7 +107,7 @@ public static void saveConfig() {
107107
KeyBind editedKeyBind = editableKeyBinds.get(i);
108108
if (!editedKeyBind.equals(keyBind)) {
109109
keyBind.setFrom(editedKeyBind);
110-
Config.keyBinds().setBind(editedKeyBind);
110+
Config.keybind().setBind(editedKeyBind);
111111
}
112112
}
113113
}

0 commit comments

Comments
 (0)