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 ResourceManager resourceManager;
59 private String libUri;
61 private Item selected;
62 private Set<PositionType> allowed;
63 private Set<PositionType> filterAllowed;
64 // private boolean positionAdjustment;
65 private PipelineComponent component;
66 private boolean insertAdjustable;
67 private boolean lenghtAdjustable;
68 private PositionType insertPosition = PositionType.NEXT;
71 private Double length;
72 private Double rotationAngle;
76 private Text nameText;
79 private Text lengthText;
81 private Text angleText;
82 // Rotated In-line, or turn component.
83 private Text rotationAngleText;
85 // Input for new PipeRun
86 private Double diameter;
87 private Double turnRadius;
89 private Text diameterText;
90 private Text turnRadiusText;
93 private Button startButton;
94 private Button middleButton;
95 private Button endButton;
97 private boolean inlineSplit = false;
99 ListViewer inlineViewer;
100 ListViewer turnViewer;
101 ListViewer endViewer;
103 private Set<String> usedNames;
105 public ComponentSelectionDialog(Shell parentShell, Set<PositionType> allowed, PipelineComponent component) {
106 this(parentShell, allowed, component, Plant3D.URIs.Builtin);
109 public ComponentSelectionDialog(Shell parentShell, Set<PositionType> allowed, PipelineComponent component,
112 this.allowed = allowed;
113 this.component = component;
114 filterAllowed = new HashSet<PositionType>();
115 insertAdjustable = component instanceof InlineComponent ? ((InlineComponent) component).isVariableLength()
117 lenghtAdjustable = false;
118 this.libUri = libUri;
120 usedNames = new HashSet<>();
122 setShellStyle(getShellStyle() | SWT.RESIZE);
124 IDialogSettings settings = Activator.getDefault().getDialogSettings();
125 dialogSettings = settings.getSection(DIALOG);
126 if (dialogSettings == null)
127 dialogSettings = settings.addNewSection(DIALOG);
131 protected IDialogSettings getDialogBoundsSettings() {
132 return dialogSettings;
136 protected void configureShell(Shell newShell) {
137 super.configureShell(newShell);
138 newShell.setText("Create pipeline component");
141 public void addUsedNames(Collection<String> names) {
142 usedNames.addAll(names);
145 protected List<Item> getItems(Class<?> c, String libUri) throws DatabaseException {
146 if (InlineComponent.class.equals(c)) {
147 return P3DUtil.getInlines(libUri);
148 } else if (TurnComponent.class.equals(c)) {
149 return P3DUtil.getTurns(libUri);
150 } else if (EndComponent.class.equals(c)) {
151 return P3DUtil.getEnds(libUri);
158 protected Control createDialogArea(Composite parent) {
159 resourceManager = new LocalResourceManager(JFaceResources.getResources(), parent);
161 Composite composite = new Composite(parent, SWT.NONE);
162 GridLayout layout = new GridLayout(2, false);
163 layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
164 layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
165 layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
166 layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
167 composite.setLayout(layout);
168 composite.setLayoutData(new GridData(GridData.FILL_BOTH));
169 applyDialogFont(composite);
171 // Grid layout data for fields that grab horizontal space
172 final GridDataFactory horizFillData = GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.TOP);
174 // TODO : we need better classification than inline,turn, and end:
175 // * fixed length inlines
176 // * fixed angle turns
177 // * size changes (requires input for pipe run specs)
178 // * variable length inlines (input for length)
179 // * variable angle turns (input for angle)
182 List<Item> ends = null;
183 List<Item> turns = null;
184 List<Item> inlines = null;
186 ends = getItems(EndComponent.class, libUri);
187 turns = getItems(TurnComponent.class, libUri);
188 inlines = getItems(InlineComponent.class, libUri);
189 } catch (DatabaseException e) {
190 Label label = new Label(composite, SWT.NONE);
191 label.setText("Cannot load pipeline components: " + e.getMessage());
192 ExceptionUtils.logError(e);
195 ends = P3DUtil.filterUserComponents(ends);
196 turns = P3DUtil.filterUserComponents(turns);
197 inlines = P3DUtil.filterUserComponents(inlines);
199 ExpandBar expandBar = new ExpandBar(composite, SWT.V_SCROLL);
201 ExpandItem inlineItem = new ExpandItem(expandBar, SWT.NONE);
202 inlineItem.setText("Inline");
203 inlineViewer = new ListViewer(expandBar);
204 inlineViewer.setLabelProvider(new ComponentLabelProvider());
205 inlineViewer.setContentProvider(new ComponentContentProvider());
207 ExpandItem turnItem = new ExpandItem(expandBar, SWT.NONE);
208 turnItem.setText("Turn");
209 turnViewer = new ListViewer(expandBar);
210 turnViewer.setLabelProvider(new ComponentLabelProvider());
211 turnViewer.setContentProvider(new ComponentContentProvider());
213 ExpandItem endItem = new ExpandItem(expandBar, SWT.NONE);
214 endItem.setText("End");
215 endViewer = new ListViewer(expandBar);
216 endViewer.setLabelProvider(new ComponentLabelProvider());
217 endViewer.setContentProvider(new ComponentContentProvider());
219 inlineItem.setControl(inlineViewer.getList());
220 turnItem.setControl(turnViewer.getList());
221 endItem.setControl(endViewer.getList());
223 inlineViewer.setInput(inlines);
224 turnViewer.setInput(turns);
225 endViewer.setInput(ends);
227 inlineItem.setHeight(inlineViewer.getList().computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
228 turnItem.setHeight(turnViewer.getList().computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
229 endItem.setHeight(endViewer.getList().computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
231 inlineViewer.addSelectionChangedListener(this);
232 turnViewer.addSelectionChangedListener(this);
233 endViewer.addSelectionChangedListener(this);
235 GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).span(2, 1).applyTo(expandBar);
236 GridDataFactory.fillDefaults().grab(true, true).minSize(500, 500).hint(500, 500).applyTo(composite);
238 Label label = new Label(composite, SWT.NONE);
239 label.setText("Position");
240 Composite buttonComposite = new Composite(composite, SWT.NONE);
241 startButton = new Button(buttonComposite, SWT.TOGGLE);
242 middleButton = new Button(buttonComposite, SWT.TOGGLE);
243 endButton = new Button(buttonComposite, SWT.TOGGLE);
244 startButton.setImage(resourceManager.createImage(
245 ResourceLocator.imageDescriptorFromBundle(Activator.PLUGIN_ID, "icons/insert_start.png").get()));
246 middleButton.setImage(resourceManager.createImage(
247 ResourceLocator.imageDescriptorFromBundle(Activator.PLUGIN_ID, "icons/insert_middle.png").get()));
248 endButton.setImage(resourceManager.createImage(
249 ResourceLocator.imageDescriptorFromBundle(Activator.PLUGIN_ID, "icons/insert_end.png").get()));
250 startButton.setToolTipText("Overlapping insert");
251 middleButton.setToolTipText("Cutting insert");
252 endButton.setToolTipText("Adding insert");
253 horizFillData.applyTo(buttonComposite);
254 GridLayoutFactory.fillDefaults().numColumns(3).applyTo(buttonComposite);
256 startButton.setEnabled(false);
257 middleButton.setEnabled(false);
258 endButton.setEnabled(false);
260 startButton.addSelectionListener(new SelectionAdapter() {
262 public void widgetSelected(SelectionEvent e) {
263 updateInsertPosition(PositionType.PREVIOUS);
267 middleButton.addSelectionListener(new SelectionAdapter() {
269 public void widgetSelected(SelectionEvent e) {
270 updateInsertPosition(PositionType.SPLIT);
273 endButton.addSelectionListener(new SelectionAdapter() {
275 public void widgetSelected(SelectionEvent e) {
276 updateInsertPosition(PositionType.NEXT);
279 endButton.setSelection(true);
281 label = new Label(composite, SWT.NONE);
282 label.setText("Name");
283 nameText = new Text(composite, SWT.SINGLE | SWT.BORDER);
285 label = new Label(composite, SWT.NONE);
286 label.setText("Length");
287 lengthText = new Text(composite, SWT.SINGLE | SWT.BORDER);
288 label = new Label(composite, SWT.NONE);
289 label.setText("Angle");
290 angleText = new Text(composite, SWT.SINGLE | SWT.BORDER);
291 label = new Label(composite, SWT.NONE);
292 label.setText("Rotation angle");
293 rotationAngleText = new Text(composite, SWT.SINGLE | SWT.BORDER);
295 label = new Label(composite, SWT.NONE);
296 label.setText("Diameter");
297 diameterText = new Text(composite, SWT.SINGLE | SWT.BORDER);
298 label = new Label(composite, SWT.NONE);
299 label.setText("Turn Radius");
300 turnRadiusText = new Text(composite, SWT.SINGLE | SWT.BORDER);
302 lengthText.setEnabled(false);
303 angleText.setEnabled(false);
304 rotationAngleText.setEnabled(false);
305 turnRadiusText.setEnabled(false);
306 diameterText.setEnabled(false);
308 nameText.addKeyListener(new KeyAdapter() {
310 public void keyReleased(KeyEvent e) {
311 name = nameText.getText();
316 lengthText.addKeyListener(new KeyAdapter() {
318 public void keyReleased(KeyEvent e) {
320 length = Double.parseDouble(lengthText.getText());
321 } catch (NumberFormatException err) {
328 angleText.addKeyListener(new KeyAdapter() {
330 public void keyReleased(KeyEvent e) {
332 angle = Double.parseDouble(angleText.getText());
333 } catch (NumberFormatException err) {
340 rotationAngleText.addKeyListener(new KeyAdapter() {
342 public void keyReleased(KeyEvent e) {
344 rotationAngle = Double.parseDouble(rotationAngleText.getText());
345 } catch (NumberFormatException err) {
346 rotationAngle = null;
352 diameterText.addKeyListener(new KeyAdapter() {
354 public void keyReleased(KeyEvent e) {
356 diameter = Double.parseDouble(diameterText.getText());
357 } catch (NumberFormatException err) {
364 turnRadiusText.addKeyListener(new KeyAdapter() {
366 public void keyReleased(KeyEvent e) {
368 turnRadius = Double.parseDouble(turnRadiusText.getText());
369 } catch (NumberFormatException err) {
376 horizFillData.applyTo(nameText);
377 horizFillData.applyTo(lengthText);
378 horizFillData.applyTo(angleText);
379 horizFillData.applyTo(rotationAngleText);
380 horizFillData.applyTo(diameterText);
381 horizFillData.applyTo(turnRadiusText);
383 if (!allowed.contains(PositionType.NEXT) && !allowed.contains(PositionType.PREVIOUS)) {
384 turnViewer.getList().setEnabled(false);
385 endViewer.getList().setEnabled(false);
392 private void updateInsertPosition(PositionType type) {
393 if (insertPosition == type)
395 endButton.setSelection(type == PositionType.NEXT);
396 middleButton.setSelection(type == PositionType.SPLIT);
397 startButton.setSelection(type == PositionType.PREVIOUS);
398 insertPosition = type;
402 public void selectionChanged(SelectionChangedEvent event) {
403 IStructuredSelection sel = (IStructuredSelection) event.getSelection();
404 Item i = (Item) sel.getFirstElement();
407 if (event.getSource() == inlineViewer) {
408 turnViewer.setSelection(new StructuredSelection());
409 endViewer.setSelection(new StructuredSelection());
410 } else if (event.getSource() == turnViewer) {
411 inlineViewer.setSelection(new StructuredSelection());
412 endViewer.setSelection(new StructuredSelection());
413 } else if (event.getSource() == endViewer) {
414 inlineViewer.setSelection(new StructuredSelection());
415 turnViewer.setSelection(new StructuredSelection());
418 name = generateUniqueName(selected.getName());
419 nameText.setText(name);
425 private void validate() {
426 filterAllowed.clear();
427 Set<PositionType> filterAllowed = new HashSet<PositionType>();
429 if (selected == null) {
431 } else if (selected.isCode()) {// TODO : instead of disabling the button, we should filter the content.
434 lenghtAdjustable = ((selected.getType() == Type.INLINE)
435 && (selected.isVariable() || selected.isModifiable()));
436 if (insertAdjustable) {
437 switch (selected.getType()) {
439 startButton.setEnabled(false);
440 middleButton.setEnabled(false);
441 endButton.setEnabled(true);
442 updateInsertPosition(PositionType.NEXT);
445 if (!selected.isVariable()) {
446 startButton.setEnabled(true);
447 middleButton.setEnabled(true);
448 endButton.setEnabled(true);
450 startButton.setEnabled(false);
451 middleButton.setEnabled(false);
452 endButton.setEnabled(true);
453 updateInsertPosition(PositionType.NEXT);
457 startButton.setEnabled(false);
458 middleButton.setEnabled(false);
459 endButton.setEnabled(true);
460 updateInsertPosition(PositionType.NEXT);
463 startButton.setEnabled(false);
464 middleButton.setEnabled(true);
465 endButton.setEnabled(true);
466 if (insertPosition == PositionType.PREVIOUS)
467 updateInsertPosition(PositionType.NEXT);
470 throw new RuntimeException("Expected component, got equipment " + selected);
472 } else if (lenghtAdjustable) {
473 if (component instanceof InlineComponent) {
474 startButton.setEnabled(true);
475 middleButton.setEnabled(true);
476 endButton.setEnabled(true);
477 } else if (component instanceof TurnComponent) {
478 startButton.setEnabled(false);
479 middleButton.setEnabled(true);
480 endButton.setEnabled(true);
481 if (insertPosition == PositionType.PREVIOUS)
482 updateInsertPosition(PositionType.NEXT);
483 } else if (component instanceof EndComponent || component instanceof Nozzle) {
484 startButton.setEnabled(false);
485 middleButton.setEnabled(false);
486 endButton.setEnabled(true);
487 updateInsertPosition(PositionType.NEXT);
490 startButton.setEnabled(false);
491 middleButton.setEnabled(false);
492 endButton.setEnabled(true);
494 if (selected.isVariable() || selected.isModifiable()) {
495 if (selected.getType() == Type.INLINE) {
496 filterAllowed.add(PositionType.NEXT);
497 filterAllowed.add(PositionType.PREVIOUS);
498 if (inlineSplit && selected.isVariable()) {
499 lengthText.setEnabled(false);
500 angleText.setEnabled(false);
501 rotationAngleText.setEnabled(selected.isRotated());
505 lengthText.setEnabled(true);
506 angleText.setEnabled(false);
507 rotationAngleText.setEnabled(selected.isRotated());
511 } else if (selected.getType() == Type.TURN) {
512 filterAllowed.add(PositionType.NEXT);
513 filterAllowed.add(PositionType.PREVIOUS);
514 lengthText.setEnabled(false);
515 angleText.setEnabled(true);
516 rotationAngleText.setEnabled(true);
520 // this should not happen, since end components should not have variable, or
522 lengthText.setEnabled(false);
523 angleText.setEnabled(false);
524 rotationAngleText.setEnabled(false);
528 lengthText.setEnabled(false);
529 angleText.setEnabled(false);
530 rotationAngleText.setEnabled(selected.getType() == Type.TURN || selected.isRotated());
533 if (selected.isSizeChange()) {
534 turnRadiusText.setEnabled(true);
535 diameterText.setEnabled(true);
536 if (diameter == null || turnRadius == null)
539 turnRadiusText.setEnabled(false);
540 diameterText.setEnabled(false);
543 if (!selected.isVariable()) {
544 switch (selected.getType()) {
546 filterAllowed.add(PositionType.NEXT);
547 filterAllowed.add(PositionType.PREVIOUS);
553 filterAllowed.add(PositionType.NEXT);
554 filterAllowed.add(PositionType.PREVIOUS);
555 filterAllowed.add(PositionType.SPLIT);
557 filterAllowed.add(PositionType.NEXT);
558 filterAllowed.add(PositionType.PREVIOUS);
562 for (PositionType t : filterAllowed) {
563 if (allowed.contains(t))
564 this.filterAllowed.add(t);
567 if (name.isEmpty() || usedNames.contains(name))
570 getButton(OK).setEnabled(ok);
573 private String generateUniqueName(String name) {
576 while (usedNames.contains((newName = name + "_" + i)))
581 public Item getSelected() {
585 public String getName() {
589 public Double getAngle() {
593 public Double getLength() {
597 public Double getRotationAngle() {
598 return rotationAngle;
601 public Double getDiameter() {
605 public Double getTurnRadius() {
609 public Set<PositionType> filterAllowed() {
610 return filterAllowed;
613 public PositionType getInsertPosition() {
614 return insertPosition;
617 public boolean isInsertAdjustable() {
618 return insertAdjustable;
621 public boolean isLenghtAdjustable() {
622 return lenghtAdjustable;