]> gerrit.simantics Code Review - simantics/platform.git/commitdiff
Merge "Reading background color of a ICanvasContext with SCL"
authorMarko Luukkainen <marko.luukkainen@semantum.fi>
Fri, 21 Sep 2018 09:22:43 +0000 (09:22 +0000)
committerGerrit Code Review <gerrit2@simantics>
Fri, 21 Sep 2018 09:22:43 +0000 (09:22 +0000)
50 files changed:
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/StructuredProperty.java [new file with mode: 0644]
bundles/org.simantics.diagram/src/org/simantics/diagram/synchronization/graph/TranslateElement.java
bundles/org.simantics.diagram/src/org/simantics/diagram/ui/SWTPopupMenuParticipant.java
bundles/org.simantics.diagram/src/org/simantics/diagram/ui/e4/SWTPopupMenuParticipant.java
bundles/org.simantics.g2d/plugin.xml
bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/DiagramHints.java
bundles/org.simantics.g2d/src/org/simantics/g2d/event/adapter/SWTMouseEventAdapter.java
bundles/org.simantics.g2d/src/org/simantics/g2d/gallery/GalleryViewer.java
bundles/org.simantics.g2d/src/org/simantics/g2d/utils/FontHelper.java
bundles/org.simantics.jdbc.ontology/.classpath [new file with mode: 0644]
bundles/org.simantics.jdbc.ontology/.project [new file with mode: 0644]
bundles/org.simantics.jdbc.ontology/.settings/org.eclipse.jdt.core.prefs [new file with mode: 0644]
bundles/org.simantics.jdbc.ontology/META-INF/MANIFEST.MF [new file with mode: 0644]
bundles/org.simantics.jdbc.ontology/build.properties [new file with mode: 0644]
bundles/org.simantics.jdbc.ontology/graph/JDBC.pgraph [new file with mode: 0644]
bundles/org.simantics.jdbc.ontology/src/org/simantics/jdbc/ontology/Activator.java [new file with mode: 0644]
bundles/org.simantics.jdbc/.classpath [new file with mode: 0644]
bundles/org.simantics.jdbc/.project [new file with mode: 0644]
bundles/org.simantics.jdbc/.settings/org.eclipse.jdt.core.prefs [new file with mode: 0644]
bundles/org.simantics.jdbc/META-INF/MANIFEST.MF [new file with mode: 0644]
bundles/org.simantics.jdbc/adapters.xml [new file with mode: 0644]
bundles/org.simantics.jdbc/build.properties [new file with mode: 0644]
bundles/org.simantics.jdbc/jdbc.properties [new file with mode: 0644]
bundles/org.simantics.jdbc/src/org/simantics/jdbc/SimanticsJDBC.java [new file with mode: 0644]
bundles/org.simantics.jdbc/src/org/simantics/jdbc/internal/Activator.java [new file with mode: 0644]
bundles/org.simantics.jdbc/src/org/simantics/jdbc/variable/JDBCNode.java [new file with mode: 0644]
bundles/org.simantics.jdbc/src/org/simantics/jdbc/variable/JDBCNodeManager.java [new file with mode: 0644]
bundles/org.simantics.jdbc/src/org/simantics/jdbc/variable/JDBCNodeManagerSupport.java [new file with mode: 0644]
bundles/org.simantics.jdbc/src/org/simantics/jdbc/variable/JDBCRealm.java [new file with mode: 0644]
bundles/org.simantics.jdbc/src/org/simantics/jdbc/variable/JDBCSessionManager.java [new file with mode: 0644]
bundles/org.simantics.jdbc/src/org/simantics/jdbc/variable/JDBCVariableBuilder.java [new file with mode: 0644]
bundles/org.simantics.layer0/graph/Layer0.pgraph
bundles/org.simantics.layer0/graph/Layer0Literals.pgraph
bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagram/style/ConnectionPointNameStyle.java
bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagramEditor/OpenDiagramFromConfigurationAdapter.java
bundles/org.simantics.modeling/src/org/simantics/modeling/SCLTypeUtils.java
bundles/org.simantics.modeling/src/org/simantics/modeling/typicals/SyncTypicalTemplatesToInstances.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/common/names/SCLReservedWords.java [new file with mode: 0644]
bundles/org.simantics.scl.db/scl/Simantics/Variables.scl
bundles/org.simantics.simulation/src/org/simantics/simulation/project/ExperimentRuns.java
bundles/org.simantics.structural2/src/org/simantics/structural2/variables/ActualConnectionDescriptor.java
bundles/org.simantics.ui/src/org/simantics/ui/workbench/ResourceEditorPart.java
bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/SWTDPIUtil.java [new file with mode: 0644]
features/org.simantics.jdbc.feature/.project [new file with mode: 0644]
features/org.simantics.jdbc.feature/build.properties [new file with mode: 0644]
features/org.simantics.jdbc.feature/feature.xml [new file with mode: 0644]
releng/org.simantics.sdk.build.p2.site/pom.xml
releng/org.simantics.sdk.build.targetdefinition/org.simantics.sdk.build.targetdefinition.target
releng/org.simantics.sdk.build.targetdefinition/org.simantics.sdk.build.targetdefinition.tpd
releng/org.simantics.sdk.build.targetdefinition/simantics.target

diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/StructuredProperty.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/StructuredProperty.java
new file mode 100644 (file)
index 0000000..fa6469c
--- /dev/null
@@ -0,0 +1,10 @@
+package org.simantics.db.layer0.variable;
+
+/**
+ * Java interface for StructuredProperty SCL value type.
+ * 
+ * @author Tuukka Lehtonen
+ * @since 1.36.0
+ */
+public interface StructuredProperty {
+}
\ No newline at end of file
index 215b77f3f3204ab90f4b0d2c534d5aa184d9acba..f7a1ad185429f8d17b495ed560a6392566a0add7 100644 (file)
@@ -97,7 +97,7 @@ public class TranslateElement extends ModificationAdapter {
         if (!changed)
             return;
 
-        at.setTransform(at.getScaleX(), at.getShearX(), at.getShearY(), at.getScaleY(), x, y);
+        at.setTransform(at.getScaleX(), at.getShearY(), at.getShearX(), at.getScaleY(), x, y);
 
         DiagramGraphUtil.setTransform(graph, element, at);
         CommentMetadata cm = graph.getMetadata(CommentMetadata.class);
index 588692b917fc3b5a3fa5cdd33ca175311b373c1b..c489373b6a5b0391ea2e64b7f6ec8b22fd78731c 100644 (file)
@@ -27,7 +27,6 @@ import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Event;
 import org.eclipse.swt.widgets.Listener;
 import org.eclipse.swt.widgets.Menu;
-import org.eclipse.swt.widgets.Widget;
 import org.eclipse.ui.IWorkbenchActionConstants;
 import org.eclipse.ui.IWorkbenchPartSite;
 import org.simantics.g2d.canvas.ICanvasContext;
@@ -42,6 +41,7 @@ import org.simantics.utils.datastructures.hints.HintListenerAdapter;
 import org.simantics.utils.datastructures.hints.IHintContext.Key;
 import org.simantics.utils.datastructures.hints.IHintListener;
 import org.simantics.utils.datastructures.hints.IHintObservable;
+import org.simantics.utils.ui.SWTDPIUtil;
 
 /**
  * A participant that initializes an SWT pop-up menu and registers it with the
@@ -221,20 +221,15 @@ public class SWTPopupMenuParticipant extends AbstractCanvasParticipant {
      * @param newValue
      * @thread canvas-thread (AWT)
      */
-    protected void showPopup(Point2D newValue) {
-       final Point2D cp = (Point2D) newValue;
+    protected void showPopup(Point2D cp) {
         setHint(DiagramHints.POPUP_MENU_CONTROL_POSITION, cp);
         setHint(DiagramHints.POPUP_MENU_CANVAS_POSITION, trUtil.controlToCanvas(cp, null));
-        display.asyncExec(new Runnable() {
-            @Override
-            public void run() {
-               if (control == null || control.isDisposed())
-                    return;
-                
-                Point p = control.toDisplay((int) cp.getX(), (int) cp.getY());
-                menuManager.getMenu().setLocation(p);
-                menuManager.getMenu().setVisible(true);
-            }
+        display.asyncExec(() -> {
+            if (control == null || control.isDisposed())
+                return;
+            Point p = control.toDisplay( SWTDPIUtil.downscaleSwtToInteger(cp) );
+            menuManager.getMenu().setLocation(p);
+            menuManager.getMenu().setVisible(true);
         });
     }
 
index eb7fd99281b39255a22d2ca98f3d7cd4e371c86f..e6e4d33ee1e98639ee64e063fd557db368209b5e 100644 (file)
@@ -14,9 +14,6 @@ package org.simantics.diagram.ui.e4;
 import java.awt.geom.Point2D;
 
 import org.eclipse.e4.ui.model.application.ui.basic.MPart;
-import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
-import org.eclipse.e4.ui.model.application.ui.menu.MMenuFactory;
-import org.eclipse.e4.ui.model.application.ui.menu.MPopupMenu;
 import org.eclipse.jface.action.GroupMarker;
 import org.eclipse.jface.action.IMenuListener2;
 import org.eclipse.jface.action.IMenuManager;
@@ -46,6 +43,7 @@ import org.simantics.utils.datastructures.hints.HintListenerAdapter;
 import org.simantics.utils.datastructures.hints.IHintContext.Key;
 import org.simantics.utils.datastructures.hints.IHintListener;
 import org.simantics.utils.datastructures.hints.IHintObservable;
+import org.simantics.utils.ui.SWTDPIUtil;
 
 /**
  * A participant that initializes an SWT pop-up menu and registers it with the
@@ -215,19 +213,15 @@ public class SWTPopupMenuParticipant extends AbstractCanvasParticipant {
      * @param newValue
      * @thread canvas-thread (AWT)
      */
-    protected void showPopup(Point2D newValue) {
-        final Point2D cp = (Point2D) newValue;
+    protected void showPopup(Point2D cp) {
         setHint(DiagramHints.POPUP_MENU_CONTROL_POSITION, cp);
         setHint(DiagramHints.POPUP_MENU_CANVAS_POSITION, trUtil.controlToCanvas(cp, null));
-        display.asyncExec(new Runnable() {
-            @Override
-            public void run() {
-                if (control == null || control.isDisposed())
-                    return;
-                Point p = control.toDisplay((int) cp.getX(), (int) cp.getY());
-                menuManager.getMenu().setLocation(p);
-                menuManager.getMenu().setVisible(true);
-            }
+        display.asyncExec(() -> {
+            if (control == null || control.isDisposed())
+                return;
+            Point p = control.toDisplay( SWTDPIUtil.downscaleSwtToInteger(cp) );
+            menuManager.getMenu().setLocation(p);
+            menuManager.getMenu().setVisible(true);
         });
     }
 
index 10cb3b73f512c4a0b637ef70c8aefc1128596658..85dfc192cbdd2ef30073cb26cf5f71d5f9115b9c 100644 (file)
@@ -34,7 +34,7 @@
             categoryId="org.simantics.g2d"
             id="org.simantics.gallery.itemfont"
             label="Symbol Font"
-            value="Tahoma-regular-8">
+            value="Tahoma-regular-12">
          <description>
             The symbol font is used for labels of symbols in the symbol library view.
          </description>
index aded9d170a2ccc9238b9e72f96e62c79f89fd3ef..0c11d348ab62fcc3860437b1e8a72f779f5349d5 100644 (file)
@@ -155,7 +155,7 @@ public class DiagramHints {
 
     /**
      * A Hint for other participants to use for showing the context menu at the
-     * contol position specified by the Point2D argument.
+     * control position specified by the Point2D argument.
      */
     public static final Key SHOW_POPUP_MENU                = new KeyOf(Point2D.class, "SHOW_POPUP_MENU_CMD");
 
index bb8560c306a1da6091adca58c1c104b50405ed1a..924c7c252b47a929183cfcb4403784486d5f1615 100644 (file)
@@ -34,6 +34,7 @@ import org.simantics.scenegraph.g2d.events.MouseEvent.MouseExitEvent;
 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent;
 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseWheelMovedEvent;
 import org.simantics.scenegraph.g2d.events.adapter.AbstractEventAdapter;
+import org.simantics.utils.ui.SWTDPIUtil;
 
 public class SWTMouseEventAdapter extends AbstractEventAdapter implements MouseListener, MouseMoveListener, MouseTrackListener, MouseWheelListener {
 
@@ -64,12 +65,12 @@ public class SWTMouseEventAdapter extends AbstractEventAdapter implements MouseL
        
        private Point2D getControlPosition(MouseEvent e)
        {
-               return new Point2D.Double(e.x, e.y);
+               return new Point2D.Double(SWTDPIUtil.upscaleSwt(e.x), SWTDPIUtil.upscaleSwt(e.y));
        }
        
        private Point2D getScreenPosition(MouseEvent e)
        {
-               Point p = e.display.getCursorLocation();
+               Point p = SWTDPIUtil.upscaleSwt(e.display.getCursorLocation());
                return new Point2D.Double(p.x, p.y);
                
        }
index 2e8ad5b66f434345ef03e435a5440bb409403fb2..ce5687e8486e05b38f4ca2b28efd72fa8af7b9c7 100644 (file)
@@ -105,6 +105,7 @@ import org.simantics.utils.threads.logger.ITask;
 import org.simantics.utils.threads.logger.ThreadLogger;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.simantics.utils.ui.SWTDPIUtil;
 
 /**
  * @author Toni Kalajainen <toni.kalajainen@vtt.fi>
@@ -165,22 +166,24 @@ public class GalleryViewer extends ContentViewer {
         chassis = new SWTChassis(composite, style) {
             @Override
             public Point computeSize(int wHint, int hHint, boolean changed) {
-//              System.out.println("chassis compute size: " + wHint + ", " + hHint + ", " + changed);
-
                 if (diagram == null)
                     return super.computeSize(wHint, hHint, changed);
 
+                // Note: This code must take into account that FlowLayout expects to 
+                // receive pixel coordinates, not SWT API coordinates.
+
                 Rectangle2D rect;
 //                if (!changed) {
 //                    rect = ElementUtils.getSurroundingElementBoundsOnDiagram(diagram.getSnapshot());
 //                }
 //                else
                 {
-                    Double wH = wHint==SWT.DEFAULT ? null : (double) wHint-vMargin-vMargin;
-                    Double hH = hHint==SWT.DEFAULT ? null : (double) hHint-hMargin-hMargin;
+                    Double wH = wHint==SWT.DEFAULT ? null : (double) SWTDPIUtil.upscaleSwt(wHint)-hMargin*2;
+                    Double hH = hHint==SWT.DEFAULT ? null : (double) SWTDPIUtil.upscaleSwt(hHint)-vMargin*2;
                     rect = fl.computeSize(diagram, wH, hH);
+                    SWTDPIUtil.downscaleSwt(rect, rect);
                 }
-                return new Point((int)rect.getMaxX()+hMargin*2, (int)rect.getMaxY()+vMargin*2);
+                return new Point((int)rect.getWidth()+hMargin*2, (int)rect.getHeight()+vMargin*2);
             }
         };
 
@@ -210,12 +213,7 @@ public class GalleryViewer extends ContentViewer {
             hintCtx.setHint(DiagramHints.KEY_DIAGRAM, diagram);
 
             // Force layout
-            ThreadUtils.asyncExec(swtThread, new Runnable() {
-                @Override
-                public void run() {
-                    resized(false);
-                }
-            });
+            ThreadUtils.asyncExec(swtThread, () -> resized(false));
         });
 
         chassis.addControlListener(new ControlListener() {
@@ -255,12 +253,9 @@ public class GalleryViewer extends ContentViewer {
                     fontRegistry.removeListener(fontRegistryListener);
 
                 // Prevent memory leaks.
-                ThreadUtils.asyncExec(ctx.getThreadAccess(), new Runnable() {
-                    @Override
-                    public void run() {
-                        chassis.getAWTComponent().setCanvasContext(null);
-                        ctx.dispose();
-                    }
+                ThreadUtils.asyncExec(ctx.getThreadAccess(), () -> {
+                    chassis.getAWTComponent().setCanvasContext(null);
+                    ctx.dispose();
                 });
             }
         });
@@ -274,12 +269,7 @@ public class GalleryViewer extends ContentViewer {
             currentItemFont = FontHelper.toAwt(fdn);
             itemClass.getSingleItem(GalleryItemSGNode.class).setFont(currentItemFont);
             // FIXME: a bug exists in this case. The group size will not be refreshed even though the sizes of the gallery items are recalculated and changed.
-            ThreadUtils.asyncExec(swtThread, new Runnable() {
-                @Override
-                public void run() {
-                    resized(true);
-                }
-            });
+            ThreadUtils.asyncExec(swtThread, () -> resized(true));
         }
     };
 
@@ -324,26 +314,25 @@ public class GalleryViewer extends ContentViewer {
         //System.out.println(this + ".resized(" + refreshElementSizes + ")");
         if (chassis.isDisposed())
             return;
-        org.eclipse.swt.graphics.Rectangle b = chassis.getBounds();
+        org.eclipse.swt.graphics.Rectangle b = SWTDPIUtil.upscaleSwt(chassis.getBounds());
+        //System.out.println("chassis bounds: " + b);
         final Rectangle2D bounds = new Rectangle2D.Double(hMargin, vMargin, b.width-hMargin*2, b.height-vMargin*2);
-        ctx.getThreadAccess().asyncExec(new Runnable() {
-            @Override
-            public void run() {
-                if (ctx.isDisposed())
-                    return;
-                if (diagram == null)
-                    return;
-                //System.out.println(this + ".resized(" + refreshElementSizes + ") AWT update");
-                if (refreshElementSizes)
-                    refreshElementSizes();
-                fl.layout(diagram, bounds);
-
-                // Makes sure RTreeNode is marked dirty and everything is
-                // properly repainted.
-                if (itemPainter != null)
-                    itemPainter.updateAll();
-                ctx.getContentContext().setDirty();
-            }});
+        ctx.getThreadAccess().asyncExec(() -> {
+            if (ctx.isDisposed())
+                return;
+            if (diagram == null)
+                return;
+            //System.out.println(this + ".resized(" + refreshElementSizes + ") AWT update");
+            if (refreshElementSizes)
+                refreshElementSizes();
+            fl.layout(diagram, bounds);
+
+            // Makes sure RTreeNode is marked dirty and everything is
+            // properly repainted.
+            if (itemPainter != null)
+                itemPainter.updateAll();
+            ctx.getContentContext().setDirty();
+        });
     }
 
     /**
@@ -392,12 +381,9 @@ public class GalleryViewer extends ContentViewer {
         // wrong thread (SWT) for AWTChassis.
         chassis.getAWTComponent().setCanvasContext(canvasContext);
 
-        swtThread.asyncExec(new Runnable() {
-            @Override
-            public void run() {
-                if (!chassis.isDisposed())
-                    chassis.setCanvasContext(canvasContext);
-            }
+        swtThread.asyncExec(() -> {
+            if (!chassis.isDisposed())
+                chassis.setCanvasContext(canvasContext);
         });
 
         canvasContext.assertParticipantDependencies();
@@ -573,12 +559,7 @@ public class GalleryViewer extends ContentViewer {
                 // 3. Calculate maximum vertical space needed by current diagram element texts
                 refreshElementSizes();
 
-                ThreadUtils.asyncExec(swtThread, new Runnable() {
-                    @Override
-                    public void run() {
-                        resized(false);
-                    }
-                });
+                ThreadUtils.asyncExec(swtThread, () -> resized(false));
                 // $AWT-Thread-End$
             }
         });
@@ -609,9 +590,9 @@ public class GalleryViewer extends ContentViewer {
         // Calculate maximum vertical space needed by current diagram element texts
         FontMetrics metrics = awtComponent.getFontMetrics(currentItemFont);
         int fontHeight = metrics.getHeight();
-        int maxWidth = (int) itemSize.getWidth();
-        Rectangle2D size = itemSize;
-        java.awt.Point targetSize = new java.awt.Point((int) itemSize.getWidth(), (int) itemSize.getHeight());
+        Rectangle2D size = SWTDPIUtil.upscaleSwt(itemSize);
+        int maxWidth = (int) size.getWidth();
+        java.awt.Point targetSize = new java.awt.Point((int) size.getWidth(), (int) size.getHeight());
         diagram.setHint(DiagramHints.KEY_ELEMENT_RASTER_TARGET_SIZE, targetSize);
         int maxLinesNeeded = 0;
         for (IElement el : diagram.getElements()) {
@@ -619,7 +600,7 @@ public class GalleryViewer extends ContentViewer {
             // for caching rendered images in the correct size only.
             // NOTE: currently this is not used in GalleryItemPainter since the
             // target size is now propagated through the element class loading
-            // process through the diagram hint KEY_ELEMENT_RASTER_REFERENCE_SIZE.
+            // process through the diagram hint KEY_ELEMENT_RASTER_TARGET_SIZE.
             el.setHint(GalleryItemSGNode.KEY_TARGET_IMAGE_SIZE, targetSize);
 
             String text = ElementUtils.getText(el);
@@ -647,14 +628,11 @@ public class GalleryViewer extends ContentViewer {
                 if (image != i)
                     continue;
 
-                ctx.getThreadAccess().asyncExec(new Runnable() {
-                    @Override
-                    public void run() {
-                        //System.out.println(Thread.currentThread() + ": update scene graph(" + el + ")");
-                        // Update scene graph and repaint.
-                        el.getElementClass().getSingleItem(GalleryItemSGNode.class).update(el);
-                        ctx.getContentContext().setDirty();
-                    }
+                ctx.getThreadAccess().asyncExec(() -> {
+                    //System.out.println(Thread.currentThread() + ": update scene graph(" + el + ")");
+                    // Update scene graph and repaint.
+                    el.getElementClass().getSingleItem(GalleryItemSGNode.class).update(el);
+                    ctx.getContentContext().setDirty();
                 });
                 break;
             }
@@ -665,12 +643,9 @@ public class GalleryViewer extends ContentViewer {
         if (ctx.getThreadAccess().currentThreadAccess()) {
             ctx.add(p);
         } else {
-            ctx.getThreadAccess().asyncExec(new Runnable() {
-                @Override
-                public void run() {
-                    if (!ctx.isDisposed())
-                        ctx.add(p);
-                }
+            ctx.getThreadAccess().asyncExec(() -> {
+                if (!ctx.isDisposed())
+                    ctx.add(p);
             });
         }
     }
@@ -679,12 +654,9 @@ public class GalleryViewer extends ContentViewer {
         if (ctx.getThreadAccess().currentThreadAccess()) {
             ctx.add(p);
         } else {
-            ctx.getThreadAccess().asyncExec(new Runnable() {
-                @Override
-                public void run() {
-                    if (!ctx.isDisposed())
-                        ctx.add(p);
-                }
+            ctx.getThreadAccess().asyncExec(() -> {
+                if (!ctx.isDisposed())
+                    ctx.add(p);
             });
         }
     }
index 06bd80aa8e027c45a971de4b179bf1899c3e38c6..98d5c78f664759653e2a5ffad20cbf7600da24af 100644 (file)
 package org.simantics.g2d.utils;
 
 import java.awt.Font;
-import java.awt.Toolkit;
 
 import org.eclipse.jface.resource.FontRegistry;
 import org.eclipse.swt.graphics.FontData;
 import org.eclipse.ui.PlatformUI;
+import org.simantics.utils.ui.SWTDPIUtil;
 
 public final class FontHelper {
 
@@ -35,8 +35,7 @@ public final class FontHelper {
     }
 
     public static java.awt.Font toAwt(FontData fd) {
-        int resolution = Toolkit.getDefaultToolkit().getScreenResolution();
-        int awtFontSize = (int) Math.round((double) fd.getHeight() * resolution / 72.0);
+        int awtFontSize = SWTDPIUtil.upscaleSwt(fd.getHeight());
         // The style constants for SWT and AWT map exactly, and since they are int constants, they should
         // never change. So, the SWT style is passed through as the AWT style.
         Font font = new java.awt.Font(fd.getName(), fd.getStyle(), awtFontSize);
diff --git a/bundles/org.simantics.jdbc.ontology/.classpath b/bundles/org.simantics.jdbc.ontology/.classpath
new file mode 100644 (file)
index 0000000..eca7bdb
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+       <classpathentry kind="src" path="src"/>
+       <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/bundles/org.simantics.jdbc.ontology/.project b/bundles/org.simantics.jdbc.ontology/.project
new file mode 100644 (file)
index 0000000..6668cd1
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>org.simantics.jdbc.ontology</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.simantics.graph.builder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.pde.ManifestBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.pde.SchemaBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.pde.PluginNature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+               <nature>org.simantics.graph.nature</nature>
+       </natures>
+</projectDescription>
diff --git a/bundles/org.simantics.jdbc.ontology/.settings/org.eclipse.jdt.core.prefs b/bundles/org.simantics.jdbc.ontology/.settings/org.eclipse.jdt.core.prefs
new file mode 100644 (file)
index 0000000..0c68a61
--- /dev/null
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/bundles/org.simantics.jdbc.ontology/META-INF/MANIFEST.MF b/bundles/org.simantics.jdbc.ontology/META-INF/MANIFEST.MF
new file mode 100644 (file)
index 0000000..69dae10
--- /dev/null
@@ -0,0 +1,12 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: http://www.simantics.org/JDBC-1.0
+Bundle-SymbolicName: org.simantics.jdbc.ontology
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: org.simantics.jdbc.ontology.Activator
+Require-Bundle: org.eclipse.core.runtime,
+ org.simantics.layer0,
+ org.simantics.selectionview.ontology;bundle-version="1.2.0"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Bundle-ActivationPolicy: lazy
+Export-Package: org.simantics.jdbc
diff --git a/bundles/org.simantics.jdbc.ontology/build.properties b/bundles/org.simantics.jdbc.ontology/build.properties
new file mode 100644 (file)
index 0000000..e85b630
--- /dev/null
@@ -0,0 +1,5 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               graph.tg
diff --git a/bundles/org.simantics.jdbc.ontology/graph/JDBC.pgraph b/bundles/org.simantics.jdbc.ontology/graph/JDBC.pgraph
new file mode 100644 (file)
index 0000000..432e10c
--- /dev/null
@@ -0,0 +1,10 @@
+L0 = <http://www.simantics.org/Layer0-1.1>
+SEL = <http://www.simantics.org/SelectionView-1.2>
+
+JDBC = <http://www.simantics.org/JDBC-1.0> : L0.Ontology
+    @L0.new
+    L0.HasResourceClass "org.simantics.jdbc.JDBCResource"
+    
+JDBC.Session <T L0.Entity
+    >-- JDBC.Session.hasValue --> L0.Value <R L0.HasProperty : SEL.GenericParameterType
\ No newline at end of file
diff --git a/bundles/org.simantics.jdbc.ontology/src/org/simantics/jdbc/ontology/Activator.java b/bundles/org.simantics.jdbc.ontology/src/org/simantics/jdbc/ontology/Activator.java
new file mode 100644 (file)
index 0000000..596e25d
--- /dev/null
@@ -0,0 +1,30 @@
+package org.simantics.jdbc.ontology;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+public class Activator implements BundleActivator {
+
+       private static BundleContext context;
+
+       static BundleContext getContext() {
+               return context;
+       }
+
+       /*
+        * (non-Javadoc)
+        * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
+        */
+       public void start(BundleContext bundleContext) throws Exception {
+               Activator.context = bundleContext;
+       }
+
+       /*
+        * (non-Javadoc)
+        * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
+        */
+       public void stop(BundleContext bundleContext) throws Exception {
+               Activator.context = null;
+       }
+
+}
diff --git a/bundles/org.simantics.jdbc/.classpath b/bundles/org.simantics.jdbc/.classpath
new file mode 100644 (file)
index 0000000..b862a29
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>\r
+       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>\r
+       <classpathentry kind="src" path="src"/>\r
+       <classpathentry kind="output" path="bin"/>\r
+</classpath>\r
diff --git a/bundles/org.simantics.jdbc/.project b/bundles/org.simantics.jdbc/.project
new file mode 100644 (file)
index 0000000..3af9a2f
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>org.simantics.jdbc</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.simantics.graph.builder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.pde.ManifestBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.pde.SchemaBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.pde.PluginNature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+               <nature>org.simantics.graph.nature</nature>
+       </natures>
+</projectDescription>
diff --git a/bundles/org.simantics.jdbc/.settings/org.eclipse.jdt.core.prefs b/bundles/org.simantics.jdbc/.settings/org.eclipse.jdt.core.prefs
new file mode 100644 (file)
index 0000000..0c68a61
--- /dev/null
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/bundles/org.simantics.jdbc/META-INF/MANIFEST.MF b/bundles/org.simantics.jdbc/META-INF/MANIFEST.MF
new file mode 100644 (file)
index 0000000..9aff2f4
--- /dev/null
@@ -0,0 +1,24 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Simantics JDBC support
+Bundle-SymbolicName: org.simantics.jdbc
+Bundle-Version: 1.0.0.qualifier
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Bundle-ClassPath: .
+Require-Bundle: org.eclipse.osgi,
+ org.simantics.simulator.toolkit,
+ org.simantics.databoard,
+ gnu.trove3;bundle-version="3.0.3",
+ org.slf4j.api;bundle-version="1.7.25",
+ org.simantics.db.layer0,
+ org.simantics.simulator.toolkit.db,
+ org.simantics,
+ org.simantics.jdbc.ontology,
+ io.netty.buffer;bundle-version="4.1.27",
+ io.netty.codec;bundle-version="4.1.27",
+ io.netty.common;bundle-version="4.1.27",
+ io.netty.handler;bundle-version="4.1.27",
+ io.netty.transport;bundle-version="4.1.27",
+ pgjdbc-ng;bundle-version="0.7.1"
+Export-Package: org.simantics.jdbc,
+ org.simantics.jdbc.variable
diff --git a/bundles/org.simantics.jdbc/adapters.xml b/bundles/org.simantics.jdbc/adapters.xml
new file mode 100644 (file)
index 0000000..800ee14
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<adapters>
+    <target interface="org.simantics.db.layer0.variable.VariableBuilder">
+        <type uri="http://www.simantics.org/JDBC-1.0/Session" class="org.simantics.jdbc.variable.JDBCVariableBuilder" />
+    </target>
+</adapters>
\ No newline at end of file
diff --git a/bundles/org.simantics.jdbc/build.properties b/bundles/org.simantics.jdbc/build.properties
new file mode 100644 (file)
index 0000000..0dc8dce
--- /dev/null
@@ -0,0 +1,6 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               adapters.xml,\
+               jdbc.properties
diff --git a/bundles/org.simantics.jdbc/jdbc.properties b/bundles/org.simantics.jdbc/jdbc.properties
new file mode 100644 (file)
index 0000000..7f23859
--- /dev/null
@@ -0,0 +1,5 @@
+simantics.jdbc.host=127.0.0.1
+simantics.jdbc.port=5432
+simantics.jdbc.user=simantics
+simantics.jdbc.password=simantics
+simantics.jdbc.database=simantics
\ No newline at end of file
diff --git a/bundles/org.simantics.jdbc/src/org/simantics/jdbc/SimanticsJDBC.java b/bundles/org.simantics.jdbc/src/org/simantics/jdbc/SimanticsJDBC.java
new file mode 100644 (file)
index 0000000..ac287e6
--- /dev/null
@@ -0,0 +1,45 @@
+package org.simantics.jdbc;
+
+import org.simantics.databoard.Bindings;
+import org.simantics.db.Resource;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.util.Layer0Utils;
+import org.simantics.db.layer0.variable.Variable;
+import org.simantics.db.layer0.variable.Variables;
+import org.simantics.layer0.Layer0;
+
+/**
+ * Simantics JDBC facade.
+ * 
+ * @author Jani Simomaa
+ */
+public class SimanticsJDBC {
+
+    public static final String PROP_SIMANTICS_JDBC_PROPERTYFILE = "simantics.jdbc.propertyfile";
+    public static final String PROP_SIMANTICS_JDBC_HOST         = "simantics.jdbc.host";
+    public static final String PROP_SIMANTICS_JDBC_PORT         = "simantics.jdbc.port";
+    public static final String PROP_SIMANTICS_JDBC_USER         = "simantics.jdbc.user";
+    public static final String PROP_SIMANTICS_JDBC_PASSWORD     = "simantics.jdbc.password";
+    public static final String PROP_SIMANTICS_JDBC_DATABASE     = "simantics.jdbc.database";
+
+    public static String createJDBCSession(WriteGraph graph, String sessionGUID) throws DatabaseException {
+        Resource projects = graph.getResource("http://Projects");
+        Resource documentSessions = Layer0Utils.getPossibleChild(graph, projects, "DocumentSessions");
+        Layer0 L0 = Layer0.getInstance(graph);
+        Resource documentSession = Layer0Utils.getPossibleChild(graph, documentSessions, sessionGUID);
+
+        String sessionId = "http://Projects/DocumentSessions/" + sessionGUID + "/__jdbc__";
+
+        JDBCResource JDBC = JDBCResource.getInstance(graph);
+        Resource jdbcSession = graph.newResource();
+        graph.claim(jdbcSession, L0.InstanceOf, JDBC.Session);
+        graph.claimLiteral(jdbcSession, L0.HasName, L0.NameOf, L0.String, "__jdbc__", Bindings.STRING);
+        graph.claim(documentSession, L0.ConsistsOf, jdbcSession);
+
+        @SuppressWarnings("unused")
+        Variable jdbcState = Variables.getVariable(graph, jdbcSession);
+
+        return sessionId;
+    }
+}
diff --git a/bundles/org.simantics.jdbc/src/org/simantics/jdbc/internal/Activator.java b/bundles/org.simantics.jdbc/src/org/simantics/jdbc/internal/Activator.java
new file mode 100644 (file)
index 0000000..0f9da36
--- /dev/null
@@ -0,0 +1,18 @@
+package org.simantics.jdbc.internal;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+public class Activator implements BundleActivator {
+
+    @Override
+    public void start(BundleContext context) throws Exception {
+        
+    }
+
+    @Override
+    public void stop(BundleContext context) throws Exception {
+        
+    }
+
+}
diff --git a/bundles/org.simantics.jdbc/src/org/simantics/jdbc/variable/JDBCNode.java b/bundles/org.simantics.jdbc/src/org/simantics/jdbc/variable/JDBCNode.java
new file mode 100644 (file)
index 0000000..54f5d39
--- /dev/null
@@ -0,0 +1,41 @@
+package org.simantics.jdbc.variable;
+
+import org.simantics.simulator.toolkit.StandardNode;
+
+public class JDBCNode implements StandardNode {
+
+    public String name;
+
+    public JDBCNode(String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((name == null) ? 0 : name.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        JDBCNode other = (JDBCNode) obj;
+        if (name == null) {
+            if (other.name != null)
+                return false;
+        } else if (!name.equals(other.name))
+            return false;
+        return true;
+    }
+}
diff --git a/bundles/org.simantics.jdbc/src/org/simantics/jdbc/variable/JDBCNodeManager.java b/bundles/org.simantics.jdbc/src/org/simantics/jdbc/variable/JDBCNodeManager.java
new file mode 100644 (file)
index 0000000..fd25852
--- /dev/null
@@ -0,0 +1,21 @@
+package org.simantics.jdbc.variable;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.simantics.simulator.toolkit.StandardNodeManager;
+import org.simantics.simulator.toolkit.StandardRealm;
+import org.simantics.simulator.variable.exceptions.NodeManagerException;
+
+public class JDBCNodeManager extends StandardNodeManager<JDBCNode, JDBCNodeManagerSupport> {
+
+    public JDBCNodeManager(StandardRealm<JDBCNode, JDBCNodeManagerSupport> realm, JDBCNode root) {
+        super(realm, root);
+    }
+
+    @Override
+    public Set<String> getClassifications(JDBCNode node) throws NodeManagerException {
+        return Collections.emptySet();
+    }
+
+}
diff --git a/bundles/org.simantics.jdbc/src/org/simantics/jdbc/variable/JDBCNodeManagerSupport.java b/bundles/org.simantics.jdbc/src/org/simantics/jdbc/variable/JDBCNodeManagerSupport.java
new file mode 100644 (file)
index 0000000..b1c16a6
--- /dev/null
@@ -0,0 +1,123 @@
+package org.simantics.jdbc.variable;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.simantics.databoard.Bindings;
+import org.simantics.databoard.binding.Binding;
+import org.simantics.simulator.toolkit.StandardNodeManagerSupport;
+import org.simantics.simulator.variable.exceptions.NodeManagerException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.impossibl.postgres.api.jdbc.PGConnection;
+import com.impossibl.postgres.jdbc.PGDataSource;
+
+public class JDBCNodeManagerSupport implements StandardNodeManagerSupport<JDBCNode> {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(JDBCNodeManagerSupport.class);
+    @SuppressWarnings("unused")
+    private String id; // this might have some use later in the future?
+    private PGDataSource dataSource;
+    private String channelName;
+
+    public JDBCNodeManagerSupport(String id, PGDataSource dataSource, String channelName) {
+        this.id = id;
+        this.dataSource = dataSource;
+        this.channelName = channelName;
+    }
+
+    @Override
+    public Object getEngineValue(JDBCNode node) throws NodeManagerException {
+        if (LOGGER.isDebugEnabled())
+            LOGGER.debug("Getting value for {}", node.getName());
+
+        try (PGConnection connection = (PGConnection) dataSource.getConnection()) {
+            // do get value
+            PreparedStatement ps = connection.prepareStatement("SELECT value->'value' FROM simantics_table WHERE key IN ('" + node.getName() + "');");
+            ResultSet rs = ps.executeQuery();
+            if (!rs.next()) {
+                if (LOGGER.isDebugEnabled()) {
+                    LOGGER.debug("no value for query {}", ps.toString());
+                }
+                return null;
+            }
+            return rs.getObject(1);
+        } catch (Exception e) {
+            LOGGER.error("Failed to get value for {}", node.getName(), e);
+            throw new NodeManagerException("Failed to get value for " + node.getName(), e);
+        }
+    }
+
+    @Override
+    public Binding getEngineBinding(JDBCNode node) throws NodeManagerException {
+        return Bindings.OBJECT;
+    }
+
+    @Override
+    public void setEngineValue(JDBCNode node, Object value) throws NodeManagerException {
+        if (LOGGER.isDebugEnabled())
+            LOGGER.debug("Setting value for {} to {}", node.getName(), value);
+
+        setValueImpl(node.getName(), value);
+    }
+
+    private void setValueImpl(String name, Object value) throws NodeManagerException {
+        try (PGConnection connection = (PGConnection) dataSource.getConnection()) {
+            // do set value
+            PreparedStatement statement = connection.prepareStatement("INSERT INTO simantics_table VALUES (?, ?::JSON) ON CONFLICT (key) DO UPDATE SET value= ?::JSON");
+            statement.setString(1, name);
+            statement.setObject(2, "{\"value\": " + value.toString() + "}");
+            statement.setObject(3, "{\"value\": " + value.toString() + "}");
+            statement.executeUpdate();
+
+            // notify others (including ourselves)
+            doNotify(connection, name);
+        } catch (Exception e) {
+            LOGGER.error("Failed to set value for {} to {}", name, value, e);
+            throw new NodeManagerException("Failed to set value for " + name + " to " + String.valueOf(value), e);
+        }
+    }
+
+    private void doNotify(PGConnection connection, String name) throws SQLException {
+        if (LOGGER.isDebugEnabled())
+            LOGGER.debug("Notifying change {} to channel {}", name, this.channelName);
+        Statement statement = connection.createStatement();
+        String sql = "NOTIFY " + this.channelName + ", '" + name + "'";
+        statement.execute(sql);
+        statement.close();
+    }
+
+    @Override
+    public String getName(JDBCNode node) {
+        return node.getName();
+    }
+
+    @Override
+    public Map<String, JDBCNode> getChildren(JDBCNode node) {
+        return Collections.emptyMap();
+    }
+
+    @Override
+    public Map<String, JDBCNode> getProperties(JDBCNode node) {
+        HashMap<String, JDBCNode> properties = new HashMap<>();
+        try (PGConnection connection = (PGConnection) dataSource.getConnection()) {
+            Statement st = connection.createStatement();
+            ResultSet executeQuery = st.executeQuery("SELECT key FROM simantics_table");
+            while (executeQuery.next()) {
+                String key = executeQuery.getString(1);
+                properties.put(key, new JDBCNode(key));
+            }
+        } catch (Exception e) {
+            LOGGER.error("Could not read properties", e);
+        }
+
+        return properties;
+    }
+
+}
diff --git a/bundles/org.simantics.jdbc/src/org/simantics/jdbc/variable/JDBCRealm.java b/bundles/org.simantics.jdbc/src/org/simantics/jdbc/variable/JDBCRealm.java
new file mode 100644 (file)
index 0000000..9a6f4ab
--- /dev/null
@@ -0,0 +1,28 @@
+package org.simantics.jdbc.variable;
+
+import org.simantics.simulator.toolkit.StandardNodeManager;
+import org.simantics.simulator.toolkit.StandardRealm;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class JDBCRealm extends StandardRealm<JDBCNode, JDBCNodeManagerSupport> {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(JDBCRealm.class);
+
+    protected JDBCRealm(JDBCNodeManagerSupport engine, String id) {
+        super(engine, id);
+    }
+
+    @Override
+    protected StandardNodeManager<JDBCNode, JDBCNodeManagerSupport> createManager() {
+        if (LOGGER.isDebugEnabled())
+            LOGGER.debug("Creating {} for realm with id {}", JDBCNodeManager.class.getSimpleName(), getId());
+        return new JDBCNodeManager(this, new JDBCNode("ROOT"));
+    }
+
+    @Override
+    public Logger getLogger() {
+        return LOGGER;
+    }
+
+}
diff --git a/bundles/org.simantics.jdbc/src/org/simantics/jdbc/variable/JDBCSessionManager.java b/bundles/org.simantics.jdbc/src/org/simantics/jdbc/variable/JDBCSessionManager.java
new file mode 100644 (file)
index 0000000..f6a6077
--- /dev/null
@@ -0,0 +1,208 @@
+package org.simantics.jdbc.variable;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.nio.file.Paths;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Properties;
+import java.util.function.Function;
+
+import org.simantics.Simantics;
+import org.simantics.databoard.Bindings;
+import org.simantics.databoard.binding.error.BindingException;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.common.request.ReadRequest;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.variable.NodeSupport;
+import org.simantics.jdbc.SimanticsJDBC;
+import org.simantics.simulator.toolkit.StandardRealm;
+import org.simantics.simulator.toolkit.db.StandardSessionManager;
+import org.simantics.simulator.variable.exceptions.NodeManagerException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.impossibl.postgres.api.jdbc.PGConnection;
+import com.impossibl.postgres.api.jdbc.PGNotificationListener;
+import com.impossibl.postgres.jdbc.PGDataSource;
+
+public class JDBCSessionManager extends StandardSessionManager<JDBCNode, JDBCNodeManagerSupport> {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(JDBCSessionManager.class);
+    private static JDBCSessionManager INSTANCE = new JDBCSessionManager();
+
+    private static final String VALUE_SIMANTICS_JDBC_HOST     = "localhost";
+    private static final int    VALUE_SIMANTICS_JDBC_PORT     = 5432;
+    private static final String VALUE_SIMANTICS_JDBC_USER     = "simantics";
+    private static final String VALUE_SIMANTICS_JDBC_PASSWORD = "simantics";
+    private static final String VALUE_SIMANTICS_JDBC_DATABASE = "simantics";
+
+    private String channelName;
+    private PGNotificationListener listener;
+
+    private PGDataSource dataSource;
+    private Connection connection;
+
+    private static Properties readProperties(InputStream s) throws IOException {
+        try (InputStream is = s) {
+            Properties props = new Properties();
+            props.load(is);
+            return props;
+        }
+    }
+
+    private static Properties safeReadProperties(URL url) {
+        try {
+            return readProperties(url.openStream());
+        } catch (IOException e) {
+            LOGGER.error("Could not read props from " + url, e);
+            return null;
+        }
+    }
+
+    private static Properties safeReadProperties(URI uri) {
+        try {
+            return safeReadProperties(uri.toURL());
+        } catch (MalformedURLException e) {
+            LOGGER.error("Could not read props from " + uri, e);
+            return null;
+        }
+    }
+
+    private static Properties safeReadProperties(String path) {
+        return safeReadProperties(Paths.get(path).toUri());
+    }
+
+    private static Properties readProperties() {
+        String propFile = System.getProperty(SimanticsJDBC.PROP_SIMANTICS_JDBC_PROPERTYFILE, null);
+        if (propFile != null) {
+            Properties p = safeReadProperties(propFile);
+            if (p != null)
+                return p;
+        }
+        // Read default settings from built-in file and override them with values in System properties 
+        Properties p = safeReadProperties(JDBCSessionManager.class.getClassLoader().getResource("jdbc.properties"));
+        if (p != null) {
+            p.putAll(System.getProperties());
+        } else {
+            p = System.getProperties();
+        }
+        return p;
+    }
+
+    public JDBCSessionManager() {
+        this.channelName = "test";
+
+        Properties props = readProperties();
+        String host = props.getProperty(SimanticsJDBC.PROP_SIMANTICS_JDBC_HOST, VALUE_SIMANTICS_JDBC_HOST);
+        String port = props.getProperty(SimanticsJDBC.PROP_SIMANTICS_JDBC_PORT, "" + VALUE_SIMANTICS_JDBC_PORT);
+        String database = props.getProperty(SimanticsJDBC.PROP_SIMANTICS_JDBC_DATABASE, VALUE_SIMANTICS_JDBC_DATABASE);
+        String user = props.getProperty(SimanticsJDBC.PROP_SIMANTICS_JDBC_USER, VALUE_SIMANTICS_JDBC_USER);
+        String password = props.getProperty(SimanticsJDBC.PROP_SIMANTICS_JDBC_PASSWORD, VALUE_SIMANTICS_JDBC_PASSWORD);
+
+        try {
+            int portNumber = Integer.valueOf(port);
+
+            dataSource = new PGDataSource();
+            dataSource.setHost(host);
+            dataSource.setPort(portNumber);
+            dataSource.setDatabase(database);
+            dataSource.setUser(user);
+            dataSource.setPassword(password);
+
+            this.connection = dataSource.getConnection();
+            this.listener = new PGNotificationListener() {
+                @Override
+                public void notification(int processId, String channelName, String payload) {
+                    if (LOGGER.isDebugEnabled())
+                        LOGGER.debug("Received notification from processId={} channelName={} and payload={}", processId, channelName, payload);
+                    Simantics.getSession().asyncRequest(new ReadRequest() {
+                        @Override
+                        public void run(ReadGraph graph) throws DatabaseException {
+                            for (String realmId : INSTANCE.getRealms()) {
+                                try {
+                                    JDBCRealm jdbcRealm = (JDBCRealm) INSTANCE.getOrCreateRealm(graph, realmId);
+                                    jdbcRealm.getNodeManager().refreshVariable(new JDBCNode(payload));
+                                } catch (DatabaseException e) {
+                                    LOGGER.error("Could not refresh variable in realm {} with payload {}", realmId, payload, e);
+                                }
+                            }
+                        }
+                    });
+                }
+            };
+            createTable();
+            init();
+        } catch (SQLException e) {
+            LOGGER.error("Could not initialize JDBCSessionManager!", e);
+        }
+    }
+    
+    private void createTable() throws SQLException {
+        Statement statement = connection.createStatement();
+        statement.execute("CREATE TABLE IF NOT EXISTS simantics_table (key VARCHAR UNIQUE, value JSON)");
+        statement.close();
+    }
+
+    protected void init() throws SQLException {
+        Statement statement = connection.createStatement();
+        statement.execute("LISTEN " + this.channelName);
+        statement.close();
+        ((PGConnection) connection).addNotificationListener(this.listener);
+    }
+
+    protected void destroy() throws SQLException {
+        try (PGConnection connection = (PGConnection) dataSource.getConnection()) {
+            Statement statement = connection.createStatement();
+            statement.execute("UNLISTEN " + this.channelName);
+            statement.close();
+        }
+    }
+
+
+    @Override
+    protected JDBCNodeManagerSupport createEngine(ReadGraph graph, String id) throws DatabaseException {
+        return new JDBCNodeManagerSupport(id, this.dataSource, this.channelName);
+    }
+
+    @Override
+    protected StandardRealm<JDBCNode, JDBCNodeManagerSupport> createRealm(JDBCNodeManagerSupport engine, String id) {
+        return new JDBCRealm(engine, id);
+    }
+
+    public static void setValue(ReadGraph graph, String id, String key, Object value) throws DatabaseException, NodeManagerException, BindingException, InterruptedException {
+        JDBCRealm realm = (JDBCRealm) INSTANCE.getOrCreateRealm(graph, id);
+        realm.asyncExec(() -> {
+            try {
+                realm.getNodeManager().setValue(new JDBCNode(key), key, value, Bindings.OBJECT);
+            } catch (NodeManagerException | BindingException e) {
+                LOGGER.error("Could not set value {} for {}", value, key, e);
+            }
+        });
+    }
+
+    public static NodeSupport<?> nodeSupport(ReadGraph graph, String sessionName) throws DatabaseException {
+        return INSTANCE.getOrCreateNodeSupport(graph, sessionName);
+    }
+
+    public static Object getValue(ReadGraph graph, String uri, String key) throws InterruptedException, DatabaseException {
+        JDBCRealm realm = (JDBCRealm) INSTANCE.getOrCreateRealm(graph, uri);
+        return realm.syncExec(new Function<Object, Object>() {
+
+            @Override
+            public Object apply(Object t) {
+                try {
+                    return realm.getNodeManager().getValue(new JDBCNode(key), key).getValue();
+                } catch (NodeManagerException e) {
+                    LOGGER.error("Could not get value for {}", key, e);
+                    return null;
+                }
+            }
+        });
+    }
+
+}
diff --git a/bundles/org.simantics.jdbc/src/org/simantics/jdbc/variable/JDBCVariableBuilder.java b/bundles/org.simantics.jdbc/src/org/simantics/jdbc/variable/JDBCVariableBuilder.java
new file mode 100644 (file)
index 0000000..c633fd7
--- /dev/null
@@ -0,0 +1,21 @@
+package org.simantics.jdbc.variable;
+
+import org.simantics.db.ReadGraph;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.variable.NodeManagerVariableBuilder;
+import org.simantics.db.layer0.variable.NodeSupport;
+
+public class JDBCVariableBuilder extends NodeManagerVariableBuilder {
+
+    @Override
+    protected NodeSupport<?> getNodeSupport(ReadGraph graph, String sessionName) throws DatabaseException {
+        return JDBCSessionManager.nodeSupport(graph, sessionName);
+    }
+
+    @Override
+    protected Object getRoot(ReadGraph graph, NodeSupport<?> support, String sessionName) throws DatabaseException {
+        JDBCNodeManager manager = (JDBCNodeManager) support.manager;
+        return manager.getRoot();
+    }
+
+}
index 5fe74ec0175fd9e358bd724dc2e36f47672c2fdb..225a4f17ee79c075da4c75164749dec77de459dc 100644 (file)
@@ -22,6 +22,7 @@ L0.Entity : L0.Type
     >-- L0.identifier <R L0.HasProperty : L0.FunctionalRelation
         L0.HasLabel "Identifier"
         --> L0.GUID
+        ==> "GUID"
     >-- L0.typeURI <R L0.HasProperty : L0.FunctionalRelation
         L0.HasLabel "Type URI"
         --> L0.String
@@ -42,7 +43,7 @@ L0.Entity : L0.Type
     @L0.assert L0.Entity.methods
       _ : L0.Value
     
-L0.Entity.methods --> L0.Value <R L0.HasProperty : L0.FunctionalRelation
+L0.Entity.methods ==> "StructuredProperty" <R L0.HasProperty : L0.FunctionalRelation
   L0.domainProperties L0.Functions.methodsPropertyDomainProperties
   
 L0.Entity.method <R L0.HasProperty : L0.FunctionalRelation
index 329cfa12dc7576c302420de57bd1586b1517466f..08f6f27a819de56191fa197ace79976618b194db 100644 (file)
@@ -103,7 +103,7 @@ L0.Literal.FloatValidator <T L0.Value
 L0.Literal.DoubleValidator <T L0.Value
 
 L0.GUID <T L0.Literal
-    @L0.assert L0.HasValueType "(Long,Long)"
+    @L0.assert L0.HasValueType "GUID"
     @L0.assert L0.HasDataType ${ mostSigBits : Long, leastSigBits : Long }
     
 L0.TypeWithIdentifier <T L0.Entity
index a4f32e81139a5f22d699af3e7d15a5ee7ba3578b..d86925e485d187ef8d48e25535a091ffbcb5facd 100644 (file)
@@ -159,8 +159,8 @@ public class ConnectionPointNameStyle extends StyleBase<List<ConnectionPointName
         // always clean up old items before drawing new items
         cleanupStyleForNode(_node);
 
-        int count = resultList.size();
-        if (resultList == null || count < 2)
+        int count = resultList != null ? resultList.size() : 0;
+        if (count < 2)
             return;
 
         G2DParentNode parentNode = ProfileVariables.claimChild(_node, "", PARENT_NODE_NAME_PREFIX, G2DParentNode.class, observer);
index 978d1f89595989dc811de829f1051941edec5190..1ba559e563245878643c2aa06927b3471e6640b8 100644 (file)
@@ -150,42 +150,51 @@ public class OpenDiagramFromConfigurationAdapter extends AbstractResourceEditorA
      * @param selectedObjects
      * @throws DatabaseException
      */
-    public static boolean openEditor(ReadGraph g, Resource r, final String editorId, final Collection<Object> selectedObjects) throws DatabaseException {
-
-        final Resource diagram = getDiagram(g, r, selectedObjects);
-        if (diagram == null)
-            return false;
-
-        final Resource configurationComposite = ComponentUtils.getPossibleDiagramComposite(g, diagram);
-        if (configurationComposite == null)
-            return false;
-
-        Pair<Resource, RVI> modelAndRVI = getModelAndRVI(g, configurationComposite);
+    public static boolean openEditor(ReadGraph g, Resource r, String editorId, Collection<Object> selectedObjects) throws DatabaseException {
+        Resource diagram = getDiagram(g, r, selectedObjects);
+        Resource configurationComposite = diagram != null ? ComponentUtils.getPossibleDiagramComposite(g, diagram) : null;
+        Pair<Resource, RVI> modelAndRVI = configurationComposite != null ? getModelAndRVI(g, configurationComposite) : null;
         //System.out.println("modelAndRVI: " + modelAndRVI);
         if (modelAndRVI == null)
             return false;
+        scheduleOpenEditor(editorId, diagram, modelAndRVI.first, modelAndRVI.second, selectedObjects);
+        return true;
+    }
+
+    /**
+     * @param g
+     * @param configurationComposite
+     * @param editorId
+     * @param selectedObjects
+     * @throws DatabaseException
+     */
+    public static boolean openEditor(ReadGraph g, Resource r, String editorId, Collection<Object> selectedObjects, Resource model, RVI rvi) throws DatabaseException {
+        Resource diagram = getDiagram(g, r, selectedObjects);
+        if (diagram == null)
+            return false;
+        scheduleOpenEditor(editorId, diagram, model, rvi, selectedObjects);
+        return true;
+    }
 
-        final Runnable editorActivator = NavigateToTarget.editorActivator(editorId, diagram, modelAndRVI.first, modelAndRVI.second, part -> {
+    /**
+     * @param g
+     * @param configurationComposite
+     * @param editorId
+     * @param selectedObjects
+     * @throws DatabaseException
+     */
+    private static void scheduleOpenEditor(String editorId, Resource diagram, Resource model, RVI rvi, Collection<Object> selectedObjects) throws DatabaseException {
+        Runnable editorActivator = NavigateToTarget.editorActivator(editorId, diagram, model, rvi, part -> {
             if (selectedObjects.isEmpty())
                 return;
-
-            final ICanvasContext openedCanvas = (ICanvasContext) part.getAdapter(ICanvasContext.class);
+            ICanvasContext openedCanvas = (ICanvasContext) part.getAdapter(ICanvasContext.class);
             assert openedCanvas != null;
             // CanvasContext-wide denial of initial zoom-to-fit on diagram open.
             openedCanvas.getDefaultHintContext().setHint(DiagramHints.KEY_INITIAL_ZOOM_TO_FIT, Boolean.FALSE);
-            //System.out.println("ASDF: " + element);
             ThreadUtils.asyncExec(openedCanvas.getThreadAccess(),
                     NavigateToTarget.elementSelectorZoomer(openedCanvas, selectedObjects, false));
         });
-
-        PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
-            @Override
-            public void run() {
-                editorActivator.run();
-            }
-        });
-
-        return true;
+        PlatformUI.getWorkbench().getDisplay().asyncExec(editorActivator);
     }
 
 }
index 9632090e3acf342255dce3dc151ea9558479efc0..d0a777caa8ffbdf061c1f64b003ae24f2d4d3608 100644 (file)
@@ -60,6 +60,9 @@ public class SCLTypeUtils {
         TYPE_MAP.put("ByteArray", Types.BYTE_ARRAY);
         
         add((TCon)Types.RESOURCE);
+        add(Types.con("Simantics/GUID", "GUID")); // L0.GUID
+        add(Types.con("Simantics/Variables", "StructuredProperty")); // L0.methods
+        add(Types.con("Simantics/Variables", "ValueAccessor")); // L0.ValueAccessor
         add(Types.con("Simantics/Variables", "VariableMap"));
     }
     
index 7c1fe461a5e14218991f87224c8ec1d47e42a16e..8a0b1ddbca77e0f81fd283d8445c715e8c2e5adb 100644 (file)
@@ -459,6 +459,8 @@ public class SyncTypicalTemplatesToInstances extends WriteRequest {
     private boolean isSynchronizedConnector(ReadGraph graph, Resource templateConnection, Resource instanceConnector) throws DatabaseException {
        DiagramResource DIA = DiagramResource.getInstance(graph);
        Resource instanceConnection = graph.getPossibleObject(instanceConnector, DIA.IsConnectorOf);
+       if (instanceConnection == null)
+               return false;
        return graph.hasStatement(instanceConnection, MOD.HasElementSource, templateConnection)
                        // If the master connection has been removed, this is all that's left
                        // to identify a connection that at least was originally synchronized
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/common/names/SCLReservedWords.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/common/names/SCLReservedWords.java
new file mode 100644 (file)
index 0000000..7f6f80b
--- /dev/null
@@ -0,0 +1,65 @@
+package org.simantics.scl.compiler.common.names;
+
+import java.io.StringReader;
+
+import org.simantics.scl.compiler.internal.parsing.Token;
+import org.simantics.scl.compiler.internal.parsing.parser.SCLLexer;
+import org.simantics.scl.compiler.internal.parsing.parser.SCLTerminals;
+
+import gnu.trove.set.hash.THashSet;
+
+public class SCLReservedWords {
+    public static final String[] RESERVED_WORDS_ARRAY = {
+            "as",
+            "by",
+            "do",
+            "if",
+            "in",
+            "edo",
+            "let",
+            "mdo",
+            "data",
+            "else",
+            "rule",
+            "then",
+            "type",
+            "when",
+            "with",
+            "class",
+            "infix",
+            "match",
+            "where",
+            "effect",
+            "forall",
+            "hiding",
+            "import",
+            "infixl",
+            "infixr",
+            "select",
+            "enforce",
+            "include",
+            "ruleset",
+            "deriving",
+            "instance",
+            "constraint",
+            "importJava",
+            "transformation",
+    };
+
+    public static final THashSet<String> RESERVED_WORDS_SET = new THashSet<>();
+
+    static {
+        for(String word : RESERVED_WORDS_ARRAY)
+            RESERVED_WORDS_SET.add(word);
+    }
+
+    public static boolean isReserved(String str) {
+        try {
+            SCLLexer lexer = new SCLLexer(new StringReader(str));
+            Token token = lexer.nextToken();
+            return token.id != SCLTerminals.ID;
+        } catch(Exception e) {
+            return true;
+        }
+    }
+}
index 12d06b76b0c5fff84d9af479cb33e7eb8d888366..43be6defbb6ee486957572caff2abe9d0a93f226 100644 (file)
@@ -96,6 +96,9 @@ importJava "org.simantics.db.layer0.function.All" where
 importJava "org.simantics.db.layer0.variable.VariableMap" where
     data VariableMap
 
+importJava "org.simantics.db.layer0.variable.StructuredProperty" where
+    data StructuredProperty
+
 importJava "org.simantics.db.layer0.variable.ResourceCollectionVariableMap" where
     @JavaName "<init>"
     createVariableMap :: [Resource] -> VariableMap
index 21fcf2c268847704ad00375f60dcbe525dca309b..5edf6c856ca80a020e394afeab4ba53e0e883fb6 100644 (file)
@@ -82,6 +82,37 @@ public class ExperimentRuns {
             final IExperimentActivationListener listener,
             final Function2<WriteGraph, Resource, Object> externalWrite,
             final Consumer<Resource> successCallback)
+    {
+        createRun(session, vg,
+                experimentResource, experiment, experimentRunTypeURI,
+                listener, externalWrite, successCallback, true);
+    }
+
+    /**
+     * Create new experiment run in a selected virtual graph.
+     * 
+     * @param session
+     * @param vg
+     * @param experimentResource
+     * @param experiment
+     * @param experimentRunTypeURI
+     * @param listener
+     * @param successCallback if non-null invoked with the created run resource
+     *        as an argument, just before invoking
+     *        listener.onExperimentActivated(experiment)
+     * @param attachDeactivationListener <code>true</code> to run for the created run-resource
+     *        {@link #attachStateListener(Session, IExperiment, Resource)}
+     */
+    public static void createRun(
+            Session session,
+            VirtualGraph vg,
+            Resource experimentResource,
+            IExperiment experiment,
+            String experimentRunTypeURI,
+            IExperimentActivationListener listener,
+            Function2<WriteGraph, Resource, Object> externalWrite,
+            Consumer<Resource> successCallback,
+            boolean attachDeactivationListener)
     {
         final AtomicReference<Resource> run = new AtomicReference<>();
         session.asyncRequest(new WriteRequest(vg) {
@@ -97,7 +128,8 @@ public class ExperimentRuns {
                 else
                     ErrorLogger.defaultLogError(e);
             } else {
-                attachStateListener(session, experiment, run.get());
+                if (attachDeactivationListener)
+                    attachStateListener(session, experiment, run.get());
                 if (successCallback != null)
                     successCallback.accept(run.get());
                 if (listener != null)
index 716d4a0017014e3cb727a4d1b26c587f71411680..f79bdb0b59187f7509a4b59c228cf0f53a12934d 100644 (file)
@@ -94,7 +94,7 @@ class ActualConnectionDescriptor extends AbstractVariableConnectionPointDescript
                
                StructuralResource2 STR = StructuralResource2.getInstance(graph);
                Resource type = graph.getPossibleType(component, STR.Component);
-               return graph.syncRequest(new IsLeafType(type));
+               return type != null ? graph.syncRequest(new IsLeafType(type)) : false;
                
        }
        
index 1cd72de635c2349fa3fec31241b25c76a55be0c7..ca06a5d7b5d538c9091fb8b71d7f45d26ad906d3 100644 (file)
@@ -20,7 +20,10 @@ import org.eclipse.jface.action.IStatusLineManager;
 import org.eclipse.ui.IActionBars;
 import org.eclipse.ui.IEditorInput;
 import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.IWorkbenchPartSite;
 import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.internal.PartSite;
+import org.eclipse.ui.internal.e4.compatibility.CompatibilityEditor;
 import org.eclipse.ui.part.EditorPart;
 import org.simantics.Simantics;
 import org.simantics.db.Resource;
@@ -98,11 +101,25 @@ public abstract class ResourceEditorPart extends EditorPart implements IResource
      * @param partName
      */
     protected void safeSetPartName(String partName) {
-        if (!disposed) {
+        if (!disposed && checkCompatibilityPartNotBeingDisposed()) { // this is to fix bug https://gitlab.simantics.org/simantics/platform/issues/117
             setPartName(partName);
         }
     }
 
+    @SuppressWarnings("restriction")
+    private boolean checkCompatibilityPartNotBeingDisposed() {
+        IWorkbenchPartSite site = getSite();
+        if (site instanceof PartSite) {
+            PartSite partSite = (PartSite) getSite();
+            Object object = partSite.getModel().getObject();
+            if (object instanceof CompatibilityEditor) {
+                CompatibilityEditor editor = (CompatibilityEditor) object;
+                return !editor.isBeingDisposed();
+            }
+        }
+        return true;
+    }
+
     /**
      * Safely sets title tooltip for parts whose IEditorInput is not yet disposed (e.g.
      * removed from database)
diff --git a/bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/SWTDPIUtil.java b/bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/SWTDPIUtil.java
new file mode 100644 (file)
index 0000000..0fe51a9
--- /dev/null
@@ -0,0 +1,261 @@
+package org.simantics.utils.ui;
+
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.DPIUtil;
+
+/**
+ * This class is needed to support {@link SWTAWTComponent} and HiDPI screens
+ * with different display zoom settings.
+ * 
+ * <p>
+ * See {@link DPIUtil} for explanations on what downscaling and upscaling are in
+ * this context. If user has zoom > 100% in use in the system display settings,
+ * SWT's API coordinates will be "downscaled" from actual internal HiDPI
+ * coordinates (pixels).
+ * 
+ * <p>
+ * This class contains methods to work around problems with e.g. opening context
+ * menu's in the correct location when using {@link SWTAWTComponent}. AWT always
+ * returns HiDPI pixel coordinates which need to be converted to SWT API
+ * coordinates before giving them to any SWT APIs.
+ *
+ * @author Tuukka Lehtonen
+ * @since 1.36.0
+ */
+@SuppressWarnings("restriction")
+public class SWTDPIUtil {
+
+       private static boolean initialized = false;
+       private static int swtZoom;
+       private static boolean hasSwtScale;
+
+       private static float fromSwtInternalScalingFactorF;
+       private static double fromSwtInternalScalingFactorD;
+       private static float toSwtInternalScalingFactorF;
+       private static double toSwtInternalScalingFactorD;
+
+       private static void initialize() {
+               if (initialized)
+                       return;
+
+               swtZoom = DPIUtil.autoScaleUp(100);
+               hasSwtScale = swtZoom != 100;
+
+               fromSwtInternalScalingFactorD         = 100.0 / (double) swtZoom;
+               toSwtInternalScalingFactorD           = (double) swtZoom / 100.0;
+               fromSwtInternalScalingFactorF         = (float) fromSwtInternalScalingFactorD;
+               toSwtInternalScalingFactorF           = (float) toSwtInternalScalingFactorD;
+
+//             System.out.format("SWTDPIUtil:%n\tswt zoom = %d%n\tfrom swt internal scaling factor = %f%n\tto swt internal scaling factor = %f%n",
+//                             swtZoom,
+//                             fromSwtInternalScalingFactorD,
+//                             toSwtInternalScalingFactorD,
+//                             );
+
+               initialized = true;
+       }
+
+       // Internals
+
+       private static Rectangle scale(float s, Rectangle r, Rectangle target) {
+               if (s == 1.0f) {
+                       if (r == target)
+                               return r;
+                       if (target == null) {
+                               return new Rectangle(r.x, r.y, r.width, r.height);
+                       } else {
+                               target.x = r.x;
+                               target.y = r.y;
+                               target.width = r.width;
+                               target.height = r.height;
+                               return target;
+                       }
+               }
+               if (target == null) {
+                       return new Rectangle(
+                                       Math.round(r.x*s),
+                                       Math.round(r.y*s),
+                                       Math.round(r.width*s),
+                                       Math.round(r.height*s));
+               } else {
+                       target.x = Math.round(r.x*s);
+                       target.y = Math.round(r.y*s);
+                       target.width = Math.round(r.width*s);
+                       target.height = Math.round(r.height*s);
+                       return target;
+               }
+       }
+
+       private static Rectangle2D scale(double s, Rectangle2D r, Rectangle2D target) {
+               if (s == 1.0) {
+                       if (r == target)
+                               return r;
+                       if (target == null)
+                               return (Rectangle2D) r.clone();
+                       target.setFrame(r);
+                       return target;
+               }
+               if (target == null)
+                       target = (Rectangle2D) r.clone();
+               target.setFrame(r.getX()*s, r.getY()*s, r.getWidth()*s, r.getHeight()*s);
+               return target;
+       }
+
+       private static double downscaleSwt0(double x) {
+               return hasSwtScale ? x * fromSwtInternalScalingFactorD : x;
+       }
+
+       private static int downscaleToIntegerSwt0(double x) {
+               return (int)(hasSwtScale ? Math.round((double) x * fromSwtInternalScalingFactorD) : x);
+       }
+
+       private static int downscaleSwt0(int x) {
+               return hasSwtScale ? (int) Math.round((double) x * fromSwtInternalScalingFactorD) : x;
+       }
+
+       private static double upscaleSwt0(double x) {
+               return hasSwtScale ? x * toSwtInternalScalingFactorD : x;
+       }
+
+       private static int upscaleToIntegerSwt0(double x) {
+               return (int)(hasSwtScale ? Math.round((double) x * toSwtInternalScalingFactorD) : x);
+       }
+
+       private static int upscaleSwt0(int x) {
+               return hasSwtScale ? (int) Math.round((double) x * toSwtInternalScalingFactorD) : x;
+       }
+
+       // SWT API Coordinates <-> pixels
+
+       // Downscaling
+
+       public static double downscaleSwt(double x) {
+               initialize();
+               return downscaleSwt0(x);
+       }
+
+       public static int downscaleSwt(int x) {
+               initialize();
+               return downscaleSwt0(x);
+       }
+
+       public static Point2D downscaleSwt(double x, double y) {
+               initialize();
+               if (!hasSwtScale)
+                       return new Point2D.Double(x, y);
+               double s = fromSwtInternalScalingFactorD;
+               return new Point2D.Double(x * s, y * s);
+       }
+
+       public static Point downscaleSwt(int x, int y) {
+               initialize();
+               return new Point(downscaleSwt0(x), downscaleSwt0(y));
+       }
+
+       public static Point2D downscaleSwt(Point2D p) {
+               return downscaleSwt(p.getX(), p.getY());
+       }
+
+       public static Point downscaleSwtToInteger(Point2D p) {
+               initialize();
+               return new Point(downscaleToIntegerSwt0(p.getX()), downscaleToIntegerSwt0(p.getY()));
+       }
+
+       public static Rectangle2D downscaleSwt(Rectangle2D r, Rectangle2D target) {
+               initialize();
+               return scale(fromSwtInternalScalingFactorD, r, target);
+       }
+
+       public static Rectangle2D downscaleSwt(Rectangle2D r) {
+               return downscaleSwt(r, null);
+       }
+
+       public static Rectangle downscaleSwt(Rectangle r, Rectangle target) {
+               initialize();
+               return scale(fromSwtInternalScalingFactorF, r, target);
+       }
+
+       public static Rectangle downscaleSwt(Rectangle r) {
+               return downscaleSwt(r, null);
+       }
+
+       public static Rectangle downscaleSwtToInteger(Rectangle2D r) {
+               initialize();
+               return new Rectangle( 
+                               downscaleToIntegerSwt0(r.getMinX()),
+                               downscaleToIntegerSwt0(r.getMinY()),
+                               downscaleToIntegerSwt0(r.getWidth()),
+                               downscaleToIntegerSwt0(r.getHeight()));
+       }
+
+       // Upscaling
+
+       public static double upscaleSwt(double x) {
+               initialize();
+               return upscaleSwt0(x);
+       }
+
+       public static int upscaleSwt(int x) {
+               initialize();
+               return upscaleSwt0(x);
+       }
+
+       public static Point2D upscaleSwt(double x, double y) {
+               initialize();
+               if (!hasSwtScale)
+                       return new Point2D.Double(x, y);
+               double s = toSwtInternalScalingFactorD;
+               return new Point2D.Double(x * s, y * s);
+       }
+
+       public static Point upscaleSwt(int x, int y) {
+               initialize();
+               return new Point(upscaleSwt0(x), upscaleSwt0(y));
+       }
+
+       public static Point2D upscaleSwt(Point2D p) {
+               initialize();
+               return (hasSwtScale && p != null) ? upscaleSwt(p.getX(), p.getY()) : p;
+       }
+
+       public static Point upscaleSwtToInteger(Point2D p) {
+               initialize();
+               return new Point(upscaleToIntegerSwt0(p.getX()), upscaleToIntegerSwt0(p.getY()));
+       }
+
+       public static Point upscaleSwt(Point p) {
+               initialize();
+               return (hasSwtScale && p != null) ? upscaleSwt(p.x, p.y) : p;
+       }
+
+       public static Rectangle2D upscaleSwt(Rectangle2D r, Rectangle2D target) {
+               initialize();
+               return scale(toSwtInternalScalingFactorD, r, target);
+       }
+
+       public static Rectangle upscaleSwt(Rectangle r, Rectangle target) {
+               initialize();
+               return scale(toSwtInternalScalingFactorF, r, target);
+       }
+
+       public static Rectangle2D upscaleSwt(Rectangle2D r) {
+               return upscaleSwt(r, null);
+       }
+
+       public static Rectangle upscaleSwt(Rectangle r) {
+               return upscaleSwt(r, null);
+       }
+
+       public static Rectangle upscaleSwtToInteger(Rectangle2D r) {
+               return new Rectangle( 
+                               upscaleToIntegerSwt0(r.getMinX()),
+                               upscaleToIntegerSwt0(r.getMinY()),
+                               upscaleToIntegerSwt0(r.getWidth()),
+                               upscaleToIntegerSwt0(r.getHeight()));
+       }
+
+}
diff --git a/features/org.simantics.jdbc.feature/.project b/features/org.simantics.jdbc.feature/.project
new file mode 100644 (file)
index 0000000..0d18720
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>org.simantics.jdbc.feature</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.pde.FeatureBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.pde.FeatureNature</nature>
+       </natures>
+</projectDescription>
diff --git a/features/org.simantics.jdbc.feature/build.properties b/features/org.simantics.jdbc.feature/build.properties
new file mode 100644 (file)
index 0000000..64f93a9
--- /dev/null
@@ -0,0 +1 @@
+bin.includes = feature.xml
diff --git a/features/org.simantics.jdbc.feature/feature.xml b/features/org.simantics.jdbc.feature/feature.xml
new file mode 100644 (file)
index 0000000..66b53fa
--- /dev/null
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feature
+      id="org.simantics.jdbc.feature"
+      label="Simantics JDBC Feature"
+      version="1.0.0.qualifier">
+
+   <description url="http://www.example.com/description">
+      [Enter Feature Description here.]
+   </description>
+
+   <copyright url="http://www.example.com/copyright">
+      [Enter Copyright Description here.]
+   </copyright>
+
+   <license url="http://www.example.com/license">
+      [Enter License Description here.]
+   </license>
+
+   <plugin
+         id="org.simantics.jdbc"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.simantics.simulator.toolkit"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.simantics.simulator.toolkit.db"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.simantics.simulator"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.simantics.jdbc.ontology"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.simantics.jdbc.simupedia.sharedlibrary"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+</feature>
index 87df82cfe3b4d8cf4ca3c32215da0b98eb68b932..1001743bea6053ea8d92b908d96a1ce132358ce4 100644 (file)
                                         <Import-Package>!sun.misc.*,*;resolution:=optional</Import-Package>
                                     </instructions>
                                 </artifact>
+                                <artifact>
+                                    <id>com.impossibl.pgjdbc-ng:pgjdbc-ng:0.7.1</id>
+                                    <source>true</source>
+                                    <transitive>false</transitive>
+                                </artifact>
                             </artifacts>
                         </configuration>
                     </execution>
index 7306e4e4a004f5b68fe0a23a4f268a991d5bab20..aa58f2419da579a697bb5845ed5a6e642fcd2af5 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/mbarbero/fr.obeo.releng.targetplatform -->
-<target name="Eclipse Oxygen" sequenceNumber="1536132639">
+<target name="Eclipse Oxygen" sequenceNumber="1536132640">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="true" includeSource="true" includeConfigurePhase="false" type="InstallableUnit">
       <unit id="com.google.guava" version="21.0.0.v20170206-1425"/>
       <unit id="org.slf4j.api.source" version="1.7.25.b001"/>
       <unit id="org.supercsv" version="2.4.0"/>
       <unit id="org.supercsv.source" version="2.4.0"/>
+      <unit id="pgjdbc-ng" version="0.7.1"/>
+      <unit id="pgjdbc-ng.source" version="0.7.1"/>
       <unit id="stax2-api" version="3.1.4"/>
       <unit id="stax2-api.source" version="3.1.4"/>
       <repository location="http://www.simantics.org/download/master/external-components/maven"/>
index 50ce5ca5b3fa052c2a47de2ceac9e0a917bab397..2875cbbd2780d0ebea6028e17ad2fc1b5585053c 100644 (file)
@@ -354,6 +354,8 @@ location "http://www.simantics.org/download/master/external-components/maven" {
        org.slf4j.api.source
        org.supercsv
        org.supercsv.source
+       pgjdbc-ng
+       pgjdbc-ng.source
        stax2-api
        stax2-api.source
 }
index eb9605a93ab36f3178ecf6468eb1f8951a7031e0..4853e0c4400c47174324db5d02c06fc3e33314ab 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/mbarbero/fr.obeo.releng.targetplatform -->
-<target name="Simantics 1.36.0" sequenceNumber="1535957308">
+<target name="Simantics 1.36.0" sequenceNumber="1535957309">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="true" includeSource="true" includeConfigurePhase="false" type="InstallableUnit">
       <unit id="com.google.guava" version="21.0.0.v20170206-1425"/>
       <unit id="org.slf4j.api.source" version="1.7.25.b001"/>
       <unit id="org.supercsv" version="2.4.0"/>
       <unit id="org.supercsv.source" version="2.4.0"/>
+      <unit id="pgjdbc-ng" version="0.7.1"/>
+      <unit id="pgjdbc-ng.source" version="0.7.1"/>
       <unit id="stax2-api" version="3.1.4"/>
       <unit id="stax2-api.source" version="3.1.4"/>
       <repository location="http://www.simantics.org/download/master/external-components/maven"/>