1 package org.simantics.plant3d.dialog;
3 import java.util.Collection;
4 import java.util.HashSet;
8 import org.eclipse.jface.dialogs.Dialog;
9 import org.eclipse.jface.dialogs.IDialogConstants;
10 import org.eclipse.jface.dialogs.IDialogSettings;
11 import org.eclipse.jface.layout.GridDataFactory;
12 import org.eclipse.jface.layout.GridLayoutFactory;
13 import org.eclipse.jface.resource.JFaceResources;
14 import org.eclipse.jface.resource.LocalResourceManager;
15 import org.eclipse.jface.resource.ResourceLocator;
16 import org.eclipse.jface.resource.ResourceManager;
17 import org.eclipse.jface.viewers.ISelectionChangedListener;
18 import org.eclipse.jface.viewers.IStructuredSelection;
19 import org.eclipse.jface.viewers.ListViewer;
20 import org.eclipse.jface.viewers.SelectionChangedEvent;
21 import org.eclipse.jface.viewers.StructuredSelection;
22 import org.eclipse.swt.SWT;
23 import org.eclipse.swt.events.KeyAdapter;
24 import org.eclipse.swt.events.KeyEvent;
25 import org.eclipse.swt.events.SelectionAdapter;
26 import org.eclipse.swt.events.SelectionEvent;
27 import org.eclipse.swt.layout.GridData;
28 import org.eclipse.swt.layout.GridLayout;
29 import org.eclipse.swt.widgets.Button;
30 import org.eclipse.swt.widgets.Composite;
31 import org.eclipse.swt.widgets.Control;
32 import org.eclipse.swt.widgets.ExpandBar;
33 import org.eclipse.swt.widgets.ExpandItem;
34 import org.eclipse.swt.widgets.Label;
35 import org.eclipse.swt.widgets.Shell;
36 import org.eclipse.swt.widgets.Text;
37 import org.simantics.Simantics;
38 import org.simantics.db.Session;
39 import org.simantics.db.exception.DatabaseException;
40 import org.simantics.plant3d.Activator;
41 import org.simantics.plant3d.ontology.Plant3D;
42 import org.simantics.plant3d.scenegraph.EndComponent;
43 import org.simantics.plant3d.scenegraph.InlineComponent;
44 import org.simantics.plant3d.scenegraph.Nozzle;
45 import org.simantics.plant3d.scenegraph.PipelineComponent;
46 import org.simantics.plant3d.scenegraph.TurnComponent;
47 import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint.PositionType;
48 import org.simantics.plant3d.utils.Item;
49 import org.simantics.plant3d.utils.Item.Type;
50 import org.simantics.plant3d.utils.P3DUtil;
51 import org.simantics.utils.ui.ExceptionUtils;
53 public class ComponentSelectionDialog extends Dialog implements ISelectionChangedListener {
55 private static final String DIALOG = "ComponentSelectionDialog"; //$NON-NLS-1$
57 private IDialogSettings dialogSettings;
59 private double lengthFactor = 1.0;
61 private ResourceManager resourceManager;
63 private String libUri;
65 private Item selected;
66 private Set<PositionType> allowed;
67 private Set<PositionType> filterAllowed;
68 // private boolean positionAdjustment;
69 private PipelineComponent component;
70 private boolean insertAdjustable;
71 private boolean lenghtAdjustable;
72 private PositionType insertPosition = PositionType.NEXT;
75 private Double length;
76 private Double rotationAngle;
80 private Text nameText;
83 private Text lengthText;
85 private Text angleText;
86 // Rotated In-line, or turn component.
87 private Text rotationAngleText;
89 // Input for new PipeRun
90 private Double diameter;
91 private Double turnRadius;
93 private Text diameterText;
94 private Text turnRadiusText;
97 private Button startButton;
98 private Button middleButton;
99 private Button endButton;
101 private boolean inlineSplit = false;
103 ListViewer inlineViewer;
104 ListViewer turnViewer;
105 ListViewer endViewer;
107 private Set<String> usedNames;
109 public ComponentSelectionDialog(Shell parentShell, Set<PositionType> allowed, PipelineComponent component) {
110 this(parentShell, allowed, component, Plant3D.URIs.Builtin);
113 public ComponentSelectionDialog(Shell parentShell, Set<PositionType> allowed, PipelineComponent component,
116 this.allowed = allowed;
117 this.component = component;
118 filterAllowed = new HashSet<PositionType>();
119 insertAdjustable = component instanceof InlineComponent ? ((InlineComponent) component).isVariableLength()
121 lenghtAdjustable = false;
122 this.libUri = libUri;
124 usedNames = new HashSet<>();
126 setShellStyle(getShellStyle() | SWT.RESIZE);
128 IDialogSettings settings = Activator.getDefault().getDialogSettings();
129 dialogSettings = settings.getSection(DIALOG);
130 if (dialogSettings == null)
131 dialogSettings = settings.addNewSection(DIALOG);
134 public void setLengthFactor(double lengthFactor) {
135 this.lengthFactor = lengthFactor;
139 protected IDialogSettings getDialogBoundsSettings() {
140 return dialogSettings;
144 protected void configureShell(Shell newShell) {
145 super.configureShell(newShell);
146 newShell.setText("Create pipeline component");
149 public void addUsedNames(Collection<String> names) {
150 usedNames.addAll(names);
153 protected List<Item> getItems(Class<?> c, String libUri) throws DatabaseException {
154 Session session = Simantics.getSession();
155 if (InlineComponent.class.equals(c)) {
156 return P3DUtil.getInlines(session, libUri);
157 } else if (TurnComponent.class.equals(c)) {
158 return P3DUtil.getTurns(session, libUri);
159 } else if (EndComponent.class.equals(c)) {
160 return P3DUtil.getEnds(session, libUri);
167 protected Control createDialogArea(Composite parent) {
168 resourceManager = new LocalResourceManager(JFaceResources.getResources(), parent);
170 Composite composite = new Composite(parent, SWT.NONE);
171 GridLayout layout = new GridLayout(2, false);
172 layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
173 layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
174 layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
175 layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
176 composite.setLayout(layout);
177 composite.setLayoutData(new GridData(GridData.FILL_BOTH));
178 applyDialogFont(composite);
180 // Grid layout data for fields that grab horizontal space
181 final GridDataFactory horizFillData = GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.TOP);
183 // TODO : we need better classification than inline,turn, and end:
184 // * fixed length inlines
185 // * fixed angle turns
186 // * size changes (requires input for pipe run specs)
187 // * variable length inlines (input for length)
188 // * variable angle turns (input for angle)
191 List<Item> ends = null;
192 List<Item> turns = null;
193 List<Item> inlines = null;
195 ends = getItems(EndComponent.class, libUri);
196 turns = getItems(TurnComponent.class, libUri);
197 inlines = getItems(InlineComponent.class, libUri);
198 } catch (DatabaseException e) {
199 Label label = new Label(composite, SWT.NONE);
200 label.setText("Cannot load pipeline components: " + e.getMessage());
201 ExceptionUtils.logError(e);
204 ends = P3DUtil.filterUserComponents(ends);
205 turns = P3DUtil.filterUserComponents(turns);
206 inlines = P3DUtil.filterUserComponents(inlines);
208 ExpandBar expandBar = new ExpandBar(composite, SWT.V_SCROLL);
210 ExpandItem inlineItem = new ExpandItem(expandBar, SWT.NONE);
211 inlineItem.setText("Inline");
212 inlineViewer = new ListViewer(expandBar);
213 inlineViewer.setLabelProvider(new ComponentLabelProvider());
214 inlineViewer.setContentProvider(new ComponentContentProvider());
216 ExpandItem turnItem = new ExpandItem(expandBar, SWT.NONE);
217 turnItem.setText("Turn");
218 turnViewer = new ListViewer(expandBar);
219 turnViewer.setLabelProvider(new ComponentLabelProvider());
220 turnViewer.setContentProvider(new ComponentContentProvider());
222 ExpandItem endItem = new ExpandItem(expandBar, SWT.NONE);
223 endItem.setText("End");
224 endViewer = new ListViewer(expandBar);
225 endViewer.setLabelProvider(new ComponentLabelProvider());
226 endViewer.setContentProvider(new ComponentContentProvider());
228 inlineItem.setControl(inlineViewer.getList());
229 turnItem.setControl(turnViewer.getList());
230 endItem.setControl(endViewer.getList());
232 inlineViewer.setInput(inlines);
233 turnViewer.setInput(turns);
234 endViewer.setInput(ends);
236 inlineItem.setHeight(inlineViewer.getList().computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
237 turnItem.setHeight(turnViewer.getList().computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
238 endItem.setHeight(endViewer.getList().computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
240 inlineViewer.addSelectionChangedListener(this);
241 turnViewer.addSelectionChangedListener(this);
242 endViewer.addSelectionChangedListener(this);
244 GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).span(2, 1).applyTo(expandBar);
245 GridDataFactory.fillDefaults().grab(true, true).minSize(500, 500).hint(500, 500).applyTo(composite);
247 Label label = new Label(composite, SWT.NONE);
248 label.setText("Position");
249 Composite buttonComposite = new Composite(composite, SWT.NONE);
250 startButton = new Button(buttonComposite, SWT.TOGGLE);
251 middleButton = new Button(buttonComposite, SWT.TOGGLE);
252 endButton = new Button(buttonComposite, SWT.TOGGLE);
253 startButton.setImage(resourceManager.createImage(
254 ResourceLocator.imageDescriptorFromBundle(Activator.PLUGIN_ID, "icons/insert_start.png").get()));
255 middleButton.setImage(resourceManager.createImage(
256 ResourceLocator.imageDescriptorFromBundle(Activator.PLUGIN_ID, "icons/insert_middle.png").get()));
257 endButton.setImage(resourceManager.createImage(
258 ResourceLocator.imageDescriptorFromBundle(Activator.PLUGIN_ID, "icons/insert_end.png").get()));
259 startButton.setToolTipText("Overlapping insert");
260 middleButton.setToolTipText("Cutting insert");
261 endButton.setToolTipText("Adding insert");
262 horizFillData.applyTo(buttonComposite);
263 GridLayoutFactory.fillDefaults().numColumns(3).applyTo(buttonComposite);
265 startButton.setEnabled(false);
266 middleButton.setEnabled(false);
267 endButton.setEnabled(false);
269 startButton.addSelectionListener(new SelectionAdapter() {
271 public void widgetSelected(SelectionEvent e) {
272 updateInsertPosition(PositionType.PREVIOUS);
276 middleButton.addSelectionListener(new SelectionAdapter() {
278 public void widgetSelected(SelectionEvent e) {
279 updateInsertPosition(PositionType.SPLIT);
282 endButton.addSelectionListener(new SelectionAdapter() {
284 public void widgetSelected(SelectionEvent e) {
285 updateInsertPosition(PositionType.NEXT);
288 endButton.setSelection(true);
290 label = new Label(composite, SWT.NONE);
291 label.setText("Name");
292 nameText = new Text(composite, SWT.SINGLE | SWT.BORDER);
294 label = new Label(composite, SWT.NONE);
295 label.setText("Length");
296 lengthText = new Text(composite, SWT.SINGLE | SWT.BORDER);
297 label = new Label(composite, SWT.NONE);
298 label.setText("Angle");
299 angleText = new Text(composite, SWT.SINGLE | SWT.BORDER);
300 label = new Label(composite, SWT.NONE);
301 label.setText("Rotation angle");
302 rotationAngleText = new Text(composite, SWT.SINGLE | SWT.BORDER);
304 label = new Label(composite, SWT.NONE);
305 label.setText("Diameter");
306 diameterText = new Text(composite, SWT.SINGLE | SWT.BORDER);
307 label = new Label(composite, SWT.NONE);
308 label.setText("Turn Radius");
309 turnRadiusText = new Text(composite, SWT.SINGLE | SWT.BORDER);
311 lengthText.setEnabled(false);
312 angleText.setEnabled(false);
313 rotationAngleText.setEnabled(false);
314 turnRadiusText.setEnabled(false);
315 diameterText.setEnabled(false);
317 nameText.addKeyListener(new KeyAdapter() {
319 public void keyReleased(KeyEvent e) {
320 name = nameText.getText();
325 lengthText.addKeyListener(new KeyAdapter() {
327 public void keyReleased(KeyEvent e) {
329 length = Double.parseDouble(lengthText.getText()) / lengthFactor;
330 } catch (NumberFormatException err) {
337 angleText.addKeyListener(new KeyAdapter() {
339 public void keyReleased(KeyEvent e) {
341 angle = Double.parseDouble(angleText.getText());
342 } catch (NumberFormatException err) {
349 rotationAngleText.addKeyListener(new KeyAdapter() {
351 public void keyReleased(KeyEvent e) {
353 rotationAngle = Double.parseDouble(rotationAngleText.getText());
354 } catch (NumberFormatException err) {
355 rotationAngle = null;
361 diameterText.addKeyListener(new KeyAdapter() {
363 public void keyReleased(KeyEvent e) {
365 diameter = Double.parseDouble(diameterText.getText()) / lengthFactor;
366 } catch (NumberFormatException err) {
373 turnRadiusText.addKeyListener(new KeyAdapter() {
375 public void keyReleased(KeyEvent e) {
377 turnRadius = Double.parseDouble(turnRadiusText.getText()) / lengthFactor;
378 } catch (NumberFormatException err) {
385 horizFillData.applyTo(nameText);
386 horizFillData.applyTo(lengthText);
387 horizFillData.applyTo(angleText);
388 horizFillData.applyTo(rotationAngleText);
389 horizFillData.applyTo(diameterText);
390 horizFillData.applyTo(turnRadiusText);
392 if (!allowed.contains(PositionType.NEXT) && !allowed.contains(PositionType.PREVIOUS)) {
393 turnViewer.getList().setEnabled(false);
394 endViewer.getList().setEnabled(false);
401 private void updateInsertPosition(PositionType type) {
402 if (insertPosition == type)
404 endButton.setSelection(type == PositionType.NEXT);
405 middleButton.setSelection(type == PositionType.SPLIT);
406 startButton.setSelection(type == PositionType.PREVIOUS);
407 insertPosition = type;
411 public void selectionChanged(SelectionChangedEvent event) {
412 IStructuredSelection sel = (IStructuredSelection) event.getSelection();
413 Item i = (Item) sel.getFirstElement();
416 if (event.getSource() == inlineViewer) {
417 turnViewer.setSelection(new StructuredSelection());
418 endViewer.setSelection(new StructuredSelection());
419 } else if (event.getSource() == turnViewer) {
420 inlineViewer.setSelection(new StructuredSelection());
421 endViewer.setSelection(new StructuredSelection());
422 } else if (event.getSource() == endViewer) {
423 inlineViewer.setSelection(new StructuredSelection());
424 turnViewer.setSelection(new StructuredSelection());
427 name = generateUniqueName(selected.getName());
428 nameText.setText(name);
434 private void validate() {
435 filterAllowed.clear();
436 Set<PositionType> filterAllowed = new HashSet<PositionType>();
438 if (selected == null) {
440 } else if (selected.isCode()) {// TODO : instead of disabling the button, we should filter the content.
443 lenghtAdjustable = ((selected.getType() == Type.INLINE)
444 && (selected.isVariable() || selected.isModifiable()));
445 if (insertAdjustable) {
446 switch (selected.getType()) {
448 startButton.setEnabled(false);
449 middleButton.setEnabled(false);
450 endButton.setEnabled(true);
451 updateInsertPosition(PositionType.NEXT);
454 if (!selected.isVariable()) {
455 startButton.setEnabled(true);
456 middleButton.setEnabled(true);
457 endButton.setEnabled(true);
459 startButton.setEnabled(false);
460 middleButton.setEnabled(false);
461 endButton.setEnabled(true);
462 updateInsertPosition(PositionType.NEXT);
466 startButton.setEnabled(false);
467 middleButton.setEnabled(false);
468 endButton.setEnabled(true);
469 updateInsertPosition(PositionType.NEXT);
472 startButton.setEnabled(false);
473 middleButton.setEnabled(true);
474 endButton.setEnabled(true);
475 if (insertPosition == PositionType.PREVIOUS)
476 updateInsertPosition(PositionType.NEXT);
479 throw new RuntimeException("Expected component, got equipment " + selected);
481 } else if (lenghtAdjustable) {
482 if (component instanceof InlineComponent) {
483 startButton.setEnabled(true);
484 middleButton.setEnabled(true);
485 endButton.setEnabled(true);
486 } else if (component instanceof TurnComponent) {
487 startButton.setEnabled(false);
488 middleButton.setEnabled(true);
489 endButton.setEnabled(true);
490 if (insertPosition == PositionType.PREVIOUS)
491 updateInsertPosition(PositionType.NEXT);
492 } else if (component instanceof EndComponent || component instanceof Nozzle) {
493 startButton.setEnabled(false);
494 middleButton.setEnabled(false);
495 endButton.setEnabled(true);
496 updateInsertPosition(PositionType.NEXT);
499 startButton.setEnabled(false);
500 middleButton.setEnabled(false);
501 endButton.setEnabled(true);
503 if (selected.isVariable() || selected.isModifiable()) {
504 if (selected.getType() == Type.INLINE) {
505 filterAllowed.add(PositionType.NEXT);
506 filterAllowed.add(PositionType.PREVIOUS);
507 if (inlineSplit && selected.isVariable()) {
508 lengthText.setEnabled(false);
509 angleText.setEnabled(false);
510 rotationAngleText.setEnabled(selected.isRotated());
514 lengthText.setEnabled(true);
515 angleText.setEnabled(false);
516 rotationAngleText.setEnabled(selected.isRotated());
520 } else if (selected.getType() == Type.TURN) {
521 filterAllowed.add(PositionType.NEXT);
522 filterAllowed.add(PositionType.PREVIOUS);
523 lengthText.setEnabled(false);
524 angleText.setEnabled(true);
525 rotationAngleText.setEnabled(true);
529 // this should not happen, since end components should not have variable, or
531 lengthText.setEnabled(false);
532 angleText.setEnabled(false);
533 rotationAngleText.setEnabled(false);
537 lengthText.setEnabled(false);
538 angleText.setEnabled(false);
539 rotationAngleText.setEnabled(selected.getType() == Type.TURN || selected.isRotated());
542 if (selected.isSizeChange()) {
543 turnRadiusText.setEnabled(true);
544 diameterText.setEnabled(true);
545 if (diameter == null || turnRadius == null)
548 turnRadiusText.setEnabled(false);
549 diameterText.setEnabled(false);
552 if (!selected.isVariable()) {
553 switch (selected.getType()) {
555 filterAllowed.add(PositionType.NEXT);
556 filterAllowed.add(PositionType.PREVIOUS);
562 filterAllowed.add(PositionType.NEXT);
563 filterAllowed.add(PositionType.PREVIOUS);
564 filterAllowed.add(PositionType.SPLIT);
566 filterAllowed.add(PositionType.NEXT);
567 filterAllowed.add(PositionType.PREVIOUS);
571 for (PositionType t : filterAllowed) {
572 if (allowed.contains(t))
573 this.filterAllowed.add(t);
576 if (name.isEmpty() || usedNames.contains(name))
579 getButton(OK).setEnabled(ok);
582 private String generateUniqueName(String name) {
585 while (usedNames.contains((newName = name + "_" + i)))
590 public Item getSelected() {
594 public String getName() {
598 public Double getAngle() {
602 public Double getLength() {
606 public Double getRotationAngle() {
607 return rotationAngle;
610 public Double getDiameter() {
614 public Double getTurnRadius() {
618 public Set<PositionType> filterAllowed() {
619 return filterAllowed;
622 public PositionType getInsertPosition() {
623 return insertPosition;
626 public boolean isInsertAdjustable() {
627 return insertAdjustable;
630 public boolean isLenghtAdjustable() {
631 return lenghtAdjustable;