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; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.FillLayout; 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.slf4j.Logger; import org.slf4j.LoggerFactory; 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) { super(parent, style); 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.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)) return new Object[0]; 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() { @Override public String getText(Object element) { ElementSelector selector = (ElementSelector) element; return selector.getName(); } @Override public Image getImage(Object element) { return null; } }); column2 = new TreeViewerColumn(viewer, SWT.NONE); column2.getColumn().setText("Query"); column2.getColumn().setWidth(600); column2.getColumn().setResizable(true); column2.setLabelProvider(new ColumnLabelProvider() { @Override public String getText(Object element) { ElementSelector selector = (ElementSelector) element; return selector.getExpression(); } @Override public Image getImage(Object element) { return null; } }); } 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); } @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; } } private static final class DoubleClickListener implements IDoubleClickListener { private final ESelectionService selectionService; private Resource model; private DoubleClickListener(ESelectionService selectionService) { this.selectionService = selectionService; } @Override public void doubleClick(DoubleClickEvent event) { TreeSelection selection = (TreeSelection) event.getViewer().getSelection(); 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); } } } }