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
This commit is contained in:
Konloch 2021-07-26 22:43:36 -07:00
parent f7e47540dc
commit 70a205c5d9
3 changed files with 119 additions and 47 deletions

View file

@ -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);
}

View file

@ -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 <http://www.gnu.org/licenses/>. *
***************************************************************************/
/**
* @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);
}
}

View file

@ -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())