From: Tuukka Lehtonen Date: Sat, 27 Oct 2018 17:35:14 +0000 (+0300) Subject: UI locking fixes for GraphExplorer implementations X-Git-Tag: v1.43.0~136^2~310^2 X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=commitdiff_plain;h=97e8b055b8ad16f1d799c81898fee075780a5a83;p=simantics%2Fplatform.git UI locking fixes for GraphExplorer implementations GraphExplorer implementations contained ExplorerState restore code that was ran synchronously in the UI thread. It will possibly require DB read transactions which locks the UI up. Persisted explorer state loading has now been moved into a Job from GraphExplorer implementations and GraphExplorerComposite. Also contains fixes for doSetColumns of all graph explorer implementations which was using a Map with the wrong keys. gitlab #160 Change-Id: I879fe4a099db70d5d8bbba185b4dc9d745c80911 --- diff --git a/bundles/org.simantics.browsing.ui.common/META-INF/MANIFEST.MF b/bundles/org.simantics.browsing.ui.common/META-INF/MANIFEST.MF index 4da99a126..b33d37df4 100644 --- a/bundles/org.simantics.browsing.ui.common/META-INF/MANIFEST.MF +++ b/bundles/org.simantics.browsing.ui.common/META-INF/MANIFEST.MF @@ -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 index 000000000..380968bed --- /dev/null +++ b/bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/state/ExplorerStates.java @@ -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 scheduleRead(NodeContext root, StatePersistor persistor) { + CompletableFuture 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 consumer; + + public ReaderJob(NodeContext root, StatePersistor persistor, CompletableFuture 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(); + } + } + + } + +} diff --git a/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/GraphExplorerStateBean.java b/bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/state/GraphExplorerStateBean.java 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 c9bf211dd..7b4d7877e 100644 --- a/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/GraphExplorerStateBean.java +++ b/bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/state/GraphExplorerStateBean.java @@ -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; diff --git a/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/GraphExplorerStateNodeBean.java b/bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/state/GraphExplorerStateNodeBean.java 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 49831e28c..67c5c9d7a 100644 --- a/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/GraphExplorerStateNodeBean.java +++ b/bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/state/GraphExplorerStateNodeBean.java @@ -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; diff --git a/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/IdentifiedStatePersistor.java b/bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/state/IdentifiedStatePersistor.java 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 5a3bb75b2..0a417bd38 100644 --- a/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/IdentifiedStatePersistor.java +++ b/bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/state/IdentifiedStatePersistor.java @@ -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; } } diff --git a/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/StringArrayBean.java b/bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/state/StringArrayBean.java 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 219db8364..90ff79a14 100644 --- a/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/StringArrayBean.java +++ b/bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/state/StringArrayBean.java @@ -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; diff --git a/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/StringBean.java b/bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/state/StringBean.java 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 c584da059..c2b435648 100644 --- a/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/StringBean.java +++ b/bundles/org.simantics.browsing.ui.common/src/org/simantics/browsing/ui/common/state/StringBean.java @@ -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; diff --git a/bundles/org.simantics.browsing.ui.nattable/src/org/simantics/browsing/ui/nattable/NatTableGraphExplorer.java b/bundles/org.simantics.browsing.ui.nattable/src/org/simantics/browsing/ui/nattable/NatTableGraphExplorer.java index be6a73a0c..37eafd4eb 100644 --- a/bundles/org.simantics.browsing.ui.nattable/src/org/simantics/browsing/ui/nattable/NatTableGraphExplorer.java +++ b/bundles/org.simantics.browsing.ui.nattable/src/org/simantics/browsing/ui/nattable/NatTableGraphExplorer.java @@ -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); } } } diff --git a/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/GraphExplorerImpl.java b/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/GraphExplorerImpl.java index 3cf5f7478..df736c1e6 100644 --- a/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/GraphExplorerImpl.java +++ b/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/GraphExplorerImpl.java @@ -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> callback) { // Attempt to keep previous column widths. - Map prevWidths = new HashMap(); + Map 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 keyToIndex = new HashMap(); + HashMap 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 map = new HashMap(); + Map 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(); - } }); } diff --git a/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/GraphExplorerImpl2.java b/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/GraphExplorerImpl2.java index af0fa25a3..c21158e31 100644 --- a/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/GraphExplorerImpl2.java +++ b/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/GraphExplorerImpl2.java @@ -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> callback) { // Attempt to keep previous column widths. - Map prevWidths = new HashMap(); - + Map 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 keyToIndex = new HashMap(); @@ -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 getAdapter(Class 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 getAdapter(Class adapter) { return null; } diff --git a/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/widgets/GraphExplorerComposite.java b/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/widgets/GraphExplorerComposite.java index 42ee2bdf8..2f52153a1 100644 --- a/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/widgets/GraphExplorerComposite.java +++ b/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/widgets/GraphExplorerComposite.java @@ -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>() { - - @Override - public void accept(Map objects) { - ExplorerState state = null; - if (persistor != null) { - state = persistor.deserialize( - Platform.getStateLocation(Activator.getDefault().getBundle()).toFile(), - explorer.getRoot()); - } - - for(Map.Entry 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 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 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 diff --git a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/function/StandardPersistor.java b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/function/StandardPersistor.java index c8bf80cd8..21126cccc 100644 --- a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/function/StandardPersistor.java +++ b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/function/StandardPersistor.java @@ -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;