]> gerrit.simantics Code Review - simantics/platform.git/commitdiff
Merge "UI locking fixes for GraphExplorer implementations"
authorTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Sat, 27 Oct 2018 21:42:49 +0000 (21:42 +0000)
committerGerrit Code Review <gerrit2@simantics>
Sat, 27 Oct 2018 21:42:49 +0000 (21:42 +0000)
12 files changed:
bundles/org.simantics.browsing.ui.common/META-INF/MANIFEST.MF
bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/state/ExplorerStates.java [new file with mode: 0644]
bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/state/GraphExplorerStateBean.java [moved from bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/GraphExplorerStateBean.java with 95% similarity]
bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/state/GraphExplorerStateNodeBean.java [moved from bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/GraphExplorerStateNodeBean.java with 94% similarity]
bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/state/IdentifiedStatePersistor.java [moved from bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/IdentifiedStatePersistor.java with 89% similarity]
bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/state/StringArrayBean.java [moved from bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/StringArrayBean.java with 94% similarity]
bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/state/StringBean.java [moved from bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/StringBean.java with 94% similarity]
bundles/org.simantics.browsing.ui.nattable/src/org/simantics/browsing/ui/nattable/NatTableGraphExplorer.java
bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/GraphExplorerImpl.java
bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/GraphExplorerImpl2.java
bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/widgets/GraphExplorerComposite.java
bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/function/StandardPersistor.java

index 4da99a1260a8210d2b1681de5f13b5186a1ef8fb..b33d37df42e03f5c4d706c3cfc5a89d4379a60e9 100644 (file)
@@ -24,6 +24,7 @@ Export-Package: org.simantics.browsing.ui.common,
  org.simantics.browsing.ui.common.node,
  org.simantics.browsing.ui.common.processors,
  org.simantics.browsing.ui.common.property,
+ org.simantics.browsing.ui.common.state,
  org.simantics.browsing.ui.common.viewpoints,
  org.simantics.browsing.ui.common.views
 Bundle-Vendor: VTT Technical Research Center of Finland
diff --git a/bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/state/ExplorerStates.java b/bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/state/ExplorerStates.java
new file mode 100644 (file)
index 0000000..380968b
--- /dev/null
@@ -0,0 +1,60 @@
+package org.simantics.browsing.ui.common.state;
+
+import java.io.File;
+import java.util.concurrent.CompletableFuture;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.simantics.DatabaseJob;
+import org.simantics.browsing.ui.ExplorerState;
+import org.simantics.browsing.ui.NodeContext;
+import org.simantics.browsing.ui.StatePersistor;
+import org.simantics.browsing.ui.common.Activator;
+
+/**
+ * @author Tuukka Lehtonen
+ * @since 1.36.0
+ */
+public class ExplorerStates {
+
+    public static File explorerStateLocation() {
+        return Platform.getStateLocation(Activator.getDefault().getBundle()).toFile();
+    }
+
+    public static CompletableFuture<ExplorerState> scheduleRead(NodeContext root, StatePersistor persistor) {
+        CompletableFuture<ExplorerState> result = new CompletableFuture<>();
+        new ReaderJob(root, persistor, result).schedule();
+        return result;
+    }
+
+    private static class ReaderJob extends DatabaseJob {
+
+        private NodeContext root;
+        private StatePersistor persistor;
+        private CompletableFuture<ExplorerState> consumer;
+
+        public ReaderJob(NodeContext root, StatePersistor persistor, CompletableFuture<ExplorerState> consumer) {
+            super("Reading previous graph explorer state");
+            this.root = root;
+            this.persistor = persistor;
+            this.consumer = consumer;
+        }
+
+        @Override
+        protected IStatus run(IProgressMonitor monitor) {
+            try {
+                monitor.beginTask("Loading persisted data", 1);
+                ExplorerState state = persistor.deserialize(explorerStateLocation(), root);
+                monitor.worked(1);
+                consumer.complete(state);
+                return Status.OK_STATUS;
+            } finally {
+                monitor.done();
+            }
+        }
+
+    }
+
+}
similarity index 95%
rename from bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/GraphExplorerStateBean.java
rename to bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/state/GraphExplorerStateBean.java
index c9bf211dd9028f94c63b6a316567a60dff8a83c2..7b4d7877e6d608d6953737c16ee0ac82f6fe578c 100644 (file)
@@ -9,7 +9,7 @@
  * Contributors:
  *     VTT Technical Research Centre of Finland - initial API and implementation
  *******************************************************************************/
-package org.simantics.browsing.ui.swt;
+package org.simantics.browsing.ui.common.state;
 
 import java.util.Map;
 
similarity index 94%
rename from bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/GraphExplorerStateNodeBean.java
rename to bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/state/GraphExplorerStateNodeBean.java
index 49831e28c0b44ae0288fbfd807e73a5725abc126..67c5c9d7a54a0833bea422443b191759825c356d 100644 (file)
@@ -9,7 +9,7 @@
  * Contributors:
  *     VTT Technical Research Centre of Finland - initial API and implementation
  *******************************************************************************/
-package org.simantics.browsing.ui.swt;
+package org.simantics.browsing.ui.common.state;
 
 import java.util.TreeMap;
 
similarity index 89%
rename from bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/IdentifiedStatePersistor.java
rename to bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/state/IdentifiedStatePersistor.java
index 5a3bb75b225af675b90ca05a2bbb021343ba8965..0a417bd389c32ca8b2368888c3fb3ebef06fe2dc 100644 (file)
@@ -1,4 +1,4 @@
-package org.simantics.browsing.ui.swt;
+package org.simantics.browsing.ui.common.state;
 
 import java.io.File;
 import java.nio.file.Files;
@@ -11,13 +11,16 @@ import org.simantics.browsing.ui.ExplorerState;
 import org.simantics.browsing.ui.NodeContext;
 import org.simantics.browsing.ui.StatePersistor;
 import org.simantics.databoard.util.StringUtil;
-import org.simantics.db.common.utils.Logger;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * @author Tuukka Lehtonen
  */
 public class IdentifiedStatePersistor implements StatePersistor {
 
+       private static final Logger LOGGER = LoggerFactory.getLogger(IdentifiedStatePersistor.class);
+
        protected final String id;
 
        public IdentifiedStatePersistor(String id) {
@@ -40,7 +43,7 @@ public class IdentifiedStatePersistor implements StatePersistor {
                        if (bean != null && memento != null)
                                Files.write(memento, bean.serialize());
                } catch (Throwable t) {
-                       Logger.defaultLogError(t);
+                       LOGGER.error("Failed to serialize ExplorerState " + state, t);
                }
        }
 
@@ -52,7 +55,7 @@ public class IdentifiedStatePersistor implements StatePersistor {
                        stateBean.deserialize( Files.readAllBytes(path) );
                        return toState(stateBean);
                } catch (Throwable t) {
-                       Logger.defaultLogError(t);
+                       LOGGER.error("Failed to deserialize ExplorerState from " + path, t);
                        return ExplorerState.EMPTY;
                }
        }
similarity index 94%
rename from bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/StringArrayBean.java
rename to bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/state/StringArrayBean.java
index 219db8364e5c322d27e9775d662a4358f36ffb54..90ff79a142929d52c9017deeb9d523b9b14ea887 100644 (file)
@@ -9,7 +9,7 @@
  * Contributors:
  *     Semantum Oy - initial API and implementation
  *******************************************************************************/
-package org.simantics.browsing.ui.swt;
+package org.simantics.browsing.ui.common.state;
 
 import org.simantics.databoard.annotations.Optional;
 import org.simantics.databoard.util.Bean;
similarity index 94%
rename from bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/StringBean.java
rename to bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/state/StringBean.java
index c584da059eb55970d0168e0518296acc6ba21425..c2b435648fe17051f72c34ed89fca950178cb6ec 100644 (file)
@@ -9,7 +9,7 @@
  * Contributors:
  *     Semantum Oy - initial API and implementation
  *******************************************************************************/
-package org.simantics.browsing.ui.swt;
+package org.simantics.browsing.ui.common.state;
 
 import org.simantics.databoard.annotations.Optional;
 import org.simantics.databoard.util.Bean;
index be6a73a0c05dbff44a460e4b5de85bd9000947fb..37eafd4eb5e965e1e1811fc418576e8a37535b21 100644 (file)
@@ -26,7 +26,6 @@ import org.eclipse.core.runtime.Assert;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.MultiStatus;
-import org.eclipse.core.runtime.Platform;
 import org.eclipse.core.runtime.Status;
 import org.eclipse.core.runtime.jobs.Job;
 import org.eclipse.jface.resource.ColorDescriptor;
@@ -172,6 +171,7 @@ import org.simantics.browsing.ui.common.processors.DefaultViewpointProcessor;
 import org.simantics.browsing.ui.common.processors.IsExpandedProcessor;
 import org.simantics.browsing.ui.common.processors.NoSelectionRequestProcessor;
 import org.simantics.browsing.ui.common.processors.ProcessorLifecycle;
+import org.simantics.browsing.ui.common.state.ExplorerStates;
 import org.simantics.browsing.ui.content.Labeler;
 import org.simantics.browsing.ui.content.Labeler.CustomModifier;
 import org.simantics.browsing.ui.content.Labeler.DialogModifier;
@@ -198,6 +198,7 @@ import org.simantics.utils.threads.SWTThread;
 import org.simantics.utils.threads.ThreadUtils;
 import org.simantics.utils.ui.AdaptionUtils;
 import org.simantics.utils.ui.ISelectionUtils;
+import org.simantics.utils.ui.SWTUtils;
 import org.simantics.utils.ui.jface.BasePostSelectionProvider;
 
 import gnu.trove.map.hash.THashMap;
@@ -580,17 +581,16 @@ public class NatTableGraphExplorer extends GraphExplorerImplBase implements Grap
     private void initializeState() {
         if (persistor == null)
             return;
+        ExplorerStates.scheduleRead(getRoot(), persistor)
+        .thenAccept(state -> SWTUtils.asyncExec(natTable, () -> restoreState(state)));
+    }
 
-        ExplorerState state = persistor.deserialize(
-                Platform.getStateLocation(Activator.getDefault().getBundle()).toFile(),
-                getRoot());
-
-
+    private void restoreState(ExplorerState state) {
         Object processor = getPrimitiveProcessor(BuiltinKeys.IS_EXPANDED);
         if (processor instanceof DefaultIsExpandedProcessor) {
             DefaultIsExpandedProcessor isExpandedProcessor = (DefaultIsExpandedProcessor)processor;
             for(NodeContext expanded : state.expandedNodes) {
-                isExpandedProcessor.setExpanded(expanded, true);
+                isExpandedProcessor.replaceExpanded(expanded, true);
             }
         }
     }
index 3cf5f7478cd7af3dc23ff412db75eac0628f87c1..df736c1e6dc2603315bea23f47b46a2170a52f55 100644 (file)
@@ -39,7 +39,6 @@ import org.eclipse.core.runtime.AssertionFailedException;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.MultiStatus;
-import org.eclipse.core.runtime.Platform;
 import org.eclipse.core.runtime.Status;
 import org.eclipse.core.runtime.jobs.Job;
 import org.eclipse.jface.action.IStatusLineManager;
@@ -145,6 +144,7 @@ import org.simantics.browsing.ui.common.processors.DefaultViewpointProcessor;
 import org.simantics.browsing.ui.common.processors.IsExpandedProcessor;
 import org.simantics.browsing.ui.common.processors.NoSelectionRequestProcessor;
 import org.simantics.browsing.ui.common.processors.ProcessorLifecycle;
+import org.simantics.browsing.ui.common.state.ExplorerStates;
 import org.simantics.browsing.ui.content.ImageDecorator;
 import org.simantics.browsing.ui.content.Imager;
 import org.simantics.browsing.ui.content.LabelDecorator;
@@ -169,6 +169,7 @@ import org.simantics.utils.threads.IThreadWorkQueue;
 import org.simantics.utils.threads.SWTThread;
 import org.simantics.utils.threads.ThreadUtils;
 import org.simantics.utils.ui.ISelectionUtils;
+import org.simantics.utils.ui.SWTUtils;
 import org.simantics.utils.ui.jface.BasePostSelectionProvider;
 import org.simantics.utils.ui.widgets.VetoingEventHandler;
 import org.simantics.utils.ui.workbench.WorkbenchUtils;
@@ -1883,15 +1884,15 @@ class GraphExplorerImpl extends GraphExplorerImplBase implements Listener, Graph
             });
         }
     }
-    
+
     private void initializeState() {
         if (persistor == null)
             return;
+        ExplorerStates.scheduleRead(getRoot(), persistor)
+        .thenAccept(state -> SWTUtils.asyncExec(tree, () -> restoreState(state)));
+    }
 
-        ExplorerState state = persistor.deserialize(
-                Platform.getStateLocation(Activator.getDefault().getBundle()).toFile(),
-                getRoot());
-
+    private void restoreState(ExplorerState state) {
         // topNodeToSet will be processed by #setData when it encounters a
         // NodeContext that matches this one.
 //        topNodePath = state.topNodePath;
@@ -1902,7 +1903,7 @@ class GraphExplorerImpl extends GraphExplorerImplBase implements Listener, Graph
         if (processor instanceof DefaultIsExpandedProcessor) {
             DefaultIsExpandedProcessor isExpandedProcessor = (DefaultIsExpandedProcessor)processor;
             for(NodeContext expanded : state.expandedNodes) {
-                isExpandedProcessor.setExpanded(expanded, true);
+                isExpandedProcessor.replaceExpanded(expanded, true);
             }
         }
     }
@@ -1947,7 +1948,7 @@ class GraphExplorerImpl extends GraphExplorerImplBase implements Listener, Graph
         }
                    
         persistor.serialize(
-                Platform.getStateLocation(Activator.getDefault().getBundle()).toFile(),
+                ExplorerStates.explorerStateLocation(),
                 getRoot(),
                 new ExplorerState(topNodePath, topNodePathChildIndex, expandedNodes, columnWidths));
     }
@@ -3251,13 +3252,16 @@ class GraphExplorerImpl extends GraphExplorerImplBase implements Listener, Graph
      */
     private void doSetColumns(Column[] cols, Consumer<Map<Column, Object>> callback) {
         // Attempt to keep previous column widths.
-        Map<String, Integer> prevWidths = new HashMap<String, Integer>();
+        Map<String, Integer> prevWidths = new HashMap<>();
         for (TreeColumn column : tree.getColumns()) {
-            prevWidths.put(column.getText(), column.getWidth());
-            column.dispose();
+            Column c = (Column) column.getData();
+            if (c != null) {
+                prevWidths.put(c.getKey(), column.getWidth());
+                column.dispose();
+            }
         }
 
-        HashMap<String, Integer> keyToIndex = new HashMap<String, Integer>();
+        HashMap<String, Integer> keyToIndex = new HashMap<>();
         for (int i = 0; i < cols.length; ++i) {
             keyToIndex.put(cols[i].getKey(), i);
         }
@@ -3268,7 +3272,7 @@ class GraphExplorerImpl extends GraphExplorerImplBase implements Listener, Graph
         this.columnImageArray = new Image[cols.length];
         this.columnDescOrImageArray = new Object[cols.length];
 
-        Map<Column, Object> map = new HashMap<Column, Object>();
+        Map<Column, Object> map = new HashMap<>();
 
         tree.setHeaderVisible(columnsAreVisible);
         for (Column column : columns) {
@@ -3281,7 +3285,7 @@ class GraphExplorerImpl extends GraphExplorerImplBase implements Listener, Graph
             int cw = column.getWidth();
 
             // Try to keep previous widths
-            Integer w = prevWidths.get(column);
+            Integer w = prevWidths.get(column.getKey());
             if (w != null)
                 c.setWidth(w);
             else if (cw != Column.DEFAULT_CONTROL_WIDTH)
@@ -3306,13 +3310,9 @@ class GraphExplorerImpl extends GraphExplorerImplBase implements Listener, Graph
         if(callback != null) callback.accept(map);
 
         // Make sure the explorer fits the columns properly after initialization.
-        tree.getDisplay().asyncExec(new Runnable() {
-            @Override
-            public void run() {
-                if (tree.isDisposed())
-                    return;
+        SWTUtils.asyncExec(tree, () -> {
+            if (!tree.isDisposed())
                 refreshColumnSizes();
-            }
         });
     }
 
index af0fa25a355019468aecd5a89f6a6f950e69833e..c21158e31a65785d8a9dd5d7df728871af63a785 100644 (file)
@@ -38,7 +38,6 @@ import org.eclipse.core.runtime.IAdaptable;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.MultiStatus;
-import org.eclipse.core.runtime.Platform;
 import org.eclipse.core.runtime.Status;
 import org.eclipse.core.runtime.jobs.Job;
 import org.eclipse.jface.layout.GridDataFactory;
@@ -154,6 +153,7 @@ import org.simantics.browsing.ui.common.processors.DefaultViewpointProcessor;
 import org.simantics.browsing.ui.common.processors.IsExpandedProcessor;
 import org.simantics.browsing.ui.common.processors.NoSelectionRequestProcessor;
 import org.simantics.browsing.ui.common.processors.ProcessorLifecycle;
+import org.simantics.browsing.ui.common.state.ExplorerStates;
 import org.simantics.browsing.ui.content.ImageDecorator;
 import org.simantics.browsing.ui.content.Imager;
 import org.simantics.browsing.ui.content.LabelDecorator;
@@ -174,6 +174,7 @@ import org.simantics.utils.threads.SWTThread;
 import org.simantics.utils.threads.ThreadUtils;
 import org.simantics.utils.ui.AdaptionUtils;
 import org.simantics.utils.ui.ISelectionUtils;
+import org.simantics.utils.ui.SWTUtils;
 import org.simantics.utils.ui.jface.BasePostSelectionProvider;
 
 import gnu.trove.map.hash.THashMap;
@@ -574,17 +575,16 @@ public class GraphExplorerImpl2 extends GraphExplorerImplBase implements GraphEx
     private void initializeState() {
         if (persistor == null)
             return;
+        ExplorerStates.scheduleRead(getRoot(), persistor)
+        .thenAccept(state -> SWTUtils.asyncExec(viewer.getTree(), () -> restoreState(state)));
+    }
 
-        ExplorerState state = persistor.deserialize(
-                Platform.getStateLocation(Activator.getDefault().getBundle()).toFile(),
-                getRoot());
-
-
+    private void restoreState(ExplorerState state) {
         Object processor = getPrimitiveProcessor(BuiltinKeys.IS_EXPANDED);
         if (processor instanceof DefaultIsExpandedProcessor) {
             DefaultIsExpandedProcessor isExpandedProcessor = (DefaultIsExpandedProcessor)processor;
             for(NodeContext expanded : state.expandedNodes) {
-                isExpandedProcessor.setExpanded(expanded, true);
+                isExpandedProcessor.replaceExpanded(expanded, true);
             }
         }
     }
@@ -717,13 +717,14 @@ public class GraphExplorerImpl2 extends GraphExplorerImplBase implements GraphEx
     
     private void doSetColumns(Column[] cols, Consumer<Map<Column, Object>> callback) {
         // Attempt to keep previous column widths.
-        Map<String, Integer> prevWidths = new HashMap<String, Integer>();
-        
+        Map<String, Integer> prevWidths = new HashMap<>();
         for (TreeViewerColumn c : treeViewerColumns) {
-               prevWidths.put(c.getColumn().getText(), c.getColumn().getWidth());
-               c.getColumn().dispose();
+            Column col = (Column) (c.getColumn().getData());
+            if (col != null)
+                prevWidths.put(col.getKey(), c.getColumn().getWidth());
+            c.getColumn().dispose();
         }
-       
+
         treeViewerColumns.clear();
         
         HashMap<String, Integer> keyToIndex = new HashMap<String, Integer>();
@@ -765,7 +766,7 @@ public class GraphExplorerImpl2 extends GraphExplorerImplBase implements GraphEx
             int cw = column.getWidth();
 
             // Try to keep previous widths
-            Integer w = prevWidths.get(column);
+            Integer w = prevWidths.get(column.getKey());
             if (w != null)
                 c.setWidth(w);
             else if (cw != Column.DEFAULT_CONTROL_WIDTH)
@@ -2487,11 +2488,11 @@ public class GraphExplorerImpl2 extends GraphExplorerImplBase implements GraphEx
                        return context == null;
                }
                
-               @SuppressWarnings("rawtypes")
+               @SuppressWarnings("unchecked")
                @Override
-               public Object getAdapter(Class adapter) {
+               public <T> T getAdapter(Class<T> adapter) {
                        if (adapter == NodeContext.class)
-                               return context;
+                               return (T) context;
                        return context.getAdapter(adapter);
                }
                
@@ -2712,9 +2713,8 @@ public class GraphExplorerImpl2 extends GraphExplorerImplBase implements GraphEx
             * store the key, this is not used.
             */
            NodeContext getNC = new NodeContext() {
-               @SuppressWarnings("rawtypes")
-                       @Override
-               public Object getAdapter(Class adapter) {
+               @Override
+               public <T> T getAdapter(Class<T> adapter) {
                        return null;
                }
                
index 42ee2bdf812fe788e20b040139ac9ae9df4fdce6..2f52153a1192b45e2a6c33e42afd2da58a86e1a1 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2012 Association for Decentralized Information Management
+ * Copyright (c) 2007, 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,10 +17,8 @@ import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 import java.util.function.BiFunction;
-import java.util.function.Consumer;
 
 import org.eclipse.core.runtime.IAdaptable;
-import org.eclipse.core.runtime.Platform;
 import org.eclipse.jface.action.IMenuManager;
 import org.eclipse.jface.layout.GridDataFactory;
 import org.eclipse.jface.layout.GridLayoutFactory;
@@ -45,7 +43,6 @@ import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Event;
 import org.eclipse.swt.widgets.Listener;
 import org.eclipse.swt.widgets.Tree;
-import org.eclipse.swt.widgets.TreeColumn;
 import org.eclipse.swt.widgets.TreeItem;
 import org.eclipse.ui.ISelectionListener;
 import org.eclipse.ui.IWorkbenchSite;
@@ -72,6 +69,7 @@ import org.simantics.browsing.ui.common.processors.LabelerFactoryResolver;
 import org.simantics.browsing.ui.common.processors.UserSelectedComparableFactoryQueryProcessor;
 import org.simantics.browsing.ui.common.processors.UserSelectedViewpointFactoryQueryProcessor;
 import org.simantics.browsing.ui.common.processors.ViewpointFactoryResolver;
+import org.simantics.browsing.ui.common.state.ExplorerStates;
 import org.simantics.browsing.ui.common.views.FilterAreaSource;
 import org.simantics.browsing.ui.common.views.IFilterArea;
 import org.simantics.browsing.ui.common.views.IFilterAreaProvider;
@@ -83,7 +81,6 @@ import org.simantics.browsing.ui.graph.impl.RelatedObjectsQueryProcessor;
 import org.simantics.browsing.ui.graph.impl.SessionContextInputSource;
 import org.simantics.browsing.ui.model.browsecontexts.BrowseContext;
 import org.simantics.browsing.ui.model.nodetypes.NodeType;
-import org.simantics.browsing.ui.swt.Activator;
 import org.simantics.browsing.ui.swt.ComparatorSelector;
 import org.simantics.browsing.ui.swt.ContextMenuInitializer;
 import org.simantics.browsing.ui.swt.DefaultExplorerSelectionListener;
@@ -135,6 +132,7 @@ 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.datastructures.hints.IHintTracker;
+import org.simantics.utils.ui.SWTUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -1194,52 +1192,48 @@ public class GraphExplorerComposite extends Composite implements Widget, IAdapta
     }
 
     private int getColumnWidth(Column column, ExplorerState state) {
-       // Get saved width from the persistor if there is one.
+        // Get saved width from the persistor if there is one.
         if (state != null && state.columnWidths != null) {
-               Integer width = state.columnWidths.get(column.getLabel());
-               if (width != null)
-                       return width;
+            Integer width = state.columnWidths.get(column.getLabel());
+            if (width != null)
+                return width;
         }
         return column.getWidth();
     }
-    
-    public void setColumns(Column[] columns) {
-
-        explorer.setColumns(columns, new Consumer<Map<Column, Object>>() {
-
-            @Override
-            public void accept(Map<Column, Object> objects) {
-               ExplorerState state = null;
-               if (persistor != null) {
-                       state = persistor.deserialize(
-                               Platform.getStateLocation(Activator.getDefault().getBundle()).toFile(),
-                               explorer.getRoot());
-               }
-
-                for(Map.Entry<Column, Object> entry : objects.entrySet()) {
-                    Column column = entry.getKey();
-                    TreeColumn treeColumn = (TreeColumn)entry.getValue();
-
-                    if (column.getWidth() < 0) {
-                        throw new IllegalArgumentException("Column minimum width cannot be < 0, got " + column.getWidth());
-                    }
-
-                    int width = getColumnWidth(column, state);
-                    if(column.hasGrab()) {
-                       
-                        ad.setColumnData(treeColumn, new ColumnWeightData(column.getWeight(), width));
-
-                    } else {
-
-                        ad.setColumnData(treeColumn, new ColumnWeightData(0, width));
 
-                    }
-
-                }
-            }
+    protected void restoreColumnSizes(Map<Column, Object> columns) {
+        if (persistor != null) {
+            setColumnData(columns, null);
+            ExplorerStates.scheduleRead(explorer.getRoot(), persistor).thenAccept(state -> {
+                SWTUtils.asyncExec(GraphExplorerComposite.this, () -> {
+                    if (explorerComposite.isDisposed())
+                        setColumnData(columns, state);
+                });
+            });
+        } else {
+            setColumnData(columns, null);
+        }
+    }
 
+    protected void setColumnData(Map<Column, Object> columns, ExplorerState state) {
+        columns.forEach((column, widget) -> {
+            org.eclipse.swt.widgets.Widget columnWidget = (org.eclipse.swt.widgets.Widget) widget;
+            ad.setColumnData(columnWidget,
+                    new ColumnWeightData(
+                            column.hasGrab() ? column.getWeight() : 0,
+                            getColumnWidth(column, state)));
         });
+    }
 
+    public void setColumns(Column[] columns) {
+        // ColumnWeightData does not support column weight/width < 0
+        for (Column column : columns) {
+            if (column.getWeight() < 0)
+                throw new IllegalArgumentException("Column weight must be >= 0, got " + column.getWeight() + " for " + column);
+            if (column.getWidth() < 0)
+                throw new IllegalArgumentException("Column minimum width must be >= 0, got " + column.getWidth() + " for " + column);
+        }
+        explorer.setColumns(columns, this::restoreColumnSizes);
     }
 
     @Override
index c8bf80cd8520b8152e994f93f48ae6b69650da57..21126cccca89eebcac44a0f3cae4df133922a77e 100644 (file)
@@ -24,18 +24,18 @@ import org.simantics.browsing.ui.NodeContext;
 import org.simantics.browsing.ui.NodeContext.ConstantKey;
 import org.simantics.browsing.ui.common.NodeContextBuilder;
 import org.simantics.browsing.ui.common.NodeContextBuilder.MapNodeContext;
+import org.simantics.browsing.ui.common.state.GraphExplorerStateBean;
+import org.simantics.browsing.ui.common.state.GraphExplorerStateNodeBean;
+import org.simantics.browsing.ui.common.state.IdentifiedStatePersistor;
+import org.simantics.browsing.ui.common.state.StringArrayBean;
+import org.simantics.browsing.ui.common.state.StringBean;
 import org.simantics.browsing.ui.model.actions.ActionBrowseContext;
 import org.simantics.browsing.ui.model.browsecontexts.BrowseContext;
 import org.simantics.browsing.ui.model.browsecontexts.BrowseContexts;
 import org.simantics.browsing.ui.model.nodetypes.EntityNodeType;
 import org.simantics.browsing.ui.model.nodetypes.NodeType;
 import org.simantics.browsing.ui.model.nodetypes.SpecialNodeType;
-import org.simantics.browsing.ui.swt.GraphExplorerStateBean;
-import org.simantics.browsing.ui.swt.GraphExplorerStateNodeBean;
-import org.simantics.browsing.ui.swt.IdentifiedStatePersistor;
 import org.simantics.browsing.ui.swt.NodeContextValueBean;
-import org.simantics.browsing.ui.swt.StringArrayBean;
-import org.simantics.browsing.ui.swt.StringBean;
 import org.simantics.databoard.Bindings;
 import org.simantics.databoard.binding.impl.ArrayListBinding;
 import org.simantics.databoard.util.Bean;