]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.ui/src/org/simantics/ui/contribution/DynamicMenuContribution.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.ui / src / org / simantics / ui / contribution / DynamicMenuContribution.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.ui.contribution;\r
13 \r
14 import org.eclipse.jface.action.ActionContributionItem;\r
15 import org.eclipse.jface.action.IAction;\r
16 import org.eclipse.jface.action.IContributionItem;\r
17 import org.eclipse.jface.viewers.ISelection;\r
18 import org.eclipse.jface.viewers.IStructuredSelection;\r
19 import org.eclipse.ui.ISelectionService;\r
20 import org.eclipse.ui.IWorkbenchWindow;\r
21 import org.eclipse.ui.PlatformUI;\r
22 import org.eclipse.ui.actions.CompoundContributionItem;\r
23 import org.simantics.DatabaseJob;\r
24 import org.simantics.Simantics;\r
25 import org.simantics.db.ReadGraph;\r
26 import org.simantics.db.common.request.UniqueRead;\r
27 import org.simantics.db.common.utils.RequestUtil;\r
28 import org.simantics.db.exception.DatabaseException;\r
29 import org.simantics.db.management.ISessionContext;\r
30 import org.simantics.ui.SimanticsUI;\r
31 import org.simantics.utils.ui.ErrorLogger;\r
32 \r
33 /**\r
34  * A more or less carbon copy of CompoundContributionItem with the exception of\r
35  * adding Simantics Graph database traits to the menu filling process.\r
36  * \r
37  * <p>\r
38  * The simplest way to use this class is to override the\r
39  * {@link #getActions(ReadGraph, Object[])} method which should return any\r
40  * actions that you want to be performed on the specified selection. Another way\r
41  * is to override {@link #getContributionItems(ReadGraph, Object[])} that by\r
42  * default simply invokes the simplest method\r
43  * {@link #getActions(ReadGraph, Object[])}. Overriding it allows you to create\r
44  * e.g. submenus, which you cannot do with actions.\r
45  * </p>\r
46  * \r
47  * <p>\r
48  * To customize what gets passed to either\r
49  * {@link #getActions(ReadGraph, Object[])} or\r
50  * {@link #getContributionItems(ReadGraph, Object[])} as the selection\r
51  * parameter, override {@link #getSelectedObjects()}\r
52  * </p>\r
53  * \r
54  * @author Tuukka Lehtonen\r
55  */\r
56 public abstract class DynamicMenuContribution extends CompoundContributionItem {\r
57 \r
58     protected static final Object[] NO_OBJECTS = {};\r
59     protected static final IAction[] NO_ACTIONS = {};\r
60     protected static final IContributionItem[] NONE = {};\r
61 \r
62     /**\r
63      * Creates a contribution item with a <code>null</code> id.\r
64      */\r
65     protected DynamicMenuContribution() {\r
66         super();\r
67     }\r
68 \r
69     /**\r
70      * Creates a contribution item with the given (optional) id.\r
71      *\r
72      * @param id the contribution item identifier, or <code>null</code>\r
73      */\r
74     protected DynamicMenuContribution(String id) {\r
75         super(id);\r
76     }\r
77 \r
78     /* (non-Javadoc)\r
79      * @see org.eclipse.ui.actions.CompoundContributionItem#getContributionItems()\r
80      */\r
81     @Override\r
82     protected final IContributionItem[] getContributionItems() {\r
83         if (DatabaseJob.inProgress())\r
84             return NONE;\r
85         ISessionContext ctx = SimanticsUI.getSessionContext();\r
86         if (ctx != null) {\r
87             final Object[] selection = getSelectedObjects();\r
88             //System.out.println(getClass().getSimpleName() + "@" + System.identityHashCode(this) + "( " + System.identityHashCode(selection) + ": " + Arrays.toString(selection) + " )");\r
89             if (!preAcceptSelection(selection))\r
90                 return NONE;\r
91             try {\r
92                 return RequestUtil.trySyncRequest(\r
93                         Simantics.getSession(),\r
94                         SimanticsUI.UI_THREAD_REQUEST_START_TIMEOUT,\r
95                         SimanticsUI.UI_THREAD_REQUEST_EXECUTION_TIMEOUT_LONG,\r
96                         NONE,\r
97                         new UniqueRead<IContributionItem[]>() {\r
98                     @Override\r
99                     public IContributionItem[] perform(ReadGraph graph) throws DatabaseException {\r
100                         return getContributionItems(graph, selection);\r
101                     }\r
102                     @Override\r
103                     public String toString() {\r
104                         return DynamicMenuContribution.this.toString();\r
105                     }\r
106                 });\r
107             } catch (DatabaseException | InterruptedException e) {\r
108                 ErrorLogger.defaultLogError(e);\r
109             }\r
110         }\r
111         return NONE;\r
112     }\r
113 \r
114     /* (non-Javadoc)\r
115      * @see org.eclipse.ui.actions.CompoundContributionItem#isDynamic()\r
116      */\r
117     @Override\r
118     public boolean isDynamic() {\r
119         return true;\r
120     }\r
121 \r
122     //////////////////////////////////////////////////////////////////////////\r
123 \r
124     protected ISelection getSelection() {\r
125         IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();\r
126         ISelectionService service = window.getSelectionService();\r
127         return service.getSelection();\r
128     }\r
129 \r
130     protected Object[] getSelectedObjects() {\r
131         ISelection sel = getSelection();\r
132         if (!(sel instanceof IStructuredSelection))\r
133             return NO_OBJECTS;\r
134         return ((IStructuredSelection) sel).toArray();\r
135     }\r
136 \r
137     protected Object getSingleSelectedObject() {\r
138         Object[] resources = getSelectedObjects();\r
139         return resources.length == 1 ? resources[0] : null;\r
140     }\r
141 \r
142     protected IContributionItem[] toContributionItems(IAction... actions) {\r
143         if (actions == null)\r
144             return NONE;\r
145 \r
146         IContributionItem[] ret = new IContributionItem[actions.length];\r
147         for (int i = 0; i < actions.length; ++i)\r
148             ret[i] = new ActionContributionItem(actions[i]);\r
149 \r
150         return ret;\r
151     }\r
152 \r
153     //////////////////////////////////////////////////////////////////////////\r
154     // Override these where needed\r
155 \r
156     /**\r
157      * Tests the input selection for whether it can produce any meaningful\r
158      * contribution items in the first place. This is a filter that is invoked\r
159      * before performing a database request to find out more about the possible\r
160      * contributions.\r
161      * \r
162      * <p>\r
163      * The default implementation checks that the input selection is not empty.\r
164      * To be able to provide contributions for empty selection, you must\r
165      * override this method.\r
166      * \r
167      * @param selection\r
168      * @return\r
169      */\r
170     protected boolean preAcceptSelection(Object[] selection) {\r
171         return selection != null && selection.length > 0;\r
172     }\r
173 \r
174     protected IContributionItem[] getContributionItems(ReadGraph graph, Object[] selection) throws DatabaseException {\r
175         return toContributionItems( getActions(graph, selection) );\r
176     }\r
177 \r
178     protected IAction[] getActions(ReadGraph graph, Object[] selection) throws DatabaseException {\r
179         return new IAction[0];\r
180     }\r
181 \r
182 }\r