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