]> gerrit.simantics Code Review - simantics/3d.git/blob - org.simantics.plant3d/src/org/simantics/plant3d/dialog/ComponentSelectionDialog.java
Merge "More precise position selection for add component action"
[simantics/3d.git] / org.simantics.plant3d / src / org / simantics / plant3d / dialog / ComponentSelectionDialog.java
1 package org.simantics.plant3d.dialog;
2
3 import java.util.HashSet;
4 import java.util.List;
5 import java.util.Set;
6
7 import org.eclipse.jface.dialogs.Dialog;
8 import org.eclipse.jface.dialogs.IDialogConstants;
9 import org.eclipse.jface.layout.GridDataFactory;
10 import org.eclipse.jface.layout.GridLayoutFactory;
11 import org.eclipse.jface.resource.JFaceResources;
12 import org.eclipse.jface.resource.LocalResourceManager;
13 import org.eclipse.jface.resource.ResourceManager;
14 import org.eclipse.jface.viewers.ISelectionChangedListener;
15 import org.eclipse.jface.viewers.IStructuredSelection;
16 import org.eclipse.jface.viewers.ListViewer;
17 import org.eclipse.jface.viewers.SelectionChangedEvent;
18 import org.eclipse.jface.viewers.StructuredSelection;
19 import org.eclipse.swt.SWT;
20 import org.eclipse.swt.events.KeyAdapter;
21 import org.eclipse.swt.events.KeyEvent;
22 import org.eclipse.swt.events.SelectionAdapter;
23 import org.eclipse.swt.events.SelectionEvent;
24 import org.eclipse.swt.layout.GridData;
25 import org.eclipse.swt.layout.GridLayout;
26 import org.eclipse.swt.widgets.Button;
27 import org.eclipse.swt.widgets.Composite;
28 import org.eclipse.swt.widgets.Control;
29 import org.eclipse.swt.widgets.ExpandBar;
30 import org.eclipse.swt.widgets.ExpandItem;
31 import org.eclipse.swt.widgets.Label;
32 import org.eclipse.swt.widgets.Shell;
33 import org.eclipse.swt.widgets.Text;
34 import org.simantics.db.exception.DatabaseException;
35 import org.simantics.plant3d.Activator;
36 import org.simantics.plant3d.scenegraph.EndComponent;
37 import org.simantics.plant3d.scenegraph.InlineComponent;
38 import org.simantics.plant3d.scenegraph.Nozzle;
39 import org.simantics.plant3d.scenegraph.PipelineComponent;
40 import org.simantics.plant3d.scenegraph.TurnComponent;
41 import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint.PositionType;
42 import org.simantics.plant3d.utils.Item;
43 import org.simantics.plant3d.utils.Item.Type;
44 import org.simantics.plant3d.utils.P3DUtil;
45 import org.simantics.utils.ui.ExceptionUtils;
46
47 public class ComponentSelectionDialog extends Dialog implements ISelectionChangedListener{
48
49     private ResourceManager resourceManager;
50     
51         private Item selected;
52         private Set<PositionType> allowed;
53         private Set<PositionType> filterAllowed;
54         //private boolean positionAdjustment;
55         private PipelineComponent component;
56         private boolean insertAdjustable;
57         private boolean lenghtAdjustable;
58         private PositionType insertPosition = PositionType.NEXT; 
59         
60         private Double angle;
61         private Double length;
62         
63         private Text lengthText;
64         private Text angleText;
65         
66         private Double diameter;
67         private Double turnRadius;
68         
69         private Text diameterText;
70         private Text turnRadiusText;
71         
72         private Button startButton;
73         private Button middleButton;
74         private Button endButton;
75         
76         private boolean inlineSplit = false;
77         
78         ListViewer inlineViewer;
79         ListViewer turnViewer;
80         ListViewer endViewer;
81         
82         
83         public ComponentSelectionDialog(Shell parentShell, Set<PositionType> allowed, PipelineComponent component){
84                 super(parentShell);
85                 this.allowed = allowed;
86                 this.component = component;
87                 filterAllowed = new HashSet<PositionType>();
88                 insertAdjustable = component instanceof InlineComponent ? ((InlineComponent)component).isVariableLength() : false;
89                 lenghtAdjustable = false;
90         }
91         
92         @Override
93         protected Control createDialogArea(Composite parent) {
94             resourceManager = new LocalResourceManager(JFaceResources.getResources(), parent);
95             
96                 Composite composite = new Composite(parent, SWT.NONE);
97                 GridLayout layout = new GridLayout(2,false);
98                 layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
99                 layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
100                 layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
101                 layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
102                 composite.setLayout(layout);
103                 composite.setLayoutData(new GridData(GridData.FILL_BOTH));
104                 applyDialogFont(composite);
105                 
106                 // TODO : we need better classification than inline,turn, and end:
107                 // * fixed length inlines
108                 // * fixed angle turns
109                 // * size changes (requires input for pipe run specs)
110                 // * variable length inlines (input for length)
111                 // * variable angle turns (input for angle)
112                 // * ends
113                 
114                 List<Item> ends = null;
115                 List<Item> turns = null;
116                 List<Item> inlines = null;
117                 try {
118                         ends = P3DUtil.getEnds();
119                         turns= P3DUtil.getTurns();
120                         inlines = P3DUtil.getInlines();
121                 } catch (DatabaseException e) {
122                         Label label = new Label(composite, SWT.NONE);
123                         label.setText("Cannot load pipeline components: " + e.getMessage());
124                         ExceptionUtils.logError(e);
125                         return composite;
126                 }
127                 ends = P3DUtil.filterUserComponents(ends);
128                 turns = P3DUtil.filterUserComponents(turns);
129                 inlines = P3DUtil.filterUserComponents(inlines);
130                 
131                 ExpandBar expandBar = new ExpandBar(composite, SWT.NONE);
132                 
133                 
134                 ExpandItem inlineItem = new ExpandItem(expandBar, SWT.NONE);
135                 inlineItem.setText("Inline");
136                 inlineViewer = new ListViewer(expandBar);
137                 inlineViewer.setLabelProvider(new ComponentLabelProvider());
138                 inlineViewer.setContentProvider(new ComponentContentProvider());
139                 
140                 ExpandItem turnItem = new ExpandItem(expandBar, SWT.NONE);
141                 turnItem.setText("Turn");
142                 turnViewer = new ListViewer(expandBar);
143                 turnViewer.setLabelProvider(new ComponentLabelProvider());
144                 turnViewer.setContentProvider(new ComponentContentProvider());
145                 
146                 ExpandItem endItem = new ExpandItem(expandBar, SWT.NONE);
147                 endItem.setText("End");
148                 endViewer = new ListViewer(expandBar);
149                 endViewer.setLabelProvider(new ComponentLabelProvider());
150                 endViewer.setContentProvider(new ComponentContentProvider());
151                 
152                 
153                 inlineItem.setControl(inlineViewer.getList());
154                 turnItem.setControl(turnViewer.getList());
155                 endItem.setControl(endViewer.getList());
156                 
157                 inlineViewer.setInput(inlines);
158                 turnViewer.setInput(turns);
159                 endViewer.setInput(ends);
160                 
161                 inlineItem.setHeight(inlineViewer.getList().computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
162                 turnItem.setHeight(turnViewer.getList().computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
163                 endItem.setHeight(endViewer.getList().computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
164                 
165                 inlineViewer.addSelectionChangedListener(this);
166                 turnViewer.addSelectionChangedListener(this);
167                 endViewer.addSelectionChangedListener(this);
168                 
169                 GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).span(2, 1).applyTo(expandBar);
170                 GridDataFactory.fillDefaults().minSize(500, 500).hint(500, 500).applyTo(composite);
171                 
172                 Label label = new Label(composite, SWT.NONE);
173         label.setText("Position");
174                 Composite buttonComposite = new Composite(composite, SWT.NONE);
175             startButton = new Button(buttonComposite, SWT.TOGGLE);
176             middleButton = new Button(buttonComposite, SWT.TOGGLE);
177             endButton = new Button(buttonComposite, SWT.TOGGLE);
178         startButton.setImage(resourceManager.createImage(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/insert_start.png")));
179         middleButton.setImage(resourceManager.createImage(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/insert_middle.png")));
180         endButton.setImage(resourceManager.createImage(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/insert_end.png")));
181         GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(buttonComposite);
182         GridLayoutFactory.fillDefaults().numColumns(3).applyTo(buttonComposite);
183                 
184         startButton.setEnabled(false);
185         middleButton.setEnabled(false);
186         endButton.setEnabled(false);
187         
188         startButton.addSelectionListener(new SelectionAdapter() {
189             @Override
190             public void widgetSelected(SelectionEvent e) {
191                 updateInsertPosition(PositionType.PREVIOUS);
192             }
193         });
194         
195         middleButton.addSelectionListener(new SelectionAdapter() {
196             @Override
197             public void widgetSelected(SelectionEvent e) {
198                 updateInsertPosition(PositionType.SPLIT);
199             }
200         });
201         endButton.addSelectionListener(new SelectionAdapter() {
202             @Override
203             public void widgetSelected(SelectionEvent e) {
204                 updateInsertPosition(PositionType.NEXT);
205             }
206         });
207         endButton.setSelection(true);
208         
209                 label = new Label(composite, SWT.NONE);
210                 label.setText("Length");
211                 lengthText = new Text(composite, SWT.SINGLE|SWT.BORDER);
212                 label = new Label(composite, SWT.NONE);
213                 label.setText("Angle");
214                 angleText = new Text(composite, SWT.SINGLE|SWT.BORDER);
215                 
216                 label = new Label(composite, SWT.NONE);
217                 label.setText("Diameter");
218                 diameterText = new Text(composite, SWT.SINGLE|SWT.BORDER);
219                 label = new Label(composite, SWT.NONE);
220                 label.setText("Turn Radius");
221                 turnRadiusText = new Text(composite, SWT.SINGLE|SWT.BORDER);
222                 
223                 lengthText.setEnabled(false);
224                 angleText.setEnabled(false);
225                 turnRadiusText.setEnabled(false);
226                 diameterText.setEnabled(false);
227                 
228                 lengthText.addKeyListener(new KeyAdapter() {
229                         @Override
230                         public void keyReleased(KeyEvent e) {
231                                 try {
232                                         length = Double.parseDouble(lengthText.getText());
233                                 } catch (NumberFormatException err) {
234                                         length = null;
235                                 }
236                                 validate();
237                         }
238                 });
239                 
240                 angleText.addKeyListener(new KeyAdapter() {
241                         @Override
242                         public void keyReleased(KeyEvent e) {
243                                 try {
244                                         angle = Double.parseDouble(angleText.getText());
245                                 } catch (NumberFormatException err) {
246                                         angle = null;
247                                 }
248                                 validate();
249                         }
250                 });
251                 
252                 diameterText.addKeyListener(new KeyAdapter() {
253                         @Override
254                         public void keyReleased(KeyEvent e) {
255                                 try {
256                                         diameter = Double.parseDouble(diameterText.getText());
257                                 } catch (NumberFormatException err) {
258                                         diameter = null;
259                                 }
260                                 validate();
261                         }
262                 });
263                 
264                 turnRadiusText.addKeyListener(new KeyAdapter() {
265                         @Override
266                         public void keyReleased(KeyEvent e) {
267                                 try {
268                                         turnRadius = Double.parseDouble(turnRadiusText.getText());
269                                 } catch (NumberFormatException err) {
270                                         turnRadius = null;
271                                 }
272                                 validate();
273                         }
274                 });
275                 
276                 GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(lengthText);
277                 GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(angleText);
278                 GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(diameterText);
279                 GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(turnRadiusText);
280                 
281                 if (!allowed.contains(PositionType.NEXT) && !allowed.contains(PositionType.PREVIOUS)) {
282                         turnViewer.getList().setEnabled(false);
283                         endViewer.getList().setEnabled(false);
284                         inlineSplit = true;
285                 }
286                 
287                 return composite;
288         }
289         
290         
291         private void updateInsertPosition(PositionType type) {
292             if (insertPosition == type)
293                 return;
294             endButton.setSelection(type == PositionType.NEXT);
295         middleButton.setSelection(type == PositionType.SPLIT);
296         startButton.setSelection(type == PositionType.PREVIOUS);
297             insertPosition = type;
298         }
299         
300         @Override
301         public void selectionChanged(SelectionChangedEvent event) {
302                 IStructuredSelection sel = (IStructuredSelection)event.getSelection();
303                 Item i = (Item)sel.getFirstElement();
304                 if (i != null) {
305                 selected = i;
306                 if (event.getSource() == inlineViewer) {
307                     turnViewer.setSelection(new StructuredSelection());
308                     endViewer.setSelection(new StructuredSelection());
309                 } else if (event.getSource() == turnViewer) {
310                     inlineViewer.setSelection(new StructuredSelection());
311                 endViewer.setSelection(new StructuredSelection());
312                 } else if (event.getSource() == endViewer) {
313                 inlineViewer.setSelection(new StructuredSelection());
314                 turnViewer.setSelection(new StructuredSelection());
315             }
316                 validate();     
317                 }
318         }
319         
320         private void validate() {
321                 filterAllowed.clear();
322                 Set<PositionType> filterAllowed = new HashSet<PositionType>();
323                 boolean ok = true;
324                 if (selected == null) {
325                         ok = false;
326                 } else if (selected.isCode()) {// TODO : instead of disabling the button, we should filter the content.
327                         ok = false;
328                 } else {
329                     lenghtAdjustable = ((selected.getType() == Type.INLINE) && selected.isVariable());
330                     if (insertAdjustable) {
331                     switch (selected.getType()) {
332                     case END:
333                         startButton.setEnabled(false);
334                         middleButton.setEnabled(false);
335                         endButton.setEnabled(true);
336                         updateInsertPosition(PositionType.NEXT);
337                         break;
338                     case INLINE:
339                         if (!selected.isVariable()) {
340                             startButton.setEnabled(true);
341                         middleButton.setEnabled(true);
342                         endButton.setEnabled(true);
343                         } else {
344                             startButton.setEnabled(false);
345                         middleButton.setEnabled(false);
346                         endButton.setEnabled(true);
347                         updateInsertPosition(PositionType.NEXT);
348                         }
349                     break;
350                     case NOZZLE:
351                         startButton.setEnabled(false);
352                     middleButton.setEnabled(false);
353                     endButton.setEnabled(true);
354                     updateInsertPosition(PositionType.NEXT);
355                     break;
356                     case TURN:
357                         startButton.setEnabled(false);
358                     middleButton.setEnabled(true);
359                     endButton.setEnabled(true);
360                     if (insertPosition == PositionType.PREVIOUS)
361                         updateInsertPosition(PositionType.NEXT);
362                     break;
363                     case EQUIPMENT:
364                         throw new RuntimeException("Expected component, got equipment " + selected);
365                     }
366                     } else if (lenghtAdjustable) {
367                         if (component instanceof InlineComponent) {
368                             startButton.setEnabled(true);
369                     middleButton.setEnabled(true);
370                     endButton.setEnabled(true);
371                         } else if (component instanceof TurnComponent) {
372                             startButton.setEnabled(false);
373                     middleButton.setEnabled(true);
374                     endButton.setEnabled(true);
375                     if (insertPosition == PositionType.PREVIOUS)
376                         updateInsertPosition(PositionType.NEXT);
377                         } else if (component instanceof EndComponent || component instanceof Nozzle) {
378                             startButton.setEnabled(false);
379                     middleButton.setEnabled(false);
380                     endButton.setEnabled(true);
381                     updateInsertPosition(PositionType.NEXT);
382                         }
383                     } else {
384                         startButton.setEnabled(false);
385                 middleButton.setEnabled(false);
386                 endButton.setEnabled(true);
387                     }
388                     if (selected.isVariable()) {
389                                 if (selected.getType() == Type.INLINE) {
390                                         filterAllowed.add(PositionType.NEXT);
391                                         filterAllowed.add(PositionType.PREVIOUS);
392                                         if (inlineSplit) {
393                                                 lengthText.setEnabled(false);
394                                                 angleText.setEnabled(false);
395                                                 ok = false;
396                                                 
397                                         } else {
398                                                 lengthText.setEnabled(true);
399                                                 angleText.setEnabled(false);
400                                                 if (length == null)
401                                                         ok = false;
402                                         }
403                                 } else if (selected.getType() == Type.TURN) {
404                                         filterAllowed.add(PositionType.NEXT);
405                                         filterAllowed.add(PositionType.PREVIOUS);
406                                         lengthText.setEnabled(false);
407                                         angleText.setEnabled(true);
408                                         if (angle == null)
409                                                 ok = false;
410                                 } else {
411                                         // this should not happen
412                                         lengthText.setEnabled(false);
413                                         angleText.setEnabled(false);
414                                 }
415                         } else {
416                                 lengthText.setEnabled(false);
417                                 angleText.setEnabled(false);                    
418                         }
419                 
420                         if (selected.isSizeChange()) {
421                                 filterAllowed.add(PositionType.NEXT);
422                                 filterAllowed.add(PositionType.PREVIOUS);
423                                 if (inlineSplit) {
424                                         turnRadiusText.setEnabled(false);
425                                         diameterText.setEnabled(false);
426                                         ok = false;
427                                 } else {
428                                         turnRadiusText.setEnabled(true);
429                                         diameterText.setEnabled(true);
430                                         if (diameter == null || turnRadius == null)
431                                                 ok = false;
432                                 }
433                                 
434                         } else {
435                                 turnRadiusText.setEnabled(false);
436                                 diameterText.setEnabled(false);
437                         }
438                         
439                         if (!selected.isSizeChange() && !selected.isVariable()) {
440                                 switch (selected.getType()) {
441                                         case END:
442                                                 filterAllowed.add(PositionType.NEXT);
443                                                 filterAllowed.add(PositionType.PREVIOUS);
444                                                 break;
445                                         case NOZZLE:
446                                         case EQUIPMENT:
447                                                 break;
448                                         case INLINE:
449                                                 filterAllowed.add(PositionType.NEXT);
450                                                 filterAllowed.add(PositionType.PREVIOUS);
451                                                 filterAllowed.add(PositionType.SPLIT);
452                                         case TURN:
453                                                 filterAllowed.add(PositionType.NEXT);
454                                                 filterAllowed.add(PositionType.PREVIOUS);
455                                 }
456                         }
457                 }
458                 for (PositionType t : filterAllowed) {
459                         if (allowed.contains(t))
460                                 this.filterAllowed.add(t);
461                 }
462         
463                 getButton(OK).setEnabled(ok); 
464         }
465         
466         public Item getSelected() {
467                 return selected;
468         }
469         
470         public Double getAngle() {
471                 return angle;
472         }
473         
474         public Double getLength() {
475                 return length;
476         }
477         
478         public Double getDiameter() {
479                 return diameter;
480         }
481         
482         public Double getTurnRadius() {
483                 return turnRadius;
484         }
485         
486         public Set<PositionType> filterAllowed() {
487                 return filterAllowed;
488         }
489         
490         public PositionType getInsertPosition() {
491         return insertPosition;
492     }
493         
494         public boolean isInsertAdjustable() {
495         return insertAdjustable;
496     }
497         
498         public boolean isLenghtAdjustable() {
499         return lenghtAdjustable;
500     }
501
502 }