package org.simantics.modeling.ui.componentTypeEditor; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.layout.TableColumnLayout; import org.eclipse.jface.viewers.ColumnWeightData; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.TableEditor; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; import org.eclipse.ui.forms.widgets.Form; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.forms.widgets.Section; import org.simantics.Simantics; import org.simantics.db.ReadGraph; import org.simantics.db.RequestProcessor; import org.simantics.db.Resource; import org.simantics.db.WriteGraph; import org.simantics.db.common.request.PossibleIndexRoot; import org.simantics.db.common.request.UniqueRead; import org.simantics.db.common.request.WriteRequest; import org.simantics.db.exception.DatabaseException; import org.simantics.layer0.Layer0; import org.simantics.modeling.userComponent.ComponentTypeCommands; import org.simantics.scl.runtime.function.Function4; import org.simantics.structural.stubs.StructuralResource2; public class DerivedPropertiesSection implements ComponentTypeViewerSection { private static final String[] COLUMN_NAMES = new String[] {"Name", "Type", "Expression", "Label", "Description"}; private static final int[] COLUMN_LENGTHS = new int[] { 120, 100, 100, 100, 100 }; private static final int[] COLUMN_WEIGHTS = new int[] { 0, 0, 100, 0, 0 }; private static Function4 VALIDATE_MONITOR_EXPRESSION = new Function4() { @Override public String apply(RequestProcessor p0, Resource p1, Resource p2, String p3) { return validateMonitorExpression(p0, p1, p2, p3); } }; ComponentTypeViewerData data; Table table; TableColumn[] columns; TableEditor editor; Button newProperty; Button removeProperty; Section section; public DerivedPropertiesSection(ComponentTypeViewerData data) { this.data = data; FormToolkit tk = data.tk; Form form = data.form; section = tk.createSection(form.getBody(), Section.TITLE_BAR | Section.EXPANDED); section.setLayout(new FillLayout()); section.setText("Derived properties"); Composite sectionBody = tk.createComposite(section); GridLayoutFactory.fillDefaults().numColumns(2).applyTo(sectionBody); section.setClient(sectionBody); Composite tableComposite = tk.createComposite(sectionBody); GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).applyTo(tableComposite); TableColumnLayout tcl = new TableColumnLayout(); tableComposite.setLayout(tcl); table = tk.createTable(tableComposite, SWT.MULTI | SWT.FULL_SELECTION | SWT.BORDER); table.setLinesVisible(true); table.setHeaderVisible(true); columns = new TableColumn[COLUMN_NAMES.length]; for(int i=0;i propertiesToBeRemoved = new ArrayList<>(); for(TableItem item : table.getSelection()) propertiesToBeRemoved.add(((ComponentTypeViewerPropertyInfo)item.getData()).resource); //System.out.println("remove " + propertiesToBeRemoved.size() + " resources"); if(!propertiesToBeRemoved.isEmpty()) Simantics.getSession().async(new WriteRequest() { @Override public void perform(WriteGraph graph) throws DatabaseException { graph.markUndoPoint(); for(Resource property : propertiesToBeRemoved) ComponentTypeCommands.removeProperty(graph, data.componentType, property); } }); } }); } @Override public void setReadOnly(boolean readOnly) { boolean e = !readOnly; newProperty.setEnabled(e); removeProperty.setEnabled(e); } public static String validateMonitorExpression(final RequestProcessor processor, final Resource componentType, final Resource relation, final String expression) { if (expression.trim().isEmpty()) { return "Expression is empty."; } if (expression.trim().isEmpty()) { return "Expression is empty."; } try { return processor.sync(new UniqueRead() { @Override public String perform(ReadGraph graph) throws DatabaseException { StructuralResource2 STR = StructuralResource2.getInstance(graph); Resource indexRoot = graph.syncRequest(new PossibleIndexRoot(componentType)); for(Resource literal : graph.getAssertedObjects(componentType, relation)) { try { // TODO validation if(graph.isInstanceOf(componentType, STR.ProceduralComponentType)) { //Layer0 L0 = Layer0.getInstance(graph); //Resource environment = graph.getPossibleObject(literal, L0.SCLValue_environment); //ContextModule context = graph.sync(new TypeMonitorContextRequest(componentType)); //String SCLMain = graph.syncRequest(new SCLMainModuleRequest(indexRoot)); //CompilationContext cc = new CompilationContext(environment, context, SCLMain); //graph.syncRequest(new ActualCompileRequest(expression, cc), TransientCacheListener.instance()); } else { //CompilationContext cc = new CompileSCLMonitorRequest(literal, componentType, indexRoot).getContext(graph); //graph.syncRequest(new ActualCompileRequest(expression, cc), TransientCacheListener.instance()); //graph.syncRequest(new CompileSCLMonitorRequest(graph, context)); } } catch (Exception e) { String msg = e.getMessage(); int index = msg.indexOf(":"); if(index > 0) msg = msg.substring(index); return msg; } } return null; } }); } catch (DatabaseException e) { e.printStackTrace(); } return null; } @Override public void update(ComponentTypePropertiesResult result) { if (table.isDisposed()) return; Set selected = new HashSet<>(); List selectedItems = new ArrayList(selected.size()); for (int i : table.getSelectionIndices()) { TableItem item = table.getItem(i); selected.add((ComponentTypeViewerPropertyInfo) item.getData()); } int topIndex = table.getTopIndex(); table.removeAll(); if(editor.getEditor() != null) editor.getEditor().dispose(); for(ComponentTypeViewerPropertyInfo info : result.getProperties()) { boolean immutable = result.isImmutable() || info.immutable; Color fg = immutable ? table.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY) : null; if(info.sectionSpecificData != MONITOR) continue; TableItem item = new TableItem(table, SWT.NONE); item.setText(0, info.valid != null ? info.name + " (!)" : info.name); item.setText(1, info.type); item.setText(2, info.expression); //item.setText(3, unitStr(info)); item.setText(3, info.label); item.setText(4, info.description); item.setForeground(fg); item.setData(info); if (selected.contains(info)) selectedItems.add(item); } table.setTopIndex(topIndex); table.setSelection(selectedItems.toArray(new TableItem[selectedItems.size()])); table.redraw(); } @Override public Section getSection() { return section; } @Override public double getPriority() { return 100.0; } private static final Object MONITOR = new Object(); @Override public Object getSectionSpecificData(ReadGraph graph, ComponentTypeViewerPropertyInfo info) throws DatabaseException { Layer0 L0 = Layer0.getInstance(graph); StructuralResource2 STR = StructuralResource2.getInstance(graph); Resource range = graph.getPossibleObject(info.resource, L0.HasRange); if(range != null && graph.isInstanceOf(range, STR.MonitorValueType)) return MONITOR; else return null; } @Override public double getDataPriority() { return 100.0; } }