Merge branch 'release/3.8.0'
[taxeditor.git] / eu.etaxonomy.taxeditor.editor / src / main / java / eu / etaxonomy / taxeditor / editor / view / derivate / DerivateView.java
1 package eu.etaxonomy.taxeditor.editor.view.derivate;
2
3 import java.util.Collection;
4 import java.util.HashSet;
5 import java.util.Map.Entry;
6 import java.util.Set;
7 import java.util.UUID;
8
9 import org.eclipse.core.runtime.IProgressMonitor;
10 import org.eclipse.jface.action.MenuManager;
11 import org.eclipse.jface.util.LocalSelectionTransfer;
12 import org.eclipse.jface.viewers.AbstractTreeViewer;
13 import org.eclipse.jface.viewers.ISelection;
14 import org.eclipse.jface.viewers.ISelectionChangedListener;
15 import org.eclipse.jface.viewers.SelectionChangedEvent;
16 import org.eclipse.jface.viewers.StructuredSelection;
17 import org.eclipse.jface.viewers.TreeNode;
18 import org.eclipse.jface.viewers.TreeSelection;
19 import org.eclipse.jface.viewers.TreeViewer;
20 import org.eclipse.swt.SWT;
21 import org.eclipse.swt.dnd.DND;
22 import org.eclipse.swt.dnd.Transfer;
23 import org.eclipse.swt.widgets.Composite;
24 import org.eclipse.swt.widgets.Control;
25 import org.eclipse.swt.widgets.Menu;
26 import org.eclipse.swt.widgets.Tree;
27 import org.eclipse.ui.IEditorInput;
28 import org.eclipse.ui.IEditorPart;
29 import org.eclipse.ui.IEditorSite;
30 import org.eclipse.ui.PartInitException;
31 import org.eclipse.ui.part.EditorPart;
32
33 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
34 import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
35 import eu.etaxonomy.cdm.api.service.IOccurrenceService;
36 import eu.etaxonomy.cdm.api.service.molecular.ISequenceService;
37 import eu.etaxonomy.cdm.model.common.CdmBase;
38 import eu.etaxonomy.cdm.model.molecular.Sequence;
39 import eu.etaxonomy.cdm.model.molecular.SingleRead;
40 import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
41 import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
42 import eu.etaxonomy.taxeditor.editor.Messages;
43 import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
44 import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
45 import eu.etaxonomy.taxeditor.model.IPartContentHasFactualData;
46 import eu.etaxonomy.taxeditor.model.IPartContentHasMedia;
47 import eu.etaxonomy.taxeditor.model.IPartContentHasSupplementalData;
48 import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
49 import eu.etaxonomy.taxeditor.store.CdmStore;
50 import eu.etaxonomy.taxeditor.view.derivateSearch.DerivateContentProvider;
51 import eu.etaxonomy.taxeditor.view.derivateSearch.DerivateLabelProvider;
52
53 /**
54 * Displays the derivate hierarchy of the specimen specified in the editor input.
55 *
56 */
57 public class DerivateView extends EditorPart implements IPartContentHasFactualData, IDirtyMarkable,
58 IConversationEnabled, IPartContentHasDetails, IPartContentHasSupplementalData, IPartContentHasMedia,
59 ISelectionChangedListener, IPostOperationEnabled {
60
61 public static final String ID = "eu.etaxonomy.taxeditor.editor.view.derivate.DerivateView"; //$NON-NLS-1$
62
63 public static final String YOU_NEED_TO_SAVE_BEFORE_PERFORMING_THIS_ACTION = Messages.DerivateView_YOU_NEED_TO_SAVE;
64 public static final String VIEW_HAS_UNSAVED_CHANGES = Messages.DerivateView_UNSAVED_CHANGES;
65
66 private ConversationHolder conversation;
67
68 private TreeViewer viewer;
69
70 private boolean isDirty;
71
72 private final int dndOperations = DND.DROP_MOVE;
73
74 private DerivateLabelProvider labelProvider;
75
76 private Set<SingleRead> multiLinkSingleReads;
77
78 private ISelection selection = null;
79
80 /**
81 * Default constructor
82 */
83 public DerivateView() {
84 }
85
86 @Override
87 public void createPartControl(Composite parent) {
88 viewer = new TreeViewer(new Tree(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION));
89 viewer.setContentProvider(new DerivateContentProvider());
90 labelProvider = new DerivateLabelProvider();
91 labelProvider.setConversation(conversation);
92 viewer.setLabelProvider(labelProvider);
93 viewer.setAutoExpandLevel(AbstractTreeViewer.ALL_LEVELS);
94 // Propagate selection from viewer
95 getSite().setSelectionProvider(viewer);
96 //listen to selection changes
97 viewer.addSelectionChangedListener(this);
98
99 //create context menu
100 MenuManager menuManager = new MenuManager();
101 getSite().registerContextMenu(menuManager, viewer);
102 Control control = viewer.getControl();
103 Menu menu = menuManager.createContextMenu(control);
104 control.setMenu(menu);
105
106 generateMultiLinkSingleReads();
107 labelProvider.setMultiLinkSingleReads(multiLinkSingleReads);
108 IEditorInput editorInput = getEditorInput();
109 viewer.setInput(((DerivateViewEditorInput) editorInput).getRootUUIDs());
110 //set selection to selected derivate if only one was selected
111 if(editorInput instanceof DerivateViewEditorInput){
112 Set<UUID> derivateUUIDs = ((DerivateViewEditorInput) editorInput).getDerivateUUIDs();
113 if(derivateUUIDs.size()==1){
114 SpecimenOrObservationBase<?> specimen = CdmStore.getService(IOccurrenceService.class).load(derivateUUIDs.iterator().next());
115 if(specimen!=null){
116 viewer.setSelection(new StructuredSelection(new TreeNode(specimen)));
117 }
118 }
119 }
120
121 //add drag'n'drop support
122 Transfer[] transfers = new Transfer[] {LocalSelectionTransfer.getTransfer(),};
123 viewer.addDragSupport(dndOperations, transfers, new DerivateDragListener(this));
124 viewer.addDropSupport(dndOperations, transfers, new DerivateDropListener(this));
125 }
126
127 @Override
128 public void doSave(IProgressMonitor monitor) {
129 String taskName = Messages.DerivateView_SAVING_HIERARCHY;
130 if(getEditorInput() instanceof DerivateViewEditorInput){
131 DerivateViewEditorInput derivateViewEditorInput = (DerivateViewEditorInput) getEditorInput();
132 taskName += " "+derivateViewEditorInput.getName(); //$NON-NLS-1$
133 }
134 monitor.beginTask(taskName, 3);
135 if (!conversation.isBound()) {
136 conversation.bind();
137 }
138 monitor.worked(1);
139
140 // commit the conversation and start a new transaction immediately
141 conversation.commit(true);
142 monitor.worked(1);
143
144 this.setDirty(false);
145 monitor.worked(1);
146 monitor.done();
147 firePropertyChange(PROP_DIRTY);
148 refreshTree();
149 }
150
151 @Override
152 public void doSaveAs() {
153 }
154
155 @Override
156 public String getTitleToolTip() {
157 if(getEditorInput() instanceof DerivateViewEditorInput){
158 DerivateViewEditorInput derivateViewEditorInput = (DerivateViewEditorInput) getEditorInput();
159 return derivateViewEditorInput.getName();
160 }
161 return Messages.DerivateView_DERIVATIVE_EDITOR;
162 }
163
164 @Override
165 public void init(IEditorSite site, IEditorInput input) throws PartInitException {
166 setSite(site);
167 setInput(input);
168 if(input instanceof DerivateViewEditorInput){
169 DerivateViewEditorInput derivateViewEditorInput = (DerivateViewEditorInput) input;
170 conversation = derivateViewEditorInput.getConversationHolder();
171 setPartName(derivateViewEditorInput.getName());
172 }
173 }
174
175 @Override
176 public boolean isDirty() {
177 return isDirty;
178 }
179
180 /**
181 * @param isDirty the isDirty to set
182 */
183 public void setDirty(boolean isDirty) {
184 this.isDirty = isDirty;
185 }
186
187 @Override
188 public boolean isSaveAsAllowed() {
189 return false;
190 }
191
192 @Override
193 public void setFocus() {
194 viewer.getControl().setFocus();
195 //make sure to bind again if maybe in another view the conversation was unbound
196 if(!conversation.isBound()){
197 conversation.bind();
198 }
199 }
200
201 @Override
202 public void update(CdmDataChangeMap changeEvents) {
203 }
204
205 @Override
206 public ConversationHolder getConversationHolder() {
207 return conversation;
208 }
209
210 /**
211 * @return the viewer
212 */
213 public TreeViewer getViewer() {
214 return viewer;
215 }
216
217 @Override
218 public void changed(Object element) {
219 setDirty(true);
220 firePropertyChange(IEditorPart.PROP_DIRTY);
221 viewer.refresh();
222 }
223
224 @Override
225 public void forceDirty() {
226 changed(null);
227 }
228
229 /**
230 * Refreshes the derivate hierarchy tree and expands the tree
231 * to show and select the given object.
232 *
233 * @param expandTo the object to which the tree should be expanded
234 */
235 public void refreshTree(Object expandTo){
236 refreshTree();
237 TreeSelection selection = (TreeSelection) viewer.getSelection();
238 viewer.expandToLevel(selection.getFirstElement(), 1);
239 viewer.setSelection(new StructuredSelection(new TreeNode(expandTo)));
240 }
241
242 /**
243 * Refreshes the derivate hierarchy tree
244 */
245 public void refreshTree(){
246 generateMultiLinkSingleReads();
247 labelProvider.setMultiLinkSingleReads(multiLinkSingleReads);
248 viewer.refresh();
249 }
250
251 private void generateMultiLinkSingleReads() {
252 Set<SingleRead> multiLinkSingleReads = new HashSet<SingleRead>();
253 for(Entry<SingleRead, Collection<Sequence>> entry:CdmStore.getService(ISequenceService.class).getSingleReadSequencesMap().entrySet()){
254 if(entry.getValue().size()>1){
255 multiLinkSingleReads.add(entry.getKey());
256 }
257 }
258 this.multiLinkSingleReads = multiLinkSingleReads;
259 }
260
261 /**
262 * @return a set of {@link SingleRead}s that have multiple parents
263 */
264 public Set<SingleRead> getMultiLinkSingleReads() {
265 return this.multiLinkSingleReads;
266 }
267
268 @Override
269 public void selectionChanged(SelectionChangedEvent event) {
270 this.selection = event.getSelection();
271 }
272
273 public ISelection getSelection() {
274 return selection;
275 }
276
277 public DerivateLabelProvider getLabelProvider() {
278 return labelProvider;
279 }
280
281 @Override
282 public boolean postOperation(CdmBase objectAffectedByOperation) {
283 refreshTree();
284 if(objectAffectedByOperation!=null){
285 changed(objectAffectedByOperation);
286 }
287 return true;
288 }
289
290 @Override
291 public boolean onComplete() {
292 return true;
293 }
294
295 @Override
296 public boolean canAttachMedia() {
297 return true;
298 }
299
300 }