Project

General

Profile

Download (19.3 KB) Statistics
| Branch: | Tag: | Revision:
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.editor.name.e4;
11

    
12
import java.util.ArrayList;
13
import java.util.HashSet;
14
import java.util.List;
15
import java.util.Set;
16

    
17
import javax.annotation.PostConstruct;
18
import javax.annotation.PreDestroy;
19
import javax.inject.Inject;
20

    
21
import org.apache.commons.lang.StringUtils;
22
import org.eclipse.core.commands.operations.IUndoContext;
23
import org.eclipse.core.commands.operations.UndoContext;
24
import org.eclipse.core.runtime.IProgressMonitor;
25
import org.eclipse.core.runtime.OperationCanceledException;
26
import org.eclipse.e4.core.contexts.IEclipseContext;
27
import org.eclipse.e4.core.services.events.IEventBroker;
28
import org.eclipse.e4.ui.di.Focus;
29
import org.eclipse.e4.ui.di.Persist;
30
import org.eclipse.e4.ui.model.application.ui.MDirtyable;
31
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
32
import org.eclipse.e4.ui.services.EMenuService;
33
import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
34
import org.eclipse.jface.dialogs.MessageDialog;
35
import org.eclipse.jface.viewers.ISelection;
36
import org.eclipse.jface.viewers.ISelectionProvider;
37
import org.eclipse.jface.viewers.StructuredSelection;
38
import org.eclipse.swt.dnd.DND;
39
import org.eclipse.swt.dnd.DropTarget;
40
import org.eclipse.swt.dnd.Transfer;
41
import org.eclipse.swt.graphics.Color;
42
import org.eclipse.swt.widgets.Composite;
43
import org.eclipse.ui.ISelectionListener;
44
import org.eclipse.ui.IWorkbenchPart;
45
import org.eclipse.ui.IWorkbenchPartReference;
46
import org.eclipse.ui.forms.ManagedForm;
47
import org.eclipse.ui.forms.widgets.FormToolkit;
48
import org.eclipse.ui.forms.widgets.ScrolledForm;
49
import org.eclipse.ui.forms.widgets.TableWrapLayout;
50

    
51
import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
52
import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
53
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
54
import eu.etaxonomy.cdm.model.common.CdmBase;
55
import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
56
import eu.etaxonomy.cdm.model.taxon.Taxon;
57
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
58
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
59
import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
60
import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
61
import eu.etaxonomy.taxeditor.editor.CdmDataTransfer;
62
import eu.etaxonomy.taxeditor.editor.ISecuredEditor;
63
import eu.etaxonomy.taxeditor.editor.ITaxonEditor;
64
import eu.etaxonomy.taxeditor.editor.e4.TaxonEditorInputE4;
65
import eu.etaxonomy.taxeditor.editor.l10n.Messages;
66
import eu.etaxonomy.taxeditor.editor.name.e4.container.AbstractGroupE4;
67
import eu.etaxonomy.taxeditor.editor.name.e4.container.AbstractGroupedContainerE4;
68
import eu.etaxonomy.taxeditor.editor.name.e4.container.AcceptedGroupE4;
69
import eu.etaxonomy.taxeditor.editor.name.e4.container.AcceptedNameContainerE4;
70
import eu.etaxonomy.taxeditor.editor.name.e4.container.ContainerFactoryE4;
71
import eu.etaxonomy.taxeditor.editor.name.e4.container.HomotypicalSynonymGroupE4;
72
import eu.etaxonomy.taxeditor.editor.name.e4.container.MisappliedGroupE4;
73
import eu.etaxonomy.taxeditor.editor.name.e4.dnd.NameEditorDropTargetListenerE4;
74
import eu.etaxonomy.taxeditor.event.WorkbenchEventConstants;
75
import eu.etaxonomy.taxeditor.model.AbstractUtility;
76
import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
77
import eu.etaxonomy.taxeditor.model.IPartChangeListener;
78
import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
79
import eu.etaxonomy.taxeditor.model.IPartContentHasFactualData;
80
import eu.etaxonomy.taxeditor.model.IPartContentHasMedia;
81
import eu.etaxonomy.taxeditor.model.IPartContentHasSupplementalData;
82
import eu.etaxonomy.taxeditor.model.MessagingUtils;
83
import eu.etaxonomy.taxeditor.model.TaxeditorPartService;
84
import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
85
import eu.etaxonomy.taxeditor.preference.Resources;
86
import eu.etaxonomy.taxeditor.security.RequiredPermissions;
87
import eu.etaxonomy.taxeditor.store.CdmStore;
88
import eu.etaxonomy.taxeditor.workbench.part.IE4SavablePart;
89

    
90
/**
91
 *
92
 * @author pplitzner
93
 * @date Aug 24, 2017
94
 *
95
 */
96
public class TaxonNameEditorE4 implements IConversationEnabled, IDirtyMarkable, IPartContentHasDetails,
97
        IPartContentHasSupplementalData, IPartContentHasMedia, IPartContentHasFactualData, IPartChangeListener,
98
        ISelectionListener, ISecuredEditor, IPostOperationEnabled, IE4SavablePart, ITaxonEditor, IDropTargetableE4 {
99

    
100
	private Taxon taxon;
101

    
102
	private ManagedForm managedForm;
103
	private ScrolledForm scrolledForm;
104
	private Composite parent;
105
	private ISelectionProvider simpleSelectionProvider;
106

    
107
	private TaxonBase selection;
108

    
109
	private ConversationHolder conversation;
110

    
111
	private AcceptedGroupE4 acceptedGroup;
112
	private List<HomotypicalSynonymGroupE4> heterotypicSynonymGroups = new ArrayList<>();
113
	private MisappliedGroupE4 misappliedGroup;
114

    
115
	private DropTarget target;
116

    
117
	private TaxonBase objectAffectedByLastOperation;
118

    
119
	@Inject
120
	private EMenuService menuService;
121

    
122
	@Inject
123
	private ESelectionService selService;
124

    
125
	@Inject
126
	private IEclipseContext context;
127

    
128
	@Inject
129
	private MDirtyable dirty;
130

    
131
	private MPart thisPart;
132

    
133
    private TaxonEditorInputE4 input;
134

    
135
    private UndoContext undoContext;
136

    
137
    @Inject
138
    private IEventBroker eventBroker;
139

    
140
	@Inject
141
	public TaxonNameEditorE4() {
142
	    undoContext = new UndoContext();
143
	}
144

    
145

    
146
	@PostConstruct
147
    public void createPartControl(Composite parent, MPart thisPart) {
148
	    this.thisPart = thisPart;
149
        if (CdmStore.isActive()){
150
            if(conversation == null){
151
                conversation = CdmStore.createConversation();
152
            }
153
        }
154
        else{
155
            return;
156
        }
157

    
158
        createManagedForm(parent);
159

    
160
		TaxeditorPartService.getInstance().addListener(
161
				TaxeditorPartService.PART_ACTIVATED, this);
162

    
163
	}
164

    
165
	protected void createManagedForm(Composite composite) {
166

    
167
		managedForm = new ManagedForm(composite) {
168

    
169
			@Override
170
			public void dirtyStateChanged() {
171
			    dirty.setDirty(true);
172
			}
173

    
174
			@Override
175
			public boolean setInput(Object input) {
176
				if (input instanceof AbstractGroupedContainerE4) {
177
				    TaxonBase newSelection = ((AbstractGroupedContainerE4) input).getData();
178
				    if(selection!=newSelection || TaxonNameEditorE4.this.isDirty()){
179
				        selection = newSelection;
180
				        selService.setSelection(new StructuredSelection(selection));
181
				    }
182
				}else if(input == null){
183
					selection = null;
184
                    selService.setSelection(new StructuredSelection());
185
				}
186

    
187

    
188
				return super.setInput(input);
189
			}
190
		};
191

    
192
		scrolledForm = managedForm.getForm();
193
		parent = scrolledForm.getBody();
194

    
195
		parent.setData(taxon);
196

    
197
		TableWrapLayout layout = new TableWrapLayout();
198
		layout.leftMargin = 0;
199
		layout.rightMargin = 0;
200
		layout.topMargin = 0;
201
		layout.bottomMargin = 0;
202

    
203
		layout.verticalSpacing = 0;
204
		layout.horizontalSpacing = 0;
205

    
206
		parent.setLayout(layout);
207
		parent.setBackground(AbstractUtility
208
				.getColor(Resources.COLOR_COMPOSITE_BACKGROUND));
209
	}
210

    
211
	public void createOrUpdateNameComposites() {
212
		ContainerFactoryE4.createOrUpdateAcceptedTaxonsHomotypicGroup(this);
213
		ContainerFactoryE4.createOrUpdateHeterotypicSynonymyGroups(this);
214
		ContainerFactoryE4.createOrUpdateMisapplicationsGroup(this);
215

    
216

    
217
		// Redraw composite
218
		managedForm.reflow(true);
219
		managedForm.refresh();
220
	}
221

    
222
	@Override
223
    public Taxon getTaxon() {
224
		return HibernateProxyHelper.deproxy(taxon);
225
	}
226

    
227
	public void setDirty() {
228
		managedForm.dirtyStateChanged();
229
	}
230

    
231
	@Focus
232
	public void setFocus() {
233
	    //make sure to bind again if maybe in another view the conversation was unbound
234
        if(conversation!=null && !conversation.isBound()){
235
            conversation.bind();
236
        }
237
	    if(input!=null){
238
	        if (getSelectedContainer() == null) {
239
	            throw new IllegalStateException(
240
	                    Messages.TaxonNameEditor_THERE_SHOULD_ALWAYS_BE);
241
	        }
242
	        getSelectedContainer().setSelected();
243

    
244
	        // check permissions
245
	        boolean doEnable = permissionsSatisfied();
246
	        managedForm.getForm().setEnabled(doEnable);
247
	    }
248
        eventBroker.post(WorkbenchEventConstants.CURRENT_ACTIVE_EDITOR, this);
249
	}
250

    
251
	@Override
252
	public boolean permissionsSatisfied() {
253
		TaxonNode taxonNode = input.getTaxonNode();
254
		boolean doEnable = CdmStore.currentAuthentiationHasPermission(taxonNode, RequiredPermissions.TAXONNODE_EDIT);
255
		return doEnable;
256
	}
257

    
258
	@Override
259
    public ConversationHolder getConversationHolder() {
260
		return conversation;
261
	}
262

    
263
	/** {@inheritDoc} */
264
	@Override
265
    public void update(CdmDataChangeMap events) {
266
		// redraw();
267
	}
268

    
269
	/**
270
	 * Redraws this editor return true on success
271
	 *
272
	 * @return a boolean.
273
	 */
274
    public boolean redraw() {
275
		return redraw(true);
276
	}
277

    
278
	/**
279
	 * {@inheritDoc}
280
	 *
281
	 * Redraws the editor controls
282
	 */
283
    public boolean redraw(boolean focus) {
284

    
285
		createOrUpdateNameComposites();
286

    
287
		if (focus) {
288
			setFocus();
289
		}
290

    
291
		return true;
292
	}
293

    
294
	@Override
295
    public boolean postOperation(CdmBase objectAffectedByOperation) {
296

    
297
		changed(objectAffectedByOperation);
298

    
299
		redraw(false);
300

    
301
		if (objectAffectedByOperation instanceof TaxonBase) {
302
			objectAffectedByLastOperation = (TaxonBase) objectAffectedByOperation;
303
		}
304

    
305
		return true;
306
	}
307

    
308
	public ManagedForm getManagedForm() {
309
		return managedForm;
310
	}
311

    
312

    
313
	/**
314
	 * <p>
315
	 * checkForEmptyNames
316
	 * </p>
317
	 *
318
	 * @return true if there are empty names
319
	 */
320
	public boolean checkForEmptyNames() {
321
		for (AbstractGroupedContainerE4 container : getGroupedContainers()) {
322
			if (container.getName() == null
323
					|| StringUtils.isEmpty(container.getName().getTitleCache())) {
324
				return true;
325
			}
326
		}
327
		return false;
328
	}
329

    
330
	public Set<AbstractGroupedContainerE4> getEmptyContainers() {
331
		Set<AbstractGroupedContainerE4> containersWithEmptyNames = new HashSet<>();
332

    
333
		for (AbstractGroupedContainerE4 container : getGroupedContainers()) {
334
			if (container.getName() == null
335
					|| StringUtils.isEmpty(container.getName().getTitleCache())) {
336
				containersWithEmptyNames.add(container);
337
			}
338
		}
339

    
340
		return containersWithEmptyNames;
341
	}
342

    
343
	/** {@inheritDoc} */
344
	@Override
345
    @Persist
346
	public void save(IProgressMonitor monitor) {
347

    
348
	    monitor.beginTask(Messages.TaxonNameEditor_SAVING_NAMES, getGroupedContainers().size());
349
	    if (!conversation.isBound()) {
350
	        conversation.bind();
351
	    }
352
	    monitor.worked(1);
353

    
354
	    // check for empty names
355
	    if (checkForEmptyNames()) {
356
	        MessageDialog.openWarning(AbstractUtility.getShell(), Messages.MultiPageTaxonEditor_NO_NAME_SPECIFIED,
357
	                Messages.MultiPageTaxonEditor_NO_NAME_SPECIFIED_MESSAGE);
358
	        return;
359
	    }
360
	    for (AbstractGroupedContainerE4 container : getGroupedContainers()) {
361

    
362
	        monitor.subTask(Messages.TaxonNameEditor_SAVING_COMPOSITES
363
	                + container.getTaxonBase().getTitleCache());
364
	        container.persistName();
365

    
366
	        // In case the progress monitor was canceled throw an exception.
367
	        if (monitor.isCanceled()) {
368
	            throw new OperationCanceledException();
369
	        }
370

    
371
	     // Otherwise declare this step as done.
372
	        monitor.worked(1);
373

    
374
	    }
375
	    input.merge();
376
	    // commit the conversation and start a new transaction immediately
377
        conversation.commit(true);
378

    
379

    
380
        dirty.setDirty(false);
381

    
382
	    // Stop the progress monitor.
383
	    monitor.done();
384
	}
385

    
386
	public void init(TaxonEditorInputE4 input) {
387

    
388
		if (!(input != null)) {
389
            MessagingUtils.error(this.getClass(), new Exception(Messages.TaxonNameEditor_INVALID_INPUT));
390
            return;
391
        }
392

    
393
		if (input.getAdapter(Taxon.class) != null) {
394
			taxon = CdmBase.deproxy(input.getAdapter(Taxon.class), Taxon.class);
395
		} else {
396
		    MessagingUtils.error(this.getClass(), new Exception(Messages.TaxonNameEditor_INVALID_INPUT_TAXON_NULL));
397
		    return;
398
		}
399

    
400
		this.input = input;
401

    
402
        createOrUpdateNameComposites();
403

    
404
        createDragSupport();
405

    
406
        setPartName();
407

    
408
        //set initial selection
409
        TaxonBase initiallySelectedTaxonBase = input.getInitiallySelectedTaxonBase();
410
        if(initiallySelectedTaxonBase!=null){
411
            selService.setSelection(new StructuredSelection(initiallySelectedTaxonBase));
412
            getContainer(initiallySelectedTaxonBase).setSelected();
413
        }
414
	}
415

    
416
   private void createDragSupport() {
417
       // Listen for names being dragged outside of existing homotypic groups -
418
       // user wants to create a new group
419
       Transfer[] types = new Transfer[] { CdmDataTransfer.getInstance() };
420
       int operations = DND.DROP_MOVE;
421
       if (target == null) {
422
           target = new DropTarget(parent, operations);
423
           target.setTransfer(types);
424
           target.addDropListener(new NameEditorDropTargetListenerE4(this));
425
       }
426
   }
427

    
428
	public AcceptedNameContainerE4 getAcceptedNameContainer() {
429
		return getAcceptedGroup().getAcceptedNameContainer();
430
	}
431

    
432
	public HomotypicalSynonymGroupE4 getHomotypicalGroupContainer(
433
			HomotypicalGroup homotypicalGroup) {
434
		for (HomotypicalSynonymGroupE4 group : getHeterotypicSynonymGroups()) {
435
			if (group.getGroup().equals(homotypicalGroup)) {
436
				return group;
437
			}
438
		}
439

    
440
		return null;
441
	}
442

    
443
	/**
444
	 * <p>
445
	 * getDirtyNames
446
	 * </p>
447
	 *
448
	 * @return a Set containing all composites that have been edited
449
	 */
450
	public Set<AbstractGroupedContainerE4> getDirtyNames() {
451
		Set<AbstractGroupedContainerE4> dirtyNames = new HashSet<>();
452

    
453
		for (AbstractGroupedContainerE4 composite : getGroupedContainers()) {
454
			if (composite.isDirty()) {
455
				dirtyNames.add(composite);
456
			}
457
		}
458

    
459
		return dirtyNames;
460
	}
461

    
462
	public List<AbstractGroupedContainerE4> getGroupedContainers() {
463
		List<AbstractGroupedContainerE4> groupedComposites = new ArrayList<>();
464

    
465
		for (AbstractGroupE4 group : getAllGroups()) {
466
		    if (group!= null){
467
		        groupedComposites.addAll(group.getGroupedContainers());
468
		    }
469
		}
470

    
471
		return groupedComposites;
472
	}
473

    
474
	public List<AbstractGroupE4> getAllGroups() {
475
		List<AbstractGroupE4> allGroups = new ArrayList<>();
476

    
477
		allGroups.add(getAcceptedGroup());
478

    
479
		heterotypicSynonymGroups = getHeterotypicSynonymGroups();
480

    
481
		if (heterotypicSynonymGroups != null) {
482
			allGroups.addAll(heterotypicSynonymGroups);
483
		}
484

    
485
		if (misappliedGroup != null) {
486
			allGroups.add(misappliedGroup);
487
		}
488

    
489
		return allGroups;
490
	}
491

    
492
	@Override
493
	public IEclipseContext getContext() {
494
	    return context;
495
	}
496

    
497
	public boolean isDirty() {
498
		return dirty.isDirty();
499
	}
500

    
501
	@PreDestroy
502
	public void dispose() {
503
        if(conversation!=null){
504
            conversation.unregisterForDataStoreChanges(this);
505
            conversation.close();
506
        }
507
        eventBroker.post(WorkbenchEventConstants.CURRENT_ACTIVE_EDITOR, null);
508
	}
509

    
510
	/** {@inheritDoc} */
511
	@Override
512
    public void selectionChanged(IWorkbenchPart part, ISelection selection) {
513

    
514
	}
515

    
516
	public AbstractGroupedContainerE4 getSelectedContainer() {
517
		return (selection != null) ? getContainer(selection)
518
				: getAcceptedNameContainer();
519
	}
520

    
521
    @Override
522
    public void dragEntered() {
523
        // TODO change this
524
        getControl().setBackground(
525
                AbstractUtility.getColor(Resources.COLOR_DRAG_ENTER));
526
    }
527

    
528
    @Override
529
    public void dragLeft() {
530
        getControl().setBackground(
531
                AbstractUtility.getColor(Resources.COLOR_COMPOSITE_BACKGROUND));
532
    }
533

    
534

    
535
	public void setMisapplicationsGroup(MisappliedGroupE4 misappliedGroup) {
536
		this.misappliedGroup = misappliedGroup;
537
	}
538

    
539
	public FormToolkit getToolkit() {
540
		return managedForm.getToolkit();
541
	}
542

    
543
	public List<HomotypicalSynonymGroupE4> getHeterotypicSynonymGroups() {
544
		return heterotypicSynonymGroups;
545
	}
546

    
547
	public void addHeterotypicSynonymGroup(HomotypicalSynonymGroupE4 group) {
548
		heterotypicSynonymGroups.add(group);
549
	}
550

    
551
	public AcceptedGroupE4 getAcceptedGroup() {
552
		return acceptedGroup;
553
	}
554

    
555
	public void setAcceptedGroup(AcceptedGroupE4 acceptedGroup) {
556
		this.acceptedGroup = acceptedGroup;
557
	}
558

    
559
	public MisappliedGroupE4 getMisappliedGroup() {
560
		return misappliedGroup;
561
	}
562

    
563
	public boolean isActive() {
564
		return this.equals(AbstractUtility.getActivePart());
565
	}
566

    
567
    @Override
568
    public boolean onComplete() {
569
		getContainer(objectAffectedByLastOperation).setSelected();
570
		return true;
571
	}
572

    
573
	/** {@inheritDoc} */
574
	@Override
575
    public void partChanged(Integer eventType, IWorkbenchPartReference partRef) {
576
		if (!partRef.getPart(false).equals(this)) {
577
			// getSelectedObject().colorSelected(AbstractGroupedContainer.SELECTED_NO_FOCUS);
578
		}
579
	}
580

    
581
	public void removeGroup(AbstractGroupE4 group) {
582
		if (group != null) {
583
			group.dispose();
584

    
585
			//if (heterotypicSynonymGroups != null) {
586
			heterotypicSynonymGroups.remove(group);
587
			//}
588
		}
589
	}
590

    
591
	public AbstractGroupedContainerE4 getContainer(TaxonBase taxonBase) {
592
		List<AbstractGroupedContainerE4> groupedContainers = getGroupedContainers();
593
		for (AbstractGroupedContainerE4 container : groupedContainers) {
594
			if (container.getData().equals(taxonBase)
595
					&& container.getNameViewer().getTextWidget() != null) {
596
				return container;
597
			}
598
		}
599
		return getAcceptedNameContainer();
600
	}
601

    
602
    public void setOnError() {
603
		Color disabledColor =  AbstractUtility.getColor(Resources.COLOR_EDITOR_ERROR);
604
		setEnabled(false, disabledColor);
605
	}
606

    
607
	public void setDisabled(){
608
		Color disabledColor =  AbstractUtility.getColor(Resources.COLOR_TEXT_DISABLED_BACKGROUND);
609
		setEnabled(false, disabledColor);
610
	}
611

    
612
	protected void setEnabled(boolean enabled, Color background) {
613

    
614
		for(AbstractGroupedContainerE4 groupedContainer : getGroupedContainers()){
615
			groupedContainer.setEnabled(enabled);
616
		}
617

    
618
		// send an empty selection to the current provider - TODO only on error ???
619
		if (!enabled) {
620
			getManagedForm().setInput(null);
621

    
622
			for (AbstractGroupedContainerE4 groupedContainer : getGroupedContainers()) {
623
				groupedContainer.setBackground(background);
624
			}
625
		}
626
		getControl().setBackground(background);
627
	}
628

    
629
    @Override
630
    public void changed(Object element) {
631
        // setDirty(true);
632
        // if the attribute is null then do not set the dirty flag -> hotfix for the problem that for tasks done in service methods the changes are saved automatically
633
        if (element != null){
634
            dirty.setDirty(true);
635
            //refresh part title
636
            //TODO: refresh taxon node in taxon navigator
637
            setPartName();
638
        }
639

    
640
        if (element instanceof TaxonBase) {
641
            AbstractGroupedContainerE4 container = getContainer((TaxonBase) element);
642
            if (container != null) {
643
                container.refresh();
644
            }
645
        }
646
        if (element instanceof TaxonRelationship) {
647
            AbstractGroupedContainerE4 container = getContainer(((TaxonRelationship) element).getFromTaxon());
648
            if (container != null) {
649
                container.refresh();
650
            }
651
        }
652
    }
653

    
654
    public void setPartName(){
655
        thisPart.setLabel(this.taxon.getName().getFullTitleCache());
656
    }
657

    
658
    @Override
659
    public void forceDirty() {
660
        setDirty();
661
    }
662

    
663

    
664
    public IUndoContext getUndoContext() {
665
        return undoContext;
666
    }
667

    
668
    @Override
669
    public Composite getControl(){
670
        return managedForm.getForm().getBody();
671
    }
672

    
673
    public EMenuService getMenuService() {
674
        return menuService;
675
    }
676

    
677
    public ESelectionService getSelectionService() {
678
        return selService;
679
    }
680

    
681

    
682
    /**
683
     * {@inheritDoc}
684
     */
685
    @Override
686
    public boolean canAttachMedia() {
687
        return true;
688
    }
689

    
690
    public TaxonEditorInputE4 getEditorInput() {
691
        return input;
692
    }
693

    
694
    /**
695
     * {@inheritDoc}
696
     */
697
    @Override
698
    public TaxonNameEditorE4 getEditor() {
699
        return this;
700
    }
701

    
702
}
(2-2/2)