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; import org.eclipse.e4.ui.model.application.ui.menu.MHandledToolItem; import org.eclipse.e4.ui.model.application.ui.menu.MMenuContribution; import org.eclipse.e4.ui.model.application.ui.menu.MMenuFactory; import org.eclipse.e4.ui.model.application.ui.menu.MPopupMenu; 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.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; public class ElementSelectionView { private static final String CONTEXT_MENU_ID = "org.simantics.district.selection.ui.contextMenu"; private static final String POPUP_ID = "org.simantics.district.selection.ui.selectiontable.popup"; private static final String CREATE_NEW_ID = "org.simantics.district.selection.ui.command.createNewSelection"; private static final String CREATE_NEW_LABEL = "Create New Element Selection Query"; private static final String CREATE_NEW_ICON = "platform:/plugin/com.famfamfam.silk/icons/add.png"; private static final String EDIT_ID = "org.simantics.district.selection.ui.command.editElementSelector"; private static final String EDIT_LABEL = "Edit Element Selection Query"; private static final String EDIT_ICON = "platform:/plugin/com.famfamfam.silk/icons/pencil.png"; 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); private ElementSelectorTableUI table; @Inject private ESelectionService selectionService; @Inject private IEventBroker eventBroker; @Inject public void init(MPart part, MApplication app) { // Command is contributed via fragment MHandledToolItem createItem = MMenuFactory.INSTANCE.createHandledToolItem(); createItem.setCommand(app.getCommand(CREATE_NEW_ID)); createItem.setLabel(CREATE_NEW_LABEL); createItem.setIconURI(CREATE_NEW_ICON); MHandledToolItem editItem = MMenuFactory.INSTANCE.createHandledToolItem(); editItem.setCommand(app.getCommand(EDIT_ID)); editItem.setLabel(EDIT_LABEL); editItem.setIconURI(EDIT_ICON); MHandledToolItem deleteItem = MMenuFactory.INSTANCE.createHandledToolItem(); deleteItem.setCommand(app.getCommand(DELETE_ID)); deleteItem.setLabel(DELETE_LABEL); deleteItem.setIconURI(DELETE_ICON); MToolBar toolBar = MMenuFactory.INSTANCE.createToolBar(); toolBar.setToBeRendered(true); List children = toolBar.getChildren(); children.add(createItem); children.add(editItem); children.add(deleteItem); part.setToolbar(toolBar); MPopupMenu popupMenu = MMenuFactory.INSTANCE.createPopupMenu(); popupMenu.setElementId(POPUP_ID); List menuContributions = app.getMenuContributions(); for (MMenuContribution menuContribution : menuContributions) { if (CONTEXT_MENU_ID.equals(menuContribution.getParentId())) { popupMenu.getChildren().addAll(menuContribution.getChildren()); } } part.getMenus().add(popupMenu); } @PostConstruct public void createPartControl(Composite parent, EMenuService menuService) { table = new ElementSelectorTableUI(parent, SWT.BORDER, this); if (!(menuService.registerContextMenu(this.table.getTable(), POPUP_ID))) LOGGER.warn("Could not register context menu {}", POPUP_ID); } @Focus public void setFocus() { table.setFocus(); } 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; } }