mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 19:42:36 +02:00
GP-1913 - Updated data type synchronization workflow by adding a new action and a home button to the structure editor. Added action to the composite editors and enum editor to show the type being edited in the Data Type Manager's tree.
This commit is contained in:
parent
d7f9cdfe5c
commit
d9af59df1a
53 changed files with 955 additions and 453 deletions
|
@ -30,24 +30,24 @@ import docking.widgets.GComponent;
|
|||
|
||||
/**
|
||||
* GhidraComboBox adds the following features:
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* 1) ActionListeners are only invoked when the <Enter> key is pressed within the text-field
|
||||
* of the combo-box. In normal JComboBox case, the ActionListeners are notified when an item is
|
||||
* selected from the list.
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* 2) Adds the auto-completion feature. As a user types in the field, the combo box suggest the
|
||||
* nearest matching entry in the combo box model.
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* It also fixes the following bug:
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* A normal JComboBox has a problem (feature?) that if you have a dialog with a button and
|
||||
* JComboBox and you edit the comboText field and then hit the button, the button sometimes does
|
||||
* not work.
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* When the combobox loses focus, and its text has changed, it generates an actionPerformed event
|
||||
* as though the user pressed <Enter> in the combo text field. This has a bizarre effect if
|
||||
|
@ -55,12 +55,12 @@ import docking.widgets.GComponent;
|
|||
* enablement state of the button that you pressed (which caused the text field to lose focus) in
|
||||
* that you end up changing the button's internal state(by calling setEnabled(true or false)) in
|
||||
* the middle of the button press.
|
||||
*
|
||||
*
|
||||
* @param <E> the item type
|
||||
*/
|
||||
public class GhidraComboBox<E> extends JComboBox<E> implements GComponent {
|
||||
private ArrayList<ActionListener> listeners = new ArrayList<>();
|
||||
private ArrayList<DocumentListener> docListeners = new ArrayList<>();
|
||||
private List<ActionListener> listeners = new ArrayList<>();
|
||||
private List<DocumentListener> docListeners = new ArrayList<>();
|
||||
private boolean setSelectedFlag = false;
|
||||
|
||||
private boolean forwardEnter;
|
||||
|
@ -70,7 +70,6 @@ public class GhidraComboBox<E> extends JComboBox<E> implements GComponent {
|
|||
* Default constructor.
|
||||
*/
|
||||
public GhidraComboBox() {
|
||||
super();
|
||||
init();
|
||||
}
|
||||
|
||||
|
@ -164,7 +163,7 @@ public class GhidraComboBox<E> extends JComboBox<E> implements GComponent {
|
|||
* {@link GhidraComboBox} will add an action listener to handle <Enter> actions.
|
||||
* <p>
|
||||
* To re-enable the default behavior, set the <code>forwardEnter</code> value to true.
|
||||
*
|
||||
*
|
||||
* @param forwardEnter true to enable default <Enter> key handling.
|
||||
*/
|
||||
public void setEnterKeyForwarding(boolean forwardEnter) {
|
||||
|
@ -198,7 +197,7 @@ public class GhidraComboBox<E> extends JComboBox<E> implements GComponent {
|
|||
* editor used</b>. By default the editor for combo boxes is a text field. This method is
|
||||
* a convenience for the user to set the number of columns on that text field, which updates
|
||||
* the preferred size of the combo box.
|
||||
*
|
||||
*
|
||||
* @param columnCount The number of columns for the text field editor
|
||||
* @see JTextField#setColumns(int)
|
||||
*/
|
||||
|
@ -216,11 +215,11 @@ public class GhidraComboBox<E> extends JComboBox<E> implements GComponent {
|
|||
* <li>The user deletes the text</li>
|
||||
* <li>setSelectedItem(Object) method is called with the same item</li>
|
||||
* </ol>
|
||||
*
|
||||
*
|
||||
* In that above series of steps, the text will still be empty, as the user deleted it *and*
|
||||
* the call to setSelectedItem(Object) had no effect because the base class assumed that the
|
||||
* item is already selected.
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* This method exists to make sure, in that case, that the text of the field matches the
|
||||
* selected item.
|
||||
|
@ -256,6 +255,13 @@ public class GhidraComboBox<E> extends JComboBox<E> implements GComponent {
|
|||
model.addElement(obj);
|
||||
}
|
||||
|
||||
public void addToModel(Collection<E> items) {
|
||||
DefaultComboBoxModel<E> model = (DefaultComboBoxModel<E>) getModel();
|
||||
for (E e : items) {
|
||||
model.addElement(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean containsItem(E obj) {
|
||||
DefaultComboBoxModel<E> model = (DefaultComboBoxModel<E>) getModel();
|
||||
return model.getIndexOf(obj) != -1;
|
||||
|
|
|
@ -28,7 +28,6 @@ import docking.widgets.label.GHtmlLabel;
|
|||
|
||||
/**
|
||||
* A dialog that has text fields to get user input.
|
||||
*
|
||||
*/
|
||||
public class InputWithChoicesDialog extends DialogComponentProvider {
|
||||
|
||||
|
@ -37,19 +36,17 @@ public class InputWithChoicesDialog extends DialogComponentProvider {
|
|||
private boolean allowEdits;
|
||||
|
||||
/**
|
||||
* Creates a provider for a generic input dialog with the specified title,
|
||||
* a label and a editable comboBox pre-populated with selectable values. The user
|
||||
* can check the value of {@link #isCanceled()} to know whether or not
|
||||
* the user canceled the operation. To get the user selected value use the
|
||||
* {@link #getValue()} value(s) entered by the user. If the user cancelled the operation, then
|
||||
* null will be returned from <code>getValue()</code>.
|
||||
* <P>
|
||||
* Creates a provider for a generic input dialog with the specified title, a label and a
|
||||
* editable comboBox pre-populated with selectable values. The user can check the value of
|
||||
* {@link #isCanceled()} to know whether or not the user canceled the operation. To get the
|
||||
* user selected value use the {@link #getValue()} value(s) entered by the user. If the user
|
||||
* cancelled the operation, then null will be returned from {@link #getValue()}.
|
||||
*
|
||||
* @param dialogTitle used as the name of the dialog's title bar
|
||||
* @param label value to use for the label of the text field
|
||||
* @param optionValues values to populate the combo box
|
||||
* @param initialValue the initial value - can be null
|
||||
* @param messageIcon the icon to display on the dialog--can be null
|
||||
* @param initialValue the initial value; may be null
|
||||
* @param messageIcon the icon to display on the dialog; may be null
|
||||
*/
|
||||
public InputWithChoicesDialog(String dialogTitle, String label, String[] optionValues,
|
||||
String initialValue, Icon messageIcon) {
|
||||
|
@ -67,20 +64,18 @@ public class InputWithChoicesDialog extends DialogComponentProvider {
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates a provider for a generic input dialog with the specified title,
|
||||
* a label and a editable comboBox pre-populated with selectable values. The user
|
||||
* can check the value of {@link #isCanceled()} to know whether or not
|
||||
* the user canceled the operation. To get the user selected value use the
|
||||
* {@link #getValue()} value(s) entered by the user. If the user cancelled the operation, then
|
||||
* null will be returned from <code>getValue()</code>.
|
||||
* <P>
|
||||
* Creates a provider for a generic input dialog with the specified title, a label and a
|
||||
* editable comboBox pre-populated with selectable values. The user can check the value of
|
||||
* {@link #isCanceled()} to know whether or not the user canceled the operation. To get the
|
||||
* user selected value use the {@link #getValue()} value(s) entered by the user. If the user
|
||||
* cancelled the operation, then null will be returned from {@link #getValue()}.
|
||||
*
|
||||
* @param dialogTitle used as the name of the dialog's title bar
|
||||
* @param label value to use for the label of the text field
|
||||
* @param optionValues values to populate the combo box
|
||||
* @param initialValue the initial value - can be null
|
||||
* @param allowEdits true allows the user to add custom entries to the combo box by entering text
|
||||
* @param messageIcon the icon to display on the dialog--can be null
|
||||
* @param initialValue the initial value; may be null
|
||||
* @param allowEdits true allows the user to add custom entries by entering text
|
||||
* @param messageIcon the icon to display on the dialog; may be null
|
||||
*/
|
||||
public InputWithChoicesDialog(String dialogTitle, String label, String[] optionValues,
|
||||
String initialValue, boolean allowEdits, Icon messageIcon) {
|
||||
|
@ -103,7 +98,7 @@ public class InputWithChoicesDialog extends DialogComponentProvider {
|
|||
}
|
||||
|
||||
/**
|
||||
* completes the construction of the gui for this dialog
|
||||
* Completes the construction of the gui for this dialog
|
||||
*/
|
||||
private void buildMainPanel(String labelText, String[] optionValues, String initialValue,
|
||||
Icon messageIcon) {
|
||||
|
@ -168,13 +163,15 @@ public class InputWithChoicesDialog extends DialogComponentProvider {
|
|||
|
||||
/**
|
||||
* Returns if this dialog is canceled.
|
||||
* @return true if canceled
|
||||
*/
|
||||
public boolean isCanceled() {
|
||||
return isCanceled;
|
||||
}
|
||||
|
||||
/**
|
||||
* return the value of the first combo box
|
||||
* Return the value of the first combo box.
|
||||
* @return the value
|
||||
*/
|
||||
public String getValue() {
|
||||
if (isCanceled) {
|
||||
|
@ -192,8 +189,7 @@ public class InputWithChoicesDialog extends DialogComponentProvider {
|
|||
/**
|
||||
* Set the current choice to value.
|
||||
* @param value updated choice
|
||||
* @throws NoSuchElementException if choice does not permit edits and value is
|
||||
* not a valid choice.
|
||||
* @throws NoSuchElementException if edits not permitted and value is not a valid choice
|
||||
*/
|
||||
public void setValue(String value) {
|
||||
combo.setSelectedItem(value);
|
||||
|
|
|
@ -27,6 +27,7 @@ import java.util.*;
|
|||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.Timer;
|
||||
|
@ -334,7 +335,7 @@ public class GTree extends JPanel implements BusyListener {
|
|||
* <p>
|
||||
* <b>Note: </b>See the usage note at the header of this class concerning how tree state
|
||||
* is used relative to the <code>equals()</code> method.
|
||||
*
|
||||
*
|
||||
* @param state the state to restore
|
||||
*
|
||||
* @see #getTreeState()
|
||||
|
@ -582,7 +583,7 @@ public class GTree extends JPanel implements BusyListener {
|
|||
* been replaced by a new node that is equal, but a different instance. One way this happens
|
||||
* is if the tree is filtered and therefor the displayed nodes are clones of the model nodes.
|
||||
* This can also happen if the tree nodes are rebuilt for some reason.
|
||||
*
|
||||
*
|
||||
* @param node the node
|
||||
* @return the corresponding model node in the tree. If the tree is filtered the viewed node
|
||||
* will be a clone of the corresponding model node.
|
||||
|
@ -596,7 +597,7 @@ public class GTree extends JPanel implements BusyListener {
|
|||
* been replaced by a new node that is equal, but a different instance. One way this happens
|
||||
* is if the tree is filtered and therefor the displayed nodes are clones of the model nodes.
|
||||
* This can also happen if the tree nodes are rebuilt for some reason.
|
||||
*
|
||||
*
|
||||
* @param path the path of the node
|
||||
* @return the corresponding model node in the tree. If the tree is filtered the viewed node
|
||||
* will be a clone of the corresponding model node.
|
||||
|
@ -609,7 +610,7 @@ public class GTree extends JPanel implements BusyListener {
|
|||
* Gets the view node for the given node. This is useful to translate to a tree path that is
|
||||
* valid for the currently displayed tree. (Remember that if the tree is filtered, then the
|
||||
* displayed nodes are clones of the model nodes.)
|
||||
*
|
||||
*
|
||||
* @param node the node
|
||||
* @return the current node in the displayed (possibly filtered) tree
|
||||
*/
|
||||
|
@ -621,7 +622,7 @@ public class GTree extends JPanel implements BusyListener {
|
|||
* Gets the view node for the given path. This is useful to translate to a tree path that is
|
||||
* valid for the currently displayed tree. (Remember that if the tree is filtered, then the
|
||||
* displayed nodes are clones of the model nodes.)
|
||||
*
|
||||
*
|
||||
* @param path the path of the node
|
||||
* @return the current node in the displayed (possibly filtered) tree
|
||||
*/
|
||||
|
@ -760,7 +761,7 @@ public class GTree extends JPanel implements BusyListener {
|
|||
|
||||
/**
|
||||
* Returns true if the given JTree is the actual JTree used by this GTree.
|
||||
*
|
||||
*
|
||||
* @param jTree the tree to test
|
||||
* @return true if the given JTree is the actual JTree used by this GTree.
|
||||
*/
|
||||
|
@ -773,7 +774,7 @@ public class GTree extends JPanel implements BusyListener {
|
|||
* <P>
|
||||
* NOTE: if this method is not called from the Swing thread, then the root node will be set
|
||||
* later on the Swing thread. That is, this method will return before the work has been done.
|
||||
*
|
||||
*
|
||||
* @param rootNode The node to set as the new root.
|
||||
*/
|
||||
public void setRootNode(GTreeNode rootNode) {
|
||||
|
@ -916,6 +917,13 @@ public class GTree extends JPanel implements BusyListener {
|
|||
return paths;
|
||||
}
|
||||
|
||||
public List<GTreeNode> getSelectedNodes() {
|
||||
TreePath[] paths = getSelectionPaths();
|
||||
return Arrays.stream(paths)
|
||||
.map(tp -> (GTreeNode) tp.getLastPathComponent())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public boolean isExpanded(TreePath treePath) {
|
||||
return tree.isExpanded(treePath);
|
||||
}
|
||||
|
@ -1023,20 +1031,20 @@ public class GTree extends JPanel implements BusyListener {
|
|||
* becomes available to the model. This method will ensure that the named child passes any
|
||||
* current filter in order for the child to appear in the tree. This effect is temporary and
|
||||
* will be undone when next the filter changes.
|
||||
*
|
||||
*
|
||||
* <p>This method is intended to be used by clients using an asynchronous node model, where
|
||||
* new nodes will get created by application-level events. Such clients may wish to perform
|
||||
* work when newly created nodes become available. This method simplifies the concurrent
|
||||
* nature of the GTree, asynchronous nodes and the processing of asynchronous application-level
|
||||
* events by providing a callback mechanism for clients. <b>This method is non-blocking.</b>
|
||||
*
|
||||
*
|
||||
* <p>Note: this method assumes that the given parent node is in the view and not filtered
|
||||
* out of the view. This method makes no attempt to ensure the given parent node passes any
|
||||
* existing filter.
|
||||
*
|
||||
*
|
||||
* <p>Note: this method will not wait forever for the given node to appear. It will eventually
|
||||
* give up if the node never arrives.
|
||||
*
|
||||
*
|
||||
* @param parent the model's parent node. If the view's parent node is passed, it will
|
||||
* be translated to the model node.
|
||||
* @param childName the name of the desired child
|
||||
|
@ -1046,17 +1054,17 @@ public class GTree extends JPanel implements BusyListener {
|
|||
Consumer<GTreeNode> consumer) {
|
||||
|
||||
/*
|
||||
|
||||
|
||||
If the GTree were to use Java's CompletableStage API, then the code below
|
||||
could be written thusly:
|
||||
|
||||
|
||||
tree.getNewNode(modelParent, newName)
|
||||
.thenCompose(newModelChild -> {
|
||||
tree.ignoreFilter(newModelChild);
|
||||
return tree.getNewNode(viewParent, newName);
|
||||
))
|
||||
.thenAccept(consumer);
|
||||
|
||||
|
||||
*/
|
||||
|
||||
// ensure we operate on the model node which will always have the given child not the view
|
||||
|
@ -1075,7 +1083,7 @@ public class GTree extends JPanel implements BusyListener {
|
|||
* Requests that the node with the given name, in the given parent, be edited. This operation
|
||||
* is asynchronous. This request will be buffered as needed to wait for the given node to be
|
||||
* added to the parent, up to a timeout period.
|
||||
*
|
||||
*
|
||||
* @param parent the parent node
|
||||
* @param childName the name of the child to edit
|
||||
*/
|
||||
|
@ -1101,7 +1109,7 @@ public class GTree extends JPanel implements BusyListener {
|
|||
|
||||
/**
|
||||
* Requests that the node be edited. This operation is asynchronous.
|
||||
*
|
||||
*
|
||||
* @param node the node to edit
|
||||
*/
|
||||
public void startEditing(GTreeNode node) {
|
||||
|
@ -1269,7 +1277,7 @@ public class GTree extends JPanel implements BusyListener {
|
|||
/**
|
||||
* Used to run tree tasks. This method is not meant for general clients of this tree, but
|
||||
* rather for tasks to tell the tree to perform subtasks.
|
||||
*
|
||||
*
|
||||
* @param task the task to run
|
||||
*/
|
||||
public void runTask(GTreeTask task) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue