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 thickness;
92 private Double turnRadius;
94 private Text diameterText;
95 private Text thicknessText;
96 private Text turnRadiusText;
99 private Button startButton;
100 private Button middleButton;
101 private Button endButton;
103 private boolean inlineSplit = false;
105 ListViewer inlineViewer;
106 ListViewer turnViewer;
107 ListViewer endViewer;
109 private Set<String> usedNames;
111 public ComponentSelectionDialog(Shell parentShell, Set<PositionType> allowed, PipelineComponent component) {
112 this(parentShell, allowed, component, Plant3D.URIs.Builtin);
115 public ComponentSelectionDialog(Shell parentShell, Set<PositionType> allowed, PipelineComponent component,
118 this.allowed = allowed;
119 this.component = component;
120 filterAllowed = new HashSet<PositionType>();
121 insertAdjustable = component instanceof InlineComponent ? ((InlineComponent) component).isVariableLength()
123 lenghtAdjustable = false;
124 this.libUri = libUri;
126 usedNames = new HashSet<>();
128 setShellStyle(getShellStyle() | SWT.RESIZE);
130 IDialogSettings settings = Activator.getDefault().getDialogSettings();
131 dialogSettings = settings.getSection(DIALOG);
132 if (dialogSettings == null)
133 dialogSettings = settings.addNewSection(DIALOG);
136 public void setLengthFactor(double lengthFactor) {
137 this.lengthFactor = lengthFactor;
141 protected IDialogSettings getDialogBoundsSettings() {
142 return dialogSettings;
146 protected void configureShell(Shell newShell) {
147 super.configureShell(newShell);
148 newShell.setText("Create pipeline component");
151 public void addUsedNames(Collection<String> names) {
152 usedNames.addAll(names);
155 protected List<Item> getItems(Class<?> c, String libUri) throws DatabaseException {
156 Session session = Simantics.getSession();
157 if (InlineComponent.class.equals(c)) {
158 return P3DUtil.getInlines(session, libUri);
159 } else if (TurnComponent.class.equals(c)) {
160 return P3DUtil.getTurns(session, libUri);
161 } else if (EndComponent.class.equals(c)) {
162 return P3DUtil.getEnds(session, libUri);
169 protected Control createDialogArea(Composite parent) {
170 resourceManager = new LocalResourceManager(JFaceResources.getResources(), parent);
172 Composite composite = new Composite(parent, SWT.NONE);
173 GridLayout layout = new GridLayout(2, false);
174 layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
175 layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
176 layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
177 layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
178 composite.setLayout(layout);
179 composite.setLayoutData(new GridData(GridData.FILL_BOTH));
180 applyDialogFont(composite);
182 // Grid layout data for fields that grab horizontal space
183 final GridDataFactory horizFillData = GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.TOP);
185 // TODO : we need better classification than inline,turn, and end:
186 // * fixed length inlines
187 // * fixed angle turns
188 // * size changes (requires input for pipe run specs)
189 // * variable length inlines (input for length)
190 // * variable angle turns (input for angle)
193 List<Item> ends = null;
194 List<Item> turns = null;
195 List<Item> inlines = null;
197 ends = getItems(EndComponent.class, libUri);
198 turns = getItems(TurnComponent.class, libUri);
199 inlines = getItems(InlineComponent.class, libUri);
200 } catch (DatabaseException e) {
201 Label label = new Label(composite, SWT.NONE);
202 label.setText("Cannot load pipeline components: " + e.getMessage());
203 ExceptionUtils.logError(e);
206 ends = P3DUtil.filterUserComponents(ends);
207 turns = P3DUtil.filterUserComponents(turns);
208 inlines = P3DUtil.filterUserComponents(inlines);
210 ExpandBar expandBar = new ExpandBar(composite, SWT.V_SCROLL);
212 ExpandItem inlineItem = new ExpandItem(expandBar, SWT.NONE);
213 inlineItem.setText("Inline");
214 inlineViewer = new ListViewer(expandBar);
215 inlineViewer.setLabelProvider(new ComponentLabelProvider());
216 inlineViewer.setContentProvider(new ComponentContentProvider());
218 ExpandItem turnItem = new ExpandItem(expandBar, SWT.NONE);
219 turnItem.setText("Turn");
220 turnViewer = new ListViewer(expandBar);
221 turnViewer.setLabelProvider(new ComponentLabelProvider());
222 turnViewer.setContentProvider(new ComponentContentProvider());
224 ExpandItem endItem = new ExpandItem(expandBar, SWT.NONE);
225 endItem.setText("End");
226 endViewer = new ListViewer(expandBar);
227 endViewer.setLabelProvider(new ComponentLabelProvider());
228 endViewer.setContentProvider(new ComponentContentProvider());
230 inlineItem.setControl(inlineViewer.getList());
231 turnItem.setControl(turnViewer.getList());
232 endItem.setControl(endViewer.getList());
234 inlineViewer.setInput(inlines);
235 turnViewer.setInput(turns);
236 endViewer.setInput(ends);
238 inlineItem.setHeight(inlineViewer.getList().computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
239 turnItem.setHeight(turnViewer.getList().computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
240 endItem.setHeight(endViewer.getList().computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
242 inlineViewer.addSelectionChangedListener(this);
243 turnViewer.addSelectionChangedListener(this);
244 endViewer.addSelectionChangedListener(this);
246 GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).span(2, 1).applyTo(expandBar);
247 GridDataFactory.fillDefaults().grab(true, true).minSize(500, 500).hint(500, 500).applyTo(composite);
249 Label label = new Label(composite, SWT.NONE);
250 label.setText("Position");
251 Composite buttonComposite = new Composite(composite, SWT.NONE);
252 startButton = new Button(buttonComposite, SWT.TOGGLE);
253 middleButton = new Button(buttonComposite, SWT.TOGGLE);
254 endButton = new Button(buttonComposite, SWT.TOGGLE);
255 startButton.setImage(resourceManager.createImage(
256 ResourceLocator.imageDescriptorFromBundle(Activator.PLUGIN_ID, "icons/insert_start.png").get()));
257 middleButton.setImage(resourceManager.createImage(
258 ResourceLocator.imageDescriptorFromBundle(Activator.PLUGIN_ID, "icons/insert_middle.png").get()));
259 endButton.setImage(resourceManager.createImage(
260 ResourceLocator.imageDescriptorFromBundle(Activator.PLUGIN_ID, "icons/insert_end.png").get()));
261 startButton.setToolTipText("Overlapping insert");
262 middleButton.setToolTipText("Cutting insert");
263 endButton.setToolTipText("Adding insert");
264 horizFillData.applyTo(buttonComposite);
265 GridLayoutFactory.fillDefaults().numColumns(3).applyTo(buttonComposite);
267 startButton.setEnabled(false);
268 middleButton.setEnabled(false);
269 endButton.setEnabled(false);
271 startButton.addSelectionListener(new SelectionAdapter() {
273 public void widgetSelected(SelectionEvent e) {
274 updateInsertPosition(PositionType.PREVIOUS);
278 middleButton.addSelectionListener(new SelectionAdapter() {
280 public void widgetSelected(SelectionEvent e) {
281 updateInsertPosition(PositionType.SPLIT);
284 endButton.addSelectionListener(new SelectionAdapter() {
286 public void widgetSelected(SelectionEvent e) {
287 updateInsertPosition(PositionType.NEXT);
290 endButton.setSelection(true);
292 label = new Label(composite, SWT.NONE);
293 label.setText("Name");
294 nameText = new Text(composite, SWT.SINGLE | SWT.BORDER);
296 label = new Label(composite, SWT.NONE);
297 label.setText("Length");
298 lengthText = new Text(composite, SWT.SINGLE | SWT.BORDER);
299 label = new Label(composite, SWT.NONE);
300 label.setText("Angle");
301 angleText = new Text(composite, SWT.SINGLE | SWT.BORDER);
302 label = new Label(composite, SWT.NONE);
303 label.setText("Rotation angle");
304 rotationAngleText = new Text(composite, SWT.SINGLE | SWT.BORDER);
306 label = new Label(composite, SWT.NONE);
307 label.setText("Diameter");
308 diameterText = new Text(composite, SWT.SINGLE | SWT.BORDER);
309 label = new Label(composite, SWT.NONE);
310 label.setText("Wall thickness");
311 thicknessText = new Text(composite, SWT.SINGLE | SWT.BORDER);
312 label = new Label(composite, SWT.NONE);
313 label.setText("Turn radius");
314 turnRadiusText = new Text(composite, SWT.SINGLE | SWT.BORDER);
316 lengthText.setEnabled(false);
317 angleText.setEnabled(false);
318 rotationAngleText.setEnabled(false);
319 turnRadiusText.setEnabled(false);
320 diameterText.setEnabled(false);
321 thicknessText.setEnabled(false);
323 nameText.addKeyListener(new KeyAdapter() {
325 public void keyReleased(KeyEvent e) {
326 name = nameText.getText();
331 lengthText.addKeyListener(new KeyAdapter() {
333 public void keyReleased(KeyEvent e) {
335 length = Double.parseDouble(lengthText.getText()) / lengthFactor;
336 } catch (NumberFormatException err) {
343 angleText.addKeyListener(new KeyAdapter() {
345 public void keyReleased(KeyEvent e) {
347 angle = Double.parseDouble(angleText.getText());
348 } catch (NumberFormatException err) {
355 rotationAngleText.addKeyListener(new KeyAdapter() {
357 public void keyReleased(KeyEvent e) {
359 rotationAngle = Double.parseDouble(rotationAngleText.getText());
360 } catch (NumberFormatException err) {
361 rotationAngle = null;
367 diameterText.addKeyListener(new KeyAdapter() {
369 public void keyReleased(KeyEvent e) {
371 diameter = Double.parseDouble(diameterText.getText()) / lengthFactor;
372 } catch (NumberFormatException err) {
379 thicknessText.addKeyListener(new KeyAdapter() {
381 public void keyReleased(KeyEvent e) {
383 thickness = Double.parseDouble(thicknessText.getText()) / lengthFactor;
384 } catch (NumberFormatException err) {
391 turnRadiusText.addKeyListener(new KeyAdapter() {
393 public void keyReleased(KeyEvent e) {
395 turnRadius = Double.parseDouble(turnRadiusText.getText()) / lengthFactor;
396 } catch (NumberFormatException err) {
403 horizFillData.applyTo(nameText);
404 horizFillData.applyTo(lengthText);
405 horizFillData.applyTo(angleText);
406 horizFillData.applyTo(rotationAngleText);
407 horizFillData.applyTo(diameterText);
408 horizFillData.applyTo(thicknessText);
409 horizFillData.applyTo(turnRadiusText);
411 if (!allowed.contains(PositionType.NEXT) && !allowed.contains(PositionType.PREVIOUS)) {
412 turnViewer.getList().setEnabled(false);
413 endViewer.getList().setEnabled(false);
420 private void updateInsertPosition(PositionType type) {
421 if (insertPosition == type)
423 endButton.setSelection(type == PositionType.NEXT);
424 middleButton.setSelection(type == PositionType.SPLIT);
425 startButton.setSelection(type == PositionType.PREVIOUS);
426 insertPosition = type;
430 public void selectionChanged(SelectionChangedEvent event) {
431 IStructuredSelection sel = (IStructuredSelection) event.getSelection();
432 Item i = (Item) sel.getFirstElement();
435 if (event.getSource() == inlineViewer) {
436 turnViewer.setSelection(new StructuredSelection());
437 endViewer.setSelection(new StructuredSelection());
438 } else if (event.getSource() == turnViewer) {
439 inlineViewer.setSelection(new StructuredSelection());
440 endViewer.setSelection(new StructuredSelection());
441 } else if (event.getSource() == endViewer) {
442 inlineViewer.setSelection(new StructuredSelection());
443 turnViewer.setSelection(new StructuredSelection());
446 name = generateUniqueName(selected.getName());
447 nameText.setText(name);
453 private void validate() {
454 filterAllowed.clear();
455 Set<PositionType> filterAllowed = new HashSet<PositionType>();
457 if (selected == null) {
459 } else if (selected.isCode()) {// TODO : instead of disabling the button, we should filter the content.
462 lenghtAdjustable = ((selected.getType() == Type.INLINE)
463 && (selected.isVariable() || selected.isModifiable()));
464 if (insertAdjustable) {
465 switch (selected.getType()) {
467 startButton.setEnabled(false);
468 middleButton.setEnabled(false);
469 endButton.setEnabled(true);
470 updateInsertPosition(PositionType.NEXT);
473 if (!selected.isVariable()) {
474 startButton.setEnabled(true);
475 middleButton.setEnabled(true);
476 endButton.setEnabled(true);
478 startButton.setEnabled(false);
479 middleButton.setEnabled(false);
480 endButton.setEnabled(true);
481 updateInsertPosition(PositionType.NEXT);
485 startButton.setEnabled(false);
486 middleButton.setEnabled(false);
487 endButton.setEnabled(true);
488 updateInsertPosition(PositionType.NEXT);
491 startButton.setEnabled(false);
492 middleButton.setEnabled(true);
493 endButton.setEnabled(true);
494 if (insertPosition == PositionType.PREVIOUS)
495 updateInsertPosition(PositionType.NEXT);
498 throw new RuntimeException("Expected component, got equipment " + selected);
500 } else if (lenghtAdjustable) {
501 if (component instanceof InlineComponent) {
502 startButton.setEnabled(true);
503 middleButton.setEnabled(true);
504 endButton.setEnabled(true);
505 } else if (component instanceof TurnComponent) {
506 startButton.setEnabled(false);
507 middleButton.setEnabled(true);
508 endButton.setEnabled(true);
509 if (insertPosition == PositionType.PREVIOUS)
510 updateInsertPosition(PositionType.NEXT);
511 } else if (component instanceof EndComponent || component instanceof Nozzle) {
512 startButton.setEnabled(false);
513 middleButton.setEnabled(false);
514 endButton.setEnabled(true);
515 updateInsertPosition(PositionType.NEXT);
518 startButton.setEnabled(false);
519 middleButton.setEnabled(false);
520 endButton.setEnabled(true);
522 if (selected.isVariable() || selected.isModifiable()) {
523 if (selected.getType() == Type.INLINE) {
524 filterAllowed.add(PositionType.NEXT);
525 filterAllowed.add(PositionType.PREVIOUS);
526 if (inlineSplit && selected.isVariable()) {
527 lengthText.setEnabled(false);
528 angleText.setEnabled(false);
529 rotationAngleText.setEnabled(selected.isRotated());
533 lengthText.setEnabled(true);
534 angleText.setEnabled(false);
535 rotationAngleText.setEnabled(selected.isRotated());
539 } else if (selected.getType() == Type.TURN) {
540 filterAllowed.add(PositionType.NEXT);
541 filterAllowed.add(PositionType.PREVIOUS);
542 lengthText.setEnabled(false);
543 angleText.setEnabled(true);
544 rotationAngleText.setEnabled(true);
548 // this should not happen, since end components should not have variable, or
550 lengthText.setEnabled(false);
551 angleText.setEnabled(false);
552 rotationAngleText.setEnabled(false);
556 lengthText.setEnabled(false);
557 angleText.setEnabled(false);
558 rotationAngleText.setEnabled(selected.getType() == Type.TURN || selected.isRotated());
561 if (selected.isSizeChange()) {
562 turnRadiusText.setEnabled(true);
563 diameterText.setEnabled(true);
564 thicknessText.setEnabled(true);
565 if (diameter == null || turnRadius == null || thickness == null)
568 turnRadiusText.setEnabled(false);
569 diameterText.setEnabled(false);
572 if (!selected.isVariable()) {
573 switch (selected.getType()) {
575 filterAllowed.add(PositionType.NEXT);
576 filterAllowed.add(PositionType.PREVIOUS);
582 filterAllowed.add(PositionType.NEXT);
583 filterAllowed.add(PositionType.PREVIOUS);
584 filterAllowed.add(PositionType.SPLIT);
586 filterAllowed.add(PositionType.NEXT);
587 filterAllowed.add(PositionType.PREVIOUS);
591 for (PositionType t : filterAllowed) {
592 if (allowed.contains(t))
593 this.filterAllowed.add(t);
596 if (name.isEmpty() || usedNames.contains(name))
599 getButton(OK).setEnabled(ok);
602 private String generateUniqueName(String name) {
605 while (usedNames.contains((newName = name + "_" + i)))
610 public Item getSelected() {
614 public String getName() {
618 public Double getAngle() {
622 public Double getLength() {
626 public Double getRotationAngle() {
627 return rotationAngle;
630 public Double getDiameter() {
634 public Double getTurnRadius() {
638 public Set<PositionType> filterAllowed() {
639 return filterAllowed;
642 public PositionType getInsertPosition() {
643 return insertPosition;
646 public boolean isInsertAdjustable() {
647 return insertAdjustable;
650 public boolean isLenghtAdjustable() {
651 return lenghtAdjustable;
654 public Double getThickness() {