public void accumulateConfigLabels(LabelStack configLabels, int columnPosition, int rowPosition) {
CdmBase rowObject = dataProvider.getRowObject(rowPosition);
if(input.getMergeCandidates().contains(rowObject)){
- configLabels.addLabel(BulkEditorE4.CANDIDATE_LABEL);
+ configLabels.addLabel(BulkEditorE4Composite.CANDIDATE_LABEL);
}
else if(input.getMergeTarget()==rowObject){
- configLabels.addLabel(BulkEditorE4.TARGET_LABEL);
+ configLabels.addLabel(BulkEditorE4Composite.TARGET_LABEL);
}
}
}
package eu.etaxonomy.taxeditor.bulkeditor.e4;
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.HashMap;
-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.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.AbstractRegistryConfiguration;
-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.config.IConfigRegistry;
-import org.eclipse.nebula.widgets.nattable.config.IEditableRule;
-import org.eclipse.nebula.widgets.nattable.data.IRowIdAccessor;
-import org.eclipse.nebula.widgets.nattable.data.ListDataProvider;
-import org.eclipse.nebula.widgets.nattable.edit.EditConfigAttributes;
-import org.eclipse.nebula.widgets.nattable.edit.action.MouseEditAction;
-import org.eclipse.nebula.widgets.nattable.edit.config.DefaultEditConfiguration;
-import org.eclipse.nebula.widgets.nattable.edit.editor.TextCellEditor;
-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.AbstractLayer;
-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.sort.SortHeaderLayer;
-import org.eclipse.nebula.widgets.nattable.sort.config.SingleClickSortConfiguration;
-import org.eclipse.nebula.widgets.nattable.style.DisplayMode;
-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.CellEditorMouseEventMatcher;
-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.occurrence.DerivedUnit;
import eu.etaxonomy.cdm.model.occurrence.FieldUnit;
import eu.etaxonomy.cdm.model.taxon.Taxon;
import eu.etaxonomy.taxeditor.bulkeditor.input.AbstractBulkEditorInput;
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;
IDirtyMarkable, IDerivedUnitFacadePart, IPartContentHasFactualData,
IPartContentHasSupplementalData, IPartContentHasMedia, IE4SavablePart, ITaxonEditor {
- public static final String TARGET_LABEL = "target";
- public static final String CANDIDATE_LABEL = "candidate";
-
- public static final String TYPE_PROPERTY = Messages.BulkEditorE4_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;
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);
-
- bottomComposite.layout();
- }
-
- 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(), input.getTitleComparator());
- //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);
-
- dataLayer.setColumnPercentageSizing(true);
- dataLayer.setColumnWidthPercentageByPosition(0, 80);
- dataLayer.setColumnWidthPercentageByPosition(1, 20);
-
- //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
- DataLayer rowHeaderDataLayer = new DataLayer(rowHeaderDataProvider);
- RowHeaderLayer rowHeaderLayer = new RowHeaderLayer(rowHeaderDataLayer,
- bodyLayer, bodyLayer.getSelectionLayer());
-
- //corner
- DefaultCornerDataProvider cornerDataProvider = new DefaultCornerDataProvider(
- colHeaderDataProvider, rowHeaderDataProvider);
- DataLayer cornerDataLayer = new DataLayer(cornerDataProvider);
- CornerLayer cornerLayer = new CornerLayer(cornerDataLayer, rowHeaderLayer, sortHeaderLayer);
- //grid
- GridLayer gridLayer = new GridLayer(bodyLayer, sortHeaderLayer,
- rowHeaderLayer, cornerLayer, false);//set autoconfigure to false to get rid of the single click editing
- 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);
- }
- }));
-
- //add label to deduplication rows
- dataLayer.setConfigLabelAccumulator(new BulkEditorConfigLabelAccumulator(bodyDataProvider, input));
-
- //add tooltip to table
- new BulkEditorTooltip(natTable);
- }
-
- private void configureTable(){
-
- //this configuration enables cell to be editable in general
- //necessary because we disabled this beforehand by setting autoconfigure=false
- //in the GridLayer constructor
- ((AbstractLayer) natTable.getLayer()).addConfiguration(new DefaultEditConfiguration());
-
- natTable.addConfiguration(new AbstractUiBindingConfiguration() {
- @Override
- public void configureUiBindings(UiBindingRegistry uiBindingRegistry) {
- uiBindingRegistry.registerFirstDoubleClickBinding(new CellEditorMouseEventMatcher(GridRegion.BODY),
- new MouseEditAction());
- }
- });
-
- //make cells editable to allow selecting the text
- natTable.addConfiguration(new AbstractRegistryConfiguration() {
- @Override
- public void configureRegistry(IConfigRegistry configRegistry) {
- //make cell editable
- configRegistry.registerConfigAttribute(
- EditConfigAttributes.CELL_EDITABLE_RULE,
- IEditableRule.ALWAYS_EDITABLE,
- DisplayMode.EDIT);
- //register editor
- TextCellEditor editor = new TextCellEditor();
- editor.setEditable(false);
- configRegistry.registerConfigAttribute(
- EditConfigAttributes.CELL_EDITOR,
- editor,
- DisplayMode.NORMAL);
- }
- });
-
- //+++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,
- null,
- MouseEventMatcher.RIGHT_BUTTON),
- new PopupMenuAction(e4Menu));
- }
- });
-
-
- //enable sorting
- natTable.addConfiguration(new SingleClickSortConfiguration());
-
- // Custom style for deduplication labels
- natTable.addConfiguration(new LabelStyleConfiguration());
-
- //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
dirty.setDirty(false);
}
- 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){
- performSearch(lastQuery, selection);
- }
- }
-
- public void performSearch(BulkEditorQuery query) {
- performSearch(query, null);
- }
-
- /** {@inheritDoc}
- * @param selection */
- public void performSearch(BulkEditorQuery query, IStructuredSelection selection) {
- 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, selection);
- lastQuery = query;
- }
- }
-
@Optional
@Inject
private void updateAfterSearch(@UIEventTopic(WorkbenchEventConstants.BULK_EDITOR_SEARCH_FINISHED)IStructuredSelection selection){
}
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) {
+ bulkEditorComposite.setSelection(selection);
+ }
- if(object instanceof CdmBase && input.getModel().contains(object)){
- bodyLayer.getSelectionLayer().selectRow(0, bodyDataProvider.indexOfRowObject((CdmBase) object), false, false);
- }
- }
+ public void setDirty(boolean isDirty){
+ dirty.setDirty(isDirty);
}
public void setDirty(){
- dirty.setDirty(true);
+ setDirty(true);
}
public boolean 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
--- /dev/null
+/**
+* Copyright (C) 2007 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+
+package eu.etaxonomy.taxeditor.bulkeditor.e4;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.inject.Inject;
+
+import org.eclipse.core.runtime.NullProgressMonitor;
+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.AbstractRegistryConfiguration;
+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.config.IConfigRegistry;
+import org.eclipse.nebula.widgets.nattable.config.IEditableRule;
+import org.eclipse.nebula.widgets.nattable.data.IRowIdAccessor;
+import org.eclipse.nebula.widgets.nattable.data.ListDataProvider;
+import org.eclipse.nebula.widgets.nattable.edit.EditConfigAttributes;
+import org.eclipse.nebula.widgets.nattable.edit.action.MouseEditAction;
+import org.eclipse.nebula.widgets.nattable.edit.config.DefaultEditConfiguration;
+import org.eclipse.nebula.widgets.nattable.edit.editor.TextCellEditor;
+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.AbstractLayer;
+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.sort.SortHeaderLayer;
+import org.eclipse.nebula.widgets.nattable.sort.config.SingleClickSortConfiguration;
+import org.eclipse.nebula.widgets.nattable.style.DisplayMode;
+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.CellEditorMouseEventMatcher;
+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.model.common.CdmBase;
+import eu.etaxonomy.cdm.model.description.SpecimenDescription;
+import eu.etaxonomy.taxeditor.bulkeditor.BulkEditorQuery;
+import eu.etaxonomy.taxeditor.bulkeditor.input.AbstractBulkEditorInput;
+import eu.etaxonomy.taxeditor.l10n.Messages;
+
+/**
+ *
+ * @author pplitzner
+ * @since Sep 8, 2017
+ *
+ */
+public class BulkEditorE4Composite extends Composite {
+
+ public static final String TYPE_PROPERTY = Messages.BulkEditorE4_TYPE;
+
+ public static final String CANDIDATE_LABEL = "candidate";
+
+ public static final String TARGET_LABEL = "target";
+
+ private Composite topComposite;
+
+ @Inject
+ private ESelectionService selService;
+
+ private ISelectionChangedListener selectionChangedListener;
+
+ private Composite bottomComposite;
+
+ @Inject
+ private EMenuService menuService;
+
+ private NatTable natTable;
+
+ private DefaultBodyLayerStack bodyLayer;
+
+ private ListDataProvider<CdmBase> bodyDataProvider;
+
+ private BulkEditorE4 bulkEditor;
+
+
+ public BulkEditorE4Composite(BulkEditorE4 bulkEditor, Composite parent, int style) {
+ super(parent, style);
+ parent.setLayout(new GridLayout());
+ this.bulkEditor = bulkEditor;
+
+ this.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());
+ }
+
+ @SuppressWarnings("unused")
+ public void init(AbstractBulkEditorInput<?> input){
+
+ new BulkEditorSearchE4(this, topComposite, SWT.NONE);
+ //layout needed because the search bar is added after @PostConstuct method
+ topComposite.getParent().layout();
+
+ 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);
+
+ bottomComposite.layout();
+ }
+
+ private void createTable(){
+ ConfigRegistry configRegistry = new ConfigRegistry();
+ //property map
+ Map<String, String> propertyToLabels = new HashMap<>();
+ propertyToLabels.put(bulkEditor.getEditorInput().getName(), bulkEditor.getEditorInput().getName());
+ propertyToLabels.put(TYPE_PROPERTY, TYPE_PROPERTY);
+ String[] propertyNames = new String[] { bulkEditor.getEditorInput().getName(), TYPE_PROPERTY };
+ //sorted list
+ SortedList<CdmBase> sortedList = new SortedList<>(bulkEditor.getEditorInput().getModel(), bulkEditor.getEditorInput().getTitleComparator());
+ //data provider
+ BulkEditorPropertyAccessor columnPropertyAccessor = new BulkEditorPropertyAccessor(bulkEditor.getEditorInput());
+ 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, bulkEditor.getEditorInput().getModel());
+ bodyLayer = new DefaultBodyLayerStack(eventLayer);
+
+ dataLayer.setColumnPercentageSizing(true);
+ dataLayer.setColumnWidthPercentageByPosition(0, 80);
+ dataLayer.setColumnWidthPercentageByPosition(1, 20);
+
+ //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
+ DataLayer rowHeaderDataLayer = new DataLayer(rowHeaderDataProvider);
+ RowHeaderLayer rowHeaderLayer = new RowHeaderLayer(rowHeaderDataLayer,
+ bodyLayer, bodyLayer.getSelectionLayer());
+
+ //corner
+ DefaultCornerDataProvider cornerDataProvider = new DefaultCornerDataProvider(
+ colHeaderDataProvider, rowHeaderDataProvider);
+ DataLayer cornerDataLayer = new DataLayer(cornerDataProvider);
+ CornerLayer cornerLayer = new CornerLayer(cornerDataLayer, rowHeaderLayer, sortHeaderLayer);
+ //grid
+ GridLayer gridLayer = new GridLayer(bodyLayer, sortHeaderLayer,
+ rowHeaderLayer, cornerLayer, false);//set autoconfigure to false to get rid of the single click editing
+ 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 bulkEditor.getEditorInput().getModel().indexOf(rowObject);
+ }
+ }));
+
+ //add label to deduplication rows
+ dataLayer.setConfigLabelAccumulator(new BulkEditorConfigLabelAccumulator(bodyDataProvider, bulkEditor.getEditorInput()));
+
+ //add tooltip to table
+ new BulkEditorTooltip(natTable);
+ }
+
+ private void configureTable(){
+
+ //this configuration enables cell to be editable in general
+ //necessary because we disabled this beforehand by setting autoconfigure=false
+ //in the GridLayer constructor
+ ((AbstractLayer) natTable.getLayer()).addConfiguration(new DefaultEditConfiguration());
+
+ natTable.addConfiguration(new AbstractUiBindingConfiguration() {
+ @Override
+ public void configureUiBindings(UiBindingRegistry uiBindingRegistry) {
+ uiBindingRegistry.registerFirstDoubleClickBinding(new CellEditorMouseEventMatcher(GridRegion.BODY),
+ new MouseEditAction());
+ }
+ });
+
+ //make cells editable to allow selecting the text
+ natTable.addConfiguration(new AbstractRegistryConfiguration() {
+ @Override
+ public void configureRegistry(IConfigRegistry configRegistry) {
+ //make cell editable
+ configRegistry.registerConfigAttribute(
+ EditConfigAttributes.CELL_EDITABLE_RULE,
+ IEditableRule.ALWAYS_EDITABLE,
+ DisplayMode.EDIT);
+ //register editor
+ TextCellEditor editor = new TextCellEditor();
+ editor.setEditable(false);
+ configRegistry.registerConfigAttribute(
+ EditConfigAttributes.CELL_EDITOR,
+ editor,
+ DisplayMode.NORMAL);
+ }
+ });
+
+ //+++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,
+ null,
+ MouseEventMatcher.RIGHT_BUTTON),
+ new PopupMenuAction(e4Menu));
+ }
+ });
+
+
+ //enable sorting
+ natTable.addConfiguration(new SingleClickSortConfiguration());
+
+ // Custom style for deduplication labels
+ natTable.addConfiguration(new LabelStyleConfiguration());
+
+ //add default configuration because autoconfigure is set to false in constructor
+ natTable.addConfiguration(new DefaultNatTableStyleConfiguration());
+ natTable.configure();
+ }
+
+ private void styleTable(){
+ natTable.setTheme(new ModernNatTableThemeConfiguration());
+ }
+
+ public void performSearch(BulkEditorQuery query) {
+ performSearch(query, null);
+ }
+
+ /** {@inheritDoc}
+ * @param selection */
+ public void performSearch(BulkEditorQuery query, IStructuredSelection selection) {
+ if (query != null) {
+ if (bulkEditor.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) {
+ bulkEditor.save(new NullProgressMonitor());
+ } else if (result == 2){
+ return;
+ }
+ }
+ bulkEditor.setDirty(false);
+ bulkEditor.getEditorInput().performSearch(query, selection);
+ bulkEditor.setLastQuery(query);
+ }
+ }
+
+ public void refresh(){
+ natTable.doCommand(new VisualRefreshCommand());
+ }
+
+ 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);
+ }
+
+ public void setSelection(IStructuredSelection selection){
+ Object[] objects = selection.toArray();
+ for (Object object : objects) {
+
+ if(object instanceof CdmBase && bulkEditor.getEditorInput().getModel().contains(object)){
+ bodyLayer.getSelectionLayer().selectRow(0, bodyDataProvider.indexOfRowObject((CdmBase) object), false, false);
+ }
+ }
+ }
+
+ public void copyDataToClipboard() {
+ String textData = "";
+ IStructuredSelection selection = getSelection();
+ Object[] objects = selection.toArray();
+ for (Object object : objects) {
+ if(object instanceof CdmBase){
+ textData += bulkEditor.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();
+ }
+ }
+
+}
+++ /dev/null
-// $Id$
-/**
-* Copyright (C) 2018 EDIT
-* European Distributed Institute of Taxonomy
-* http://www.e-taxonomy.eu
-*
-* The contents of this file are subject to the Mozilla Public License Version 1.1
-* See LICENSE.TXT at the top of this package for the full license terms.
-*/
-package eu.etaxonomy.taxeditor.bulkeditor.e4;
-
-import org.eclipse.jface.viewers.ColumnViewer;
-import org.eclipse.jface.viewers.FocusCellOwnerDrawHighlighter;
-import org.eclipse.jface.viewers.ViewerCell;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Color;
-
-/**
- * @author k.luther
- * @date 02.03.2018
- *
- */
-public class BulkEditorFocusCellOwnerDrawHighLighter extends FocusCellOwnerDrawHighlighter {
-
- /**
- * @param viewer
- */
- public BulkEditorFocusCellOwnerDrawHighLighter(ColumnViewer viewer) {
- super(viewer);
-
- }
-
-
- /**
- * The color to use when rendering the background of the selected cell when
- * the control has <b>no</b> input focus
- *
- * @param cell
- * the cell which is colored
- * @return the color or <code>null</code> to use the same used when
- * control has focus
- * @since 3.4
- */
- @Override
- protected Color getSelectedCellBackgroundColorNoFocus(ViewerCell cell) {
- return cell.getItem().getDisplay().getSystemColor(
- SWT.COLOR_LIST_SELECTION);
- }
-
- /**
- * The color to use when rendering the foreground (=text) of the selected
- * cell when the control has <b>no</b> input focus
- *
- * @param cell
- * the cell which is colored
- * @return the color or <code>null</code> to use the same used when
- * control has focus
- * @since 3.4
- */
- @Override
- protected Color getSelectedCellForegroundColorNoFocus(ViewerCell cell) {
- return cell.getItem().getDisplay().getSystemColor(
- SWT.COLOR_LIST_SELECTION_TEXT);
- }
-
-
-
-}
+++ /dev/null
-// $Id$
-/**
-* Copyright (C) 2017 EDIT
-* European Distributed Institute of Taxonomy
-* http://www.e-taxonomy.eu
-*
-* The contents of this file are subject to the Mozilla Public License Version 1.1
-* See LICENSE.TXT at the top of this package for the full license terms.
-*/
-package eu.etaxonomy.taxeditor.bulkeditor.e4;
-
-import java.net.URISyntaxException;
-import java.net.URL;
-
-import org.eclipse.core.runtime.FileLocator;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.Path;
-import org.eclipse.jface.viewers.ITableLabelProvider;
-import org.eclipse.jface.viewers.LabelProvider;
-import org.eclipse.swt.graphics.Image;
-
-import eu.etaxonomy.cdm.model.common.CdmBase;
-import eu.etaxonomy.taxeditor.bulkeditor.input.AbstractBulkEditorInput;
-import eu.etaxonomy.taxeditor.bulkeditor.internal.TaxeditorBulkeditorPlugin;
-import eu.etaxonomy.taxeditor.model.ImageResources;
-
-/**
- * @author pplitzner
- * @date 11.09.2017
- *
- */
-public class BulkEditorLabelProvider extends LabelProvider implements ITableLabelProvider{
-
- private BulkEditorE4 editor;
-
- public BulkEditorLabelProvider(BulkEditorE4 editor) {
- super();
- this.editor = editor;
- }
-
- /** {@inheritDoc} */
- @Override
- public Image getColumnImage(Object element, int columnIndex) {
- if (columnIndex == 0) {
- AbstractBulkEditorInput input = editor.getEditorInput();
-
- try {
- if(input.getMergeCandidates().contains(element)){
- IPath path = new Path("icons/merge_candidate.gif"); //$NON-NLS-1$
- URL url = FileLocator.find(TaxeditorBulkeditorPlugin.getDefault().getBundle(), path, null);
- return ImageResources.getImage(url.toURI());
- }
- else if(input.getMergeTarget()!=null && input.getMergeTarget().equals(element)){
- IPath path = new Path("icons/merge_target.gif"); //$NON-NLS-1$
- URL url = FileLocator.find(TaxeditorBulkeditorPlugin.getDefault().getBundle(), path, null);
- return ImageResources.getImage(url.toURI());
- }
- } catch (URISyntaxException e) {
- return null;
- }
- }
- return null;
- }
-
- /** {@inheritDoc} */
- @Override
- public String getColumnText(Object element, int columnIndex) {
- String text = null;
-
- if (columnIndex == 0) {
- if(element instanceof CdmBase){
- text = editor.getEditorInput().getText((CdmBase) element);
- }
- }else if (columnIndex == 1) {
- if(editor.getEditorInput().getTypeText(element)!=null){
- text = editor.getEditorInput().getTypeText(element);
- }
- }
- return text;
- }
-
-
-}
if(columnIndex==0){
return input.getName();
}else if(columnIndex==1){
- return BulkEditorE4.TYPE_PROPERTY;
+ return BulkEditorE4Composite.TYPE_PROPERTY;
}
return null;
}
if(propertyName.equals(input.getName())){
return 0;
}
- else if(propertyName.equals(BulkEditorE4.TYPE_PROPERTY)){
+ else if(propertyName.equals(BulkEditorE4Composite.TYPE_PROPERTY)){
return 1;
}
return 0;
private static final String DEFAULT_TEXT = String.format(Messages.BulkEditorSearchE4_WILDCARD, SearchManager.WILDCARD);
- private final BulkEditorE4 editor;
+ private final BulkEditorE4Composite editor;
private Text text;
public Object ORDER_BY = new Object();
- public BulkEditorSearchE4(BulkEditorE4 editor, Composite parent, int style) {
+ public BulkEditorSearchE4(BulkEditorE4Composite editor, Composite parent, int style) {
this.editor = editor;
createControl(parent, style);
int row = this.natTable.getRowPositionByY(event.y);
LabelStack configLabels = natTable.getConfigLabelsByPosition(col, row);
- if(configLabels.hasLabel(BulkEditorE4.TARGET_LABEL)){
+ if(configLabels.hasLabel(BulkEditorE4Composite.TARGET_LABEL)){
return Messages.BulkEditorTooltip_TARGET;
}
- else if(configLabels.hasLabel(BulkEditorE4.CANDIDATE_LABEL)){
+ else if(configLabels.hasLabel(BulkEditorE4Composite.CANDIDATE_LABEL)){
return Messages.BulkEditorTooltip_CANDIDATE;
}
return ""; //$NON-NLS-1$
int row = this.natTable.getRowPositionByY(event.y);
LabelStack configLabels = natTable.getConfigLabelsByPosition(col, row);
- if(configLabels.hasLabel(BulkEditorE4.CANDIDATE_LABEL)
- || configLabels.hasLabel(BulkEditorE4.TARGET_LABEL)){
+ if(configLabels.hasLabel(BulkEditorE4Composite.CANDIDATE_LABEL)
+ || configLabels.hasLabel(BulkEditorE4Composite.TARGET_LABEL)){
return true;
}
return false;
GUIHelper.COLOR_YELLOW);
configRegistry.registerConfigAttribute(
CellConfigAttributes.CELL_STYLE, cellStyle,
- DisplayMode.NORMAL, BulkEditorE4.CANDIDATE_LABEL);
+ DisplayMode.NORMAL, BulkEditorE4Composite.CANDIDATE_LABEL);
cellStyle = new Style();
cellStyle.setAttributeValue(
GUIHelper.COLOR_GREEN);
configRegistry.registerConfigAttribute(
CellConfigAttributes.CELL_STYLE, cellStyle,
- DisplayMode.NORMAL, BulkEditorE4.TARGET_LABEL);
+ DisplayMode.NORMAL, BulkEditorE4Composite.TARGET_LABEL);
}
}
\ No newline at end of file
public String getText(T entity) {
if(entity instanceof IdentifiableEntity){
IdentifiableEntity identifiableEntity = (IdentifiableEntity) HibernateProxyHelper.deproxy(entity);
- String text = ""; //$NON-NLS-1$
- if(markedMergeCandidates.contains(entity)){
- text += Messages.AbstractBulkEditorInput_CANDIDATE;
- }
- else if(markedMergeTarget==entity){
- text += Messages.AbstractBulkEditorInput_TARGET;
- }
- text += identifiableEntity.getTitleCache();
+ String text = identifiableEntity.getTitleCache();
return text;
}
public class Messages extends NLS {
private static final String BUNDLE_NAME = "src/main/java/eu.etaxonomy.taxeditor.l10n.messages"; //$NON-NLS-1$
- public static String AbstractBulkEditorInput_CANDIDATE;
public static String AbstractBulkEditorInput_LOADED;
public static String AbstractBulkEditorInput_LOADING;
public static String AbstractBulkEditorInput_MERGE_ERROR_MESSAGE;
public static String AbstractBulkEditorInput_MERGE_ERROR_TITLE;
- public static String AbstractBulkEditorInput_TARGET;
public static String USER_CREATOR_user_exists_title;
public static String USER_CREATOR_user_exists;
public static String BulkEditorE4_CANCEL;
-AbstractBulkEditorInput_CANDIDATE=[Candidate]
AbstractBulkEditorInput_LOADED=%s/%s %s loaded
AbstractBulkEditorInput_LOADING=Loading %s for %s
AbstractBulkEditorInput_MERGE_ERROR_MESSAGE=Could not merge chosen objects of type %s
AbstractBulkEditorInput_MERGE_ERROR_TITLE=Merging failes
-AbstractBulkEditorInput_TARGET=[Target]
BulkEditorE4_CANCEL=Cancel
BulkEditorE4_DONT_SAVE=Don't save (and Search)
BulkEditorE4_SAVE_AND_SEARCH=Save (and Search)
-AbstractBulkEditorInput_CANDIDATE=[Kandidat]
AbstractBulkEditorInput_LOADED=%s/%s %s geladen
AbstractBulkEditorInput_LOADING=Lade %s für %s
AbstractBulkEditorInput_MERGE_ERROR_MESSAGE=Zusammenführen von Objekten des Typen %s fehlgeschlagen
AbstractBulkEditorInput_MERGE_ERROR_TITLE=Zusammenführen fehlgeschlagen
-AbstractBulkEditorInput_TARGET=[Ziel]
BulkEditorE4_CANCEL=Abbrechen
BulkEditorE4_DONT_SAVE=Nicht speichern (und suchen)
BulkEditorE4_SAVE_AND_SEARCH=Speichern (und suchen)