From 9026bdb43820fcd07826ed649ede5b3a82e92f5a Mon Sep 17 00:00:00 2001 From: Reino Ruusu Date: Mon, 7 Oct 2019 16:14:18 +0300 Subject: [PATCH] Send event for performed queries + some refactoring gitlab #62 Change-Id: Ib6327b22ed2a622bfd4af05346dcb8a86419ddd1 (cherry picked from commit fc5581727a984b57dade7a627ac408ea5ad3f811) --- .../META-INF/MANIFEST.MF | 4 +- .../selection/ui/ElementSelectionTools.java | 84 ++++++ .../selection/ui/ElementSelectorTableUI.java | 253 ++++++------------ .../ui/parts/ElementSelectionView.java | 99 ++++++- 4 files changed, 266 insertions(+), 174 deletions(-) create mode 100644 org.simantics.district.selection.ui/src/org/simantics/district/selection/ui/ElementSelectionTools.java diff --git a/org.simantics.district.selection.ui/META-INF/MANIFEST.MF b/org.simantics.district.selection.ui/META-INF/MANIFEST.MF index 31f83e38..2dc51ac9 100644 --- a/org.simantics.district.selection.ui/META-INF/MANIFEST.MF +++ b/org.simantics.district.selection.ui/META-INF/MANIFEST.MF @@ -28,9 +28,11 @@ Require-Bundle: javax.inject, org.simantics.silk.ontology;bundle-version="1.1.0", org.simantics.district.network.ui, org.simantics.structural.ontology, - org.simantics.diagram.ontology + org.simantics.diagram.ontology, + org.eclipse.e4.core.services Bundle-ManifestVersion: 2 Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-Vendor: Semantum oy Import-Package: javax.annotation;version="1.2.0" +Export-Package: org.simantics.district.selection.ui.parts diff --git a/org.simantics.district.selection.ui/src/org/simantics/district/selection/ui/ElementSelectionTools.java b/org.simantics.district.selection.ui/src/org/simantics/district/selection/ui/ElementSelectionTools.java new file mode 100644 index 00000000..130e3f4f --- /dev/null +++ b/org.simantics.district.selection.ui/src/org/simantics/district/selection/ui/ElementSelectionTools.java @@ -0,0 +1,84 @@ +package org.simantics.district.selection.ui; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import org.simantics.Simantics; +import org.simantics.browsing.ui.common.AdaptableHintContext; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.common.request.ResourceRead; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.QueryIndexUtils; +import org.simantics.db.layer0.SelectionHints; +import org.simantics.db.layer0.request.ActiveModels; +import org.simantics.db.layer0.variable.Variable; +import org.simantics.db.request.Read; +import org.simantics.district.selection.ElementSelectionResource; +import org.simantics.district.selection.ElementSelector; +import org.simantics.layer0.Layer0; +import org.simantics.ui.selection.AnyResource; +import org.simantics.ui.selection.AnyVariable; +import org.simantics.ui.selection.WorkbenchSelectionContentType; + +public class ElementSelectionTools { + + public static final class SelectionElement extends AdaptableHintContext { + public SelectionElement(Key[] keys) { + super(keys); + } + + @SuppressWarnings("unchecked") + public T getContent(WorkbenchSelectionContentType contentType) { + Resource element = getHint(SelectionHints.KEY_MAIN); + if (contentType instanceof AnyResource) { + return (T)element; + } + else if (contentType instanceof AnyVariable) { + try { + return (T) Simantics.getSession().syncRequest(new ResourceRead(element) { + public Variable perform(ReadGraph graph) throws DatabaseException { + return ElementSelector.getVariableForElement(graph, resource); + } + }); + } catch (DatabaseException e) { + return null; + } + } + + return null; + } + } + + public static final class SelectionsRequest implements Read> { + @Override + public Collection perform(ReadGraph graph) throws DatabaseException { + Layer0 L0 = Layer0.getInstance(graph); + ElementSelectionResource ES = ElementSelectionResource.getInstance(graph); + + Resource model = ActiveModels.getPossibleActiveModel(graph, Simantics.getProjectResource()); + if (model == null) { + return Collections.emptyList(); + } + + List libs = QueryIndexUtils.searchByType(graph, model, ES.SelectionLibrary); + if (libs.isEmpty()) + return Collections.emptyList(); + + Resource lib = libs.get(0); + + List result = new ArrayList<>(); + for (Resource selection : graph.getObjects(lib, L0.ConsistsOf)) { + if (!graph.isInstanceOf(selection, ES.Selection)) + continue; + + result.add(ElementSelector.getSelector(graph, selection)); + } + + return result; + } + } + +} diff --git a/org.simantics.district.selection.ui/src/org/simantics/district/selection/ui/ElementSelectorTableUI.java b/org.simantics.district.selection.ui/src/org/simantics/district/selection/ui/ElementSelectorTableUI.java index 001c8730..cdddd928 100644 --- a/org.simantics.district.selection.ui/src/org/simantics/district/selection/ui/ElementSelectorTableUI.java +++ b/org.simantics.district.selection.ui/src/org/simantics/district/selection/ui/ElementSelectorTableUI.java @@ -1,19 +1,13 @@ package org.simantics.district.selection.ui; -import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; -import java.util.List; -import org.eclipse.e4.ui.workbench.modeling.ESelectionService; -import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.ColumnLabelProvider; import org.eclipse.jface.viewers.ColumnViewerToolTipSupport; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITreeContentProvider; -import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TreeSelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.TreeViewerColumn; @@ -25,28 +19,11 @@ import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Tree; import org.simantics.Simantics; -import org.simantics.browsing.ui.common.AdaptableHintContext; import org.simantics.db.ReadGraph; -import org.simantics.db.Resource; import org.simantics.db.common.procedure.adapter.SyncListenerAdapter; -import org.simantics.db.common.request.ResourceRead; import org.simantics.db.exception.DatabaseException; -import org.simantics.db.layer0.QueryIndexUtils; -import org.simantics.db.layer0.SelectionHints; -import org.simantics.db.layer0.request.ActiveModels; -import org.simantics.db.layer0.variable.Variable; -import org.simantics.db.request.Read; -import org.simantics.district.network.ui.DistrictNetworkUIUtil; -import org.simantics.district.selection.ElementSelectionResource; import org.simantics.district.selection.ElementSelector; -import org.simantics.district.selection.ElementSelector.DiagramGenerator; -import org.simantics.district.selection.ElementSelector.ExplicitGenerator; -import org.simantics.district.selection.ElementSelector.PropertySelector; -import org.simantics.district.selection.ElementSelector.SelectionResult; -import org.simantics.layer0.Layer0; -import org.simantics.ui.selection.AnyResource; -import org.simantics.ui.selection.AnyVariable; -import org.simantics.ui.selection.WorkbenchSelectionContentType; +import org.simantics.district.selection.ui.parts.ElementSelectionView; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -55,30 +32,64 @@ public class ElementSelectorTableUI extends Composite { private static final Logger LOGGER = LoggerFactory.getLogger(ElementSelectorTableUI.class); private TreeViewer viewer; - private TreeViewerColumn column1; - private TreeViewerColumn column2; - public ElementSelectorTableUI(ESelectionService selectionService, Composite parent, int style) { + private ElementSelectionView view; + + public ElementSelectorTableUI(Composite parent, int style, ElementSelectionView view) { super(parent, style); + this.view = view; + parent.setLayout(new FillLayout()); // GridDataFactory.fillDefaults().grab(true, true).applyTo(this); // GridLayoutFactory.fillDefaults().numColumns(1).applyTo(this); this.setLayout(new FillLayout()); - viewer = new TreeViewer(this, SWT.FULL_SELECTION); - viewer.addDoubleClickListener(new DoubleClickListener(selectionService)); - + viewer = createViewer(); + addSelectionListener(); + setContentProvider(); + createSelectorListener(parent); + enableToolTips(); + configureTable(); + } + + public Tree getTree() { + return viewer.getTree(); + } + + public ElementSelector getSelectedItem() { + IStructuredSelection selection = (IStructuredSelection) viewer.getSelection(); + return selection != null ? (ElementSelector) selection.getFirstElement() : null; + } + + private TreeViewer createViewer() { + return new TreeViewer(this, SWT.FULL_SELECTION); + } + + private void configureTable() { + Tree table = viewer.getTree(); + table.setHeaderVisible(true); + table.setLinesVisible(true); + + createNameColumn(); + createQueryColumn(); + } + + private void enableToolTips() { + ColumnViewerToolTipSupport.enableFor(viewer); + } + + private void setContentProvider() { viewer.setContentProvider(new ITreeContentProvider() { @Override public boolean hasChildren(Object element) { return false; } - + @Override public Object getParent(Object element) { return null; } - + @Override public Object[] getElements(Object inputElement) { if (inputElement == null || !(inputElement instanceof Collection)) @@ -86,47 +97,25 @@ public class ElementSelectorTableUI extends Composite { return ((Collection)inputElement).toArray(); } - + @Override public Object[] getChildren(Object parentElement) { return null; } - + @Override public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { ITreeContentProvider.super.inputChanged(viewer, oldInput, newInput); } }); - - Simantics.getSession().asyncRequest(new SelectionsRequest(), new SyncListenerAdapter>() { - public void execute(ReadGraph graph, Collection result) { - parent.getDisplay().asyncExec(() -> { - viewer.setInput(result); - }); - } - - @Override - public void exception(ReadGraph graph, Throwable t) throws DatabaseException { - LOGGER.error("Error getting element selector list", t); - } - - @Override - public boolean isDisposed() { - return ElementSelectorTableUI.this.isDisposed(); - } - }); - - ColumnViewerToolTipSupport.enableFor(viewer); - - Tree table = viewer.getTree(); - table.setHeaderVisible(true); - table.setLinesVisible(true); + } - column1 = new TreeViewerColumn(viewer, SWT.NONE); - column1.getColumn().setText("Name"); - column1.getColumn().setWidth(200); - column1.getColumn().setResizable(true); - column1.setLabelProvider(new ColumnLabelProvider() { + private TreeViewerColumn createNameColumn() { + TreeViewerColumn column = new TreeViewerColumn(viewer, SWT.NONE); + column.getColumn().setText("Name"); + column.getColumn().setWidth(200); + column.getColumn().setResizable(true); + column.setLabelProvider(new ColumnLabelProvider() { @Override public String getText(Object element) { ElementSelector selector = (ElementSelector) element; @@ -138,12 +127,15 @@ public class ElementSelectorTableUI extends Composite { return null; } }); + return column; + } - column2 = new TreeViewerColumn(viewer, SWT.NONE); - column2.getColumn().setText("Query"); - column2.getColumn().setWidth(600); - column2.getColumn().setResizable(true); - column2.setLabelProvider(new ColumnLabelProvider() { + private TreeViewerColumn createQueryColumn() { + TreeViewerColumn column = new TreeViewerColumn(viewer, SWT.NONE); + column.getColumn().setText("Query"); + column.getColumn().setWidth(600); + column.getColumn().setResizable(true); + column.setLabelProvider(new ColumnLabelProvider() { @Override public String getText(Object element) { ElementSelector selector = (ElementSelector) element; @@ -155,122 +147,41 @@ public class ElementSelectorTableUI extends Composite { return null; } }); + return column; } - public Tree getTree() { - return viewer.getTree(); - } - - public ElementSelector getSelectedItem() { - IStructuredSelection selection = (IStructuredSelection) viewer.getSelection(); - return selection != null ? (ElementSelector) selection.getFirstElement() : null; - } - - private static final class SelectionElement extends AdaptableHintContext { - private SelectionElement(Key[] keys) { - super(keys); - } + private void createSelectorListener(Composite parent) { + Simantics.getSession().asyncRequest(new ElementSelectionTools.SelectionsRequest(), new SyncListenerAdapter>() { + public void execute(ReadGraph graph, Collection result) { + parent.getDisplay().asyncExec(() -> { + viewer.setInput(result); + }); + } - @SuppressWarnings("unchecked") - public T getContent(WorkbenchSelectionContentType contentType) { - Resource element = getHint(SelectionHints.KEY_MAIN); - if (contentType instanceof AnyResource) { - return (T)element; + @Override + public void exception(ReadGraph graph, Throwable t) throws DatabaseException { + LOGGER.error("Error getting element selector list", t); } - else if (contentType instanceof AnyVariable) { - try { - return (T) Simantics.getSession().syncRequest(new ResourceRead(element) { - public Variable perform(ReadGraph graph) throws DatabaseException { - return ElementSelector.getVariableForElement(graph, resource); - } - }); - } catch (DatabaseException e) { - return null; - } + + @Override + public boolean isDisposed() { + return ElementSelectorTableUI.this.isDisposed(); } - - return null; - } + }); } - public static final class SelectionsRequest implements Read> { - @Override - public Collection perform(ReadGraph graph) throws DatabaseException { - Layer0 L0 = Layer0.getInstance(graph); - ElementSelectionResource ES = ElementSelectionResource.getInstance(graph); - - Resource model = ActiveModels.getPossibleActiveModel(graph, Simantics.getProjectResource()); - if (model == null) { - return Collections.emptyList(); - } - - List libs = QueryIndexUtils.searchByType(graph, model, ES.SelectionLibrary); - if (libs.isEmpty()) - return Collections.emptyList(); - - Resource lib = libs.get(0); - - List result = new ArrayList<>(); - for (Resource selection : graph.getObjects(lib, L0.ConsistsOf)) { - if (!graph.isInstanceOf(selection, ES.Selection)) - continue; - - result.add(ElementSelector.getSelector(graph, selection)); - } - - return result; - } + private void addSelectionListener() { + viewer.addDoubleClickListener(new DoubleClickListener()); } - private static final class DoubleClickListener implements IDoubleClickListener { - private final ESelectionService selectionService; - private Resource model; - - private DoubleClickListener(ESelectionService selectionService) { - this.selectionService = selectionService; - } - + private final class DoubleClickListener implements IDoubleClickListener { @Override public void doubleClick(DoubleClickEvent event) { TreeSelection selection = (TreeSelection) event.getViewer().getSelection(); + Display display = event.getViewer().getControl().getDisplay(); ElementSelector query = (ElementSelector) selection.getFirstElement(); - try { - SelectionResult result = Simantics.getSession().syncRequest(new Read() { - @Override - public SelectionResult perform(ReadGraph graph) throws DatabaseException { - model = ActiveModels.getPossibleActiveModel(graph, Simantics.getProjectResource()); - if (model == null) { - LOGGER.warn("No active model"); - return new SelectionResult(Collections.emptyList(), 0, 0); - } - - return query.selectElementsFrom(graph, model); - } - }); - - if (query.getGenerator() instanceof DiagramGenerator || query.getGenerator() instanceof ExplicitGenerator) { - DistrictNetworkUIUtil.openDNDiagramWithSelection(event.getViewer().getControl().getDisplay(), new ArrayList<>(result.elements)); - } - else { - selectionService.setPostSelection(new StructuredSelection(result.elements.stream() - .map(p0 -> { - AdaptableHintContext selectionElement = new SelectionElement(SelectionHints.STD_KEYS); - selectionElement.setHint(SelectionHints.KEY_MAIN, p0); - selectionElement.setHint(SelectionHints.KEY_MODEL, model); - return selectionElement; - }) - .toArray())); - } - - if (result.tailCount != result.tailSize) { - String name = query.getSelector() != null && query.getSelector() instanceof PropertySelector ? ((PropertySelector)query.getSelector()).propertyName : null; - String msg = "Last " + result.tailCount + " of the " + result.elements.size() + " selected elements are an arbitraty subset of " + result.tailSize + " elements with equal values" + - (name != null ? " for " + name : ""); - MessageDialog.openInformation(Display.getDefault().getActiveShell(), "Note", msg); - } - } catch (DatabaseException e) { - LOGGER.error("Element selection query failed", e); - } + + view.performSelection(display, query); } } } diff --git a/org.simantics.district.selection.ui/src/org/simantics/district/selection/ui/parts/ElementSelectionView.java b/org.simantics.district.selection.ui/src/org/simantics/district/selection/ui/parts/ElementSelectionView.java index 1cddde9f..5a0767f8 100644 --- a/org.simantics.district.selection.ui/src/org/simantics/district/selection/ui/parts/ElementSelectionView.java +++ b/org.simantics.district.selection.ui/src/org/simantics/district/selection/ui/parts/ElementSelectionView.java @@ -1,10 +1,14 @@ package org.simantics.district.selection.ui.parts; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.List; import javax.annotation.PostConstruct; import javax.inject.Inject; +import org.eclipse.e4.core.services.events.IEventBroker; import org.eclipse.e4.ui.di.Focus; import org.eclipse.e4.ui.model.application.MApplication; import org.eclipse.e4.ui.model.application.ui.basic.MPart; @@ -16,9 +20,27 @@ import org.eclipse.e4.ui.model.application.ui.menu.MToolBar; import org.eclipse.e4.ui.model.application.ui.menu.MToolBarElement; import org.eclipse.e4.ui.services.EMenuService; import org.eclipse.e4.ui.workbench.modeling.ESelectionService; +import org.eclipse.e4.ui.workbench.modeling.ISelectionListener; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.simantics.Simantics; +import org.simantics.browsing.ui.common.AdaptableHintContext; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.SelectionHints; +import org.simantics.db.layer0.request.ActiveModels; +import org.simantics.db.request.Read; +import org.simantics.district.network.ui.DistrictNetworkUIUtil; import org.simantics.district.selection.ElementSelector; +import org.simantics.district.selection.ElementSelector.DiagramGenerator; +import org.simantics.district.selection.ElementSelector.ExplicitGenerator; +import org.simantics.district.selection.ElementSelector.PropertySelector; +import org.simantics.district.selection.ElementSelector.SelectionResult; +import org.simantics.district.selection.ui.ElementSelectionTools; import org.simantics.district.selection.ui.ElementSelectorTableUI; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,6 +57,12 @@ public class ElementSelectionView { private static final String DELETE_ID = "org.simantics.district.selection.ui.command.deleteElementSelector"; private static final String DELETE_LABEL = "Delete Element Selection Query"; private static final String DELETE_ICON = "platform:/plugin/com.famfamfam.silk/icons/cross.png"; + + /** + * Name of an event that is posted to IEventBroker when a selection is made. The data value is + * an instance of Collection<Resource>. + */ + public static final String SELECTION_EVENT_ID = "org/simantics/district/selection/elementQuerySelection"; private static final Logger LOGGER = LoggerFactory.getLogger(ElementSelectionView.class); @@ -42,7 +70,10 @@ public class ElementSelectionView { @Inject private ESelectionService selectionService; - + + @Inject + private IEventBroker eventBroker; + @Inject public void init(MPart part, MApplication app) { // Command is contributed via fragment @@ -84,7 +115,7 @@ public class ElementSelectionView { @PostConstruct public void createPartControl(Composite parent, EMenuService menuService) { - table = new ElementSelectorTableUI(selectionService, parent, SWT.BORDER); + table = new ElementSelectorTableUI(parent, SWT.BORDER, this); if (!(menuService.registerContextMenu(this.table.getTree(), POPUP_ID))) LOGGER.warn("Could not register context menu {}", POPUP_ID); } @@ -97,4 +128,68 @@ public class ElementSelectionView { public ElementSelector getSelectedItem() { return table.getSelectedItem(); } + + public void performSelection(Display display, ElementSelector query) { + try { + Collection models = Simantics.getSession().syncRequest(new ActiveModels(Simantics.getProjectResource())); + final Resource model = models.isEmpty() ? null : models.iterator().next(); + + SelectionResult result = performQuery(query, model); + + if (result.tailCount != result.tailSize) { + showArbitraryResultWarning(query, result); + } + + if (query.getGenerator() instanceof DiagramGenerator || query.getGenerator() instanceof ExplicitGenerator) { + openDiagramWithSelection(display, result); + } + + StructuredSelection selection = makeSelection(model, result); + selectionService.setPostSelection(selection); + sendSelectionEvent(selection); + } catch (DatabaseException e) { + LOGGER.error("Element selection query failed", e); + } + } + + private StructuredSelection makeSelection(final Resource model, SelectionResult result) { + return new StructuredSelection(result.elements.stream() + .map(p0 -> { + AdaptableHintContext selectionElement = new ElementSelectionTools.SelectionElement(SelectionHints.STD_KEYS); + selectionElement.setHint(SelectionHints.KEY_MAIN, p0); + selectionElement.setHint(SelectionHints.KEY_MODEL, model); + return selectionElement; + }) + .toArray()); + } + + private void openDiagramWithSelection(Display display, SelectionResult result) throws DatabaseException { + DistrictNetworkUIUtil.openDNDiagramWithSelection(display, new ArrayList<>(result.elements)); + } + + private void sendSelectionEvent(Object selection) { + eventBroker.send(SELECTION_EVENT_ID, selection); + } + + private void showArbitraryResultWarning(ElementSelector query, SelectionResult result) { + String name = query.getSelector() != null && query.getSelector() instanceof PropertySelector ? ((PropertySelector)query.getSelector()).propertyName : null; + String msg = "Last " + result.tailCount + " of the " + result.elements.size() + " selected elements are an arbitraty subset of " + result.tailSize + " elements with equal values" + + (name != null ? " for " + name : ""); + MessageDialog.openInformation(Display.getDefault().getActiveShell(), "Note", msg); + } + + private SelectionResult performQuery(ElementSelector query, final Resource model) throws DatabaseException { + SelectionResult result = Simantics.getSession().syncRequest(new Read() { + @Override + public SelectionResult perform(ReadGraph graph) throws DatabaseException { + if (model == null) { + LOGGER.warn("No active model"); + return new SelectionResult(Collections.emptyList(), 0, 0); + } + + return query.selectElementsFrom(graph, model); + } + }); + return result; + } } -- 2.45.1