mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
GP-1619 - Fixed bug that caused some MultiStateDockinActions to get called twice when clicked
This commit is contained in:
parent
436bb4873e
commit
6934c33aa6
25 changed files with 197 additions and 627 deletions
|
@ -24,7 +24,6 @@ public interface DebuggerAutoReadMemoryAction extends AutoReadMemoryAction {
|
||||||
static MultiStateActionBuilder<AutoReadMemorySpec> builder(Plugin owner) {
|
static MultiStateActionBuilder<AutoReadMemorySpec> builder(Plugin owner) {
|
||||||
MultiStateActionBuilder<AutoReadMemorySpec> builder = AutoReadMemoryAction.builder(owner);
|
MultiStateActionBuilder<AutoReadMemorySpec> builder = AutoReadMemoryAction.builder(owner);
|
||||||
builder.toolBarGroup(NAME);
|
builder.toolBarGroup(NAME);
|
||||||
builder.performActionOnButtonClick(true);
|
|
||||||
for (AutoReadMemorySpec spec : AutoReadMemorySpec.allSpecs().values()) {
|
for (AutoReadMemorySpec spec : AutoReadMemorySpec.allSpecs().values()) {
|
||||||
builder.addState(spec.getMenuName(), spec.getMenuIcon(), spec);
|
builder.addState(spec.getMenuName(), spec.getMenuIcon(), spec);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,6 @@ public interface DebuggerTrackLocationAction extends TrackLocationAction {
|
||||||
static MultiStateActionBuilder<LocationTrackingSpec> builder(Plugin owner) {
|
static MultiStateActionBuilder<LocationTrackingSpec> builder(Plugin owner) {
|
||||||
MultiStateActionBuilder<LocationTrackingSpec> builder = TrackLocationAction.builder(owner);
|
MultiStateActionBuilder<LocationTrackingSpec> builder = TrackLocationAction.builder(owner);
|
||||||
builder.toolBarGroup(owner.getName());
|
builder.toolBarGroup(owner.getName());
|
||||||
builder.performActionOnButtonClick(true);
|
|
||||||
for (LocationTrackingSpec spec : LocationTrackingSpec.allSpecs().values()) {
|
for (LocationTrackingSpec spec : LocationTrackingSpec.allSpecs().values()) {
|
||||||
builder.addState(spec.getMenuName(), spec.getMenuIcon(), spec);
|
builder.addState(spec.getMenuName(), spec.getMenuIcon(), spec);
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,22 +63,14 @@ import ghidra.util.datastruct.ListenerSet;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
@PluginInfo(
|
@PluginInfo(shortDescription = "Debugger models manager service (proxy to front-end)", description = "Manage debug sessions, connections, and trace recording", category = PluginCategoryNames.DEBUGGER, packageName = DebuggerPluginPackage.NAME, status = PluginStatus.RELEASED, eventsConsumed = {
|
||||||
shortDescription = "Debugger models manager service (proxy to front-end)",
|
|
||||||
description = "Manage debug sessions, connections, and trace recording",
|
|
||||||
category = PluginCategoryNames.DEBUGGER,
|
|
||||||
packageName = DebuggerPluginPackage.NAME,
|
|
||||||
status = PluginStatus.RELEASED,
|
|
||||||
eventsConsumed = {
|
|
||||||
ProgramActivatedPluginEvent.class,
|
ProgramActivatedPluginEvent.class,
|
||||||
ProgramClosedPluginEvent.class,
|
ProgramClosedPluginEvent.class,
|
||||||
},
|
}, servicesRequired = {
|
||||||
servicesRequired = {
|
|
||||||
DebuggerTraceManagerService.class,
|
DebuggerTraceManagerService.class,
|
||||||
},
|
}, servicesProvided = {
|
||||||
servicesProvided = {
|
|
||||||
DebuggerModelService.class,
|
DebuggerModelService.class,
|
||||||
})
|
})
|
||||||
public class DebuggerModelServiceProxyPlugin extends Plugin
|
public class DebuggerModelServiceProxyPlugin extends Plugin
|
||||||
implements DebuggerModelServiceInternal {
|
implements DebuggerModelServiceInternal {
|
||||||
|
|
||||||
|
@ -250,7 +242,6 @@ public class DebuggerModelServiceProxyPlugin extends Plugin
|
||||||
.enabledWhen(ctx -> currentProgram != null)
|
.enabledWhen(ctx -> currentProgram != null)
|
||||||
.onAction(this::debugProgramButtonActivated)
|
.onAction(this::debugProgramButtonActivated)
|
||||||
.onActionStateChanged(this::debugProgramStateActivated)
|
.onActionStateChanged(this::debugProgramStateActivated)
|
||||||
.performActionOnButtonClick(true)
|
|
||||||
.addState(DUMMY_LAUNCH_STATE)
|
.addState(DUMMY_LAUNCH_STATE)
|
||||||
.buildAndInstall(tool);
|
.buildAndInstall(tool);
|
||||||
actionDisconnectAll = DisconnectAllAction.builder(this, delegate)
|
actionDisconnectAll = DisconnectAllAction.builder(this, delegate)
|
||||||
|
@ -383,7 +374,7 @@ public class DebuggerModelServiceProxyPlugin extends Plugin
|
||||||
List<DebuggerProgramLaunchOffer> offers = program == null ? List.of()
|
List<DebuggerProgramLaunchOffer> offers = program == null ? List.of()
|
||||||
: getProgramLaunchOffers(program).collect(Collectors.toList());
|
: getProgramLaunchOffers(program).collect(Collectors.toList());
|
||||||
List<ActionState<DebuggerProgramLaunchOffer>> states = offers.stream()
|
List<ActionState<DebuggerProgramLaunchOffer>> states = offers.stream()
|
||||||
.map(o -> new ActionState<DebuggerProgramLaunchOffer>(o.getButtonTitle(),
|
.map(o -> new ActionState<>(o.getButtonTitle(),
|
||||||
o.getIcon(), o))
|
o.getIcon(), o))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
if (!states.isEmpty()) {
|
if (!states.isEmpty()) {
|
||||||
|
|
|
@ -348,7 +348,7 @@ public class SampleGraphProvider extends ComponentProviderAdapter {
|
||||||
new MultiStateDockingAction<>(RELAYOUT_GRAPH_ACTION_NAME, plugin.getName()) {
|
new MultiStateDockingAction<>(RELAYOUT_GRAPH_ACTION_NAME, plugin.getName()) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doActionPerformed(ActionContext context) {
|
public void actionPerformed(ActionContext context) {
|
||||||
// this callback is when the user clicks the button
|
// this callback is when the user clicks the button
|
||||||
LayoutProvider<SampleVertex, SampleEdge, SampleGraph> currentUserData =
|
LayoutProvider<SampleVertex, SampleEdge, SampleGraph> currentUserData =
|
||||||
getCurrentUserData();
|
getCurrentUserData();
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,17 +15,16 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.datamgr.actions;
|
package ghidra.app.plugin.core.datamgr.actions;
|
||||||
|
|
||||||
|
import javax.swing.Icon;
|
||||||
|
|
||||||
|
import docking.menu.ActionState;
|
||||||
|
import docking.menu.MultiStateDockingAction;
|
||||||
|
import docking.widgets.EventTrigger;
|
||||||
import ghidra.app.plugin.core.datamgr.DataTypeManagerPlugin;
|
import ghidra.app.plugin.core.datamgr.DataTypeManagerPlugin;
|
||||||
import ghidra.program.model.data.DataTypeConflictHandler;
|
import ghidra.program.model.data.DataTypeConflictHandler;
|
||||||
import ghidra.program.model.data.DataTypeConflictHandler.ConflictResolutionPolicy;
|
import ghidra.program.model.data.DataTypeConflictHandler.ConflictResolutionPolicy;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
|
|
||||||
import javax.swing.Icon;
|
|
||||||
|
|
||||||
import resources.ResourceManager;
|
import resources.ResourceManager;
|
||||||
import docking.menu.ActionState;
|
|
||||||
import docking.menu.MultiStateDockingAction;
|
|
||||||
import docking.widgets.EventTrigger;
|
|
||||||
|
|
||||||
public class ConflictHandlerModesAction extends
|
public class ConflictHandlerModesAction extends
|
||||||
MultiStateDockingAction<DataTypeConflictHandler.ConflictResolutionPolicy> {
|
MultiStateDockingAction<DataTypeConflictHandler.ConflictResolutionPolicy> {
|
||||||
|
@ -43,33 +41,31 @@ public class ConflictHandlerModesAction extends
|
||||||
new HelpLocation(plugin.getName(), "conflict_mode");
|
new HelpLocation(plugin.getName(), "conflict_mode");
|
||||||
setHelpLocation(conflictModesHelpLocation);
|
setHelpLocation(conflictModesHelpLocation);
|
||||||
|
|
||||||
setPerformActionOnPrimaryButtonClick(false);
|
|
||||||
|
|
||||||
Icon renameAndAddIcon = ResourceManager.loadImage("images/conflictRename.png");
|
Icon renameAndAddIcon = ResourceManager.loadImage("images/conflictRename.png");
|
||||||
Icon useExistingIcon = ResourceManager.loadImage("images/conflictKeep.png");
|
Icon useExistingIcon = ResourceManager.loadImage("images/conflictKeep.png");
|
||||||
Icon replaceExistingIcon = ResourceManager.loadImage("images/conflictReplace.png");
|
Icon replaceExistingIcon = ResourceManager.loadImage("images/conflictReplace.png");
|
||||||
Icon replaceDefaultIcon = ResourceManager.loadImage("images/conflictReplaceOrRename.png");
|
Icon replaceDefaultIcon = ResourceManager.loadImage("images/conflictReplaceOrRename.png");
|
||||||
|
|
||||||
ActionState<DataTypeConflictHandler.ConflictResolutionPolicy> renameAndAddState =
|
ActionState<DataTypeConflictHandler.ConflictResolutionPolicy> renameAndAddState =
|
||||||
new ActionState<DataTypeConflictHandler.ConflictResolutionPolicy>(
|
new ActionState<>(
|
||||||
"Rename New or Moved Data Type", renameAndAddIcon,
|
"Rename New or Moved Data Type", renameAndAddIcon,
|
||||||
DataTypeConflictHandler.ConflictResolutionPolicy.RENAME_AND_ADD);
|
DataTypeConflictHandler.ConflictResolutionPolicy.RENAME_AND_ADD);
|
||||||
renameAndAddState.setHelpLocation(conflictModesHelpLocation);
|
renameAndAddState.setHelpLocation(conflictModesHelpLocation);
|
||||||
|
|
||||||
ActionState<DataTypeConflictHandler.ConflictResolutionPolicy> useExistingState =
|
ActionState<DataTypeConflictHandler.ConflictResolutionPolicy> useExistingState =
|
||||||
new ActionState<DataTypeConflictHandler.ConflictResolutionPolicy>(
|
new ActionState<>(
|
||||||
"Use Existing Data Type", useExistingIcon,
|
"Use Existing Data Type", useExistingIcon,
|
||||||
DataTypeConflictHandler.ConflictResolutionPolicy.USE_EXISTING);
|
DataTypeConflictHandler.ConflictResolutionPolicy.USE_EXISTING);
|
||||||
useExistingState.setHelpLocation(conflictModesHelpLocation);
|
useExistingState.setHelpLocation(conflictModesHelpLocation);
|
||||||
|
|
||||||
ActionState<DataTypeConflictHandler.ConflictResolutionPolicy> replaceExistingState =
|
ActionState<DataTypeConflictHandler.ConflictResolutionPolicy> replaceExistingState =
|
||||||
new ActionState<DataTypeConflictHandler.ConflictResolutionPolicy>(
|
new ActionState<>(
|
||||||
"Replace Existing Data Type", replaceExistingIcon,
|
"Replace Existing Data Type", replaceExistingIcon,
|
||||||
DataTypeConflictHandler.ConflictResolutionPolicy.REPLACE_EXISTING);
|
DataTypeConflictHandler.ConflictResolutionPolicy.REPLACE_EXISTING);
|
||||||
replaceExistingState.setHelpLocation(conflictModesHelpLocation);
|
replaceExistingState.setHelpLocation(conflictModesHelpLocation);
|
||||||
|
|
||||||
ActionState<DataTypeConflictHandler.ConflictResolutionPolicy> replaceDefaultState =
|
ActionState<DataTypeConflictHandler.ConflictResolutionPolicy> replaceDefaultState =
|
||||||
new ActionState<DataTypeConflictHandler.ConflictResolutionPolicy>(
|
new ActionState<>(
|
||||||
"Replace Empty Structures else Rename",
|
"Replace Empty Structures else Rename",
|
||||||
replaceDefaultIcon,
|
replaceDefaultIcon,
|
||||||
DataTypeConflictHandler.ConflictResolutionPolicy.REPLACE_EMPTY_STRUCTS_OR_RENAME_AND_ADD);
|
DataTypeConflictHandler.ConflictResolutionPolicy.REPLACE_EMPTY_STRUCTS_OR_RENAME_AND_ADD);
|
||||||
|
|
|
@ -15,9 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.navigation;
|
package ghidra.app.plugin.core.navigation;
|
||||||
|
|
||||||
import java.util.Iterator;
|
|
||||||
|
|
||||||
import java.awt.event.*;
|
import java.awt.event.*;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
import javax.swing.ImageIcon;
|
import javax.swing.ImageIcon;
|
||||||
import javax.swing.KeyStroke;
|
import javax.swing.KeyStroke;
|
||||||
|
@ -103,7 +102,7 @@ public class NextPreviousBookmarkAction extends MultiStateDockingAction<String>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doActionPerformed(ActionContext context) {
|
public void actionPerformed(ActionContext context) {
|
||||||
if (context instanceof NavigatableActionContext) {
|
if (context instanceof NavigatableActionContext) {
|
||||||
gotoNextPrevious((NavigatableActionContext) context, this.getCurrentUserData());
|
gotoNextPrevious((NavigatableActionContext) context, this.getCurrentUserData());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,314 +0,0 @@
|
||||||
/* ###
|
|
||||||
* IP: GHIDRA
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package ghidra.app.plugin.core.navigation;
|
|
||||||
|
|
||||||
import java.awt.event.InputEvent;
|
|
||||||
import java.awt.event.KeyEvent;
|
|
||||||
|
|
||||||
import javax.swing.ImageIcon;
|
|
||||||
import javax.swing.KeyStroke;
|
|
||||||
|
|
||||||
import docking.ActionContext;
|
|
||||||
import docking.action.*;
|
|
||||||
import docking.menu.ActionState;
|
|
||||||
import docking.menu.MultiStateDockingAction;
|
|
||||||
import docking.tool.ToolConstants;
|
|
||||||
import docking.widgets.EventTrigger;
|
|
||||||
import ghidra.app.context.ListingActionContext;
|
|
||||||
import ghidra.app.nav.Navigatable;
|
|
||||||
import ghidra.app.plugin.core.codebrowser.CodeViewerActionContext;
|
|
||||||
import ghidra.app.services.GoToService;
|
|
||||||
import ghidra.app.services.MarkerSet;
|
|
||||||
import ghidra.app.util.HelpTopics;
|
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
|
||||||
import ghidra.program.model.address.Address;
|
|
||||||
import ghidra.program.model.listing.BookmarkType;
|
|
||||||
import ghidra.util.HelpLocation;
|
|
||||||
import resources.ResourceManager;
|
|
||||||
|
|
||||||
public class NextPreviousMarkerAction extends MultiStateDockingAction<String> {
|
|
||||||
//private static final ImageIcon new ImageIcon(); = null;
|
|
||||||
private boolean isForward = true;
|
|
||||||
private PluginTool tool;
|
|
||||||
|
|
||||||
private static ImageIcon markerIcon = ResourceManager.loadImage("images/M.gif");
|
|
||||||
private static ImageIcon markerAnalysisBookmarkIcon = ResourceManager.loadImage("images/M.gif");
|
|
||||||
private static ImageIcon markerConflictingChangesIcon =
|
|
||||||
ResourceManager.loadImage("images/edit-delete.png");
|
|
||||||
private static ImageIcon markerLatestVersionChangesIcon =
|
|
||||||
ResourceManager.loadImage("images/information.png");
|
|
||||||
private static ImageIcon markerNotCheckedInChangesIcon =
|
|
||||||
ResourceManager.loadImage("images/notes.gif");
|
|
||||||
private static ImageIcon markerUnSavedChangesIcon =
|
|
||||||
ResourceManager.loadImage("images/warning.png");
|
|
||||||
private static ImageIcon markerCursorIcon = ResourceManager.loadImage("images/unknown.gif");
|
|
||||||
private static ImageIcon markerErrorBookmarkIcon =
|
|
||||||
ResourceManager.loadImage("images/unknown.gif");
|
|
||||||
private static ImageIcon markerHighlightIcon = ResourceManager.loadImage("images/unknown.gif");
|
|
||||||
private static ImageIcon markerInfoBookmarkIcon =
|
|
||||||
ResourceManager.loadImage("images/unknown.gif");
|
|
||||||
private static ImageIcon markerNoteBookmarkIcon =
|
|
||||||
ResourceManager.loadImage("images/unknown.gif");
|
|
||||||
private static ImageIcon markerSelectionIcon = ResourceManager.loadImage("images/unknown.gif");
|
|
||||||
private static ImageIcon markerWarningBookmarkIcon =
|
|
||||||
ResourceManager.loadImage("images/unknown.gif");
|
|
||||||
|
|
||||||
public NextPreviousMarkerAction(PluginTool tool, String owner, String subGroup) {
|
|
||||||
super("Next Marker", owner);
|
|
||||||
this.tool = tool;
|
|
||||||
|
|
||||||
ToolBarData toolBarData =
|
|
||||||
new ToolBarData(markerIcon, ToolConstants.TOOLBAR_GROUP_FOUR);
|
|
||||||
toolBarData.setToolBarSubGroup(subGroup);
|
|
||||||
setToolBarData(toolBarData);
|
|
||||||
|
|
||||||
MenuData menuData =
|
|
||||||
new MenuData(new String[] { ToolConstants.MENU_NAVIGATION, getMenuName() }, markerIcon,
|
|
||||||
ToolConstants.MENU_GROUP_NEXT_CODE_UNIT_NAV);
|
|
||||||
menuData.setMenuSubGroup(subGroup);
|
|
||||||
setMenuBarData(menuData);
|
|
||||||
|
|
||||||
setKeyBindingData(new KeyBindingData(getKeyStroke()));
|
|
||||||
addToWindowWhen(CodeViewerActionContext.class);
|
|
||||||
|
|
||||||
setHelpLocation(new HelpLocation(HelpTopics.NAVIGATION, getName()));
|
|
||||||
setDescription("Set marker options");
|
|
||||||
addToWindowWhen(CodeViewerActionContext.class);
|
|
||||||
|
|
||||||
ActionState<String> allMarkers =
|
|
||||||
new ActionState<String>("All Types", markerIcon, "All Types");
|
|
||||||
ActionState<String> analysis =
|
|
||||||
new ActionState<String>("Analysis Marker", markerAnalysisBookmarkIcon,
|
|
||||||
BookmarkType.ANALYSIS);
|
|
||||||
ActionState<String> conflictingChanges =
|
|
||||||
new ActionState<String>("Conflicting Changes", markerAnalysisBookmarkIcon,
|
|
||||||
"Conflicting Changes");
|
|
||||||
ActionState<String> latestVersionChanges =
|
|
||||||
new ActionState<String>("Latest Version Changes", markerAnalysisBookmarkIcon,
|
|
||||||
"Latest Version Changes");
|
|
||||||
ActionState<String> notCheckedInChanges =
|
|
||||||
new ActionState<String>("Not Checked In Changes", markerAnalysisBookmarkIcon,
|
|
||||||
"Not Checked In Changes");
|
|
||||||
ActionState<String> unsavedChanges =
|
|
||||||
new ActionState<String>("Unsaved Changes", markerIcon, "Unsaved Changes");
|
|
||||||
ActionState<String> cursor = new ActionState<String>("Cursor", markerIcon, "Cursor");
|
|
||||||
ActionState<String> error =
|
|
||||||
new ActionState<String>("Error Marker", markerIcon, BookmarkType.ERROR);
|
|
||||||
ActionState<String> highlight =
|
|
||||||
new ActionState<String>("Highlight", markerIcon, "Highlight");
|
|
||||||
ActionState<String> info =
|
|
||||||
new ActionState<String>("Info Marker", markerIcon, BookmarkType.INFO);
|
|
||||||
ActionState<String> note =
|
|
||||||
new ActionState<String>("Note Marker", markerIcon, BookmarkType.NOTE);
|
|
||||||
ActionState<String> selection =
|
|
||||||
new ActionState<String>("Selection", markerIcon, "Selection");
|
|
||||||
ActionState<String> warning =
|
|
||||||
new ActionState<String>("Warning Marker", markerIcon, BookmarkType.WARNING);
|
|
||||||
ActionState<String> custom =
|
|
||||||
new ActionState<String>("Custom Marker", markerIcon, "Custom Marker");
|
|
||||||
|
|
||||||
addActionState(allMarkers);
|
|
||||||
addActionState(analysis);
|
|
||||||
addActionState(conflictingChanges);
|
|
||||||
addActionState(latestVersionChanges);
|
|
||||||
addActionState(notCheckedInChanges);
|
|
||||||
addActionState(unsavedChanges);
|
|
||||||
addActionState(cursor);
|
|
||||||
addActionState(error);
|
|
||||||
addActionState(highlight);
|
|
||||||
addActionState(info);
|
|
||||||
addActionState(note);
|
|
||||||
addActionState(selection);
|
|
||||||
addActionState(warning);
|
|
||||||
addActionState(custom);
|
|
||||||
|
|
||||||
setCurrentActionState(allMarkers); // default
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setMenuBarData(MenuData newMenuData) {
|
|
||||||
//
|
|
||||||
// When we are in the menu we will display our default icon, which is the marker icon.
|
|
||||||
//
|
|
||||||
superSetMenuBarData(newMenuData);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doActionPerformed(ActionContext context) {
|
|
||||||
gotoNextPrevious((ListingActionContext) context.getContextObject(),
|
|
||||||
this.getCurrentUserData());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void actionStateChanged(ActionState<String> newActionState, EventTrigger trigger) {
|
|
||||||
// nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the beginning of the next instruction range
|
|
||||||
/*private Address getNextAddress(Program program, Address address, String markerType) {
|
|
||||||
MarkerSet nextMarker = getNextMarker(program, address, true, markerType);
|
|
||||||
return nextMarker == null ? null : nextMarker.getAddressSet().getMinAddress();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
/*private Address getPreviousAddress(Program program, Address address, String markerType) {
|
|
||||||
MarkerManager markerManager = program.getMarkerManager();
|
|
||||||
Iterator<Marker> markerIterator = markerManager.getMarkersIterator(address, false);
|
|
||||||
if (isMarkerAddressEqualToCurrent(markerIterator.next(), address)) {
|
|
||||||
|
|
||||||
}
|
|
||||||
MarkerSet nextMarker = getNextMarker(program, address, false, markerType);
|
|
||||||
return nextMarker == null ? null : nextMarker.getAddressSet().getMinAddress();
|
|
||||||
}
|
|
||||||
|
|
||||||
private MarkerSet getNextMarker(Program program, Address address, boolean forward,
|
|
||||||
String markerType) {
|
|
||||||
MarkerManager markerManager = program.getMarkerManager();
|
|
||||||
Iterator<MarkerSet> markerIterator = markerManager.getMarkersIterator(address, forward);
|
|
||||||
while (markerIterator.hasNext()) {
|
|
||||||
MarkerSet nextMarker = markerIterator.next();
|
|
||||||
Address nextAddress = nextMarker.getAddressSet().getMinAddress();
|
|
||||||
if (nextAddress.isExternalAddress()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (markerType.equals(MarkerType.ALL_TYPES) && !nextAddress.equals(address)) {
|
|
||||||
return nextMarker;
|
|
||||||
}
|
|
||||||
else if (markerType.equals("Custom")) {
|
|
||||||
if (!nextMarker.getTypeString().equals(MarkerType.ANALYSIS) &&
|
|
||||||
!nextMarker.getTypeString().equals(MarkerType.INFO) &&
|
|
||||||
!nextMarker.getTypeString().equals(MarkerType.NOTE) &&
|
|
||||||
!nextMarker.getTypeString().equals(MarkerType.WARNING) &&
|
|
||||||
!nextMarker.getTypeString().equals(MarkerType.ERROR) &&
|
|
||||||
!nextAddress.equals(address)) {
|
|
||||||
return nextMarker;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (nextMarker.getTypeString().equals(markerType) && !nextAddress.equals(address)) {
|
|
||||||
return nextMarker;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!markerIterator.hasNext()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return markerIterator.next();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
private boolean isMarkerAddressEqualToCurrent(MarkerSet marker, Address address) {
|
|
||||||
if (marker == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return !address.equals(marker.getMinAddress());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void gotoAddress(GoToService service, Navigatable navigatable, Address address) {
|
|
||||||
service.goTo(navigatable, address);
|
|
||||||
}
|
|
||||||
|
|
||||||
//==================================================================================================
|
|
||||||
// AbstractNextPreviousAction Methods
|
|
||||||
//==================================================================================================
|
|
||||||
void gotoNextPrevious(final ListingActionContext context, final String markerType) {
|
|
||||||
/*final Address address =
|
|
||||||
isForward ? getNextAddress(context.getProgram(), context.getAddress(), markerType)
|
|
||||||
: getPreviousAddress(context.getProgram(), context.getAddress(), markerType);
|
|
||||||
*//*
|
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
gotoAddress(context, address);
|
|
||||||
}
|
|
||||||
});*/
|
|
||||||
}
|
|
||||||
|
|
||||||
private void gotoAddress(ListingActionContext listingActionContext, Address address) {
|
|
||||||
if (address == null) {
|
|
||||||
tool.setStatusInfo("Unable to locate another " + getNavigationTypeName() +
|
|
||||||
" past the current range, in the current direction.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
tool.clearStatusInfo();
|
|
||||||
GoToService service = tool.getService(GoToService.class);
|
|
||||||
if (service != null) {
|
|
||||||
Navigatable navigatable = listingActionContext.getNavigatable();
|
|
||||||
gotoAddress(service, navigatable, address);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDirection(boolean isForward) {
|
|
||||||
this.isForward = isForward;
|
|
||||||
getMenuBarData().setMenuItemName(getMenuName());
|
|
||||||
setDescription(getDescription());
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getMenuName() {
|
|
||||||
String prefix = isForward ? "Next " : "Previous ";
|
|
||||||
return prefix + getNavigationTypeName();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getNavigationTypeName() {
|
|
||||||
return "Marker";
|
|
||||||
}
|
|
||||||
|
|
||||||
private KeyStroke getKeyStroke() {
|
|
||||||
return KeyStroke.getKeyStroke(KeyEvent.VK_B, InputEvent.CTRL_DOWN_MASK |
|
|
||||||
InputEvent.ALT_DOWN_MASK);
|
|
||||||
}
|
|
||||||
|
|
||||||
//==================================================================================================
|
|
||||||
// CodeViewerContextAction Methods
|
|
||||||
//==================================================================================================
|
|
||||||
@Override
|
|
||||||
public boolean isEnabledForContext(ActionContext context) {
|
|
||||||
if (!(context instanceof CodeViewerActionContext)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return isEnabledForContext((CodeViewerActionContext) context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isValidContext(ActionContext context) {
|
|
||||||
if (!(context instanceof CodeViewerActionContext)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return isValidContext((CodeViewerActionContext) context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAddToPopup(ActionContext context) {
|
|
||||||
if (!(context instanceof CodeViewerActionContext)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return isAddToPopup((CodeViewerActionContext) context);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean isValidContext(CodeViewerActionContext context) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean isEnabledForContext(CodeViewerActionContext context) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean isAddToPopup(CodeViewerActionContext context) {
|
|
||||||
return isEnabledForContext(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -128,15 +128,8 @@ public class OverviewColorPlugin extends ProgramPlugin {
|
||||||
actionMap.put(overviewColorService,
|
actionMap.put(overviewColorService,
|
||||||
new OverviewToggleAction(getName(), overviewColorService));
|
new OverviewToggleAction(getName(), overviewColorService));
|
||||||
}
|
}
|
||||||
multiAction = new MultiActionDockingAction("Overview", getName()) {
|
|
||||||
|
|
||||||
@Override
|
multiAction = new MultiActionDockingAction("Overview", getName());
|
||||||
public void actionPerformed(ActionContext context) {
|
|
||||||
// do nothing - the following setPerformActionOnButtonClick(false) will ensure
|
|
||||||
// this never gets called.
|
|
||||||
}
|
|
||||||
};
|
|
||||||
multiAction.setPerformActionOnButtonClick(false);
|
|
||||||
multiAction.setActions(new ArrayList<DockingActionIf>(actionMap.values()));
|
multiAction.setActions(new ArrayList<DockingActionIf>(actionMap.values()));
|
||||||
multiAction.setToolBarData(
|
multiAction.setToolBarData(
|
||||||
new ToolBarData(ResourceManager.loadImage("images/x-office-document-template.png")));
|
new ToolBarData(ResourceManager.loadImage("images/x-office-document-template.png")));
|
||||||
|
|
|
@ -668,8 +668,6 @@ public class ListingCodeComparisonPanel
|
||||||
setHelpLocation(helpLocation);
|
setHelpLocation(helpLocation);
|
||||||
setDescription("Set Navigate Next/Previous Area Marker options");
|
setDescription("Set Navigate Next/Previous Area Marker options");
|
||||||
|
|
||||||
setPerformActionOnPrimaryButtonClick(false);
|
|
||||||
|
|
||||||
ActionState<String> allAreaMarkers =
|
ActionState<String> allAreaMarkers =
|
||||||
new ActionState<>(ALL_AREA_MARKERS, bothIcon, ALL_AREA_MARKERS);
|
new ActionState<>(ALL_AREA_MARKERS, bothIcon, ALL_AREA_MARKERS);
|
||||||
allAreaMarkers.setHelpLocation(helpLocation);
|
allAreaMarkers.setHelpLocation(helpLocation);
|
||||||
|
|
|
@ -177,7 +177,8 @@ public class ClearTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
public void testClearActionEnablement() throws Exception {
|
public void testClearActionEnablement() throws Exception {
|
||||||
|
|
||||||
closeProgram();
|
closeProgram();
|
||||||
assertTrue(!clearAction.isEnabledForContext(new ActionContext()));
|
ActionContext context = cb.getProvider().getActionContext(null);
|
||||||
|
assertFalse(clearAction.isEnabledForContext(context));
|
||||||
|
|
||||||
showTool(tool);
|
showTool(tool);
|
||||||
loadProgram("notepad");
|
loadProgram("notepad");
|
||||||
|
@ -185,10 +186,12 @@ public class ClearTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
assertTrue(cb.goToField(addr("0x10026f0"), "Address", 0, 0));
|
assertTrue(cb.goToField(addr("0x10026f0"), "Address", 0, 0));
|
||||||
|
|
||||||
assertTrue(clearAction.isEnabled());
|
context = cb.getProvider().getActionContext(null);
|
||||||
|
assertTrue(clearAction.isEnabledForContext(context));
|
||||||
closeProgram();
|
closeProgram();
|
||||||
|
|
||||||
assertTrue(!clearAction.isEnabledForContext(new ActionContext()));
|
context = cb.getProvider().getActionContext(null);
|
||||||
|
assertFalse(clearAction.isEnabledForContext(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -453,7 +456,7 @@ public class ClearTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
Symbol[] symbols = program.getSymbolTable().getSymbols(addr("0x01001010"));
|
Symbol[] symbols = program.getSymbolTable().getSymbols(addr("0x01001010"));
|
||||||
assertEquals(1, symbols.length);
|
assertEquals(1, symbols.length);
|
||||||
assertTrue(!symbols[0].isDynamic());
|
assertFalse(symbols[0].isDynamic());
|
||||||
int id = program.startTransaction("Anchor");
|
int id = program.startTransaction("Anchor");
|
||||||
symbols[0].setPinned(true);
|
symbols[0].setPinned(true);
|
||||||
program.endTransaction(id, true);
|
program.endTransaction(id, true);
|
||||||
|
@ -467,7 +470,7 @@ public class ClearTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
symbols = program.getSymbolTable().getSymbols(addr("0x01001010"));
|
symbols = program.getSymbolTable().getSymbols(addr("0x01001010"));
|
||||||
assertEquals(1, symbols.length);
|
assertEquals(1, symbols.length);
|
||||||
assertTrue(!symbols[0].isDynamic());
|
assertFalse(symbols[0].isDynamic());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -639,7 +642,7 @@ public class ClearTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
assertTrue(l.getNumInstructions() > 0);
|
assertTrue(l.getNumInstructions() > 0);
|
||||||
assertTrue(l.getNumDefinedData() > 0);
|
assertTrue(l.getNumDefinedData() > 0);
|
||||||
|
|
||||||
assertTrue(!program.getListing().getFunctions(true).hasNext());
|
assertFalse(program.getListing().getFunctions(true).hasNext());
|
||||||
|
|
||||||
assertTrue(program.getSymbolTable().getNumSymbols() > 0);
|
assertTrue(program.getSymbolTable().getNumSymbols() > 0);
|
||||||
undo(program);
|
undo(program);
|
||||||
|
@ -674,7 +677,7 @@ public class ClearTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
okOnClearDialog();
|
okOnClearDialog();
|
||||||
|
|
||||||
assertTrue(!context.hasValueOverRange(ax, BigInteger.valueOf(5),
|
assertFalse(context.hasValueOverRange(ax, BigInteger.valueOf(5),
|
||||||
new AddressSet(addr("0x10022cc"))));
|
new AddressSet(addr("0x10022cc"))));
|
||||||
undo(program);
|
undo(program);
|
||||||
assertTrue(context.hasValueOverRange(ax, BigInteger.valueOf(5),
|
assertTrue(context.hasValueOverRange(ax, BigInteger.valueOf(5),
|
||||||
|
|
|
@ -304,13 +304,6 @@ public class NextPrevAddressPluginTest extends AbstractGhidraHeadedIntegrationTe
|
||||||
// Private Methods
|
// Private Methods
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
|
|
||||||
private ComponentProvider showDecompiler() {
|
|
||||||
ComponentProvider cp = tool.getComponentProvider("Decompiler");
|
|
||||||
tool.showComponentProvider(cp, true);
|
|
||||||
cp.requestFocus();
|
|
||||||
return cp;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void assertCurrentAddress(Address expected) {
|
private void assertCurrentAddress(Address expected) {
|
||||||
assertEquals(expected, currentAddress());
|
assertEquals(expected, currentAddress());
|
||||||
}
|
}
|
||||||
|
@ -415,8 +408,7 @@ public class NextPrevAddressPluginTest extends AbstractGhidraHeadedIntegrationTe
|
||||||
//
|
//
|
||||||
|
|
||||||
// clear the popup
|
// clear the popup
|
||||||
Object mouseAdapter = getInstanceField("popupListener", button);
|
setInstanceField("popupMenu", button, null);
|
||||||
setInstanceField("popupMenu", mouseAdapter, null);
|
|
||||||
|
|
||||||
// trigger the popup
|
// trigger the popup
|
||||||
Shape popupTriggerArea = (Shape) TestUtils.getInstanceField("popupContext", button);
|
Shape popupTriggerArea = (Shape) TestUtils.getInstanceField("popupContext", button);
|
||||||
|
@ -426,7 +418,7 @@ public class NextPrevAddressPluginTest extends AbstractGhidraHeadedIntegrationTe
|
||||||
clickMouse(button, MouseEvent.BUTTON1, x, y, 1, 0);
|
clickMouse(button, MouseEvent.BUTTON1, x, y, 1, 0);
|
||||||
|
|
||||||
// get the popup
|
// get the popup
|
||||||
JPopupMenu menu = (JPopupMenu) getInstanceField("popupMenu", mouseAdapter);
|
JPopupMenu menu = (JPopupMenu) getInstanceField("popupMenu", button);
|
||||||
assertNotNull(menu);
|
assertNotNull(menu);
|
||||||
|
|
||||||
// Note: calling clickMouse() seems to work for now. If this is not consistent, then
|
// Note: calling clickMouse() seems to work for now. If this is not consistent, then
|
||||||
|
|
|
@ -43,18 +43,17 @@ import ghidra.framework.main.datatree.DataTree;
|
||||||
import ghidra.framework.main.datatree.ProjectDataTreePanel;
|
import ghidra.framework.main.datatree.ProjectDataTreePanel;
|
||||||
import ghidra.framework.model.*;
|
import ghidra.framework.model.*;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.framework.store.LockException;
|
|
||||||
import ghidra.program.database.symbol.LibrarySymbol;
|
import ghidra.program.database.symbol.LibrarySymbol;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.Address;
|
||||||
|
import ghidra.program.model.address.AddressSpace;
|
||||||
import ghidra.program.model.listing.Function;
|
import ghidra.program.model.listing.Function;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.mem.Memory;
|
import ghidra.program.model.mem.Memory;
|
||||||
import ghidra.program.model.mem.MemoryConflictException;
|
|
||||||
import ghidra.program.model.symbol.*;
|
import ghidra.program.model.symbol.*;
|
||||||
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
||||||
import ghidra.test.TestEnv;
|
import ghidra.test.TestEnv;
|
||||||
import ghidra.util.SystemUtilities;
|
import ghidra.util.SystemUtilities;
|
||||||
import ghidra.util.exception.*;
|
import ghidra.util.exception.InvalidInputException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -158,7 +157,7 @@ public abstract class AbstractSymbolTreePluginExternalsTest
|
||||||
|
|
||||||
protected ExternalLocation setupExternalLocation(String library, String label, Address address,
|
protected ExternalLocation setupExternalLocation(String library, String label, Address address,
|
||||||
SourceType sourceType, boolean isFunction)
|
SourceType sourceType, boolean isFunction)
|
||||||
throws InvalidInputException, DuplicateNameException {
|
throws Exception {
|
||||||
boolean success = false;
|
boolean success = false;
|
||||||
int transactionID =
|
int transactionID =
|
||||||
program.startTransaction("Setting Up External Location " + library + "::" + label);
|
program.startTransaction("Setting Up External Location " + library + "::" + label);
|
||||||
|
@ -181,12 +180,12 @@ public abstract class AbstractSymbolTreePluginExternalsTest
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ExternalLocation setupExternalLocation(String library, String label, Address address,
|
protected ExternalLocation setupExternalLocation(String library, String label, Address address,
|
||||||
SourceType sourceType) throws InvalidInputException, DuplicateNameException {
|
SourceType sourceType) throws Exception {
|
||||||
return setupExternalLocation(library, label, address, sourceType, false);
|
return setupExternalLocation(library, label, address, sourceType, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ExternalLocation setupExternalFunction(String library, String label, Address address,
|
protected ExternalLocation setupExternalFunction(String library, String label, Address address,
|
||||||
SourceType sourceType) throws InvalidInputException, DuplicateNameException {
|
SourceType sourceType) throws Exception {
|
||||||
return setupExternalLocation(library, label, address, sourceType, true);
|
return setupExternalLocation(library, label, address, sourceType, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -448,8 +447,7 @@ public abstract class AbstractSymbolTreePluginExternalsTest
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addOverlayBlock(String name, String startAddress, long length)
|
protected void addOverlayBlock(String name, String startAddress, long length)
|
||||||
throws LockException, DuplicateNameException, MemoryConflictException,
|
throws Exception {
|
||||||
AddressOverflowException, CancelledException {
|
|
||||||
int transactionID = program.startTransaction("Add Overlay Block to test");
|
int transactionID = program.startTransaction("Add Overlay Block to test");
|
||||||
Address address = program.getAddressFactory().getAddress(startAddress);
|
Address address = program.getAddressFactory().getAddress(startAddress);
|
||||||
Memory memory = program.getMemory();
|
Memory memory = program.getMemory();
|
||||||
|
|
|
@ -87,7 +87,7 @@ public class CloseToolTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
assertNotNull(closeOthersAction);
|
assertNotNull(closeOthersAction);
|
||||||
ProgramActionContext context = new ProgramActionContext(null, program1);
|
ProgramActionContext context = new ProgramActionContext(null, program1);
|
||||||
assertEquals(true, closeOthersAction.isEnabledForContext(context));
|
assertEquals(true, closeOthersAction.isEnabledForContext(context));
|
||||||
performAction(closeOthersAction, true);
|
performAction(closeOthersAction, context, true);
|
||||||
|
|
||||||
allOpenPrograms = pm.getAllOpenPrograms();
|
allOpenPrograms = pm.getAllOpenPrograms();
|
||||||
assertEquals(1, allOpenPrograms.length);
|
assertEquals(1, allOpenPrograms.length);
|
||||||
|
|
|
@ -859,10 +859,10 @@ class FGActionManager {
|
||||||
HelpLocation layoutHelpLocation =
|
HelpLocation layoutHelpLocation =
|
||||||
new HelpLocation("FunctionGraphPlugin", "Function_Graph_Action_Layout");
|
new HelpLocation("FunctionGraphPlugin", "Function_Graph_Action_Layout");
|
||||||
|
|
||||||
layoutAction = new MultiStateDockingAction<>("Relayout Graph", plugin.getName(), true) {
|
layoutAction = new MultiStateDockingAction<>("Relayout Graph", plugin.getName()) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doActionPerformed(ActionContext context) {
|
public void actionPerformed(ActionContext context) {
|
||||||
// this callback is when the user clicks the button
|
// this callback is when the user clicks the button
|
||||||
FGLayoutProvider currentUserData = getCurrentUserData();
|
FGLayoutProvider currentUserData = getCurrentUserData();
|
||||||
changeLayout(currentUserData);
|
changeLayout(currentUserData);
|
||||||
|
@ -994,7 +994,6 @@ class FGActionManager {
|
||||||
};
|
};
|
||||||
vertexHoverModeAction.setGroup(group);
|
vertexHoverModeAction.setGroup(group);
|
||||||
vertexHoverModeAction.setHelpLocation(pathHelpLocation);
|
vertexHoverModeAction.setHelpLocation(pathHelpLocation);
|
||||||
vertexHoverModeAction.setPerformActionOnPrimaryButtonClick(false);
|
|
||||||
|
|
||||||
vertexHoverModeAction.addActionState(offState);
|
vertexHoverModeAction.addActionState(offState);
|
||||||
vertexHoverModeAction.addActionState(pathsForwardScopedFlow);
|
vertexHoverModeAction.addActionState(pathsForwardScopedFlow);
|
||||||
|
@ -1063,7 +1062,6 @@ class FGActionManager {
|
||||||
};
|
};
|
||||||
vertexFocusModeAction.setGroup(group);
|
vertexFocusModeAction.setGroup(group);
|
||||||
vertexFocusModeAction.setHelpLocation(pathHelpLocation);
|
vertexFocusModeAction.setHelpLocation(pathHelpLocation);
|
||||||
vertexFocusModeAction.setPerformActionOnPrimaryButtonClick(false);
|
|
||||||
|
|
||||||
vertexFocusModeAction.addActionState(offState);
|
vertexFocusModeAction.addActionState(offState);
|
||||||
vertexFocusModeAction.addActionState(pathsForwardScopedFlow);
|
vertexFocusModeAction.addActionState(pathsForwardScopedFlow);
|
||||||
|
|
|
@ -526,7 +526,7 @@ public class FcgProvider
|
||||||
RELAYOUT_GRAPH_ACTION_NAME, plugin.getName()) {
|
RELAYOUT_GRAPH_ACTION_NAME, plugin.getName()) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doActionPerformed(ActionContext context) {
|
public void actionPerformed(ActionContext context) {
|
||||||
// this callback is when the user clicks the button
|
// this callback is when the user clicks the button
|
||||||
LayoutProvider<FcgVertex, FcgEdge, FunctionCallGraph> currentUserData =
|
LayoutProvider<FcgVertex, FcgEdge, FunctionCallGraph> currentUserData =
|
||||||
getCurrentUserData();
|
getCurrentUserData();
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,19 +16,20 @@
|
||||||
package ghidra.feature.vt.gui.actions;
|
package ghidra.feature.vt.gui.actions;
|
||||||
|
|
||||||
import static ghidra.feature.vt.gui.actions.TableSelectionTrackingState.*;
|
import static ghidra.feature.vt.gui.actions.TableSelectionTrackingState.*;
|
||||||
import ghidra.feature.vt.gui.plugin.VTPlugin;
|
|
||||||
import ghidra.feature.vt.gui.provider.matchtable.VTMatchTableProvider;
|
|
||||||
import ghidra.util.HelpLocation;
|
|
||||||
|
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
|
|
||||||
import resources.ResourceManager;
|
|
||||||
import docking.action.ToolBarData;
|
import docking.action.ToolBarData;
|
||||||
import docking.menu.ActionState;
|
import docking.menu.ActionState;
|
||||||
import docking.menu.MultiStateDockingAction;
|
import docking.menu.MultiStateDockingAction;
|
||||||
import docking.widgets.EventTrigger;
|
import docking.widgets.EventTrigger;
|
||||||
|
import ghidra.feature.vt.gui.plugin.VTPlugin;
|
||||||
|
import ghidra.feature.vt.gui.provider.matchtable.VTMatchTableProvider;
|
||||||
|
import ghidra.util.HelpLocation;
|
||||||
|
import resources.ResourceManager;
|
||||||
|
|
||||||
public class MatchTableSelectionAction extends MultiStateDockingAction<TableSelectionTrackingState> {
|
public class MatchTableSelectionAction
|
||||||
|
extends MultiStateDockingAction<TableSelectionTrackingState> {
|
||||||
|
|
||||||
private static final String MENU_GROUP = VTPlugin.VT_SETTINGS_MENU_GROUP;
|
private static final String MENU_GROUP = VTPlugin.VT_SETTINGS_MENU_GROUP;
|
||||||
|
|
||||||
|
@ -44,7 +44,6 @@ public class MatchTableSelectionAction extends MultiStateDockingAction<TableSele
|
||||||
setToolBarData(new ToolBarData(null, MENU_GROUP));
|
setToolBarData(new ToolBarData(null, MENU_GROUP));
|
||||||
setDescription("Adjust the Apply Mark-up Settings for Applying Matches");
|
setDescription("Adjust the Apply Mark-up Settings for Applying Matches");
|
||||||
setEnabled(true);
|
setEnabled(true);
|
||||||
setPerformActionOnPrimaryButtonClick(false); // pressing button shows drop-down
|
|
||||||
|
|
||||||
HelpLocation helpLocation =
|
HelpLocation helpLocation =
|
||||||
new HelpLocation("VersionTrackingPlugin", "Match_Table_Selection");
|
new HelpLocation("VersionTrackingPlugin", "Match_Table_Selection");
|
||||||
|
@ -55,17 +54,17 @@ public class MatchTableSelectionAction extends MultiStateDockingAction<TableSele
|
||||||
Icon trackRowIndexSelectionIcon = ResourceManager.loadImage("images/table_gear.png");
|
Icon trackRowIndexSelectionIcon = ResourceManager.loadImage("images/table_gear.png");
|
||||||
|
|
||||||
ActionState<TableSelectionTrackingState> trackSelectedIndexActionState =
|
ActionState<TableSelectionTrackingState> trackSelectedIndexActionState =
|
||||||
new ActionState<TableSelectionTrackingState>("Track Selected Index",
|
new ActionState<>("Track Selected Index",
|
||||||
trackRowIndexSelectionIcon, MAINTAIN_SELECTED_ROW_INDEX);
|
trackRowIndexSelectionIcon, MAINTAIN_SELECTED_ROW_INDEX);
|
||||||
trackSelectedIndexActionState.setHelpLocation(helpLocation);
|
trackSelectedIndexActionState.setHelpLocation(helpLocation);
|
||||||
|
|
||||||
ActionState<TableSelectionTrackingState> trackMatchSelectionActionState =
|
ActionState<TableSelectionTrackingState> trackMatchSelectionActionState =
|
||||||
new ActionState<TableSelectionTrackingState>("Track Selected Match",
|
new ActionState<>("Track Selected Match",
|
||||||
trackMatchSelectionIcon, MAINTAIN_SELECTED_ROW_VALUE);
|
trackMatchSelectionIcon, MAINTAIN_SELECTED_ROW_VALUE);
|
||||||
trackMatchSelectionActionState.setHelpLocation(helpLocation);
|
trackMatchSelectionActionState.setHelpLocation(helpLocation);
|
||||||
|
|
||||||
ActionState<TableSelectionTrackingState> noSelectionTrackingActionState =
|
ActionState<TableSelectionTrackingState> noSelectionTrackingActionState =
|
||||||
new ActionState<TableSelectionTrackingState>("No Selection Tracking",
|
new ActionState<>("No Selection Tracking",
|
||||||
noSelectionTrackingIcon, NO_SELECTION_TRACKING);
|
noSelectionTrackingIcon, NO_SELECTION_TRACKING);
|
||||||
noSelectionTrackingActionState.setHelpLocation(helpLocation);
|
noSelectionTrackingActionState.setHelpLocation(helpLocation);
|
||||||
|
|
||||||
|
|
|
@ -15,12 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.feature.vt.gui.provider.functionassociation;
|
package ghidra.feature.vt.gui.provider.functionassociation;
|
||||||
|
|
||||||
import static ghidra.feature.vt.api.impl.VTChangeManager.DOCR_VT_ASSOCIATION_STATUS_CHANGED;
|
import static ghidra.feature.vt.api.impl.VTChangeManager.*;
|
||||||
import static ghidra.feature.vt.api.impl.VTChangeManager.DOCR_VT_MATCH_ADDED;
|
import static ghidra.feature.vt.gui.provider.functionassociation.FilterSettings.*;
|
||||||
import static ghidra.feature.vt.api.impl.VTChangeManager.DOCR_VT_MATCH_DELETED;
|
|
||||||
import static ghidra.feature.vt.gui.provider.functionassociation.FilterSettings.SHOW_ALL;
|
|
||||||
import static ghidra.feature.vt.gui.provider.functionassociation.FilterSettings.SHOW_UNACCEPTED;
|
|
||||||
import static ghidra.feature.vt.gui.provider.functionassociation.FilterSettings.SHOW_UNMATCHED;
|
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.*;
|
import java.awt.event.*;
|
||||||
|
@ -156,6 +152,7 @@ public class VTFunctionAssociationProvider extends ComponentProviderAdapter
|
||||||
destinationFunctionsModel.setFilterSettings(filterSettings);
|
destinationFunctionsModel.setFilterSettings(filterSettings);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
filterAction.setHelpLocation(new HelpLocation("VersionTrackingPlugin", "Functions_Filter"));
|
filterAction.setHelpLocation(new HelpLocation("VersionTrackingPlugin", "Functions_Filter"));
|
||||||
|
|
||||||
Icon allFunctionsIcon = ResourceManager.loadImage("images/function.png");
|
Icon allFunctionsIcon = ResourceManager.loadImage("images/function.png");
|
||||||
|
|
|
@ -31,10 +31,6 @@ public class MultiActionBuilder
|
||||||
* List of actions for the the MultActionDockingAction
|
* List of actions for the the MultActionDockingAction
|
||||||
*/
|
*/
|
||||||
private List<DockingActionIf> actionList = Collections.emptyList();
|
private List<DockingActionIf> actionList = Collections.emptyList();
|
||||||
/**
|
|
||||||
* determines if the the main action is invokable
|
|
||||||
*/
|
|
||||||
private boolean performActionOnButtonClick = true;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builder constructor
|
* Builder constructor
|
||||||
|
@ -61,7 +57,6 @@ public class MultiActionBuilder
|
||||||
};
|
};
|
||||||
decorateAction(action);
|
decorateAction(action);
|
||||||
action.setActions(actionList);
|
action.setActions(actionList);
|
||||||
action.setPerformActionOnButtonClick(performActionOnButtonClick);
|
|
||||||
return action;
|
return action;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,26 +76,8 @@ public class MultiActionBuilder
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Configure whether to perform actions on a button click.
|
|
||||||
* See {@link MultiActionDockingAction#setPerformActionOnButtonClick(boolean)}
|
|
||||||
*
|
|
||||||
* @param b true if the main action is invokable
|
|
||||||
* @return this MultiActionDockingActionBuilder (for chaining)
|
|
||||||
*/
|
|
||||||
public MultiActionBuilder performActionOnButtonClick(boolean b) {
|
|
||||||
this.performActionOnButtonClick = b;
|
|
||||||
return self();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void validate() {
|
protected void validate() {
|
||||||
// if the MultiAction performs an action when the main button is presseed, make sure that
|
|
||||||
// an action callback has been defined in before building (which is what super validate
|
|
||||||
// does). Otherwise, don't force the client to define an action callback if it won't be used.
|
|
||||||
if (performActionOnButtonClick) {
|
|
||||||
super.validate();
|
|
||||||
}
|
|
||||||
if (actionList == null) {
|
if (actionList == null) {
|
||||||
throw new IllegalStateException("No ActionList has been set");
|
throw new IllegalStateException("No ActionList has been set");
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,8 @@ import java.util.function.BiConsumer;
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
|
|
||||||
import docking.ActionContext;
|
import docking.ActionContext;
|
||||||
import docking.menu.*;
|
import docking.menu.ActionState;
|
||||||
|
import docking.menu.MultiStateDockingAction;
|
||||||
import docking.widgets.EventTrigger;
|
import docking.widgets.EventTrigger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,7 +36,6 @@ public class MultiStateActionBuilder<T> extends
|
||||||
|
|
||||||
private BiConsumer<ActionState<T>, EventTrigger> actionStateChangedCallback;
|
private BiConsumer<ActionState<T>, EventTrigger> actionStateChangedCallback;
|
||||||
private boolean useCheckboxForIcons;
|
private boolean useCheckboxForIcons;
|
||||||
private boolean performActionOnButtonClick = false;
|
|
||||||
|
|
||||||
private List<ActionState<T>> states = new ArrayList<>();
|
private List<ActionState<T>> states = new ArrayList<>();
|
||||||
|
|
||||||
|
@ -68,18 +68,6 @@ public class MultiStateActionBuilder<T> extends
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Configure whether to perform actions on a button click.
|
|
||||||
* See {@link MultiActionDockingAction#setPerformActionOnButtonClick(boolean)}
|
|
||||||
*
|
|
||||||
* @param b true if the main action is invokable
|
|
||||||
* @return this MultiActionDockingActionBuilder (for chaining)
|
|
||||||
*/
|
|
||||||
public MultiStateActionBuilder<T> performActionOnButtonClick(boolean b) {
|
|
||||||
this.performActionOnButtonClick = b;
|
|
||||||
return self();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overrides the default icons for actions shown in popup menu of the multi-state action. By
|
* Overrides the default icons for actions shown in popup menu of the multi-state action. By
|
||||||
* default, the popup menu items will use the icons as provided by the {@link ActionState}.
|
* default, the popup menu items will use the icons as provided by the {@link ActionState}.
|
||||||
|
@ -103,7 +91,7 @@ public class MultiStateActionBuilder<T> extends
|
||||||
* @return this MultiActionDockingActionBuilder (for chaining)
|
* @return this MultiActionDockingActionBuilder (for chaining)
|
||||||
*/
|
*/
|
||||||
public MultiStateActionBuilder<T> addState(String displayName, Icon icon, T userData) {
|
public MultiStateActionBuilder<T> addState(String displayName, Icon icon, T userData) {
|
||||||
states.add(new ActionState<T>(displayName, icon, userData));
|
states.add(new ActionState<>(displayName, icon, userData));
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +121,7 @@ public class MultiStateActionBuilder<T> extends
|
||||||
public MultiStateDockingAction<T> build() {
|
public MultiStateDockingAction<T> build() {
|
||||||
validate();
|
validate();
|
||||||
MultiStateDockingAction<T> action =
|
MultiStateDockingAction<T> action =
|
||||||
new MultiStateDockingAction<>(name, owner, isToolbarAction()) {
|
new MultiStateDockingAction<>(name, owner) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionStateChanged(ActionState<T> newActionState,
|
public void actionStateChanged(ActionState<T> newActionState,
|
||||||
|
@ -142,10 +130,13 @@ public class MultiStateActionBuilder<T> extends
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doActionPerformed(ActionContext context) {
|
public void actionPerformed(ActionContext context) {
|
||||||
if (actionCallback != null) {
|
if (actionCallback != null) {
|
||||||
actionCallback.accept(context);
|
actionCallback.accept(context);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
super.actionPerformed(context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -154,16 +145,12 @@ public class MultiStateActionBuilder<T> extends
|
||||||
}
|
}
|
||||||
|
|
||||||
decorateAction(action);
|
decorateAction(action);
|
||||||
action.setPerformActionOnPrimaryButtonClick(performActionOnButtonClick);
|
|
||||||
action.setUseCheckboxForIcons(useCheckboxForIcons);
|
action.setUseCheckboxForIcons(useCheckboxForIcons);
|
||||||
return action;
|
return action;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void validate() {
|
protected void validate() {
|
||||||
if (performActionOnButtonClick) {
|
|
||||||
super.validate(); // require an action callback has been defined
|
|
||||||
}
|
|
||||||
if (actionStateChangedCallback == null) {
|
if (actionStateChangedCallback == null) {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"Can't build a MultiStateDockingAction without an action state changed callback");
|
"Can't build a MultiStateDockingAction without an action state changed callback");
|
||||||
|
|
|
@ -22,13 +22,14 @@ import javax.swing.JButton;
|
||||||
|
|
||||||
import docking.ActionContext;
|
import docking.ActionContext;
|
||||||
import docking.action.*;
|
import docking.action.*;
|
||||||
|
import ghidra.util.Swing;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class that supports multiple sub-actions, as well as a primary action. This is useful for
|
* A class that supports multiple sub-actions, as well as a primary action. This is useful for
|
||||||
* actions that perform navigation operations.
|
* actions that perform navigation operations.
|
||||||
* <p>
|
* <p>
|
||||||
* Clients may add actions to this class with the intention that they will be accessible
|
* Clients may add actions to this class with the intention that they will be accessible to the
|
||||||
* to the user via a GUI; for example, from a popup menu.
|
* user via a GUI; for example, from a popup menu.
|
||||||
* <p>
|
* <p>
|
||||||
* Actions added must have menu bar data set.
|
* Actions added must have menu bar data set.
|
||||||
*
|
*
|
||||||
|
@ -36,18 +37,20 @@ import docking.action.*;
|
||||||
* the user to execute.
|
* the user to execute.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* If the user executes this action directly, then
|
* If the user executes this action directly (by clicking the non-popup section of the button),
|
||||||
* {@link #actionPerformed(ActionContext)} will be called. Otherwise, the
|
* then {@link #actionPerformed(ActionContext)} will be called. By default, when the button is
|
||||||
* {@link DockingAction#actionPerformed(ActionContext)} method of the sub-action
|
* clicked, the popup menu is shown. To change this behavior, override
|
||||||
* that was executed will be called.
|
* {@link #actionPerformed(ActionContext)}. If an item of the popup menu is clicked, then the
|
||||||
|
* {@link DockingAction#actionPerformed(ActionContext)} method of the sub-action that was executed
|
||||||
|
* will be called.
|
||||||
*
|
*
|
||||||
* @see MultiStateDockingAction
|
* @see MultiStateDockingAction
|
||||||
*/
|
*/
|
||||||
public abstract class MultiActionDockingAction extends DockingAction
|
public class MultiActionDockingAction extends DockingAction
|
||||||
implements MultiActionDockingActionIf {
|
implements MultiActionDockingActionIf {
|
||||||
|
|
||||||
private List<DockingActionIf> actionList = Collections.emptyList();
|
private List<DockingActionIf> actionList = Collections.emptyList();
|
||||||
private boolean performActionOnButtonClick = true;
|
private MultipleActionDockingToolbarButton multipleButton;
|
||||||
|
|
||||||
public MultiActionDockingAction(String name, String owner) {
|
public MultiActionDockingAction(String name, String owner) {
|
||||||
super(name, owner);
|
super(name, owner);
|
||||||
|
@ -67,24 +70,23 @@ public abstract class MultiActionDockingAction extends DockingAction
|
||||||
return actionList;
|
return actionList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called when the user clicks the button <B>when this action is used as part of
|
||||||
|
* the default {@link DockingAction} framework.</B>
|
||||||
|
*
|
||||||
|
* This is the callback to be overridden when the child wishes to respond to user button
|
||||||
|
* presses that are on the button and not the drop-down. The default behavior is to show the
|
||||||
|
* popup menu when the button is clicked.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public JButton doCreateButton() {
|
public void actionPerformed(ActionContext context) {
|
||||||
MultipleActionDockingToolbarButton button = new MultipleActionDockingToolbarButton(this);
|
Swing.runLater(() -> multipleButton.showPopup());
|
||||||
button.setPerformActionOnButtonClick(performActionOnButtonClick);
|
|
||||||
return button;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* By default a click on this action will trigger <code>actionPerformed()</code> to be called.
|
public JButton doCreateButton() {
|
||||||
* You can call this method to disable that feature. When called with <code>false</code>, this
|
multipleButton = new MultipleActionDockingToolbarButton(this);
|
||||||
* method will effectively let the user click anywhere on the button or its drop-down arrow
|
return multipleButton;
|
||||||
* to show the popup menu. During normal operation, the user can only show the popup by
|
|
||||||
* clicking the drop-down arrow.
|
|
||||||
* @param performActionOnButtonClick if true, pressing the button calls actionPerformed;
|
|
||||||
* otherwise it pops up the menu.
|
|
||||||
*/
|
|
||||||
public void setPerformActionOnButtonClick(boolean performActionOnButtonClick) {
|
|
||||||
this.performActionOnButtonClick = performActionOnButtonClick;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DockingActionIf createSeparator() {
|
public static DockingActionIf createSeparator() {
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package docking.menu;
|
package docking.menu;
|
||||||
|
|
||||||
import java.awt.event.ActionListener;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -23,24 +22,23 @@ import javax.swing.Icon;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
|
|
||||||
import docking.ActionContext;
|
import docking.ActionContext;
|
||||||
import docking.DockingWindowManager;
|
|
||||||
import docking.action.*;
|
import docking.action.*;
|
||||||
import docking.widgets.EventTrigger;
|
import docking.widgets.EventTrigger;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
import ghidra.util.SystemUtilities;
|
import ghidra.util.Swing;
|
||||||
import ghidra.util.exception.AssertException;
|
import ghidra.util.exception.AssertException;
|
||||||
import resources.icons.EmptyIcon;
|
import resources.icons.EmptyIcon;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An action that can be in one of multiple states. The button of this action has a
|
* An action that can be in one of multiple states. The button of this action has a
|
||||||
* drop-down icon that allows users to change the state of the button. Also, by default, as
|
* drop-down icon that allows users to change the state of the button. As the user changes the
|
||||||
* the user presses the button, it will execute the action corresponding to the current
|
* state of this action, {@link #actionStateChanged(ActionState, EventTrigger)} will be called.
|
||||||
* state.
|
* Clients may also use the button of this action to respond to button presses by overriding
|
||||||
|
* {@link #actionPerformed(ActionContext)}.
|
||||||
*
|
*
|
||||||
* <p>Warning: if you use this action in a toolbar, then be sure to call the
|
* <p>This action is intended primarily for use as toolbar actions. Alternatively, some clients
|
||||||
* {@link #MultiStateDockingAction(String, String, boolean) correct constructor}. If you call
|
* use this action to add a button to custom widgets. In the custom usage case, clients should use
|
||||||
* another constructor, or pass false for this boolean above, your
|
* {@link NonToolbarMultiStateAction}.
|
||||||
* {@link #doActionPerformed(ActionContext)} method will get called twice.
|
|
||||||
*
|
*
|
||||||
* @param <T> the type of the user data
|
* @param <T> the type of the user data
|
||||||
* @see MultiActionDockingAction
|
* @see MultiActionDockingAction
|
||||||
|
@ -54,16 +52,9 @@ public abstract class MultiStateDockingAction<T> extends DockingAction {
|
||||||
private MultiActionDockingActionIf multiActionGenerator;
|
private MultiActionDockingActionIf multiActionGenerator;
|
||||||
private MultipleActionDockingToolbarButton multipleButton;
|
private MultipleActionDockingToolbarButton multipleButton;
|
||||||
|
|
||||||
private boolean performActionOnPrimaryButtonClick = true;
|
|
||||||
private Icon defaultIcon;
|
private Icon defaultIcon;
|
||||||
private boolean useCheckboxForIcons;
|
private boolean useCheckboxForIcons;
|
||||||
|
|
||||||
// A listener that will get called when the button (not the popup) is clicked. Toolbar
|
|
||||||
// actions do not use this listener.
|
|
||||||
private ActionListener clickListener = e -> {
|
|
||||||
// stub for toolbar actions
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call this constructor with this action will not be added to a toolbar
|
* Call this constructor with this action will not be added to a toolbar
|
||||||
*
|
*
|
||||||
|
@ -72,7 +63,11 @@ public abstract class MultiStateDockingAction<T> extends DockingAction {
|
||||||
* @see #MultiStateDockingAction(String, String, boolean)
|
* @see #MultiStateDockingAction(String, String, boolean)
|
||||||
*/
|
*/
|
||||||
public MultiStateDockingAction(String name, String owner) {
|
public MultiStateDockingAction(String name, String owner) {
|
||||||
this(name, owner, false);
|
super(name, owner);
|
||||||
|
multiActionGenerator = context -> getStateActions();
|
||||||
|
|
||||||
|
// set this here so we don't have to check for null elsewhere
|
||||||
|
super.setToolBarData(new ToolBarData(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -82,50 +77,31 @@ public abstract class MultiStateDockingAction<T> extends DockingAction {
|
||||||
* @param name the action name
|
* @param name the action name
|
||||||
* @param owner the owner
|
* @param owner the owner
|
||||||
* @param isToolbarAction true if this action is a toolbar action
|
* @param isToolbarAction true if this action is a toolbar action
|
||||||
|
* @deprecated use {@link #MultiStateDockingAction(String, String)}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(forRemoval = true, since = "10.2")
|
||||||
protected MultiStateDockingAction(String name, String owner, boolean isToolbarAction) {
|
protected MultiStateDockingAction(String name, String owner, boolean isToolbarAction) {
|
||||||
super(name, owner);
|
this(name, owner);
|
||||||
multiActionGenerator = context -> getStateActions();
|
|
||||||
|
|
||||||
// set this here so we don't have to check for null elsewhere
|
|
||||||
super.setToolBarData(new ToolBarData(null));
|
|
||||||
|
|
||||||
if (!isToolbarAction) {
|
|
||||||
// we need this listener to perform the action when the user click the button;
|
|
||||||
// toolbar actions have their own listener
|
|
||||||
clickListener = e -> {
|
|
||||||
actionPerformed(getActionContext());
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will be called as the user changes the selected button state
|
||||||
|
* @param newActionState the newly selected state
|
||||||
|
* @param trigger the source of the event
|
||||||
|
*/
|
||||||
public abstract void actionStateChanged(ActionState<T> newActionState, EventTrigger trigger);
|
public abstract void actionStateChanged(ActionState<T> newActionState, EventTrigger trigger);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If <code>doPerformAction</code> is <code>true</code>, then, when the user clicks the
|
* This method is called when the user clicks the button <B>when this action is used as part of
|
||||||
* button and not the drop-down arrow, the {@link #doActionPerformed(ActionContext)}
|
* the default {@link DockingAction} framework.</B>
|
||||||
* method will be called. If <code>doPerformAction</code> is <code>false</code>, then, when
|
|
||||||
* the user clicks the button and not the drop-down arrow, the popup menu will be shown, just
|
|
||||||
* as if the user had clicked the drop-down arrow.
|
|
||||||
* <p>
|
|
||||||
* Also, if the parameter is true, then the button will behave like a button in terms of
|
|
||||||
* mouse feedback. If false, then the button will behave more like a label.
|
|
||||||
*
|
*
|
||||||
* @param doPerformAction true to call {@link #doActionPerformed(ActionContext)} when the
|
* This is the callback to be overridden when the child wishes to respond to user button
|
||||||
* user presses the button for this action (not the drop-down menu; see above)
|
* presses that are on the button and not the drop-down. The default behavior is to show the
|
||||||
|
* popup menu when the button is clicked.
|
||||||
*/
|
*/
|
||||||
public void setPerformActionOnPrimaryButtonClick(boolean doPerformAction) {
|
@Override
|
||||||
performActionOnPrimaryButtonClick = doPerformAction;
|
public void actionPerformed(ActionContext context) {
|
||||||
if (multipleButton == null) {
|
Swing.runLater(() -> multipleButton.showPopup());
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
multipleButton.setPerformActionOnButtonClick(performActionOnPrimaryButtonClick);
|
|
||||||
|
|
||||||
multipleButton.removeActionListener(clickListener);
|
|
||||||
if (performActionOnPrimaryButtonClick) {
|
|
||||||
multipleButton.addActionListener(clickListener);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -151,38 +127,6 @@ public abstract class MultiStateDockingAction<T> extends DockingAction {
|
||||||
this.defaultIcon = icon;
|
this.defaultIcon = icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void actionPerformed(ActionContext context) {
|
|
||||||
if (!performActionOnPrimaryButtonClick) {
|
|
||||||
SystemUtilities.runSwingLater(() -> multipleButton.showPopup(null));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
doActionPerformed(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is the callback to be overridden when the child wishes to respond to user button
|
|
||||||
* presses that are on the button and not the drop-down. This will only be called if
|
|
||||||
* {@link #performActionOnPrimaryButtonClick} is true.
|
|
||||||
*
|
|
||||||
* @param context the action context
|
|
||||||
*/
|
|
||||||
protected void doActionPerformed(ActionContext context) {
|
|
||||||
// override me to do work
|
|
||||||
}
|
|
||||||
|
|
||||||
private ActionContext getActionContext() {
|
|
||||||
DockingWindowManager manager = DockingWindowManager.getActiveInstance();
|
|
||||||
|
|
||||||
ActionContext context = manager.getActionContext(this);
|
|
||||||
|
|
||||||
if (context == null) {
|
|
||||||
context = new ActionContext();
|
|
||||||
}
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected List<DockingActionIf> getStateActions() {
|
protected List<DockingActionIf> getStateActions() {
|
||||||
ActionState<T> selectedState = actionStates.get(currentStateIndex);
|
ActionState<T> selectedState = actionStates.get(currentStateIndex);
|
||||||
List<DockingActionIf> actions = new ArrayList<>(actionStates.size());
|
List<DockingActionIf> actions = new ArrayList<>(actionStates.size());
|
||||||
|
@ -295,15 +239,6 @@ public abstract class MultiStateDockingAction<T> extends DockingAction {
|
||||||
@Override
|
@Override
|
||||||
public JButton doCreateButton() {
|
public JButton doCreateButton() {
|
||||||
multipleButton = new MultipleActionDockingToolbarButton(multiActionGenerator);
|
multipleButton = new MultipleActionDockingToolbarButton(multiActionGenerator);
|
||||||
multipleButton.setPerformActionOnButtonClick(performActionOnPrimaryButtonClick);
|
|
||||||
|
|
||||||
if (performActionOnPrimaryButtonClick) {
|
|
||||||
multipleButton.addActionListener(clickListener);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
multipleButton.removeActionListener(clickListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentStateIndex >= 0) {
|
if (currentStateIndex >= 0) {
|
||||||
ActionState<T> actionState = actionStates.get(currentStateIndex);
|
ActionState<T> actionState = actionStates.get(currentStateIndex);
|
||||||
setButtonState(actionState);
|
setButtonState(actionState);
|
||||||
|
@ -350,6 +285,10 @@ public abstract class MultiStateDockingAction<T> extends DockingAction {
|
||||||
return getName() + ": " + getCurrentState().getName();
|
return getName() + ": " + getCurrentState().getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void showPopup() {
|
||||||
|
multipleButton.showPopup();
|
||||||
|
}
|
||||||
|
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
// Inner Classes
|
// Inner Classes
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
|
|
|
@ -43,11 +43,11 @@ public class MultipleActionDockingToolbarButton extends EmptyBorderButton {
|
||||||
private static int ARROW_PADDING = 4;
|
private static int ARROW_PADDING = 4;
|
||||||
|
|
||||||
private PopupMouseListener popupListener;
|
private PopupMouseListener popupListener;
|
||||||
|
private JPopupMenu popupMenu;
|
||||||
private Shape popupContext;
|
private Shape popupContext;
|
||||||
|
private long popupLastClosedTime;
|
||||||
|
|
||||||
private final MultiActionDockingActionIf multipleAction;
|
private final MultiActionDockingActionIf multipleAction;
|
||||||
private boolean iconBorderEnabled = true;
|
|
||||||
private boolean entireButtonShowsPopupMenu;
|
|
||||||
|
|
||||||
public MultipleActionDockingToolbarButton(MultiActionDockingActionIf action) {
|
public MultipleActionDockingToolbarButton(MultiActionDockingActionIf action) {
|
||||||
multipleAction = action;
|
multipleAction = action;
|
||||||
|
@ -74,21 +74,6 @@ public class MultipleActionDockingToolbarButton extends EmptyBorderButton {
|
||||||
return disabledIcon;
|
return disabledIcon;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* By default a click on this button will trigger <code>actionPerformed()</code> to be called.
|
|
||||||
* You can call this method to disable that feature. When called with <code>false</code>, this
|
|
||||||
* method will effectively let the user click anywhere on the button or its drop-down arrow
|
|
||||||
* to show the popup menu. During normal operation, the user can only show the popup by
|
|
||||||
* clicking the drop-down arrow.
|
|
||||||
*
|
|
||||||
* @param performActionOnButtonClick true to perform the action when the button is clicked
|
|
||||||
*/
|
|
||||||
public void setPerformActionOnButtonClick(boolean performActionOnButtonClick) {
|
|
||||||
entireButtonShowsPopupMenu = !performActionOnButtonClick;
|
|
||||||
iconBorderEnabled = performActionOnButtonClick;
|
|
||||||
popupContext = createPopupContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintBorder(Graphics g) {
|
protected void paintBorder(Graphics g) {
|
||||||
Border buttonBorder = getBorder();
|
Border buttonBorder = getBorder();
|
||||||
|
@ -98,10 +83,7 @@ public class MultipleActionDockingToolbarButton extends EmptyBorderButton {
|
||||||
|
|
||||||
Insets borderInsets = buttonBorder.getBorderInsets(this);
|
Insets borderInsets = buttonBorder.getBorderInsets(this);
|
||||||
int leftIconWidth = primaryIcon.getIconWidth() + (borderInsets.left + borderInsets.right);
|
int leftIconWidth = primaryIcon.getIconWidth() + (borderInsets.left + borderInsets.right);
|
||||||
if (iconBorderEnabled) {
|
|
||||||
buttonBorder.paintBorder(this, g, 0, 0, leftIconWidth, getHeight());
|
buttonBorder.paintBorder(this, g, 0, 0, leftIconWidth, getHeight());
|
||||||
}
|
|
||||||
|
|
||||||
int rightButtonWidth =
|
int rightButtonWidth =
|
||||||
ARROW_WIDTH + ARROW_PADDING + (borderInsets.left + borderInsets.right);
|
ARROW_WIDTH + ARROW_PADDING + (borderInsets.left + borderInsets.right);
|
||||||
buttonBorder.paintBorder(this, g, leftIconWidth, 0, rightButtonWidth, getHeight());
|
buttonBorder.paintBorder(this, g, leftIconWidth, 0, rightButtonWidth, getHeight());
|
||||||
|
@ -132,10 +114,6 @@ public class MultipleActionDockingToolbarButton extends EmptyBorderButton {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Shape createPopupContext() {
|
private Shape createPopupContext() {
|
||||||
if (entireButtonShowsPopupMenu) {
|
|
||||||
return new Rectangle(0, 0, getWidth(), getHeight());
|
|
||||||
}
|
|
||||||
|
|
||||||
Border buttonBorder = getBorder();
|
Border buttonBorder = getBorder();
|
||||||
Insets borderInsets =
|
Insets borderInsets =
|
||||||
buttonBorder == null ? new Insets(0, 0, 0, 0) : buttonBorder.getBorderInsets(this);
|
buttonBorder == null ? new Insets(0, 0, 0, 0) : buttonBorder.getBorderInsets(this);
|
||||||
|
@ -163,10 +141,31 @@ public class MultipleActionDockingToolbarButton extends EmptyBorderButton {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show a popup containing all the actions below the button
|
* Show a popup containing all the actions below the button
|
||||||
* @param listener for the created popup menu
|
|
||||||
* @return the popup menu that was shown
|
* @return the popup menu that was shown
|
||||||
*/
|
*/
|
||||||
JPopupMenu showPopup(PopupMenuListener listener) {
|
JPopupMenu showPopup() {
|
||||||
|
|
||||||
|
if (popupIsShowing()) {
|
||||||
|
popupMenu.setVisible(false);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// showPopup() will handled 2 cases when this action's button is clicked:
|
||||||
|
// 1) show a popup if it was not showing
|
||||||
|
// 2) hide the popup if it was showing
|
||||||
|
//
|
||||||
|
// Case 2 requires timestamps. Java will close the popup as the button is clicked. This
|
||||||
|
// means that when we are told to show the popup as the result of a click, the popup will
|
||||||
|
// never be showing. To work around this, we track the elapsed time since last click. If
|
||||||
|
// the period is too short, then we assume Java closed the popup when the click happened
|
||||||
|
//and thus we should ignore it.
|
||||||
|
//
|
||||||
|
long elapsedTime = System.currentTimeMillis() - popupLastClosedTime;
|
||||||
|
if (elapsedTime < 500) { // somewhat arbitrary time window
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
JPopupMenu menu = new JPopupMenu();
|
JPopupMenu menu = new JPopupMenu();
|
||||||
List<DockingActionIf> actionList = multipleAction.getActionList(getActionContext());
|
List<DockingActionIf> actionList = multipleAction.getActionList(getActionContext());
|
||||||
for (DockingActionIf dockingAction : actionList) {
|
for (DockingActionIf dockingAction : actionList) {
|
||||||
|
@ -202,9 +201,7 @@ public class MultipleActionDockingToolbarButton extends EmptyBorderButton {
|
||||||
menu.add(item);
|
menu.add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listener != null) {
|
menu.addPopupMenuListener(popupListener);
|
||||||
menu.addPopupMenuListener(listener);
|
|
||||||
}
|
|
||||||
Point p = getPopupPoint();
|
Point p = getPopupPoint();
|
||||||
menu.show(this, p.x, p.y);
|
menu.show(this, p.x, p.y);
|
||||||
return menu;
|
return menu;
|
||||||
|
@ -215,6 +212,10 @@ public class MultipleActionDockingToolbarButton extends EmptyBorderButton {
|
||||||
return new Point(0, bounds.y + bounds.height);
|
return new Point(0, bounds.y + bounds.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean popupIsShowing() {
|
||||||
|
return (popupMenu != null) && popupMenu.isVisible();
|
||||||
|
}
|
||||||
|
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
// Inner Classes
|
// Inner Classes
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
|
@ -285,8 +286,6 @@ public class MultipleActionDockingToolbarButton extends EmptyBorderButton {
|
||||||
|
|
||||||
private class PopupMouseListener extends MouseAdapter implements PopupMenuListener {
|
private class PopupMouseListener extends MouseAdapter implements PopupMenuListener {
|
||||||
private final MouseListener[] parentListeners;
|
private final MouseListener[] parentListeners;
|
||||||
private JPopupMenu popupMenu;
|
|
||||||
private long actionID = 0; // used to determine when the popup was closed by clicking the button
|
|
||||||
|
|
||||||
public PopupMouseListener(MouseListener[] parentListeners) {
|
public PopupMouseListener(MouseListener[] parentListeners) {
|
||||||
this.parentListeners = parentListeners;
|
this.parentListeners = parentListeners;
|
||||||
|
@ -294,16 +293,6 @@ public class MultipleActionDockingToolbarButton extends EmptyBorderButton {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mousePressed(MouseEvent e) {
|
public void mousePressed(MouseEvent e) {
|
||||||
// close the popup if the user clicks the button while the popup is visible
|
|
||||||
if (popupIsShowing() && e.getClickCount() == 1) { // ignore double-click when the menu is up
|
|
||||||
popupMenu.setVisible(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
long eventTime = System.currentTimeMillis();
|
|
||||||
if (actionID == eventTime) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Point clickPoint = e.getPoint();
|
Point clickPoint = e.getPoint();
|
||||||
if (isEnabled() && popupContext.contains(clickPoint)) {
|
if (isEnabled() && popupContext.contains(clickPoint)) {
|
||||||
|
@ -311,8 +300,8 @@ public class MultipleActionDockingToolbarButton extends EmptyBorderButton {
|
||||||
// Unusual Code Alert: we need to put this call in an invoke later, since Java
|
// Unusual Code Alert: we need to put this call in an invoke later, since Java
|
||||||
// will update the focused window after we click. We need the focus to be
|
// will update the focused window after we click. We need the focus to be
|
||||||
// correct before we show, since our menu is built with actions based upon the
|
// correct before we show, since our menu is built with actions based upon the
|
||||||
// focused dude.
|
// focused component.
|
||||||
Swing.runLater(() -> popupMenu = showPopup(PopupMouseListener.this));
|
Swing.runLater(() -> popupMenu = showPopup());
|
||||||
|
|
||||||
e.consume();
|
e.consume();
|
||||||
model.setPressed(false);
|
model.setPressed(false);
|
||||||
|
@ -372,10 +361,6 @@ public class MultipleActionDockingToolbarButton extends EmptyBorderButton {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean popupIsShowing() {
|
|
||||||
return (popupMenu != null) && popupMenu.isVisible();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void popupMenuCanceled(PopupMenuEvent e) {
|
public void popupMenuCanceled(PopupMenuEvent e) {
|
||||||
// no-op
|
// no-op
|
||||||
|
@ -383,7 +368,7 @@ public class MultipleActionDockingToolbarButton extends EmptyBorderButton {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
|
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
|
||||||
actionID = System.currentTimeMillis(); // hacktastic!
|
popupLastClosedTime = System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -15,7 +15,13 @@
|
||||||
*/
|
*/
|
||||||
package docking.menu;
|
package docking.menu;
|
||||||
|
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
|
||||||
|
import javax.swing.JButton;
|
||||||
|
|
||||||
|
import docking.action.DockingAction;
|
||||||
import docking.widgets.EventTrigger;
|
import docking.widgets.EventTrigger;
|
||||||
|
import ghidra.util.Swing;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class for clients that wish to create a button that has multiple states, controlled by a
|
* A class for clients that wish to create a button that has multiple states, controlled by a
|
||||||
|
@ -27,12 +33,39 @@ import docking.widgets.EventTrigger;
|
||||||
* {@link #actionStateChanged(ActionState, EventTrigger)} callback. Call
|
* {@link #actionStateChanged(ActionState, EventTrigger)} callback. Call
|
||||||
* {@link #createButton()} and add the return value to your UI.
|
* {@link #createButton()} and add the return value to your UI.
|
||||||
*
|
*
|
||||||
* @param <T>
|
* @param <T> the type
|
||||||
* @see MultiStateDockingAction
|
* @see MultiStateDockingAction
|
||||||
*/
|
*/
|
||||||
public abstract class NonToolbarMultiStateAction<T> extends MultiStateDockingAction<T> {
|
public abstract class NonToolbarMultiStateAction<T> extends MultiStateDockingAction<T> {
|
||||||
|
|
||||||
|
// A listener that will get called when the button (not the popup) is clicked. Toolbar
|
||||||
|
// actions do not need this functionality, since the toolbar API will call actionPerfomred().
|
||||||
|
private ActionListener clickListener = e -> {
|
||||||
|
actionPerformed();
|
||||||
|
};
|
||||||
|
|
||||||
public NonToolbarMultiStateAction(String name, String owner) {
|
public NonToolbarMultiStateAction(String name, String owner) {
|
||||||
super(name, owner);
|
super(name, owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JButton doCreateButton() {
|
||||||
|
JButton button = super.doCreateButton();
|
||||||
|
button.addActionListener(clickListener);
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called when the user clicks the button <B>when this action is used as a
|
||||||
|
* custom button provider and not installed into the default {@link DockingAction} framework.
|
||||||
|
* </B>
|
||||||
|
*
|
||||||
|
* This is the callback to be overridden when the child wishes to respond to user button
|
||||||
|
* presses that are on the button and not the drop-down. The default behavior is to show the
|
||||||
|
* popup menu when the button is clicked.
|
||||||
|
*/
|
||||||
|
protected void actionPerformed() {
|
||||||
|
Swing.runLater(() -> showPopup());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,6 @@ import javax.swing.table.TableModel;
|
||||||
|
|
||||||
import org.jdom.Element;
|
import org.jdom.Element;
|
||||||
|
|
||||||
import docking.ActionContext;
|
|
||||||
import docking.DockingWindowManager;
|
import docking.DockingWindowManager;
|
||||||
import docking.help.HelpService;
|
import docking.help.HelpService;
|
||||||
import docking.menu.*;
|
import docking.menu.*;
|
||||||
|
@ -413,12 +412,12 @@ public class GTableFilterPanel<ROW_OBJECT> extends JPanel {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doActionPerformed(ActionContext context) {
|
protected void actionPerformed() {
|
||||||
showFilterDialog(tableModel);
|
showFilterDialog(tableModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
columnFilterAction.setPerformActionOnPrimaryButtonClick(true);
|
|
||||||
HelpLocation helpLocation = new HelpLocation("Trees", "Column_Filters");
|
HelpLocation helpLocation = new HelpLocation("Trees", "Column_Filters");
|
||||||
columnFilterAction.setHelpLocation(helpLocation);
|
columnFilterAction.setHelpLocation(helpLocation);
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ public interface DataType {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WARNING: do not add <code>default</code> method implementations to this interface. Doing so
|
* WARNING: do not add <code>default</code> method implementations to this interface. Doing so
|
||||||
* intereferes with correct initialization of the static instance variables {@link #DEFAULT} and
|
* interferes with correct initialization of the static instance variables {@link #DEFAULT} and
|
||||||
* {@link #VOID} below.
|
* {@link #VOID} below.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -559,7 +559,7 @@ public interface DataType {
|
||||||
* The datatypes must be of the same "type" (i.e. structure can only be replacedWith another
|
* The datatypes must be of the same "type" (i.e. structure can only be replacedWith another
|
||||||
* structure.
|
* structure.
|
||||||
*
|
*
|
||||||
* @param datatype the datatype that contains the internals to upgrade to.
|
* @param dataType the datatype that contains the internals to upgrade to.
|
||||||
* @throws UnsupportedOperationException if the datatype does not support change.
|
* @throws UnsupportedOperationException if the datatype does not support change.
|
||||||
* @throws IllegalArgumentException if the given datatype is not the same type as this datatype.
|
* @throws IllegalArgumentException if the given datatype is not the same type as this datatype.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue