提交 c39a6a07 编写于 作者: S serge-rider

Navigator: Create menu refactoring

上级 d073dd1e
......@@ -36,6 +36,24 @@
</extension>
<extension point="org.eclipse.core.expressions.propertyTesters">
<propertyTester
class="org.jkiss.dbeaver.ui.actions.GlobalPropertyTester"
id="org.jkiss.dbeaver.ui.actions.GlobalPropertyTester"
namespace="org.jkiss.dbeaver.core.global"
properties="standalone,hasActiveProject,hasMultipleProjects"
type="java.lang.Object"/>
<propertyTester
class="org.jkiss.dbeaver.ui.actions.ObjectPropertyTester"
id="org.jkiss.dbeaver.ui.actions.ObjectPropertyTester"
namespace="org.jkiss.dbeaver.core.object"
properties="canOpen,canCreate,canPaste,canDelete,canRename,canMoveUp,canMoveDown,canFilter,canFilterObject,hasFilter"
type="org.jkiss.dbeaver.model.navigator.DBNNode"/>
<propertyTester
class="org.jkiss.dbeaver.ui.actions.ToolsPropertyTester"
id="org.jkiss.dbeaver.ui.actions.ToolsPropertyTester"
namespace="org.jkiss.dbeaver.core.tools"
properties="hasTools"
type="org.eclipse.ui.IWorkbenchPart"/>
<propertyTester
class="org.jkiss.dbeaver.ui.actions.UIPropertyTester"
id="org.jkiss.dbeaver.ui.actions.UIPropertyTester"
......
......@@ -106,7 +106,7 @@
class="org.jkiss.dbeaver.ui.actions.ObjectPropertyTester"
id="org.jkiss.dbeaver.ui.actions.ObjectPropertyTester"
namespace="org.jkiss.dbeaver.core.object"
properties="canOpen,canCreate,canPaste,canDelete,canRename,canMoveUp,canMoveDown,canFilter,canFilterObject,hasFilter"
properties="canOpen,canCreateSingle,canCreateMulti,canPaste,canDelete,canRename,canMoveUp,canMoveDown,canFilter,canFilterObject,hasFilter"
type="org.jkiss.dbeaver.model.navigator.DBNNode"/>
<propertyTester
class="org.jkiss.dbeaver.ui.actions.ToolsPropertyTester"
......@@ -723,7 +723,25 @@
<extension point="org.eclipse.ui.menus">
<menuContribution allPopups="false" locationURI="popup:org.eclipse.ui.popup.any?after=create">
<command commandId="org.jkiss.dbeaver.core.object.create">
<visibleWhen>
<with variable="selection">
<count value="1"/>
<iterate operator="and">
<test property="org.jkiss.dbeaver.core.object.canCreateSingle"/>
</iterate>
</with>
</visibleWhen>
</command>
<menu id="dbeaver-menu-create" label="%menu.create.label">
<visibleWhen>
<with variable="selection">
<count value="1"/>
<iterate operator="and">
<test property="org.jkiss.dbeaver.core.object.canCreateMulti"/>
</iterate>
</with>
</visibleWhen>
<dynamic id="org.jkiss.dbeaver.core.menu.create" class="org.jkiss.dbeaver.ui.navigator.actions.NavigatorHandlerObjectCreateNew$MenuCreateContributor"/>
</menu>
</menuContribution>
......
......@@ -17,6 +17,7 @@
package org.jkiss.dbeaver.ui.actions;
import org.eclipse.core.expressions.PropertyTester;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IWorkbenchPart;
......@@ -35,9 +36,12 @@ import org.jkiss.dbeaver.registry.ObjectManagerRegistry;
import org.jkiss.dbeaver.tools.registry.ToolsRegistry;
import org.jkiss.dbeaver.ui.ActionUtils;
import org.jkiss.dbeaver.ui.navigator.NavigatorUtils;
import org.jkiss.dbeaver.ui.navigator.actions.NavigatorHandlerObjectCreateNew;
import org.jkiss.dbeaver.utils.RuntimeUtils;
import org.jkiss.utils.CommonUtils;
import java.util.List;
/**
* ObjectPropertyTester
*/
......@@ -47,7 +51,8 @@ public class ObjectPropertyTester extends PropertyTester
public static final String NAMESPACE = "org.jkiss.dbeaver.core.object";
public static final String PROP_CAN_OPEN = "canOpen";
public static final String PROP_CAN_CREATE = "canCreate";
public static final String PROP_CAN_CREATE_SINGLE = "canCreateSingle";
public static final String PROP_CAN_CREATE_MULTI = "canCreateMulti";
public static final String PROP_CAN_PASTE = "canPaste";
public static final String PROP_CAN_DELETE = "canDelete";
public static final String PROP_CAN_RENAME = "canRename";
......@@ -79,52 +84,21 @@ public class ObjectPropertyTester extends PropertyTester
switch (property) {
case PROP_CAN_OPEN:
return node.isPersisted();
case PROP_CAN_CREATE:
case PROP_CAN_CREATE_SINGLE: {
return canCreateObject(node, true);
}
case PROP_CAN_CREATE_MULTI: {
return canCreateObject(node, false);
}
case PROP_CAN_PASTE: {
if (node instanceof DBNResource) {
return property.equals(PROP_CAN_PASTE);
}
if (node instanceof DBNDataSource) {
// We always can create datasource
return true;
}
Class objectType;
if (!(node instanceof DBNContainer)) {
if (node.getParentNode() instanceof DBNContainer) {
node = node.getParentNode();
}
}
DBNContainer container;
if (node instanceof DBNContainer) {
// Try to detect child type
objectType = ((DBNContainer) node).getChildrenClass();
container = (DBNContainer) node;
} else {
return false;
}
if (node instanceof DBSWrapper && isReadOnly(((DBSWrapper) node).getObject())) {
return false;
}
if (objectType == null) {
return false;
}
DBEObjectMaker objectMaker = getObjectManager(objectType, DBEObjectMaker.class);
if (objectMaker == null) {
return false;
}
if (!objectMaker.canCreateObject(container.getValueObject())) {
return false;
}
return canCreateObject(node, null);
// Do not check PASTE command state. It requires clipboard contents check
// which means UI interaction which can break menu popup [RedHat]
// and also is a slow operation. So let paste be always enabled.
/*
if (property.equals(PROP_CAN_CREATE)) {
return true;
}
// Check objects in clipboard
Collection<DBNNode> cbNodes = TreeNodeTransfer.getFromClipboard();
if (cbNodes == null) {
......@@ -141,7 +115,6 @@ public class ObjectPropertyTester extends PropertyTester
}
}
*/
return true;
}
case PROP_CAN_DELETE: {
if (node instanceof DBNDataSource || node instanceof DBNLocalFolder) {
......@@ -234,6 +207,54 @@ public class ObjectPropertyTester extends PropertyTester
return false;
}
private boolean canCreateObject(DBNNode node, Boolean onlySingle) {
if (onlySingle == null) {
// Just try to find first create handler
if (node instanceof DBNDataSource) {
// We always can create datasource
return true;
}
Class objectType;
if (!(node instanceof DBNContainer)) {
if (node.getParentNode() instanceof DBNContainer) {
node = node.getParentNode();
}
}
DBNContainer container;
if (node instanceof DBNContainer) {
// Try to detect child type
objectType = ((DBNContainer) node).getChildrenClass();
container = (DBNContainer) node;
} else {
return false;
}
if (node instanceof DBSWrapper && isReadOnly(((DBSWrapper) node).getObject())) {
return false;
}
if (objectType == null) {
return false;
}
DBEObjectMaker objectMaker = getObjectManager(objectType, DBEObjectMaker.class);
if (objectMaker == null) {
return false;
}
if (!objectMaker.canCreateObject(container.getValueObject())) {
return false;
}
return true;
}
// Check whether only single object type can be created or multiple ones
List<IContributionItem> createItems = NavigatorHandlerObjectCreateNew.fillCreateMenuItems(null, node);
if (onlySingle) {
return createItems.size() == 1;
} else {
return createItems.size() > 1;
}
}
private boolean isReadOnly(DBSObject object)
{
if (object == null) {
......
......@@ -20,9 +20,11 @@ import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.osgi.util.NLS;
import org.eclipse.ui.IWorkbenchCommandConstants;
import org.eclipse.ui.IWorkbenchPage;
......@@ -50,10 +52,7 @@ import org.jkiss.dbeaver.model.navigator.meta.DBXTreeItem;
import org.jkiss.dbeaver.model.navigator.meta.DBXTreeNode;
import org.jkiss.dbeaver.model.struct.DBSObject;
import org.jkiss.dbeaver.runtime.DBWorkbench;
import org.jkiss.dbeaver.ui.ActionUtils;
import org.jkiss.dbeaver.ui.DBeaverIcons;
import org.jkiss.dbeaver.ui.UIIcon;
import org.jkiss.dbeaver.ui.UIUtils;
import org.jkiss.dbeaver.ui.*;
import org.jkiss.dbeaver.ui.internal.UINavigatorMessages;
import org.jkiss.dbeaver.ui.navigator.NavigatorCommands;
import org.jkiss.dbeaver.ui.navigator.NavigatorUtils;
......@@ -64,6 +63,12 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Sorry, this is a bit over-complicated handler. Historical reasons.
* It can create object of specified type (in parameters) or for current selection.
* Dynamic menu "Create" fills elements with parameters. Direct contribution of create command will create nearest
* object type according to navigator selection.
*/
public class NavigatorHandlerObjectCreateNew extends NavigatorHandlerObjectCreateBase implements IElementUpdater {
private static final Log log = Log.getLog(NavigatorHandlerObjectCreateNew.class);
......@@ -150,68 +155,50 @@ public class NavigatorHandlerObjectCreateNew extends NavigatorHandlerObjectCreat
return null;
}
public static class MenuCreateContributor extends CompoundContributionItem {
private static final IContributionItem[] EMPTY_MENU = new IContributionItem[0];
private DBNNode lastNode;
private IContributionItem[] lastCreateActions;
// If site is null then we need only item count. BAD CODE.
public static List<IContributionItem> fillCreateMenuItems(@Nullable IWorkbenchPartSite site, DBNNode node) {
List<IContributionItem> createActions = new ArrayList<>();
@Override
protected IContributionItem[] getContributionItems() {
IWorkbenchPage activePage = UIUtils.getActiveWorkbenchWindow().getActivePage();
IWorkbenchPart activePart = activePage.getActivePart();
if (activePart == null) {
return EMPTY_MENU;
}
IWorkbenchPartSite site = activePart.getSite();
DBNNode node = NavigatorUtils.getSelectedNode(site.getSelectionProvider());
if (node == lastNode) {
// We cache last contribution items because Eclipse call this function tens of times per single menu show (WHY??).
return lastCreateActions;
}
lastNode = node;
List<IContributionItem> createActions = new ArrayList<>();
if (node instanceof DBNLocalFolder || node instanceof DBNProjectDatabases) {
IContributionItem item = makeCreateContributionItem(
site, DBPDataSourceContainer.class.getName(), ModelMessages.model_navigator_Connection, UIIcon.SQL_NEW_CONNECTION, false);
createActions.add(item);
}
if (node instanceof DBNDatabaseNode) {
addDatabaseNodeCreateItems(site, createActions, (DBNDatabaseNode) node);
}
if (node instanceof DBNLocalFolder || node instanceof DBNProjectDatabases) {
CommandContributionItem item = makeCreateContributionItem(
site, DBPDataSourceContainer.class.getName(), ModelMessages.model_navigator_Connection, UIIcon.SQL_NEW_CONNECTION, false);
createActions.add(item);
if (node instanceof DBNLocalFolder || node instanceof DBNProjectDatabases || node instanceof DBNDataSource) {
createActions.add(ActionUtils.makeCommandContribution(site, NavigatorCommands.CMD_CREATE_LOCAL_FOLDER));
} else if (node instanceof DBNResource) {
final DBPProjectManager projectRegistry = DBWorkbench.getPlatform().getProjectManager();
IResource resource = ((DBNResource) node).getResource();
DBPResourceHandler handler = projectRegistry.getResourceHandler(resource);
if (handler instanceof DBPResourceCreator && (handler.getFeatures(resource) & DBPResourceCreator.FEATURE_CREATE_FILE) != 0) {
createActions.add(ActionUtils.makeCommandContribution(site, NavigatorCommands.CMD_CREATE_RESOURCE_FILE));
}
if (node instanceof DBNDatabaseNode) {
addDatabaseNodeCreateItems(site, createActions, (DBNDatabaseNode) node);
if (handler != null && (handler.getFeatures(resource) & DBPResourceHandler.FEATURE_CREATE_FOLDER) != 0) {
createActions.add(ActionUtils.makeCommandContribution(site, NavigatorCommands.CMD_CREATE_RESOURCE_FOLDER));
}
if (node instanceof DBNLocalFolder || node instanceof DBNProjectDatabases || node instanceof DBNDataSource) {
createActions.add(ActionUtils.makeCommandContribution(site, NavigatorCommands.CMD_CREATE_LOCAL_FOLDER));
} else if (node instanceof DBNResource) {
final DBPProjectManager projectRegistry = DBWorkbench.getPlatform().getProjectManager();
IResource resource = ((DBNResource) node).getResource();
DBPResourceHandler handler = projectRegistry.getResourceHandler(resource);
if (handler instanceof DBPResourceCreator && (handler.getFeatures(resource) & DBPResourceCreator.FEATURE_CREATE_FILE) != 0) {
createActions.add(ActionUtils.makeCommandContribution(site, NavigatorCommands.CMD_CREATE_RESOURCE_FILE));
}
if (handler != null && (handler.getFeatures(resource) & DBPResourceHandler.FEATURE_CREATE_FOLDER) != 0) {
createActions.add(ActionUtils.makeCommandContribution(site, NavigatorCommands.CMD_CREATE_RESOURCE_FOLDER));
}
if (resource instanceof IFolder) {
if (resource instanceof IFolder) {
if (site != null) {
createActions.add(new Separator());
createActions.add(ActionUtils.makeCommandContribution(site, NavigatorCommands.CMD_CREATE_FILE_LINK));
createActions.add(ActionUtils.makeCommandContribution(site, NavigatorCommands.CMD_CREATE_FOLDER_LINK));
}
createActions.add(ActionUtils.makeCommandContribution(site, NavigatorCommands.CMD_CREATE_FILE_LINK));
createActions.add(ActionUtils.makeCommandContribution(site, NavigatorCommands.CMD_CREATE_FOLDER_LINK));
}
}
if (site != null) {
if (!createActions.isEmpty() && !(createActions.get(createActions.size() - 1) instanceof Separator)) {
createActions.add(new Separator());
}
createActions.add(ActionUtils.makeCommandContribution(site, IWorkbenchCommandConstants.FILE_NEW, "Other ...", null));
lastCreateActions = createActions.toArray(new IContributionItem[0]);
return lastCreateActions;
}
return createActions;
}
private static void addDatabaseNodeCreateItems(IWorkbenchPartSite site, List<IContributionItem> createActions, DBNDatabaseNode node) {
private static void addDatabaseNodeCreateItems(@Nullable IWorkbenchPartSite site, List<IContributionItem> createActions, DBNDatabaseNode node) {
if (node instanceof DBNDatabaseFolder) {
final List<DBXTreeNode> metaChildren = ((DBNDatabaseFolder) node).getMeta().getChildren(node);
if (!CommonUtils.isEmpty(metaChildren)) {
......@@ -220,7 +207,7 @@ public class NavigatorHandlerObjectCreateNew extends NavigatorHandlerObjectCreat
DBPImage nodeIcon = metaChildren.get(0).getIcon(node);
if (nodeClass != null && nodeType != null) {
if (isCreateSupported(node, nodeClass)) {
CommandContributionItem item = makeCreateContributionItem(
IContributionItem item = makeCreateContributionItem(
site, nodeClass.getName(), nodeType, nodeIcon, false);
createActions.add(item);
}
......@@ -246,8 +233,10 @@ public class NavigatorHandlerObjectCreateNew extends NavigatorHandlerObjectCreat
return;
}
// Now add all child folders
createActions.add(new Separator());
if (site != null) {
// Now add all child folders
createActions.add(new Separator());
}
List<DBXTreeNode> childNodeMetas = node.getMeta().getChildren(node);
if (!CommonUtils.isEmpty(childNodeMetas)) {
......@@ -265,7 +254,7 @@ public class NavigatorHandlerObjectCreateNew extends NavigatorHandlerObjectCreat
}
}
private static boolean addChildNodeCreateItem(IWorkbenchPartSite site, List<IContributionItem> createActions, DBNDatabaseNode node, DBXTreeItem childMeta) {
private static boolean addChildNodeCreateItem(@Nullable IWorkbenchPartSite site, List<IContributionItem> createActions, DBNDatabaseNode node, DBXTreeItem childMeta) {
if (childMeta.isVirtual()) {
return false;
}
......@@ -278,7 +267,7 @@ public class NavigatorHandlerObjectCreateNew extends NavigatorHandlerObjectCreat
String typeName = childMeta.getNodeType(node.getDataSource(), null);
if (typeName != null) {
CommandContributionItem item = makeCreateContributionItem(
IContributionItem item = makeCreateContributionItem(
site, objectClass.getName(), typeName, childMeta.getIcon(node), true);
createActions.add(item);
return true;
......@@ -292,9 +281,12 @@ public class NavigatorHandlerObjectCreateNew extends NavigatorHandlerObjectCreat
return objectMaker != null && objectMaker.canCreateObject(parentNode == null ? null : parentNode.getValueObject());
}
private static CommandContributionItem makeCreateContributionItem(
IWorkbenchPartSite site, String objectType, String objectTypeName, DBPImage objectIcon, boolean isFolder)
private static IContributionItem makeCreateContributionItem(
@Nullable IWorkbenchPartSite site, String objectType, String objectTypeName, DBPImage objectIcon, boolean isFolder)
{
if (site == null) {
return new ActionContributionItem(new EmptyAction(objectType));
}
CommandContributionItemParameter params = new CommandContributionItemParameter(
site,
NavigatorCommands.CMD_OBJECT_CREATE,
......@@ -324,4 +316,108 @@ public class NavigatorHandlerObjectCreateNew extends NavigatorHandlerObjectCreat
return dataSource == null || dataSource.getContainer().isConnectionReadOnly();
}
/*
/////////////////////////////////////////////////////////////////
// BAD CODE.
// It is optimization
private static int countCreateMenuItems(DBNNode node) {
int count = 0;
if (node instanceof DBNLocalFolder || node instanceof DBNProjectDatabases) {
// Create connection
count++;
}
if (node instanceof DBNDatabaseNode) {
count += countDatabaseNodeCreateItems((DBNDatabaseNode) node);
}
if (node instanceof DBNLocalFolder || node instanceof DBNProjectDatabases || node instanceof DBNDataSource) {
// Create local folder
count++;
} else if (node instanceof DBNResource) {
final DBPProjectManager projectRegistry = DBWorkbench.getPlatform().getProjectManager();
IResource resource = ((DBNResource) node).getResource();
DBPResourceHandler handler = projectRegistry.getResourceHandler(resource);
if (handler instanceof DBPResourceCreator && (handler.getFeatures(resource) & DBPResourceCreator.FEATURE_CREATE_FILE) != 0) {
// Create file
count++;
}
if (handler != null && (handler.getFeatures(resource) & DBPResourceHandler.FEATURE_CREATE_FOLDER) != 0) {
// Create folder
count++;
}
if (resource instanceof IFolder) {
// Create file and folder links
count++;
count++;
}
}
return count;
}
private static int countDatabaseNodeCreateItems(DBNDatabaseNode node) {
int count = 0;
if (node instanceof DBNDatabaseFolder) {
final List<DBXTreeNode> metaChildren = ((DBNDatabaseFolder) node).getMeta().getChildren(node);
if (!CommonUtils.isEmpty(metaChildren)) {
Class<?> nodeClass = ((DBNContainer) node).getChildrenClass();
String nodeType = metaChildren.get(0).getChildrenType(node.getDataSource(), null);
DBPImage nodeIcon = metaChildren.get(0).getIcon(node);
if (nodeClass != null && nodeType != null) {
if (isCreateSupported(node, nodeClass)) {
count++;
}
}
}
} else {
Class<?> nodeItemClass = node.getObject().getClass();
if (isCreateSupported(
node.getParentNode() instanceof DBNDatabaseNode ? (DBNDatabaseNode) node.getParentNode() : null,
nodeItemClass))
{
count++;
}
if (!isReadOnly(node.getObject())) {
List<DBXTreeNode> childNodeMetas = node.getMeta().getChildren(node);
if (!CommonUtils.isEmpty(childNodeMetas)) {
for (DBXTreeNode childMeta : childNodeMetas) {
if (childMeta instanceof DBXTreeFolder) {
List<DBXTreeNode> folderChildMeta = childMeta.getChildren(node);
if (!CommonUtils.isEmpty(folderChildMeta) && folderChildMeta.size() == 1 && folderChildMeta.get(0) instanceof DBXTreeItem) {
addChildNodeCreateItem(site, createActions, node, (DBXTreeItem) folderChildMeta.get(0));
}
} else if (childMeta instanceof DBXTreeItem) {
addChildNodeCreateItem(site, createActions, node, (DBXTreeItem) childMeta);
}
}
}
}
}
return count;
}
*/
public static class MenuCreateContributor extends CompoundContributionItem {
private static final IContributionItem[] EMPTY_MENU = new IContributionItem[0];
@Override
protected IContributionItem[] getContributionItems() {
IWorkbenchPage activePage = UIUtils.getActiveWorkbenchWindow().getActivePage();
IWorkbenchPart activePart = activePage.getActivePart();
if (activePart == null) {
return EMPTY_MENU;
}
IWorkbenchPartSite site = activePart.getSite();
DBNNode node = NavigatorUtils.getSelectedNode(site.getSelectionProvider());
List<IContributionItem> createActions = fillCreateMenuItems(site, node);
return createActions.toArray(new IContributionItem[0]);
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册