Move derivative search view classes to taxeditor.editor
[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
8 import org.eclipse.core.runtime.IProgressMonitor;
9 import org.eclipse.jface.action.MenuManager;
10 import org.eclipse.jface.util.LocalSelectionTransfer;
11 import org.eclipse.jface.viewers.AbstractTreeViewer;
12 import org.eclipse.jface.viewers.ISelection;
13 import org.eclipse.jface.viewers.ISelectionChangedListener;
14 import org.eclipse.jface.viewers.SelectionChangedEvent;
15 import org.eclipse.jface.viewers.StructuredSelection;
16 import org.eclipse.jface.viewers.TreeNode;
17 import org.eclipse.jface.viewers.TreeSelection;
18 import org.eclipse.jface.viewers.TreeViewer;
19 import org.eclipse.swt.SWT;
20 import org.eclipse.swt.dnd.DND;
21 import org.eclipse.swt.dnd.Transfer;
22 import org.eclipse.swt.widgets.Composite;
23 import org.eclipse.swt.widgets.Control;
24 import org.eclipse.swt.widgets.Menu;
25 import org.eclipse.swt.widgets.Tree;
26 import org.eclipse.ui.IEditorInput;
27 import org.eclipse.ui.IEditorPart;
28 import org.eclipse.ui.IEditorSite;
29 import org.eclipse.ui.PartInitException;
30 import org.eclipse.ui.part.EditorPart;
31
32 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
33 import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
34 import eu.etaxonomy.cdm.api.service.molecular.ISequenceService;
35 import eu.etaxonomy.cdm.model.common.CdmBase;
36 import eu.etaxonomy.cdm.model.molecular.Sequence;
37 import eu.etaxonomy.cdm.model.molecular.SingleRead;
38 import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
39 import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
40 import eu.etaxonomy.taxeditor.editor.Messages;
41 import eu.etaxonomy.taxeditor.editor.view.derivate.searchFilter.DerivateSearchCompositeController;
42 import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
43 import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
44 import eu.etaxonomy.taxeditor.model.IPartContentHasFactualData;
45 import eu.etaxonomy.taxeditor.model.IPartContentHasMedia;
46 import eu.etaxonomy.taxeditor.model.IPartContentHasSupplementalData;
47 import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
48 import eu.etaxonomy.taxeditor.store.CdmStore;
49 import eu.etaxonomy.taxeditor.ui.element.LayoutConstants;
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 private DerivateContentProvider contentProvider;
82
83 private DerivateSearchCompositeController derivateSearchCompositeController;
84
85 /**
86 * Default constructor
87 */
88 public DerivateView() {
89 }
90
91 @Override
92 public void createPartControl(Composite parent) {
93
94 parent.setLayout(LayoutConstants.LAYOUT());
95 parent.setLayoutData(LayoutConstants.FILL());
96
97 //---search and filter---
98 derivateSearchCompositeController = new DerivateSearchCompositeController(parent, this);
99 derivateSearchCompositeController.setEnabled(CdmStore.isActive());
100 derivateSearchCompositeController.setLayoutData(LayoutConstants.FILL_HORIZONTALLY());
101
102 //---tree viewer---
103 viewer = new TreeViewer(new Tree(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION));
104 viewer.getTree().setLayoutData(LayoutConstants.FILL());
105 contentProvider = new DerivateContentProvider();
106 viewer.setContentProvider(contentProvider);
107 labelProvider = new DerivateLabelProvider();
108 labelProvider.setConversation(conversation);
109 viewer.setLabelProvider(labelProvider);
110 viewer.setAutoExpandLevel(AbstractTreeViewer.ALL_LEVELS);
111 // Propagate selection from viewer
112 getSite().setSelectionProvider(viewer);
113 //listen to selection changes
114 viewer.addSelectionChangedListener(this);
115
116 //create context menu
117 MenuManager menuManager = new MenuManager();
118 getSite().registerContextMenu(menuManager, viewer);
119 Control control = viewer.getControl();
120 Menu menu = menuManager.createContextMenu(control);
121 control.setMenu(menu);
122
123 generateMultiLinkSingleReads();
124 labelProvider.setMultiLinkSingleReads(multiLinkSingleReads);
125 IEditorInput editorInput = getEditorInput();
126 viewer.setInput(((DerivateViewEditorInput) editorInput).getRootEntities());
127 //set selection to selected derivate if only one was selected
128 if(editorInput instanceof DerivateViewEditorInput){
129 Set<SpecimenOrObservationBase<?>> derivateEntities = ((DerivateViewEditorInput) editorInput).getDerivateEntities();
130 if(derivateEntities.size()==1){
131 SpecimenOrObservationBase<?> specimen = derivateEntities.iterator().next();
132 if(specimen != null){
133 viewer.setSelection(new StructuredSelection(new TreeNode(specimen)));
134 }
135 }
136 }
137
138 //add drag'n'drop support
139 Transfer[] transfers = new Transfer[] {LocalSelectionTransfer.getTransfer(),};
140 viewer.addDragSupport(dndOperations, transfers, new DerivateDragListener(this));
141 viewer.addDropSupport(dndOperations, transfers, new DerivateDropListener(this));
142 }
143
144 @Override
145 public void doSave(IProgressMonitor monitor) {
146 String taskName = Messages.DerivateView_SAVING_HIERARCHY;
147 if(getEditorInput() instanceof DerivateViewEditorInput){
148 DerivateViewEditorInput derivateViewEditorInput = (DerivateViewEditorInput) getEditorInput();
149 taskName += " "+derivateViewEditorInput.getName(); //$NON-NLS-1$
150 }
151 monitor.beginTask(taskName, 3);
152 if (!conversation.isBound()) {
153 conversation.bind();
154 }
155 monitor.worked(1);
156
157 // commit the conversation and start a new transaction immediately
158 conversation.commit(true);
159 ((DerivateViewEditorInput) getEditorInput()).merge();
160 monitor.worked(1);
161
162 this.setDirty(false);
163 monitor.worked(1);
164 monitor.done();
165 firePropertyChange(PROP_DIRTY);
166 refreshTree();
167 }
168
169 @Override
170 public void doSaveAs() {
171 }
172
173 @Override
174 public String getTitleToolTip() {
175 if(getEditorInput() instanceof DerivateViewEditorInput){
176 DerivateViewEditorInput derivateViewEditorInput = (DerivateViewEditorInput) getEditorInput();
177 return derivateViewEditorInput.getName();
178 }
179 return Messages.DerivateView_DERIVATIVE_EDITOR;
180 }
181
182 @Override
183 public void init(IEditorSite site, IEditorInput input) throws PartInitException {
184 setSite(site);
185 setInput(input);
186 if(input instanceof DerivateViewEditorInput){
187 DerivateViewEditorInput derivateViewEditorInput = (DerivateViewEditorInput) input;
188 conversation = derivateViewEditorInput.getConversationHolder();
189 setPartName(derivateViewEditorInput.getName());
190 }
191 }
192
193 @Override
194 public boolean isDirty() {
195 return isDirty;
196 }
197
198 /**
199 * @param isDirty the isDirty to set
200 */
201 public void setDirty(boolean isDirty) {
202 this.isDirty = isDirty;
203 }
204
205 @Override
206 public boolean isSaveAsAllowed() {
207 return false;
208 }
209
210 @Override
211 public void setFocus() {
212 viewer.getControl().setFocus();
213 //make sure to bind again if maybe in another view the conversation was unbound
214 if(!conversation.isBound()){
215 conversation.bind();
216 }
217 ((DerivateViewEditorInput) getEditorInput()).bind();
218 }
219
220 @Override
221 public void update(CdmDataChangeMap changeEvents) {
222 }
223
224 @Override
225 public ConversationHolder getConversationHolder() {
226 return conversation;
227 }
228
229 /**
230 * @return the viewer
231 */
232 public TreeViewer getViewer() {
233 return viewer;
234 }
235
236 @Override
237 public void changed(Object element) {
238 setDirty(true);
239 firePropertyChange(IEditorPart.PROP_DIRTY);
240 viewer.refresh();
241 }
242
243 @Override
244 public void forceDirty() {
245 changed(null);
246 }
247
248 /**
249 * Refreshes the derivate hierarchy tree and expands the tree
250 * to show and select the given object.
251 *
252 * @param expandTo the object to which the tree should be expanded
253 */
254 public void refreshTree(Object expandTo){
255 refreshTree();
256 TreeSelection selection = (TreeSelection) viewer.getSelection();
257 viewer.expandToLevel(selection.getFirstElement(), 1);
258 viewer.setSelection(new StructuredSelection(new TreeNode(expandTo)));
259 }
260
261 /**
262 * Refreshes the derivate hierarchy tree
263 */
264 public void refreshTree(){
265 generateMultiLinkSingleReads();
266 labelProvider.setMultiLinkSingleReads(multiLinkSingleReads);
267 viewer.refresh();
268 }
269
270 //FIXME:Remoting hack to make this work for remoting
271 //This should actually be resolved using remoting post operations
272 public void remove(Object obj) {
273 Set<SpecimenOrObservationBase<?>> rootEntities = ((DerivateViewEditorInput) getEditorInput()).getRootEntities();
274 rootEntities.remove(obj);
275 viewer.setInput(rootEntities);
276 }
277
278 private void generateMultiLinkSingleReads() {
279 Set<SingleRead> multiLinkSingleReads = new HashSet<SingleRead>();
280 for(Entry<SingleRead, Collection<Sequence>> entry:CdmStore.getService(ISequenceService.class).getSingleReadSequencesMap().entrySet()){
281 if(entry.getValue().size()>1){
282 multiLinkSingleReads.add(entry.getKey());
283 }
284 }
285 this.multiLinkSingleReads = multiLinkSingleReads;
286 }
287
288 /**
289 * @return a set of {@link SingleRead}s that have multiple parents
290 */
291 public Set<SingleRead> getMultiLinkSingleReads() {
292 return this.multiLinkSingleReads;
293 }
294
295 @Override
296 public void selectionChanged(SelectionChangedEvent event) {
297 this.selection = event.getSelection();
298 }
299
300 public ISelection getSelection() {
301 return selection;
302 }
303
304 public DerivateLabelProvider getLabelProvider() {
305 return labelProvider;
306 }
307
308 @Override
309 public boolean postOperation(CdmBase objectAffectedByOperation) {
310 refreshTree();
311 if(objectAffectedByOperation!=null){
312 changed(objectAffectedByOperation);
313 }
314 return true;
315 }
316
317 @Override
318 public boolean onComplete() {
319 return true;
320 }
321
322 @Override
323 public void dispose() {
324 ((DerivateViewEditorInput) getEditorInput()).dispose();
325 super.dispose();
326 }
327
328
329 @Override
330 public boolean canAttachMedia() {
331 return true;
332 }
333 }