import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.ui.IEditorInput;
import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
import eu.etaxonomy.taxeditor.editor.EditorUtil;
import eu.etaxonomy.taxeditor.editor.Messages;
+import eu.etaxonomy.taxeditor.editor.MultiPageTaxonEditor;
import eu.etaxonomy.taxeditor.editor.view.derivate.searchFilter.DerivateSearchCompositeController;
import eu.etaxonomy.taxeditor.model.IContextListener;
import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
import eu.etaxonomy.taxeditor.model.IPartContentHasFactualData;
import eu.etaxonomy.taxeditor.model.IPartContentHasMedia;
import eu.etaxonomy.taxeditor.model.IPartContentHasSupplementalData;
+import eu.etaxonomy.taxeditor.model.MessagingUtils;
import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
import eu.etaxonomy.taxeditor.session.ICdmEntitySession;
import eu.etaxonomy.taxeditor.session.ICdmEntitySessionEnabled;
"derivationEvents.derivatives.sources"
});
+ private static final int WARN_THRESHOLD = 200;
+
+ private DelaySelection delaySelection = null;
+ /**
+ * This is the monitor for the DelaySelection runnable.
+ * If it is <code>true</code> then it is currently delaying a selection.
+ */
+ private boolean isInDelay;
+
+
+ /**
+ * This class invokes internal_selectionChanged() in a separate thread.
+ * This allows an asynchronous and/or delayed handling of selection changes
+ */
+ private class DelaySelection implements Runnable{
+ private IWorkbenchPart part;
+ private ISelection selection;
+
+ public DelaySelection(IWorkbenchPart part, ISelection selection) {
+ super();
+ this.part = part;
+ this.selection = selection;
+ }
+
+ @Override
+ public void run() {
+ try{
+ selectionChanged_internal(part, selection);
+ }
+ finally{
+ isInDelay = false;
+ }
+ }
+
+ public synchronized void setSelection(ISelection selection) {
+ this.selection = selection;
+ }
+
+ public synchronized void setPart(IWorkbenchPart part) {
+ this.part = part;
+ }
+
+ }
+
private ConversationHolder conversation;
private TreeViewer viewer;
//create context menu
MenuManager menuManager = new MenuManager();
+ menuManager.setRemoveAllWhenShown(true);
getSite().registerContextMenu(menuManager, viewer);
Control control = viewer.getControl();
Menu menu = menuManager.createContextMenu(control);
control.setMenu(menu);
//init tree
- updateRootEntities();
+ Collection<UUID> derivativeUuids = ((DerivateViewEditorInput)getEditorInput()).getDerivativeUuids();
+ checkWarnThreshold(derivativeUuids);
+ updateRootEntities(derivativeUuids);
+ //set taxon filter
+ derivateSearchCompositeController.setTaxonFilter(((DerivateViewEditorInput) getEditorInput()).getTaxonUuid());
+ //reset status bar
+ getEditorSite().getActionBars().getStatusLineManager().setMessage("");
//add drag'n'drop support
Transfer[] transfers = new Transfer[] {LocalSelectionTransfer.getTransfer(),};
}
public void updateRootEntities() {
- updateRootEntities(null);
+ updateRootEntities((Collection)null);
}
public void updateRootEntities(Collection<UUID> derivativeUuids) {
conversation.bind();
}
/*
- * If the active session is not the session of the Derivate Editor then we will
- * save it, bind temporarily to our session and rebind to the original session.
- * This happens e.g. if a selection change happens in the taxon editor and
- * "Link with editor" is enabled. The selection change event and thus the
- * loading in updateRootEntities() happens in the session of the taxon
- * editor.
+ * If the active session is not the session of the Derivative Editor
+ * then we will save the active session for later, bind temporarily
+ * to our session and rebind to the original session when we are
+ * done. This happens e.g. if a selection change happens in the
+ * taxon editor and "Link with editor" is enabled. The selection
+ * change event and thus the loading in updateRootEntities() happens
+ * in the session of the taxon editor.
*/
ICdmEntitySession previousCdmEntitySession = CdmStore.getCurrentSessionManager().getActiveSession();
if(cdmEntitySession != null) {
cdmEntitySession.bind();
}
+ List<SpecimenOrObservationBase> derivates = null;
if(derivativeUuids!=null){
this.derivateToRootEntityMap = new HashMap<SpecimenOrObservationBase<?>, SpecimenOrObservationBase<?>>();
this.rootElements = new HashSet<SpecimenOrObservationBase<?>>();
- for (UUID uuid : derivativeUuids) {
- SpecimenOrObservationBase<?> derivate = CdmStore.getService(IOccurrenceService.class).load(uuid, SPECIMEN_INIT_STRATEGY);
+ derivates = CdmStore.getService(IOccurrenceService.class).load(new ArrayList(derivativeUuids), SPECIMEN_INIT_STRATEGY);
+ }
+ updateRootEntities(derivates);
+ previousCdmEntitySession.bind();
+ }
+ }
+
+
+ public void updateRootEntities(List<SpecimenOrObservationBase> derivates) {
+ if(derivates!=null){
+ this.derivateToRootEntityMap = new HashMap<SpecimenOrObservationBase<?>, SpecimenOrObservationBase<?>>();
+ this.rootElements = new HashSet<SpecimenOrObservationBase<?>>();
+ for (SpecimenOrObservationBase derivate : derivates) {
+
if(derivate instanceof FieldUnit){
derivateToRootEntityMap.put(derivate, derivate);
}
rootElements.add(specimen);
}
}
+ labelProvider.updateLabelCache(rootElements);
viewer.setInput(rootElements);
- refreshTree(false);
- previousCdmEntitySession.bind();
- }
+
+ getEditorSite().getActionBars().getStatusLineManager().setMessage(rootElements.size() +" derivative hierarchies found");
+
+ //set selection to derivatives if the filter criteria
+ //taxon assignment or derivative type are set
+ if(derivates!=null && !derivateSearchCompositeController.isDefaultSearch()){
+ List<TreeNode> nodesToSelect = new ArrayList<TreeNode>();
+ for (SpecimenOrObservationBase specimenOrObservationBase : derivates) {
+ nodesToSelect.add(new TreeNode(specimenOrObservationBase));
+ }
+ viewer.setSelection(new StructuredSelection(nodesToSelect));
+ }
+ else{
+ viewer.setSelection(null);
+ }
+
+ }
+
+ public void updateLabelCache(){
+ labelProvider.updateLabelCache(rootElements);
}
@Override
// commit the conversation and start a new transaction immediately
conversation.commit(true);
- if(CdmStore.getCurrentSessionManager().isRemoting()) {
- CdmStore.getService(IOccurrenceService.class).merge(new ArrayList<SpecimenOrObservationBase>(rootElements), true);
- }
+ CdmStore.getService(IOccurrenceService.class).merge(new ArrayList<SpecimenOrObservationBase>(rootElements), true);
+
monitor.worked(1);
this.setDirty(false);
@Override
public void setFocus() {
- viewer.getControl().setFocus();
//make sure to bind again if maybe in another view the conversation was unbound
if(conversation!=null && !conversation.isBound()){
conversation.bind();
if(cdmEntitySession != null) {
cdmEntitySession.bind();
}
+ derivateSearchCompositeController.setFocusOnSearchField();
}
@Override
public void changed(Object element) {
setDirty(true);
firePropertyChange(IEditorPart.PROP_DIRTY);
- viewer.refresh();
+ viewer.update(new TreeNode(element), null);
}
@Override
* Refreshes the derivate hierarchy tree
*/
public void refreshTree(){
- refreshTree(true);
- }
-
- /**
- * Refreshes the derivate hierarchy tree
- * @param refreshViewer if <code>true</code> then also the
- * viewer will be refreshed. This was implemented due to
- * performance reasons. If passing <code>false</code>
- * does what was expected use <code>false</code> preferably.
- */
- public void refreshTree(boolean refreshViewer){
- //refresh typedesignations
- labelProvider.refresh();
- if(refreshViewer){
- viewer.refresh();
- }
+ if(!viewer.getTree().isDisposed()){
+ viewer.refresh();
+ }
}
//FIXME:Remoting hack to make this work for remoting
cdmEntitySession.dispose();
}
}
-
- @Override
- public void selectionChanged(IWorkbenchPart part, ISelection selection) {
+ public void selectionChanged_internal(IWorkbenchPart part, ISelection selection) {
+ if(part == this){
+ return;
+ }
if(viewer.getTree().isDisposed()){
return;
}
- if(listenToSelectionChange && selection instanceof IStructuredSelection){
- Object selectedElement = ((IStructuredSelection) selection).getFirstElement();
- if(selectedElement instanceof CdmBase){
- if(((CdmBase) selectedElement).isInstanceOf(TaxonNode.class)){
- selectedTaxon = HibernateProxyHelper.deproxy(selectedElement, TaxonNode.class).getTaxon();
- }
- else if(((CdmBase) selectedElement).isInstanceOf(Taxon.class)){
- selectedTaxon = HibernateProxyHelper.deproxy(selectedElement, Taxon.class);
+ if(listenToSelectionChange){
+ if(part instanceof MultiPageTaxonEditor){
+ selectedTaxon = ((MultiPageTaxonEditor) part).getTaxon();
+ }
+ else if(selection instanceof IStructuredSelection){
+ Object selectedElement = ((IStructuredSelection) selection).getFirstElement();
+ if(selectedElement instanceof CdmBase){
+ if(((CdmBase) selectedElement).isInstanceOf(TaxonNode.class)){
+ selectedTaxon = HibernateProxyHelper.deproxy(selectedElement, TaxonNode.class).getTaxon();
+ }
+ else if(((CdmBase) selectedElement).isInstanceOf(Taxon.class)){
+ selectedTaxon = HibernateProxyHelper.deproxy(selectedElement, Taxon.class);
+ }
}
+ }
+ if(selectedTaxon!=null){
Collection<SpecimenOrObservationBase> fieldUnits = CdmStore.getService(IOccurrenceService.class).listFieldUnitsByAssociatedTaxon(selectedTaxon, null, null);
Collection<UUID> uuids = new HashSet<UUID>();
for (SpecimenOrObservationBase specimenOrObservationBase : fieldUnits) {
uuids.add(specimenOrObservationBase.getUuid());
}
+ checkWarnThreshold(uuids);
updateRootEntities(uuids);
setPartName("Derivative Editor: " + selectedTaxon.getName());
}
}
}
+ @Override
+ public void selectionChanged(IWorkbenchPart part, ISelection selection) {
+ if(delaySelection==null){
+ delaySelection = new DelaySelection(part, selection);
+ }
+ delaySelection.setPart(part);
+ delaySelection.setSelection(selection);
+ if(!isInDelay){
+ isInDelay = true;
+ Display.getCurrent().asyncExec(delaySelection);
+ }
+ }
+
+
+ private void checkWarnThreshold(Collection<UUID> uuids) {
+ if(uuids!=null && uuids.size()>WARN_THRESHOLD){
+ MessagingUtils.warningDialog("Performance warning", this.getClass(), String.format("Specimens will not be loaded!\n"
+ + "There are %d specimens associated with the current "
+ + "selection. If you really want to show all of them in the specimen editor please "
+ + "use the taxon filter in the search bar.", uuids.size()));
+ uuids.clear();
+ }
+ }
+
public TreeViewer getViewer() {
return viewer;
}
@Override
public void contextStop(IMemento memento, IProgressMonitor monitor) {
derivateSearchCompositeController.setEnabled(false);
- viewer.getTree().setEnabled(false);
- viewer.setInput(null);
+ if(!viewer.getTree().isDisposed()) {
+ viewer.getTree().setEnabled(false);
+ viewer.setInput(null);
+ }
}
/**
@Override
public void contextStart(IMemento memento, IProgressMonitor monitor) {
derivateSearchCompositeController.setEnabled(!listenToSelectionChange);
- viewer.getTree().setEnabled(true);
+ if(!viewer.getTree().isDisposed()){
+ viewer.getTree().setEnabled(true);
+ }
refreshTree();
}