diff options
| author | 2021-04-07 16:30:37 +0200 | |
|---|---|---|
| committer | 2021-04-07 16:30:37 +0200 | |
| commit | 3052b37441b1e779b2badd6e4f15b00de91cd63a (patch) | |
| tree | 71c914e22971b7f4e6bce7a54238365753e519b1 | |
| parent | Allow only one selected entry in trees (diff) | |
| download | enigma-3052b37441b1e779b2badd6e4f15b00de91cd63a.tar.gz enigma-3052b37441b1e779b2badd6e4f15b00de91cd63a.tar.xz enigma-3052b37441b1e779b2badd6e4f15b00de91cd63a.zip | |
New ways to search
3 files changed, 97 insertions, 32 deletions
diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/SearchDialog.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/SearchDialog.java index 2d396c36..9ed7339c 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/SearchDialog.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/SearchDialog.java | |||
| @@ -16,19 +16,22 @@ import java.awt.Color; | |||
| 16 | import java.awt.FlowLayout; | 16 | import java.awt.FlowLayout; |
| 17 | import java.awt.Font; | 17 | import java.awt.Font; |
| 18 | import java.awt.event.*; | 18 | import java.awt.event.*; |
| 19 | import java.util.Arrays; | 19 | import java.util.*; |
| 20 | import java.util.Collections; | ||
| 21 | import java.util.List; | ||
| 22 | 20 | ||
| 23 | import javax.swing.*; | 21 | import javax.swing.*; |
| 24 | import javax.swing.event.DocumentEvent; | 22 | import javax.swing.event.DocumentEvent; |
| 25 | import javax.swing.event.DocumentListener; | 23 | import javax.swing.event.DocumentListener; |
| 26 | 24 | ||
| 25 | import cuchaz.enigma.analysis.index.EntryIndex; | ||
| 27 | import cuchaz.enigma.gui.Gui; | 26 | import cuchaz.enigma.gui.Gui; |
| 28 | import cuchaz.enigma.gui.GuiController; | 27 | import cuchaz.enigma.gui.GuiController; |
| 29 | import cuchaz.enigma.gui.util.AbstractListCellRenderer; | 28 | import cuchaz.enigma.gui.util.AbstractListCellRenderer; |
| 29 | import cuchaz.enigma.gui.util.GuiUtil; | ||
| 30 | import cuchaz.enigma.gui.util.ScaleUtil; | 30 | import cuchaz.enigma.gui.util.ScaleUtil; |
| 31 | import cuchaz.enigma.translation.representation.entry.ClassEntry; | 31 | import cuchaz.enigma.translation.representation.entry.ClassEntry; |
| 32 | import cuchaz.enigma.translation.representation.entry.FieldEntry; | ||
| 33 | import cuchaz.enigma.translation.representation.entry.MethodEntry; | ||
| 34 | import cuchaz.enigma.translation.representation.entry.ParentedEntry; | ||
| 32 | import cuchaz.enigma.utils.I18n; | 35 | import cuchaz.enigma.utils.I18n; |
| 33 | import cuchaz.enigma.gui.search.SearchEntry; | 36 | import cuchaz.enigma.gui.search.SearchEntry; |
| 34 | import cuchaz.enigma.gui.search.SearchUtil; | 37 | import cuchaz.enigma.gui.search.SearchUtil; |
| @@ -49,7 +52,7 @@ public class SearchDialog { | |||
| 49 | 52 | ||
| 50 | su = new SearchUtil<>(); | 53 | su = new SearchUtil<>(); |
| 51 | 54 | ||
| 52 | dialog = new JDialog(parent.getFrame(), I18n.translate("menu.view.search"), true); | 55 | dialog = new JDialog(parent.getFrame(), I18n.translate("menu.search"), true); |
| 53 | JPanel contentPane = new JPanel(); | 56 | JPanel contentPane = new JPanel(); |
| 54 | contentPane.setBorder(ScaleUtil.createEmptyBorder(4, 4, 4, 4)); | 57 | contentPane.setBorder(ScaleUtil.createEmptyBorder(4, 4, 4, 4)); |
| 55 | contentPane.setLayout(new BorderLayout(ScaleUtil.scale(4), ScaleUtil.scale(4))); | 58 | contentPane.setLayout(new BorderLayout(ScaleUtil.scale(4), ScaleUtil.scale(4))); |
| @@ -95,7 +98,7 @@ public class SearchDialog { | |||
| 95 | classListModel = new DefaultListModel<>(); | 98 | classListModel = new DefaultListModel<>(); |
| 96 | classList = new JList<>(); | 99 | classList = new JList<>(); |
| 97 | classList.setModel(classListModel); | 100 | classList.setModel(classListModel); |
| 98 | classList.setCellRenderer(new ListCellRendererImpl()); | 101 | classList.setCellRenderer(new ListCellRendererImpl(parent)); |
| 99 | classList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); | 102 | classList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); |
| 100 | classList.addMouseListener(new MouseAdapter() { | 103 | classList.addMouseListener(new MouseAdapter() { |
| 101 | @Override | 104 | @Override |
| @@ -133,14 +136,37 @@ public class SearchDialog { | |||
| 133 | dialog.setLocationRelativeTo(parent.getFrame()); | 136 | dialog.setLocationRelativeTo(parent.getFrame()); |
| 134 | } | 137 | } |
| 135 | 138 | ||
| 136 | public void show() { | 139 | public void show(Type type) { |
| 137 | su.clear(); | 140 | su.clear(); |
| 138 | parent.getController().project.getJarIndex().getEntryIndex().getClasses().parallelStream() | 141 | |
| 139 | .filter(e -> !e.isInnerClass()) | 142 | final EntryIndex entryIndex = parent.getController().project.getJarIndex().getEntryIndex(); |
| 140 | .map(e -> SearchEntryImpl.from(e, parent.getController())) | 143 | |
| 141 | .map(SearchUtil.Entry::from) | 144 | switch (type) { |
| 142 | .sequential() | 145 | default: |
| 143 | .forEach(su::add); | 146 | case CLASS: |
| 147 | entryIndex.getClasses().parallelStream() | ||
| 148 | .filter(e -> !e.isInnerClass()) | ||
| 149 | .map(e -> SearchEntryImpl.from(e, parent.getController())) | ||
| 150 | .map(SearchUtil.Entry::from) | ||
| 151 | .sequential() | ||
| 152 | .forEach(su::add); | ||
| 153 | break; | ||
| 154 | case METHOD: | ||
| 155 | entryIndex.getMethods().parallelStream() | ||
| 156 | .filter(e -> !e.isConstructor() && !entryIndex.getMethodAccess(e).isSynthetic()) | ||
| 157 | .map(e -> SearchEntryImpl.from(e, parent.getController())) | ||
| 158 | .map(SearchUtil.Entry::from) | ||
| 159 | .sequential() | ||
| 160 | .forEach(su::add); | ||
| 161 | break; | ||
| 162 | case FIELD: | ||
| 163 | entryIndex.getFields().parallelStream() | ||
| 164 | .map(e -> SearchEntryImpl.from(e, parent.getController())) | ||
| 165 | .map(SearchUtil.Entry::from) | ||
| 166 | .sequential() | ||
| 167 | .forEach(su::add); | ||
| 168 | break; | ||
| 169 | } | ||
| 144 | 170 | ||
| 145 | updateList(); | 171 | updateList(); |
| 146 | 172 | ||
| @@ -161,10 +187,18 @@ public class SearchDialog { | |||
| 161 | close(); | 187 | close(); |
| 162 | su.hit(e); | 188 | su.hit(e); |
| 163 | parent.getController().navigateTo(e.obf); | 189 | parent.getController().navigateTo(e.obf); |
| 164 | if (e.deobf != null) { | 190 | if (e.obf instanceof ClassEntry) { |
| 165 | parent.getDeobfPanel().deobfClasses.setSelectionClass(e.deobf); | 191 | if (e.deobf != null) { |
| 192 | parent.getDeobfPanel().deobfClasses.setSelectionClass((ClassEntry) e.deobf); | ||
| 193 | } else { | ||
| 194 | parent.getObfPanel().obfClasses.setSelectionClass((ClassEntry) e.obf); | ||
| 195 | } | ||
| 166 | } else { | 196 | } else { |
| 167 | parent.getObfPanel().obfClasses.setSelectionClass(e.obf); | 197 | if (e.deobf != null) { |
| 198 | parent.getDeobfPanel().deobfClasses.setSelectionClass((ClassEntry) e.deobf.getParent()); | ||
| 199 | } else { | ||
| 200 | parent.getObfPanel().obfClasses.setSelectionClass((ClassEntry) e.obf.getParent()); | ||
| 201 | } | ||
| 168 | } | 202 | } |
| 169 | } | 203 | } |
| 170 | 204 | ||
| @@ -189,10 +223,10 @@ public class SearchDialog { | |||
| 189 | 223 | ||
| 190 | private static final class SearchEntryImpl implements SearchEntry { | 224 | private static final class SearchEntryImpl implements SearchEntry { |
| 191 | 225 | ||
| 192 | public final ClassEntry obf; | 226 | public final ParentedEntry<?> obf; |
| 193 | public final ClassEntry deobf; | 227 | public final ParentedEntry<?> deobf; |
| 194 | 228 | ||
| 195 | private SearchEntryImpl(ClassEntry obf, ClassEntry deobf) { | 229 | private SearchEntryImpl(ParentedEntry<?> obf, ParentedEntry<?> deobf) { |
| 196 | this.obf = obf; | 230 | this.obf = obf; |
| 197 | this.deobf = deobf; | 231 | this.deobf = deobf; |
| 198 | } | 232 | } |
| @@ -216,8 +250,8 @@ public class SearchDialog { | |||
| 216 | return String.format("SearchEntryImpl { obf: %s, deobf: %s }", obf, deobf); | 250 | return String.format("SearchEntryImpl { obf: %s, deobf: %s }", obf, deobf); |
| 217 | } | 251 | } |
| 218 | 252 | ||
| 219 | public static SearchEntryImpl from(ClassEntry e, GuiController controller) { | 253 | public static SearchEntryImpl from(ParentedEntry<?> e, GuiController controller) { |
| 220 | ClassEntry deobf = controller.project.getMapper().deobfuscate(e); | 254 | ParentedEntry<?> deobf = controller.project.getMapper().deobfuscate(e); |
| 221 | if (deobf.equals(e)) deobf = null; | 255 | if (deobf.equals(e)) deobf = null; |
| 222 | return new SearchEntryImpl(e, deobf); | 256 | return new SearchEntryImpl(e, deobf); |
| 223 | } | 257 | } |
| @@ -225,12 +259,13 @@ public class SearchDialog { | |||
| 225 | } | 259 | } |
| 226 | 260 | ||
| 227 | private static final class ListCellRendererImpl extends AbstractListCellRenderer<SearchEntryImpl> { | 261 | private static final class ListCellRendererImpl extends AbstractListCellRenderer<SearchEntryImpl> { |
| 228 | 262 | private final Gui gui; | |
| 229 | private final JLabel mainName; | 263 | private final JLabel mainName; |
| 230 | private final JLabel secondaryName; | 264 | private final JLabel secondaryName; |
| 231 | 265 | ||
| 232 | public ListCellRendererImpl() { | 266 | public ListCellRendererImpl(Gui gui) { |
| 233 | this.setLayout(new BorderLayout()); | 267 | this.setLayout(new BorderLayout()); |
| 268 | this.gui = gui; | ||
| 234 | 269 | ||
| 235 | mainName = new JLabel(); | 270 | mainName = new JLabel(); |
| 236 | this.add(mainName, BorderLayout.WEST); | 271 | this.add(mainName, BorderLayout.WEST); |
| @@ -244,18 +279,31 @@ public class SearchDialog { | |||
| 244 | @Override | 279 | @Override |
| 245 | public void updateUiForEntry(JList<? extends SearchEntryImpl> list, SearchEntryImpl value, int index, boolean isSelected, boolean cellHasFocus) { | 280 | public void updateUiForEntry(JList<? extends SearchEntryImpl> list, SearchEntryImpl value, int index, boolean isSelected, boolean cellHasFocus) { |
| 246 | if (value.deobf == null) { | 281 | if (value.deobf == null) { |
| 247 | mainName.setText(value.obf.getSimpleName()); | 282 | mainName.setText(value.obf.getContextualName()); |
| 248 | mainName.setToolTipText(value.obf.getFullName()); | 283 | mainName.setToolTipText(value.obf.getFullName()); |
| 249 | secondaryName.setText(""); | 284 | secondaryName.setText(""); |
| 250 | secondaryName.setToolTipText(""); | 285 | secondaryName.setToolTipText(""); |
| 251 | } else { | 286 | } else { |
| 252 | mainName.setText(value.deobf.getSimpleName()); | 287 | mainName.setText(value.deobf.getContextualName()); |
| 253 | mainName.setToolTipText(value.deobf.getFullName()); | 288 | mainName.setToolTipText(value.deobf.getFullName()); |
| 254 | secondaryName.setText(value.obf.getSimpleName()); | 289 | secondaryName.setText(value.obf.getSimpleName()); |
| 255 | secondaryName.setToolTipText(value.obf.getFullName()); | 290 | secondaryName.setToolTipText(value.obf.getFullName()); |
| 256 | } | 291 | } |
| 292 | |||
| 293 | if (value.obf instanceof ClassEntry) { | ||
| 294 | mainName.setIcon(GuiUtil.getClassIcon(gui, (ClassEntry) value.obf)); | ||
| 295 | } else if (value.obf instanceof MethodEntry) { | ||
| 296 | mainName.setIcon(GuiUtil.getMethodIcon((MethodEntry) value.obf)); | ||
| 297 | } else if (value.obf instanceof FieldEntry) { | ||
| 298 | mainName.setIcon(GuiUtil.FIELD_ICON); | ||
| 299 | } | ||
| 257 | } | 300 | } |
| 258 | 301 | ||
| 259 | } | 302 | } |
| 260 | 303 | ||
| 304 | public enum Type { | ||
| 305 | CLASS, | ||
| 306 | METHOD, | ||
| 307 | FIELD | ||
| 308 | } | ||
| 261 | } | 309 | } |
diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java index f7f42a58..472ff609 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java | |||
| @@ -57,7 +57,11 @@ public class MenuBar { | |||
| 57 | private final JMenu scaleMenu = new JMenu(); | 57 | private final JMenu scaleMenu = new JMenu(); |
| 58 | private final JMenuItem fontItem = new JMenuItem(); | 58 | private final JMenuItem fontItem = new JMenuItem(); |
| 59 | private final JMenuItem customScaleItem = new JMenuItem(); | 59 | private final JMenuItem customScaleItem = new JMenuItem(); |
| 60 | private final JMenuItem searchItem = new JMenuItem(); | 60 | |
| 61 | private final JMenu searchMenu = new JMenu(); | ||
| 62 | private final JMenuItem searchClassItem = new JMenuItem(); | ||
| 63 | private final JMenuItem searchMethodItem = new JMenuItem(); | ||
| 64 | private final JMenuItem searchFieldItem = new JMenuItem(); | ||
| 61 | 65 | ||
| 62 | private final JMenu collabMenu = new JMenu(); | 66 | private final JMenu collabMenu = new JMenu(); |
| 63 | private final JMenuItem connectItem = new JMenuItem(); | 67 | private final JMenuItem connectItem = new JMenuItem(); |
| @@ -109,9 +113,13 @@ public class MenuBar { | |||
| 109 | this.viewMenu.add(this.scaleMenu); | 113 | this.viewMenu.add(this.scaleMenu); |
| 110 | this.viewMenu.add(this.fontItem); | 114 | this.viewMenu.add(this.fontItem); |
| 111 | this.viewMenu.addSeparator(); | 115 | this.viewMenu.addSeparator(); |
| 112 | this.viewMenu.add(this.searchItem); | ||
| 113 | this.ui.add(this.viewMenu); | 116 | this.ui.add(this.viewMenu); |
| 114 | 117 | ||
| 118 | this.searchMenu.add(this.searchClassItem); | ||
| 119 | this.searchMenu.add(this.searchMethodItem); | ||
| 120 | this.searchMenu.add(this.searchFieldItem); | ||
| 121 | this.ui.add(this.searchMenu); | ||
| 122 | |||
| 115 | this.collabMenu.add(this.connectItem); | 123 | this.collabMenu.add(this.connectItem); |
| 116 | this.collabMenu.add(this.startServerItem); | 124 | this.collabMenu.add(this.startServerItem); |
| 117 | this.ui.add(this.collabMenu); | 125 | this.ui.add(this.collabMenu); |
| @@ -121,7 +129,7 @@ public class MenuBar { | |||
| 121 | this.ui.add(this.helpMenu); | 129 | this.ui.add(this.helpMenu); |
| 122 | 130 | ||
| 123 | this.saveMappingsItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK)); | 131 | this.saveMappingsItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK)); |
| 124 | this.searchItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, InputEvent.SHIFT_DOWN_MASK)); | 132 | this.searchClassItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, InputEvent.SHIFT_DOWN_MASK)); |
| 125 | 133 | ||
| 126 | this.jarOpenItem.addActionListener(_e -> this.onOpenJarClicked()); | 134 | this.jarOpenItem.addActionListener(_e -> this.onOpenJarClicked()); |
| 127 | this.jarCloseItem.addActionListener(_e -> this.gui.getController().closeJar()); | 135 | this.jarCloseItem.addActionListener(_e -> this.gui.getController().closeJar()); |
| @@ -136,7 +144,9 @@ public class MenuBar { | |||
| 136 | this.exitItem.addActionListener(_e -> this.gui.close()); | 144 | this.exitItem.addActionListener(_e -> this.gui.close()); |
| 137 | this.customScaleItem.addActionListener(_e -> this.onCustomScaleClicked()); | 145 | this.customScaleItem.addActionListener(_e -> this.onCustomScaleClicked()); |
| 138 | this.fontItem.addActionListener(_e -> this.onFontClicked(this.gui)); | 146 | this.fontItem.addActionListener(_e -> this.onFontClicked(this.gui)); |
| 139 | this.searchItem.addActionListener(_e -> this.onSearchClicked()); | 147 | this.searchClassItem.addActionListener(_e -> this.onSearchClicked(SearchDialog.Type.CLASS)); |
| 148 | this.searchMethodItem.addActionListener(_e -> this.onSearchClicked(SearchDialog.Type.METHOD)); | ||
| 149 | this.searchFieldItem.addActionListener(_e -> this.onSearchClicked(SearchDialog.Type.FIELD)); | ||
| 140 | this.connectItem.addActionListener(_e -> this.onConnectClicked()); | 150 | this.connectItem.addActionListener(_e -> this.onConnectClicked()); |
| 141 | this.startServerItem.addActionListener(_e -> this.onStartServerClicked()); | 151 | this.startServerItem.addActionListener(_e -> this.onStartServerClicked()); |
| 142 | this.aboutItem.addActionListener(_e -> AboutDialog.show(this.gui.getFrame())); | 152 | this.aboutItem.addActionListener(_e -> AboutDialog.show(this.gui.getFrame())); |
| @@ -188,7 +198,11 @@ public class MenuBar { | |||
| 188 | this.scaleMenu.setText(I18n.translate("menu.view.scale")); | 198 | this.scaleMenu.setText(I18n.translate("menu.view.scale")); |
| 189 | this.fontItem.setText(I18n.translate("menu.view.font")); | 199 | this.fontItem.setText(I18n.translate("menu.view.font")); |
| 190 | this.customScaleItem.setText(I18n.translate("menu.view.scale.custom")); | 200 | this.customScaleItem.setText(I18n.translate("menu.view.scale.custom")); |
| 191 | this.searchItem.setText(I18n.translate("menu.view.search")); | 201 | |
| 202 | this.searchMenu.setText(I18n.translate("menu.search")); | ||
| 203 | this.searchClassItem.setText(I18n.translate("menu.search.class")); | ||
| 204 | this.searchMethodItem.setText(I18n.translate("menu.search.method")); | ||
| 205 | this.searchFieldItem.setText(I18n.translate("menu.search.field")); | ||
| 192 | 206 | ||
| 193 | this.collabMenu.setText(I18n.translate("menu.collab")); | 207 | this.collabMenu.setText(I18n.translate("menu.collab")); |
| 194 | this.connectItem.setText(I18n.translate("menu.collab.connect")); | 208 | this.connectItem.setText(I18n.translate("menu.collab.connect")); |
| @@ -295,9 +309,9 @@ public class MenuBar { | |||
| 295 | FontDialog.display(gui.getFrame()); | 309 | FontDialog.display(gui.getFrame()); |
| 296 | } | 310 | } |
| 297 | 311 | ||
| 298 | private void onSearchClicked() { | 312 | private void onSearchClicked(SearchDialog.Type type) { |
| 299 | if (this.gui.getController().project != null) { | 313 | if (this.gui.getController().project != null) { |
| 300 | this.gui.getSearchDialog().show(); | 314 | this.gui.getSearchDialog().show(type); |
| 301 | } | 315 | } |
| 302 | } | 316 | } |
| 303 | 317 | ||
diff --git a/enigma/src/main/resources/lang/en_us.json b/enigma/src/main/resources/lang/en_us.json index 903faa76..eebdb534 100644 --- a/enigma/src/main/resources/lang/en_us.json +++ b/enigma/src/main/resources/lang/en_us.json | |||
| @@ -46,7 +46,10 @@ | |||
| 46 | "menu.view.font": "Fonts...", | 46 | "menu.view.font": "Fonts...", |
| 47 | "menu.view.change.title": "Changes", | 47 | "menu.view.change.title": "Changes", |
| 48 | "menu.view.change.summary": "Changes will be applied after the next restart.", | 48 | "menu.view.change.summary": "Changes will be applied after the next restart.", |
| 49 | "menu.view.search": "Search", | 49 | "menu.search": "Search", |
| 50 | "menu.search.class": "Search Class", | ||
| 51 | "menu.search.method": "Search Method", | ||
| 52 | "menu.search.field": "Search Field", | ||
| 50 | "menu.collab": "Collab", | 53 | "menu.collab": "Collab", |
| 51 | "menu.collab.connect": "Connect to server", | 54 | "menu.collab.connect": "Connect to server", |
| 52 | "menu.collab.connect.error": "Error connecting to server", | 55 | "menu.collab.connect.error": "Error connecting to server", |