diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypesProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypesProvider.java index b6196bdbd6..6300f0e83f 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypesProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypesProvider.java @@ -426,9 +426,18 @@ public class DataTypesProvider extends ComponentProviderAdapter { archiveGTree.addGTreeSelectionListener(e -> { TreePath path = e.getNewLeadSelectionPath(); - DataType dataType = getDataTypeFrom(path); + DataType selectedDt = getDataTypeFrom(path); + DataTypeUrl dtUrl = navigationHistory.getCurrentHistoryItem(); + if (dtUrl != null) { + DataType historyDt = dtUrl.getDataType(plugin); + if (Objects.equals(historyDt, selectedDt)) { + // Don't add an item to the history that is already there. This can happen when + // the user interacts with the navigation buttons. + return; + } + } - dataTypeSelected(e.getEventOrigin(), dataType); + dataTypeSelected(e.getEventOrigin(), selectedDt); }); buildPreviewPane(); @@ -783,8 +792,9 @@ public class DataTypesProvider extends ComponentProviderAdapter { return; } + TreePath treePath = dataTypeNode.getTreePath(); gTree.setSelectedNode(dataTypeNode); - gTree.scrollPathToVisible(dataTypeNode.getTreePath()); + gTree.scrollPathToVisible(treePath); contextChanged(); } diff --git a/Ghidra/Framework/Generic/src/main/java/util/HistoryList.java b/Ghidra/Framework/Generic/src/main/java/util/HistoryList.java index c1796c6255..a229422d9a 100644 --- a/Ghidra/Framework/Generic/src/main/java/util/HistoryList.java +++ b/Ghidra/Framework/Generic/src/main/java/util/HistoryList.java @@ -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. @@ -21,6 +21,7 @@ import java.util.function.Consumer; import org.apache.commons.lang3.StringUtils; +import ghidra.util.Msg; import ghidra.util.SystemUtilities; import ghidra.util.datastruct.FixedSizeStack; @@ -38,8 +39,10 @@ import ghidra.util.datastruct.FixedSizeStack; * item is cleared, then client is expected to call {@link #add(Object)} with value of * null. (This is safe to do, regardless of whether null are allowed). When nulls are allowed * and a null value is received, then current item is placed onto the history stack as the - * previous item. This way, when the user presses the back button, the last visible item - * will be activated. + * previous item, thus using the null value as a flag. After using null this way, when the user + * presses the back button, the last visible item will be activated. + * + *
If nulls are not allowed, then any calls to {@link #add(Object)} a null value will be ignored. * *
Note: when nulls are allowed, only a single null value will be stored. Further,
* if new, non-null items are added, then the null value is dropped.
@@ -191,8 +194,14 @@ public class HistoryList