X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.ui%2Fsrc%2Forg%2Fsimantics%2Fui%2Fworkbench%2Fdialogs%2FResourceLabelProvider.java;fp=bundles%2Forg.simantics.ui%2Fsrc%2Forg%2Fsimantics%2Fui%2Fworkbench%2Fdialogs%2FResourceLabelProvider.java;h=e2f70e7c7d1d50197a28e01fb4873476e6277fa0;hb=0ae2b770234dfc3cbb18bd38f324125cf0faca07;hp=704138d2af6e7627eae9a0ba6d8f7c878c17be1f;hpb=24e2b34260f219f0d1644ca7a138894980e25b14;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.ui/src/org/simantics/ui/workbench/dialogs/ResourceLabelProvider.java b/bundles/org.simantics.ui/src/org/simantics/ui/workbench/dialogs/ResourceLabelProvider.java index 704138d2a..e2f70e7c7 100644 --- a/bundles/org.simantics.ui/src/org/simantics/ui/workbench/dialogs/ResourceLabelProvider.java +++ b/bundles/org.simantics.ui/src/org/simantics/ui/workbench/dialogs/ResourceLabelProvider.java @@ -1,366 +1,366 @@ -/******************************************************************************* - * 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. - * - *

- * 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 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(); - 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 true if scheduled, false 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 images = new ArrayList(1+decorations.length); - images.add(baseImage); - for (ImageDescriptor image : decorations) - images.add(image); - return CompositionImageDescriptor.compose(images); - } - - } - - private static class TaskRepository { - Map tasks = new THashMap(); - Map completed = new THashMap(); - - 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; - } - } - -} +/******************************************************************************* + * 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. + * + *

+ * 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 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(); + 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 true if scheduled, false 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 images = new ArrayList(1+decorations.length); + images.add(baseImage); + for (ImageDescriptor image : decorations) + images.add(image); + return CompositionImageDescriptor.compose(images); + } + + } + + private static class TaskRepository { + Map tasks = new THashMap(); + Map completed = new THashMap(); + + 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; + } + } + +}