]> gerrit.simantics Code Review - simantics/district.git/blob - org.simantics.district.selection.ui/src/org/simantics/district/selection/ui/parts/ElementSelectionView.java
Finder visualisation coloring to diagram & checkbox for enable/disable
[simantics/district.git] / org.simantics.district.selection.ui / src / org / simantics / district / selection / ui / parts / ElementSelectionView.java
1 package org.simantics.district.selection.ui.parts;
2
3 import java.awt.Color;
4 import java.util.ArrayList;
5 import java.util.Collection;
6 import java.util.Collections;
7 import java.util.HashMap;
8 import java.util.List;
9 import java.util.Map;
10 import java.util.Map.Entry;
11
12 import javax.annotation.PostConstruct;
13 import javax.inject.Inject;
14
15 import org.eclipse.e4.core.services.events.IEventBroker;
16 import org.eclipse.e4.ui.di.Focus;
17 import org.eclipse.e4.ui.model.application.MApplication;
18 import org.eclipse.e4.ui.model.application.ui.basic.MPart;
19 import org.eclipse.e4.ui.model.application.ui.menu.MHandledToolItem;
20 import org.eclipse.e4.ui.model.application.ui.menu.MMenuContribution;
21 import org.eclipse.e4.ui.model.application.ui.menu.MMenuFactory;
22 import org.eclipse.e4.ui.model.application.ui.menu.MPopupMenu;
23 import org.eclipse.e4.ui.model.application.ui.menu.MToolBar;
24 import org.eclipse.e4.ui.model.application.ui.menu.MToolBarElement;
25 import org.eclipse.e4.ui.services.EMenuService;
26 import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
27 import org.eclipse.jface.dialogs.MessageDialog;
28 import org.eclipse.jface.viewers.StructuredSelection;
29 import org.eclipse.swt.SWT;
30 import org.eclipse.swt.widgets.Composite;
31 import org.eclipse.swt.widgets.Display;
32 import org.simantics.Simantics;
33 import org.simantics.browsing.ui.common.AdaptableHintContext;
34 import org.simantics.db.ReadGraph;
35 import org.simantics.db.Resource;
36 import org.simantics.db.exception.DatabaseException;
37 import org.simantics.db.layer0.SelectionHints;
38 import org.simantics.db.layer0.request.ActiveModels;
39 import org.simantics.db.request.Read;
40 import org.simantics.district.network.ui.DistrictNetworkUIUtil;
41 import org.simantics.district.network.ui.participants.DistrictFinderVisualisationParticipant;
42 import org.simantics.district.selection.ElementSelector;
43 import org.simantics.district.selection.ElementSelector.DiagramGenerator;
44 import org.simantics.district.selection.ElementSelector.ExplicitGenerator;
45 import org.simantics.district.selection.ElementSelector.PropertySelector;
46 import org.simantics.district.selection.ElementSelector.SelectionResult;
47 import org.simantics.district.selection.ui.ElementSelectionTools;
48 import org.simantics.district.selection.ui.ElementSelectorTableUI;
49 import org.simantics.scl.runtime.tuple.Tuple2;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52
53 public class ElementSelectionView {
54         private static final String CONTEXT_MENU_ID = "org.simantics.district.selection.ui.contextMenu";
55         private static final String POPUP_ID = "org.simantics.district.selection.ui.selectiontable.popup";
56         private static final String CREATE_NEW_ID = "org.simantics.district.selection.ui.command.createNewSelection";
57         private static final String CREATE_NEW_LABEL = "Create New Element Selection Query";
58         private static final String CREATE_NEW_ICON = "platform:/plugin/com.famfamfam.silk/icons/add.png";
59         private static final String EDIT_ID = "org.simantics.district.selection.ui.command.editElementSelector";
60         private static final String EDIT_LABEL = "Edit Element Selection Query";
61         private static final String EDIT_ICON = "platform:/plugin/com.famfamfam.silk/icons/pencil.png";
62         private static final String DELETE_ID = "org.simantics.district.selection.ui.command.deleteElementSelector";
63         private static final String DELETE_LABEL = "Delete Element Selection Query";
64         private static final String DELETE_ICON = "platform:/plugin/com.famfamfam.silk/icons/cross.png";
65
66         /**
67          * Name of an event that is posted to IEventBroker when a selection is made. The data value is
68          * an instance of Collection<Resource>.
69          */
70         public static final String SELECTION_EVENT_ID = "org/simantics/district/selection/elementQuerySelection";
71         
72         private static final Logger LOGGER = LoggerFactory.getLogger(ElementSelectionView.class);
73
74         private ElementSelectorTableUI table;
75
76         @Inject
77         private ESelectionService selectionService;
78         
79         @Inject
80         private IEventBroker eventBroker;
81         
82         @Inject
83         public void init(MPart part, MApplication app) {
84                 // Command is contributed via fragment
85                 MHandledToolItem createItem = MMenuFactory.INSTANCE.createHandledToolItem();
86                 createItem.setCommand(app.getCommand(CREATE_NEW_ID));
87                 createItem.setLabel(CREATE_NEW_LABEL);
88                 createItem.setIconURI(CREATE_NEW_ICON);
89                 MHandledToolItem editItem = MMenuFactory.INSTANCE.createHandledToolItem();
90                 editItem.setCommand(app.getCommand(EDIT_ID));
91                 editItem.setLabel(EDIT_LABEL);
92                 editItem.setIconURI(EDIT_ICON);
93                 MHandledToolItem deleteItem = MMenuFactory.INSTANCE.createHandledToolItem();
94                 deleteItem.setCommand(app.getCommand(DELETE_ID));
95                 deleteItem.setLabel(DELETE_LABEL);
96                 deleteItem.setIconURI(DELETE_ICON);
97                 
98                 MToolBar toolBar = MMenuFactory.INSTANCE.createToolBar();
99                 toolBar.setToBeRendered(true);
100                 
101                 List<MToolBarElement> children = toolBar.getChildren();
102                 children.add(createItem);
103                 children.add(editItem);
104                 children.add(deleteItem);
105                 
106                 part.setToolbar(toolBar);
107
108                 MPopupMenu popupMenu = MMenuFactory.INSTANCE.createPopupMenu();
109                 popupMenu.setElementId(POPUP_ID);
110
111                 List<MMenuContribution> menuContributions = app.getMenuContributions();
112                 for (MMenuContribution menuContribution : menuContributions) {
113                         if (CONTEXT_MENU_ID.equals(menuContribution.getParentId())) {
114                                 popupMenu.getChildren().addAll(menuContribution.getChildren());
115                         }
116                 }
117
118                 part.getMenus().add(popupMenu);
119         }
120
121         @PostConstruct
122         public void createPartControl(Composite parent, EMenuService menuService) {
123                 table = new ElementSelectorTableUI(parent, SWT.BORDER, this);
124                 if (!(menuService.registerContextMenu(this.table.getTable(), POPUP_ID)))
125                         LOGGER.warn("Could not register context menu {}", POPUP_ID);
126         }
127
128         @Focus
129         public void setFocus() {
130                 table.setFocus();
131         }
132         
133         public ElementSelector getSelectedItem() {
134                 return table.getSelectedItem();
135         }
136         
137         private Map<ElementSelector, Tuple2> resultCache = new HashMap<>();
138
139         public void performSelection(Display display, ElementSelector query) {
140                 try {
141                         Collection<Resource> models = Simantics.getSession().syncRequest(new ActiveModels(Simantics.getProjectResource()));
142                         final Resource model = models.isEmpty() ? null : models.iterator().next();
143                         
144                         Tuple2 selectionResult = resultCache.get(query);
145                         if (selectionResult != null) {
146                                 // clear existing result and visualisation
147                                 clearResultVisualisation(query);
148                         }
149                         
150                         SelectionResult result = performQuery(query, model);
151                         
152                         resultCache.put(query, new Tuple2(result, model));
153                         
154                         if (result.tailCount != result.tailSize) {
155                                 showArbitraryResultWarning(query, result);
156                         }
157                         
158                         if (query.getGenerator() instanceof DiagramGenerator || query.getGenerator() instanceof ExplicitGenerator) {
159                                 openDiagramWithSelection(display, result);
160                         }
161                         
162                         StructuredSelection selection = makeSelection(model, result, query.getColor());
163                         selectionService.setPostSelection(selection);
164                         sendSelectionEvent(selection);
165                 } catch (DatabaseException e) {
166                         LOGGER.error("Element selection query failed", e);
167                 }
168         }
169         
170         public void clearResultVisualisation(ElementSelector query) {
171                 Tuple2 selectionResult = resultCache.get(query);
172                 if (selectionResult != null) {
173                         SelectionResult result = (SelectionResult) selectionResult.c0;
174                         Resource model = (Resource) selectionResult.c1;
175                         eventBroker.send(SELECTION_EVENT_ID, makeSelection(model, result, null));
176                 }
177         }
178
179         private StructuredSelection makeSelection(final Resource model, SelectionResult result, float[] fs) {
180                 return new StructuredSelection(result.elements.stream()
181                                 .map(p0 -> {
182                                         AdaptableHintContext selectionElement = new ElementSelectionTools.SelectionElement(SelectionHints.STD_KEYS);
183                                         selectionElement.setHint(SelectionHints.KEY_MAIN, p0);
184                                         selectionElement.setHint(SelectionHints.KEY_MODEL, model);
185                                         if (fs != null) {
186                                                 selectionElement.setHint(DistrictFinderVisualisationParticipant.COLOR_KEY, new Color(fs[2], fs[1], fs[0], fs[3]));
187                                         }
188                                         return selectionElement;
189                                 })
190                                 .toArray());
191         }
192
193         private void openDiagramWithSelection(Display display, SelectionResult result) throws DatabaseException {
194                 DistrictNetworkUIUtil.openDNDiagramWithSelection(display, new ArrayList<>(result.elements));
195         }
196
197         private void sendSelectionEvent(Object selection) {
198                 eventBroker.send(SELECTION_EVENT_ID, selection);
199         }
200
201         private void showArbitraryResultWarning(ElementSelector query, SelectionResult result) {
202                 String name = query.getSelector() != null && query.getSelector() instanceof PropertySelector ? ((PropertySelector)query.getSelector()).propertyName : null;
203                 String msg = "Last " + result.tailCount + " of the " + result.elements.size() + " selected elements are an arbitraty subset of " + result.tailSize + " elements with equal values" +
204                                 (name != null ? " for " + name : "");
205                 MessageDialog.openInformation(Display.getDefault().getActiveShell(), "Note", msg);
206         }
207
208         private SelectionResult performQuery(ElementSelector query, final Resource model) throws DatabaseException {
209                 SelectionResult result = Simantics.getSession().syncRequest(new Read<SelectionResult>() {
210                         @Override
211                         public SelectionResult perform(ReadGraph graph) throws DatabaseException {
212                                 if (model == null) {
213                                         LOGGER.warn("No active model");
214                                         return new SelectionResult(Collections.emptyList(), 0, 0);
215                                 }
216                                 
217                                 return query.selectElementsFrom(graph, model);
218                         }
219                 });
220                 return result;
221         }
222
223         public void dispose() {
224                 for (Entry<ElementSelector, Tuple2> entry : resultCache.entrySet()) {
225                         ElementSelector query = entry.getKey();
226                         clearResultVisualisation(query);
227                 }
228         }
229 }