Skip to content

Commit a852d57

Browse files
Tab improvements (#296)
* fix #295 * focus editor on tab press and close * add full class name tooltip to table titles * checkstyle * minor tweaks * fix disabling background tab close button when cursor is over tab title
1 parent d375d15 commit a852d57

File tree

3 files changed

+72
-35
lines changed

3 files changed

+72
-35
lines changed

enigma-swing/src/main/java/org/quiltmc/enigma/gui/element/EditorTabbedPane.java

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -38,19 +38,22 @@ public EditorTabbedPane(Gui gui) {
3838

3939
public EditorPanel openClass(ClassEntry entry) {
4040
EditorPanel activeEditor = this.getActiveEditor();
41-
EditorPanel editorPanel = this.editors.computeIfAbsent(entry, e -> {
42-
ClassHandle ch = this.gui.getController().getClassHandleProvider().openClass(entry);
43-
if (ch == null) return null;
41+
EditorPanel entryEditor = this.editors.computeIfAbsent(entry, editing -> {
42+
ClassHandle classHandle = this.gui.getController().getClassHandleProvider().openClass(editing);
43+
if (classHandle == null) {
44+
return null;
45+
}
46+
4447
this.navigator = new NavigatorPanel(this.gui);
45-
EditorPanel ed = new EditorPanel(this.gui, this.navigator);
46-
ed.setClassHandle(ch);
47-
this.openFiles.addTab(ed.getFileName(), ed.getUi());
48+
EditorPanel newEditor = new EditorPanel(this.gui, this.navigator);
49+
newEditor.setClassHandle(classHandle);
50+
this.openFiles.addTab(newEditor.getSimpleClassName(), newEditor.getUi());
4851

49-
ClosableTabTitlePane titlePane = new ClosableTabTitlePane(ed.getFileName(), () -> this.closeEditor(ed));
50-
this.openFiles.setTabComponentAt(this.openFiles.indexOfComponent(ed.getUi()), titlePane.getUi());
52+
ClosableTabTitlePane titlePane = new ClosableTabTitlePane(newEditor.getSimpleClassName(), newEditor.getFullClassName(), () -> this.closeEditor(newEditor));
53+
this.openFiles.setTabComponentAt(this.openFiles.indexOfComponent(newEditor.getUi()), titlePane.getUi());
5154
titlePane.setTabbedPane(this.openFiles);
5255

53-
ed.addListener(new EditorActionListener() {
56+
newEditor.addListener(new EditorActionListener() {
5457
@Override
5558
public void onCursorReferenceChanged(EditorPanel editor, EntryReference<Entry<?>, Entry<?>> ref) {
5659
if (editor == EditorTabbedPane.this.getActiveEditor()) {
@@ -66,38 +69,39 @@ public void onClassHandleChanged(EditorPanel editor, ClassEntry old, ClassHandle
6669

6770
@Override
6871
public void onTitleChanged(EditorPanel editor, String title) {
69-
titlePane.setText(editor.getFileName());
72+
titlePane.setText(editor.getSimpleClassName(), editor.getFullClassName());
7073
}
7174
});
7275

73-
ed.getEditor().addKeyListener(GuiUtil.onKeyPress(keyEvent -> {
76+
newEditor.getEditor().addKeyListener(GuiUtil.onKeyPress(keyEvent -> {
7477
if (KeyBinds.EDITOR_CLOSE_TAB.matches(keyEvent)) {
75-
this.closeEditor(ed);
78+
this.closeEditor(newEditor);
7679
} else if (KeyBinds.ENTRY_NAVIGATOR_NEXT.matches(keyEvent)) {
77-
ed.getNavigatorPanel().navigateDown();
80+
newEditor.getNavigatorPanel().navigateDown();
7881
keyEvent.consume();
7982
} else if (KeyBinds.ENTRY_NAVIGATOR_LAST.matches(keyEvent)) {
80-
ed.getNavigatorPanel().navigateUp();
83+
newEditor.getNavigatorPanel().navigateUp();
8184
keyEvent.consume();
8285
}
8386
}));
8487

85-
return ed;
88+
return newEditor;
8689
});
8790

88-
if (editorPanel != null && activeEditor != editorPanel) {
91+
if (entryEditor != null && activeEditor != entryEditor) {
8992
this.openFiles.setSelectedComponent(this.editors.get(entry).getUi());
90-
this.gui.updateStructure(editorPanel);
91-
this.gui.showCursorReference(editorPanel.getCursorReference());
93+
this.gui.updateStructure(entryEditor);
94+
this.gui.showCursorReference(entryEditor.getCursorReference());
9295
}
9396

94-
return editorPanel;
97+
return entryEditor;
9598
}
9699

97100
public void closeEditor(EditorPanel ed) {
98101
this.openFiles.remove(ed.getUi());
99102
this.editors.inverse().remove(ed);
100103
EditorPanel activeEditor = this.getActiveEditor();
104+
activeEditor.getEditor().requestFocus();
101105
this.gui.updateStructure(activeEditor);
102106
this.gui.showCursorReference(activeEditor != null ? activeEditor.getCursorReference() : null);
103107
ed.destroy();
@@ -151,6 +155,7 @@ private void onTabPressed(MouseEvent e) {
151155
}
152156

153157
EditorPanel activeEditor = this.getActiveEditor();
158+
activeEditor.getEditor().requestFocus();
154159
this.gui.updateStructure(activeEditor);
155160
this.gui.showCursorReference(activeEditor != null ? activeEditor.getCursorReference() : null);
156161
}

enigma-swing/src/main/java/org/quiltmc/enigma/gui/panel/ClosableTabTitlePane.java

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import javax.swing.UIManager;
1212
import javax.swing.border.EmptyBorder;
1313
import javax.swing.event.ChangeListener;
14+
import java.awt.Component;
1415
import java.awt.Dimension;
1516
import java.awt.FlowLayout;
1617
import java.awt.Point;
@@ -20,16 +21,18 @@
2021
public class ClosableTabTitlePane {
2122
private final JPanel ui;
2223
private final JButton closeButton;
23-
private final JLabel label;
24+
private final JLabel title;
2425

2526
private ChangeListener cachedChangeListener;
2627
private JTabbedPane parent;
2728

28-
public ClosableTabTitlePane(String text, Runnable onClose) {
29+
public ClosableTabTitlePane(String title, String tooltip, Runnable onClose) {
2930
this.ui = new JPanel(new FlowLayout(FlowLayout.CENTER, 2, 2));
3031
this.ui.setOpaque(false);
31-
this.label = new JLabel(text);
32-
this.ui.add(this.label);
32+
33+
this.title = new JLabel(title);
34+
this.title.setToolTipText(tooltip);
35+
this.ui.add(this.title);
3336

3437
// Adapted from javax.swing.plaf.metal.MetalTitlePane
3538
this.closeButton = new JButton();
@@ -82,6 +85,22 @@ public void mousePressed(MouseEvent e) {
8285
ClosableTabTitlePane.this.parent.dispatchEvent(e1);
8386
}
8487
}
88+
89+
@Override
90+
public void mouseEntered(MouseEvent e) {
91+
ClosableTabTitlePane.this.closeButton.setEnabled(true);
92+
}
93+
94+
@Override
95+
public void mouseExited(MouseEvent e) {
96+
if (!ClosableTabTitlePane.this.isActive(ClosableTabTitlePane.this.parent)) {
97+
final Component target = SwingUtilities.getDeepestComponentAt(e.getComponent(), e.getX(), e.getY());
98+
if (target == null || !SwingUtilities.isDescendingFrom(target, ClosableTabTitlePane.this.ui)) {
99+
// only disable if mouse is not over this ui or descendants
100+
ClosableTabTitlePane.this.closeButton.setEnabled(false);
101+
}
102+
}
103+
}
85104
});
86105

87106
this.ui.putClientProperty(ClosableTabTitlePane.class, this);
@@ -101,26 +120,31 @@ public void setTabbedPane(JTabbedPane pane) {
101120
this.parent = pane;
102121
}
103122

104-
public void setText(String text) {
105-
this.label.setText(text);
123+
public void setText(String title, String tooltip) {
124+
this.title.setText(title);
125+
this.title.setToolTipText(tooltip);
106126
}
107127

108-
public String getText() {
109-
return this.label.getText();
128+
public String getTitle() {
129+
return this.title.getText();
110130
}
111131

112132
private void updateState(JTabbedPane pane) {
113-
int selectedIndex = pane.getSelectedIndex();
114-
boolean isActive = selectedIndex != -1 && pane.getTabComponentAt(selectedIndex) == this.ui;
115-
this.closeButton.setEnabled(isActive);
116-
this.closeButton.putClientProperty("paintActive", isActive);
133+
final boolean active = this.isActive(pane);
134+
this.closeButton.setEnabled(active);
135+
this.closeButton.putClientProperty("paintActive", active);
117136

118137
this.ui.remove(this.closeButton);
119138
this.ui.add(this.closeButton);
120139

121140
this.ui.repaint();
122141
}
123142

143+
private boolean isActive(JTabbedPane pane) {
144+
int selectedIndex = pane.getSelectedIndex();
145+
return selectedIndex != -1 && pane.getTabComponentAt(selectedIndex) == this.ui;
146+
}
147+
124148
public JPanel getUi() {
125149
return this.ui;
126150
}

enigma-swing/src/main/java/org/quiltmc/enigma/gui/panel/EditorPanel.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ private void setClassHandle0(ClassEntry old, ClassHandle handle) {
256256
handle.addListener(new ClassHandleListener() {
257257
@Override
258258
public void onDeobfRefChanged(ClassHandle h, ClassEntry deobfRef) {
259-
SwingUtilities.invokeLater(() -> EditorPanel.this.listeners.forEach(l -> l.onTitleChanged(EditorPanel.this, EditorPanel.this.getFileName())));
259+
SwingUtilities.invokeLater(() -> EditorPanel.this.listeners.forEach(l -> l.onTitleChanged(EditorPanel.this, EditorPanel.this.getSimpleClassName())));
260260
}
261261

262262
@Override
@@ -653,9 +653,17 @@ public ClassHandle getClassHandle() {
653653
return this.classHandle;
654654
}
655655

656-
public String getFileName() {
657-
ClassEntry classEntry = this.classHandle.getDeobfRef() != null ? this.classHandle.getDeobfRef() : this.classHandle.getRef();
658-
return classEntry.getSimpleName();
656+
public String getSimpleClassName() {
657+
return this.getDeobfOrObfHandleRef().getSimpleName();
658+
}
659+
660+
public String getFullClassName() {
661+
return this.getDeobfOrObfHandleRef().getFullName();
662+
}
663+
664+
private ClassEntry getDeobfOrObfHandleRef() {
665+
final ClassEntry deobfRef = this.classHandle.getDeobfRef();
666+
return deobfRef == null ? this.classHandle.getRef() : deobfRef;
659667
}
660668

661669
public void retranslateUi() {

0 commit comments

Comments
 (0)