Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
6 changes: 6 additions & 0 deletions enigma-swing/src/main/java/cuchaz/enigma/gui/Gui.java
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,12 @@ public EntryReference<Entry<?>, Entry<?>> getCursorReference() {
return activeEditor == null ? null : activeEditor.getCursorReference();
}

@Nullable
public Entry<?> getCursorDeclaration() {
EditorPanel activeEditor = this.editorTabbedPane.getActiveEditor();
return activeEditor == null ? null : activeEditor.getCursorDeclaration();
}

public void startDocChange(EditorPanel editor) {
EntryReference<Entry<?>, Entry<?>> cursorReference = editor.getCursorReference();

Expand Down
27 changes: 27 additions & 0 deletions enigma-swing/src/main/java/cuchaz/enigma/gui/GuiController.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
Expand All @@ -52,12 +53,15 @@
import cuchaz.enigma.api.service.ProjectService;
import cuchaz.enigma.api.view.GuiView;
import cuchaz.enigma.api.view.entry.EntryReferenceView;
import cuchaz.enigma.api.view.entry.EntryView;
import cuchaz.enigma.classhandle.ClassHandle;
import cuchaz.enigma.classhandle.ClassHandleProvider;
import cuchaz.enigma.gui.config.LookAndFeel;
import cuchaz.enigma.gui.config.NetConfig;
import cuchaz.enigma.gui.config.UiConfig;
import cuchaz.enigma.gui.dialog.ProgressDialog;
import cuchaz.enigma.gui.newabstraction.EntryValidation;
import cuchaz.enigma.gui.panels.EditorPanel;
import cuchaz.enigma.gui.stats.StatsGenerator;
import cuchaz.enigma.gui.stats.StatsMember;
import cuchaz.enigma.gui.util.History;
Expand Down Expand Up @@ -130,6 +134,23 @@ public JFrame getFrame() {
return gui.getFrame();
}

@Override
public float getScale() {
return UiConfig.getActiveScaleFactor();
}

@Override
public boolean isDarkTheme() {
return LookAndFeel.isDarkLaf();
}

@Override
public JEditorPane createEditorPane() {
JEditorPane editor = new JEditorPane();
EditorPanel.customizeEditor(editor);
return editor;
}

public boolean isDirty() {
return project != null && project.getMapper().isDirty();
}
Expand Down Expand Up @@ -349,6 +370,12 @@ public EntryReferenceView getCursorReference() {
return gui.getCursorReference();
}

@Override
@Nullable
public EntryView getCursorDeclaration() {
return gui.getCursorDeclaration();
}

/**
* Navigates to the declaration with respect to navigation history.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public enum LookAndFeel {
// the "JVM default" look and feel, get it at the beginning and store it so we can set it later
private static final javax.swing.LookAndFeel NONE_LAF = UIManager.getLookAndFeel();
private final boolean needsScaling;
private static Boolean isDarkLaf = null;

LookAndFeel(boolean needsScaling) {
this.needsScaling = needsScaling;
Expand Down Expand Up @@ -52,6 +53,10 @@ public void setGlobalLAF() {
}

public static boolean isDarkLaf() {
if (isDarkLaf != null) {
return isDarkLaf;
}

// a bit of a hack because swing doesn't give any API for that, and we need colors that aren't defined in look and feel
JPanel panel = new JPanel();
panel.setSize(new Dimension(10, 10));
Expand All @@ -64,6 +69,6 @@ public static boolean isDarkLaf() {

// convert the color we got to grayscale
int b = (int) (0.3 * c.getRed() + 0.59 * c.getGreen() + 0.11 * c.getBlue());
return b < 85;
return isDarkLaf = b < 85;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package cuchaz.enigma.gui.elements;

import java.awt.Cursor;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;

import javax.swing.JButton;

import cuchaz.enigma.api.service.GuiService;
import cuchaz.enigma.gui.util.EnigmaIconImpl;
import cuchaz.enigma.gui.util.ScaleUtil;

public class GutterIcon extends JButton implements GuiService.GutterMarkerBuilder {
private Runnable clickAction = () -> { };

public GutterIcon(EnigmaIconImpl icon) {
super(icon.icon());
setContentAreaFilled(false);
setCursor(Cursor.getDefaultCursor());
addActionListener(e -> clickAction.run());

addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
setIcon(icon.icon().derive(ScaleUtil.invert(getWidth()), ScaleUtil.invert(getHeight())));
}
});
}

@Override
public GuiService.GutterMarkerBuilder setClickAction(Runnable action) {
this.clickAction = action;
setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
return this;
}

@Override
public GuiService.GutterMarkerBuilder setTooltip(String tooltip) {
setToolTipText(tooltip);
return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

Expand All @@ -35,10 +36,12 @@

import de.sciss.syntaxpane.DefaultSyntaxKit;
import de.sciss.syntaxpane.SyntaxDocument;
import de.sciss.syntaxpane.actions.ActionUtils;
import org.jetbrains.annotations.Nullable;

import cuchaz.enigma.EnigmaProject;
import cuchaz.enigma.analysis.EntryReference;
import cuchaz.enigma.api.service.GuiService;
import cuchaz.enigma.classhandle.ClassHandle;
import cuchaz.enigma.classhandle.ClassHandleError;
import cuchaz.enigma.events.ClassHandleListener;
Expand All @@ -50,27 +53,32 @@
import cuchaz.enigma.gui.config.Themes;
import cuchaz.enigma.gui.config.UiConfig;
import cuchaz.enigma.gui.elements.EditorPopupMenu;
import cuchaz.enigma.gui.elements.GutterIcon;
import cuchaz.enigma.gui.events.EditorActionListener;
import cuchaz.enigma.gui.events.ThemeChangeListener;
import cuchaz.enigma.gui.highlight.BoxHighlightPainter;
import cuchaz.enigma.gui.highlight.SelectionHighlightPainter;
import cuchaz.enigma.gui.util.EnigmaIconImpl;
import cuchaz.enigma.gui.util.GridBagConstraintsBuilder;
import cuchaz.enigma.gui.util.ScaleUtil;
import cuchaz.enigma.source.DecompiledClassSource;
import cuchaz.enigma.source.RenamableTokenType;
import cuchaz.enigma.source.SourceIndex;
import cuchaz.enigma.source.Token;
import cuchaz.enigma.translation.mapping.EntryRemapper;
import cuchaz.enigma.translation.mapping.EntryResolver;
import cuchaz.enigma.translation.mapping.ResolutionStrategy;
import cuchaz.enigma.translation.representation.entry.ClassEntry;
import cuchaz.enigma.translation.representation.entry.Entry;
import cuchaz.enigma.utils.I18n;
import cuchaz.enigma.utils.Pair;
import cuchaz.enigma.utils.Result;

public class EditorPanel {
private final JPanel ui = new JPanel();
private final JEditorPane editor = new JEditorPane();
private final JScrollPane editorScrollPane = new JScrollPane(this.editor);
private final GutterPanel gutterPanel;
private final EditorPopupMenu popupMenu;

// progress UI
Expand Down Expand Up @@ -109,20 +117,16 @@ public EditorPanel(Gui gui) {
this.gui = gui;
this.controller = gui.getController();

this.editor.setEditable(false);
this.editor.setSelectionColor(new Color(31, 46, 90));
this.editor.setCaret(new BrowserCaret());
customizeEditor(this.editor);
this.editor.addCaretListener(event -> onCaretMove(event.getDot(), this.mouseIsPressed));
this.editor.setCaretColor(UiConfig.getCaretColor());
this.editor.setContentType("text/enigma-sources");
this.editor.setBackground(UiConfig.getEditorBackgroundColor());
DefaultSyntaxKit kit = (DefaultSyntaxKit) this.editor.getEditorKit();
kit.toggleComponent(this.editor, "de.sciss.syntaxpane.components.TokenMarker");

// set unit increment to height of one line, the amount scrolled per
// mouse wheel rotation is then controlled by OS settings
this.editorScrollPane.getVerticalScrollBar().setUnitIncrement(this.editor.getFontMetrics(this.editor.getFont()).getHeight());

this.gutterPanel = new GutterPanel(this.editor, (JComponent) this.editorScrollPane.getRowHeader().getView());
this.editorScrollPane.setRowHeaderView(this.gutterPanel);

// init editor popup menu
this.popupMenu = new EditorPopupMenu(this, gui);
this.editor.setComponentPopupMenu(this.popupMenu.getUi());
Expand Down Expand Up @@ -255,6 +259,17 @@ public void keyReleased(KeyEvent event) {
this.ui.putClientProperty(EditorPanel.class, this);
}

public static void customizeEditor(JEditorPane editor) {
editor.setEditable(false);
editor.setSelectionColor(new Color(31, 46, 90));
editor.setCaret(new BrowserCaret());
editor.setCaretColor(UiConfig.getCaretColor());
editor.setContentType("text/enigma-sources");
editor.setBackground(UiConfig.getEditorBackgroundColor());
DefaultSyntaxKit kit = (DefaultSyntaxKit) editor.getEditorKit();
kit.toggleComponent(editor, "de.sciss.syntaxpane.components.TokenMarker");
}

@Nullable
public static EditorPanel byUi(Component ui) {
if (ui instanceof JComponent) {
Expand Down Expand Up @@ -512,6 +527,7 @@ public void setSource(DecompiledClassSource source) {
this.editor.setCaretPosition(newCaretPos);
}

addGutterMarkers(source.getIndex());
setHighlightedTokens(source.getHighlightedTokens());
setCursorReference(getReference(getToken(this.editor.getCaretPosition())));
} finally {
Expand All @@ -524,6 +540,44 @@ public void setSource(DecompiledClassSource source) {
}
}

private void addGutterMarkers(SourceIndex sourceIndex) {
List<GuiService> services = this.gui.getController().enigma.getServices().get(GuiService.TYPE);

if (services.isEmpty()) {
return;
}

this.gutterPanel.clearMarkers();

List<Pair<Entry<?>, Token>> declarationTokens = new ArrayList<>();

for (Entry<?> declaration : sourceIndex.declarations()) {
declarationTokens.add(new Pair<>(declaration, sourceIndex.getDeclarationToken(declaration)));
}

declarationTokens.sort(Comparator.comparing(pair -> pair.b));

for (Pair<Entry<?>, Token> declaration : declarationTokens) {
int lineNumber;

try {
lineNumber = ActionUtils.getLineNumber(this.editor, declaration.b.start);
} catch (BadLocationException e) {
continue;
}

for (GuiService service : services) {
service.addGutterMarkers(this.gui.getController(), declaration.a, (icon, alignment) -> {
GutterIcon button = new GutterIcon((EnigmaIconImpl) icon);
this.gutterPanel.addMarker(lineNumber, alignment, button);
return button;
});
}
}

this.editor.revalidate();
}

public void setHighlightedTokens(Map<RenamableTokenType, ? extends Collection<Token>> tokens) {
// remove any old highlighters
this.editor.getHighlighter().removeAllHighlights();
Expand Down Expand Up @@ -565,10 +619,23 @@ private void addHighlightedToken(Token token, HighlightPainter tokenPainter) {
}
}

@Nullable
public EntryReference<Entry<?>, Entry<?>> getCursorReference() {
return this.cursorReference;
}

@Nullable
public Entry<?> getCursorDeclaration() {
int pos = this.editor.getCaretPosition();
Token token = getToken(pos);

if (token == null) {
return null;
}

return this.source.getIndex().getDeclaration(token);
}

public void showReference(EntryReference<Entry<?>, Entry<?>> reference) {
if (this.mode == DisplayMode.SUCCESS) {
showReference0(reference);
Expand Down
Loading