Merge remote-tracking branch

'origin/GT-3302-dragonmacher-front-end-ui-lockup'

Conflicts:
	Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeManagerPlugin.java
This commit is contained in:
Ryan Kurtz 2019-12-19 15:30:21 -05:00
commit cf4328bda4
26 changed files with 211 additions and 162 deletions

View file

@ -170,9 +170,6 @@ public class DataTypeManagerPlugin extends ProgramPlugin
}
/**
* @see ghidra.framework.plugintool.Plugin#serviceAdded(java.lang.Class, java.lang.Object)
*/
@Override
public void serviceAdded(Class<?> interfaceClass, Object service) {
if (interfaceClass == CodeViewerService.class) {
@ -616,10 +613,6 @@ public class DataTypeManagerPlugin extends ProgramPlugin
return new Class[] { DataTypeArchive.class };
}
/**
* Method called if the plugin supports this domain file.
* @param data the data to be used by the running tool
*/
@Override
public boolean acceptData(DomainFile[] data) {
if (data == null || data.length == 0) {
@ -780,6 +773,14 @@ public class DataTypeManagerPlugin extends ProgramPlugin
return true;
}
public DataTypeConflictHandler getConflictHandler() {
return provider.getConflictHandler();
}
void setStatus(String message) {
tool.setStatusInfo(message);
}
public static boolean isValidTypeDefBaseType(Component parent, DataType dataType) {
if (dataType instanceof FactoryDataType) {
Msg.showError(DataTypeManagerPlugin.class, parent, "TypeDef not allowed",
@ -798,12 +799,4 @@ public class DataTypeManagerPlugin extends ProgramPlugin
}
return true;
}
public DataTypeConflictHandler getConflictHandler() {
return provider.getConflictHandler();
}
void setStatus(String message) {
tool.setStatusInfo(message);
}
}

View file

@ -25,11 +25,11 @@ import ghidra.app.context.ProgramActionContext;
import ghidra.app.plugin.core.datamgr.archive.ProjectArchive;
import ghidra.app.plugin.core.datamgr.tree.DataTypeArchiveGTree;
import ghidra.app.plugin.core.datamgr.tree.ProjectArchiveNode;
import ghidra.framework.main.datatable.DomainFileProvider;
import ghidra.framework.main.datatable.DomainFileContext;
import ghidra.framework.model.DomainFile;
import ghidra.program.model.listing.Program;
public class DataTypesActionContext extends ProgramActionContext implements DomainFileProvider {
public class DataTypesActionContext extends ProgramActionContext implements DomainFileContext {
private final GTreeNode clickedNode;
private final boolean isToolbarAction;
private DataTypeArchiveGTree archiveGTree;
@ -42,6 +42,7 @@ public class DataTypesActionContext extends ProgramActionContext implements Doma
public DataTypesActionContext(DataTypesProvider provider, Program program,
DataTypeArchiveGTree archiveGTree, GTreeNode clickedNode, boolean isToolbarAction) {
super(provider, program, archiveGTree);
this.archiveGTree = archiveGTree;
this.clickedNode = clickedNode;

View file

@ -332,7 +332,6 @@ public class DataTypesProvider extends ComponentProviderAdapter {
GTreeNode clickedNode = null;
boolean isToolbarAction = true;
if (event != null) {
Object source = event.getSource();
if (source instanceof JTextField || source instanceof JTextPane) {
Component component = (Component) source;
@ -343,12 +342,12 @@ public class DataTypesProvider extends ComponentProviderAdapter {
clickedNode = archiveGTree.getNodeForLocation(point.x, point.y);
isToolbarAction = false;
}
return new DataTypesActionContext(this, plugin.getProgram(), archiveGTree, clickedNode,
isToolbarAction);
return new DataTypesActionContext(this, plugin.getProgram(), archiveGTree,
clickedNode, isToolbarAction);
}
@Override
// overridden to handle special logic in plugin
@Override // overridden to handle special logic in plugin
public void closeComponent() {
plugin.closeProvider(this);
}

View file

@ -27,7 +27,7 @@ import ghidra.app.plugin.core.datamgr.archive.*;
import ghidra.app.plugin.core.datamgr.editor.DataTypeEditorManager;
import ghidra.framework.client.ClientUtil;
import ghidra.framework.main.SaveDataDialog;
import ghidra.framework.main.datatable.DomainFileProvider;
import ghidra.framework.main.datatable.DomainFileContext;
import ghidra.framework.main.projectdata.actions.VersionControlAction;
import ghidra.framework.model.DomainFile;
import ghidra.util.exception.AssertException;
@ -61,7 +61,7 @@ public class VersionControlDataTypeArchiveUndoCheckoutAction extends VersionCont
}
@Override
public void actionPerformed(DomainFileProvider context) {
public void actionPerformed(DomainFileContext context) {
undoCheckOut();
}
@ -69,7 +69,7 @@ public class VersionControlDataTypeArchiveUndoCheckoutAction extends VersionCont
* Returns true if at least one of the provided domain files is checked out from the repository.
*/
@Override
public boolean isEnabledForContext(DomainFileProvider context) {
public boolean isEnabledForContext(DomainFileContext context) {
List<DomainFile> domainFiles = context.getSelectedFiles();
for (DomainFile domainFile : domainFiles) {
if (domainFile.isCheckedOut()) {

View file

@ -673,7 +673,7 @@ public class ProjectFileManager implements ProjectData {
/**
* Returns the standard user data filename associated with the specified file ID.
* @param associatedFileID
* @param associatedFileID the file id
* @return user data filename
*/
public static String getUserDataFilename(String associatedFileID) {

View file

@ -1009,9 +1009,6 @@ public class FrontEndPlugin extends Plugin
tool.addLocalAction(frontEndProvider, propertiesAction);
}
/**
* Delete the tool template from the tool chest.
*/
private void delete(String toolName) {
if (!confirmDelete(toolName + " from your local tool chest?")) {
return;
@ -1049,17 +1046,11 @@ public class FrontEndPlugin extends Plugin
}
}
/**
* @see ghidra.framework.main.FrontEndService#addProjectListener(ghidra.framework.model.ProjectListener)
*/
@Override
public void addProjectListener(ProjectListener l) {
((FrontEndTool) tool).addProjectListener(l);
}
/**
* @see ghidra.framework.main.FrontEndService#removeProjectListener(ghidra.framework.model.ProjectListener)
*/
@Override
public void removeProjectListener(ProjectListener l) {
if (tool != null) { // tool is null when we've been disposed

View file

@ -50,7 +50,7 @@ class ProjectDataPanel extends JSplitPane {
private static final String EXPANDED_PATHS = "EXPANDED_PATHS";
private FrontEndPlugin frontEndPlugin;
private JTabbedPane projectTabPanel;
private JTabbedPane projectTab;
private JTabbedPane readOnlyTab;
private Map<ProjectLocator, ProjectDataTreePanel> readOnlyViews;
private FrontEndTool tool;
@ -70,15 +70,15 @@ class ProjectDataPanel extends JSplitPane {
// initialize the table of views being managed
readOnlyViews = new HashMap<>(TYPICAL_NUM_VIEWS);
projectTabPanel = new JTabbedPane(SwingConstants.BOTTOM);
projectTabPanel.setBorder(BorderFactory.createTitledBorder(BORDER_PREFIX));
projectTabPanel.addChangeListener(e -> frontEndPlugin.getTool().contextChanged(null));
projectTab = new JTabbedPane(SwingConstants.BOTTOM);
projectTab.setBorder(BorderFactory.createTitledBorder(BORDER_PREFIX));
projectTab.addChangeListener(e -> frontEndPlugin.getTool().contextChanged(null));
projectTabPanel.addTab("Tree View", activePanel);
projectTabPanel.addTab("Table View", tablePanel);
projectTab.addTab("Tree View", activePanel);
projectTab.addTab("Table View", tablePanel);
// setup the active data tree panel
this.add(projectTabPanel, JSplitPane.LEFT);
projectTabPanel.setBorder(BorderFactory.createTitledBorder(BORDER_PREFIX));
this.add(projectTab, JSplitPane.LEFT);
projectTab.setBorder(BorderFactory.createTitledBorder(BORDER_PREFIX));
// initialize the read-only project view tabbed pane
// create a container panel just to have a title border because of a bug in
@ -213,7 +213,9 @@ class ProjectDataPanel extends JSplitPane {
}
/**
* Get the project data for the given project view.
* Get the project data for the given project view
*
* @param projectView the locator for the project to retrieve
* @return null if project view was not found
*/
ProjectData getProjectData(ProjectLocator projectView) {
@ -226,6 +228,7 @@ class ProjectDataPanel extends JSplitPane {
/**
* remove (close) the specified project view
* @param projectView the url for the view to close
*/
void closeView(URL projectView) {
Project activeProject = tool.getProject();
@ -265,6 +268,7 @@ class ProjectDataPanel extends JSplitPane {
/**
* returns the ProjectURL for the current active view; null if no views open
* @return the ProjectURL for the current active view; null if no views open
*/
URL getCurrentView() {
return getProjectURL(treePanel);
@ -312,12 +316,12 @@ class ProjectDataPanel extends JSplitPane {
}
void setBorder(String projectName) {
projectTabPanel.setBorder(BorderFactory.createTitledBorder(BORDER_PREFIX + projectName));
projectTab.setBorder(BorderFactory.createTitledBorder(BORDER_PREFIX + projectName));
treePanel.updateProjectName(projectName);
}
ActionContext getActionContext(ComponentProvider provider, MouseEvent e) {
Component comp = e == null ? projectTabPanel.getSelectedComponent() : e.getComponent();
Component comp = e == null ? projectTab.getSelectedComponent() : e.getComponent();
while (comp != null) {
if (comp instanceof JTabbedPane) {
@ -361,11 +365,11 @@ class ProjectDataPanel extends JSplitPane {
}
private void showTable() {
projectTabPanel.setSelectedIndex(1);
projectTab.setSelectedIndex(1);
}
private boolean isTableShowing() {
return projectTabPanel.getSelectedIndex() == 1;
return projectTab.getSelectedIndex() == 1;
}
}

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,14 +15,32 @@
*/
package ghidra.framework.main.datatable;
import ghidra.framework.model.DomainFile;
import java.util.List;
public interface DomainFileProvider {
List<DomainFile> getSelectedFiles();
import ghidra.framework.model.DomainFile;
int getFileCount();
/**
* A context that provides information to actions about domain files that are selected in the tool
*/
public interface DomainFileContext {
boolean isInActiveProject();
/**
* The selected files or empty if no files are selected
* @return the files
*/
public List<DomainFile> getSelectedFiles();
/**
* Returns the count of selected files
* @return the count of selected files
*/
public int getFileCount();
/**
* True if the current set of files is in the active project (false implies a non-active,
* read-only project)
*
* @return true if in the active project
*/
public boolean isInActiveProject();
}

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,6 +17,8 @@ package ghidra.framework.main.datatable;
import docking.ActionContext;
import docking.action.DockingAction;
import ghidra.framework.main.AppInfo;
import ghidra.framework.main.FrontEndTool;
public abstract class DomainFileProviderContextAction extends DockingAction {
@ -27,45 +28,56 @@ public abstract class DomainFileProviderContextAction extends DockingAction {
@Override
public final boolean isEnabledForContext(ActionContext actionContext) {
if (!(actionContext instanceof DomainFileProvider)) {
if (!(actionContext instanceof DomainFileContext)) {
return false;
}
DomainFileProvider context = (DomainFileProvider) actionContext;
return isEnabledForContext(context);
FrontEndTool tool = AppInfo.getFrontEndTool();
if (tool.isExecutingCommand()) {
return false;
}
protected boolean isEnabledForContext(DomainFileProvider context) {
return isEnabledForContext((DomainFileContext) actionContext);
}
protected boolean isEnabledForContext(DomainFileContext context) {
return context.getFileCount() > 0;
}
@Override
public final void actionPerformed(ActionContext context) {
actionPerformed((DomainFileProvider) context);
actionPerformed((DomainFileContext) context);
}
protected abstract void actionPerformed(DomainFileProvider context);
protected abstract void actionPerformed(DomainFileContext context);
@Override
public boolean isValidContext(ActionContext context) {
if (!(context instanceof DomainFileProvider)) {
if (!(context instanceof DomainFileContext)) {
return false;
}
return isValidContext((DomainFileProvider) context);
return isValidContext((DomainFileContext) context);
}
protected boolean isValidContext(DomainFileProvider context) {
protected boolean isValidContext(DomainFileContext context) {
return true;
}
@Override
public boolean isAddToPopup(ActionContext context) {
if (!(context instanceof DomainFileProvider)) {
public final boolean isAddToPopup(ActionContext context) {
if (!(context instanceof DomainFileContext)) {
return false;
}
return isAddToPopup((DomainFileProvider) context);
FrontEndTool tool = AppInfo.getFrontEndTool();
if (tool.isExecutingCommand()) {
return false;
}
protected boolean isAddToPopup(DomainFileProvider context) {
return isAddToPopup((DomainFileContext) context);
}
protected boolean isAddToPopup(DomainFileContext context) {
return isEnabledForContext(context);
}

View file

@ -23,7 +23,11 @@ import docking.ActionContext;
import docking.ComponentProvider;
import ghidra.framework.model.*;
public class ProjectDataActionContext extends ActionContext implements DomainFileProvider {
/**
* A context that understands files that live in a {@link Project}. Most of the clients of
* this context will use its notion of selected {@link DomainFile}s and folders.
*/
public class ProjectDataActionContext extends ActionContext implements DomainFileContext {
private List<DomainFolder> selectedFolders;
private List<DomainFile> selectedFiles;
@ -35,6 +39,7 @@ public class ProjectDataActionContext extends ActionContext implements DomainFil
public ProjectDataActionContext(ComponentProvider provider, ProjectData projectData,
Object contextObject, List<DomainFolder> selectedFolders,
List<DomainFile> selectedFiles, Component comp, boolean isActiveProject) {
super(provider, contextObject, comp);
this.projectData = projectData;
this.selectedFolders = selectedFolders;

View file

@ -102,7 +102,8 @@ public class ProjectDataTablePanel extends JPanel {
checkOpen(e);
}
});
gTable.getSelectionModel().addListSelectionListener(
gTable.getSelectionModel()
.addListSelectionListener(
e -> plugin.getTool().contextChanged(null));
gTable.setDefaultRenderer(Date.class, new DateCellRenderer());
gTable.setDefaultRenderer(DomainFileType.class, new TypeCellRenderer());
@ -280,6 +281,7 @@ public class ProjectDataTablePanel extends JPanel {
DomainFileInfo info = model.getRowObject(i);
list.add(info.getDomainFile());
}
return new ProjectDataActionContext(provider, projectData,
model.getRowObject(selectedRows[0]), null, list, gTable, true);
}

View file

@ -37,7 +37,7 @@ public class CheckoutDialog extends DialogComponentProvider {
private int actionID = CANCELED;
public CheckoutDialog() {
super("Check-out Versioned File(s)");
super("Checkout Versioned File(s)");
setHelpLocation(new HelpLocation(GenericHelpTopics.REPOSITORY, "CheckoutDialog"));
addWorkPanel(buildMainPanel());

View file

@ -29,14 +29,13 @@ public class ProjectDataTreeActionContext extends ProjectDataActionContext {
private DataTree tree;
public ProjectDataTreeActionContext(ComponentProvider provider, ProjectData projectData,
TreePath[] selectionPaths, List<DomainFolder> folderList, List<DomainFile> fileList,
DataTree tree, boolean isActiveProject) {
super(provider, projectData, getContextObject(selectionPaths), folderList, fileList, tree,
isActiveProject);
TreePath[] selectionPaths,
List<DomainFolder> folderList, List<DomainFile> fileList, DataTree tree,
boolean isActiveProject) {
super(provider, projectData, getContextObject(selectionPaths), folderList,
fileList, tree, isActiveProject);
this.selectionPaths = selectionPaths;
this.tree = tree;
}
private static Object getContextObject(TreePath[] selectionPaths) {

View file

@ -119,8 +119,8 @@ public class ProjectDataTreePanel extends JPanel {
}
/**
* Update the project name.
* @param newName
* Update the project name
* @param newName the new name
*/
public void updateProjectName(String newName) {
if (root instanceof DomainFolderRootNode) {
@ -338,8 +338,9 @@ public class ProjectDataTreePanel extends JPanel {
}
}
ProjectDataTreeActionContext context = new ProjectDataTreeActionContext(provider,
projectData, selectionPaths, domainFolderList, domainFileList, tree, isActiveProject);
ProjectDataTreeActionContext context =
new ProjectDataTreeActionContext(provider, projectData, selectionPaths,
domainFolderList, domainFileList, tree, isActiveProject);
boolean isTransient = tool == null; // null for stand-alone dialog, not the project's tree
context.setTransient(isTransient);
return context;

View file

@ -20,7 +20,7 @@ import java.util.List;
import docking.widgets.OptionDialog;
import ghidra.framework.client.*;
import ghidra.framework.main.datatable.DomainFileProvider;
import ghidra.framework.main.datatable.DomainFileContext;
import ghidra.framework.main.datatable.DomainFileProviderContextAction;
import ghidra.framework.model.*;
import ghidra.framework.plugintool.PluginTool;
@ -50,7 +50,7 @@ public abstract class VersionControlAction extends DomainFileProviderContextActi
* or is version controlled.
*/
@Override
public boolean isAddToPopup(DomainFileProvider context) {
public boolean isAddToPopup(DomainFileContext context) {
if (!context.isInActiveProject()) {
return false;

View file

@ -24,7 +24,7 @@ import javax.swing.ImageIcon;
import docking.action.MenuData;
import docking.action.ToolBarData;
import ghidra.framework.client.ClientUtil;
import ghidra.framework.main.datatable.DomainFileProvider;
import ghidra.framework.main.datatable.DomainFileContext;
import ghidra.framework.main.datatree.*;
import ghidra.framework.model.DomainFile;
import ghidra.framework.plugintool.Plugin;
@ -52,7 +52,7 @@ public class VersionControlAddAction extends VersionControlAction {
}
@Override
public void actionPerformed(DomainFileProvider context) {
public void actionPerformed(DomainFileContext context) {
addToVersionControl(context.getSelectedFiles());
}
@ -60,7 +60,7 @@ public class VersionControlAddAction extends VersionControlAction {
* Returns true if at least one of the provided domain files can be added to the repository.
*/
@Override
public boolean isEnabledForContext(DomainFileProvider context) {
public boolean isEnabledForContext(DomainFileContext context) {
List<DomainFile> domainFiles = context.getSelectedFiles();
for (DomainFile domainFile : domainFiles) {
if (domainFile.canAddToRepository()) {

View file

@ -23,7 +23,7 @@ import javax.swing.ImageIcon;
import docking.action.MenuData;
import docking.action.ToolBarData;
import ghidra.framework.main.datatable.DomainFileProvider;
import ghidra.framework.main.datatable.DomainFileContext;
import ghidra.framework.main.datatree.ChangedFilesDialog;
import ghidra.framework.main.datatree.CheckInTask;
import ghidra.framework.model.DomainFile;
@ -57,7 +57,7 @@ public class VersionControlCheckInAction extends VersionControlAction {
}
@Override
public void actionPerformed(DomainFileProvider context) {
public void actionPerformed(DomainFileContext context) {
doCheckIn(context.getSelectedFiles());
}
@ -66,7 +66,7 @@ public class VersionControlCheckInAction extends VersionControlAction {
* checked into the repository.
*/
@Override
public boolean isEnabledForContext(DomainFileProvider context) {
public boolean isEnabledForContext(DomainFileContext context) {
List<DomainFile> domainFiles = context.getSelectedFiles();
for (DomainFile domainFile : domainFiles) {
if (domainFile.isCheckedOut() && domainFile.modifiedSinceCheckout()) {

View file

@ -24,7 +24,7 @@ import docking.action.MenuData;
import docking.action.ToolBarData;
import docking.widgets.OptionDialog;
import ghidra.framework.client.ClientUtil;
import ghidra.framework.main.datatable.DomainFileProvider;
import ghidra.framework.main.datatable.DomainFileContext;
import ghidra.framework.main.datatree.CheckoutDialog;
import ghidra.framework.model.DomainFile;
import ghidra.framework.plugintool.Plugin;
@ -60,7 +60,7 @@ public class VersionControlCheckOutAction extends VersionControlAction {
}
@Override
public void actionPerformed(DomainFileProvider context) {
public void actionPerformed(DomainFileContext context) {
checkOut(context.getSelectedFiles());
}
@ -69,7 +69,7 @@ public class VersionControlCheckOutAction extends VersionControlAction {
* checked out of the repository.
*/
@Override
public boolean isEnabledForContext(DomainFileProvider context) {
public boolean isEnabledForContext(DomainFileContext context) {
List<DomainFile> providedList = context.getSelectedFiles();
for (DomainFile domainFile : providedList) {
if (domainFile.canCheckout()) {
@ -92,29 +92,13 @@ public class VersionControlCheckOutAction extends VersionControlAction {
return null;
}
protected void checkOut(Collection<DomainFile> providedList) {
protected void checkOut(Collection<DomainFile> files) {
if (!checkRepositoryConnected()) {
return;
}
doCheckOut(providedList);
}
/*package*/ void doCheckOut(Collection<DomainFile> providedList) {
// note: a 'null' user means that we are using a local repository
User user = getUser();
boolean exclusive = true;
if (user != null && user.hasWritePermission()) {
CheckoutDialog checkout = new CheckoutDialog();
if (checkout.showDialog(tool) != CheckoutDialog.OK) {
return;
}
exclusive = checkout.exclusiveCheckout();
}
tool.execute(new CheckOutTask(providedList, exclusive));
tool.execute(new CheckOutTask(files));
}
/**
@ -122,12 +106,11 @@ public class VersionControlCheckOutAction extends VersionControlAction {
*/
private class CheckOutTask extends Task {
private Collection<DomainFile> files;
private boolean exclusive;
private boolean exclusive = true;
CheckOutTask(Collection<DomainFile> files, boolean exclusive) {
CheckOutTask(Collection<DomainFile> files) {
super("Check Out", true, true, true);
this.files = files;
this.exclusive = exclusive;
}
private boolean gatherVersionedFiles(TaskMonitor monitor, List<DomainFile> results)
@ -148,10 +131,27 @@ public class VersionControlCheckOutAction extends VersionControlAction {
int n = results.size();
if (n == 0) {
Msg.showError(this, tool.getToolFrame(), "Checkout Failed",
"No versioned files have been specified which can be checked-out");
"The specified files do not contain any versioned files available for " +
"checkeout");
return false;
}
//
// Confirm checkout - prompt for exclusive checkout, if possible. Otherwise, only
// confirm a bulk checkout.
//
// note: a 'null' user means that we are using a local repository
User user = getUser();
if (user != null && user.hasWritePermission()) {
CheckoutDialog checkout = new CheckoutDialog();
if (checkout.showDialog(tool) != CheckoutDialog.OK) {
return false;
}
exclusive = checkout.exclusiveCheckout();
return true;
}
if (n == 1) {
return true; // single file; no prompt needed
}
@ -165,6 +165,7 @@ public class VersionControlCheckOutAction extends VersionControlAction {
@Override
public void run(TaskMonitor monitor) {
try {
List<DomainFile> versionedFiles = new ArrayList<>();
@ -190,6 +191,7 @@ public class VersionControlCheckOutAction extends VersionControlAction {
List<DomainFile> failedCheckouts = new ArrayList<>();
int progress = 0;
for (DomainFile df : versionedFiles) {
monitor.checkCanceled();
monitor.setMessage("Checkout " + progress + " of " + versionedFiles.size() +
": " + df.getName());

View file

@ -18,7 +18,7 @@ package ghidra.framework.main.projectdata.actions;
import java.util.List;
import docking.action.MenuData;
import ghidra.framework.main.datatable.DomainFileProvider;
import ghidra.framework.main.datatable.DomainFileContext;
import ghidra.framework.main.datatree.VersionHistoryDialog;
import ghidra.framework.model.DomainFile;
import ghidra.framework.plugintool.Plugin;
@ -44,7 +44,7 @@ public class VersionControlShowHistoryAction extends VersionControlAction {
}
@Override
public void actionPerformed(DomainFileProvider context) {
public void actionPerformed(DomainFileContext context) {
showHistory(context.getSelectedFiles());
}
@ -52,7 +52,7 @@ public class VersionControlShowHistoryAction extends VersionControlAction {
* Returns true if a single version controlled domain file is being provided.
*/
@Override
public boolean isEnabledForContext(DomainFileProvider context) {
public boolean isEnabledForContext(DomainFileContext context) {
List<DomainFile> domainFiles = context.getSelectedFiles();
if (domainFiles.size() != 1) {
return false;

View file

@ -24,7 +24,7 @@ import javax.swing.ImageIcon;
import docking.action.MenuData;
import docking.action.ToolBarData;
import ghidra.framework.client.ClientUtil;
import ghidra.framework.main.datatable.DomainFileProvider;
import ghidra.framework.main.datatable.DomainFileContext;
import ghidra.framework.main.datatree.UndoActionDialog;
import ghidra.framework.model.DomainFile;
import ghidra.framework.plugintool.Plugin;
@ -57,7 +57,7 @@ public class VersionControlUndoCheckOutAction extends VersionControlAction {
}
@Override
public void actionPerformed(DomainFileProvider context) {
public void actionPerformed(DomainFileContext context) {
undoCheckOut(context.getSelectedFiles());
}
@ -65,7 +65,7 @@ public class VersionControlUndoCheckOutAction extends VersionControlAction {
* Returns true if at least one of the provided domain files is checked out from the repository.
*/
@Override
public boolean isEnabledForContext(DomainFileProvider context) {
public boolean isEnabledForContext(DomainFileContext context) {
List<DomainFile> domainFiles = context.getSelectedFiles();
for (DomainFile domainFile : domainFiles) {
if (domainFile.isCheckedOut()) {

View file

@ -23,7 +23,7 @@ import javax.swing.ImageIcon;
import docking.action.MenuData;
import ghidra.framework.client.ClientUtil;
import ghidra.framework.main.datatable.DomainFileProvider;
import ghidra.framework.main.datatable.DomainFileContext;
import ghidra.framework.main.datatree.UndoActionDialog;
import ghidra.framework.model.DomainFile;
import ghidra.framework.model.DomainFolder;
@ -51,7 +51,7 @@ public class VersionControlUndoHijackAction extends VersionControlAction {
}
@Override
public void actionPerformed(DomainFileProvider context) {
public void actionPerformed(DomainFileContext context) {
undoHijackedFiles(context.getSelectedFiles());
}
@ -59,7 +59,7 @@ public class VersionControlUndoHijackAction extends VersionControlAction {
* Returns true if at least one of the provided domain files is hijacked.
*/
@Override
public boolean isEnabledForContext(DomainFileProvider context) {
public boolean isEnabledForContext(DomainFileContext context) {
List<DomainFile> domainFiles = context.getSelectedFiles();
for (DomainFile domainFile : domainFiles) {
if (domainFile.isHijacked()) {

View file

@ -23,7 +23,7 @@ import javax.swing.ImageIcon;
import docking.action.MenuData;
import docking.action.ToolBarData;
import ghidra.framework.main.AppInfo;
import ghidra.framework.main.datatable.DomainFileProvider;
import ghidra.framework.main.datatable.DomainFileContext;
import ghidra.framework.model.DomainFile;
import ghidra.framework.plugintool.Plugin;
import ghidra.util.task.Task;
@ -55,7 +55,7 @@ public class VersionControlUpdateAction extends VersionControlAction {
}
@Override
public void actionPerformed(DomainFileProvider context) {
public void actionPerformed(DomainFileContext context) {
update(context.getSelectedFiles());
}
@ -63,7 +63,7 @@ public class VersionControlUpdateAction extends VersionControlAction {
* Returns true if at least one checked out file has a newer version in the repository.
*/
@Override
public boolean isEnabledForContext(DomainFileProvider context) {
public boolean isEnabledForContext(DomainFileContext context) {
List<DomainFile> providedList = context.getSelectedFiles();
for (DomainFile domainFile : providedList) {
if (domainFile.isVersioned() &&

View file

@ -20,7 +20,7 @@ import java.util.List;
import docking.action.MenuData;
import ghidra.framework.client.ClientUtil;
import ghidra.framework.main.datatable.DomainFileProvider;
import ghidra.framework.main.datatable.DomainFileContext;
import ghidra.framework.model.DomainFile;
import ghidra.framework.plugintool.Plugin;
import ghidra.framework.remote.User;
@ -37,8 +37,8 @@ public class VersionControlViewCheckOutAction extends VersionControlAction {
* @param plugin the plug-in that owns this action.
*/
public VersionControlViewCheckOutAction(Plugin plugin) {
super("View Check Outs", plugin.getName(), plugin.getTool());
setPopupMenuData(new MenuData(new String[] { "View Check Outs..." }, null, GROUP));
super("View Checkouts", plugin.getName(), plugin.getTool());
setPopupMenuData(new MenuData(new String[] { "View Checkouts..." }, null, GROUP));
setDescription("View current checkouts");
@ -46,7 +46,7 @@ public class VersionControlViewCheckOutAction extends VersionControlAction {
}
@Override
public void actionPerformed(DomainFileProvider context) {
public void actionPerformed(DomainFileContext context) {
viewCheckouts(context.getSelectedFiles());
}
@ -54,7 +54,7 @@ public class VersionControlViewCheckOutAction extends VersionControlAction {
* Returns true if a single version controlled domain file is being provided.
*/
@Override
public boolean isEnabledForContext(DomainFileProvider context) {
public boolean isEnabledForContext(DomainFileContext context) {
List<DomainFile> domainFiles = context.getSelectedFiles();
if (domainFiles.size() != 1) {
return false;

View file

@ -21,8 +21,8 @@ import java.awt.*;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.*;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import javax.swing.ImageIcon;
@ -57,8 +57,7 @@ import ghidra.framework.plugintool.mgr.*;
import ghidra.framework.plugintool.util.*;
import ghidra.framework.project.ProjectDataService;
import ghidra.util.*;
import ghidra.util.task.Task;
import ghidra.util.task.TaskLauncher;
import ghidra.util.task.*;
/**
* Base class that is a container to manage plugins and their actions, and to coordinate the
@ -88,12 +87,13 @@ public abstract class PluginTool extends AbstractDockingTool implements Tool, Se
private String subTitle;
private ServiceManager serviceMgr;
private ToolTaskManager taskMgr;
private OptionsManager optionsMgr;
private PluginManager pluginMgr;
private EventManager eventMgr;
private DialogManager dialogMgr;
private PropertyChangeSupport propertyChangeMgr;
private ToolTaskManager taskMgr;
private Set<TaskListener> executingTaskListeners = Collections.synchronizedSet(new HashSet<>());
private OptionsChangeListener optionsListener = new ToolOptionsListener();
protected ManagePluginsDialog manageDialog;
@ -455,6 +455,7 @@ public abstract class PluginTool extends AbstractDockingTool implements Tool, Se
private void disposeManagers() {
taskMgr.dispose();
executingTaskListeners.clear();
}
@Override
@ -647,7 +648,7 @@ public abstract class PluginTool extends AbstractDockingTool implements Tool, Se
* @return true if there is a command being executed
*/
public boolean isExecutingCommand() {
return taskMgr.isBusy();
return taskMgr.isBusy() || !executingTaskListeners.isEmpty();
}
/**
@ -694,6 +695,25 @@ public abstract class PluginTool extends AbstractDockingTool implements Tool, Se
taskMgr.scheduleFollowOnCommand(cmd, obj);
}
/**
* Launch the task in a new thread
* @param task task to run in a new thread
* @param delay number of milliseconds to delay the display of task monitor dialog
*/
public void execute(Task task, int delay) {
task.addTaskListener(new TaskBusyListener());
new TaskLauncher(task, getToolFrame(), delay);
}
/**
* Launch the task in a new thread
* @param task task to run in a new thread
*/
public void execute(Task task) {
task.addTaskListener(new TaskBusyListener());
new TaskLauncher(task, winMgr.getActiveWindow());
}
/**
* Get the options for the given category name; if no options exist with
* the given name, then one is created.
@ -738,23 +758,6 @@ public abstract class PluginTool extends AbstractDockingTool implements Tool, Se
return optionsMgr.getOptions();
}
/**
* Launch the task in a new thread.
* @param task task to run in a new thread
* @param delay number of milliseconds to delay the display of task monitor dialog
*/
public void execute(Task task, int delay) {
new TaskLauncher(task, getToolFrame(), delay);
}
/**
* Launch the task in a new thread.
* @param task task to run in a new thread
*/
public void execute(Task task) {
new TaskLauncher(task, winMgr.getActiveWindow());
}
/**
* Get the project associated with this tool. Null will be returned if there is no
* project open or if this tool does not use projects.
@ -1497,4 +1500,20 @@ public abstract class PluginTool extends AbstractDockingTool implements Tool, Se
}
}
private class TaskBusyListener implements TaskListener {
TaskBusyListener() {
executingTaskListeners.add(this);
}
@Override
public void taskCompleted(Task t) {
executingTaskListeners.remove(this);
}
@Override
public void taskCancelled(Task t) {
executingTaskListeners.remove(this);
}
}
}

View file

@ -15,7 +15,7 @@
*/
package ghidra.framework.main.projectdata.actions;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.*;
import java.io.IOException;
import java.util.HashSet;
@ -180,6 +180,10 @@ public class VersionControlCheckOutActionTest extends AbstractDockingTest {
assertNoDisplayedMessages();
}
//==================================================================================================
// Private Methods
//==================================================================================================
private void checkout(VersionControlCheckOutAction action, Set<DomainFile> files) {
runSwing(() -> action.checkOut(files), false);
}