ref #5616 Add alternative to double click execution in search view
[taxeditor.git] / eu.etaxonomy.taxeditor.navigation / src / main / java / eu / etaxonomy / taxeditor / navigation / NavigationUtil.java
1 /**
2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
8 */
9
10 package eu.etaxonomy.taxeditor.navigation;
11
12 import java.util.HashMap;
13 import java.util.Map;
14 import java.util.Set;
15 import java.util.UUID;
16
17 import org.eclipse.core.commands.Command;
18 import org.eclipse.core.commands.ParameterizedCommand;
19 import org.eclipse.core.commands.common.NotDefinedException;
20 import org.eclipse.core.commands.operations.IUndoContext;
21 import org.eclipse.core.commands.operations.UndoContext;
22 import org.eclipse.jface.viewers.StructuredSelection;
23 import org.eclipse.jface.wizard.WizardDialog;
24 import org.eclipse.swt.widgets.Display;
25 import org.eclipse.swt.widgets.Shell;
26 import org.eclipse.ui.IEditorPart;
27 import org.eclipse.ui.IEditorReference;
28 import org.eclipse.ui.IWorkbenchWindow;
29 import org.eclipse.ui.PartInitException;
30 import org.eclipse.ui.PlatformUI;
31 import org.eclipse.ui.commands.ICommandService;
32 import org.eclipse.ui.handlers.IHandlerService;
33 import org.eclipse.ui.navigator.CommonViewer;
34
35 import eu.etaxonomy.cdm.api.service.IClassificationService;
36 import eu.etaxonomy.cdm.api.service.INameService;
37 import eu.etaxonomy.cdm.api.service.ITaxonNodeService;
38 import eu.etaxonomy.cdm.api.service.ITaxonService;
39 import eu.etaxonomy.cdm.model.common.ICdmBase;
40 import eu.etaxonomy.cdm.model.description.PolytomousKey;
41 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
42 import eu.etaxonomy.cdm.model.taxon.Classification;
43 import eu.etaxonomy.cdm.model.taxon.Synonym;
44 import eu.etaxonomy.cdm.model.taxon.Taxon;
45 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
46 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
47 import eu.etaxonomy.cdm.persistence.dto.UuidAndTitleCache;
48 import eu.etaxonomy.taxeditor.editor.EditorUtil;
49 import eu.etaxonomy.taxeditor.editor.TaxonEditorInput;
50 import eu.etaxonomy.taxeditor.editor.internal.TaxeditorEditorPlugin;
51 import eu.etaxonomy.taxeditor.model.AbstractUtility;
52 import eu.etaxonomy.taxeditor.model.MessagingUtils;
53 import eu.etaxonomy.taxeditor.navigation.internal.TaxeditorNavigationPlugin;
54 import eu.etaxonomy.taxeditor.navigation.navigator.TaxonNavigator;
55 import eu.etaxonomy.taxeditor.newWizard.NewClassificationWizard;
56 import eu.etaxonomy.taxeditor.store.CdmStore;
57 import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
58
59 /**
60 * <p>NavigationUtil class.</p>
61 *
62 * @author n.hoffmann
63 * @created 24.03.2009
64 * @version 1.0
65 */
66 public class NavigationUtil extends AbstractUtility{
67 private static IUndoContext defaultUndoContext;
68
69 /**
70 * <p>openEditor</p>
71 *
72 * @param selectedObject a {@link eu.etaxonomy.cdm.model.common.CdmBase} object.
73 */
74 public static void openEditor(UuidAndTitleCache uuidAndTitleCache){
75 Class type = uuidAndTitleCache.getType();
76 ICdmBase cdmBase = null;
77 if(type.equals(Classification.class)){
78 cdmBase = CdmStore.getService(IClassificationService.class).load(uuidAndTitleCache.getUuid());
79 }
80 else if(type.equals(TaxonNode.class)){
81 cdmBase = CdmStore.getService(ITaxonNodeService.class).load(uuidAndTitleCache.getUuid());
82 }
83 else if(TaxonBase.class.isAssignableFrom(type)){
84 cdmBase = CdmStore.getService(ITaxonService.class).load(uuidAndTitleCache.getUuid());
85 }
86 else if(type.equals(TaxonNameBase.class)){
87 cdmBase = CdmStore.getService(INameService.class).load(uuidAndTitleCache.getUuid());
88 }
89 else{
90 MessagingUtils.warningDialog("Unknown type", NavigationUtil.class, "There is no editor available to open this object.");
91 }
92 if(cdmBase!=null){
93 openEditor(cdmBase);
94 }
95 else{
96 MessagingUtils.warningDialog("Cdm entity not found", NavigationUtil.class, "CDM entity could not be found in the database.");
97 }
98 }
99
100 public static void openEditor(ICdmBase selectedObject){
101 UUID entityUuid = selectedObject.getUuid();
102 try {
103 if(selectedObject instanceof Classification){
104 NewClassificationWizard classificationWizard = new NewClassificationWizard();
105 classificationWizard.init(null, null);
106 classificationWizard.setEntity((Classification) selectedObject);
107 WizardDialog dialog = new WizardDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), classificationWizard);
108 dialog.open();
109 }
110 else if(selectedObject instanceof TaxonNode){
111 EditorUtil.openTaxonNode(entityUuid);
112 }else if(selectedObject instanceof TaxonBase){
113 TaxonBase taxonBase = (TaxonBase)selectedObject;
114 if(taxonBase.isOrphaned()){
115 openInBulkEditor(taxonBase);
116 }
117 else{
118 EditorUtil.openTaxonBase(entityUuid);
119 }
120 }else if(selectedObject instanceof TaxonNameBase){
121 openInBulkEditor(selectedObject);
122 }else if(selectedObject instanceof PolytomousKey){
123 EditorUtil.openPolytomousKey(entityUuid);
124 }else{
125 MessagingUtils.warningDialog("Unsupported Type", NavigationUtil.class, "No editor exists for the current selection: " + selectedObject);
126 }
127 } catch (PartInitException e) {
128 MessagingUtils.error(NavigationUtil.class, "Error opening the editor", e);
129 } catch (Exception e) {
130 MessagingUtils.errorDialog("Could not create Taxon",
131 NavigationUtil.class,
132 e.getMessage(), TaxeditorStorePlugin.PLUGIN_ID,
133 e,
134 true);
135
136 }
137 }
138
139 private static void openInBulkEditor(ICdmBase selectedObject) {
140 ICommandService commandService = (ICommandService)PlatformUI.getWorkbench().getService(ICommandService.class);
141 IHandlerService handlerService = (IHandlerService)PlatformUI.getWorkbench().getService(IHandlerService.class);
142 String openInBulkEditorCommand = "eu.etaxonomy.taxeditor.bulkeditor.openBulkEditorForIdentifiableEntity";
143 Command command = commandService.getCommand(openInBulkEditorCommand);
144 if(command.isDefined()){
145 Map<String, UUID> params = new HashMap<String, UUID>();
146 params.put(openInBulkEditorCommand+".uuid", ((ICdmBase) selectedObject).getUuid()); //$NON-NLS-1$
147 ParameterizedCommand parameterizedCommand = ParameterizedCommand.generateCommand(command, params);
148 try {
149 if(parameterizedCommand!=null){
150 handlerService.executeCommand(parameterizedCommand, null);
151 return;
152 }
153 else{
154 handlerService.executeCommand(command.getId(), null);
155 return;
156 }
157 } catch (NotDefinedException nde) {
158 throw new RuntimeException("Could not find open command: " + command.getId()); //$NON-NLS-1$
159 } catch (Exception exception) {
160 MessagingUtils.error(NavigationUtil.class, "An exception occured while trying to execute "+command.getId(), exception); //$NON-NLS-1$
161 }
162 }
163 }
164
165 /**
166 * <p>openEmpty</p>
167 *
168 * @param parentNodeUuid a {@link java.util.UUID} object.
169 */
170 public static void openEmpty(UUID parentNodeUuid) {
171 try {
172 EditorUtil.openEmpty(parentNodeUuid);
173 } catch (PartInitException e) {
174 MessagingUtils.error(NavigationUtil.class, "Error opening the editor", e);
175 }
176 }
177
178 /**
179 * <p>getShell</p>
180 *
181 * @return a {@link org.eclipse.swt.widgets.Shell} object.
182 */
183 public static Shell getShell() {
184 return getActiveWindow().getShell();
185 }
186
187 /**
188 * <p>getActiveWindow</p>
189 *
190 * @return a {@link org.eclipse.ui.IWorkbenchWindow} object.
191 */
192 public static IWorkbenchWindow getActiveWindow() {
193 return TaxeditorNavigationPlugin.getDefault().getWorkbench().
194 getActiveWorkbenchWindow();
195 }
196
197 /**
198 * <p>getWorkbenchUndoContext</p>
199 *
200 * @return a {@link org.eclipse.core.commands.operations.IUndoContext} object.
201 */
202 public static IUndoContext getWorkbenchUndoContext() {
203 return TaxeditorEditorPlugin.getDefault().getWorkbench().
204 getOperationSupport().getUndoContext();
205 }
206
207 /**
208 * <p>getUndoContext</p>
209 *
210 * @return a {@link org.eclipse.core.commands.operations.IUndoContext} object.
211 */
212 public static IUndoContext getUndoContext() {
213 // FIXME this has to be more specific. Every widget has to have its own undo context
214 // return IOperationHistory.GLOBAL_UNDO_CONTEXT;
215
216 // Plug-ins that wish their operations to be undoable from workbench views
217 // such as the Navigator or Package Explorer should assign the workbench
218 // undo context to their operations.
219 if (defaultUndoContext == null) {
220 defaultUndoContext = new UndoContext();
221 }
222 return defaultUndoContext;
223 }
224
225 /**
226 * Whether a taxonNode has unsaved changes.
227 *
228 * @param taxonNode a {@link eu.etaxonomy.cdm.model.taxon.TaxonNode} object.
229 * @return a boolean.
230 */
231 public static boolean isDirty(TaxonNode taxonNode){
232
233 for (IEditorReference reference : getActivePage().getEditorReferences()) {
234
235 try {
236 if (reference.getEditorInput() instanceof TaxonEditorInput) {
237 TaxonEditorInput editorInput = (TaxonEditorInput) reference.getEditorInput();
238 if(editorInput.getTaxonNode().equals(taxonNode) && reference.isDirty()){
239 return true;
240 }
241 }
242 } catch (PartInitException e) {
243 MessagingUtils.error(NavigationUtil.class, e.getMessage(), e);
244 throw new RuntimeException(e);
245 }
246
247 }
248 return false;
249 }
250
251 /**
252 * <p>selectInNavigator</p>
253 *
254 * @param element a {@link java.lang.Object} object.
255 * @param parentElement a {@link java.lang.Object} object.
256 */
257 public static void selectInNavigator(final Object element, final Object parentElement) {
258 Display.getDefault().asyncExec(new Runnable(){
259
260 @Override
261 public void run() {
262 TaxonNavigator navigator = showNavigator();
263
264 if (navigator != null) {
265 CommonViewer viewer = navigator.getCommonViewer();
266 if (viewer != null) {
267 if (parentElement != null) {
268 viewer.setExpandedState(parentElement, true);
269 }
270 viewer.setSelection(new StructuredSelection(element));
271 }
272 }
273 }
274
275 });
276 }
277
278 /**
279 * <p>openSearch</p>
280 *
281 * @param selection a {@link java.lang.Object} object.
282 */
283 public static void openSearch(Object selection) {
284 if(selection instanceof Taxon){
285 Taxon taxon = (Taxon) selection;
286
287 handleOpeningOfMultipleTaxonNodes(taxon.getTaxonNodes());
288
289 }else if(selection instanceof Synonym){
290 Synonym synonym = (Synonym) selection;
291
292 handleOpeningOfMultipleTaxa(synonym.getAcceptedTaxa());
293
294 }else{
295 MessagingUtils.warningDialog("Not implemented yet", NavigationUtil.class, "You chose to open a name that has no connection to a taxon. The Editor does not support editing of such a content type at the moment.");
296 }
297
298 }
299
300 private static void handleOpeningOfMultipleTaxa(Set<Taxon> acceptedTaxa) {
301 if(acceptedTaxa.size() == 1){
302 openEditor(acceptedTaxa.iterator().next());
303 }else if(acceptedTaxa.size() > 1){
304 // FIXME implement a dialog that shows all possible taxa and let the user choose which he wants to open.
305 MessagingUtils.warningDialog("Not implemented yet", NavigationUtil.class, "The accepted taxon is in multiple taxonomic trees. We currently do not know which one you want to open." +
306 " This case is not handled yet by the software.");
307 }else if(acceptedTaxa.size() == 0){
308 // this is an undesired state
309 MessagingUtils.warningDialog("Not implemented yet", NavigationUtil.class, "This taxon is not connected to a classification. Currently editing of such taxa is not supported yet.");
310 }
311 }
312
313 /**
314 * @param taxonNodes
315 */
316 private static void handleOpeningOfMultipleTaxonNodes(
317 Set<TaxonNode> taxonNodes) {
318
319 if(taxonNodes.size() == 1){
320 openEditor(taxonNodes.iterator().next());
321 }else if(taxonNodes.size() > 1){
322 // FIXME implement a dialog that shows all possible taxa and let the user choose which he wants to open.
323 MessagingUtils.warningDialog("Not implemented yet", NavigationUtil.class, "The accepted taxon is in multiple taxonomic trees. We currently do not know which one you want to open." +
324 " This case is not handled yet by the software.");
325 }else if(taxonNodes.size() == 0){
326 // this is an undesired state
327 MessagingUtils.warningDialog("Incorrect state", NavigationUtil.class, "The accepted taxon is not in a taxonomic view. This should not have happened.");
328 }
329 }
330
331 /**
332 * <p>showNavigator</p>
333 *
334 * @return the TaxonNavigator instance if present
335 */
336 public static TaxonNavigator showNavigator() {
337 return (TaxonNavigator) showView(TaxonNavigator.ID);
338 }
339
340 /**
341 * <p>getNavigator</p>
342 *
343 * @param restore a boolean.
344 * @return a {@link eu.etaxonomy.taxeditor.navigation.navigator.TaxonNavigator} object.
345 */
346 public static TaxonNavigator getNavigator(boolean restore) {
347 return (TaxonNavigator) getView(TaxonNavigator.ID, restore);
348 }
349
350 /**
351 * <p>getOpenEditors</p>
352 *
353 * @return a {@link java.util.Set} object.
354 */
355 public static Set<IEditorPart> getOpenEditors() {
356 return EditorUtil.getOpenEditors();
357 }
358
359 /**
360 * <p>getPluginId</p>
361 *
362 * @return a {@link java.lang.String} object.
363 */
364 public static String getPluginId(){
365 return TaxeditorNavigationPlugin.PLUGIN_ID;
366 }
367
368 }