Merge remote-tracking branch 'origin/GP-4574-dragonmacher-tree-to-table-cleanup-v2'

This commit is contained in:
Ryan Kurtz 2024-05-21 13:15:54 -04:00
commit a29a59488a
19 changed files with 605 additions and 1108 deletions

View File

@ -340,11 +340,6 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter
return null;
}
@Override
public void dragCanceled(DragSourceDropEvent event) {
// nothing to do
}
@Override
public int getDragAction() {
return dragAction;
@ -370,11 +365,6 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter
return listingPanel.isStartDragOk();
}
@Override
public void move() {
// nothing to do
}
@Override
public void add(Object obj, DropTargetDropEvent event, DataFlavor f) {
Point p = event.getLocation();
@ -385,11 +375,6 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter
}
}
@Override
public void dragUnderFeedback(boolean ok, DropTargetDragEvent e) {
// nothing to do
}
@Override
public boolean isDropOk(DropTargetDragEvent e) {
curDropProvider = null;
@ -431,11 +416,6 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter
}
}
@Override
public void undoDragUnderFeedback() {
// nothing to do
}
protected void doSetProgram(Program newProgram) {
currentLocation = null;
@ -1112,11 +1092,10 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter
public Highlight[] createHighlights(String text, ListingField field, int cursorTextOffset) {
List<Highlight> list = new ArrayList<>();
ListingHighlightProvider currentExternalHighligter =
programHighlighterMap.get(program);
ListingHighlightProvider currentExternalHighligter = programHighlighterMap.get(program);
if (currentExternalHighligter != null) {
Highlight[] highlights = currentExternalHighligter.createHighlights(text, field,
cursorTextOffset);
Highlight[] highlights =
currentExternalHighligter.createHighlights(text, field, cursorTextOffset);
for (Highlight highlight : highlights) {
list.add(highlight);
}

View File

@ -17,7 +17,6 @@ package ghidra.app.plugin.core.compositeeditor;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.*;
import java.awt.event.*;
import java.math.BigInteger;
@ -34,7 +33,8 @@ import javax.swing.text.JTextComponent;
import docking.DockingWindowManager;
import docking.actions.KeyBindingUtils;
import docking.dnd.*;
import docking.dnd.DropTgtAdapter;
import docking.dnd.Droppable;
import docking.widgets.DropDownSelectionTextField;
import docking.widgets.OptionDialog;
import docking.widgets.fieldpanel.support.FieldRange;
@ -68,10 +68,7 @@ import help.HelpService;
* composite data type. To add your own info panel override the createInfoPanel() method.
*/
public abstract class CompositeEditorPanel extends JPanel
implements CompositeEditorModelListener, ComponentCellEditorListener, Draggable, Droppable {
// Normal color for selecting components in the table.
//protected static final Insets TEXTFIELD_INSETS = new JTextField().getInsets();
implements CompositeEditorModelListener, ComponentCellEditorListener, Droppable {
protected static final Border BEVELED_BORDER = BorderFactory.createLoweredBevelBorder();
@ -90,10 +87,6 @@ public abstract class CompositeEditorPanel extends JPanel
/** The table cell renderer for drag-n-drop. */
protected DndTableCellRenderer dndTableCellRenderer;
protected DndTableCellRenderer dndDtiCellRenderer;
private DragSource dragSource;
private DragGestureAdapter dragGestureAdapter;
private DragSrcAdapter dragSourceAdapter;
private int dragAction = DnDConstants.ACTION_MOVE;
private DropTarget dropTarget;
private DropTgtAdapter dropTargetAdapter;
private DataFlavor[] acceptableFlavors; // data flavors that are valid.
@ -151,8 +144,7 @@ public abstract class CompositeEditorPanel extends JPanel
}
private boolean launchBitFieldEditor(int modelRow, int modelColumn) {
if (model.viewComposite instanceof Structure &&
!model.viewComposite.isPackingEnabled() &&
if (model.viewComposite instanceof Structure && !model.viewComposite.isPackingEnabled() &&
model.getDataTypeColumn() == modelColumn && modelRow < model.getNumComponents()) {
// check if we are attempting to edit a bitfield
DataTypeComponent dtComponent = model.getComponent(modelRow);
@ -788,99 +780,6 @@ public abstract class CompositeEditorPanel extends JPanel
dropTarget =
new DropTarget(table, DnDConstants.ACTION_COPY_OR_MOVE, dropTargetAdapter, true);
dropTarget.setActive(true);
// set up the component area as a drag site that provides Data Types.
dragSource = DragSource.getDefaultDragSource();
dragGestureAdapter = new DragGestureAdapter(this);
dragSourceAdapter = new DragSrcAdapter(this);
dragSource.createDefaultDragGestureRecognizer(table, dragAction, dragGestureAdapter);
}
/**
* Return true if the object at the location in the DragGesture
* event is draggable.
*
* @param e event passed to a DragGestureListener via its
* dragGestureRecognized() method when a particular DragGestureRecognizer
* detects a platform dependent Drag and Drop action initiating
* gesture has occurred on the Component it is tracking.
* @see docking.dnd.DragGestureAdapter
*/
@Override
public boolean isStartDragOk(DragGestureEvent e) {
return false;
// boolean dragOk = false;
// // Need to check that the location is on a component.
// Point point = e.getDragOrigin();
// int index = table.rowAtPoint(point);
// // If we are on a component then drag is allowed.
// if ((index >= 0) && (index < model.getNumComponents())) {
// dragOk = true;
// }
// return dragOk;
}
/**
* Called by the DragGestureAdapter to start the drag.
*/
@Override
public DragSourceListener getDragSourceListener() {
return dragSourceAdapter;
}
/**
* Do the move operation; called when the drag and drop operation
* completes.
* @see docking.dnd.DragSrcAdapter#dragDropEnd
*/
@Override
public void move() {
// no-op
}
/**
* Method called when the drag operation exits the drop target
* without dropping.
*/
@Override
public void dragCanceled(DragSourceDropEvent event) {
// no-op
}
/**
* Get the drag actions supported by this drag source:
* <ul>
* <li>DnDConstants.ACTION_MOVE
* <li>DnDConstants.ACTION_COPY
* <li>DnDConstants.ACTION_COPY_OR_MOVE
* </ul>
*
* @return the drag actions
*/
@Override
public int getDragAction() {
return dragAction;
}
/**
* Get the object to transfer.
*
* @param p location of object to transfer
* @return object to transfer
*/
@Override
public Transferable getTransferable(Point p) {
int index = table.rowAtPoint(p);
int numRows = model.getRowCount();
if (index >= numRows) {
index = numRows;
}
DataType dt = DefaultDataType.dataType;
// If we are on a component then get the data type.
if ((index >= 0)) {
dt = model.getComponent(index).getDataType();
}
return new DataTypeTransferable(dt);
}
@Override
@ -888,15 +787,6 @@ public abstract class CompositeEditorPanel extends JPanel
return true;
}
/**
* Add the object to the droppable component. The DragSrcAdapter calls this method from its
* drop() method.
*
* @param obj Transferable object that is to be dropped.
* @param e has current state of drop operation
* @param f represents the opaque concept of a data format as
* would appear on a clipboard, during drag and drop.
*/
@Override
public void add(Object obj, DropTargetDropEvent e, DataFlavor f) {
if (!(obj instanceof DataType)) {
@ -1491,8 +1381,8 @@ public abstract class CompositeEditorPanel extends JPanel
String status = columnName + " field is not editable";
boolean isValidRow = row >= 0 && row < model.getNumComponents();
boolean isStringColumn = modelColumn == model.getNameColumn() ||
modelColumn == model.getCommentColumn();
boolean isStringColumn =
modelColumn == model.getNameColumn() || modelColumn == model.getCommentColumn();
if (isValidRow && isStringColumn) {
DataType dt = model.getComponent(row).getDataType();
if (dt == DataType.DEFAULT) {

View File

@ -422,16 +422,6 @@ public class DataTypePreviewPlugin extends ProgramPlugin {
return true;
}
@Override
public void dragUnderFeedback(boolean ok, DropTargetDragEvent e) {
// don't care
}
@Override
public void undoDragUnderFeedback() {
// don't care
}
@Override
public void add(Object obj, DropTargetDropEvent e, DataFlavor f) {
if (obj instanceof DataType) {
@ -608,9 +598,7 @@ public class DataTypePreviewPlugin extends ProgramPlugin {
}
private boolean contains(DataType dt) {
Iterator<Preview> iter = data.iterator();
while (iter.hasNext()) {
Preview p = iter.next();
for (Preview p : data) {
if (p.getDataType().equals(dt) || p.getDataType().isEquivalent(dt)) {
return true;
}

View File

@ -43,7 +43,7 @@ public abstract class DragNDropTree extends JTree implements Draggable, Droppabl
private AutoscrollAdapter autoscroller;
protected DefaultTreeModel treeModel;
protected DefaultTreeModel model;
protected DragSource dragSource;
protected DragGestureAdapter dragGestureAdapter;
protected TreeDragSrcAdapter dragSourceAdapter;
@ -52,7 +52,6 @@ public abstract class DragNDropTree extends JTree implements Draggable, Droppabl
protected DropTarget dropTarget;
protected DropTgtAdapter dropTargetAdapter;
protected ProgramNode root;
protected ProgramTreeCellEditor cellEditor;
protected Color plafSelectionColor;
protected DnDTreeCellRenderer dndCellRenderer;
protected boolean drawFeedback;
@ -60,23 +59,23 @@ public abstract class DragNDropTree extends JTree implements Draggable, Droppabl
protected ProgramNode destinationNode; // target for drop site
// data flavors that this tree can support
protected DataFlavor[] acceptableFlavors; // filled in by the
// getAcceptableDataFlavors() method
protected DataFlavor[] acceptableFlavors;
protected TreeTransferable transferable;
protected Color nonSelectionDragColor;
protected int relativeMousePos; // mouse position within the node:
protected int relativeMousePos; // mouse position within the node
public DragNDropTree(DefaultTreeModel model) {
super(model);
setBackground(new GColor("color.bg.tree"));
treeModel = model;
this.model = model;
this.root = (ProgramNode) model.getRoot();
//setEditable(true); // edit interferes with drag gesture listener
// setEditable(true); // edit interferes with drag gesture listener
setShowsRootHandles(true); // need this to "drill down"
cellEditor = new ProgramTreeCellEditor();
setCellEditor(cellEditor);
ProgramTreeCellEditor treeCellEditor = new ProgramTreeCellEditor();
setCellEditor(treeCellEditor);
dndCellRenderer = new DnDTreeCellRenderer();
setCellRenderer(dndCellRenderer);
plafSelectionColor = dndCellRenderer.getBackgroundSelectionColor();
@ -87,10 +86,10 @@ public abstract class DragNDropTree extends JTree implements Draggable, Droppabl
disableJTreeTransferActions();
}
//// Draggable interface methods
/**
* Return true if the location in the event is draggable.
*/
//=================================================================================================
// Draggable Methods
//=================================================================================================
@Override
public boolean isStartDragOk(DragGestureEvent e) {
synchronized (root) {
@ -106,27 +105,16 @@ public abstract class DragNDropTree extends JTree implements Draggable, Droppabl
}
}
/**
* Called by the DragGestureAdapter to start the drag.
*/
@Override
public DragSourceListener getDragSourceListener() {
return dragSourceAdapter;
}
/**
* Called by the DragGestureAdapter and the DragSourceAdapter to
* know what actions this component allows.
*/
@Override
public int getDragAction() {
return DnDConstants.ACTION_COPY_OR_MOVE;
}
/**
* Called by the DragGestureAdapter when the drag is about to
* start.
*/
@Override
public Transferable getTransferable(Point p) {
synchronized (root) {
@ -146,31 +134,16 @@ public abstract class DragNDropTree extends JTree implements Draggable, Droppabl
}
}
/**
* Do the move operation. Called from the DragSourceAdapter
* when the drop completes and the user action was a
* DnDConstants.MOVE.
*/
@Override
public abstract void move();
/**
* Called from the DragSourceAdapter when the drag operation exits the
* drop target without dropping.
*/
@Override
public void dragCanceled(DragSourceDropEvent event) {
public void dragFinished(boolean wasCancelled) {
draggedNodes = null;
dndCellRenderer.setBackgroundSelectionColor(plafSelectionColor);
dndCellRenderer
.setBackgroundNonSelectionColor(dndCellRenderer.getBackgroundNonSelectionColor());
}
//////////////////////////////////////////////////////////////////////
// Droppable interface methods
/**
* Return true if OK to drop at the location specified in the event.
*/
//=================================================================================================
// Droppable Methods
//=================================================================================================
@Override
public boolean isDropOk(DropTargetDragEvent e) {
synchronized (root) {
@ -228,11 +201,6 @@ public abstract class DragNDropTree extends JTree implements Draggable, Droppabl
return false;
}
/**
* Called from the DropTgtAdapter when the drag operation is going over a drop site; indicate
* when the drop is OK by providing appropriate feedback.
* @param ok true means OK to drop
*/
@Override
public void dragUnderFeedback(boolean ok, DropTargetDragEvent e) {
synchronized (root) {
@ -271,10 +239,6 @@ public abstract class DragNDropTree extends JTree implements Draggable, Droppabl
}
}
/**
* Called from the DropTgtAdapter to revert any feedback
* changes back to normal.
*/
@Override
public void undoDragUnderFeedback() {
synchronized (root) {
@ -283,52 +247,29 @@ public abstract class DragNDropTree extends JTree implements Draggable, Droppabl
repaint();
}
/**
* Add the data to the tree. Called from the DropTgtAdapter
* when the drop completes and the user action was a
* DnDConstants.COPY.
*/
@Override
public abstract void add(Object data, DropTargetDropEvent e, DataFlavor chosen);
//=================================================================================================
// Autoscroll Methods
//=================================================================================================
///////////////////////////////////////////////////////////
// Autoscroll Interface methods
///////////////////////////////////////////////////////////
/**
* This method returns the <code>Insets</code> describing
* the autoscrolling region or border relative
* to the geometry of the implementing Component; called
* repeatedly while dragging.
* @return the Insets
*/
@Override
public Insets getAutoscrollInsets() {
return autoscroller.getAutoscrollInsets();
}
/**
* Notify the <code>Component</code> to autoscroll; called repeatedly
* while dragging.
* <P>
* @param p A <code>Point</code> indicating the
* location of the cursor that triggered this operation.
*/
@Override
public void autoscroll(Point p) {
autoscroller.autoscroll(p);
}
///////////////////////////////////////////////////////////////
// protected methods
///////////////////////////////////////////////////////////////
/**
* Get the data flavors that this tree supports.
*/
//=================================================================================================
// Protected Methods
//=================================================================================================
protected abstract DataFlavor[] getAcceptableDataFlavors();
/**
* Return true if the node can accept the drop as indicated by the event.
* @param node the node being dragged
* @param e event that has current state of drag and drop operation
* @return true if drop is OK
*/
@ -336,11 +277,14 @@ public abstract class DragNDropTree extends JTree implements Draggable, Droppabl
/**
* Get the string to use as the tool tip for the specified node.
* @param node the node
* @return the text
*/
protected abstract String getToolTipText(ProgramNode node);
/**
* Get the node at the given point.
* @param p the point
* @return null if there is no node a the point p.
*/
protected ProgramNode getTreeNode(Point p) {
@ -351,16 +295,41 @@ public abstract class DragNDropTree extends JTree implements Draggable, Droppabl
return null;
}
/**
* Return the drawFeedback state.
*/
boolean getDrawFeedbackState() {
return drawFeedback;
}
//////////////////////////////////////////////////////////////////////
// *** private methods
//////////////////////////////////////////////////////////////////////
/**
* Determine where the mouse pointer is within the node.
* @param p the point
* @param node the node
* @return -1 if the mouse pointer is in the upper quarter of the node, 1 if the mouse pointer
* is in the lower quarter of the node, or 0 if the mouse pointer is in the center of the node.
*/
protected int comparePointerLocation(Point p, ProgramNode node) {
int localRowHeight = getRowHeight();
int row = this.getRowForPath(node.getTreePath());
Rectangle rect = getRowBounds(row);
if (p.y == rect.y) {
return 1;
}
if ((p.y - rect.y) <= localRowHeight) {
int delta = localRowHeight - (p.y - rect.y);
int sliceSize = localRowHeight / 4;
if (delta < sliceSize) {
return 1; // in the lower part of the node
}
if (delta > (sliceSize * 3)) {
return -1; // in the upper part of the node
}
}
return 0;
}
//=================================================================================================
// Private Methods
//=================================================================================================
/**
* Set up the drag and drop stuff.
@ -392,49 +361,16 @@ public abstract class DragNDropTree extends JTree implements Draggable, Droppabl
KeyStroke.getKeyStroke(KeyEvent.VK_X, DockingUtils.CONTROL_KEY_MODIFIER_MASK));
}
/**
* Determine where the mouse pointer is within the node.
* @return -1 if the mouse pointer is in the upper quarter of the node, 1 if the mouse pointer
* is in the lower quarter of the node, or 0 if the mouse pointer is in the center of the node.
*/
int comparePointerLocation(Point p, ProgramNode node) {
//=================================================================================================
// Inner Classes
//=================================================================================================
int localRowHeight = getRowHeight();
int row = this.getRowForPath(node.getTreePath());
Rectangle rect = getRowBounds(row);
if (p.y == rect.y) {
return 1;
}
if ((p.y - rect.y) <= localRowHeight) {
int delta = localRowHeight - (p.y - rect.y);
int sliceSize = localRowHeight / 4;
if (delta < sliceSize) {
return 1; // in the lower part of the node
}
if (delta > (sliceSize * 3)) {
return -1; // in the upper part of the node
}
}
return 0;
}
private class ProgramTreeCellEditor extends DefaultTreeCellEditor {
//////////////////////////////////////////////////////////////////////
/**
* TreeCellEditor for the program tree.
*/
protected class ProgramTreeCellEditor extends DefaultTreeCellEditor {
/**
* Construct a new ProgramTreeCellEditor.
*/
public ProgramTreeCellEditor() {
super(DragNDropTree.this, null);
}
/**
* Override this method in order to select the contents of
* the editing component which is a JTextField.
*/
@Override
public boolean shouldSelectCell(EventObject anEvent) {
((JTextField) editingComponent).selectAll();

View File

@ -161,10 +161,12 @@ public class ProgramDnDTree extends DragNDropTree {
if (!super.isDropOk(e)) {
return false;
}
if (draggedNodes == null) {
return true; // drag initiated from somewhere else, so
// if the superclass said it was OK, then it's OK...
// drag initiated from elsewhere, if the superclass said it was OK, then it's OK
return true;
}
Point p = e.getLocation();
ProgramNode destNode = getTreeNode(p);
relativeMousePos = comparePointerLocation(p, destNode);
@ -173,14 +175,13 @@ public class ProgramDnDTree extends DragNDropTree {
}
}
/**
* Droppable interface method called from the DropTargetAdapter's
* drop() method.
*/
@Override
public void add(Object data, DropTargetDropEvent e, DataFlavor chosen) {
synchronized (root) {
draggedNodes = null;
if (destinationNode == null) {
return;
}
@ -189,20 +190,16 @@ public class ProgramDnDTree extends DragNDropTree {
if (e != null) {
dropAction = e.getDropAction();
}
// note: must use destinationNode because the when the user
// releases the mouse, the point could have moved, so
// the node obtained at the point is not necessarily the
// Note: must use destinationNode because when the user releases the mouse, the
// point could have moved, so the node obtained at the point is not necessarily the
// expected destinationNode.
processDropRequest(destinationNode, data, chosen, dropAction);
if (dropAction == DnDConstants.ACTION_COPY) {
draggedNodes = null;
}
}
catch (Exception ex) {
if (!(ex instanceof UsrException)) {
Msg.error(this, "Unexpected Exception: " + ex.getMessage(), ex);
}
draggedNodes = null;
//let the drop() method handle the error reporting
String msg = ex.getMessage();
@ -219,20 +216,6 @@ public class ProgramDnDTree extends DragNDropTree {
}
}
/**
* Method called from the dragDropEnd() method in the
* DragSourceAdapter when the drop has completed.
* The "copy" part is done in the add() method.
* @see #add(Object, DropTargetDropEvent, DataFlavor)
*/
@Override
public void move() {
draggedNodes = null;
}
/**
* Set the program for this tree.
*/
void setProgram(Program p) {
if (p == program) {
return;
@ -423,13 +406,6 @@ public class ProgramDnDTree extends DragNDropTree {
treeListener = null;
}
/**
* Clear the variable that has the dragged data.
*/
void clearDragData() {
draggedNodes = null;
}
/**
* Get the view list.
*
@ -506,8 +482,7 @@ public class ProgramDnDTree extends DragNDropTree {
TreePath path = node.getTreePath();
for (int i = 0; i < viewList.size(); i++) {
TreePath viewPath = viewList.get(i);
for (TreePath viewPath : viewList) {
if (viewPath.isDescendant(path) && !viewPath.equals(path)) {
return true;
}
@ -834,7 +809,7 @@ public class ProgramDnDTree extends DragNDropTree {
if (parentModuleName.equals(parent.getName())) {
TreePath childPath = child.getTreePath();
treeModel.removeNodeFromParent(child);
model.removeNodeFromParent(child);
child.removeAllChildren();
child.removeFromParent();
if (updateViewList) {
@ -902,7 +877,7 @@ public class ProgramDnDTree extends DragNDropTree {
}
ProgramNode child = new ProgramNode(program, group);
treeModel.insertNodeInto(child, parent, index);
model.insertNodeInto(child, parent, index);
child.setParentModule(parent.getModule());
// do the lazy population which means don't
@ -1013,11 +988,10 @@ public class ProgramDnDTree extends DragNDropTree {
}
parent.insert(node, tempIndex);
treeModel.reload(parent);
model.reload(parent);
}
for (int i = 0; i < list.size(); i++) {
TreePath p = list.get(i);
for (TreePath p : list) {
expandPath(p);
}
}
@ -1181,7 +1155,7 @@ public class ProgramDnDTree extends DragNDropTree {
List<TreePath> list = getExpandedPaths(node);
TreePath[] paths = getSelectionPaths();
treeModel.reload(node);
model.reload(node);
expandPaths(list);
@ -1331,8 +1305,7 @@ public class ProgramDnDTree extends DragNDropTree {
* @param list list of TreePaths.
*/
public void expandPaths(List<TreePath> list) {
for (int i = 0; i < list.size(); i++) {
TreePath path = list.get(i);
for (TreePath path : list) {
expandPath(path);
}
}
@ -1402,8 +1375,7 @@ public class ProgramDnDTree extends DragNDropTree {
*/
private TreePath findTreePath(GroupPath groupPath) {
for (int i = 0; i < nodeList.size(); i++) {
ProgramNode node = nodeList.get(i);
for (ProgramNode node : nodeList) {
GroupPath p = node.getGroupPath();
if (p.equals(groupPath)) {
return node.getTreePath();
@ -1753,8 +1725,7 @@ public class ProgramDnDTree extends DragNDropTree {
* garbage collected.
*/
private void disposeOfNodes() {
for (int i = 0; i < nodeList.size(); i++) {
ProgramNode node = nodeList.get(i);
for (ProgramNode node : nodeList) {
node.dispose();
}
}
@ -1837,7 +1808,7 @@ public class ProgramDnDTree extends DragNDropTree {
versionTag = rm.getVersionTag();
}
treeModel.setRoot(root);
model.setRoot(root);
root.setTree(this);
}

View File

@ -15,134 +15,126 @@
*/
package ghidra.app.plugin.core.programtree;
import ghidra.app.cmd.module.ReorderModuleCmd;
import ghidra.program.model.listing.CircularDependencyException;
import ghidra.program.model.listing.DuplicateGroupException;
import ghidra.program.model.listing.ProgramFragment;
import ghidra.program.model.listing.Group;
import ghidra.program.model.listing.ProgramModule;
import ghidra.util.Msg;
import ghidra.util.exception.NotFoundException;
import java.awt.dnd.DnDConstants;
import javax.swing.SwingUtilities;
import javax.swing.tree.TreePath;
import ghidra.app.cmd.module.ReorderModuleCmd;
import ghidra.program.model.listing.*;
import ghidra.util.Msg;
import ghidra.util.exception.NotFoundException;
/**
* Manage the drop operation for reordering modules and fragments.
*/
class ReorderManager {
private ProgramDnDTree tree;
private ProgramDnDTree tree;
ReorderManager(ProgramDnDTree tree) {
this.tree = tree;
}
ReorderManager(ProgramDnDTree tree) {
this.tree = tree;
}
/**
* Return true if the destNode can accept the dropNode.
*/
boolean isDropSiteOk(ProgramNode destNode, ProgramNode dropNode,
int dropAction, int relativeMousePos) {
/**
* Return true if the destNode can accept the dropNode.
*/
boolean isDropSiteOk(ProgramNode destNode, ProgramNode dropNode, int dropAction,
int relativeMousePos) {
ProgramModule mParent = destNode.getParentModule();
Group dragGroup = dropNode.getGroup();
ProgramModule mParent = destNode.getParentModule();
Group dragGroup = dropNode.getGroup();
if (dragGroup.equals(destNode.getGroup())) {
return false; // can't drop a group onto itself
}
if (dragGroup.equals(destNode.getGroup())) {
return false; // can't drop a group onto itself
}
if (mParent == null && relativeMousePos != 0) {
return false;// can't reorder above or below root
}
// if the target node is the same as the parent of the
// fromObject (node to be dropped), then the action
// must be a move, because this is just a reorder of the
// children.
if (destNode.equals(dropNode.getParent())) {
if (dropAction != DnDConstants.ACTION_MOVE) {
return false;
}
return true;
}
if (dropNode.getParent().equals(destNode.getParent()) &&
dropAction != DnDConstants.ACTION_MOVE) {
return false;
}
if (!dropNode.getParent().equals(destNode.getParent())) {
// if parent nodes are different, check to make sure this
// fragment does not already exist as a child of the
// parent of the fromObject
if (dropNode.isFragment() ) {
// if the target node is the same as the parent of the
// fromObject (node to be dropped), then the action
// must be a move, because this is just a reorder of the
// children.
if (destNode.equals(dropNode.getParent())) {
if (dropAction != DnDConstants.ACTION_MOVE) {
return false;
}
return true;
}
if (dropNode.getParent().equals(destNode.getParent()) &&
dropAction != DnDConstants.ACTION_MOVE) {
return false;
}
if (!dropNode.getParent().equals(destNode.getParent())) {
// if parent nodes are different, check to make sure this
// fragment does not already exist as a child of the
// parent of the fromObject
if (dropNode.isFragment()) {
ProgramFragment frag = dropNode.getFragment();
ProgramFragment frag = dropNode.getFragment();
if (mParent != null &&
mParent.contains(frag)) {
return false;
}
// this is the root; make sure fragment does not
// already exist as a child of root...
if (mParent == null &&
destNode.getModule().contains(frag)) {
return false;
}
if (mParent != null && mParent.contains(frag)) {
return false;
}
// this is the root; make sure fragment does not
// already exist as a child of root...
if (mParent == null && destNode.getModule().contains(frag)) {
return false;
}
if (destNode.isModule()) {
ProgramModule dm = destNode.getModule();
if (dm.contains(frag)) {
return false;
}
}
return true;
}
if (destNode.isModule()) {
ProgramModule dm = destNode.getModule();
if (dm.contains(frag)) {
return false;
}
}
return true;
}
// fromObject must be a module...
ProgramModule m = dropNode.getModule();
// fromObject must be a module...
ProgramModule m = dropNode.getModule();
if (mParent != null && (!m.equals(mParent) &&
mParent.contains(m)) || m.equals(mParent) ) {
return false;
}
// this is the root; make sure module does not
// already exist as a child of root...
if (mParent == null &&
destNode.getModule().contains(m) ) {
return false;
}
}
//else parent nodes are the same, so this a reorder
if (mParent != null && (!m.equals(mParent) && mParent.contains(m)) ||
m.equals(mParent)) {
return false;
}
// this is the root; make sure module does not
// already exist as a child of root...
if (mParent == null && destNode.getModule().contains(m)) {
return false;
}
}
//else parent nodes are the same, so this a reorder
if (destNode.isModule() && dropAction == DnDConstants.ACTION_COPY) {
ProgramModule dm = destNode.getModule();
if (dropNode.isModule()) {
if (dm.contains(dropNode.getModule())) {
return false;
}
}
else {
if (dm.contains(dropNode.getFragment())) {
return false;
}
}
}
return true;
}
if (destNode.isModule() && dropAction == DnDConstants.ACTION_COPY) {
ProgramModule dm = destNode.getModule();
if (dropNode.isModule()) {
if (dm.contains(dropNode.getModule())) {
return false;
}
}
else {
if (dm.contains(dropNode.getFragment())) {
return false;
}
}
}
return true;
}
/**
* Add the given data to the destination node.
* @param destNode destination node for the data.
* @param dropNode data to add
*/
void add(ProgramNode destNode, ProgramNode[] dropNodes, int dropAction, int relativeMousePos)
throws NotFoundException, CircularDependencyException, DuplicateGroupException {
/**
* Add the given data to the destination node.
* @param destNode destination node for the data.
* @param dropNode data to add
*/
void add(ProgramNode destNode, ProgramNode[] dropNodes, int dropAction, int relativeMousePos)
throws NotFoundException, CircularDependencyException, DuplicateGroupException {
ProgramModule targetModule = destNode.getModule();
ProgramFragment targetFrag = destNode.getFragment();
if (targetModule == null && targetFrag == null) {
tree.clearDragData();
return; // ignore the drop
}
ProgramModule targetModule = destNode.getModule();
ProgramFragment targetFrag = destNode.getFragment();
if (targetModule == null && targetFrag == null) {
return; // ignore the drop
}
int transactionID = tree.startTransaction("Reorder");
if (transactionID < 0) {
@ -150,71 +142,72 @@ class ReorderManager {
}
try {
for ( int i = 0; i < dropNodes.length; i++ ) {
ProgramNode parentNode = (ProgramNode)destNode.getParent();
reorderNode( destNode, dropAction, relativeMousePos, parentNode, dropNodes[i] );
}
} finally {
for (ProgramNode dropNode : dropNodes) {
ProgramNode parentNode = (ProgramNode) destNode.getParent();
reorderNode(destNode, dropAction, relativeMousePos, parentNode, dropNode);
}
}
finally {
tree.endTransaction(transactionID, true);
}
}
}
}
private void reorderNode( ProgramNode destNode, int dropAction,
int relativeMousePos, ProgramNode parentNode, ProgramNode dropNode )
throws NotFoundException, CircularDependencyException, DuplicateGroupException {
if (!reorderChildren(destNode, dropNode, relativeMousePos)) {
int index;
// this is the case where destNode and dropNode have different parents...
if (relativeMousePos < 0) {
if (parentNode == null) {
return;
}
index = parentNode.getIndex(destNode);
}
else {
// if destNode is a module and if it is expanded,
// then dropNode will go inside the module
if (destNode.isModule() && tree.isExpanded(destNode.getTreePath())) {
index = 0;
destNode = (ProgramNode)destNode.getChildAt(0);
}
else {
// destNode is a module or a fragment, but place
// destNode after it
index = parentNode.getIndex(destNode);
++index;
}
}
addGroup(destNode, dropNode, index, dropAction);
ProgramNode child = (ProgramNode)parentNode.getChildAt(index);
selectNode(dropNode, child);
}
}
private void reorderNode(ProgramNode destNode, int dropAction, int relativeMousePos,
ProgramNode parentNode, ProgramNode dropNode)
throws NotFoundException, CircularDependencyException, DuplicateGroupException {
if (!reorderChildren(destNode, dropNode, relativeMousePos)) {
int index;
// this is the case where destNode and dropNode have different parents...
if (relativeMousePos < 0) {
if (parentNode == null) {
return;
}
index = parentNode.getIndex(destNode);
}
else {
// if destNode is a module and if it is expanded,
// then dropNode will go inside the module
if (destNode.isModule() && tree.isExpanded(destNode.getTreePath())) {
index = 0;
destNode = (ProgramNode) destNode.getChildAt(0);
}
else {
// destNode is a module or a fragment, but place
// destNode after it
index = parentNode.getIndex(destNode);
++index;
}
}
addGroup(destNode, dropNode, index, dropAction);
ProgramNode child = (ProgramNode) parentNode.getChildAt(index);
selectNode(dropNode, child);
}
}
/**
* Reorder children with the same module.
* @return true if reordering was done; false if no changes
* were made
*/
private boolean reorderChildren(ProgramNode destNode, ProgramNode dropNode,
int relativeMousePos) {
private boolean reorderChildren(ProgramNode destNode, ProgramNode dropNode,
int relativeMousePos) {
boolean didReorder = false;
int index = 0;
ProgramNode parentNode = (ProgramNode)destNode.getParent();
ProgramNode parentNode = (ProgramNode) destNode.getParent();
ProgramModule dropParentModule = dropNode.getParentModule();
ProgramModule targetModule = destNode.getModule();
if (parentNode.equals(dropNode.getParent())) {
didReorder = true;
targetModule = parentNode.getModule();
targetModule = parentNode.getModule();
int myIndex = parentNode.getIndex(dropNode);
index = parentNode.getIndex(destNode);
index = parentNode.getIndex(destNode);
if (relativeMousePos < 0 && myIndex < index) {
--index;
}
@ -222,39 +215,38 @@ class ReorderManager {
++index;
}
Group group = dropNode.getGroup();
ReorderModuleCmd cmd = new ReorderModuleCmd(tree.getTreeName(),
targetModule.getName(),
group.getName(), index);
ReorderModuleCmd cmd = new ReorderModuleCmd(tree.getTreeName(), targetModule.getName(),
group.getName(), index);
if (tree.getTool().execute(cmd, tree.getProgram())) {
tree.reorder(group, dropParentModule, index);
ProgramNode child = (ProgramNode)parentNode.getChildAt(index);
tree.reorder(group, dropParentModule, index);
ProgramNode child = (ProgramNode) parentNode.getChildAt(index);
addToSelection(child);
}
}
else {
Msg.showError(this, tree, "Error Moving Child", cmd.getStatusMsg());
}
}
return didReorder;
}
////////////////////////////////////////////////////////////////////
/**
* Match the expansion state for the dropNode and the nodeToSelect
* (which is the new node that just got added). Select the new
* node.
*/
private void selectNode(ProgramNode dropNode, ProgramNode nodeToSelect) {
// apply expansion state of the dropped node to the new node.
tree.matchExpansionState(dropNode, nodeToSelect);
////////////////////////////////////////////////////////////////////
// add the target node to the selection later so
// that the selection shows as being selected;
// without the invokeLater(), the path is not
// rendered as being selected.
/**
* Match the expansion state for the dropNode and the nodeToSelect
* (which is the new node that just got added). Select the new
* node.
*/
private void selectNode(ProgramNode dropNode, ProgramNode nodeToSelect) {
// apply expansion state of the dropped node to the new node.
tree.matchExpansionState(dropNode, nodeToSelect);
// add the target node to the selection later so
// that the selection shows as being selected;
// without the invokeLater(), the path is not
// rendered as being selected.
addToSelection(nodeToSelect);
}
}
/**
* Add the path for the given node to the selection.
@ -263,61 +255,57 @@ class ReorderManager {
final TreePath p = node.getTreePath();
tree.addSelectionPath(p);
Runnable r = new Runnable() {
public void run() {
tree.addSelectionPath(p);
}
@Override
public void run() {
tree.addSelectionPath(p);
}
};
SwingUtilities.invokeLater(r);
}
/**
* Add a new group to the destNode or re-parent the drop Node to
* the destNode's parent (or to root if destNode's parent is null).
* @param destNode drop site for dropped node
* @param dropNode node to drop at destNode
* @param targetIndex new index for node that is added
* @param dropAction DnDConstants.ACTION_COPY or ACTION_MOVE
*/
private void addGroup(ProgramNode destNode, ProgramNode dropNode,
int targetIndex, int dropAction)
throws NotFoundException, CircularDependencyException,
DuplicateGroupException{
Group group = null;
ProgramNode targetParent = (ProgramNode)destNode.getParent();
// first add drop fragment or module
// to target's parent
ProgramModule targetParentModule =
(targetParent != null) ? targetParent.getModule() :
destNode.getModule();
ProgramFragment dropFragment = dropNode.getFragment();
ProgramModule dropModule = dropNode.getModule();
/**
* Add a new group to the destNode or re-parent the drop Node to
* the destNode's parent (or to root if destNode's parent is null).
* @param destNode drop site for dropped node
* @param dropNode node to drop at destNode
* @param targetIndex new index for node that is added
* @param dropAction DnDConstants.ACTION_COPY or ACTION_MOVE
*/
private void addGroup(ProgramNode destNode, ProgramNode dropNode, int targetIndex,
int dropAction)
throws NotFoundException, CircularDependencyException, DuplicateGroupException {
Group group = null;
ProgramNode targetParent = (ProgramNode) destNode.getParent();
if (dropAction == DnDConstants.ACTION_COPY) {
if (dropFragment!= null) {
targetParentModule.add(dropFragment);
group = dropFragment;
}
else {
targetParentModule.add(dropModule);
group = dropModule;
}
}
else {
targetParentModule.reparent(dropNode.getName(),
dropNode.getParentModule());
if (dropFragment != null) {
group = dropFragment;
}
else {
group = dropModule;
}
}
tree.groupAdded(group);
targetParentModule.moveChild(group.getName(),
targetIndex);
tree.reorder(dropNode.getGroup(), targetParentModule,
targetIndex);
}
// first add drop fragment or module
// to target's parent
ProgramModule targetParentModule =
(targetParent != null) ? targetParent.getModule() : destNode.getModule();
ProgramFragment dropFragment = dropNode.getFragment();
ProgramModule dropModule = dropNode.getModule();
if (dropAction == DnDConstants.ACTION_COPY) {
if (dropFragment != null) {
targetParentModule.add(dropFragment);
group = dropFragment;
}
else {
targetParentModule.add(dropModule);
group = dropModule;
}
}
else {
targetParentModule.reparent(dropNode.getName(), dropNode.getParentModule());
if (dropFragment != null) {
group = dropFragment;
}
else {
group = dropModule;
}
}
tree.groupAdded(group);
targetParentModule.moveChild(group.getName(), targetIndex);
tree.reorder(dropNode.getGroup(), targetParentModule, targetIndex);
}
}

View File

@ -112,23 +112,6 @@ public class EditReferencesProvider extends ComponentProviderAdapter
private DropTgtAdapter dropTargetAdapter;
private Droppable dropHandler = new Droppable() {
/**
* Set drag feedback according to the ok parameter.
*
* @param ok true means the drop action is OK
* @param e event that has current state of drag and drop operation
*/
@Override
public void dragUnderFeedback(boolean ok, DropTargetDragEvent e) {
// don't care
}
/**
* Return true if is OK to drop the transferable at the location
* specified the event.
*
* @param e event that has current state of drag and drop operation
*/
@Override
public boolean isDropOk(DropTargetDragEvent e) {
if (currentCodeUnit != null) {
@ -151,24 +134,6 @@ public class EditReferencesProvider extends ComponentProviderAdapter
return false;
}
/**
* Revert back to normal if any drag feedback was set.
*/
@Override
public void undoDragUnderFeedback() {
// don't care
}
/**
* Add the object to the droppable component. The DropTargetAdapter
* calls this method from its drop() method.
*
* @param obj Transferable object that is to be dropped; in this case,
* it is an AddressSetView
* @param e has current state of drop operation
* @param f represents the opaque concept of a data format as would
* appear on a clipboard, during drag and drop.
*/
@Override
public void add(Object obj, DropTargetDropEvent e, DataFlavor f) {
AddressSetView view = ((SelectionTransferData) obj).getAddressSet();

View File

@ -434,61 +434,34 @@ class InstructionPanel extends JPanel implements ChangeListener {
}
private class InstructionPanelDroppable implements Droppable {
/**
* Set drag feedback according to the ok parameter.
* @param ok true means the drop action is OK
* @param e event that has current state of drag and drop operation
*/
@Override
public void dragUnderFeedback(boolean ok, DropTargetDragEvent e) {
// stub
}
/**
* Return true if is OK to drop the transferable at the location
* specified the event.
* @param e event that has current state of drag and drop operation
*/
@Override
public boolean isDropOk(DropTargetDragEvent e) {
Component targetComp = e.getDropTargetContext().getComponent();
if (targetComp instanceof JLabel) {
if (!(targetComp instanceof JLabel)) {
return false;
}
updateActiveIndex(getLabelIndex((JLabel) targetComp), -1);
updateActiveIndex(getLabelIndex((JLabel) targetComp), -1);
try {
Object data = e.getTransferable()
.getTransferData(SelectionTransferable.localProgramSelectionFlavor);
AddressSetView view = ((SelectionTransferData) data).getAddressSet();
if (memory.contains(view)) {
return true;
}
}
catch (UnsupportedFlavorException e1) {
// return false
}
catch (IOException e1) {
// return false
try {
Object data = e.getTransferable()
.getTransferData(SelectionTransferable.localProgramSelectionFlavor);
AddressSetView view = ((SelectionTransferData) data).getAddressSet();
if (memory.contains(view)) {
return true;
}
}
catch (UnsupportedFlavorException e1) {
// return false
}
catch (IOException e1) {
// return false
}
return false;
}
@Override
public void undoDragUnderFeedback() {
// stub
}
/**
* Add the object to the droppable component. The DropTargetAdapter
* calls this method from its drop() method.
* @param obj Transferable object that is to be dropped; in this
* case, it is an AddressSetView
* @param e has current state of drop operation
* @param f represents the opaque concept of a data format as
* would appear on a clipboard, during drag and drop.
*/
@Override
public void add(Object obj, DropTargetDropEvent e, DataFlavor f) {
AddressSetView view = ((SelectionTransferData) obj).getAddressSet();

View File

@ -15,6 +15,13 @@
*/
package ghidra.feature.vt.gui.duallisting;
import java.awt.Point;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.*;
import java.util.ArrayList;
import docking.dnd.*;
import ghidra.app.util.viewer.listingpanel.ListingCodeComparisonPanel;
import ghidra.app.util.viewer.listingpanel.ListingPanel;
import ghidra.feature.vt.api.main.*;
@ -26,14 +33,6 @@ import ghidra.program.util.ProgramLocation;
import ghidra.util.Msg;
import ghidra.util.SystemUtilities;
import java.awt.Point;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.*;
import java.util.ArrayList;
import docking.dnd.*;
public class VTDualListingDragNDropHandler implements Draggable, Droppable {
private final int SOURCE = 0; // left side
@ -52,7 +51,8 @@ public class VTDualListingDragNDropHandler implements Draggable, Droppable {
private DropTgtAdapter dropTargetAdapter;
private DataFlavor[] acceptableFlavors; // data flavors that are valid.
public VTDualListingDragNDropHandler(VTController controller, ListingCodeComparisonPanel dualListingPanel) {
public VTDualListingDragNDropHandler(VTController controller,
ListingCodeComparisonPanel dualListingPanel) {
this.controller = controller;
this.dualListingPanel = dualListingPanel;
listingPanels[SOURCE] = dualListingPanel.getLeftPanel();
@ -79,9 +79,8 @@ public class VTDualListingDragNDropHandler implements Draggable, Droppable {
// set up the destination fieldPanel as a drop target that accepts mark-up items.
dropTargetAdapter =
new DropTgtAdapter(this, DnDConstants.ACTION_COPY_OR_MOVE, acceptableFlavors);
dropTarget =
new DropTarget(listingPanels[DESTINATION].getFieldPanel(),
DnDConstants.ACTION_COPY_OR_MOVE, dropTargetAdapter, true);
dropTarget = new DropTarget(listingPanels[DESTINATION].getFieldPanel(),
DnDConstants.ACTION_COPY_OR_MOVE, dropTargetAdapter, true);
dropTarget.setActive(true);
}
@ -106,9 +105,8 @@ public class VTDualListingDragNDropHandler implements Draggable, Droppable {
}
Point p = e.getDragOrigin();
ProgramLocation programLocation = listingPanels[SOURCE].getProgramLocation(p);
VTMarkupItem markupItem =
controller.getCurrentMarkupForLocation(programLocation,
dualListingPanel.getLeftProgram());
VTMarkupItem markupItem = controller.getCurrentMarkupForLocation(programLocation,
dualListingPanel.getLeftProgram());
if (markupItem == null) {
return false;
}
@ -122,11 +120,6 @@ public class VTDualListingDragNDropHandler implements Draggable, Droppable {
return status == VTMarkupItemDestinationAddressEditStatus.EDITABLE;
}
@Override
public void dragCanceled(DragSourceDropEvent event) {
// nothing to do
}
@Override
public Transferable getTransferable(Point p) {
if (!listingPanels[SOURCE].contains(p)) {
@ -134,25 +127,14 @@ public class VTDualListingDragNDropHandler implements Draggable, Droppable {
}
ProgramLocation programLocation = listingPanels[SOURCE].getProgramLocation(p);
VTMarkupItem markupItem =
controller.getCurrentMarkupForLocation(programLocation,
dualListingPanel.getLeftProgram());
VTMarkupItem markupItem = controller.getCurrentMarkupForLocation(programLocation,
dualListingPanel.getLeftProgram());
if (markupItem == null) {
return null;
}
return new VTMarkupItemTransferable(markupItem);
}
@Override
public void dragUnderFeedback(boolean ok, DropTargetDragEvent e) {
// nothing to do
}
@Override
public void undoDragUnderFeedback() {
// nothing to do
}
@Override
public boolean isDropOk(DropTargetDragEvent e) {
return true;
@ -175,9 +157,9 @@ public class VTDualListingDragNDropHandler implements Draggable, Droppable {
if ((markupItem.getStatus() == VTMarkupItemStatus.SAME) &&
(SystemUtilities.isEqual(markupItem.getDestinationAddress(), newDestinationAddress))) {
// Dropped at expected address and already the same there.
Msg.showInfo(getClass(), dualListingPanel, "Already The Same",
markupType.getDisplayName() +
" was dropped at its expected\ndestination where the value is already the same.");
Msg.showInfo(getClass(), dualListingPanel, "Already The Same", markupType
.getDisplayName() +
" was dropped at its expected\ndestination where the value is already the same.");
return;
}
@ -190,15 +172,9 @@ public class VTDualListingDragNDropHandler implements Draggable, Droppable {
// newDestinationAddress);
// Use the following if you want to set the address and apply the markup item using the default action.
ApplyMarkupAtDestinationAddressTask task =
new ApplyMarkupAtDestinationAddressTask(controller.getSession(), arrayList,
newDestinationAddress, controller.getOptions());
ApplyMarkupAtDestinationAddressTask task = new ApplyMarkupAtDestinationAddressTask(
controller.getSession(), arrayList, newDestinationAddress, controller.getOptions());
controller.runVTTask(task);
}
@Override
public void move() {
// nothing to do
}
}

View File

@ -15,87 +15,65 @@
*/
package docking.dnd;
import ghidra.util.Msg;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.*;
import java.awt.event.InputEvent;
import ghidra.util.Msg;
/**
* This class receives notification when the user intitiates a
* drag and drop operation; it is responsible for getting the
* <code>Transferable</code> and telling the <code>DragSource</code> to
* This class receives notification when the user initiates a drag and drop operation; it is
* responsible for getting the <code>Transferable</code> and telling the <code>DragSource</code> to
* start the drag.
*/
public class DragGestureAdapter implements DragGestureListener {
private Draggable dragComponent;
// private Cursor cursor = DragSource.DefaultCopyNoDrop;
// private static Transferable transferable;
private Draggable dragComponent;
/**
* Construct a new DragGestureAdapter
*
* @param dragComponent Component that can support drag operations
*/
public DragGestureAdapter(Draggable dragComponent) {
this.dragComponent = dragComponent;
}
/**
* A <code>DragGestureRecognizer</code> has detected a
* platform-dependent Drag and Drop action initiating gesture
* and is notifying this Listener in order for it to initiate
* the action for the user.
* <p>The <code>DragGestureRecognizer</code> hides the platform-specific
* events that initate a drag and drop operation.
*
* @param e event describing the gesture that has just occurred
*/
public void dragGestureRecognized(DragGestureEvent e) {
public DragGestureAdapter(Draggable dragComponent) {
this.dragComponent = dragComponent;
}
// check input event: if any button other than MB1 is pressed,
// don't attempt to process the drag and drop event.
InputEvent ie = e.getTriggerEvent();
int modifiers = ie.getModifiers();
if ((modifiers & InputEvent.BUTTON2_MASK) != 0 ||
(modifiers & InputEvent.BUTTON3_MASK) != 0) {
return;
}
int dragAction = dragComponent.getDragAction();
if ( ((e.getDragAction() & dragAction) == 0) ||
!dragComponent.isStartDragOk(e)) {
return;
}
Transferable t = dragComponent.getTransferable(e.getDragOrigin());
DragSourceListener l = dragComponent.getDragSourceListener();
if (t == null || l == null) {
return;
}
// transferable = t;
try {
e.startDrag(DragSource.DefaultCopyNoDrop, t, l);
} catch (InvalidDnDOperationException exc) {
// the Drag and Drop system is unable to initiate a drag operation
Msg.error(this, "Exception occurred during drag initiation: " + exc, exc);
@Override
public void dragGestureRecognized(DragGestureEvent e) {
// check input event: if any button other than MB1 is pressed,
// don't attempt to process the drag and drop event.
InputEvent ie = e.getTriggerEvent();
int modifiers = ie.getModifiersEx();
if ((modifiers & InputEvent.BUTTON2_DOWN_MASK) != 0 ||
(modifiers & InputEvent.BUTTON3_DOWN_MASK) != 0) {
return;
}
int dragAction = dragComponent.getDragAction();
if (((e.getDragAction() & dragAction) == 0) || !dragComponent.isStartDragOk(e)) {
return;
}
DragSourceListener l = dragComponent.getDragSourceListener();
if (l == null) {
return;
}
Transferable t = dragComponent.getTransferable(e.getDragOrigin());
if (t == null) {
return;
}
try {
e.startDrag(DragSource.DefaultCopyNoDrop, t, l);
}
catch (InvalidDnDOperationException exc) {
// the Drag and Drop system is unable to initiate a drag operation
Msg.error(this, "Exception occurred during drag initiation: " + exc, exc);
}
}
// transferable = null;
}
}
// /**
// * Get the transferable that is being dragged.
// */
// static Transferable getTransferable() {
// return transferable;
// }
// /**
// * Clear the transferable object that is being dragged.
// */
// static void clearTransferable() {
// transferable = null;
// }
}

View File

@ -19,137 +19,109 @@ import java.awt.Cursor;
import java.awt.dnd.*;
/**
* Adapter class that receives notifications in order to
* provide drag over effects.
* <p> When the operation ends, this class receives a
* <code>dragDropEnd</code> message, and is responsible for
* checking the success of the operation. If the operation was
* successful, and if it was a Move, then
* this class will remove the source data.
* Adapter class that receives notifications in order to provide drag over effects.
*
* <p>When the operation ends, this class receives a <code>dragDropEnd</code> message, and is
* responsible for checking the success of the operation. If the operation was successful, and if it
* was a Move, then this class will remove the source data.
*/
public class DragSrcAdapter implements DragSourceListener {
protected Draggable dragComponent;
private Cursor currentCursor;
private Cursor copyDropCursor=DragSource.DefaultCopyDrop;
private Cursor copyNoDropCursor=DragSource.DefaultCopyNoDrop;
private Cursor moveDropCursor =DragSource.DefaultMoveDrop;
private Cursor moveNoDropCursor=DragSource.DefaultMoveNoDrop;
private Cursor linkDropCursor =DragSource.DefaultLinkDrop;
private Cursor linkNoDropCursor = DragSource.DefaultLinkNoDrop;
private static final Cursor COPY_DROP_CURSOR = DragSource.DefaultCopyDrop;
private static final Cursor COPY_NO_DROP_CURSOR = DragSource.DefaultCopyNoDrop;
private static final Cursor MOVE_DROP_CURSOR = DragSource.DefaultMoveDrop;
private static final Cursor MOVE_NO_DROP_CURSOR = DragSource.DefaultMoveNoDrop;
private static final Cursor LINK_DROP_CURSOR = DragSource.DefaultLinkDrop;
private static final Cursor LINK_NO_DROP_CURSOR = DragSource.DefaultLinkNoDrop;
/**
* Constructor
* @param dragComponent component that can be dragged.
*/
public DragSrcAdapter(Draggable dragComponent) {
this.dragComponent = dragComponent;
}
/**
* Called when the drag-drop operation completes.
* Calls the drag component's move() method if the action is a
* move operation.
*/
public void dragDropEnd(DragSourceDropEvent e) {
private Cursor currentCursor;
protected Draggable dragComponent;
if (!e.getDropSuccess()) {
dragComponent.dragCanceled(e);
// DragGestureAdapter.clearTransferable();
return;
}
int dropOp = e.getDropAction();
int dragAction = dragComponent.getDragAction();
/**
* Constructor
* @param dragComponent component that can be dragged.
*/
public DragSrcAdapter(Draggable dragComponent) {
this.dragComponent = dragComponent;
}
if ((dropOp & DnDConstants.ACTION_MOVE) == DnDConstants.ACTION_MOVE &&
(dragAction & DnDConstants.ACTION_MOVE) != 0) {
dragComponent.move();
// DragGestureAdapter.clearTransferable();
}
}
/**
* Called as the hotspot enters a platform dependent drop site.
*/
public void dragEnter(DragSourceDragEvent e) {
@Override
public void dragDropEnd(DragSourceDropEvent e) {
dragComponent.dragFinished(!e.getDropSuccess());
}
setDragOverFeedback(e);
}
/**
* Called as the hotspot moves over a platform dependent drop site.
*/
public void dragOver(DragSourceDragEvent e) {
@Override
public void dragEnter(DragSourceDragEvent e) {
setDragOverFeedback(e);
}
setDragOverFeedback(e);
}
@Override
public void dragOver(DragSourceDragEvent e) {
setDragOverFeedback(e);
}
/**
* Called as the hotspot exits a platform dependent drop site.
*/
public void dragExit(DragSourceEvent e) {
@Override
public void dragExit(DragSourceEvent e) {
DragSourceContext context = e.getDragSourceContext();
context.setCursor(null); // bug workaround
currentCursor = copyNoDropCursor;
context.setCursor(currentCursor);
}
/**
* Drop action changed, i.e., ctrl key pressed during drag to
* change to a copy operation.
*/
public void dropActionChanged(DragSourceDragEvent e) {
setDragOverFeedback(e);
}
DragSourceContext context = e.getDragSourceContext();
context.setCursor(null); // bug workaround
currentCursor = COPY_NO_DROP_CURSOR;
context.setCursor(currentCursor);
}
//////////////////////////////////////////////////////////////////////
// *** private methods ***
//////////////////////////////////////////////////////////////////////
@Override
public void dropActionChanged(DragSourceDragEvent e) {
setDragOverFeedback(e);
}
/**
* Sets the cursor according to the actions that are legal.
*/
protected void setDragOverFeedback(DragSourceDragEvent e) {
DragSourceContext context = e.getDragSourceContext();
int dropOp = e.getDropAction();
int targetAction = e.getTargetActions();
int action = dropOp & targetAction;
Cursor c = null;
/**
* Sets the cursor according to the actions that are legal.
* @param e the event
*/
protected void setDragOverFeedback(DragSourceDragEvent e) {
DragSourceContext context = e.getDragSourceContext();
int dropOp = e.getDropAction();
int targetAction = e.getTargetActions();
int action = dropOp & targetAction;
Cursor c = null;
if (action == DnDConstants.ACTION_NONE) {
// drop not possible
if ((dropOp & DnDConstants.ACTION_LINK) == DnDConstants.ACTION_LINK) {
c = linkNoDropCursor;
}
else if ((dropOp & DnDConstants.ACTION_MOVE) == DnDConstants.ACTION_MOVE) {
c = moveNoDropCursor;
}
else {
c = copyNoDropCursor;
}
}
else {
// drop is possible
c = getDropOkCursor(action);
}
context.setCursor(null); // bug workaround...
currentCursor = c;
context.setCursor(c);
}
/**
* Get the cursor for an "OK" drop.
* @param action action for the drag operation (copy, move, link)
* @return cursor that is appropriate for the give action
*/
protected Cursor getDropOkCursor(int action) {
Cursor c;
if ((action & DnDConstants.ACTION_LINK) == DnDConstants.ACTION_LINK) {
c = linkDropCursor;
}
else if ((action & DnDConstants.ACTION_MOVE) == DnDConstants.ACTION_MOVE) {
c = moveDropCursor;
if (action == DnDConstants.ACTION_NONE) {
// drop not possible
if ((dropOp & DnDConstants.ACTION_LINK) == DnDConstants.ACTION_LINK) {
c = LINK_NO_DROP_CURSOR;
}
else if ((dropOp & DnDConstants.ACTION_MOVE) == DnDConstants.ACTION_MOVE) {
c = MOVE_NO_DROP_CURSOR;
}
else {
c = COPY_NO_DROP_CURSOR;
}
}
else {
c = copyDropCursor;
// drop is possible
c = getDropOkCursor(action);
}
context.setCursor(null); // bug workaround...
currentCursor = c;
context.setCursor(c);
}
/**
* Get the cursor for an "OK" drop.
* @param action action for the drag operation (copy, move, link)
* @return cursor that is appropriate for the give action
*/
protected Cursor getDropOkCursor(int action) {
if ((action & DnDConstants.ACTION_LINK) == DnDConstants.ACTION_LINK) {
return LINK_DROP_CURSOR;
}
else if ((action & DnDConstants.ACTION_MOVE) == DnDConstants.ACTION_MOVE) {
return MOVE_DROP_CURSOR;
}
else {
return COPY_DROP_CURSOR;
}
return c;
}
}

View File

@ -15,7 +15,7 @@
*/
package docking.dnd;
import java.awt.Point;
import java.awt.*;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.*;
@ -23,37 +23,30 @@ import java.awt.dnd.*;
* Interface to define a drag source.
*/
public interface Draggable {
/**
* Return true if the object at the location in the DragGesture
* event is draggable.
/**
* Return true if the object at the location in the DragGesture event is draggable.
*
* @param e event passed to a DragGestureListener via its
* dragGestureRecognized() method when a particular DragGestureRecognizer
* detects a platform dependent Drag and Drop action initiating
* gesture has occurred on the Component it is tracking.
* @return true if a drag can be starts
* @see docking.dnd.DragGestureAdapter
*/
public boolean isStartDragOk(DragGestureEvent e);
/**
* Called by the DragGestureAdapter to start the drag.
*/
public DragSourceListener getDragSourceListener();
/**
* Do the move operation; called when the drag and drop operation
* completes.
* @see docking.dnd.DragSrcAdapter#dragDropEnd
*/
public void move();
/**
* Method called when the drag operation exits the drop target
* without dropping.
* @param event TODO
*/
public void dragCanceled(DragSourceDropEvent event);
*/
public boolean isStartDragOk(DragGestureEvent e);
/**
* Called when the drag and drop operation completes.
*
* <p>Clients can use this callback to reset visual state.
* @param cancelled true if the drag operation was cancelled
*
* @see docking.dnd.DragSrcAdapter#dragDropEnd(DragSourceDropEvent)
*/
public default void dragFinished(boolean cancelled) {
// stub
}
/**
* Get the drag actions supported by this drag source:
@ -65,12 +58,20 @@ public interface Draggable {
*
* @return the drag actions
*/
public int getDragAction();
/**
* Get the object to transfer.
public int getDragAction();
/**
* Get the object to transfer.
* @param p location of object to transfer
* @return object to transfer
*/
public Transferable getTransferable(Point p);
*/
public Transferable getTransferable(Point p);
/**
* Called by the DragGestureAdapter when the drag is started.
* @return the listener
* @see DragGestureEvent#startDrag(Cursor, Image, Point, Transferable, DragSourceListener)
*/
public DragSourceListener getDragSourceListener();
}

View File

@ -31,18 +31,6 @@ public interface Droppable {
*/
public boolean isDropOk(DropTargetDragEvent e);
/**
* Set drag feedback according to the ok parameter
* @param ok true means the drop action is OK
* @param e event that has current state of drag and drop operation
*/
public void dragUnderFeedback(boolean ok, DropTargetDragEvent e);
/**
* Revert back to normal if any drag feedback was set
*/
public void undoDragUnderFeedback();
/**
* Add the object to the droppable component. The DropTargetAdapter
* calls this method from its drop() method.
@ -54,4 +42,20 @@ public interface Droppable {
*/
public void add(Object obj, DropTargetDropEvent e, DataFlavor f);
/**
* Set drag feedback according to the ok parameter
* @param ok true means the drop action is OK
* @param e event that has current state of drag and drop operation
*/
public default void dragUnderFeedback(boolean ok, DropTargetDragEvent e) {
// stub
}
/**
* Revert back to normal if any drag feedback was set
*/
public default void undoDragUnderFeedback() {
// stub
}
}

View File

@ -259,6 +259,20 @@ public class GhidraFileChooserPanel extends JPanel implements Droppable {
return file;
}
/**
* Sets the <code>GhidraFileChooser</code> to allow the user to just
* select files, just select
* directories, or select both files and directories. The default is
* <code>GhidraFileChooserMode.FILES_ONLY</code>.
*
* @param mode the type of files to be displayed
* @exception IllegalArgumentException if <code>mode</code> is an
* illegal Dialog mode
*/
public void setFileSelectionMode(GhidraFileChooserMode mode) {
this.selectionMode = mode;
}
private void setupDragAndDrop() {
acceptableFlavors = new DataFlavor[] { DataFlavor.javaFileListFlavor, };
@ -287,42 +301,8 @@ public class GhidraFileChooserPanel extends JPanel implements Droppable {
}
}
/**
* Sets the <code>GhidraFileChooser</code> to allow the user to just
* select files, just select
* directories, or select both files and directories. The default is
* <code>GhidraFileChooserMode.FILES_ONLY</code>.
*
* @param mode the type of files to be displayed
* @exception IllegalArgumentException if <code>mode</code> is an
* illegal Dialog mode
*/
public void setFileSelectionMode(GhidraFileChooserMode mode) {
this.selectionMode = mode;
}
/**
* @see docking.dnd.Droppable#dragUnderFeedback(boolean, java.awt.dnd.DropTargetDragEvent)
*/
@Override
public void dragUnderFeedback(boolean ok, DropTargetDragEvent e) {
// don't care
}
/**
* @see docking.dnd.Droppable#isDropOk(java.awt.dnd.DropTargetDragEvent)
*/
@Override
public boolean isDropOk(DropTargetDragEvent e) {
return true;
}
/**
* @see docking.dnd.Droppable#undoDragUnderFeedback()
*/
@Override
public void undoDragUnderFeedback() {
// don't care
}
}

View File

@ -97,16 +97,6 @@ public class FileOpenDropHandler implements DropTargetHandler, Droppable, Contai
}
}
@Override
public void dragUnderFeedback(boolean ok, DropTargetDragEvent e) {
// nothing to display or do
}
@Override
public void undoDragUnderFeedback() {
// nothing to display or do
}
private void initializeComponents(Component comp) {
if (comp instanceof CellRendererPane) {
return;

View File

@ -85,7 +85,6 @@ public class FrontEndPlugin extends Plugin
private ProjectToolBar toolBar;
private ProjectDataTreePanel dataTreePanel;
private ProjectDataTablePanel dataTablePanel;
private ToolButtonTransferable toolButtonTransferable;
private WorkspacePanel workspacePanel;
private Project activeProject;
private ProjectManager projectManager;
@ -613,17 +612,6 @@ public class FrontEndPlugin extends Plugin
return actionContext;
}
ToolButtonTransferable getToolButtonTransferable() {
return toolButtonTransferable;
}
void setToolButtonTransferable(ToolButtonTransferable t) {
if (t == null && toolButtonTransferable != null) {
toolButtonTransferable.clearTransferData();
}
toolButtonTransferable = t;
}
void updateToolConnectionDialog() {
toolActionManager.updateConnectionDialog();
}

View File

@ -151,11 +151,6 @@ class ToolButton extends EmptyBorderButton implements Draggable, Droppable {
// Droppable interface
//==================================================================================================
@Override
public void dragUnderFeedback(boolean ok, DropTargetDragEvent e) {
// nothing to do
}
@Override
public boolean isDropOk(DropTargetDragEvent e) {
DataFlavor[] flavors = e.getCurrentDataFlavors();
@ -219,11 +214,6 @@ class ToolButton extends EmptyBorderButton implements Draggable, Droppable {
return fileList.size() > 0;
}
@Override
public void undoDragUnderFeedback() {
// nothing to do
}
@Override
public void add(Object obj, DropTargetDropEvent event, DataFlavor f) {
@ -255,8 +245,8 @@ class ToolButton extends EmptyBorderButton implements Draggable, Droppable {
}
}
}
// else assume ToolButtonTransferable
else {
plugin.setToolButtonTransferable(null);
ToolButton toolButton = (ToolButton) obj;
resetButtonAfterDrag(toolButton);
addFromToolButton(toolButton);
@ -264,7 +254,6 @@ class ToolButton extends EmptyBorderButton implements Draggable, Droppable {
}
private void addFromToolButton(ToolButton toolButton) {
plugin.setToolButtonTransferable(null);
PluginTool tool = null;
if (associatedRunningTool != null && toolButton.associatedRunningTool != null) {
final PluginTool t2 = toolButton.associatedRunningTool;
@ -353,51 +342,13 @@ class ToolButton extends EmptyBorderButton implements Draggable, Droppable {
clearBorder();
}
/**
* Method called when the drag operation exits the drop target
* without dropping.
*/
@Override
public void dragCanceled(DragSourceDropEvent event) {
plugin.setToolButtonTransferable(null);
public void dragFinished(boolean wasCancelled) {
resetButtonAfterDrag(this);
// Unusual Code Alert!
// When dragging, we do not get mouseReleased() events, which we use to launch tools.
// In this case, the drag was cancelled; if we are over ourselves, then simulate
// the Java-eaten mouseReleased() call
Container parent = getParent();
if (parent == null) {
return;
}
Point point = event.getLocation();
if (point == null) {
return;
}
SwingUtilities.convertPointFromScreen(point, parent);
Component componentUnderMouse =
SwingUtilities.getDeepestComponentAt(parent, point.x, point.y);
if (componentUnderMouse == this) {
handleMouseReleased();
}
}
/**
* Return true if the object at the location in the DragGesture
* event is draggable.
*
* @param e event passed to a DragGestureListener via its
* dragGestureRecognized() method when a particular DragGestureRecognizer
* detects a platform dependent Drag and Drop action initiating
* gesture has occurred on the Component it is tracking.
* @see docking.dnd.DragGestureAdapter
*/
@Override
public boolean isStartDragOk(DragGestureEvent e) {
plugin.setToolButtonTransferable(new ToolButtonTransferable(this));
return true;
}
@ -408,12 +359,7 @@ class ToolButton extends EmptyBorderButton implements Draggable, Droppable {
@Override
public Transferable getTransferable(Point p) {
return plugin.getToolButtonTransferable();
}
@Override
public void move() {
resetButtonAfterDrag(this);
return new ToolButtonTransferable(this);
}
@Override
@ -610,10 +556,6 @@ class ToolButton extends EmptyBorderButton implements Draggable, Droppable {
help.registerHelp(this, new HelpLocation(ToolConstants.TOOL_HELP_TOPIC, anchorTag));
}
private void handleMouseReleased() {
activateTool();
}
//==================================================================================================
// Inner Classes
//==================================================================================================

View File

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,92 +15,79 @@
*/
package ghidra.framework.main;
import ghidra.util.Msg;
import java.awt.datatransfer.*;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import docking.dnd.GenericDataFlavor;
import ghidra.util.Msg;
/**
* Defines data that is available for drag/drop and clipboard transfers.
* The data is a ToolButton object.
*/
public class ToolButtonTransferable implements Transferable, ClipboardOwner {
public static DataFlavor localToolButtonFlavor = createLocalToolButtonFlavor();
// create a data flavor that is a tool button
private static DataFlavor createLocalToolButtonFlavor() {
try {
return new GenericDataFlavor(
DataFlavor.javaJVMLocalObjectMimeType+
"; class=ghidra.framework.main.ToolButton",
"Local tool button object");
}catch (Exception e) {
Msg.showError(ToolButtonTransferable.class, null, null, null, e);
}
return null;
}
private static DataFlavor []flavors=
{localToolButtonFlavor};
private static List flavorList = Arrays.asList(flavors);
private ToolButton button;
/**
* Constructor
*/
ToolButtonTransferable(ToolButton button) {
this.button = button;
}
/**
* Return all data flavors that this class supports.
*/
public synchronized DataFlavor []getTransferDataFlavors() {
return flavors;
}
/**
* Return whether the specifed data flavor is supported.
*/
public boolean isDataFlavorSupported(DataFlavor f) {
return flavorList.contains(f);
}
/**
* Return the transfer data with the given data flavor.
*/
public synchronized Object getTransferData(DataFlavor f)
throws UnsupportedFlavorException, IOException {
if (f.equals(localToolButtonFlavor)) {
return button;
}
throw new UnsupportedFlavorException(f);
}
/**
* Get the string representation for this transferable.
*/
@Override
public String toString() {
return "ToolButtonTransferable";
}
/**
* ClipboardOwner interface method.
*/
public void lostOwnership(Clipboard clipboard, Transferable contents) {
}
/**
* Clear the tool button that is being transferred.
*/
void clearTransferData() {
button = null;
}
public static DataFlavor localToolButtonFlavor = createLocalToolButtonFlavor();
// create a data flavor that is a tool button
private static DataFlavor createLocalToolButtonFlavor() {
try {
return new GenericDataFlavor(
DataFlavor.javaJVMLocalObjectMimeType + "; class=ghidra.framework.main.ToolButton",
"Local tool button object");
}
catch (Exception e) {
Msg.showError(ToolButtonTransferable.class, null, null, null, e);
}
return null;
}
private static DataFlavor[] flavors = { localToolButtonFlavor };
private ToolButton button;
/**
* Constructor
* @param button the button
*/
ToolButtonTransferable(ToolButton button) {
this.button = button;
}
@Override
public synchronized DataFlavor[] getTransferDataFlavors() {
return flavors;
}
@Override
public boolean isDataFlavorSupported(DataFlavor f) {
return localToolButtonFlavor.equals(f);
}
@Override
public synchronized Object getTransferData(DataFlavor f)
throws UnsupportedFlavorException, IOException {
if (f.equals(localToolButtonFlavor)) {
return button;
}
throw new UnsupportedFlavorException(f);
}
@Override
public String toString() {
return "ToolButtonTransferable";
}
@Override
public void lostOwnership(Clipboard clipboard, Transferable contents) {
// stub
}
/**
* Clear the tool button that is being transferred.
*/
void clearTransferData() {
button = null;
}
}

View File

@ -175,11 +175,6 @@ public class VersionHistoryPanel extends JPanel implements Draggable {
return DomainFile.DEFAULT_VERSION;
}
@Override
public void dragCanceled(DragSourceDropEvent event) {
// no-op
}
@Override
public int getDragAction() {
return dragAction;
@ -209,11 +204,6 @@ public class VersionHistoryPanel extends JPanel implements Draggable {
return false;
}
@Override
public void move() {
// no-op
}
// For Junit tests
VersionHistoryTableModel getVersionHistoryTableModel() {
return tableModel;