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