package eu.etaxonomy.taxeditor.bulkeditor.e4;
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.HashMap;
+import java.io.FileOutputStream;
+import java.io.IOException;
import java.util.List;
-import java.util.Map;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.annotations.Optional;
import org.eclipse.e4.core.services.events.IEventBroker;
import org.eclipse.e4.ui.di.Focus;
import org.eclipse.e4.ui.di.Persist;
+import org.eclipse.e4.ui.di.UIEventTopic;
import org.eclipse.e4.ui.model.application.ui.MDirtyable;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
-import org.eclipse.e4.ui.services.EMenuService;
-import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
-import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.jface.layout.GridDataFactory;
-import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
-import org.eclipse.nebula.widgets.nattable.NatTable;
-import org.eclipse.nebula.widgets.nattable.command.VisualRefreshCommand;
-import org.eclipse.nebula.widgets.nattable.command.VisualRefreshCommandHandler;
-import org.eclipse.nebula.widgets.nattable.config.AbstractUiBindingConfiguration;
-import org.eclipse.nebula.widgets.nattable.config.ConfigRegistry;
-import org.eclipse.nebula.widgets.nattable.config.DefaultNatTableStyleConfiguration;
-import org.eclipse.nebula.widgets.nattable.data.IRowIdAccessor;
-import org.eclipse.nebula.widgets.nattable.data.ListDataProvider;
-import org.eclipse.nebula.widgets.nattable.extension.glazedlists.GlazedListsEventLayer;
-import org.eclipse.nebula.widgets.nattable.extension.glazedlists.GlazedListsSortModel;
-import org.eclipse.nebula.widgets.nattable.grid.GridRegion;
-import org.eclipse.nebula.widgets.nattable.grid.data.DefaultColumnHeaderDataProvider;
-import org.eclipse.nebula.widgets.nattable.grid.data.DefaultCornerDataProvider;
-import org.eclipse.nebula.widgets.nattable.grid.data.DefaultRowHeaderDataProvider;
-import org.eclipse.nebula.widgets.nattable.grid.layer.ColumnHeaderLayer;
-import org.eclipse.nebula.widgets.nattable.grid.layer.CornerLayer;
-import org.eclipse.nebula.widgets.nattable.grid.layer.GridLayer;
-import org.eclipse.nebula.widgets.nattable.grid.layer.RowHeaderLayer;
-import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
-import org.eclipse.nebula.widgets.nattable.layer.stack.DefaultBodyLayerStack;
-import org.eclipse.nebula.widgets.nattable.selection.RowSelectionModel;
-import org.eclipse.nebula.widgets.nattable.selection.RowSelectionProvider;
-import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
-import org.eclipse.nebula.widgets.nattable.sort.SortHeaderLayer;
-import org.eclipse.nebula.widgets.nattable.sort.config.SingleClickSortConfiguration;
-import org.eclipse.nebula.widgets.nattable.style.theme.ModernNatTableThemeConfiguration;
-import org.eclipse.nebula.widgets.nattable.ui.binding.UiBindingRegistry;
-import org.eclipse.nebula.widgets.nattable.ui.matcher.MouseEventMatcher;
-import org.eclipse.nebula.widgets.nattable.ui.menu.PopupMenuAction;
-import org.eclipse.nebula.widgets.nattable.ui.menu.PopupMenuBuilder;
import org.eclipse.swt.SWT;
-import org.eclipse.swt.dnd.Clipboard;
-import org.eclipse.swt.dnd.TextTransfer;
-import org.eclipse.swt.dnd.Transfer;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Menu;
-import ca.odell.glazedlists.SortedList;
import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
import eu.etaxonomy.cdm.api.facade.DerivedUnitFacade;
import eu.etaxonomy.cdm.model.common.CdmBase;
-import eu.etaxonomy.cdm.model.description.SpecimenDescription;
+import eu.etaxonomy.cdm.model.description.DescriptionBase;
+import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
+import eu.etaxonomy.cdm.model.description.TaxonDescription;
+import eu.etaxonomy.cdm.model.description.TaxonNameDescription;
+import eu.etaxonomy.cdm.model.name.TaxonName;
import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;
import eu.etaxonomy.cdm.model.occurrence.FieldUnit;
+import eu.etaxonomy.cdm.model.permission.Group;
+import eu.etaxonomy.cdm.model.permission.User;
import eu.etaxonomy.cdm.model.taxon.Taxon;
+import eu.etaxonomy.cdm.model.taxon.TaxonNode;
import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
import eu.etaxonomy.taxeditor.bulkeditor.BulkEditorQuery;
import eu.etaxonomy.taxeditor.bulkeditor.input.AbstractBulkEditorInput;
-import eu.etaxonomy.taxeditor.bulkeditor.input.sortprovider.TitleCacheComparator;
+import eu.etaxonomy.taxeditor.bulkeditor.input.GroupEditorInput;
+import eu.etaxonomy.taxeditor.bulkeditor.input.TaxonEditorInput;
import eu.etaxonomy.taxeditor.editor.ITaxonEditor;
import eu.etaxonomy.taxeditor.event.WorkbenchEventConstants;
-import eu.etaxonomy.taxeditor.l10n.Messages;
import eu.etaxonomy.taxeditor.model.IDerivedUnitFacadePart;
import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
import eu.etaxonomy.taxeditor.model.IPartContentHasFactualData;
import eu.etaxonomy.taxeditor.model.IPartContentHasMedia;
import eu.etaxonomy.taxeditor.model.IPartContentHasSupplementalData;
+import eu.etaxonomy.taxeditor.operation.AbstractPostOperation;
import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
import eu.etaxonomy.taxeditor.workbench.part.IE4SavablePart;
IDirtyMarkable, IDerivedUnitFacadePart, IPartContentHasFactualData,
IPartContentHasSupplementalData, IPartContentHasMedia, IE4SavablePart, ITaxonEditor {
- public static final String TYPE_PROPERTY = "Type";
-
@Inject
private MDirtyable dirty;
private AbstractBulkEditorInput input;
- private Composite topComposite;
-
private ConversationHolder conversation;
- @Inject
- private ESelectionService selService;
-
@Inject
private IEventBroker eventBroker;
- private ISelectionChangedListener selectionChangedListener;
+ @Inject
+ IEclipseContext context;
@Inject
private MPart thisPart;
private BulkEditorQuery lastQuery = null;
- private Composite bottomComposite;
-
- @Inject
- private EMenuService menuService;
-
- private NatTable natTable;
-
- private DefaultBodyLayerStack bodyLayer;
-
- private ListDataProvider<CdmBase> bodyDataProvider;
+ private BulkEditorE4Composite bulkEditorComposite;
@Inject
public BulkEditorE4() {
public void init(AbstractBulkEditorInput<?> input){
this.input = input;
this.conversation = input.getConversation();
-
- new BulkEditorSearchE4(this, topComposite, SWT.NONE);
- //layout needed because the search bar is added after @PostConstuct method
- topComposite.getParent().layout();
-
thisPart.setLabel(input.getEditorName());
- if(input.getEntityUuid()!=null){
- performSearch(new BulkEditorQuery(input.getEntityUuid().toString()));
- }
-
- createTable();
-
- configureTable();
-
- styleTable();
-
- GridDataFactory.fillDefaults().grab(true, true).applyTo(natTable);
-
- //propagate selection
- selectionChangedListener = (event -> selService.setSelection(getSelection()));
- RowSelectionProvider<CdmBase> selectionProvider = new RowSelectionProvider<CdmBase>(bodyLayer.getSelectionLayer(), bodyDataProvider, true);
- selectionProvider.addSelectionChangedListener(selectionChangedListener);
- }
-
- private void createTable(){
- ConfigRegistry configRegistry = new ConfigRegistry();
- //property map
- Map<String, String> propertyToLabels = new HashMap<>();
- propertyToLabels.put(getEditorInput().getName(), getEditorInput().getName());
- propertyToLabels.put(TYPE_PROPERTY, TYPE_PROPERTY);
- String[] propertyNames = new String[] { input.getName(), TYPE_PROPERTY };
- //sorted list
- SortedList<CdmBase> sortedList = new SortedList<>(input.getModel(), new TitleCacheComparator());
- //data provider
- BulkEditorPropertyAccessor columnPropertyAccessor = new BulkEditorPropertyAccessor(input);
- bodyDataProvider = new ListDataProvider<CdmBase>(sortedList,
- columnPropertyAccessor);
- DefaultColumnHeaderDataProvider colHeaderDataProvider = new DefaultColumnHeaderDataProvider(
- propertyNames, propertyToLabels);
- DefaultRowHeaderDataProvider rowHeaderDataProvider = new DefaultRowHeaderDataProvider(
- bodyDataProvider);
- //body
- DataLayer dataLayer = new DataLayer(bodyDataProvider);
- dataLayer.registerCommandHandler(new VisualRefreshCommandHandler());
- GlazedListsEventLayer<CdmBase> eventLayer = new GlazedListsEventLayer<>(dataLayer, input.getModel());
- bodyLayer = new DefaultBodyLayerStack(eventLayer);
- //column
- DataLayer columnHeaderDataLayer = new DataLayer(colHeaderDataProvider);
- ColumnHeaderLayer columnHeaderLayer = new ColumnHeaderLayer(
- columnHeaderDataLayer,
- bodyLayer, bodyLayer.getSelectionLayer());
- // add the SortHeaderLayer to the column header layer stack
- // as we use GlazedLists, we use the GlazedListsSortModel which
- // delegates the sorting to the SortedList
- final SortHeaderLayer<SpecimenDescription> sortHeaderLayer = new SortHeaderLayer<>(
- columnHeaderLayer,
- new GlazedListsSortModel<>(
- sortedList,
- columnPropertyAccessor,
- configRegistry,
- columnHeaderDataLayer));
- //row
- RowHeaderLayer rowHeaderLayer = new RowHeaderLayer(new DataLayer(rowHeaderDataProvider, 50, 20),
- bodyLayer, bodyLayer.getSelectionLayer());
- //corner
- DefaultCornerDataProvider cornerDataProvider = new DefaultCornerDataProvider(
- colHeaderDataProvider, rowHeaderDataProvider);
- CornerLayer cornerLayer = new CornerLayer(new DataLayer(
- cornerDataProvider), rowHeaderLayer, sortHeaderLayer);
- //grid
- GridLayer gridLayer = new GridLayer(bodyLayer, sortHeaderLayer,
- rowHeaderLayer, cornerLayer);
-
- dataLayer.setColumnPercentageSizing(true);
-
- natTable = new NatTable(bottomComposite, gridLayer, false);
- natTable.setConfigRegistry(configRegistry);
-
- //full row selection
- bodyLayer.getSelectionLayer().setSelectionModel(new RowSelectionModel<CdmBase>(bodyLayer.getSelectionLayer(), bodyDataProvider, new IRowIdAccessor<CdmBase>() {
- @Override
- public Serializable getRowId(CdmBase rowObject) {
- return input.getModel().indexOf(rowObject);
- }
- }));
- }
-
- private void configureTable(){
- //+++CONTEXT MENU+++
- menuService.registerContextMenu(natTable, "eu.etaxonomy.taxeditor.bulkeditor.popupmenu.bulkeditor"); //$NON-NLS-1$
- // get the menu registered by EMenuService
- final Menu e4Menu = natTable.getMenu();
- // remove the menu reference from NatTable instance
- natTable.setMenu(null);
- natTable.addConfiguration(
- new AbstractUiBindingConfiguration() {
- @Override
- public void configureUiBindings(
- UiBindingRegistry uiBindingRegistry) {
- // add e4 menu to NatTable
- new PopupMenuBuilder(natTable, e4Menu)
- .build();
-
- // register the UI binding for header, corner and body region
- uiBindingRegistry.registerMouseDownBinding(
- new MouseEventMatcher(
- SWT.NONE,
- GridRegion.BODY,
- MouseEventMatcher.RIGHT_BUTTON),
- new PopupMenuAction(e4Menu));
- uiBindingRegistry.registerMouseDownBinding(
- new MouseEventMatcher(
- SWT.NONE,
- GridRegion.COLUMN_HEADER,
- MouseEventMatcher.RIGHT_BUTTON),
- new PopupMenuAction(e4Menu));
- uiBindingRegistry.registerMouseDownBinding(
- new MouseEventMatcher(
- SWT.NONE,
- GridRegion.CORNER,
- MouseEventMatcher.RIGHT_BUTTON),
- new PopupMenuAction(e4Menu));
- }
- });
-
- //enable sorting
- natTable.addConfiguration(new SingleClickSortConfiguration());
- //add default configuration because autoconfigure is set to false in constructor
- natTable.addConfiguration(new DefaultNatTableStyleConfiguration());
- natTable.configure();
- }
-
- private void styleTable(){
- natTable.setTheme(new ModernNatTableThemeConfiguration());
+ bulkEditorComposite.init(input);
}
/** {@inheritDoc} */
@PostConstruct
- public void createPartControl(Composite parent) {
- parent.setLayout(new GridLayout());
-
- topComposite = new Composite(parent, SWT.NONE);
- topComposite.setLayout(new GridLayout());
-
- GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, false);
- topComposite.setLayoutData(gridData);
-
- bottomComposite = new Composite(parent, SWT.NONE);
- bottomComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- bottomComposite.setLayout(new GridLayout());
+ public void createPartControl(Composite parent, IEclipseContext context) {
+ bulkEditorComposite = new BulkEditorE4Composite(this, parent, SWT.NONE);
+ ContextInjectionFactory.inject(bulkEditorComposite, context);
}
@Override
save(monitor, true);
}
+ public void save(IProgressMonitor monitor, boolean resetMerge) {
+ if (!input.getCdmEntitySession().isActive()){
+ input.getCdmEntitySession().bind();
+ }
+ input.saveModel(resetMerge);
+
+ IStructuredSelection selection = getSelection();
+
+ dirty.setDirty(false);
+ input.dispose();
+ input.bind();
+ conversation.commit(true);
+
+ if (lastQuery != null){
+ bulkEditorComposite.performSearch(lastQuery, selection);
+ }
+ }
+
+
@Focus
public void setFocus() {
//make sure to bind again if maybe in another view the conversation was unbound
input.dispose();
}
dirty.setDirty(false);
- }
-
- public void save(IProgressMonitor monitor, boolean resetMerge) {
- if (!input.getCdmEntitySession().isActive()){
- input.getCdmEntitySession().bind();
+ //save table settings
+ if(bulkEditorComposite.getNatTableState()!=null){
+ try (FileOutputStream tableStateStream =
+ new FileOutputStream(bulkEditorComposite.getStatePropertiesFile())) {
+ bulkEditorComposite.getNatTableState().store(tableStateStream, null);
+ } catch (IOException ioe) {
+ ioe.printStackTrace();
+ }
}
- input.saveModel(resetMerge);
+ }
- IStructuredSelection selection = getSelection();
+ @Optional
+ @Inject
+ private void updateAfterSearch(@UIEventTopic(WorkbenchEventConstants.BULK_EDITOR_SEARCH_FINISHED)IStructuredSelection selection){
- dirty.setDirty(false);
- input.dispose();
- input.bind();
- conversation.commit(true);
- if (lastQuery != null){
- performSearch(lastQuery);
+ if(selection!=null){
setSelection(selection);
}
- }
-
- /** {@inheritDoc} */
- public void performSearch(BulkEditorQuery query) {
- if (query != null) {
- // TODO check if dirty, prompt save
- if (isDirty()) {
- String[] labels = {Messages.BulkEditorE4_SAVE_AND_SEARCH, Messages.BulkEditorE4_DONT_SAVE,Messages.BulkEditorE4_CANCEL};
- MessageDialog dialog =new MessageDialog(topComposite.getShell(), Messages.BulkEditorE4_SAVE_CHANGES_TITLE, null, Messages.BulkEditorE4_SAVE_CHANGES_MESSAGE, MessageDialog.QUESTION,labels, 0);
- int result = dialog.open();
- if (result == 0) {
- save(new NullProgressMonitor());
- } else if (result == 2){
- return;
- }
- }
- dirty.setDirty(false);
- input.performSearch(query);
- lastQuery = query;
- }
}
-
public void refresh(){
- natTable.doCommand(new VisualRefreshCommand());
+ bulkEditorComposite.refresh();
}
public IStructuredSelection getSelection(){
- List<CdmBase> selection = new ArrayList<>();
- int[] fullySelectedRowPositions = bodyLayer.getSelectionLayer().getFullySelectedRowPositions();
- for (int i : fullySelectedRowPositions) {
- Object rowObject = bodyDataProvider.getRowObject(i);
- if(rowObject instanceof CdmBase){
- selection.add((CdmBase) rowObject);
- }
- }
- return new StructuredSelection(selection);
+ return bulkEditorComposite.getSelection();
}
public void setSelection(IStructuredSelection selection){
- Object[] objects = selection.toArray();
- for (Object object : objects) {
- if(object instanceof CdmBase){
- selectionLayer.selectRow(0, bodyDataProvider.indexOfRowObject((CdmBase) object), false, false);
- }
- }
+ bulkEditorComposite.setSelection(selection);
+ }
+
+ public void setDirty(boolean isDirty){
+ dirty.setDirty(isDirty);
}
public void setDirty(){
- dirty.setDirty(true);
+ setDirty(true);
}
+ @Override
public boolean isDirty() {
return dirty.isDirty();
}
}
public void copyDataToClipboard() {
- String textData = "";
- IStructuredSelection selection = getSelection();
- Object[] objects = selection.toArray();
- for (Object object : objects) {
- if(object instanceof CdmBase){
- textData += getEditorInput().getText((CdmBase)object);
- }
- }
- final TextTransfer textTransfer = TextTransfer.getInstance();
- final Clipboard clipboard = new Clipboard(Display.getDefault());
- try {
- clipboard.setContents(new Object[] { textData.toString() },
- new Transfer[] { textTransfer });
- } finally {
- clipboard.dispose();
- }
+ bulkEditorComposite.copyDataToClipboard();
}
@Override
}
}
else if (element instanceof CdmBase) {
- getEditorInput().addSaveCandidate((CdmBase)element);
- input.replaceInModel((CdmBase) element);
+ if (element instanceof DescriptionBase){
+ if (element instanceof TaxonNameDescription){
+ TaxonName changedName = ((TaxonNameDescription)element).getTaxonName();
+ getEditorInput().addSaveCandidate(changedName);
+ input.replaceInModel(changedName);
+ }else if (element instanceof TaxonDescription){
+ Taxon changedTaxon = ((TaxonDescription)element).getTaxon();
+ getEditorInput().addSaveCandidate(changedTaxon);
+ input.replaceInModel(changedTaxon);
+ }
+ }else if (element instanceof DescriptionElementBase){
+ if (((DescriptionElementBase)element).getInDescription() instanceof TaxonNameDescription){
+ TaxonName changedName = ((TaxonNameDescription)((DescriptionElementBase)element).getInDescription()).getTaxonName();
+ getEditorInput().addSaveCandidate(changedName);
+ input.replaceInModel(changedName);
+ }else if (((DescriptionElementBase)element).getInDescription() instanceof TaxonDescription){
+ Taxon changedTaxon = ((TaxonDescription)((DescriptionElementBase)element).getInDescription()).getTaxon();
+ getEditorInput().addSaveCandidate(changedTaxon);
+ input.replaceInModel(changedTaxon);
+ }
+ }else if(element instanceof Group){
+ Group oldGroup = ((GroupEditorInput)input).getEntityFromModel((Group)element);
+ ((GroupEditorInput)input).getSaveUserCandidates().addAll(oldGroup.getMembers());
+ getEditorInput().addSaveCandidate((Group)element);
+ input.replaceInModel((CdmBase) element);
+ }else{
+ getEditorInput().addSaveCandidate((CdmBase)element);
+ input.replaceInModel((CdmBase) element);
+ }
}
dirty.setDirty(true);
+ setSelection(new StructuredSelection(element));
}
@Override
}
@Override
- public boolean postOperation(CdmBase objectAffectedByOperation) {
+ public boolean postOperation(Object objectAffectedByOperation) {
return false;
}
return null;
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void update() {
+ input.performSearch(lastQuery, getSelection());
+ }
+
+ @Override
+ public void addOperation(AbstractPostOperation operation) {
+ // operations not yet used for bulk editor
+ }
+
+ @Inject
+ @Optional
+ private void updateView(@UIEventTopic(WorkbenchEventConstants.REFRESH_NAME_EDITOR) List<CdmBase> cdmBases) {
+ if (getEditorInput() instanceof TaxonEditorInput){
+ for (CdmBase cdmBase: cdmBases){
+ if (getEditorInput().getModel().contains(cdmBase)){
+ input.performSearch(lastQuery, getSelection());
+ break;
+ }
+ }
+ }
+ }
+
+ @Inject
+ @Optional
+ private void updatefromDelete(@UIEventTopic(WorkbenchEventConstants.REMOVE_USER) User user) {
+ if (input instanceof GroupEditorInput){
+ ((GroupEditorInput)input).getSaveUserCandidates().add(user);
+ }
+ }
+
+ @Override
+ public TaxonNode getTaxonNode() {
+ return null;
+ }
+
}