mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 09:49:23 +02:00
GP-5761 - Data Type Manager - Updated the Collapse button to stop any post-filter state restoring
This commit is contained in:
parent
c03417b3f6
commit
b07256a114
4 changed files with 63 additions and 18 deletions
|
@ -4,9 +4,9 @@
|
|||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -55,8 +55,9 @@ public class ClearFilterLabel extends GIconLabel {
|
|||
|
||||
this.textField = textField;
|
||||
|
||||
// pad some to offset from the edge of the text field
|
||||
setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
|
||||
// pad some to offset from the edge of the text field; the border width is a bit larger to
|
||||
// make it easier to hover over this label. Values were picked through trial-and-error.
|
||||
setBorder(BorderFactory.createEmptyBorder(2, 6, 4, 2));
|
||||
|
||||
textField.getDocument().addDocumentListener(new DocumentListener() {
|
||||
|
||||
|
@ -84,8 +85,12 @@ public class ClearFilterLabel extends GIconLabel {
|
|||
});
|
||||
|
||||
addMouseListener(new MouseAdapter() {
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
// Clear on released instead of clicked to allow for slight movement between the
|
||||
// press and release. If the user moves the most while holding down, the drag
|
||||
// prevents the clicked callback.
|
||||
clearFilter();
|
||||
}
|
||||
|
||||
|
@ -199,9 +204,16 @@ public class ClearFilterLabel extends GIconLabel {
|
|||
Insets textInsets = textField.getInsets();
|
||||
Point location = textBounds.getLocation();
|
||||
|
||||
Dimension size = getPreferredSize();
|
||||
int half = (textBounds.height - size.height) / 2;
|
||||
int y = textBounds.y + half;
|
||||
// For our placement, use the icon size and some padding to keep the icon visually off of
|
||||
// the edges of the text field. (We do not want to use our actual preferred size, as we
|
||||
// have made our size larger than this padding so it is easier to click us.)
|
||||
int iconHeight = ICON.getIconHeight();
|
||||
int iconWidth = ICON.getIconWidth();
|
||||
int padding = 4;
|
||||
|
||||
Dimension size = new Dimension(iconWidth + padding, iconHeight + padding);
|
||||
int halfHeight = (textBounds.height - size.height) / 2;
|
||||
int y = textBounds.y + halfHeight;
|
||||
|
||||
int end = location.x + textBounds.width;
|
||||
int x = end - textInsets.right - size.width;
|
||||
|
@ -209,7 +221,8 @@ public class ClearFilterLabel extends GIconLabel {
|
|||
// hide when text is near
|
||||
checkForTouchyText(x);
|
||||
|
||||
setBounds(x, y, size.width, size.height);
|
||||
Dimension preferredSize = getPreferredSize();
|
||||
setBounds(x, y, preferredSize.width, preferredSize.height);
|
||||
|
||||
myParent.validate();
|
||||
}
|
||||
|
|
|
@ -468,13 +468,22 @@ public class GTree extends JPanel implements BusyListener {
|
|||
public void collapseAll(GTreeNode node) {
|
||||
|
||||
runSwingNow(() -> {
|
||||
|
||||
if (!isFiltered() && lastFilterTask != null) {
|
||||
// When the user clears the filter, the filter task may be running to restore state.
|
||||
// If the user wishes to collapse nodes, it does not make sense to keep restoring
|
||||
// expanded/selected state. This call allows users to cancel any long running tree
|
||||
// state restoring by executing a collapse action.
|
||||
lastFilterTask.cancel();
|
||||
}
|
||||
|
||||
node.fireNodeStructureChanged();
|
||||
tree.collapsePath(node.getTreePath());
|
||||
|
||||
boolean nodeIsRoot = node.equals(model.getRoot());
|
||||
|
||||
if (nodeIsRoot && !tree.isRootAllowedToCollapse()) {
|
||||
runTask(new GTreeExpandNodeToDepthTask(this, getJTree(), node, 1));
|
||||
runTask(new GTreeExpandNodeToDepthTask(this, node, 1));
|
||||
}
|
||||
|
||||
});
|
||||
|
@ -1686,7 +1695,7 @@ public class GTree extends JPanel implements BusyListener {
|
|||
|
||||
if (!allowed) {
|
||||
if (model != null && model.getRoot() != null) {
|
||||
runTask(new GTreeExpandNodeToDepthTask(GTree.this, getJTree(),
|
||||
runTask(new GTreeExpandNodeToDepthTask(GTree.this,
|
||||
model.getModelRoot(), 1));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -15,6 +15,11 @@
|
|||
*/
|
||||
package docking.widgets.tree;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.swing.tree.TreePath;
|
||||
|
||||
import docking.widgets.tree.support.GTreeFilter;
|
||||
import docking.widgets.tree.tasks.GTreeClearTreeFilterTask;
|
||||
import docking.widgets.tree.tasks.GTreeExpandAllTask;
|
||||
|
@ -80,10 +85,30 @@ public class GTreeFilterTask extends GTreeTask {
|
|||
private void restoreInSameTask(TaskMonitor monitor) {
|
||||
|
||||
GTreeState state = tree.getFilterRestoreState();
|
||||
if (isOnlyRootSelected(state)) {
|
||||
// This is a special case that allows the user to signal to not restore the tree state
|
||||
// when the filter is cleared. The tree will normally restore the state to either 1)
|
||||
// the state prior to the filter, or 2) the state the user chose when filtered by
|
||||
// selecting one or more nodes. If the user selects the root, we will use that as a
|
||||
// signal from the user to say they do not want any state to be restored when the filter
|
||||
// is cleared.
|
||||
return;
|
||||
}
|
||||
GTreeRestoreTreeStateTask restoreTask = new GTreeRestoreTreeStateTask(tree, state);
|
||||
restoreTask.run(monitor);
|
||||
}
|
||||
|
||||
private boolean isOnlyRootSelected(GTreeState state) {
|
||||
List<TreePath> paths = state.getSelectedPaths();
|
||||
if (paths.size() == 1) {
|
||||
TreePath path = paths.get(0);
|
||||
GTreeNode node = (GTreeNode) path.getLastPathComponent();
|
||||
GTreeNode viewRoot = tree.getViewRoot();
|
||||
return Objects.equals(node, viewRoot);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
cancelledProgramatically = true;
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -29,12 +29,10 @@ import ghidra.util.task.TaskMonitor;
|
|||
public class GTreeExpandNodeToDepthTask extends GTreeTask {
|
||||
|
||||
private final TreePath[] paths;
|
||||
private final JTree jTree;
|
||||
private final int depth;
|
||||
|
||||
public GTreeExpandNodeToDepthTask(GTree gTree, JTree jTree, GTreeNode node, int depth) {
|
||||
public GTreeExpandNodeToDepthTask(GTree gTree, GTreeNode node, int depth) {
|
||||
super(gTree);
|
||||
this.jTree = jTree;
|
||||
this.paths = new TreePath[] { node.getTreePath() };
|
||||
this.depth = depth;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue