Merge "Fix column width issues on HiDPI displays. KeyTiSelection fixes."
authorMarko Luukkainen <marko.luukkainen@semantum.fi>
Thu, 17 May 2018 11:31:58 +0000 (11:31 +0000)
committerGerrit Code Review <gerrit2@simantics>
Thu, 17 May 2018 11:31:58 +0000 (11:31 +0000)
bundles/org.simantics.debug.ui/src/org/simantics/debug/ui/SearchResourceDialog.java
bundles/org.simantics.event/scl/Simantics/Event.scl
bundles/org.simantics.event/src/org/simantics/event/util/EventExporter.java
bundles/org.simantics.graphviz/src/org/simantics/graphviz/internal/xdot/SetStyle.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/contexts/TranslationContext.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ERecord.java
bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/editor/completion/SCLCompletionProposal.java
bundles/org.simantics.ui/src/org/simantics/ui/SimanticsUI.java
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/ModuleRegressionTests.java
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/Record4.scl [new file with mode: 0644]

index c96b8469ee2bb573fb7524877709383560028eff..29cfd63bd45d9786bed42ad25a04b9e0cdc670a7 100644 (file)
@@ -255,110 +255,122 @@ public class SearchResourceDialog extends FilteredItemsSelectionDialog {
     @Override
     protected ItemsFilter createFilter() {
         // NOTE: filter must be created here.
-        return new ItemsFilter() {
-            @Override
-            public boolean matchItem(Object item) {
-                //return matches(item.toString());
-                return true;
-            }
+        return new ItemsFilterWithSearchResults();
+    }
 
-            // If this method returns true, it means fillContentProvider will
-            // not be called again, but the existing results are just re-filtered.
-            @Override
-            public boolean isSubFilter(ItemsFilter filter) {
-                //System.out.println(getPattern() + " vs. " + filter.getPattern());
-                return false;
-            }
+    private class ItemsFilterWithSearchResults extends ItemsFilter {
+        private Set<Object> searchResults = new HashSet<Object>();
 
-            @Override
-            public boolean isConsistentItem(Object item) {
-                return true;
-            }
+        public ItemsFilterWithSearchResults() {
+            
+            final String pattern = getPattern();
+            final boolean findUris = pattern.trim().startsWith("http:/");
+            final long referencedResourceId = referencedResourceId(pattern);
+            final boolean findIds = referencedResourceId != 0;
 
-            @Override
-            public boolean equalsFilter(ItemsFilter filter) {
-                return false;
-            }
-        };
-    }
+            searchResults.clear();
+            if (pattern.isEmpty()) return;
+            //progressMonitor.beginTask("Searching", IProgressMonitor.UNKNOWN);
 
-    @Override
-    protected void fillContentProvider(final AbstractContentProvider contentProvider,
-            final ItemsFilter itemsFilter, final IProgressMonitor progressMonitor)
-                    throws CoreException {
-        final String pattern = itemsFilter.getPattern();
-        final boolean findUris = pattern.trim().startsWith("http:/");
-        final long referencedResourceId = referencedResourceId(pattern);
-        final boolean findIds = referencedResourceId != 0;
-
-        //progressMonitor.beginTask("Searching", IProgressMonitor.UNKNOWN);
-
-        try {
-            session.syncRequest(new ReadRequest() {
-                @Override
-                public void run(ReadGraph graph) throws DatabaseException {
-                    // Find by ID first.
-                    if (findIds) {
-                        try {
-                            Resource r = graph.getService(SerialisationSupport.class).getResource(referencedResourceId);
-                            contentProvider.add(new LabeledResource(DebugUtils.getSafeLabel(graph, r), r), itemsFilter);
-                            //contentProvider.add(new LabeledResource(pattern, r), itemsFilter);
-                        } catch (DatabaseException e) {
-                            // No resource for specified id.
-                        }
-                    }
-                    if (findUris) {
-                        String uri = pattern;
-                        if (uri.endsWith(Role.CHILD.getIdentifier())) {
-                            uri = uri.substring(0, uri.length() - 1);
+            try {
+                session.syncRequest(new ReadRequest() {
+                    @Override
+                    public void run(ReadGraph graph) throws DatabaseException {
+                        // Find by ID first.
+                        if (findIds) {
+                            try {
+                                Resource r = graph.getService(SerialisationSupport.class).getResource(referencedResourceId);
+                                searchResults.add(new LabeledResource(DebugUtils.getSafeLabel(graph, r), r));
+                            } catch (DatabaseException e) {
+                                // No resource for specified id.
+                            }
                         }
-                        Resource r = graph.getPossibleResource(uri);
-                        if (r != null) {
-                            contentProvider.add(new LabeledResource(DebugUtils.getSafeURI(graph, r), r), itemsFilter );
+                        if (findUris) {
+                            String uri = pattern;
+                            if (uri.endsWith(Role.CHILD.getIdentifier())) {
+                                uri = uri.substring(0, uri.length() - 1);
+                            }
+                            Resource r = graph.getPossibleResource(uri);
+                            if (r != null) {
+                               searchResults.add(new LabeledResource(DebugUtils.getSafeURI(graph, r), r));
 
-                            Map<String, Resource> children = graph.syncRequest(new UnescapedChildMapOfResource(r));
-                            for (Resource child : children.values()) {
-                                contentProvider.add(new LabeledResource(DebugUtils.getSafeURI(graph, child), child), itemsFilter );
+                                Map<String, Resource> children = graph.syncRequest(new UnescapedChildMapOfResource(r));
+                                for (Resource child : children.values()) {
+                                       searchResults.add(new LabeledResource(DebugUtils.getSafeURI(graph, child), child));
+                                }
                             }
-                        }
-                    } else {
-                        Resource project = Simantics.peekProjectResource();
-                        if (project != null) {
-                            IResourceFilter rf = resourceFilter;
-                            String filter = getFilterForResourceFilter(rf);
-                            if (!filter.isEmpty())
-                                filter += " AND ";
-                            filter += "Name:" + pattern + "*";
-
-                            Layer0 L0 = Layer0.getInstance(graph);
-
-                            Set<Resource> indexRoots = new HashSet<>();
-                            indexRoots.addAll(graph.syncRequest(new ObjectsWithType(project, L0.ConsistsOf, L0.IndexRoot)));
-                            indexRoots.addAll(graph.syncRequest(new OntologiesFromLibrary(graph.getRootLibrary())));
-                            for (Resource indexRoot : indexRoots) {
-                                Collection<Resource> hits = find(graph, indexRoot, filter);
-                                for (Resource r : hits) {
-                                    if (rf != null && !rf.acceptResource(graph, r))
-                                        continue;
-                                    contentProvider.add(new LabeledResource(DebugUtils.getSafeLabel(graph, r), r), itemsFilter);
+                        } else {
+                            Resource project = Simantics.peekProjectResource();
+                            if (project != null) {
+                                IResourceFilter rf = resourceFilter;
+                                String filter = getFilterForResourceFilter(rf);
+                                if (!filter.isEmpty())
+                                    filter += " AND ";
+                                filter += "Name:" + pattern + "*";
+
+                                Layer0 L0 = Layer0.getInstance(graph);
+
+                                Set<Resource> indexRoots = new HashSet<>();
+                                indexRoots.addAll(graph.syncRequest(new ObjectsWithType(project, L0.ConsistsOf, L0.IndexRoot)));
+                                indexRoots.addAll(graph.syncRequest(new OntologiesFromLibrary(graph.getRootLibrary())));
+                                for (Resource indexRoot : indexRoots) {
+                                    Collection<Resource> hits = find(graph, indexRoot, filter);
+                                    for (Resource r : hits) {
+                                        if (rf != null && !rf.acceptResource(graph, r))
+                                            continue;
+                                        searchResults.add(new LabeledResource(DebugUtils.getSafeLabel(graph, r), r));
+                                    }
                                 }
                             }
                         }
                     }
-                }
 
-                public Collection<Resource> find(ReadGraph graph, Resource index, String filter) throws DatabaseException {
-                    //TimeLogger.resetTimeAndLog("find(" + graph.getURI(index) + ", " + filter + ")");
-                    Collection<Resource> indexResult = graph.syncRequest(new QueryIndex(index, filter), TransientCacheListener.<Collection<Resource>>instance());
-                    //TimeLogger.log("found " + indexResult.size());
-                    return indexResult;
-                }
+                    public Collection<Resource> find(ReadGraph graph, Resource index, String filter) throws DatabaseException {
+                        //TimeLogger.resetTimeAndLog("find(" + graph.getURI(index) + ", " + filter + ")");
+                        Collection<Resource> indexResult = graph.syncRequest(new QueryIndex(index, filter), TransientCacheListener.<Collection<Resource>>instance());
+                        //TimeLogger.log("found " + indexResult.size());
+                        return indexResult;
+                    }
+
+                });
+            } catch (DatabaseException ex) {
+                Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, ex.getMessage(), ex));
+            }
 
-            });
-        } catch (DatabaseException ex) {
-            Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, ex.getMessage(), ex));
         }
 
+        @Override
+        public boolean matchItem(Object item) {
+            return searchResults.contains(item);
+        }
+
+        @Override
+        public boolean isSubFilter(ItemsFilter filter) {
+            return false;
+        }
+        
+        @Override
+        public boolean isConsistentItem(Object item) {
+            return true;
+        }
+        
+        @Override
+        public boolean equalsFilter(ItemsFilter filter) {
+            return false;
+        }
+        
+        public void fillContentProvider(final AbstractContentProvider contentProvider) {
+               for (Object item : searchResults) {
+                       contentProvider.add(item, this);
+               }
+        }
+    }
+    
+    @Override
+    protected void fillContentProvider(final AbstractContentProvider contentProvider,
+            final ItemsFilter itemsFilter, final IProgressMonitor progressMonitor)
+                    throws CoreException {
+        ((ItemsFilterWithSearchResults) itemsFilter).fillContentProvider(contentProvider);
         progressMonitor.done();
     }
 
index 01a520d52e71c2e8a57967db4aa69c0ad4c95fb5..6839c964c33d0a74c760ba3d675942e0d3c7727b 100644 (file)
@@ -20,4 +20,25 @@ findEventSlices log = do
 @private
 findEventsFromSlice :: Resource -> <ReadGraph, Proc> [Resource]
 findEventsFromSlice slice = do
-    collectionToList (objects_ slice L0.ConsistsOf)
\ No newline at end of file
+    collectionToList (objects_ slice L0.ConsistsOf)
+
+importJava "org.simantics.event.util.EventExporter" where
+    """
+        exportCurrentEvents "\t" "X:/events.txt"
+    
+    exports the currently visible events into the specified
+    text file using the specified column separator string.
+    This function should be used when invoking outside of
+    a database transaction.
+    """
+    exportCurrentEvents :: String -> String -> ()
+
+    """
+        exportCurrentEventsG "\t" "X:/events.txt"
+    
+    exports the currently visible events into the specified
+    text file using the specified column separator string.
+    This variant must be used when invoking the method with
+    DB transaction.
+    """
+    exportCurrentEventsG :: String -> String -> <ReadGraph> ()
index 10d2dfe7f28c9505f519ea649fc777cae206f2d9..0e34770c5f988a68e8cc1d0deccfb1d2cc2a0f88 100644 (file)
@@ -26,7 +26,6 @@ import org.simantics.db.common.request.ReadRequest;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.event.view.contribution.EventLabelRule;
 import org.simantics.event.view.contribution.ProjectEventsRule;
-import org.simantics.utils.FileUtils;
 import org.simantics.utils.strings.EString;
 
 /**
@@ -34,6 +33,28 @@ import org.simantics.utils.strings.EString;
  */
 public class EventExporter {
 
+       /**
+        * SCL API.
+        * 
+        * @param outputFile
+        * @throws DatabaseException
+        * @throws IOException
+        */
+       public static void exportCurrentEvents(String columnSeparator, String outputFile) throws DatabaseException, IOException {
+               new EventExporter().exportCsv(null, new File(outputFile), columnSeparator);
+       }
+
+       /**
+        * SCL API.
+        * 
+        * @param outputFile
+        * @throws DatabaseException
+        * @throws IOException
+        */
+       public static void exportCurrentEventsG(ReadGraph graph, String columnSeparator, String outputFile) throws DatabaseException, IOException {
+               new EventExporter().exportCsv(graph, null, new File(outputFile), columnSeparator);
+       }
+
        public EventExporter() {
        }
 
@@ -49,17 +70,33 @@ public class EventExporter {
         * @throws DatabaseException
         * @throws IOException
         */
-       public void exportCsv(final IProgressMonitor monitor, File file, final String columnSeparator) throws DatabaseException, IOException {
-               final PrintStream out = new PrintStream(file);
-               try {
+       public void exportCsv(IProgressMonitor monitor, File file, String columnSeparator) throws DatabaseException, IOException {
+               try (PrintStream out = new PrintStream(file)) {
                        Simantics.getSession().syncRequest(new ReadRequest() {
                                @Override
                                public void run(ReadGraph graph) throws DatabaseException {
                                        exportCsv(graph, monitor, out, columnSeparator);
                                }
                        });
-               } finally {
-                       FileUtils.uncheckedClose(out);
+               }
+       }
+
+       /**
+        * @param graph
+        * @param monitor
+        *            the progress monitor to use for reporting progress to the
+        *            user. It is the caller's responsibility to call done() on the
+        *            given monitor. Accepts <code>null</code>, indicating that no
+        *            progress should be reported and that the operation cannot be
+        *            cancelled.</pre>
+        * @param file
+        * @param columnSeparator
+        * @throws DatabaseException
+        * @throws IOException
+        */
+       public void exportCsv(ReadGraph graph, IProgressMonitor monitor, File file, String columnSeparator) throws DatabaseException, IOException {
+               try (PrintStream out = new PrintStream(file)) {
+                       exportCsv(graph, monitor, out, columnSeparator);
                }
        }
 
index 5269ac09dc0efb3cc964373fa772b0359cd4c5f3..1098c53fde7ec017378b9903d6507f186d2c9e9a 100644 (file)
@@ -34,6 +34,10 @@ public class SetStyle implements DrawCommand {
                    g.setStroke(DASHED);
                else if(styleName.equals("dotted"))
             g.setStroke(DOTTED);
+               else if(styleName.startsWith("setlinewidth(")) {
+                   double w = Double.parseDouble(styleName.substring(13, styleName.length()-1));
+                   g.setStroke(new BasicStroke((float)w, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10.0f, ((BasicStroke)g.getStroke()).getDashArray(), 0.0f));
+               }
                else
                    System.out.println("Unknown style: " + styleName);
        }
index 757aca8b5e272880e7c6526048f1b20837709f82..d8346f41f5e889fbc66437a1f9be10a1a3ad803c 100644 (file)
@@ -192,16 +192,23 @@ public class TranslationContext extends TypeTranslationContext implements Enviro
         return -1;
     }
     
+    public SCLValue resolveSCLValue(long location, Namespace namespace, String name) throws AmbiguousNameException {
+        SCLValue value = namespace.getValue(name);
+        if(value == null)
+            return null;
+        String deprecatedDescription = value.isDeprecated();
+        if(deprecatedDescription != null)
+            errorLog.logWarning(location, "Deprecated value " + value.getName().name + "." + (deprecatedDescription.isEmpty() ? "" : " " + deprecatedDescription));
+        if(moduleDebugInfo != null)
+            moduleDebugInfo.symbolReferences.add(new SymbolReference(value.getName(), Name.create(compilationContext.module.getName(), definitionName), location));
+        return value;
+    }
+    
     public Expression resolveValue(long location, Namespace namespace, String name) {
         try {
-            SCLValue value = namespace.getValue(name);
+            SCLValue value = resolveSCLValue(location, namespace, name);
             if(value == null)
                 return null;
-            String deprecatedDescription = value.isDeprecated();
-            if(deprecatedDescription != null)
-                errorLog.logWarning(location, "Deprecated value " + value.getName().name + "." + (deprecatedDescription.isEmpty() ? "" : " " + deprecatedDescription));
-            if(moduleDebugInfo != null)
-                moduleDebugInfo.symbolReferences.add(new SymbolReference(value.getName(), Name.create(compilationContext.module.getName(), definitionName), location));
             return new EConstant(location, value);
         } catch (AmbiguousNameException e) {
             if(SCLCompilerConfiguration.ALLOW_OVERLOADING)
@@ -288,6 +295,25 @@ public class TranslationContext extends TypeTranslationContext implements Enviro
         return new EError(location);
     }
     
+    public SCLValue resolveRecordConstructor(long location, String name) throws AmbiguousNameException {
+        return resolveRecordConstructor(location, getEnvironment().getLocalNamespace(), name, 0);
+    }
+    
+    public SCLValue resolveRecordConstructor(long location, Namespace namespace, String name, int begin) throws AmbiguousNameException {
+        int end = findSeparator(name, begin);
+        String part = end == -1 ? (begin == 0 ? name : name.substring(begin)) : name.substring(begin, end);
+
+        if(end != -1 && name.charAt(end) == '.') {
+            Namespace childNamespace = namespace.getNamespace(part);
+            if(childNamespace == null)
+                return null;
+            else
+                return resolveRecordConstructor(location, childNamespace, name, end+1);
+        }
+        else
+            return resolveSCLValue(location, namespace, part);
+    }
+    
     private void reportResolveFailure(long location, Namespace namespace, String name) {
         StringBuilder message = new StringBuilder();
         message.append("Couldn't resolve ").append(name).append(".");
index a859782239caac40c50cf91e34935b43aa303b7e..8c8180a66299d7fa1f33a5c85e5ad13d77137ec3 100644 (file)
@@ -37,7 +37,7 @@ public class ERecord extends ASTExpression {
     public Expression resolve(TranslationContext context, boolean asPattern) {
         SCLValue constructorValue; 
         try {
-            constructorValue = context.getEnvironment().getLocalNamespace().getValue(constructor.name);
+            constructorValue = context.resolveRecordConstructor(location, constructor.name);
         } catch (AmbiguousNameException e) {
             context.getErrorLog().log(constructor.location, e.getMessage());
             return new EError(constructor.location);
index 11749a4b2b24eef1c717eec74e9129731da58ce6..3734513cb6c3588b054e13a03b7cc15d9d4de1b6 100644 (file)
@@ -166,14 +166,15 @@ public class SCLCompletionProposal implements ICompletionProposal, ICompletionPr
     @Override
     public boolean validate(IDocument document, int offset, DocumentEvent event) {
         try {
-//            System.out.println("replacementOffset : " + replacementOffset);
-//            System.out.println("offset : " + offset);
+            String n = getName();
+            //System.out.println(n + " (" + n.length() + ") " + replacementOffset + " " + offset);
             boolean a = offset >= replacementOffset;
-            boolean b = offset < replacementOffset + getName().length();
+            boolean b = offset <= replacementOffset + n.length();
             String s = document.get(replacementOffset, offset - replacementOffset);
             prefix = s;
-            String d = getName();//.substring(0, offset - prefixStart);
-            boolean c = d.toLowerCase().startsWith(s.toLowerCase());
+            //System.out.println("prefix: " + s + " - " + prefix);
+            boolean c = n.toLowerCase().startsWith(s.toLowerCase());
+            //System.out.println("matches: " + a + " " + b + " " + c);
             return a && b && c;
         } catch (BadLocationException x) {
             //x.printStackTrace();
index 4b1554c864c19c0fd68477276d70c97859d2718f..b90e480883702de02a6f77f571ff934440848559 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * Copyright (c) 2007, 2010, 2018 Association for Decentralized Information Management
  * in Industry THTH ry.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
@@ -17,6 +17,7 @@ import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Widget;
 import org.eclipse.ui.PlatformUI;
 import org.simantics.DatabaseJob;
+import org.simantics.Simantics;
 import org.simantics.db.Resource;
 import org.simantics.db.Session;
 import org.simantics.db.common.primitiverequest.Adapter;
@@ -232,8 +233,9 @@ public class SimanticsUI {
      * 
      * @return a valid ISessionContextProvider
      */
+    @Deprecated
     public static ISessionContextProvider getSessionContextProvider() {
-        return getProviderSource().getActive();
+        return Simantics.getSessionContextProvider();
     }
 
     /**
@@ -265,9 +267,9 @@ public class SimanticsUI {
      *         workbench window or <code>null</code> if the active window has no
      *         session context
      */
+    @Deprecated
     public static ISessionContext getSessionContext() {
-        ISessionContextProvider provider = getSessionContextProvider();
-        return provider != null ? provider.getSessionContext() : null;
+        return Simantics.getSessionContext();
     }
 
     /**
@@ -360,11 +362,9 @@ public class SimanticsUI {
      * @return the Session bound to the currently active workbench window
      * @throws IllegalStateException if no Session was available
      */
+    @Deprecated
     public static Session getSession() {
-        ISessionContext ctx = getSessionContext();
-        if (ctx == null)
-            throw new IllegalStateException("Session unavailable, no database session open");
-        return ctx.getSession();
+        return Simantics.getSession();
     }
        
     /**
@@ -381,24 +381,25 @@ public class SimanticsUI {
      * @return the Session bound to the currently active workbench window or
      *         <code>null</code>
      */
+    @Deprecated
     public static Session peekSession() {
-        ISessionContext ctx = getSessionContext();
-        return ctx == null ? null : ctx.peekSession();
+        return Simantics.peekSession();
     }
 
     /**
      * @return the currently open and active project as an IProject or
      *         <code>null</code> if there is no active session or project
      */
+    @Deprecated
     public static IProject peekProject() {
-        ISessionContext ctx = getSessionContext();
-        return ctx == null ? null : (org.simantics.project.IProject) ctx.getHint(ProjectKeys.KEY_PROJECT);
+        return Simantics.peekProject();
     }
 
     /**
      * @return the currently open and active project for the specified database
      *         session or <code>null</code> if there is no current project
      */
+    @Deprecated
     public static IProject peekProject(ISessionContext ctx) {
         if (ctx == null)
             return null;
@@ -411,11 +412,9 @@ public class SimanticsUI {
      *         session, which also means there is no active project at the
      *         moment
      */
+    @Deprecated
     public static IProject getProject() {
-        ISessionContext ctx = getSessionContext();
-        if (ctx == null)
-            throw new IllegalStateException("No current database session");
-        return ctx.getHint(ProjectKeys.KEY_PROJECT);
+        return Simantics.getProject();
     }
 
     /**
index 8c2053e6f3db2cea06b8b9b19e6a558810aa595e..6a416687d1ba7d280a93f1a7c30976f1ba957b9f 100644 (file)
@@ -223,6 +223,7 @@ public class ModuleRegressionTests extends TestBase {
     @Test public void Record1() { test(); }
     @Test public void Record2() { test(); }
     @Test public void Record3() { test(); }
+    @Test public void Record4() { test(); }
     @Test public void RecordShorthand() { test(); }
     @Test public void RecordWildcards() { test(); }
     @Test public void RecursionBug() { test(); }
diff --git a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/Record4.scl b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/Record4.scl
new file mode 100644 (file)
index 0000000..7b37012
--- /dev/null
@@ -0,0 +1,11 @@
+// module Module
+data Foo = Foo { x :: Integer }
+--
+import "Prelude"
+import "Module" as M
+
+f = M.Foo { x = 3 }
+main = match f with
+    M.Foo { x } -> x
+-- 
+3
\ No newline at end of file