-/*******************************************************************************\r
- * Copyright (c) 2007, 2013 Association for Decentralized Information Management\r
- * in Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- * VTT Technical Research Centre of Finland - initial API and implementation\r
- * Semantum Oy - index based searching (#4255)\r
- *******************************************************************************/\r
-package org.simantics.ui.workbench.dialogs;\r
-\r
-import gnu.trove.map.hash.THashMap;\r
-\r
-import java.util.ArrayList;\r
-import java.util.List;\r
-import java.util.Map;\r
-import java.util.concurrent.CopyOnWriteArrayList;\r
-import java.util.concurrent.atomic.AtomicBoolean;\r
-\r
-import org.eclipse.core.runtime.IProgressMonitor;\r
-import org.eclipse.core.runtime.IStatus;\r
-import org.eclipse.core.runtime.MultiStatus;\r
-import org.eclipse.core.runtime.Status;\r
-import org.eclipse.core.runtime.jobs.Job;\r
-import org.eclipse.jface.resource.DeviceResourceManager;\r
-import org.eclipse.jface.resource.ImageDescriptor;\r
-import org.eclipse.jface.resource.ResourceManager;\r
-import org.eclipse.jface.viewers.ILabelProvider;\r
-import org.eclipse.jface.viewers.ILabelProviderListener;\r
-import org.eclipse.jface.viewers.LabelProviderChangedEvent;\r
-import org.eclipse.swt.graphics.Device;\r
-import org.eclipse.swt.graphics.Image;\r
-import org.eclipse.swt.widgets.Display;\r
-import org.eclipse.ui.progress.IProgressConstants;\r
-import org.simantics.DatabaseJob;\r
-import org.simantics.Simantics;\r
-import org.simantics.db.ReadGraph;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.Session;\r
-import org.simantics.db.common.request.ReadRequest;\r
-import org.simantics.db.common.utils.NameUtils;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.ui.icons.ImageDescriptorProvider;\r
-import org.simantics.ui.icons.ImageUtil;\r
-import org.simantics.ui.internal.Activator;\r
-import org.simantics.utils.threads.IThreadWorkQueue;\r
-import org.simantics.utils.threads.SWTThread;\r
-import org.simantics.utils.ui.gfx.CompositionImageDescriptor;\r
-\r
-/**\r
- * ResourceLabelProvider is a label provider for Simantics database\r
- * {@link Resource}s.\r
- * \r
- * <p>\r
- * This label provider utilizes {@link ImageDescriptorProvider} adapters for\r
- * determining the icon to use.\r
- * \r
- * @author Toni Kalajainen\r
- * @author Tuukka Lehtonen\r
- * \r
- * @see Resource\r
- * @see ILabelProvider\r
- * @see ILabelProviderListener\r
- */\r
-public class ResourceLabelProvider implements ILabelProvider {\r
-\r
- protected List<ILabelProviderListener> listeners = null;\r
- protected IThreadWorkQueue thread;\r
- protected TaskRepository tasks;\r
- protected LoadJob loadJob;\r
-\r
- public ResourceLabelProvider(Display display) {\r
- this.thread = SWTThread.getThreadAccess(display);\r
- this.tasks = new TaskRepository(display);\r
- this.loadJob = new LoadJob("Resource Labeler", tasks, this);\r
- }\r
-\r
- public void fireChangedEvent(LabelProviderChangedEvent e) {\r
- ILabelProviderListener[] listeners;\r
- synchronized(this) {\r
- if (this.listeners == null)\r
- return;\r
- listeners = this.listeners.toArray(new ILabelProviderListener[0]);\r
- }\r
- for (ILabelProviderListener l : listeners)\r
- l.labelProviderChanged(e);\r
- }\r
-\r
- public void asyncFireChangedEvent(final LabelProviderChangedEvent e) {\r
- thread.asyncExec(new Runnable() {\r
- @Override\r
- public void run() {\r
- fireChangedEvent(e);\r
- }\r
- });\r
- }\r
-\r
- public synchronized void addListener(ILabelProviderListener listener) {\r
- if (listeners == null)\r
- listeners = new CopyOnWriteArrayList<ILabelProviderListener>();\r
- listeners.add(listener);\r
- }\r
-\r
- public void dispose() {\r
- if (listeners != null)\r
- listeners.clear();\r
- loadJob.dispose();\r
- tasks.dispose();\r
- }\r
-\r
- public void clear() {\r
- tasks.clear();\r
- }\r
-\r
- public boolean isLabelProperty(Object element, String property) {\r
- System.out.println("isLabelProperty(" + element + ", " + property + ")");\r
- return false;\r
- }\r
-\r
- public synchronized void removeListener(ILabelProviderListener listener) {\r
- if (listeners != null)\r
- listeners.remove(listener);\r
- }\r
-\r
- @Override\r
- public Image getImage(Object element) {\r
- if (element == null)\r
- return null;\r
- Resource r = (Resource) element;\r
- Task task = tasks.getCompleted(r);\r
- if (task != null) {\r
- return task.image;\r
- }\r
- task = tasks.queue(r);\r
- loadJob.scheduleIfNecessary(100);\r
- return task.image;\r
- }\r
-\r
- @Override\r
- public String getText(Object element) {\r
- if (element == null)\r
- return null;\r
- Resource r = (Resource) element;\r
- Task task = tasks.getCompleted(r);\r
- if (task != null) {\r
- return task.label;\r
- }\r
- task = tasks.queue(r);\r
- loadJob.scheduleIfNecessary(100);\r
- return task.label;\r
- }\r
-\r
- private static class LoadJob extends DatabaseJob {\r
- private TaskRepository tasks;\r
- private ResourceLabelProvider labelProvider;\r
- private AtomicBoolean isScheduled = new AtomicBoolean();\r
-\r
- public LoadJob(String name, TaskRepository tasks, ResourceLabelProvider labelProvider) {\r
- super(name);\r
- setUser(false);\r
- setSystem(true);\r
- setPriority(SHORT);\r
- setProperty(IProgressConstants.NO_IMMEDIATE_ERROR_PROMPT_PROPERTY, Boolean.TRUE);\r
- this.tasks = tasks;\r
- this.labelProvider = labelProvider;\r
- }\r
-\r
- /**\r
- * Schedules the job with {@link Job#schedule()} if necessary, i.e. if\r
- * not already scheduled. This method avoids some unnecessary overhead\r
- * caused by repeatedly invoking {@link Job#schedule()}.\r
- * \r
- * @return <code>true</code> if scheduled, <code>false</code> otherwise\r
- */\r
- public boolean scheduleIfNecessary(long delay) {\r
- if (isScheduled.compareAndSet(false, true)) {\r
- schedule(delay);\r
- return true;\r
- }\r
- return false;\r
- }\r
-\r
- void dispose() {\r
- tasks = null;\r
- labelProvider = null;\r
- }\r
-\r
- @Override\r
- public boolean shouldSchedule() {\r
- return tasks != null;\r
- }\r
-\r
- @Override\r
- public boolean shouldRun() {\r
- return tasks != null;\r
- }\r
-\r
- @Override\r
- protected IStatus run(IProgressMonitor monitor) {\r
- try {\r
- isScheduled.set(false);\r
-\r
- TaskRepository tr = tasks;\r
- if (tr == null)\r
- return Status.CANCEL_STATUS;\r
-\r
- Task[] taskList = tr.pruneTasks();\r
- return runTasks(tr, taskList);\r
- } finally {\r
- monitor.done();\r
- }\r
- }\r
-\r
- private IStatus runTasks(final TaskRepository tr, final Task[] taskList) {\r
- Session session = Simantics.peekSession();\r
- if (session == null)\r
- return Status.CANCEL_STATUS;\r
- final ResourceManager rm = tr.resourceManager;\r
- if (rm == null)\r
- return Status.CANCEL_STATUS;\r
-\r
- final MultiStatus result = new MultiStatus(Activator.PLUGIN_ID, 0, "Problems encountered while invoking resource label provider:", null);\r
- try {\r
- Simantics.getSession().syncRequest(new ReadRequest() {\r
- @Override\r
- public void run(ReadGraph graph) throws DatabaseException {\r
- for (Task task : taskList) {\r
- try {\r
- if (tr.isDisposed())\r
- return;\r
-\r
- runTask(rm, graph, task);\r
- tasks.complete(task);\r
- } catch (DatabaseException e) {\r
- result.add(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e));\r
- }\r
- }\r
- }\r
- });\r
- return result;\r
- } catch (DatabaseException e) {\r
- return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Resource label provider failed unexpectedly.", e);\r
- } finally {\r
- labelProvider.asyncFireChangedEvent(new LabelProviderChangedEvent(labelProvider));\r
- }\r
- }\r
-\r
- protected void runTask(ResourceManager rm, ReadGraph graph, Task task) throws DatabaseException {\r
- task.label = getText(graph, task.resource);\r
- task.image = getImage(rm, graph, task.resource);\r
- }\r
-\r
- protected String getText(ReadGraph graph, Resource resource) {\r
- try {\r
- return graph.adapt(resource, String.class);\r
- } catch (DatabaseException e) {\r
- try {\r
- return NameUtils.getSafeName(graph, resource);\r
- } catch (DatabaseException e2) {\r
- return "";\r
- }\r
- }\r
- }\r
-\r
- public Image getImage(ResourceManager rm, ReadGraph graph, Resource resource) throws DatabaseException {\r
- ImageDescriptor i = getImageDescriptor(graph, resource);\r
- return i == null ? null : (Image) rm.get(i);\r
- }\r
-\r
- public ImageDescriptor getImageDescriptor(ReadGraph graph, Resource resource, ImageDescriptor... decorations)\r
- throws DatabaseException {\r
- ImageDescriptor baseImage = ImageUtil.adaptImageDescriptor(graph, resource);\r
- if (baseImage == null)\r
- return null;\r
- if (decorations == null || decorations.length == 0)\r
- return baseImage;\r
- List<ImageDescriptor> images = new ArrayList<ImageDescriptor>(1+decorations.length);\r
- images.add(baseImage);\r
- for (ImageDescriptor image : decorations)\r
- images.add(image);\r
- return CompositionImageDescriptor.compose(images);\r
- }\r
-\r
- }\r
-\r
- private static class TaskRepository {\r
- Map<Resource, Task> tasks = new THashMap<Resource, Task>();\r
- Map<Resource, Task> completed = new THashMap<Resource, Task>();\r
-\r
- ResourceManager resourceManager;\r
-\r
- public TaskRepository(Device device) {\r
- this.resourceManager = new DeviceResourceManager(device);\r
- }\r
-\r
- public boolean isDisposed() {\r
- return resourceManager == null;\r
- }\r
-\r
- public void dispose() {\r
- if (resourceManager != null) {\r
- resourceManager.dispose();\r
- resourceManager = null;\r
- }\r
- }\r
-\r
- public Task queue(Task task) {\r
- synchronized (tasks) {\r
- tasks.put(task.resource, task);\r
- }\r
- return task;\r
- }\r
-\r
- public Task queue(Resource resource) {\r
- return queue(new Task(resource));\r
- }\r
-\r
- public void clear() {\r
- pruneTasks();\r
- pruneCompleted();\r
- }\r
-\r
- public Task[] pruneTasks() {\r
- synchronized (tasks) {\r
- Task[] result = tasks.values().toArray(Task.NONE);\r
- tasks.clear();\r
- return result;\r
- }\r
- }\r
-\r
- public void pruneCompleted() {\r
- synchronized (completed) {\r
- completed.clear();\r
- }\r
- }\r
-\r
- public void complete(Task task) {\r
- synchronized (completed) {\r
- completed.put(task.resource, task);\r
- }\r
- }\r
-\r
- public Task getCompleted(Resource r) {\r
- synchronized (completed) {\r
- return completed.get(r);\r
- }\r
- }\r
-\r
- }\r
-\r
- private static class Task {\r
- public static final Task[] NONE = {};\r
-\r
- public final Resource resource;\r
- public String label = "";\r
- public Image image;\r
-\r
- public Task(Resource resource) {\r
- this.resource = resource;\r
- }\r
- }\r
-\r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2007, 2013 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VTT Technical Research Centre of Finland - initial API and implementation
+ * Semantum Oy - index based searching (#4255)
+ *******************************************************************************/
+package org.simantics.ui.workbench.dialogs;
+
+import gnu.trove.map.hash.THashMap;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.resource.DeviceResourceManager;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ResourceManager;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.LabelProviderChangedEvent;
+import org.eclipse.swt.graphics.Device;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.progress.IProgressConstants;
+import org.simantics.DatabaseJob;
+import org.simantics.Simantics;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.Session;
+import org.simantics.db.common.request.ReadRequest;
+import org.simantics.db.common.utils.NameUtils;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.ui.icons.ImageDescriptorProvider;
+import org.simantics.ui.icons.ImageUtil;
+import org.simantics.ui.internal.Activator;
+import org.simantics.utils.threads.IThreadWorkQueue;
+import org.simantics.utils.threads.SWTThread;
+import org.simantics.utils.ui.gfx.CompositionImageDescriptor;
+
+/**
+ * ResourceLabelProvider is a label provider for Simantics database
+ * {@link Resource}s.
+ *
+ * <p>
+ * This label provider utilizes {@link ImageDescriptorProvider} adapters for
+ * determining the icon to use.
+ *
+ * @author Toni Kalajainen
+ * @author Tuukka Lehtonen
+ *
+ * @see Resource
+ * @see ILabelProvider
+ * @see ILabelProviderListener
+ */
+public class ResourceLabelProvider implements ILabelProvider {
+
+ protected List<ILabelProviderListener> listeners = null;
+ protected IThreadWorkQueue thread;
+ protected TaskRepository tasks;
+ protected LoadJob loadJob;
+
+ public ResourceLabelProvider(Display display) {
+ this.thread = SWTThread.getThreadAccess(display);
+ this.tasks = new TaskRepository(display);
+ this.loadJob = new LoadJob("Resource Labeler", tasks, this);
+ }
+
+ public void fireChangedEvent(LabelProviderChangedEvent e) {
+ ILabelProviderListener[] listeners;
+ synchronized(this) {
+ if (this.listeners == null)
+ return;
+ listeners = this.listeners.toArray(new ILabelProviderListener[0]);
+ }
+ for (ILabelProviderListener l : listeners)
+ l.labelProviderChanged(e);
+ }
+
+ public void asyncFireChangedEvent(final LabelProviderChangedEvent e) {
+ thread.asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ fireChangedEvent(e);
+ }
+ });
+ }
+
+ public synchronized void addListener(ILabelProviderListener listener) {
+ if (listeners == null)
+ listeners = new CopyOnWriteArrayList<ILabelProviderListener>();
+ listeners.add(listener);
+ }
+
+ public void dispose() {
+ if (listeners != null)
+ listeners.clear();
+ loadJob.dispose();
+ tasks.dispose();
+ }
+
+ public void clear() {
+ tasks.clear();
+ }
+
+ public boolean isLabelProperty(Object element, String property) {
+ System.out.println("isLabelProperty(" + element + ", " + property + ")");
+ return false;
+ }
+
+ public synchronized void removeListener(ILabelProviderListener listener) {
+ if (listeners != null)
+ listeners.remove(listener);
+ }
+
+ @Override
+ public Image getImage(Object element) {
+ if (element == null)
+ return null;
+ Resource r = (Resource) element;
+ Task task = tasks.getCompleted(r);
+ if (task != null) {
+ return task.image;
+ }
+ task = tasks.queue(r);
+ loadJob.scheduleIfNecessary(100);
+ return task.image;
+ }
+
+ @Override
+ public String getText(Object element) {
+ if (element == null)
+ return null;
+ Resource r = (Resource) element;
+ Task task = tasks.getCompleted(r);
+ if (task != null) {
+ return task.label;
+ }
+ task = tasks.queue(r);
+ loadJob.scheduleIfNecessary(100);
+ return task.label;
+ }
+
+ private static class LoadJob extends DatabaseJob {
+ private TaskRepository tasks;
+ private ResourceLabelProvider labelProvider;
+ private AtomicBoolean isScheduled = new AtomicBoolean();
+
+ public LoadJob(String name, TaskRepository tasks, ResourceLabelProvider labelProvider) {
+ super(name);
+ setUser(false);
+ setSystem(true);
+ setPriority(SHORT);
+ setProperty(IProgressConstants.NO_IMMEDIATE_ERROR_PROMPT_PROPERTY, Boolean.TRUE);
+ this.tasks = tasks;
+ this.labelProvider = labelProvider;
+ }
+
+ /**
+ * Schedules the job with {@link Job#schedule()} if necessary, i.e. if
+ * not already scheduled. This method avoids some unnecessary overhead
+ * caused by repeatedly invoking {@link Job#schedule()}.
+ *
+ * @return <code>true</code> if scheduled, <code>false</code> otherwise
+ */
+ public boolean scheduleIfNecessary(long delay) {
+ if (isScheduled.compareAndSet(false, true)) {
+ schedule(delay);
+ return true;
+ }
+ return false;
+ }
+
+ void dispose() {
+ tasks = null;
+ labelProvider = null;
+ }
+
+ @Override
+ public boolean shouldSchedule() {
+ return tasks != null;
+ }
+
+ @Override
+ public boolean shouldRun() {
+ return tasks != null;
+ }
+
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ try {
+ isScheduled.set(false);
+
+ TaskRepository tr = tasks;
+ if (tr == null)
+ return Status.CANCEL_STATUS;
+
+ Task[] taskList = tr.pruneTasks();
+ return runTasks(tr, taskList);
+ } finally {
+ monitor.done();
+ }
+ }
+
+ private IStatus runTasks(final TaskRepository tr, final Task[] taskList) {
+ Session session = Simantics.peekSession();
+ if (session == null)
+ return Status.CANCEL_STATUS;
+ final ResourceManager rm = tr.resourceManager;
+ if (rm == null)
+ return Status.CANCEL_STATUS;
+
+ final MultiStatus result = new MultiStatus(Activator.PLUGIN_ID, 0, "Problems encountered while invoking resource label provider:", null);
+ try {
+ Simantics.getSession().syncRequest(new ReadRequest() {
+ @Override
+ public void run(ReadGraph graph) throws DatabaseException {
+ for (Task task : taskList) {
+ try {
+ if (tr.isDisposed())
+ return;
+
+ runTask(rm, graph, task);
+ tasks.complete(task);
+ } catch (DatabaseException e) {
+ result.add(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e));
+ }
+ }
+ }
+ });
+ return result;
+ } catch (DatabaseException e) {
+ return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Resource label provider failed unexpectedly.", e);
+ } finally {
+ labelProvider.asyncFireChangedEvent(new LabelProviderChangedEvent(labelProvider));
+ }
+ }
+
+ protected void runTask(ResourceManager rm, ReadGraph graph, Task task) throws DatabaseException {
+ task.label = getText(graph, task.resource);
+ task.image = getImage(rm, graph, task.resource);
+ }
+
+ protected String getText(ReadGraph graph, Resource resource) {
+ try {
+ return graph.adapt(resource, String.class);
+ } catch (DatabaseException e) {
+ try {
+ return NameUtils.getSafeName(graph, resource);
+ } catch (DatabaseException e2) {
+ return "";
+ }
+ }
+ }
+
+ public Image getImage(ResourceManager rm, ReadGraph graph, Resource resource) throws DatabaseException {
+ ImageDescriptor i = getImageDescriptor(graph, resource);
+ return i == null ? null : (Image) rm.get(i);
+ }
+
+ public ImageDescriptor getImageDescriptor(ReadGraph graph, Resource resource, ImageDescriptor... decorations)
+ throws DatabaseException {
+ ImageDescriptor baseImage = ImageUtil.adaptImageDescriptor(graph, resource);
+ if (baseImage == null)
+ return null;
+ if (decorations == null || decorations.length == 0)
+ return baseImage;
+ List<ImageDescriptor> images = new ArrayList<ImageDescriptor>(1+decorations.length);
+ images.add(baseImage);
+ for (ImageDescriptor image : decorations)
+ images.add(image);
+ return CompositionImageDescriptor.compose(images);
+ }
+
+ }
+
+ private static class TaskRepository {
+ Map<Resource, Task> tasks = new THashMap<Resource, Task>();
+ Map<Resource, Task> completed = new THashMap<Resource, Task>();
+
+ ResourceManager resourceManager;
+
+ public TaskRepository(Device device) {
+ this.resourceManager = new DeviceResourceManager(device);
+ }
+
+ public boolean isDisposed() {
+ return resourceManager == null;
+ }
+
+ public void dispose() {
+ if (resourceManager != null) {
+ resourceManager.dispose();
+ resourceManager = null;
+ }
+ }
+
+ public Task queue(Task task) {
+ synchronized (tasks) {
+ tasks.put(task.resource, task);
+ }
+ return task;
+ }
+
+ public Task queue(Resource resource) {
+ return queue(new Task(resource));
+ }
+
+ public void clear() {
+ pruneTasks();
+ pruneCompleted();
+ }
+
+ public Task[] pruneTasks() {
+ synchronized (tasks) {
+ Task[] result = tasks.values().toArray(Task.NONE);
+ tasks.clear();
+ return result;
+ }
+ }
+
+ public void pruneCompleted() {
+ synchronized (completed) {
+ completed.clear();
+ }
+ }
+
+ public void complete(Task task) {
+ synchronized (completed) {
+ completed.put(task.resource, task);
+ }
+ }
+
+ public Task getCompleted(Resource r) {
+ synchronized (completed) {
+ return completed.get(r);
+ }
+ }
+
+ }
+
+ private static class Task {
+ public static final Task[] NONE = {};
+
+ public final Resource resource;
+ public String label = "";
+ public Image image;
+
+ public Task(Resource resource) {
+ this.resource = resource;
+ }
+ }
+
+}