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.db.exception.DatabaseException;
38 import org.simantics.plant3d.Activator;
39 import org.simantics.plant3d.ontology.Plant3D;
40 import org.simantics.plant3d.scenegraph.EndComponent;
41 import org.simantics.plant3d.scenegraph.InlineComponent;
42 import org.simantics.plant3d.scenegraph.Nozzle;
43 import org.simantics.plant3d.scenegraph.PipelineComponent;
44 import org.simantics.plant3d.scenegraph.TurnComponent;
45 import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint.PositionType;
46 import org.simantics.plant3d.utils.Item;
47 import org.simantics.plant3d.utils.Item.Type;
48 import org.simantics.plant3d.utils.P3DUtil;
49 import org.simantics.utils.ui.ExceptionUtils;
51 public class ComponentSelectionDialog extends Dialog implements ISelectionChangedListener {
53 private static final String DIALOG = "ComponentSelectionDialog"; //$NON-NLS-1$
55 private IDialogSettings dialogSettings;
57 private double lengthFactor = 1.0;
59 private ResourceManager resourceManager;
61 private String libUri;
63 private Item selected;
64 private Set<PositionType> allowed;
65 private Set<PositionType> filterAllowed;
66 // private boolean positionAdjustment;
67 private PipelineComponent component;
68 private boolean insertAdjustable;
69 private boolean lenghtAdjustable;
70 private PositionType insertPosition = PositionType.NEXT;
73 private Double length;
74 private Double rotationAngle;
78 private Text nameText;
81 private Text lengthText;
83 private Text angleText;
84 // Rotated In-line, or turn component.
85 private Text rotationAngleText;
87 // Input for new PipeRun
88 private Double diameter;
89 private Double turnRadius;
91 private Text diameterText;
92 private Text turnRadiusText;
95 private Button startButton;
96 private Button middleButton;
97 private Button endButton;
99 private boolean inlineSplit = false;
101 ListViewer inlineViewer;
102 ListViewer turnViewer;
103 ListViewer endViewer;
105 private Set<String> usedNames;
107 public ComponentSelectionDialog(Shell parentShell, Set<PositionType> allowed, PipelineComponent component) {
108 this(parentShell, allowed, component, Plant3D.URIs.Builtin);
111 public ComponentSelectionDialog(Shell parentShell, Set<PositionType> allowed, PipelineComponent component,
114 this.allowed = allowed;
115 this.component = component;
116 filterAllowed = new HashSet<PositionType>();
117 insertAdjustable = component instanceof InlineComponent ? ((InlineComponent) component).isVariableLength()
119 lenghtAdjustable = false;
120 this.libUri = libUri;
122 usedNames = new HashSet<>();
124 setShellStyle(getShellStyle() | SWT.RESIZE);
126 IDialogSettings settings = Activator.getDefault().getDialogSettings();
127 dialogSettings = settings.getSection(DIALOG);
128 if (dialogSettings == null)
129 dialogSettings = settings.addNewSection(DIALOG);
132 public void setLengthFactor(double lengthFactor) {
133 this.lengthFactor = lengthFactor;
137 protected IDialogSettings getDialogBoundsSettings() {
138 return dialogSettings;
142 protected void configureShell(Shell newShell) {
143 super.configureShell(newShell);
144 newShell.setText("Create pipeline component");
147 public void addUsedNames(Collection<String> names) {
148 usedNames.addAll(names);
151 protected List<Item> getItems(Class<?> c, String libUri) throws DatabaseException {
152 if (InlineComponent.class.equals(c)) {
153 return P3DUtil.getInlines(libUri);
154 } else if (TurnComponent.class.equals(c)) {
155 return P3DUtil.getTurns(libUri);
156 } else if (EndComponent.class.equals(c)) {
157 return P3DUtil.getEnds(libUri);
164 protected Control createDialogArea(Composite parent) {
165 resourceManager = new LocalResourceManager(JFaceResources.getResources(), parent);
167 Composite composite = new Composite(parent, SWT.NONE);
168 GridLayout layout = new GridLayout(2, false);
169 layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
170 layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
171 layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
172 layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
173 composite.setLayout(layout);
174 composite.setLayoutData(new GridData(GridData.FILL_BOTH));
175 applyDialogFont(composite);
177 // Grid layout data for fields that grab horizontal space
178 final GridDataFactory horizFillData = GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.TOP);
180 // TODO : we need better classification than inline,turn, and end:
181 // * fixed length inlines
182 // * fixed angle turns
183 // * size changes (requires input for pipe run specs)
184 // * variable length inlines (input for length)
185 // * variable angle turns (input for angle)
188 List<Item> ends = null;
189 List<Item> turns = null;
190 List<Item> inlines = null;
192 ends = getItems(EndComponent.class, libUri);
193 turns = getItems(TurnComponent.class, libUri);
194 inlines = getItems(InlineComponent.class, libUri);
195 } catch (DatabaseException e) {
196 Label label = new Label(composite, SWT.NONE);
197 label.setText("Cannot load pipeline components: " + e.getMessage());
198 ExceptionUtils.logError(e);
201 ends = P3DUtil.filterUserComponents(ends);
202 turns = P3DUtil.filterUserComponents(turns);
203 inlines = P3DUtil.filterUserComponents(inlines);
205 ExpandBar expandBar = new ExpandBar(composite, SWT.V_SCROLL);
207 ExpandItem inlineItem = new ExpandItem(expandBar, SWT.NONE);
208 inlineItem.setText("Inline");
209 inlineViewer = new ListViewer(expandBar);
210 inlineViewer.setLabelProvider(new ComponentLabelProvider());
211 inlineViewer.setContentProvider(new ComponentContentProvider());
213 ExpandItem turnItem = new ExpandItem(expandBar, SWT.NONE);
214 turnItem.setText("Turn");
215 turnViewer = new ListViewer(expandBar);
216 turnViewer.setLabelProvider(new ComponentLabelProvider());
217 turnViewer.setContentProvider(new ComponentContentProvider());
219 ExpandItem endItem = new ExpandItem(expandBar, SWT.NONE);
220 endItem.setText("End");
221 endViewer = new ListViewer(expandBar);
222 endViewer.setLabelProvider(new ComponentLabelProvider());
223 endViewer.setContentProvider(new ComponentContentProvider());
225 inlineItem.setControl(inlineViewer.getList());
226 turnItem.setControl(turnViewer.getList());
227 endItem.setControl(endViewer.getList());
229 inlineViewer.setInput(inlines);
230 turnViewer.setInput(turns);
231 endViewer.setInput(ends);
233 inlineItem.setHeight(inlineViewer.getList().computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
234 turnItem.setHeight(turnViewer.getList().computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
235 endItem.setHeight(endViewer.getList().computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
237 inlineViewer.addSelectionChangedListener(this);
238 turnViewer.addSelectionChangedListener(this);
239 endViewer.addSelectionChangedListener(this);
241 GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).span(2, 1).applyTo(expandBar);
242 GridDataFactory.fillDefaults().grab(true, true).minSize(500, 500).hint(500, 500).applyTo(composite);
244 Label label = new Label(composite, SWT.NONE);
245 label.setText("Position");
246 Composite buttonComposite = new Composite(composite, SWT.NONE);
247 startButton = new Button(buttonComposite, SWT.TOGGLE);
248 middleButton = new Button(buttonComposite, SWT.TOGGLE);
249 endButton = new Button(buttonComposite, SWT.TOGGLE);
250 startButton.setImage(resourceManager.createImage(
251 ResourceLocator.imageDescriptorFromBundle(Activator.PLUGIN_ID, "icons/insert_start.png").get()));
252 middleButton.setImage(resourceManager.createImage(
253 ResourceLocator.imageDescriptorFromBundle(Activator.PLUGIN_ID, "icons/insert_middle.png").get()));
254 endButton.setImage(resourceManager.createImage(
255 ResourceLocator.imageDescriptorFromBundle(Activator.PLUGIN_ID, "icons/insert_end.png").get()));
256 startButton.setToolTipText("Overlapping insert");
257 middleButton.setToolTipText("Cutting insert");
258 endButton.setToolTipText("Adding insert");
259 horizFillData.applyTo(buttonComposite);
260 GridLayoutFactory.fillDefaults().numColumns(3).applyTo(buttonComposite);
262 startButton.setEnabled(false);
263 middleButton.setEnabled(false);
264 endButton.setEnabled(false);
266 startButton.addSelectionListener(new SelectionAdapter() {
268 public void widgetSelected(SelectionEvent e) {
269 updateInsertPosition(PositionType.PREVIOUS);
273 middleButton.addSelectionListener(new SelectionAdapter() {
275 public void widgetSelected(SelectionEvent e) {
276 updateInsertPosition(PositionType.SPLIT);
279 endButton.addSelectionListener(new SelectionAdapter() {
281 public void widgetSelected(SelectionEvent e) {
282 updateInsertPosition(PositionType.NEXT);
285 endButton.setSelection(true);
287 label = new Label(composite, SWT.NONE);
288 label.setText("Name");
289 nameText = new Text(composite, SWT.SINGLE | SWT.BORDER);
291 label = new Label(composite, SWT.NONE);
292 label.setText("Length");
293 lengthText = new Text(composite, SWT.SINGLE | SWT.BORDER);
294 label = new Label(composite, SWT.NONE);
295 label.setText("Angle");
296 angleText = new Text(composite, SWT.SINGLE | SWT.BORDER);
297 label = new Label(composite, SWT.NONE);
298 label.setText("Rotation angle");
299 rotationAngleText = new Text(composite, SWT.SINGLE | SWT.BORDER);
301 label = new Label(composite, SWT.NONE);
302 label.setText("Diameter");
303 diameterText = new Text(composite, SWT.SINGLE | SWT.BORDER);
304 label = new Label(composite, SWT.NONE);
305 label.setText("Turn Radius");
306 turnRadiusText = new Text(composite, SWT.SINGLE | SWT.BORDER);
308 lengthText.setEnabled(false);
309 angleText.setEnabled(false);
310 rotationAngleText.setEnabled(false);
311 turnRadiusText.setEnabled(false);
312 diameterText.setEnabled(false);
314 nameText.addKeyListener(new KeyAdapter() {
316 public void keyReleased(KeyEvent e) {
317 name = nameText.getText();
322 lengthText.addKeyListener(new KeyAdapter() {
324 public void keyReleased(KeyEvent e) {
326 length = Double.parseDouble(lengthText.getText()) / lengthFactor;
327 } catch (NumberFormatException err) {
334 angleText.addKeyListener(new KeyAdapter() {
336 public void keyReleased(KeyEvent e) {
338 angle = Double.parseDouble(angleText.getText());
339 } catch (NumberFormatException err) {
346 rotationAngleText.addKeyListener(new KeyAdapter() {
348 public void keyReleased(KeyEvent e) {
350 rotationAngle = Double.parseDouble(rotationAngleText.getText());
351 } catch (NumberFormatException err) {
352 rotationAngle = null;
358 diameterText.addKeyListener(new KeyAdapter() {
360 public void keyReleased(KeyEvent e) {
362 diameter = Double.parseDouble(diameterText.getText()) / lengthFactor;
363 } catch (NumberFormatException err) {
370 turnRadiusText.addKeyListener(new KeyAdapter() {
372 public void keyReleased(KeyEvent e) {
374 turnRadius = Double.parseDouble(turnRadiusText.getText()) / lengthFactor;
375 } catch (NumberFormatException err) {
382 horizFillData.applyTo(nameText);
383 horizFillData.applyTo(lengthText);
384 horizFillData.applyTo(angleText);
385 horizFillData.applyTo(rotationAngleText);
386 horizFillData.applyTo(diameterText);
387 horizFillData.applyTo(turnRadiusText);
389 if (!allowed.contains(PositionType.NEXT) && !allowed.contains(PositionType.PREVIOUS)) {
390 turnViewer.getList().setEnabled(false);
391 endViewer.getList().setEnabled(false);
398 private void updateInsertPosition(PositionType type) {
399 if (insertPosition == type)
401 endButton.setSelection(type == PositionType.NEXT);
402 middleButton.setSelection(type == PositionType.SPLIT);
403 startButton.setSelection(type == PositionType.PREVIOUS);
404 insertPosition = type;
408 public void selectionChanged(SelectionChangedEvent event) {
409 IStructuredSelection sel = (IStructuredSelection) event.getSelection();
410 Item i = (Item) sel.getFirstElement();
413 if (event.getSource() == inlineViewer) {
414 turnViewer.setSelection(new StructuredSelection());
415 endViewer.setSelection(new StructuredSelection());
416 } else if (event.getSource() == turnViewer) {
417 inlineViewer.setSelection(new StructuredSelection());
418 endViewer.setSelection(new StructuredSelection());
419 } else if (event.getSource() == endViewer) {
420 inlineViewer.setSelection(new StructuredSelection());
421 turnViewer.setSelection(new StructuredSelection());
424 name = generateUniqueName(selected.getName());
425 nameText.setText(name);
431 private void validate() {
432 filterAllowed.clear();
433 Set<PositionType> filterAllowed = new HashSet<PositionType>();
435 if (selected == null) {
437 } else if (selected.isCode()) {// TODO : instead of disabling the button, we should filter the content.
440 lenghtAdjustable = ((selected.getType() == Type.INLINE)
441 && (selected.isVariable() || selected.isModifiable()));
442 if (insertAdjustable) {
443 switch (selected.getType()) {
445 startButton.setEnabled(false);
446 middleButton.setEnabled(false);
447 endButton.setEnabled(true);
448 updateInsertPosition(PositionType.NEXT);
451 if (!selected.isVariable()) {
452 startButton.setEnabled(true);
453 middleButton.setEnabled(true);
454 endButton.setEnabled(true);
456 startButton.setEnabled(false);
457 middleButton.setEnabled(false);
458 endButton.setEnabled(true);
459 updateInsertPosition(PositionType.NEXT);
463 startButton.setEnabled(false);
464 middleButton.setEnabled(false);
465 endButton.setEnabled(true);
466 updateInsertPosition(PositionType.NEXT);
469 startButton.setEnabled(false);
470 middleButton.setEnabled(true);
471 endButton.setEnabled(true);
472 if (insertPosition == PositionType.PREVIOUS)
473 updateInsertPosition(PositionType.NEXT);
476 throw new RuntimeException("Expected component, got equipment " + selected);
478 } else if (lenghtAdjustable) {
479 if (component instanceof InlineComponent) {
480 startButton.setEnabled(true);
481 middleButton.setEnabled(true);
482 endButton.setEnabled(true);
483 } else if (component instanceof TurnComponent) {
484 startButton.setEnabled(false);
485 middleButton.setEnabled(true);
486 endButton.setEnabled(true);
487 if (insertPosition == PositionType.PREVIOUS)
488 updateInsertPosition(PositionType.NEXT);
489 } else if (component instanceof EndComponent || component instanceof Nozzle) {
490 startButton.setEnabled(false);
491 middleButton.setEnabled(false);
492 endButton.setEnabled(true);
493 updateInsertPosition(PositionType.NEXT);
496 startButton.setEnabled(false);
497 middleButton.setEnabled(false);
498 endButton.setEnabled(true);
500 if (selected.isVariable() || selected.isModifiable()) {
501 if (selected.getType() == Type.INLINE) {
502 filterAllowed.add(PositionType.NEXT);
503 filterAllowed.add(PositionType.PREVIOUS);
504 if (inlineSplit && selected.isVariable()) {
505 lengthText.setEnabled(false);
506 angleText.setEnabled(false);
507 rotationAngleText.setEnabled(selected.isRotated());
511 lengthText.setEnabled(true);
512 angleText.setEnabled(false);
513 rotationAngleText.setEnabled(selected.isRotated());
517 } else if (selected.getType() == Type.TURN) {
518 filterAllowed.add(PositionType.NEXT);
519 filterAllowed.add(PositionType.PREVIOUS);
520 lengthText.setEnabled(false);
521 angleText.setEnabled(true);
522 rotationAngleText.setEnabled(true);
526 // this should not happen, since end components should not have variable, or
528 lengthText.setEnabled(false);
529 angleText.setEnabled(false);
530 rotationAngleText.setEnabled(false);
534 lengthText.setEnabled(false);
535 angleText.setEnabled(false);
536 rotationAngleText.setEnabled(selected.getType() == Type.TURN || selected.isRotated());
539 if (selected.isSizeChange()) {
540 turnRadiusText.setEnabled(true);
541 diameterText.setEnabled(true);
542 if (diameter == null || turnRadius == null)
545 turnRadiusText.setEnabled(false);
546 diameterText.setEnabled(false);
549 if (!selected.isVariable()) {
550 switch (selected.getType()) {
552 filterAllowed.add(PositionType.NEXT);
553 filterAllowed.add(PositionType.PREVIOUS);
559 filterAllowed.add(PositionType.NEXT);
560 filterAllowed.add(PositionType.PREVIOUS);
561 filterAllowed.add(PositionType.SPLIT);
563 filterAllowed.add(PositionType.NEXT);
564 filterAllowed.add(PositionType.PREVIOUS);
568 for (PositionType t : filterAllowed) {
569 if (allowed.contains(t))
570 this.filterAllowed.add(t);
573 if (name.isEmpty() || usedNames.contains(name))
576 getButton(OK).setEnabled(ok);
579 private String generateUniqueName(String name) {
582 while (usedNames.contains((newName = name + "_" + i)))
587 public Item getSelected() {
591 public String getName() {
595 public Double getAngle() {
599 public Double getLength() {
603 public Double getRotationAngle() {
604 return rotationAngle;
607 public Double getDiameter() {
611 public Double getTurnRadius() {
615 public Set<PositionType> filterAllowed() {
616 return filterAllowed;
619 public PositionType getInsertPosition() {
620 return insertPosition;
623 public boolean isInsertAdjustable() {
624 return insertAdjustable;
627 public boolean isLenghtAdjustable() {
628 return lenghtAdjustable;