Skip to content

Commit f56eb27

Browse files
committed
feat(gui): allow to set code area theme with custom code (#2471)
1 parent fbebcb9 commit f56eb27

26 files changed

Lines changed: 411 additions & 212 deletions

jadx-gui/src/main/java/jadx/gui/settings/JadxSettings.java

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
import jadx.gui.settings.data.ShortcutsWrapper;
4242
import jadx.gui.ui.MainWindow;
4343
import jadx.gui.ui.action.ActionModel;
44-
import jadx.gui.ui.codearea.EditorTheme;
4544
import jadx.gui.ui.tab.dnd.TabDndGhostType;
4645
import jadx.gui.utils.FontUtils;
4746
import jadx.gui.utils.LafManager;
@@ -73,7 +72,11 @@ public class JadxSettings extends JadxCLIArgs {
7372
private List<Path> recentProjects = new ArrayList<>();
7473
private String fontStr = "";
7574
private String smaliFontStr = "";
76-
private String editorThemePath = EditorTheme.getDefaultTheme().getPath();
75+
private String editorTheme = "";
76+
77+
// Deprecated. Keep for backward compatibility
78+
private String editorThemePath = "/org/fife/ui/rsyntaxtextarea/themes/default.xml";
79+
7780
private String lafTheme = LafManager.INITIAL_THEME_NAME;
7881
private LangLocale langLocale = NLS.defaultLocale();
7982
private boolean autoStartJobs = false;
@@ -102,7 +105,6 @@ public void setSaveOption(SAVEOPTION saveOption) {
102105
private boolean showHeapUsageBar = false;
103106
private boolean alwaysSelectOpened = false;
104107
private boolean useAlternativeFileDialog = false;
105-
private boolean useDynamicEditorTheme = false;
106108

107109
private Map<String, WindowLocation> windowPos = new HashMap<>();
108110
private int mainWindowExtendedState = JFrame.NORMAL;
@@ -325,14 +327,6 @@ public void setUseAlternativeFileDialog(boolean useAlternativeFileDialog) {
325327
this.useAlternativeFileDialog = useAlternativeFileDialog;
326328
}
327329

328-
public boolean isUseDynamicEditorTheme() {
329-
return useDynamicEditorTheme;
330-
}
331-
332-
public void setUseDynamicEditorTheme(boolean useDynamicEditorTheme) {
333-
this.useDynamicEditorTheme = useDynamicEditorTheme;
334-
}
335-
336330
public String getExcludedPackages() {
337331
return excludedPackages;
338332
}
@@ -587,12 +581,12 @@ public void setLogLevel(LogHelper.LogLevelEnum level) {
587581
this.logLevel = level;
588582
}
589583

590-
public String getEditorThemePath() {
591-
return editorThemePath;
584+
public String getEditorTheme() {
585+
return editorTheme;
592586
}
593587

594-
public void setEditorThemePath(String editorThemePath) {
595-
this.editorThemePath = editorThemePath;
588+
public void setEditorTheme(String editorTheme) {
589+
this.editorTheme = editorTheme;
596590
}
597591

598592
public String getLafTheme() {

jadx-gui/src/main/java/jadx/gui/settings/ui/JadxSettingsWindow.java

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@
6767
import jadx.gui.settings.ui.plugins.PluginSettings;
6868
import jadx.gui.settings.ui.shortcut.ShortcutsSettingsGroup;
6969
import jadx.gui.ui.MainWindow;
70-
import jadx.gui.ui.codearea.EditorTheme;
70+
import jadx.gui.ui.codearea.theme.EditorThemeManager;
71+
import jadx.gui.ui.codearea.theme.ThemeIdAndName;
7172
import jadx.gui.ui.tab.dnd.TabDndGhostType;
7273
import jadx.gui.utils.FontUtils;
7374
import jadx.gui.utils.LafManager;
@@ -351,28 +352,15 @@ private SettingsGroup makeAppearanceGroup() {
351352
JButton fontBtn = new JButton(NLS.str("preferences.select_font"));
352353
JButton smaliFontBtn = new JButton(NLS.str("preferences.select_smali_font"));
353354

354-
EditorTheme[] editorThemes = EditorTheme.getAllThemes();
355-
JComboBox<EditorTheme> themesCbx = new JComboBox<>(editorThemes);
356-
themesCbx.setEnabled(!settings.isUseDynamicEditorTheme());
357-
for (EditorTheme theme : editorThemes) {
358-
if (theme.getPath().equals(settings.getEditorThemePath())) {
359-
themesCbx.setSelectedItem(theme);
360-
break;
355+
EditorThemeManager editorThemeManager = mainWindow.getEditorThemeManager();
356+
JComboBox<ThemeIdAndName> themesCbx = new JComboBox<>(editorThemeManager.getThemeIdNameArray());
357+
themesCbx.setSelectedItem(editorThemeManager.getCurrentThemeIdName());
358+
themesCbx.addActionListener(evt -> {
359+
ThemeIdAndName selected = (ThemeIdAndName) themesCbx.getSelectedItem();
360+
if (selected != null) {
361+
settings.setEditorTheme(selected.getId());
362+
mainWindow.loadSettings();
361363
}
362-
}
363-
themesCbx.addActionListener(e -> {
364-
int i = themesCbx.getSelectedIndex();
365-
EditorTheme editorTheme = editorThemes[i];
366-
settings.setEditorThemePath(editorTheme.getPath());
367-
mainWindow.loadSettings();
368-
});
369-
370-
JCheckBox useDynamicEditorTheme = new JCheckBox();
371-
useDynamicEditorTheme.setSelected(settings.isUseDynamicEditorTheme());
372-
useDynamicEditorTheme.addItemListener(e -> {
373-
settings.setUseDynamicEditorTheme(e.getStateChange() == ItemEvent.SELECTED);
374-
mainWindow.loadSettings();
375-
themesCbx.setEnabled(!settings.isUseDynamicEditorTheme());
376364
});
377365

378366
JComboBox<String> lafCbx = new JComboBox<>(LafManager.getThemes());
@@ -385,7 +373,6 @@ private SettingsGroup makeAppearanceGroup() {
385373
SettingsGroup group = new SettingsGroup(NLS.str("preferences.appearance"));
386374
group.addRow(NLS.str("preferences.language"), languageCbx);
387375
group.addRow(NLS.str("preferences.laf_theme"), lafCbx);
388-
group.addRow(NLS.str("preferences.dynamic_editor_theme"), useDynamicEditorTheme);
389376
group.addRow(NLS.str("preferences.theme"), themesCbx);
390377
JLabel fontLabel = group.addRow(getFontLabelStr(), fontBtn);
391378
JLabel smaliFontLabel = group.addRow(getSmaliFontLabelStr(), smaliFontBtn);

jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java

Lines changed: 10 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,8 @@
2121
import java.awt.event.WindowEvent;
2222
import java.awt.geom.AffineTransform;
2323
import java.io.File;
24-
import java.io.InputStream;
25-
import java.net.URL;
2624
import java.nio.file.Files;
2725
import java.nio.file.Path;
28-
import java.nio.file.Paths;
2926
import java.util.ArrayList;
3027
import java.util.Collections;
3128
import java.util.EnumSet;
@@ -67,8 +64,6 @@
6764
import javax.swing.tree.TreePath;
6865
import javax.swing.tree.TreeSelectionModel;
6966

70-
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
71-
import org.fife.ui.rsyntaxtextarea.Theme;
7267
import org.jetbrains.annotations.NotNull;
7368
import org.jetbrains.annotations.Nullable;
7469
import org.slf4j.Logger;
@@ -129,8 +124,8 @@
129124
import jadx.gui.ui.action.JadxGuiAction;
130125
import jadx.gui.ui.codearea.AbstractCodeArea;
131126
import jadx.gui.ui.codearea.AbstractCodeContentPanel;
132-
import jadx.gui.ui.codearea.EditorTheme;
133127
import jadx.gui.ui.codearea.EditorViewState;
128+
import jadx.gui.ui.codearea.theme.EditorThemeManager;
134129
import jadx.gui.ui.dialog.ADBDialog;
135130
import jadx.gui.ui.dialog.AboutDialog;
136131
import jadx.gui.ui.dialog.ExceptionDialog;
@@ -192,6 +187,7 @@ public class MainWindow extends JFrame {
192187
private final TabsController tabsController;
193188
private final NavigationController navController;
194189
private final EditorSyncManager editorSyncManager;
190+
private final EditorThemeManager editorThemeManager;
195191

196192
private transient @NotNull JadxProject project;
197193

@@ -223,7 +219,6 @@ public class MainWindow extends JFrame {
223219

224220
private transient Link updateLink;
225221
private transient ProgressPanel progressPane;
226-
private transient Theme editorTheme;
227222

228223
private transient IssuesPanel issuesPanel;
229224
private transient @Nullable LogPanel logPanel;
@@ -252,11 +247,12 @@ public MainWindow(JadxSettings settings) {
252247
this.shortcutsController = new ShortcutsController(settings);
253248
this.tabsController = new TabsController(this);
254249
this.navController = new NavigationController(this);
250+
this.editorThemeManager = new EditorThemeManager(settings);
255251

256252
JadxEventQueue.register();
257253
resetCache();
258254
FontUtils.registerBundledFonts();
259-
setEditorTheme(settings.getEditorThemePath());
255+
editorThemeManager.setTheme(settings.getEditorTheme());
260256
initUI();
261257
this.editorSyncManager = new EditorSyncManager(this, tabbedPane);
262258
this.backgroundExecutor = new BackgroundExecutor(settings, progressPane);
@@ -1443,40 +1439,6 @@ public void setLocationAndPosition() {
14431439
setLocationRelativeTo(null);
14441440
}
14451441

1446-
private void setEditorTheme(String editorThemePath) {
1447-
try {
1448-
URL themeUrl = getClass().getResource(editorThemePath);
1449-
if (themeUrl != null) {
1450-
try (InputStream is = themeUrl.openStream()) {
1451-
editorTheme = Theme.load(is);
1452-
return;
1453-
}
1454-
}
1455-
Path themePath = Paths.get(editorThemePath);
1456-
if (Files.isRegularFile(themePath)) {
1457-
try (InputStream is = Files.newInputStream(themePath)) {
1458-
editorTheme = Theme.load(is);
1459-
return;
1460-
}
1461-
}
1462-
} catch (Exception e) {
1463-
LOG.error("Failed to load editor theme: {}", editorThemePath, e);
1464-
}
1465-
LOG.warn("Falling back to default editor theme: {}", editorThemePath);
1466-
editorThemePath = EditorTheme.getDefaultTheme().getPath();
1467-
try (InputStream is = getClass().getResourceAsStream(editorThemePath)) {
1468-
editorTheme = Theme.load(is);
1469-
return;
1470-
} catch (Exception e) {
1471-
LOG.error("Failed to load default editor theme: {}", editorThemePath, e);
1472-
editorTheme = new Theme(new RSyntaxTextArea());
1473-
}
1474-
}
1475-
1476-
public Theme getEditorTheme() {
1477-
return editorTheme;
1478-
}
1479-
14801442
private void openSettings() {
14811443
settingsOpen = true;
14821444

@@ -1501,12 +1463,12 @@ public void loadSettings() {
15011463

15021464
private void updateUiSettings() {
15031465
LafManager.updateLaf(settings);
1466+
editorThemeManager.setTheme(settings.getEditorTheme());
15041467

15051468
Font font = settings.getFont();
15061469
Font largerFont = font.deriveFont(font.getSize() + 2.f);
15071470

15081471
setFont(largerFont);
1509-
setEditorTheme(settings.getEditorThemePath());
15101472
tree.setFont(largerFont);
15111473
tree.setRowHeight(-1);
15121474

@@ -1535,6 +1497,7 @@ private void closeWindow() {
15351497
heapUsageBar.reset();
15361498
closeAll();
15371499

1500+
editorThemeManager.unload();
15381501
dispose();
15391502
System.exit(0);
15401503
}
@@ -1754,6 +1717,10 @@ public CacheManager getCacheManager() {
17541717
return cacheManager;
17551718
}
17561719

1720+
public EditorThemeManager getEditorThemeManager() {
1721+
return editorThemeManager;
1722+
}
1723+
17571724
public JadxGuiEventsImpl events() {
17581725
return events;
17591726
}

jadx-gui/src/main/java/jadx/gui/ui/codearea/AbstractCodeArea.java

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -374,18 +374,12 @@ public static RSyntaxTextArea getDefaultArea(MainWindow mainWindow) {
374374

375375
public static void loadCommonSettings(MainWindow mainWindow, RSyntaxTextArea area) {
376376
JadxSettings settings = mainWindow.getSettings();
377-
if (settings.isUseDynamicEditorTheme()) {
378-
DynamicCoreAreaTheme.applyCustomTheme(area);
379-
} else {
380-
mainWindow.getEditorTheme().apply(area);
381-
}
382-
377+
mainWindow.getEditorThemeManager().apply(area);
383378
area.setFont(settings.getFont());
384379
Gutter gutter = RSyntaxUtilities.getGutter(area);
385380
if (gutter != null) {
386381
gutter.setLineNumberFont(settings.getFont());
387382
}
388-
389383
}
390384

391385
public void loadSettings() {
@@ -520,14 +514,6 @@ public void dispose() {
520514
}
521515
}
522516

523-
@Override
524-
public void updateUI() {
525-
super.updateUI();
526-
if (contentPanel != null && contentPanel.getMainWindow() != null) {
527-
loadSettings();
528-
}
529-
}
530-
531517
@Override
532518
public Dimension getPreferredSize() {
533519
try {

jadx-gui/src/main/java/jadx/gui/ui/codearea/CodeArea.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public final class CodeArea extends AbstractCodeArea {
4545
private static final long serialVersionUID = 6312736869579635796L;
4646

4747
private @Nullable ICodeInfo cachedCodeInfo;
48+
private @Nullable MouseHoverHighlighter mouseHoverHighlighter;
4849
private final ShortcutsController shortcutsController;
4950

5051
CodeArea(ContentPanel contentPanel, JNode node) {
@@ -76,7 +77,16 @@ public void mouseClicked(MouseEvent e) {
7677
});
7778

7879
if (isJavaCode) {
79-
addMouseMotionListener(new MouseHoverHighlighter(this, codeLinkGenerator));
80+
mouseHoverHighlighter = new MouseHoverHighlighter(this, codeLinkGenerator);
81+
addMouseMotionListener(mouseHoverHighlighter);
82+
}
83+
}
84+
85+
@Override
86+
public void loadSettings() {
87+
super.loadSettings();
88+
if (mouseHoverHighlighter != null) {
89+
mouseHoverHighlighter.loadSettings();
8090
}
8191
}
8292

jadx-gui/src/main/java/jadx/gui/ui/codearea/EditorTheme.java

Lines changed: 0 additions & 49 deletions
This file was deleted.

jadx-gui/src/main/java/jadx/gui/ui/codearea/HexArea.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import javax.swing.event.CaretListener;
1010

1111
import org.apache.commons.lang3.StringUtils;
12-
import org.fife.ui.rsyntaxtextarea.Theme;
1312
import org.jetbrains.annotations.NotNull;
1413
import org.slf4j.Logger;
1514
import org.slf4j.LoggerFactory;
@@ -19,6 +18,7 @@
1918
import jadx.core.utils.exceptions.JadxException;
2019
import jadx.gui.treemodel.JNode;
2120
import jadx.gui.treemodel.JResource;
21+
import jadx.gui.ui.MainWindow;
2222
import jadx.gui.ui.panel.ContentPanel;
2323
import jadx.gui.utils.UiUtils;
2424

@@ -85,12 +85,12 @@ public void loadSettings() {
8585
}
8686

8787
private void applyTheme() {
88-
Font font = getContentPanel().getMainWindow().getSettings().getSmaliFont();
88+
MainWindow mainWindow = getContentPanel().getMainWindow();
89+
mainWindow.getEditorThemeManager().apply(this);
90+
Font font = mainWindow.getSettings().getSmaliFont();
8991
setFont(font);
90-
91-
Theme theme = contentPanel.getMainWindow().getEditorTheme();
9292
if (hexPreviewPanel != null) {
93-
hexPreviewPanel.applyTheme(theme, font);
93+
hexPreviewPanel.applyTheme(this, font);
9494
}
9595
}
9696

0 commit comments

Comments
 (0)