summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar 2xsaiko2020-04-24 18:39:57 +0200
committerGravatar GitHub2020-04-24 17:39:57 +0100
commit04b01512c124c76f3b3d99ba07ef30ea6a90b52f (patch)
tree33ffbe9fba1fd762cc7a7997db9764b181f29d7b /src
parentUpdate darcula to fix dark theme (diff)
downloadenigma-fork-04b01512c124c76f3b3d99ba07ef30ea6a90b52f.tar.gz
enigma-fork-04b01512c124c76f3b3d99ba07ef30ea6a90b52f.tar.xz
enigma-fork-04b01512c124c76f3b3d99ba07ef30ea6a90b52f.zip
Add a configurable scale factor (#230)
* Add swing-dpi dependency * Implement scale factor * Improve custom scale dialog, fix crash * Remove use of $ in identifiers * Use custom functional interface for scale listeners * Bump version Co-authored-by: modmuss50 <modmuss50@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/main/java/cuchaz/enigma/config/Config.java5
-rw-r--r--src/main/java/cuchaz/enigma/config/Themes.java66
-rw-r--r--src/main/java/cuchaz/enigma/gui/Gui.java48
-rw-r--r--src/main/java/cuchaz/enigma/gui/dialog/AboutDialog.java3
-rw-r--r--src/main/java/cuchaz/enigma/gui/dialog/CrashDialog.java3
-rw-r--r--src/main/java/cuchaz/enigma/gui/dialog/JavadocDialog.java3
-rw-r--r--src/main/java/cuchaz/enigma/gui/dialog/ProgressDialog.java5
-rw-r--r--src/main/java/cuchaz/enigma/gui/dialog/SearchDialog.java3
-rw-r--r--src/main/java/cuchaz/enigma/gui/elements/MenuBar.java91
-rw-r--r--src/main/java/cuchaz/enigma/gui/panels/PanelEditor.java7
-rw-r--r--src/main/java/cuchaz/enigma/gui/panels/PanelIdentifier.java3
-rw-r--r--src/main/java/cuchaz/enigma/gui/util/ScaleChangeListener.java8
-rw-r--r--src/main/java/cuchaz/enigma/gui/util/ScaleUtil.java104
-rw-r--r--src/main/resources/lang/en_us.json2
14 files changed, 267 insertions, 84 deletions
diff --git a/src/main/java/cuchaz/enigma/config/Config.java b/src/main/java/cuchaz/enigma/config/Config.java
index 15a974c..20605b7 100644
--- a/src/main/java/cuchaz/enigma/config/Config.java
+++ b/src/main/java/cuchaz/enigma/config/Config.java
@@ -7,6 +7,7 @@ import cuchaz.enigma.source.DecompilerService;
7import cuchaz.enigma.source.Decompilers; 7import cuchaz.enigma.source.Decompilers;
8 8
9import cuchaz.enigma.utils.I18n; 9import cuchaz.enigma.utils.I18n;
10import cuchaz.enigma.gui.util.ScaleUtil;
10 11
11import javax.swing.*; 12import javax.swing.*;
12import javax.swing.plaf.metal.MetalLookAndFeel; 13import javax.swing.plaf.metal.MetalLookAndFeel;
@@ -78,7 +79,7 @@ public class Config {
78 public static boolean isDarkLaf() { 79 public static boolean isDarkLaf() {
79 // 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 80 // 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
80 JPanel panel = new JPanel(); 81 JPanel panel = new JPanel();
81 panel.setSize(new Dimension(10, 10)); 82 panel.setSize(ScaleUtil.getDimension(10, 10));
82 panel.doLayout(); 83 panel.doLayout();
83 84
84 BufferedImage image = new BufferedImage(panel.getSize().width, panel.getSize().height, BufferedImage.TYPE_INT_RGB); 85 BufferedImage image = new BufferedImage(panel.getSize().width, panel.getSize().height, BufferedImage.TYPE_INT_RGB);
@@ -187,6 +188,8 @@ public class Config {
187 188
188 public LookAndFeel lookAndFeel = LookAndFeel.DEFAULT; 189 public LookAndFeel lookAndFeel = LookAndFeel.DEFAULT;
189 190
191 public float scaleFactor = 1.0f;
192
190 public Decompiler decompiler = Decompiler.PROCYON; 193 public Decompiler decompiler = Decompiler.PROCYON;
191 194
192 private Config() { 195 private Config() {
diff --git a/src/main/java/cuchaz/enigma/config/Themes.java b/src/main/java/cuchaz/enigma/config/Themes.java
index 753654e..547a420 100644
--- a/src/main/java/cuchaz/enigma/config/Themes.java
+++ b/src/main/java/cuchaz/enigma/config/Themes.java
@@ -1,40 +1,48 @@
1package cuchaz.enigma.config; 1package cuchaz.enigma.config;
2 2
3import java.awt.Font;
4import java.io.IOException;
5import java.lang.reflect.Field;
6
7import javax.swing.SwingUtilities;
8
9import com.github.swingdpi.UiDefaultsScaler;
3import com.google.common.collect.ImmutableMap; 10import com.google.common.collect.ImmutableMap;
4import cuchaz.enigma.gui.Gui;
5import cuchaz.enigma.gui.EnigmaSyntaxKit; 11import cuchaz.enigma.gui.EnigmaSyntaxKit;
12import cuchaz.enigma.gui.Gui;
6import cuchaz.enigma.gui.highlight.BoxHighlightPainter; 13import cuchaz.enigma.gui.highlight.BoxHighlightPainter;
7import cuchaz.enigma.gui.highlight.TokenHighlightType; 14import cuchaz.enigma.gui.highlight.TokenHighlightType;
15import cuchaz.enigma.gui.util.ScaleUtil;
8import de.sciss.syntaxpane.DefaultSyntaxKit; 16import de.sciss.syntaxpane.DefaultSyntaxKit;
9 17
10import javax.swing.*;
11import java.io.IOException;
12
13public class Themes { 18public class Themes {
14 19
15 public static void setLookAndFeel(Gui gui, Config.LookAndFeel lookAndFeel) { 20 public static void setLookAndFeel(Gui gui, Config.LookAndFeel lookAndFeel) {
16 Config.getInstance().lookAndFeel = lookAndFeel; 21 Config.getInstance().lookAndFeel = lookAndFeel;
17 updateTheme(gui); 22 updateTheme(gui);
18 } 23 }
19 24
20 public static void updateTheme(Gui gui) { 25 public static void updateTheme(Gui gui) {
21 Config config = Config.getInstance(); 26 Config config = Config.getInstance();
22 config.lookAndFeel.setGlobalLAF(); 27 config.lookAndFeel.setGlobalLAF();
23 config.lookAndFeel.apply(config); 28 config.lookAndFeel.apply(config);
24 try { 29 try {
25 config.saveConfig(); 30 config.saveConfig();
26 } catch (IOException e) { 31 } catch (IOException e) {
27 e.printStackTrace(); 32 e.printStackTrace();
28 } 33 }
29 EnigmaSyntaxKit.invalidate(); 34 EnigmaSyntaxKit.invalidate();
30 DefaultSyntaxKit.initKit(); 35 DefaultSyntaxKit.initKit();
31 DefaultSyntaxKit.registerContentType("text/enigma-sources", EnigmaSyntaxKit.class.getName()); 36 DefaultSyntaxKit.registerContentType("text/enigma-sources", EnigmaSyntaxKit.class.getName());
32 gui.boxHighlightPainters = ImmutableMap.of( 37 gui.boxHighlightPainters = ImmutableMap.of(
33 TokenHighlightType.OBFUSCATED, BoxHighlightPainter.create(config.obfuscatedColor, config.obfuscatedColorOutline), 38 TokenHighlightType.OBFUSCATED, BoxHighlightPainter.create(config.obfuscatedColor, config.obfuscatedColorOutline),
34 TokenHighlightType.PROPOSED, BoxHighlightPainter.create(config.proposedColor, config.proposedColorOutline), 39 TokenHighlightType.PROPOSED, BoxHighlightPainter.create(config.proposedColor, config.proposedColorOutline),
35 TokenHighlightType.DEOBFUSCATED, BoxHighlightPainter.create(config.deobfuscatedColor, config.deobfuscatedColorOutline) 40 TokenHighlightType.DEOBFUSCATED, BoxHighlightPainter.create(config.deobfuscatedColor, config.deobfuscatedColorOutline)
36 ); 41 );
37 gui.setEditorTheme(config.lookAndFeel); 42 gui.setEditorTheme(config.lookAndFeel);
38 SwingUtilities.updateComponentTreeUI(gui.getFrame()); 43 SwingUtilities.updateComponentTreeUI(gui.getFrame());
39 } 44 ScaleUtil.applyScaling();
45 }
46
47
40} 48}
diff --git a/src/main/java/cuchaz/enigma/gui/Gui.java b/src/main/java/cuchaz/enigma/gui/Gui.java
index ee8fbdf..8f0d6fa 100644
--- a/src/main/java/cuchaz/enigma/gui/Gui.java
+++ b/src/main/java/cuchaz/enigma/gui/Gui.java
@@ -11,6 +11,18 @@
11 11
12package cuchaz.enigma.gui; 12package cuchaz.enigma.gui;
13 13
14import java.awt.*;
15import java.awt.event.*;
16import java.nio.file.Path;
17import java.util.List;
18import java.util.*;
19import java.util.function.Function;
20
21import javax.swing.*;
22import javax.swing.text.BadLocationException;
23import javax.swing.text.Highlighter;
24import javax.swing.tree.*;
25
14import com.google.common.base.Strings; 26import com.google.common.base.Strings;
15import com.google.common.collect.Lists; 27import com.google.common.collect.Lists;
16import cuchaz.enigma.Constants; 28import cuchaz.enigma.Constants;
@@ -37,20 +49,10 @@ import cuchaz.enigma.throwables.IllegalNameException;
37import cuchaz.enigma.translation.mapping.*; 49import cuchaz.enigma.translation.mapping.*;
38import cuchaz.enigma.translation.representation.entry.*; 50import cuchaz.enigma.translation.representation.entry.*;
39import cuchaz.enigma.utils.I18n; 51import cuchaz.enigma.utils.I18n;
52import cuchaz.enigma.gui.util.ScaleUtil;
40import cuchaz.enigma.utils.Utils; 53import cuchaz.enigma.utils.Utils;
41import de.sciss.syntaxpane.DefaultSyntaxKit; 54import de.sciss.syntaxpane.DefaultSyntaxKit;
42 55
43import javax.swing.*;
44import javax.swing.text.BadLocationException;
45import javax.swing.text.Highlighter;
46import javax.swing.tree.*;
47import java.awt.*;
48import java.awt.event.*;
49import java.nio.file.Path;
50import java.util.List;
51import java.util.*;
52import java.util.function.Function;
53
54public class Gui { 56public class Gui {
55 57
56 public final PopupMenuBar popupMenu; 58 public final PopupMenuBar popupMenu;
@@ -119,6 +121,8 @@ public class Gui {
119 121
120 this.controller = new GuiController(this, profile); 122 this.controller = new GuiController(this, profile);
121 123
124 Themes.updateTheme(this);
125
122 // init file choosers 126 // init file choosers
123 this.jarFileChooser = new FileDialog(getFrame(), I18n.translate("menu.file.jar.open"), FileDialog.LOAD); 127 this.jarFileChooser = new FileDialog(getFrame(), I18n.translate("menu.file.jar.open"), FileDialog.LOAD);
124 128
@@ -135,14 +139,13 @@ public class Gui {
135 splitClasses.setResizeWeight(0.3); 139 splitClasses.setResizeWeight(0.3);
136 this.classesPanel = new JPanel(); 140 this.classesPanel = new JPanel();
137 this.classesPanel.setLayout(new BorderLayout()); 141 this.classesPanel.setLayout(new BorderLayout());
138 this.classesPanel.setPreferredSize(new Dimension(250, 0)); 142 this.classesPanel.setPreferredSize(ScaleUtil.getDimension(250, 0));
139 143
140 // init info panel 144 // init info panel
141 infoPanel = new PanelIdentifier(this); 145 infoPanel = new PanelIdentifier(this);
142 infoPanel.clearReference(); 146 infoPanel.clearReference();
143 147
144 // init editor 148 // init editor
145 Themes.updateTheme(this);
146 selectionHighlightPainter = new SelectionHighlightPainter(); 149 selectionHighlightPainter = new SelectionHighlightPainter();
147 this.editor = new PanelEditor(this); 150 this.editor = new PanelEditor(this);
148 JScrollPane sourceScroller = new JScrollPane(this.editor); 151 JScrollPane sourceScroller = new JScrollPane(this.editor);
@@ -257,8 +260,8 @@ public class Gui {
257 } 260 }
258 } 261 }
259 }); 262 });
260 tokens.setPreferredSize(new Dimension(0, 200)); 263 tokens.setPreferredSize(ScaleUtil.getDimension(0, 200));
261 tokens.setMinimumSize(new Dimension(0, 200)); 264 tokens.setMinimumSize(ScaleUtil.getDimension(0, 200));
262 JSplitPane callPanel = new JSplitPane( 265 JSplitPane callPanel = new JSplitPane(
263 JSplitPane.VERTICAL_SPLIT, 266 JSplitPane.VERTICAL_SPLIT,
264 true, 267 true,
@@ -274,7 +277,7 @@ public class Gui {
274 centerPanel.add(infoPanel, BorderLayout.NORTH); 277 centerPanel.add(infoPanel, BorderLayout.NORTH);
275 centerPanel.add(sourceScroller, BorderLayout.CENTER); 278 centerPanel.add(sourceScroller, BorderLayout.CENTER);
276 tabs = new JTabbedPane(); 279 tabs = new JTabbedPane();
277 tabs.setPreferredSize(new Dimension(250, 0)); 280 tabs.setPreferredSize(ScaleUtil.getDimension(250, 0));
278 tabs.addTab(I18n.translate("info_panel.tree.inheritance"), inheritancePanel); 281 tabs.addTab(I18n.translate("info_panel.tree.inheritance"), inheritancePanel);
279 tabs.addTab(I18n.translate("info_panel.tree.implementations"), implementationsPanel); 282 tabs.addTab(I18n.translate("info_panel.tree.implementations"), implementationsPanel);
280 tabs.addTab(I18n.translate("info_panel.tree.calls"), callPanel); 283 tabs.addTab(I18n.translate("info_panel.tree.calls"), callPanel);
@@ -301,10 +304,11 @@ public class Gui {
301 304
302 // show the frame 305 // show the frame
303 pane.doLayout(); 306 pane.doLayout();
304 this.frame.setSize(1024, 576); 307 this.frame.setSize(ScaleUtil.getDimension(1024, 576));
305 this.frame.setMinimumSize(new Dimension(640, 480)); 308 this.frame.setMinimumSize(ScaleUtil.getDimension(640, 480));
306 this.frame.setVisible(true); 309 this.frame.setVisible(true);
307 this.frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); 310 this.frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
311 this.frame.setLocationRelativeTo(null);
308 } 312 }
309 313
310 public JFrame getFrame() { 314 public JFrame getFrame() {
@@ -492,7 +496,7 @@ public class Gui {
492 panel.setLayout(new FlowLayout(FlowLayout.LEFT, 6, 0)); 496 panel.setLayout(new FlowLayout(FlowLayout.LEFT, 6, 0));
493 497
494 JLabel label = new JLabel(name + ":", JLabel.RIGHT); 498 JLabel label = new JLabel(name + ":", JLabel.RIGHT);
495 label.setPreferredSize(new Dimension(100, label.getPreferredSize().height)); 499 label.setPreferredSize(ScaleUtil.getDimension(100, ScaleUtil.invert(label.getPreferredSize().height)));
496 panel.add(label); 500 panel.add(label);
497 501
498 panel.add(Utils.unboldLabel(new JLabel(value, JLabel.LEFT))); 502 panel.add(Utils.unboldLabel(new JLabel(value, JLabel.LEFT)));
@@ -506,11 +510,11 @@ public class Gui {
506 JPanel panel = new JPanel(); 510 JPanel panel = new JPanel();
507 panel.setLayout(new FlowLayout(FlowLayout.LEFT, 6, 0)); 511 panel.setLayout(new FlowLayout(FlowLayout.LEFT, 6, 0));
508 JLabel label = new JLabel(name + ":", JLabel.RIGHT); 512 JLabel label = new JLabel(name + ":", JLabel.RIGHT);
509 label.setPreferredSize(new Dimension(100, label.getPreferredSize().height)); 513 label.setPreferredSize(ScaleUtil.getDimension(100, ScaleUtil.invert(label.getPreferredSize().height)));
510 panel.add(label); 514 panel.add(label);
511 JComboBox<AccessModifier> combo = new JComboBox<>(AccessModifier.values()); 515 JComboBox<AccessModifier> combo = new JComboBox<>(AccessModifier.values());
512 ((JLabel) combo.getRenderer()).setHorizontalAlignment(JLabel.LEFT); 516 ((JLabel) combo.getRenderer()).setHorizontalAlignment(JLabel.LEFT);
513 combo.setPreferredSize(new Dimension(100, label.getPreferredSize().height)); 517 combo.setPreferredSize(ScaleUtil.getDimension(100, ScaleUtil.invert(label.getPreferredSize().height)));
514 518
515 EntryMapping mapping = controller.project.getMapper().getDeobfMapping(entry); 519 EntryMapping mapping = controller.project.getMapper().getDeobfMapping(entry);
516 if (mapping != null) { 520 if (mapping != null) {
@@ -628,7 +632,7 @@ public class Gui {
628 EntryReference<Entry<?>, Entry<?>> translatedReference = controller.project.getMapper().deobfuscate(cursorReference); 632 EntryReference<Entry<?>, Entry<?>> translatedReference = controller.project.getMapper().deobfuscate(cursorReference);
629 renameTextField.setText(translatedReference.getNameableName()); 633 renameTextField.setText(translatedReference.getNameableName());
630 634
631 renameTextField.setPreferredSize(new Dimension(360, renameTextField.getPreferredSize().height)); 635 renameTextField.setPreferredSize(ScaleUtil.getDimension(360, ScaleUtil.invert(renameTextField.getPreferredSize().height)));
632 renameTextField.addKeyListener(new KeyAdapter() { 636 renameTextField.addKeyListener(new KeyAdapter() {
633 @Override 637 @Override
634 public void keyPressed(KeyEvent event) { 638 public void keyPressed(KeyEvent event) {
diff --git a/src/main/java/cuchaz/enigma/gui/dialog/AboutDialog.java b/src/main/java/cuchaz/enigma/gui/dialog/AboutDialog.java
index 82fd6a5..43b8265 100644
--- a/src/main/java/cuchaz/enigma/gui/dialog/AboutDialog.java
+++ b/src/main/java/cuchaz/enigma/gui/dialog/AboutDialog.java
@@ -13,6 +13,7 @@ package cuchaz.enigma.gui.dialog;
13 13
14import cuchaz.enigma.Constants; 14import cuchaz.enigma.Constants;
15import cuchaz.enigma.utils.I18n; 15import cuchaz.enigma.utils.I18n;
16import cuchaz.enigma.gui.util.ScaleUtil;
16import cuchaz.enigma.utils.Utils; 17import cuchaz.enigma.utils.Utils;
17 18
18import javax.swing.*; 19import javax.swing.*;
@@ -59,7 +60,7 @@ public class AboutDialog {
59 60
60 // show the frame 61 // show the frame
61 pane.doLayout(); 62 pane.doLayout();
62 frame.setSize(400, 220); 63 frame.setSize(ScaleUtil.getDimension(400, 220));
63 frame.setResizable(false); 64 frame.setResizable(false);
64 frame.setLocationRelativeTo(parent); 65 frame.setLocationRelativeTo(parent);
65 frame.setVisible(true); 66 frame.setVisible(true);
diff --git a/src/main/java/cuchaz/enigma/gui/dialog/CrashDialog.java b/src/main/java/cuchaz/enigma/gui/dialog/CrashDialog.java
index 78b1d75..908b42e 100644
--- a/src/main/java/cuchaz/enigma/gui/dialog/CrashDialog.java
+++ b/src/main/java/cuchaz/enigma/gui/dialog/CrashDialog.java
@@ -13,6 +13,7 @@ package cuchaz.enigma.gui.dialog;
13 13
14import cuchaz.enigma.Constants; 14import cuchaz.enigma.Constants;
15import cuchaz.enigma.utils.I18n; 15import cuchaz.enigma.utils.I18n;
16import cuchaz.enigma.gui.util.ScaleUtil;
16import cuchaz.enigma.utils.Utils; 17import cuchaz.enigma.utils.Utils;
17 18
18import javax.swing.*; 19import javax.swing.*;
@@ -81,7 +82,7 @@ public class CrashDialog {
81 pane.add(buttonsPanel, BorderLayout.SOUTH); 82 pane.add(buttonsPanel, BorderLayout.SOUTH);
82 83
83 // show the frame 84 // show the frame
84 frame.setSize(600, 400); 85 frame.setSize(ScaleUtil.getDimension(600, 400));
85 frame.setLocationRelativeTo(parent); 86 frame.setLocationRelativeTo(parent);
86 frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); 87 frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
87 } 88 }
diff --git a/src/main/java/cuchaz/enigma/gui/dialog/JavadocDialog.java b/src/main/java/cuchaz/enigma/gui/dialog/JavadocDialog.java
index 033318a..b2c159d 100644
--- a/src/main/java/cuchaz/enigma/gui/dialog/JavadocDialog.java
+++ b/src/main/java/cuchaz/enigma/gui/dialog/JavadocDialog.java
@@ -12,6 +12,7 @@
12package cuchaz.enigma.gui.dialog; 12package cuchaz.enigma.gui.dialog;
13 13
14import cuchaz.enigma.utils.I18n; 14import cuchaz.enigma.utils.I18n;
15import cuchaz.enigma.gui.util.ScaleUtil;
15import cuchaz.enigma.utils.Utils; 16import cuchaz.enigma.utils.Utils;
16 17
17import javax.swing.*; 18import javax.swing.*;
@@ -72,7 +73,7 @@ public class JavadocDialog {
72 pane.add(buttonsPanel, BorderLayout.SOUTH); 73 pane.add(buttonsPanel, BorderLayout.SOUTH);
73 74
74 // show the frame 75 // show the frame
75 frame.setSize(600, 400); 76 frame.setSize(ScaleUtil.getDimension(600, 400));
76 frame.setLocationRelativeTo(parent); 77 frame.setLocationRelativeTo(parent);
77 frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); 78 frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
78 } 79 }
diff --git a/src/main/java/cuchaz/enigma/gui/dialog/ProgressDialog.java b/src/main/java/cuchaz/enigma/gui/dialog/ProgressDialog.java
index 6d9a419..e33ae82 100644
--- a/src/main/java/cuchaz/enigma/gui/dialog/ProgressDialog.java
+++ b/src/main/java/cuchaz/enigma/gui/dialog/ProgressDialog.java
@@ -14,6 +14,7 @@ package cuchaz.enigma.gui.dialog;
14import cuchaz.enigma.Constants; 14import cuchaz.enigma.Constants;
15import cuchaz.enigma.ProgressListener; 15import cuchaz.enigma.ProgressListener;
16import cuchaz.enigma.utils.I18n; 16import cuchaz.enigma.utils.I18n;
17import cuchaz.enigma.gui.util.ScaleUtil;
17import cuchaz.enigma.utils.Utils; 18import cuchaz.enigma.utils.Utils;
18 19
19import javax.swing.*; 20import javax.swing.*;
@@ -48,11 +49,11 @@ public class ProgressDialog implements ProgressListener, AutoCloseable {
48 this.labelText.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0)); 49 this.labelText.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0));
49 panel.add(this.labelText, BorderLayout.NORTH); 50 panel.add(this.labelText, BorderLayout.NORTH);
50 panel.add(this.progress, BorderLayout.CENTER); 51 panel.add(this.progress, BorderLayout.CENTER);
51 panel.setPreferredSize(new Dimension(360, 50)); 52 panel.setPreferredSize(ScaleUtil.getDimension(360, 50));
52 53
53 // show the frame 54 // show the frame
54 pane.doLayout(); 55 pane.doLayout();
55 this.frame.setSize(400, 120); 56 this.frame.setSize(ScaleUtil.getDimension(400, 120));
56 this.frame.setResizable(false); 57 this.frame.setResizable(false);
57 this.frame.setLocationRelativeTo(parent); 58 this.frame.setLocationRelativeTo(parent);
58 this.frame.setVisible(true); 59 this.frame.setVisible(true);
diff --git a/src/main/java/cuchaz/enigma/gui/dialog/SearchDialog.java b/src/main/java/cuchaz/enigma/gui/dialog/SearchDialog.java
index 47f9149..56ce751 100644
--- a/src/main/java/cuchaz/enigma/gui/dialog/SearchDialog.java
+++ b/src/main/java/cuchaz/enigma/gui/dialog/SearchDialog.java
@@ -15,6 +15,7 @@ import com.google.common.collect.Lists;
15import cuchaz.enigma.gui.Gui; 15import cuchaz.enigma.gui.Gui;
16import cuchaz.enigma.translation.representation.entry.ClassEntry; 16import cuchaz.enigma.translation.representation.entry.ClassEntry;
17import cuchaz.enigma.utils.I18n; 17import cuchaz.enigma.utils.I18n;
18import cuchaz.enigma.gui.util.ScaleUtil;
18import me.xdrop.fuzzywuzzy.FuzzySearch; 19import me.xdrop.fuzzywuzzy.FuzzySearch;
19import me.xdrop.fuzzywuzzy.model.ExtractedResult; 20import me.xdrop.fuzzywuzzy.model.ExtractedResult;
20 21
@@ -107,7 +108,7 @@ public class SearchDialog {
107 frame.setContentPane(pane); 108 frame.setContentPane(pane);
108 frame.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS)); 109 frame.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS));
109 110
110 frame.setSize(360, 500); 111 frame.setSize(ScaleUtil.getDimension(360, 500));
111 frame.setAlwaysOnTop(true); 112 frame.setAlwaysOnTop(true);
112 frame.setResizable(false); 113 frame.setResizable(false);
113 frame.setLocationRelativeTo(parent.getFrame()); 114 frame.setLocationRelativeTo(parent.getFrame());
diff --git a/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java b/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java
index f3bf69a..fd521ab 100644
--- a/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java
+++ b/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java
@@ -1,16 +1,8 @@
1package cuchaz.enigma.gui.elements; 1package cuchaz.enigma.gui.elements;
2 2
3import cuchaz.enigma.config.Config; 3import java.awt.Container;
4import cuchaz.enigma.config.Themes; 4import java.awt.Desktop;
5import cuchaz.enigma.gui.Gui; 5import java.awt.FlowLayout;
6import cuchaz.enigma.gui.dialog.AboutDialog;
7import cuchaz.enigma.gui.dialog.SearchDialog;
8import cuchaz.enigma.gui.stats.StatsMember;
9import cuchaz.enigma.translation.mapping.serde.MappingFormat;
10import cuchaz.enigma.utils.I18n;
11
12import javax.swing.*;
13import java.awt.*;
14import java.awt.event.InputEvent; 6import java.awt.event.InputEvent;
15import java.awt.event.KeyEvent; 7import java.awt.event.KeyEvent;
16import java.io.File; 8import java.io.File;
@@ -20,9 +12,22 @@ import java.net.URL;
20import java.nio.file.Files; 12import java.nio.file.Files;
21import java.nio.file.Path; 13import java.nio.file.Path;
22import java.nio.file.Paths; 14import java.nio.file.Paths;
23import java.util.List;
24import java.util.*; 15import java.util.*;
25import java.util.stream.Collectors; 16import java.util.stream.Collectors;
17import java.util.stream.IntStream;
18
19import javax.swing.*;
20
21import cuchaz.enigma.config.Config;
22import cuchaz.enigma.config.Themes;
23import cuchaz.enigma.gui.Gui;
24import cuchaz.enigma.gui.dialog.AboutDialog;
25import cuchaz.enigma.gui.dialog.SearchDialog;
26import cuchaz.enigma.gui.stats.StatsMember;
27import cuchaz.enigma.gui.util.ScaleUtil;
28import cuchaz.enigma.translation.mapping.serde.MappingFormat;
29import cuchaz.enigma.utils.I18n;
30import cuchaz.enigma.utils.Pair;
26 31
27public class MenuBar extends JMenuBar { 32public class MenuBar extends JMenuBar {
28 33
@@ -167,7 +172,7 @@ public class MenuBar extends JMenuBar {
167 JMenuItem stats = new JMenuItem(I18n.translate("menu.file.stats")); 172 JMenuItem stats = new JMenuItem(I18n.translate("menu.file.stats"));
168 173
169 stats.addActionListener(event -> { 174 stats.addActionListener(event -> {
170 JFrame frame = new JFrame(I18n.translate("menu.file.stats.title")); 175 JFrame frame = new JFrame(I18n.translate("menu.file.stats.title"));
171 Container pane = frame.getContentPane(); 176 Container pane = frame.getContentPane();
172 pane.setLayout(new FlowLayout()); 177 pane.setLayout(new FlowLayout());
173 178
@@ -195,10 +200,10 @@ public class MenuBar extends JMenuBar {
195 }); 200 });
196 201
197 pane.add(button); 202 pane.add(button);
198 frame.pack(); 203 frame.pack();
199 frame.setLocationRelativeTo(this.gui.getFrame()); 204 frame.setLocationRelativeTo(this.gui.getFrame());
200 frame.setVisible(true); 205 frame.setVisible(true);
201 }); 206 });
202 207
203 menu.add(stats); 208 menu.add(stats);
204 } 209 }
@@ -247,7 +252,7 @@ public class MenuBar extends JMenuBar {
247 themes.add(theme); 252 themes.add(theme);
248 theme.addActionListener(event -> Themes.setLookAndFeel(gui, lookAndFeel)); 253 theme.addActionListener(event -> Themes.setLookAndFeel(gui, lookAndFeel));
249 } 254 }
250 255
251 JMenu languages = new JMenu(I18n.translate("menu.view.languages")); 256 JMenu languages = new JMenu(I18n.translate("menu.view.languages"));
252 menu.add(languages); 257 menu.add(languages);
253 for (String lang : I18n.getAvailableLanguages()) { 258 for (String lang : I18n.getAvailableLanguages()) {
@@ -258,21 +263,63 @@ public class MenuBar extends JMenuBar {
258 JFrame frame = new JFrame(I18n.translate("menu.view.languages.title")); 263 JFrame frame = new JFrame(I18n.translate("menu.view.languages.title"));
259 Container pane = frame.getContentPane(); 264 Container pane = frame.getContentPane();
260 pane.setLayout(new FlowLayout()); 265 pane.setLayout(new FlowLayout());
261 266
262 JLabel text = new JLabel((I18n.translate("menu.view.languages.summary"))); 267 JLabel text = new JLabel((I18n.translate("menu.view.languages.summary")));
263 text.setHorizontalAlignment(JLabel.CENTER); 268 text.setHorizontalAlignment(JLabel.CENTER);
264 pane.add(text); 269 pane.add(text);
265 270
266 JButton okButton = new JButton(I18n.translate("menu.view.languages.ok")); 271 JButton okButton = new JButton(I18n.translate("menu.view.languages.ok"));
267 pane.add(okButton); 272 pane.add(okButton);
268 okButton.addActionListener(arg0 -> frame.dispose()); 273 okButton.addActionListener(arg0 -> frame.dispose());
269 274
270 frame.pack(); 275 frame.pack();
271 frame.setLocationRelativeTo(this.gui.getFrame()); 276 frame.setLocationRelativeTo(this.gui.getFrame());
272 frame.setVisible(true); 277 frame.setVisible(true);
273 }); 278 });
274 } 279 }
275 280
281 JMenu scale = new JMenu(I18n.translate("menu.view.scale"));
282 {
283 ButtonGroup scaleGroup = new ButtonGroup();
284 Map<Float, JRadioButtonMenuItem> map = IntStream.of(100, 125, 150, 175, 200)
285 .mapToObj(scaleFactor -> {
286 float realScaleFactor = scaleFactor / 100f;
287 JRadioButtonMenuItem menuItem = new JRadioButtonMenuItem(String.format("%d%%", scaleFactor));
288 menuItem.addActionListener(event -> ScaleUtil.setScaleFactor(realScaleFactor));
289 scaleGroup.add(menuItem);
290 scale.add(menuItem);
291 return new Pair<>(realScaleFactor, menuItem);
292 })
293 .collect(Collectors.toMap(x -> x.a, x -> x.b));
294
295 JMenuItem customScale = new JMenuItem(I18n.translate("menu.view.scale.custom"));
296 customScale.addActionListener(event -> {
297 String answer = (String) JOptionPane.showInputDialog(gui.getFrame(), "Custom Scale", "Custom Scale",
298 JOptionPane.QUESTION_MESSAGE, null, null, Float.toString(ScaleUtil.getScaleFactor() * 100));
299 if (answer == null) return;
300 float newScale = 1.0f;
301 try {
302 newScale = Float.parseFloat(answer) / 100f;
303 } catch (NumberFormatException ignored) {
304 }
305 ScaleUtil.setScaleFactor(newScale);
306 });
307 scale.add(customScale);
308 ScaleUtil.addListener((newScale, _oldScale) -> {
309 JRadioButtonMenuItem mi = map.get(newScale);
310 if (mi != null) {
311 mi.setSelected(true);
312 } else {
313 scaleGroup.clearSelection();
314 }
315 });
316 JRadioButtonMenuItem mi = map.get(ScaleUtil.getScaleFactor());
317 if (mi != null) {
318 mi.setSelected(true);
319 }
320 }
321 menu.add(scale);
322
276 JMenuItem search = new JMenuItem(I18n.translate("menu.view.search")); 323 JMenuItem search = new JMenuItem(I18n.translate("menu.view.search"));
277 search.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, InputEvent.SHIFT_MASK)); 324 search.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, InputEvent.SHIFT_MASK));
278 menu.add(search); 325 menu.add(search);
@@ -284,7 +331,7 @@ public class MenuBar extends JMenuBar {
284 331
285 } 332 }
286 } 333 }
287 334
288 /* 335 /*
289 * Help menu 336 * Help menu
290 */ 337 */
diff --git a/src/main/java/cuchaz/enigma/gui/panels/PanelEditor.java b/src/main/java/cuchaz/enigma/gui/panels/PanelEditor.java
index 1a34edf..8296842 100644
--- a/src/main/java/cuchaz/enigma/gui/panels/PanelEditor.java
+++ b/src/main/java/cuchaz/enigma/gui/panels/PanelEditor.java
@@ -7,6 +7,7 @@ import cuchaz.enigma.gui.BrowserCaret;
7import cuchaz.enigma.gui.Gui; 7import cuchaz.enigma.gui.Gui;
8import cuchaz.enigma.translation.representation.entry.ClassEntry; 8import cuchaz.enigma.translation.representation.entry.ClassEntry;
9import cuchaz.enigma.translation.representation.entry.Entry; 9import cuchaz.enigma.translation.representation.entry.Entry;
10import cuchaz.enigma.gui.util.ScaleUtil;
10 11
11import javax.swing.*; 12import javax.swing.*;
12import java.awt.*; 13import java.awt.*;
@@ -23,7 +24,7 @@ public class PanelEditor extends JEditorPane {
23 this.setEditable(false); 24 this.setEditable(false);
24 this.setSelectionColor(new Color(31, 46, 90)); 25 this.setSelectionColor(new Color(31, 46, 90));
25 this.setCaret(new BrowserCaret()); 26 this.setCaret(new BrowserCaret());
26 this.setFont(new Font(this.getFont().getFontName(), Font.PLAIN, this.fontSize)); 27 this.setFont(ScaleUtil.getFont(this.getFont().getFontName(), Font.PLAIN, this.fontSize));
27 this.addCaretListener(event -> gui.onCaretMove(event.getDot(), mouseIsPressed)); 28 this.addCaretListener(event -> gui.onCaretMove(event.getDot(), mouseIsPressed));
28 final PanelEditor self = this; 29 final PanelEditor self = this;
29 this.addMouseListener(new MouseAdapter() { 30 this.addMouseListener(new MouseAdapter() {
@@ -154,13 +155,13 @@ public class PanelEditor extends JEditorPane {
154 int newResult = this.fontSize + zoomAmount; 155 int newResult = this.fontSize + zoomAmount;
155 if (newResult > 8 && newResult < 72) { 156 if (newResult > 8 && newResult < 72) {
156 this.fontSize = newResult; 157 this.fontSize = newResult;
157 this.setFont(new Font(this.getFont().getFontName(), Font.PLAIN, this.fontSize)); 158 this.setFont(ScaleUtil.getFont(this.getFont().getFontName(), Font.PLAIN, this.fontSize));
158 } 159 }
159 } 160 }
160 161
161 public void resetEditorZoom() { 162 public void resetEditorZoom() {
162 this.fontSize = 12; 163 this.fontSize = 12;
163 this.setFont(new Font(this.getFont().getFontName(), Font.PLAIN, this.fontSize)); 164 this.setFont(ScaleUtil.getFont(this.getFont().getFontName(), Font.PLAIN, this.fontSize));
164 } 165 }
165 166
166 @Override 167 @Override
diff --git a/src/main/java/cuchaz/enigma/gui/panels/PanelIdentifier.java b/src/main/java/cuchaz/enigma/gui/panels/PanelIdentifier.java
index 0cca40d..de069bc 100644
--- a/src/main/java/cuchaz/enigma/gui/panels/PanelIdentifier.java
+++ b/src/main/java/cuchaz/enigma/gui/panels/PanelIdentifier.java
@@ -2,6 +2,7 @@ package cuchaz.enigma.gui.panels;
2 2
3import cuchaz.enigma.gui.Gui; 3import cuchaz.enigma.gui.Gui;
4import cuchaz.enigma.utils.I18n; 4import cuchaz.enigma.utils.I18n;
5import cuchaz.enigma.gui.util.ScaleUtil;
5import cuchaz.enigma.utils.Utils; 6import cuchaz.enigma.utils.Utils;
6 7
7import javax.swing.*; 8import javax.swing.*;
@@ -15,7 +16,7 @@ public class PanelIdentifier extends JPanel {
15 this.gui = gui; 16 this.gui = gui;
16 17
17 this.setLayout(new GridLayout(4, 1, 0, 0)); 18 this.setLayout(new GridLayout(4, 1, 0, 0));
18 this.setPreferredSize(new Dimension(0, 100)); 19 this.setPreferredSize(ScaleUtil.getDimension(0, 100));
19 this.setBorder(BorderFactory.createTitledBorder(I18n.translate("info_panel.identifier"))); 20 this.setBorder(BorderFactory.createTitledBorder(I18n.translate("info_panel.identifier")));
20 } 21 }
21 22
diff --git a/src/main/java/cuchaz/enigma/gui/util/ScaleChangeListener.java b/src/main/java/cuchaz/enigma/gui/util/ScaleChangeListener.java
new file mode 100644
index 0000000..d045c6d
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/gui/util/ScaleChangeListener.java
@@ -0,0 +1,8 @@
1package cuchaz.enigma.gui.util;
2
3@FunctionalInterface
4public interface ScaleChangeListener {
5
6 void onScaleChanged(float scale, float oldScale);
7
8}
diff --git a/src/main/java/cuchaz/enigma/gui/util/ScaleUtil.java b/src/main/java/cuchaz/enigma/gui/util/ScaleUtil.java
new file mode 100644
index 0000000..8bc826f
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/gui/util/ScaleUtil.java
@@ -0,0 +1,104 @@
1package cuchaz.enigma.gui.util;
2
3import java.awt.Dimension;
4import java.awt.Font;
5import java.io.IOException;
6import java.lang.reflect.Field;
7import java.util.ArrayList;
8import java.util.List;
9
10import javax.swing.UIManager;
11
12import com.github.swingdpi.UiDefaultsScaler;
13import com.github.swingdpi.plaf.BasicTweaker;
14import com.github.swingdpi.plaf.MetalTweaker;
15import com.github.swingdpi.plaf.NimbusTweaker;
16import com.github.swingdpi.plaf.WindowsTweaker;
17import cuchaz.enigma.config.Config;
18import de.sciss.syntaxpane.DefaultSyntaxKit;
19
20public class ScaleUtil {
21
22 private static List<ScaleChangeListener> listeners = new ArrayList<>();
23
24 public static float getScaleFactor() {
25 return Config.getInstance().scaleFactor;
26 }
27
28 public static void setScaleFactor(float scaleFactor) {
29 float oldScale = getScaleFactor();
30 float clamped = Math.min(Math.max(0.25f, scaleFactor), 10.0f);
31 Config.getInstance().scaleFactor = clamped;
32 try {
33 Config.getInstance().saveConfig();
34 } catch (IOException e) {
35 e.printStackTrace();
36 }
37 listeners.forEach(l -> l.onScaleChanged(clamped, oldScale));
38 }
39
40 public static void addListener(ScaleChangeListener listener) {
41 listeners.add(listener);
42 }
43
44 public static void removeListener(ScaleChangeListener listener) {
45 listeners.remove(listener);
46 }
47
48 public static Dimension getDimension(int width, int height) {
49 return new Dimension(scale(width), scale(height));
50 }
51
52 public static Font getFont(String fontName, int plain, int fontSize) {
53 return scaleFont(new Font(fontName, plain, fontSize));
54 }
55
56 public static Font scaleFont(Font font) {
57 return createTweakerForCurrentLook(getScaleFactor()).modifyFont("", font);
58 }
59
60 public static float scale(float f) {
61 return f * getScaleFactor();
62 }
63
64 public static float invert(float f) {
65 return f / getScaleFactor();
66 }
67
68 public static int scale(int i) {
69 return (int) (i * getScaleFactor());
70 }
71
72 public static int invert(int i) {
73 return (int) (i / getScaleFactor());
74 }
75
76 public static void applyScaling() {
77 float scale = getScaleFactor();
78 UiDefaultsScaler.updateAndApplyGlobalScaling((int) (100 * scale), true);
79 try {
80 Field defaultFontField = DefaultSyntaxKit.class.getDeclaredField("DEFAULT_FONT");
81 defaultFontField.setAccessible(true);
82 Font font = (Font) defaultFontField.get(null);
83 font = font.deriveFont(12 * scale);
84 defaultFontField.set(null, font);
85 } catch (NoSuchFieldException | IllegalAccessException e) {
86 e.printStackTrace();
87 }
88 }
89
90 private static BasicTweaker createTweakerForCurrentLook(float dpiScaling) {
91 String testString = UIManager.getLookAndFeel().getName().toLowerCase();
92 if (testString.contains("windows")) {
93 return new WindowsTweaker(dpiScaling, testString.contains("classic"));
94 }
95 if (testString.contains("metal")) {
96 return new MetalTweaker(dpiScaling);
97 }
98 if (testString.contains("nimbus")) {
99 return new NimbusTweaker(dpiScaling);
100 }
101 return new BasicTweaker(dpiScaling);
102 }
103
104}
diff --git a/src/main/resources/lang/en_us.json b/src/main/resources/lang/en_us.json
index e7f7624..6e008f1 100644
--- a/src/main/resources/lang/en_us.json
+++ b/src/main/resources/lang/en_us.json
@@ -38,6 +38,8 @@
38 "menu.view.languages.title": "Change language", 38 "menu.view.languages.title": "Change language",
39 "menu.view.languages.summary": "The new language will be applied after the next restart.", 39 "menu.view.languages.summary": "The new language will be applied after the next restart.",
40 "menu.view.languages.ok": "Ok", 40 "menu.view.languages.ok": "Ok",
41 "menu.view.scale": "Scale",
42 "menu.view.scale.custom": "Custom...",
41 "menu.view.search": "Search", 43 "menu.view.search": "Search",
42 "menu.help": "Help", 44 "menu.help": "Help",
43 "menu.help.about": "About", 45 "menu.help.about": "About",