package org.simantics.plant3d.dialog; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.resource.LocalResourceManager; import org.eclipse.jface.resource.ResourceManager; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ListViewer; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.swt.SWT; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.ExpandBar; import org.eclipse.swt.widgets.ExpandItem; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import org.simantics.db.exception.DatabaseException; import org.simantics.plant3d.Activator; import org.simantics.plant3d.ontology.Plant3D; import org.simantics.plant3d.scenegraph.EndComponent; import org.simantics.plant3d.scenegraph.InlineComponent; import org.simantics.plant3d.scenegraph.Nozzle; import org.simantics.plant3d.scenegraph.PipelineComponent; import org.simantics.plant3d.scenegraph.TurnComponent; import org.simantics.plant3d.scenegraph.controlpoint.PipeControlPoint.PositionType; import org.simantics.plant3d.utils.Item; import org.simantics.plant3d.utils.Item.Type; import org.simantics.plant3d.utils.P3DUtil; import org.simantics.utils.ui.ExceptionUtils; public class ComponentSelectionDialog extends Dialog implements ISelectionChangedListener{ private ResourceManager resourceManager; private String libUri; private Item selected; private Set allowed; private Set filterAllowed; //private boolean positionAdjustment; private PipelineComponent component; private boolean insertAdjustable; private boolean lenghtAdjustable; private PositionType insertPosition = PositionType.NEXT; private Double angle; private Double length; private Text lengthText; private Text angleText; private Double diameter; private Double turnRadius; private Text diameterText; private Text turnRadiusText; private Button startButton; private Button middleButton; private Button endButton; private boolean inlineSplit = false; ListViewer inlineViewer; ListViewer turnViewer; ListViewer endViewer; public ComponentSelectionDialog(Shell parentShell, Set allowed, PipelineComponent component){ this(parentShell, allowed, component, Plant3D.URIs.Builtin); } public ComponentSelectionDialog(Shell parentShell, Set allowed, PipelineComponent component, String libUri){ super(parentShell); this.allowed = allowed; this.component = component; filterAllowed = new HashSet(); insertAdjustable = component instanceof InlineComponent ? ((InlineComponent)component).isVariableLength() : false; lenghtAdjustable = false; this.libUri = libUri; } @Override protected Control createDialogArea(Composite parent) { resourceManager = new LocalResourceManager(JFaceResources.getResources(), parent); Composite composite = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(2,false); layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN); layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN); layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING); layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING); composite.setLayout(layout); composite.setLayoutData(new GridData(GridData.FILL_BOTH)); applyDialogFont(composite); // TODO : we need better classification than inline,turn, and end: // * fixed length inlines // * fixed angle turns // * size changes (requires input for pipe run specs) // * variable length inlines (input for length) // * variable angle turns (input for angle) // * ends List ends = null; List turns = null; List inlines = null; try { ends = P3DUtil.getEnds(libUri); turns= P3DUtil.getTurns(libUri); inlines = P3DUtil.getInlines(libUri); } catch (DatabaseException e) { Label label = new Label(composite, SWT.NONE); label.setText("Cannot load pipeline components: " + e.getMessage()); ExceptionUtils.logError(e); return composite; } ends = P3DUtil.filterUserComponents(ends); turns = P3DUtil.filterUserComponents(turns); inlines = P3DUtil.filterUserComponents(inlines); ExpandBar expandBar = new ExpandBar(composite, SWT.NONE); ExpandItem inlineItem = new ExpandItem(expandBar, SWT.NONE); inlineItem.setText("Inline"); inlineViewer = new ListViewer(expandBar); inlineViewer.setLabelProvider(new ComponentLabelProvider()); inlineViewer.setContentProvider(new ComponentContentProvider()); ExpandItem turnItem = new ExpandItem(expandBar, SWT.NONE); turnItem.setText("Turn"); turnViewer = new ListViewer(expandBar); turnViewer.setLabelProvider(new ComponentLabelProvider()); turnViewer.setContentProvider(new ComponentContentProvider()); ExpandItem endItem = new ExpandItem(expandBar, SWT.NONE); endItem.setText("End"); endViewer = new ListViewer(expandBar); endViewer.setLabelProvider(new ComponentLabelProvider()); endViewer.setContentProvider(new ComponentContentProvider()); inlineItem.setControl(inlineViewer.getList()); turnItem.setControl(turnViewer.getList()); endItem.setControl(endViewer.getList()); inlineViewer.setInput(inlines); turnViewer.setInput(turns); endViewer.setInput(ends); inlineItem.setHeight(inlineViewer.getList().computeSize(SWT.DEFAULT, SWT.DEFAULT).y); turnItem.setHeight(turnViewer.getList().computeSize(SWT.DEFAULT, SWT.DEFAULT).y); endItem.setHeight(endViewer.getList().computeSize(SWT.DEFAULT, SWT.DEFAULT).y); inlineViewer.addSelectionChangedListener(this); turnViewer.addSelectionChangedListener(this); endViewer.addSelectionChangedListener(this); GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).span(2, 1).applyTo(expandBar); GridDataFactory.fillDefaults().minSize(500, 500).hint(500, 500).applyTo(composite); Label label = new Label(composite, SWT.NONE); label.setText("Position"); Composite buttonComposite = new Composite(composite, SWT.NONE); startButton = new Button(buttonComposite, SWT.TOGGLE); middleButton = new Button(buttonComposite, SWT.TOGGLE); endButton = new Button(buttonComposite, SWT.TOGGLE); startButton.setImage(resourceManager.createImage(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/insert_start.png"))); middleButton.setImage(resourceManager.createImage(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/insert_middle.png"))); endButton.setImage(resourceManager.createImage(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/insert_end.png"))); GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(buttonComposite); GridLayoutFactory.fillDefaults().numColumns(3).applyTo(buttonComposite); startButton.setEnabled(false); middleButton.setEnabled(false); endButton.setEnabled(false); startButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { updateInsertPosition(PositionType.PREVIOUS); } }); middleButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { updateInsertPosition(PositionType.SPLIT); } }); endButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { updateInsertPosition(PositionType.NEXT); } }); endButton.setSelection(true); label = new Label(composite, SWT.NONE); label.setText("Length"); lengthText = new Text(composite, SWT.SINGLE|SWT.BORDER); label = new Label(composite, SWT.NONE); label.setText("Angle"); angleText = new Text(composite, SWT.SINGLE|SWT.BORDER); label = new Label(composite, SWT.NONE); label.setText("Diameter"); diameterText = new Text(composite, SWT.SINGLE|SWT.BORDER); label = new Label(composite, SWT.NONE); label.setText("Turn Radius"); turnRadiusText = new Text(composite, SWT.SINGLE|SWT.BORDER); lengthText.setEnabled(false); angleText.setEnabled(false); turnRadiusText.setEnabled(false); diameterText.setEnabled(false); lengthText.addKeyListener(new KeyAdapter() { @Override public void keyReleased(KeyEvent e) { try { length = Double.parseDouble(lengthText.getText()); } catch (NumberFormatException err) { length = null; } validate(); } }); angleText.addKeyListener(new KeyAdapter() { @Override public void keyReleased(KeyEvent e) { try { angle = Double.parseDouble(angleText.getText()); } catch (NumberFormatException err) { angle = null; } validate(); } }); diameterText.addKeyListener(new KeyAdapter() { @Override public void keyReleased(KeyEvent e) { try { diameter = Double.parseDouble(diameterText.getText()); } catch (NumberFormatException err) { diameter = null; } validate(); } }); turnRadiusText.addKeyListener(new KeyAdapter() { @Override public void keyReleased(KeyEvent e) { try { turnRadius = Double.parseDouble(turnRadiusText.getText()); } catch (NumberFormatException err) { turnRadius = null; } validate(); } }); GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(lengthText); GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(angleText); GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(diameterText); GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.TOP).applyTo(turnRadiusText); if (!allowed.contains(PositionType.NEXT) && !allowed.contains(PositionType.PREVIOUS)) { turnViewer.getList().setEnabled(false); endViewer.getList().setEnabled(false); inlineSplit = true; } return composite; } private void updateInsertPosition(PositionType type) { if (insertPosition == type) return; endButton.setSelection(type == PositionType.NEXT); middleButton.setSelection(type == PositionType.SPLIT); startButton.setSelection(type == PositionType.PREVIOUS); insertPosition = type; } @Override public void selectionChanged(SelectionChangedEvent event) { IStructuredSelection sel = (IStructuredSelection)event.getSelection(); Item i = (Item)sel.getFirstElement(); if (i != null) { selected = i; if (event.getSource() == inlineViewer) { turnViewer.setSelection(new StructuredSelection()); endViewer.setSelection(new StructuredSelection()); } else if (event.getSource() == turnViewer) { inlineViewer.setSelection(new StructuredSelection()); endViewer.setSelection(new StructuredSelection()); } else if (event.getSource() == endViewer) { inlineViewer.setSelection(new StructuredSelection()); turnViewer.setSelection(new StructuredSelection()); } validate(); } } private void validate() { filterAllowed.clear(); Set filterAllowed = new HashSet(); boolean ok = true; if (selected == null) { ok = false; } else if (selected.isCode()) {// TODO : instead of disabling the button, we should filter the content. ok = false; } else { lenghtAdjustable = ((selected.getType() == Type.INLINE) && selected.isVariable()); if (insertAdjustable) { switch (selected.getType()) { case END: startButton.setEnabled(false); middleButton.setEnabled(false); endButton.setEnabled(true); updateInsertPosition(PositionType.NEXT); break; case INLINE: if (!selected.isVariable()) { startButton.setEnabled(true); middleButton.setEnabled(true); endButton.setEnabled(true); } else { startButton.setEnabled(false); middleButton.setEnabled(false); endButton.setEnabled(true); updateInsertPosition(PositionType.NEXT); } break; case NOZZLE: startButton.setEnabled(false); middleButton.setEnabled(false); endButton.setEnabled(true); updateInsertPosition(PositionType.NEXT); break; case TURN: startButton.setEnabled(false); middleButton.setEnabled(true); endButton.setEnabled(true); if (insertPosition == PositionType.PREVIOUS) updateInsertPosition(PositionType.NEXT); break; case EQUIPMENT: throw new RuntimeException("Expected component, got equipment " + selected); } } else if (lenghtAdjustable) { if (component instanceof InlineComponent) { startButton.setEnabled(true); middleButton.setEnabled(true); endButton.setEnabled(true); } else if (component instanceof TurnComponent) { startButton.setEnabled(false); middleButton.setEnabled(true); endButton.setEnabled(true); if (insertPosition == PositionType.PREVIOUS) updateInsertPosition(PositionType.NEXT); } else if (component instanceof EndComponent || component instanceof Nozzle) { startButton.setEnabled(false); middleButton.setEnabled(false); endButton.setEnabled(true); updateInsertPosition(PositionType.NEXT); } } else { startButton.setEnabled(false); middleButton.setEnabled(false); endButton.setEnabled(true); } if (selected.isVariable()) { if (selected.getType() == Type.INLINE) { filterAllowed.add(PositionType.NEXT); filterAllowed.add(PositionType.PREVIOUS); if (inlineSplit) { lengthText.setEnabled(false); angleText.setEnabled(false); ok = false; } else { lengthText.setEnabled(true); angleText.setEnabled(false); if (length == null) ok = false; } } else if (selected.getType() == Type.TURN) { filterAllowed.add(PositionType.NEXT); filterAllowed.add(PositionType.PREVIOUS); lengthText.setEnabled(false); angleText.setEnabled(true); if (angle == null) ok = false; } else { // this should not happen lengthText.setEnabled(false); angleText.setEnabled(false); } } else { lengthText.setEnabled(false); angleText.setEnabled(false); } if (selected.isSizeChange()) { filterAllowed.add(PositionType.NEXT); filterAllowed.add(PositionType.PREVIOUS); if (inlineSplit) { turnRadiusText.setEnabled(false); diameterText.setEnabled(false); ok = false; } else { turnRadiusText.setEnabled(true); diameterText.setEnabled(true); if (diameter == null || turnRadius == null) ok = false; } } else { turnRadiusText.setEnabled(false); diameterText.setEnabled(false); } if (!selected.isSizeChange() && !selected.isVariable()) { switch (selected.getType()) { case END: filterAllowed.add(PositionType.NEXT); filterAllowed.add(PositionType.PREVIOUS); break; case NOZZLE: case EQUIPMENT: break; case INLINE: filterAllowed.add(PositionType.NEXT); filterAllowed.add(PositionType.PREVIOUS); filterAllowed.add(PositionType.SPLIT); case TURN: filterAllowed.add(PositionType.NEXT); filterAllowed.add(PositionType.PREVIOUS); } } } for (PositionType t : filterAllowed) { if (allowed.contains(t)) this.filterAllowed.add(t); } getButton(OK).setEnabled(ok); } public Item getSelected() { return selected; } public Double getAngle() { return angle; } public Double getLength() { return length; } public Double getDiameter() { return diameter; } public Double getTurnRadius() { return turnRadius; } public Set filterAllowed() { return filterAllowed; } public PositionType getInsertPosition() { return insertPosition; } public boolean isInsertAdjustable() { return insertAdjustable; } public boolean isLenghtAdjustable() { return lenghtAdjustable; } }