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:
parent
f7e47540dc
commit
70a205c5d9
3 changed files with 119 additions and 47 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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())
|
||||
|
|
Loading…
Reference in a new issue