/******************************************************************************* * Copyright (c) 2007- VTT Technical Research Centre of Finland. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.proconf.g3d.shapeeditor.tools; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.dialogs.InputDialog; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; 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.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Sash; import org.eclipse.swt.widgets.Tree; import org.eclipse.ui.forms.IFormColors; import org.eclipse.ui.forms.events.ExpansionAdapter; import org.eclipse.ui.forms.events.ExpansionEvent; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.forms.widgets.ScrolledForm; import org.eclipse.ui.forms.widgets.Section; import org.simantics.db.Graph; import org.simantics.db.GraphRequestAdapter; import org.simantics.db.GraphRequestStatus; import org.simantics.db.Resource; import org.simantics.equation.stubs.SecondOrderScalarPolynomial; import org.simantics.animation.stubs.Animation; import org.simantics.animation.stubs.Interpolator; import org.simantics.layer0.utils.EntityFactory; import org.simantics.layer0.utils.IEntity; import org.simantics.layer0.utils.ResourceDebugUtils; import org.simantics.proconf.browsing.GraphExplorer; import org.simantics.proconf.browsing.GraphExplorerInputFactory; import org.simantics.proconf.browsing.views.PropertyTable; import org.simantics.proconf.g3d.actions.ContextAction; import org.simantics.proconf.g3d.base.EditorContribution; import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase; import org.simantics.proconf.g3d.common.StructuredResourceSelection; import org.simantics.proconf.g3d.shapeeditor.ShapeEditorResources; import org.simantics.proconf.g3d.shapeeditor.common.ViewpointGenerator; import org.simantics.proconf.g3d.shapeeditor.views.ShapeEditorBase; import org.simantics.proconf.g3d.stubs.G3DModel; import org.simantics.proconf.g3d.tools.OESelectionListener; import org.simantics.proconf.g3d.tools.PropertyTree; import org.simantics.utils.ui.jface.BaseSelectionProvider; public class ParameterizationContribution implements EditorContribution { private ShapeEditorBase parent; private List actions = new ArrayList(); private Composite sideComposite; private Sash sash; public ParameterizationContribution(ThreeDimensionalEditorBase parent) { this.parent = (ShapeEditorBase) parent; } @Override public void createControl(final Composite parentComposite) { FormLayout flayout = new FormLayout(); parentComposite.setLayout(flayout); sash = new Sash(parentComposite,SWT.VERTICAL); sideComposite = new Composite(parentComposite,SWT.BORDER); FormData data = new FormData(); data.top = new FormAttachment(0, 0); data.left = new FormAttachment(0, 0); data.right = new FormAttachment(sash, 0, SWT.LEFT); data.bottom = new FormAttachment(100,0); this.parent.getRenderingComposite().setLayoutData(data); sideComposite.setLayout(new FillLayout(SWT.VERTICAL)); data = new FormData(); data.top = new FormAttachment(0, 0); data.bottom = new FormAttachment(100,0); data.right = new FormAttachment(100,0); data.left = new FormAttachment(sash,0,SWT.RIGHT); sideComposite.setLayoutData(data); final int limit = 20, percent = 50; final FormData sashData = new FormData(); sashData.left = new FormAttachment (percent, 0); sashData.top = new FormAttachment(0, 0); sashData.bottom = new FormAttachment(100,0); sash.setLayoutData (sashData); sash.addListener (SWT.Selection, new Listener () { public void handleEvent (Event e) { Rectangle sashRect = sash.getBounds (); Rectangle shellRect = parentComposite.getClientArea (); int right = shellRect.width - sashRect.width - limit; e.x = Math.max (Math.min (e.x, right), limit); if (e.x != sashRect.x) { sashData.left = new FormAttachment (0, e.x); parentComposite.layout (); } } }); createForm(sideComposite); hierarchyExplorer.setInput(parent.getSessionContext(),GraphExplorerInputFactory.clone(hierarchyExplorer.getInput()) .input(parent.getModelResource()) .viewpoint(ViewpointGenerator.createObjectStructureViewpoint()) .toInput()); // parameterExplorer.setInput(parent.getSessionContext(),GraphExplorerInputFactory.clone(parameterExplorer.getInput()) // .input(parent.getModelResource()) // .viewpoint(ViewpointGenerator.createObjectSizingParameterViewpoint(ShapeEditorResources.g3dResource.HasSizingParameter)) // .toInput()); parameterTable.setSession(parent.getSession()); parameterTable.setInput(new StructuredResourceSelection(parent.getModelResource())); } @Override public void disposeControl() { sideComposite.dispose(); sash.dispose(); } @Override public void dispose() { } @Override public void fillContextMenu(Graph graph, IMenuManager manager, StructuredResourceSelection selection) { } @Override public void fillLocalPullDown(IMenuManager manager) { } @Override public void fillLocalToolBar(IToolBarManager manager) { } @Override public Collection getActions() { return actions; } @Override public String getName() { return "Parameterization"; } @Override public void initialize(Graph graph) { } @Override public void run() { } private ScrolledForm form; private BaseSelectionProvider defaultInputSelectionProvider = new BaseSelectionProvider(); protected FormToolkit toolkit; private void createForm(Composite parent) { toolkit = new FormToolkit(parent.getDisplay()); form = getToolkit().createScrolledForm(parent); GridLayout layout = new GridLayout(2, false); form.getBody().setLayout(layout); form.getBody().setLayoutData( new GridData(GridData.FILL, GridData.FILL, true, true)); // By default make this ViewPart use a default ISelectionProvider // that will offer the viewparts input resource as its selection. // The Resource is wrapped into a ResourceSelection object. // Any widgets created in createWidgets may override the default // selection provider. //getEditorSite().setSelectionProvider(defaultInputSelectionProvider); beforeCreateWidgets(); createWidgets(); //reload(); form.setText(getFormText()); // Finally Set the default selection which will have an effect only // if nothing in createWidgets has overridden the default selection // provider. // ISelection s = ISelectionUtils // .createSelection(new StructuredResourceSelection( // getInputResource())); // defaultInputSelectionProvider.setSelection(s); } public ScrolledForm getActiveForm() { return form; } protected Composite getBody() { return form.getBody(); } public Composite newGridSection(int formColumns, int childColumns, boolean equalWidth, boolean grabVertical, String text, String description) { return newGridSection(getBody(), formColumns, childColumns, equalWidth, grabVertical, text, description); } public Composite newGridSection(Composite parent, int formColumns, int childColumns, boolean equalWidth, boolean grabVertical, String text, String description) { FormToolkit toolkit = getToolkit(); Section section = toolkit.createSection(parent, Section.DESCRIPTION | Section.TWISTIE | Section.TITLE_BAR | Section.EXPANDED); section.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, grabVertical, formColumns, 1)); section.addExpansionListener(new ExpansionAdapter() { public void expansionStateChanged(ExpansionEvent e) { //System.out.println("SinglePageTypeEditor: expansionStateChanged " + e); //reflow(true); } }); section.setText(text); section.setDescription(description); Composite sectionClient = toolkit.createComposite(section); sectionClient.setLayout(new GridLayout(childColumns, equalWidth)); sectionClient.setLayoutData(new GridData()); section.setClient(sectionClient); return sectionClient; } public FormToolkit getToolkit() { return toolkit; } public void reflow(boolean flushCache) { //System.out.println("FormTypeEditorBase.reflow(" + flushCache + ")"); getActiveForm().reflow(flushCache); } protected void beforeCreateWidgets() { } // private TrackedText modelName = null; StructuredResourceSelection hierarchySelection = new StructuredResourceSelection(); StructuredResourceSelection parameterSelection = new StructuredResourceSelection(); //GraphExplorer parameterExplorer; PropertyTable parameterTable; GraphExplorer hierarchyExplorer; Button deleteParameterButton; Button clearButton; PropertyTree propertiesTree; Button generateButton; Button askButton; Button overrideButton; protected String getFormText() { return "Parameterization Editor"; } protected void createWidgets() { createModelPropertiesGroup(newGridSection(2, 1, false, false, "Model Properties", "Basic properties for this viewpoint")); createParametrizationGroup(newGridSection(2, 1, false, false, "Parameterization", "Create parameterization for selected shapes")); //getSite().setSelectionProvider(this); } private void createParametrizationGroup(Composite parent) { toolkit.paintBordersFor(parent); toolkit.setBorderStyle(SWT.BORDER); overrideButton = toolkit.createButton(parent, "Overwrite previous parameterizations", SWT.CHECK); overrideButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { askButton.setEnabled(overrideButton.getSelection()); } }); askButton = toolkit.createButton(parent, "Ask before overwriting", SWT.CHECK); askButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { } }); askButton.setEnabled(false); generateButton = toolkit.createButton(parent, "Generate linear parameterization", SWT.PUSH); generateButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { generateMappings(); } }); generateButton.setEnabled(false); } private void createModelPropertiesGroup(final Composite parent) { toolkit.paintBordersFor(parent); toolkit.setBorderStyle(SWT.BORDER); GridData gridData1 = new GridData(SWT.FILL, SWT.TOP, false, false, 1, 1); // Parameters Label parameterLabel = toolkit.createLabel(parent, "Parameters:"); parameterLabel.setForeground(toolkit.getColors().getColor(IFormColors.TITLE)); parameterLabel.setLayoutData(gridData1); // parameterExplorer = new GraphExplorer(parent, SWT.SINGLE); //new OntologyExplorer("ParameterExplorer", this, getInput("ParameterExplorer", model.getId())); // parameterExplorer.getViewer().addPostSelectionChangedListener(new OESelectionListener() { // // protected void resourceSelectionUpdated(StructuredResourceSelection sel) { // parameterSelection = sel; // if (parameterSelection.size() == 0) { // deleteParameterButton.setEnabled(false); // clearButton.setEnabled(false); // } else { // deleteParameterButton.setEnabled(true); // clearButton.setEnabled(true); // } // updateGenerateButtonStatus(); // } // // }); // Tree oe = parameterExplorer.getTree(); // toolkit.adapt(oe, true, true); parameterTable = new PropertyTable(parent,SWT.NONE); parameterTable.getViewer().addPostSelectionChangedListener(new OESelectionListener() { protected void resourceSelectionUpdated(StructuredResourceSelection sel) { parameterSelection = sel; if (parameterSelection.size() == 0) { deleteParameterButton.setEnabled(false); clearButton.setEnabled(false); } else { deleteParameterButton.setEnabled(true); clearButton.setEnabled(true); } updateGenerateButtonStatus(); } }); GridData gd3 = new GridData(GridData.FILL, GridData.FILL, true, true,1,1); gd3.heightHint = 50; //oe.setLayoutData(gd3); parameterTable.setLayoutData(gd3); // Buttons to add and remove parameters toolkit.createLabel(parent, ""); Composite buttons = toolkit.createComposite(parent); buttons.setLayout(new FillLayout(SWT.HORIZONTAL)); Button newParameterButton = toolkit.createButton(buttons, "New Parameter", SWT.PUSH); newParameterButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { InputDialog dialog = new InputDialog(ParameterizationContribution.this.parent.getRenderingComposite().getShell(),"New Parameter","Enter parameter's name","new parameter",null); if (dialog.open() == InputDialog.CANCEL) return; final String name = dialog.getValue(); if (name.length() < 1) return; // TODO : show error ParameterizationContribution.this.parent.getSession().asyncWrite(new GraphRequestAdapter() { public GraphRequestStatus perform(Graph g) throws Exception { //fi.vtt.simantics.layer0.stubs.Double parameter = DoubleFactory.createDefault(g); //getModel(g).addStatement(ShapeEditorResources.g3dResource.HasSizingParameter, parameter); //parameter.setValue(new double[]{1.0}); //parameter.setName(name); Resource parameter = ParameterizationContribution.this.parent.getModel(g).addRelatedScalarDouble(ShapeEditorResources.g3dResource.HasSizingParameter, 1.0).getResource(); IEntity thing = EntityFactory.create(g,parameter); thing.setName(name); return GraphRequestStatus.transactionComplete(); }; }); } }); deleteParameterButton = toolkit.createButton(buttons, "Delete Parameter", SWT.PUSH); deleteParameterButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { //StructuredResourceSelection s = (StructuredResourceSelection)parameterScheme.getSelection(); final StructuredResourceSelection s = parameterSelection; if (s.size() != 1) return; // we'll have to start write transaction, since we may have to change the graph ParameterizationContribution.this.parent.getSession().asyncWrite(new GraphRequestAdapter() { boolean proceed; IEntity selectedParameter; public GraphRequestStatus perform(Graph g) throws Exception { selectedParameter = EntityFactory.create(g,s.getSelectionList().get(0)); Collection parameters = selectedParameter.getRelatedObjects(ShapeEditorResources.g3dResource.HasSizingParameter); if (parameters.size() > 0) { final MessageDialog dialog = new MessageDialog(ParameterizationContribution.this.parent.getRenderingComposite().getShell(),"Deleting a parameter",null,"Parameter is in use, doe you wan't to remove it?",MessageDialog.QUESTION,new String[]{"OK","Cancel"},1); parent.getDisplay().syncExec(new Runnable() { @Override public void run() { proceed = (dialog.open() != 1); } }); if (proceed) { ParameterizationContribution.this.parent.getModel(g).removeStatement(ShapeEditorResources.g3dResource.HasSizingParameter,selectedParameter); } } return GraphRequestStatus.transactionComplete(); } }); } }); deleteParameterButton.setEnabled(false); clearButton = toolkit.createButton(buttons, "Clear Parameter", SWT.PUSH); clearButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { final StructuredResourceSelection s = parameterSelection; if (s.size() != 1) return; ParameterizationContribution.this.parent.getSession().asyncWrite(new GraphRequestAdapter() { boolean proceed; @Override public GraphRequestStatus perform(Graph g) throws Exception { IEntity selectedParameter = EntityFactory.create(g,s.getSelectionList().get(0)); Collection equations = selectedParameter.getRelatedObjects(ShapeEditorResources.equationResource.HasTarget); final String name = selectedParameter.getName(); if (equations.size() > 0) { final MessageDialog dialog = new MessageDialog(ParameterizationContribution.this.parent.getRenderingComposite().getShell(),"Clearing a parameter",null,"Do you wan't to clear parameterization for "+ name + " ?\nIt has " + equations.size() + " mappings.",MessageDialog.QUESTION,new String[]{"OK","Cancel"},1); parent.getDisplay().syncExec(new Runnable() { public void run() { proceed = (dialog.open() != 1); }; }); if (proceed) { for (IEntity eq : equations) { eq.removeRelatedStatements(ShapeEditorResources.equationResource.HasSource); eq.removeRelatedStatements(ShapeEditorResources.equationResource.HasTarget); } return GraphRequestStatus.transactionComplete(); } } return GraphRequestStatus.transactionCancel(); } }); } }); clearButton.setEnabled(false); Label hierarchyLabel = toolkit.createLabel(parent, "Model Hierarchy:"); hierarchyLabel.setForeground(toolkit.getColors().getColor(IFormColors.TITLE)); hierarchyLabel.setLayoutData(gridData1); hierarchyExplorer = new GraphExplorer(parent,SWT.MULTI); //new OntologyExplorer("HierarchyExplorer", this, getInput("HierarchyExplorer", model.getId())); Tree oeh = hierarchyExplorer.getTree();//hierarchyExplorer.getControl(parent, 1, OntologyExplorer.OntologyTree, SWT.MULTI); toolkit.adapt(oeh, true, true); GridData gd4 = new GridData(GridData.FILL, GridData.FILL, true, true,1,1); gd4.heightHint = 200; oeh.setLayoutData(gd4); hierarchyExplorer.getViewer().addPostSelectionChangedListener(new OESelectionListener() { protected void resourceSelectionUpdated(StructuredResourceSelection sel) { hierarchySelection = sel; updatePropertiesTable(); updateGenerateButtonStatus(); } private void updatePropertiesTable() { propertiesTree.setProperties(hierarchySelection); } }); Label propertiesLabel = toolkit.createLabel(parent, "Available properties:"); propertiesLabel.setForeground(toolkit.getColors().getColor(IFormColors.TITLE)); propertiesLabel.setLayoutData(gridData1); //propertiesTable = toolkit.createTable(parent, SWT.MULTI); Tree tree = toolkit.createTree(parent, SWT.MULTI); propertiesTree = new PropertyTree(tree,ParameterizationContribution.this.parent.getSession()); // GridData gd5 = new GridData(GridData.FILL, GridData.FILL, true, true,1,1); gd5.heightHint = 200; //propertiesTable.setLayoutData(gd5); tree.setLayoutData(gd5); tree.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { updateGenerateButtonStatus(); } }); } private void updateGenerateButtonStatus() { if (parameterSelection.size() == 0) { generateButton.setEnabled(false); return; } if (hierarchySelection.size() == 0) { generateButton.setEnabled(false); return; } if (propertiesTree.getTree().getSelection().length == 0) { generateButton.setEnabled(false); return; } generateButton.setEnabled(true); } List res; private void generateMappings() { final StructuredResourceSelection selectedShapes = hierarchySelection; final StructuredResourceSelection selectedParameter = parameterSelection; final boolean override = overrideButton.getSelection(); final boolean ask = askButton.getSelection(); //TreeItem[] selectedProperties = propertiesTree.getTree().getSelection(); assert (selectedParameter.size() == 1); assert (selectedShapes.size() > 0); //assert(selectedProperties.length > 0); parent.getSession().asyncWrite(new GraphRequestAdapter() { @Override public GraphRequestStatus perform(Graph g) throws Exception { //fi.vtt.simantics.layer0.stubs.Double parameter = DoubleFactory.create(g,selectedParameter.getSelectionList().get(0)); IEntity parameter = EntityFactory.create(g,selectedParameter.getSelectionList().get(0)); Collection prop = parameter.getRelatedObjects(ShapeEditorResources.g3dResource.HasDefaultDoubleValue); //fi.vtt.simantics.layer0.stubs.Double defaultValue; double value = g.getScalarDouble(parameter.getResource()); if (prop.size() == 0) { //defaultValue = DoubleFactory.createDefault(g); //parameter.addStatement(ShapeEditorResources.g3dResource.HasDefaultDoubleValue, defaultValue); parameter.addRelatedScalarDouble(ShapeEditorResources.g3dResource.HasDefaultDoubleValue, value); } else { //defaultValue = DoubleFactory.create(prop.iterator().next()); g.setScalarDouble(prop.iterator().next().getResource(),value); } //defaultValue.setValue(parameter.getValue()); final Graph graph = g; parent.getRenderingComposite().getDisplay().syncExec(new Runnable() { public void run() { res = propertiesTree.findLeafPropertyInstances(graph, selectedShapes.getSelectionList()); }; }); double refValue = parameter.toProperty().getScalarDouble(); ArrayList mappedProperties = new ArrayList(); for (Resource r : res) { IEntity propertyThing = EntityFactory.create(g,r); assert (propertyThing.isInstanceOf(g.getBuiltins().Double)); final String name = ResourceDebugUtils.getReadableNameForEntity(propertyThing); double rb = propertyThing.toProperty().getScalarDouble(); System.out.println("Mapping to " + name + " " + rb); Collection equations = propertyThing.getRelatedObjects(ShapeEditorResources.equationResource.HasSource); if (equations.size() != 0) { mappedProperties.add(propertyThing.getResource()); if (override) { System.out.println("Override"); boolean over = true; if (ask) { IEntity t = propertyThing; while (t.isInstanceOf(g.getBuiltins().Property)) { Collection ts = t.getRelatedObjects(g.getBuiltins().PropertyOf); // FIXME : traverse all possible routes t = ts.iterator().next(); } //StructuredResourceSelection selection = new StructuredResourceSelection(t.getResource()); // TODO : do the selection! //hierarchyScheme.setSelection(selection); //fireSelectionChanged(); MessageDialog dialog = new MessageDialog(ParameterizationContribution.this.parent.getRenderingComposite().getShell(), "Override mapping", null, "Override mapping to property of highlighted shape?", MessageDialog.QUESTION, new String[] { "Yes","No", "Cancel" }, 0); int i = dialog.open(); if (i == 2) return GraphRequestStatus.transactionCancel(); over = (i == 0); } if (over) { } } else { if (equations.size() != 1) { throw new RuntimeException("One property can have only one euquation as source function."); } IEntity equation = equations.iterator().next(); if (!equation.isInstanceOf(ShapeEditorResources.equationResource.SecondOrderScalarPolynomial)) { throw new RuntimeException("Only Second order scalar polynomials are supported"); } SecondOrderScalarPolynomial s = new SecondOrderScalarPolynomial(equation); s.setA(new double[]{0.0}); s.setB(new double[]{rb / refValue}); s.setC(new double[]{0.0}); } } else { //override // create relation SecondOrderScalarPolynomial s = SecondOrderScalarPolynomial.createDefault(g); s.setA(new double[]{0.0}); s.setB(new double[]{rb / refValue}); s.setC(new double[]{0.0}); // these relations have been instantiated, but addStatements won't delete them so we have to delete them manually. s.removeRelatedStatements(ShapeEditorResources.equationResource.HasTarget); s.removeRelatedStatements(ShapeEditorResources.equationResource.HasSource); parameter.addStatement(ShapeEditorResources.equationResource.HasTarget, s); s.addStatement(ShapeEditorResources.equationResource.HasTarget, propertyThing); mappedProperties.add(propertyThing.getResource()); } } G3DModel model = parent.getModel(g); Collection animations = model.getAnimation(); for (Animation animation : animations) { Collection interpolators = animation.getInterpolator(); for (Interpolator interpolator : interpolators) { IEntity target = interpolator.getTarget(); for (Resource property : mappedProperties) { if (target.getResource().equals(property)) { ShapeEditorResources.curveBuilder.createDefault(interpolator); } } } } return GraphRequestStatus.transactionComplete(); } }); } }