mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
GT-2947 - updated Edit Function dialog to put focus in the signature
field by default; added undo/redo support
This commit is contained in:
parent
fb3e941959
commit
a77efd2524
5 changed files with 128 additions and 75 deletions
|
@ -87,7 +87,7 @@ import resources.ResourceManager;
|
|||
* <tr><td>{@link JList}</td><td>{@link GList}</td></tr>
|
||||
* <tr><td>{@link ListCellRenderer}<br>{@link DefaultListCellRenderer}</td><td>{@link GListCellRenderer}</td></tr>
|
||||
* <tr><td>{@link TableCellRenderer}</td><td>{@link GTableCellRenderer}</td></tr>
|
||||
* <tr><td>{@link TreeCellRenderer}<br>{@link DefaultTreeCellRenderer}</td><td>{@link GTreeRenderer}<br>{@link DnDTreeCellRenderer}</td></tr>
|
||||
* <tr><td>{@link TreeCellRenderer}<br>{@link DefaultTreeCellRenderer}</td><td>{@link GTreeRenderer}<br><code>DnDTreeCellRenderer</code></td></tr>
|
||||
* <tr><td>{@link JRadioButton}</td><td>{@link GRadioButton}</td></tr>
|
||||
* <tr><td>{@link JButton}</td><td>???tbd???</td></tr>
|
||||
* </table>
|
||||
|
@ -179,15 +179,6 @@ public class DockingUtils {
|
|||
final UndoRedoKeeper undoRedoKeeper = new UndoRedoKeeper();
|
||||
document.addUndoableEditListener(e -> {
|
||||
UndoableEdit edit = e.getEdit();
|
||||
|
||||
// TODO We are now handed a wrapper class and not the event for the 'edit'. It is not clear
|
||||
// which use case caused this code to be added. If/when we find out, we can revisit how
|
||||
// to filter these types of updates.
|
||||
// DefaultDocumentEvent defaultDocumentEvent = (DefaultDocumentEvent) edit;
|
||||
// if (defaultDocumentEvent.getType() == EventType.CHANGE) {
|
||||
// return; // this happens for style updates
|
||||
// }
|
||||
|
||||
undoRedoKeeper.addUndo(edit);
|
||||
});
|
||||
|
||||
|
|
|
@ -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,31 +15,85 @@
|
|||
*/
|
||||
package docking;
|
||||
|
||||
import ghidra.util.datastruct.FixedSizeStack;
|
||||
|
||||
import javax.swing.JTextPane;
|
||||
import javax.swing.undo.CompoundEdit;
|
||||
import javax.swing.undo.UndoableEdit;
|
||||
|
||||
import ghidra.util.datastruct.FixedSizeStack;
|
||||
|
||||
/**
|
||||
* Handles tracking undo and redo events. Clients may wish to hold on to this class in order
|
||||
* to clear the undo/redo queue.
|
||||
*
|
||||
* <p><b><u>Style Edits</u></b><br>
|
||||
* {@link JTextPane}s allow for styles (color, bold, etc) to be applied to their text. The
|
||||
* default undo/redo events may arrive singly, not in bulk. Thus, when the user presses undo,
|
||||
* each style change is undo, one at a time. This is intuitive when the user controls the
|
||||
* application of style. However, when style is applied programmatically, it can be odd to
|
||||
* see that the user-type text does not change, but just the coloring applied to that text.
|
||||
* <p>
|
||||
* To address this issue, this class takes the approach of combining all style edits into a
|
||||
* single bulk edit. Then, as the user presses undo, all style edits can be removed together, as
|
||||
* well as any neighboring text edits. <b>Put simply, this class tracks style edits such
|
||||
* that an undo operation will undo all style changes, as well as a single text edit.</b>
|
||||
*/
|
||||
public class UndoRedoKeeper {
|
||||
|
||||
private static final int MAX_UNDO_REDO_SIZE = 50;
|
||||
private static final String STYLE_EDIT_KEY = "style";
|
||||
|
||||
private FixedSizeStack<UndoableEdit> undoStack = new FixedSizeStack<UndoableEdit>(
|
||||
MAX_UNDO_REDO_SIZE);
|
||||
private FixedSizeStack<UndoableEdit> redoStack = new FixedSizeStack<UndoableEdit>(
|
||||
MAX_UNDO_REDO_SIZE);
|
||||
private FixedSizeStack<UndoableEdit> undoStack = new FixedSizeStack<>(MAX_UNDO_REDO_SIZE);
|
||||
private FixedSizeStack<UndoableEdit> redoStack = new FixedSizeStack<>(MAX_UNDO_REDO_SIZE);
|
||||
|
||||
private StyleCompoundEdit lastStyleUndo;
|
||||
|
||||
void addUndo(UndoableEdit edit) {
|
||||
|
||||
String name = edit.getPresentationName();
|
||||
if (name.contains(STYLE_EDIT_KEY)) {
|
||||
// (see header note about style edits)
|
||||
addStyleEdit(edit);
|
||||
return;
|
||||
}
|
||||
|
||||
endOutstandingStyleEdits();
|
||||
|
||||
undoStack.push(edit);
|
||||
redoStack.clear();
|
||||
redoStack.clear(); // new edit added; clear redo
|
||||
}
|
||||
|
||||
private void endOutstandingStyleEdits() {
|
||||
if (lastStyleUndo != null) {
|
||||
lastStyleUndo.end();
|
||||
lastStyleUndo = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void addStyleEdit(UndoableEdit edit) {
|
||||
if (lastStyleUndo == null) {
|
||||
lastStyleUndo = new StyleCompoundEdit();
|
||||
undoStack.push(lastStyleUndo);
|
||||
}
|
||||
|
||||
lastStyleUndo.addEdit(edit);
|
||||
redoStack.clear(); // new edit added; clear redo
|
||||
}
|
||||
|
||||
void undo() {
|
||||
if (undoStack.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
endOutstandingStyleEdits();
|
||||
|
||||
UndoableEdit item = undoStack.pop();
|
||||
redoStack.push(item);
|
||||
item.undo();
|
||||
|
||||
// (see header note)
|
||||
if (item instanceof StyleCompoundEdit) {
|
||||
undo(); // call again to get a 'real' edit
|
||||
}
|
||||
}
|
||||
|
||||
void redo() {
|
||||
|
@ -48,13 +101,24 @@ public class UndoRedoKeeper {
|
|||
return;
|
||||
}
|
||||
|
||||
endOutstandingStyleEdits();
|
||||
|
||||
UndoableEdit item = redoStack.pop();
|
||||
undoStack.push(item);
|
||||
item.redo();
|
||||
|
||||
// (see header note)
|
||||
if (item instanceof StyleCompoundEdit) {
|
||||
undo(); // call again to get a 'real' edit
|
||||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
undoStack.clear();
|
||||
redoStack.clear();
|
||||
}
|
||||
|
||||
private static class StyleCompoundEdit extends CompoundEdit {
|
||||
// simple class for us to track internally
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue