From 70a205c5d9637efb75dbd1f4c33478f26f478733 Mon Sep 17 00:00:00 2001 From: Konloch Date: Mon, 26 Jul 2021 22:43:36 -0700 Subject: [PATCH] Right-Click Context Menu Adds better control to the resource list and gives a right-click context menu that changes depending on the selected node More work is needed and a proper context API should be provided --- .../gui/resourcelist/ResourceListPane.java | 113 +++++++++++------- .../ResourceListRightClickOpen.java | 51 ++++++++ .../ResourceListRightClickRemove.java | 2 +- 3 files changed, 119 insertions(+), 47 deletions(-) create mode 100644 src/main/java/the/bytecode/club/bytecodeviewer/gui/resourcelist/ResourceListRightClickOpen.java diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourcelist/ResourceListPane.java b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourcelist/ResourceListPane.java index b8821c12..1de7f9ec 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourcelist/ResourceListPane.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourcelist/ResourceListPane.java @@ -78,33 +78,48 @@ public class ResourceListPane extends TranslatedVisibleComponent implements File public final KeyAdapter search = new SearchKeyAdapter(this); - private void showPopMenu(ResourceTree tree, TreePath selPath, int x, int y) + private void showContextMenu(ResourceTree tree, TreePath selPath, int x, int y) { if (selPath == null) return; + boolean isContainerSelected = selPath.getParentPath() != null && selPath.getParentPath().getParentPath() == null; + + //TODO this is hacky - there is probably a better way to do this + tree.setSelectionPath(selPath); + DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent(); + boolean isResourceSelected = !node.children().hasMoreElements(); + rightClickMenu.removeAll(); - rightClickMenu.add(new ResourceListRightClickRemove(this, x, y, tree)); + //container selected + if(isContainerSelected) + rightClickMenu.add(new ResourceListRightClickRemove(this, x, y, tree)); + else if(isResourceSelected) //container resource selected + rightClickMenu.add(new ResourceListRightClickOpen(this, x, y, tree)); - rightClickMenu.add(new AbstractAction("Expand", IconResources.CollapsedIcon.createCollapsedIcon()) + if(isContainerSelected || !isResourceSelected) { - @Override - public void actionPerformed(ActionEvent e) + rightClickMenu.add(new AbstractAction("Expand", IconResources.CollapsedIcon.createCollapsedIcon()) { - TreePath selPath = ResourceListPane.this.tree.getPathForLocation(x, y); - expandAll(tree, Objects.requireNonNull(selPath), true); - } - }); - rightClickMenu.add(new AbstractAction("Collapse", IconResources.ExpandedIcon.createExpandedIcon()) - { - @Override - public void actionPerformed(ActionEvent e) + @Override + public void actionPerformed(ActionEvent e) + { + TreePath selPath = ResourceListPane.this.tree.getPathForLocation(x, y); + expandAll(tree, Objects.requireNonNull(selPath), true); + } + }); + + rightClickMenu.add(new AbstractAction("Collapse", IconResources.ExpandedIcon.createExpandedIcon()) { - TreePath selPath = ResourceListPane.this.tree.getPathForLocation(x, y); - expandAll(tree, Objects.requireNonNull(selPath), false); - } - }); + @Override + public void actionPerformed(ActionEvent e) + { + TreePath selPath = ResourceListPane.this.tree.getPathForLocation(x, y); + expandAll(tree, Objects.requireNonNull(selPath), false); + } + }); + } rightClickMenu.show(this.tree, x, y); } @@ -119,6 +134,7 @@ public class ResourceListPane extends TranslatedVisibleComponent implements File public ResourceListPane() { super("Files", TranslatedComponents.FILES); + tree.setRootVisible(false); tree.setShowsRootHandles(true); quickSearch.setForeground(Color.gray); @@ -371,22 +387,12 @@ public class ResourceListPane extends TranslatedVisibleComponent implements File if (e.isMetaDown()) { ResourceTree tree = (ResourceTree) e.getSource(); - TreePath selPath = ResourceListPane.this.tree.getPathForLocation(e.getX(), e.getY()); + TreePath selPath = ResourceListPane.this.tree.getClosestPathForLocation(e.getX(), e.getY()); + if (selPath == null) return; - - DefaultMutableTreeNode selectNode = (DefaultMutableTreeNode) selPath.getLastPathComponent(); - Enumeration enumeration = treeRoot.children(); - while (enumeration.hasMoreElements()) - { - DefaultMutableTreeNode node = (DefaultMutableTreeNode) enumeration.nextElement(); - if (node.isNodeAncestor(selectNode)) - { - //rightClickMenu.show(tree, e.getX(), e.getY()); - showPopMenu(tree, selPath, e.getX(), e.getY()); - break; - } - } + + showContextMenu(tree, selPath, e.getX(), e.getY()); } } }); @@ -406,7 +412,8 @@ public class ResourceListPane extends TranslatedVisibleComponent implements File this.tree.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { - openPath(tree.getPathForLocation(e.getX(), e.getY())); + if(e.getButton() == MouseEvent.BUTTON1) //right-click + openPath(tree.getPathForLocation(e.getX(), e.getY())); } }); @@ -428,22 +435,31 @@ public class ResourceListPane extends TranslatedVisibleComponent implements File public void keyTyped(KeyEvent e) { } @Override - public void keyPressed(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_ENTER) { - if (e.getSource() instanceof ResourceTree) { + public void keyPressed(KeyEvent e) + { + if (e.getKeyCode() == KeyEvent.VK_ENTER) + { + if (e.getSource() instanceof ResourceTree) + { ResourceTree tree = (ResourceTree) e.getSource(); openPath(tree.getSelectionPath()); } - } else if ((int) e.getKeyChar() != 0 && (int) e.getKeyChar() != 8 && (int) e.getKeyChar() != 127 && (int) e.getKeyChar() != 65535 && !e.isControlDown() && !e.isAltDown()) { + } + else if ((int) e.getKeyChar() != 0 && + (int) e.getKeyChar() != 8 && + (int) e.getKeyChar() != 127 && + (int) e.getKeyChar() != 65535 && + !e.isControlDown() && + !e.isAltDown()) + { quickSearch.grabFocus(); quickSearch.setText("" + e.getKeyChar()); cancel = true; - } else if (e.isControlDown() && (int) e.getKeyChar() == 6) //ctrl + f - { - quickSearch.grabFocus(); - } else { - cancel = true; } + else if (e.isControlDown() && (int) e.getKeyChar() == 6) //ctrl + f + quickSearch.grabFocus(); + else + cancel = true; } }); } @@ -451,18 +467,23 @@ public class ResourceListPane extends TranslatedVisibleComponent implements File public void attachQuickSearchListeners() { quickSearch.addKeyListener(search); - quickSearch.addFocusListener(new FocusListener() { + quickSearch.addFocusListener(new FocusListener() + { @Override - public void focusGained(final FocusEvent arg0) { - if (quickSearch.getText().equals(TranslatedStrings.QUICK_FILE_SEARCH_NO_FILE_EXTENSION.toString())) { + public void focusGained(final FocusEvent arg0) + { + if (quickSearch.getText().equals(TranslatedStrings.QUICK_FILE_SEARCH_NO_FILE_EXTENSION.toString())) + { quickSearch.setText(""); quickSearch.setForeground(Color.black); } } @Override - public void focusLost(final FocusEvent arg0) { - if (quickSearch.getText().isEmpty()) { + public void focusLost(final FocusEvent arg0) + { + if (quickSearch.getText().isEmpty()) + { quickSearch.setText(TranslatedStrings.QUICK_FILE_SEARCH_NO_FILE_EXTENSION.toString()); quickSearch.setForeground(Color.gray); } diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourcelist/ResourceListRightClickOpen.java b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourcelist/ResourceListRightClickOpen.java new file mode 100644 index 00000000..5637cd8c --- /dev/null +++ b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourcelist/ResourceListRightClickOpen.java @@ -0,0 +1,51 @@ +package the.bytecode.club.bytecodeviewer.gui.resourcelist; + +import javax.swing.*; +import javax.swing.tree.TreePath; +import java.awt.event.ActionEvent; + +/*************************************************************************** + * Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite * + * Copyright (C) 2014 Kalen 'Konloch' Kinloch - http://bytecodeviewer.com * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + ***************************************************************************/ + +/** + * @author Konloch + * @since 7/26/2021 + */ +public class ResourceListRightClickOpen extends AbstractAction +{ + private final ResourceListPane resourceListPane; + private final int x; + private final int y; + private final ResourceTree tree; + + public ResourceListRightClickOpen(ResourceListPane resourceListPane, int x, int y, ResourceTree tree) + { + super("Open"); + this.resourceListPane = resourceListPane; + this.x = x; + this.y = y; + this.tree = tree; + } + + @Override + public void actionPerformed(ActionEvent e) + { + TreePath selPath = resourceListPane.tree.getClosestPathForLocation(x, y); + resourceListPane.openPath(selPath); + } +} diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourcelist/ResourceListRightClickRemove.java b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourcelist/ResourceListRightClickRemove.java index d1472f6b..99d64d41 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourcelist/ResourceListRightClickRemove.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourcelist/ResourceListRightClickRemove.java @@ -51,7 +51,7 @@ public class ResourceListRightClickRemove extends AbstractAction @Override public void actionPerformed(ActionEvent e) { - TreePath selPath = resourceListPane.tree.getPathForLocation(x, y); + TreePath selPath = resourceListPane.tree.getClosestPathForLocation(x, y); DefaultMutableTreeNode selectNode = (DefaultMutableTreeNode) Objects.requireNonNull(selPath).getLastPathComponent(); Enumeration enumeration = resourceListPane.treeRoot.children(); while (enumeration.hasMoreElements())