3 * Copyright (C) 2007 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
11 package eu
.etaxonomy
.taxeditor
.editor
.view
.checklist
;
13 import java
.util
.ArrayList
;
14 import java
.util
.Arrays
;
15 import java
.util
.Collections
;
16 import java
.util
.HashMap
;
17 import java
.util
.List
;
19 import java
.util
.SortedSet
;
21 import org
.apache
.log4j
.Logger
;
22 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
23 import org
.eclipse
.core
.runtime
.IStatus
;
24 import org
.eclipse
.core
.runtime
.Status
;
25 import org
.eclipse
.core
.runtime
.jobs
.Job
;
26 import org
.eclipse
.jface
.viewers
.ISelection
;
27 import org
.eclipse
.jface
.viewers
.StructuredViewer
;
28 import org
.eclipse
.jface
.viewers
.TableViewer
;
29 import org
.eclipse
.jface
.viewers
.TableViewerColumn
;
30 import org
.eclipse
.swt
.SWT
;
31 import org
.eclipse
.swt
.events
.ModifyListener
;
32 import org
.eclipse
.swt
.events
.SelectionAdapter
;
33 import org
.eclipse
.swt
.events
.SelectionEvent
;
34 import org
.eclipse
.swt
.layout
.GridData
;
35 import org
.eclipse
.swt
.layout
.GridLayout
;
36 import org
.eclipse
.swt
.widgets
.Composite
;
37 import org
.eclipse
.swt
.widgets
.Display
;
38 import org
.eclipse
.swt
.widgets
.Label
;
39 import org
.eclipse
.swt
.widgets
.Menu
;
40 import org
.eclipse
.swt
.widgets
.Table
;
41 import org
.eclipse
.swt
.widgets
.TableColumn
;
42 import org
.eclipse
.swt
.widgets
.Text
;
43 import org
.eclipse
.swt
.widgets
.ToolBar
;
44 import org
.eclipse
.swt
.widgets
.ToolItem
;
45 import org
.eclipse
.ui
.IEditorInput
;
46 import org
.eclipse
.ui
.IEditorSite
;
47 import org
.eclipse
.ui
.IMemento
;
48 import org
.eclipse
.ui
.ISelectionListener
;
49 import org
.eclipse
.ui
.ISelectionService
;
50 import org
.eclipse
.ui
.IWorkbenchPart
;
51 import org
.eclipse
.ui
.PartInitException
;
52 import org
.eclipse
.ui
.part
.EditorPart
;
53 import org
.eclipse
.ui
.progress
.IWorkbenchSiteProgressService
;
55 import eu
.etaxonomy
.cdm
.api
.conversation
.ConversationHolder
;
56 import eu
.etaxonomy
.cdm
.api
.conversation
.IConversationEnabled
;
57 import eu
.etaxonomy
.cdm
.api
.service
.ITaxonNodeService
;
58 import eu
.etaxonomy
.cdm
.hibernate
.HibernateProxyHelper
;
59 import eu
.etaxonomy
.cdm
.model
.common
.DefinedTermBase
;
60 import eu
.etaxonomy
.cdm
.model
.taxon
.Classification
;
61 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
62 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonNode
;
63 import eu
.etaxonomy
.cdm
.persistence
.hibernate
.CdmDataChangeMap
;
64 import eu
.etaxonomy
.taxeditor
.editor
.EditorUtil
;
65 import eu
.etaxonomy
.taxeditor
.editor
.SimpleSelectionProvider
;
66 import eu
.etaxonomy
.taxeditor
.editor
.view
.checklist
.edit
.DistributionEditingSupport
;
67 import eu
.etaxonomy
.taxeditor
.editor
.view
.checklist
.edit
.RankEditingSupport
;
68 import eu
.etaxonomy
.taxeditor
.editor
.view
.checklist
.filter
.ChecklistEditorFilter
;
69 import eu
.etaxonomy
.taxeditor
.editor
.view
.checklist
.listener
.ChecklistDropdownSelectionListener
;
70 import eu
.etaxonomy
.taxeditor
.editor
.view
.checklist
.listener
.ChecklistFocusListener
;
71 import eu
.etaxonomy
.taxeditor
.editor
.view
.checklist
.listener
.ChecklistModifyListener
;
72 import eu
.etaxonomy
.taxeditor
.model
.IContextListener
;
73 import eu
.etaxonomy
.taxeditor
.model
.IDirtyMarkable
;
74 import eu
.etaxonomy
.taxeditor
.model
.IPartContentHasDetails
;
75 import eu
.etaxonomy
.taxeditor
.model
.IPartContentHasFactualData
;
76 import eu
.etaxonomy
.taxeditor
.preference
.PreferencesUtil
;
77 import eu
.etaxonomy
.taxeditor
.preference
.Resources
;
78 import eu
.etaxonomy
.taxeditor
.store
.CdmStore
;
82 * ChecklistViewPart class.
89 public class ChecklistEditor
extends EditorPart
implements ISelectionListener
, IPartContentHasFactualData
,
90 IConversationEnabled
, IContextListener
, IPartContentHasDetails
, IDirtyMarkable
{
92 private static final Logger logger
= Logger
.getLogger(ChecklistEditor
.class);
94 * Key used for storing Checklist Editor View
96 private static final String CHECKLIST_EDITOR_MEMENTO_KEY
= "checklistEditor";
98 private class ChecklistJob
extends Job
{
100 private List
<TaxonNode
> taxonNodes
;
105 public ChecklistJob(String title
, List
<TaxonNode
> listTaxonNodes
) {
107 this.taxonNodes
= listTaxonNodes
;
114 * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.
118 public IStatus
run(final IProgressMonitor monitor
) {
120 logger
.debug("Begin of eclipse core runtime Job to Retrieve datasources");
121 monitor
.beginTask("Retrieving TaxonNodes", taxonNodes
.size() + 1);
123 final List
<Taxon
> taxonList
= new ArrayList
<Taxon
>();
125 for (TaxonNode taxonNode
: taxonNodes
) {
126 HibernateProxyHelper hh
= new HibernateProxyHelper();
127 Taxon taxon
= hh
.deproxy(taxonNode
.getTaxon(), Taxon
.class);
128 taxonList
.add(taxon
);
131 Display
.getDefault().asyncExec(new Runnable() {
135 viewer
.setInput(taxonList
);
144 return Status
.OK_STATUS
;
150 * <code>ID="eu.etaxonomy.taxeditor.store.datasource"{trunked}</code>
152 public static String ID
= "eu.etaxonomy.taxeditor.editor.view.checklist.ChecklistEditor";
154 private TableViewer viewer
;
156 private String partNameCache
;
158 private IWorkbenchSiteProgressService service
;
160 private ITaxonNodeService taxonNodeService
;
162 private ChecklistEditorComparator comparator
;
164 private ChecklistEditorInput checklistEditorInput
;
166 private SimpleSelectionProvider simpleSelectionProvider
;
168 private ISelectionService selectionService
;
170 private ConversationHolder conversation
;
172 private Integer countNodes
;
174 private List
<TaxonNode
> selectedTaxonNodes
;
176 private boolean dirty
;
178 private ChecklistEditorFilter filter
;
180 private Menu headerMenu
;
182 private Label statusLabel
;
184 private SortedSet
<DefinedTermBase
> terms
= null;
187 * @return the selectedTaxonNodes
189 public List
<TaxonNode
> getSelectedTaxonNodes() {
190 return selectedTaxonNodes
;
194 * @param selectedTaxonNodes
195 * the selectedTaxonNodes to set
197 public void setSelectedTaxonNodes(List
<TaxonNode
> selectedTaxonNodes
) {
198 this.selectedTaxonNodes
= selectedTaxonNodes
;
203 * Constructor for CdmDataSourceViewPart.
206 public ChecklistEditor() {
211 public void createPartControl(Composite parent
) {
212 service
= (IWorkbenchSiteProgressService
) getSite().getAdapter(IWorkbenchSiteProgressService
.class);
213 taxonNodeService
= CdmStore
.getService(ITaxonNodeService
.class);
214 selectionService
= getSite().getWorkbenchWindow().getSelectionService();
215 selectionService
.addSelectionListener(this);
216 filter
= new ChecklistEditorFilter();
217 ChecklistLabelProvider labelProvider
= new ChecklistLabelProvider();
218 terms
= (SortedSet
<DefinedTermBase
>) labelProvider
.getTermsOrderedByLabels(labelProvider
.getNamedAreas(),
219 CdmStore
.getDefaultLanguage());
220 createTopComposite(parent
);
227 private void createTopComposite(Composite parent
) {
228 GridLayout gridLayout
= new GridLayout(3, false);
229 gridLayout
.marginWidth
= 0;
230 gridLayout
.marginHeight
= 0;
231 parent
.setLayout(gridLayout
);
233 final Text searchText
= createSearchBar(parent
);
235 // if (terms != null && !terms.isEmpty()) {
236 createToolbar(parent
);
238 viewer
= new TableViewer(parent
, SWT
.MULTI
| SWT
.H_SCROLL
| SWT
.V_SCROLL
| SWT
.FULL_SELECTION
);
239 getSite().setSelectionProvider(viewer
);
241 final ModifyListener modifyListener
= new ChecklistModifyListener(viewer
, filter
, searchText
);
243 searchText
.addFocusListener(new ChecklistFocusListener(searchText
, modifyListener
));
244 searchText
.addModifyListener(modifyListener
);
247 GridData gridData
= new GridData();
248 gridData
.verticalAlignment
= GridData
.FILL
;
249 gridData
.horizontalSpan
= 3;
250 gridData
.grabExcessHorizontalSpace
= true;
251 gridData
.grabExcessVerticalSpace
= true;
252 gridData
.horizontalAlignment
= GridData
.FILL
;
253 viewer
.getControl().setLayoutData(gridData
);
255 viewer
.addFilter(filter
);
256 createColumns(viewer
);
258 viewer
.setContentProvider(new ChecklistContentProvider());
259 viewer
.setLabelProvider(new ChecklistLabelProvider());
260 comparator
= new ChecklistEditorComparator();
261 viewer
.setComparator(comparator
);
263 createStatusBar(parent
);
270 private Text
createSearchBar(Composite parent
) {
271 Label searchLabel
= new Label(parent
, SWT
.NONE
);
272 searchLabel
.setText("Search: ");
273 final Text searchText
= new Text(parent
, SWT
.BORDER
| SWT
.SEARCH
| SWT
.ICON_SEARCH
| SWT
.CANCEL
);
274 searchText
.setLayoutData(new GridData(GridData
.GRAB_HORIZONTAL
| GridData
.HORIZONTAL_ALIGN_FILL
));
275 searchText
.setForeground(EditorUtil
.getColor(Resources
.SEARCH_VIEW_FOREGROUND
));
276 searchText
.setText("type filter text");
283 private void createToolbar(Composite parent
) {
284 ToolBar toolBar
= new ToolBar(parent
, SWT
.NONE
);
285 ToolItem toolItem
= new ToolItem(toolBar
, SWT
.DROP_DOWN
| SWT
.BORDER
);
286 toolItem
.setText("Distribution Status");
287 toolItem
.setToolTipText("Show Distribution Status for selected Areas");
288 ChecklistDropdownSelectionListener dropListener
= new ChecklistDropdownSelectionListener(toolItem
, this, terms
);
289 for (DefinedTermBase
<DefinedTermBase
> term
: terms
) {
291 dropListener
.add(term
);
294 toolItem
.addSelectionListener(dropListener
);
298 private void createStatusBar(Composite composite
) {
299 GridData gridData
= new GridData();
300 gridData
.horizontalSpan
= 3;
301 gridData
.grabExcessHorizontalSpace
= true;
302 gridData
.horizontalAlignment
= GridData
.FILL
;
304 statusLabel
= new Label(composite
, SWT
.LEFT
);
305 statusLabel
.setText("Anzahl der Elemente: " + (countNodes
!= null ? countNodes
: "uknown"));
306 statusLabel
.setLayoutData(gridData
);
309 // This will create the columns for the table
310 private void createColumns(TableViewer viewer
) {
311 Table table
= viewer
.getTable();
312 List
<String
> titles
= new ArrayList
<String
>();
313 Collections
.addAll(titles
, "Taxon", "Author", "Reference", "Rank");
314 List
<Integer
> bounds
= new ArrayList
<Integer
>();
315 Collections
.addAll(bounds
, 300, 200, 200, 200);
316 Map
<Integer
, Boolean
>restoreColumnWidth
= new HashMap
<Integer
, Boolean
>();
319 for (DefinedTermBase
<DefinedTermBase
> term
: terms
) {
321 restoreColumnWidth
.put(i
, PreferencesUtil
.getPreferenceStore().getBoolean(term
.getUuid().toString()));
322 titles
.add(term
.getTitleCache());
329 for (int i
= 0; i
< titles
.size(); i
++) {
330 TableViewerColumn column
= new TableViewerColumn(viewer
, SWT
.NONE
);
331 column
.getColumn().setText(titles
.get(i
));
332 column
.getColumn().setWidth(bounds
.get(i
));
333 column
.getColumn().setResizable(true);
334 column
.getColumn().setMoveable(true);
335 column
.getColumn().addSelectionListener(getSelectionAdapter(column
.getColumn(), i
));
337 table
.setSortColumn(column
.getColumn());
340 /** uncommented it for now because no rank editing is wanted **/
341 // column.setEditingSupport(new RankEditingSupport(viewer, this));
344 //read PrefrenceStore to setWidth according to last saved state
345 if(restoreColumnWidth
.get(i
)){
346 column
.getColumn().setWidth(100);
348 column
.getColumn().setWidth(0);
350 column
.setEditingSupport(new DistributionEditingSupport(viewer
, this, i
));
353 table
.setSortDirection(SWT
.DOWN
);
354 table
.setHeaderVisible(true);
355 table
.setLinesVisible(true);
360 * pull data from database and set input for view
363 private void loadDataInput() {
364 Classification classification
= checklistEditorInput
.getClassification();
365 TaxonNode taxonNode
= checklistEditorInput
.getTaxonNode();
366 if (classification
!= null && taxonNode
== null) {
367 countNodes
= taxonNodeService
.countAllNodesForClassification(classification
);
368 statusLabel
.setText("Anzahl der Elemente: " + (countNodes
!= null ? countNodes
: "uknown"));
369 // This should not kill the view nor the editor if something goes
371 // TODO: don't load the whole taxonNode Object but rather a small
372 // and simple Solution
373 // FIXME: May be don't open classification which are greater than
375 selectedTaxonNodes
= taxonNodeService
.listAllNodesForClassification(classification
, 0, countNodes
);
376 getService().schedule(new ChecklistJob("loading Taxa", selectedTaxonNodes
), Job
.LONG
);
378 if (taxonNode
!= null) {
379 selectedTaxonNodes
= taxonNodeService
.loadChildNodesOfTaxonNode(taxonNode
, NODE_INIT_STRATEGY
, true, false);
380 getService().schedule(new ChecklistJob("loading Taxa", selectedTaxonNodes
), Job
.LONG
);
386 public void dispose() {
392 public void setFocus() {
393 viewer
.getControl().setFocus();
399 * @see org.eclipse.ui.part.WorkbenchPart#showBusy(boolean)
403 public void showBusy(boolean busy
) {
404 super.showBusy(busy
);
405 // viewer.getTable().setEnabled(!busy);
407 partNameCache
= getPartName();
408 setPartName("Loading " + countNodes
+ " Taxa...");
410 if (partNameCache
!= null) {
411 setPartName(partNameCache
);
418 * Getter for the field <code>viewer</code>.
421 * @return a {@link org.eclipse.jface.viewers.StructuredViewer} object.
423 public StructuredViewer
getViewer() {
427 public void refresh() {
433 * Getter for the field <code>service</code>.
436 * @return the service
438 public IWorkbenchSiteProgressService
getService() {
442 private SelectionAdapter
getSelectionAdapter(final TableColumn column
, final int index
) {
443 SelectionAdapter selectionAdapter
= new SelectionAdapter() {
445 public void widgetSelected(SelectionEvent e
) {
446 comparator
.setColumn(index
);
447 int dir
= viewer
.getTable().getSortDirection();
448 if (viewer
.getTable().getSortColumn() == column
) {
449 dir
= dir
== SWT
.UP ? SWT
.DOWN
: SWT
.UP
;
453 viewer
.getTable().setSortDirection(dir
);
454 viewer
.getTable().setSortColumn(column
);
458 return selectionAdapter
;
462 public void doSave(IProgressMonitor monitor
) {
464 monitor
.beginTask("Saving Editor", 1);
465 getConversationHolder().bind();
466 getConversationHolder().commit(true);
476 public void doSaveAs() {
477 // TODO Auto-generated method stub
482 public void init(IEditorSite site
, IEditorInput input
) throws PartInitException
{
485 if (input
instanceof ChecklistEditorInput
) {
486 checklistEditorInput
= (ChecklistEditorInput
) input
;
487 setPartName(getPartName() + ": " + checklistEditorInput
.getName());
488 conversation
= ((ChecklistEditorInput
) input
).getConversationHolder();
490 simpleSelectionProvider
= new SimpleSelectionProvider();
491 getSite().setSelectionProvider(simpleSelectionProvider
);
495 public boolean isSaveAsAllowed() {
496 // TODO Auto-generated method stub
503 * @see org.eclipse.ui.ISelectionListener#selectionChanged(org.eclipse.ui.
504 * IWorkbenchPart, org.eclipse.jface.viewers.ISelection)
507 public void selectionChanged(IWorkbenchPart part
, ISelection selection
) {
508 // TODO Auto-generated method stub
516 * eu.etaxonomy.cdm.persistence.hibernate.ICdmPostDataChangeObserver#update
517 * (eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap)
520 public void update(CdmDataChangeMap changeEvents
) {
528 * eu.etaxonomy.cdm.api.conversation.IConversationEnabled#getConversationHolder
532 public ConversationHolder
getConversationHolder() {
540 * eu.etaxonomy.taxeditor.model.IContextListener#contextAboutToStop(org.
541 * eclipse.ui.IMemento, org.eclipse.core.runtime.IProgressMonitor)
545 public void contextAboutToStop(IMemento memento
, IProgressMonitor monitor
) {
553 * eu.etaxonomy.taxeditor.model.IContextListener#contextStop(org.eclipse
554 * .ui.IMemento, org.eclipse.core.runtime.IProgressMonitor)
557 public void contextStop(IMemento memento
, IProgressMonitor monitor
) {
558 // TODO Auto-generated method stub
559 // IStructuredSelection sel = (IStructuredSelection) this.viewer.getSelection();
560 // if (sel.isEmpty()) {
563 // memento = memento.createChild("tree-selections");
564 // Iterator iter = sel.iterator();
565 // while (iter.hasNext()) {
566 // String nodeName = (String) iter.next();
567 // memento.createChild("selected-nodes", nodeName);
575 * eu.etaxonomy.taxeditor.model.IContextListener#contextStart(org.eclipse
576 * .ui.IMemento, org.eclipse.core.runtime.IProgressMonitor)
579 public void contextStart(IMemento memento
, IProgressMonitor monitor
) {
587 * eu.etaxonomy.taxeditor.model.IContextListener#contextRefresh(org.eclipse
588 * .core.runtime.IProgressMonitor)
591 public void contextRefresh(IProgressMonitor monitor
) {
592 // TODO Auto-generated method stub
600 * eu.etaxonomy.taxeditor.model.IContextListener#workbenchShutdown(org.eclipse
601 * .ui.IMemento, org.eclipse.core.runtime.IProgressMonitor)
604 public void workbenchShutdown(IMemento memento
, IProgressMonitor monitor
) {
605 conversation
.clear();
606 conversation
.close();
610 private static final List
<String
> NODE_INIT_STRATEGY
= Arrays
.asList(new String
[] { "descriptions",
611 "descriptions.*", "description.state", "feature", "feature.*", "childNodes", "childNodes.taxon",
612 "childNodes.taxon.name", "taxonNodes", "taxonNodes.*", "taxonNodes.taxon.*", "taxon.*",
613 "taxon.descriptions", "taxon.sec", "taxon.name.*", "taxon.synonymRelations", "terms", "name.*",
614 "name.rank.representations", "name.status.type.representations", "sources.$", "stateData.$" });
620 * eu.etaxonomy.taxeditor.model.IDirtyMarkableSelectionProvider#changed(
624 public void changed(Object element
) {
625 if (element
!= null) {
626 viewer
.update(element
, null);
628 firePropertyChange(PROP_DIRTY
);
633 * @see eu.etaxonomy.taxeditor.model.IDirtyMarkableSelectionProvider#forceDirty()
636 public void forceDirty() {
640 public void setDirty(boolean dirty
) {
642 firePropertyChange(PROP_DIRTY
);
648 * @see org.eclipse.ui.forms.editor.FormEditor#isDirty()
651 public boolean isDirty() {