| // IdentifiablePluginView.java |
| package org.eclipse.stem.ui.views; |
| |
| /******************************************************************************* |
| * Copyright (c) 2006, 2008 IBM Corporation and others. |
| * 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: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| |
| import java.text.MessageFormat; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.core.runtime.IConfigurationElement; |
| import org.eclipse.core.runtime.IExtensionRegistry; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.emf.common.notify.Adapter; |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.emf.edit.ui.dnd.LocalTransfer; |
| import org.eclipse.jface.action.MenuManager; |
| import org.eclipse.jface.action.Separator; |
| import org.eclipse.jface.util.LocalSelectionTransfer; |
| import org.eclipse.jface.viewers.DoubleClickEvent; |
| import org.eclipse.jface.viewers.IDoubleClickListener; |
| import org.eclipse.jface.viewers.ILabelProvider; |
| import org.eclipse.jface.viewers.ILabelProviderListener; |
| import org.eclipse.jface.viewers.ISelection; |
| import org.eclipse.jface.viewers.IStructuredSelection; |
| import org.eclipse.jface.viewers.ITreeContentProvider; |
| import org.eclipse.jface.viewers.StructuredSelection; |
| import org.eclipse.jface.viewers.TreeViewer; |
| import org.eclipse.jface.viewers.Viewer; |
| import org.eclipse.stem.core.Constants; |
| import org.eclipse.stem.core.common.DublinCore; |
| import org.eclipse.stem.core.common.Identifiable; |
| import org.eclipse.stem.data.geography.GeographicNames; |
| import org.eclipse.stem.jobs.execution.IExecutable; |
| import org.eclipse.stem.ui.Activator; |
| import org.eclipse.stem.ui.perspectives.Simulation; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.dnd.DND; |
| import org.eclipse.swt.dnd.DragSourceEvent; |
| import org.eclipse.swt.dnd.DragSourceListener; |
| import org.eclipse.swt.dnd.Transfer; |
| import org.eclipse.swt.events.MouseAdapter; |
| import org.eclipse.swt.events.MouseEvent; |
| import org.eclipse.swt.events.MouseTrackAdapter; |
| import org.eclipse.swt.graphics.Color; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.graphics.Rectangle; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.swt.widgets.Tree; |
| import org.eclipse.swt.widgets.TreeItem; |
| import org.eclipse.ui.ISharedImages; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.part.ViewPart; |
| |
| /** |
| * This class represents an eclipse view of the {@link Identifiable} resources |
| * of a particular type that have been imported into eclipse as plug-ins. |
| * |
| * @see Identifiable |
| * @see GraphsView |
| * @see ModelsView |
| * @see ScenariosView |
| */ |
| public abstract class IdentifiablePluginView extends ViewPart { |
| |
| protected TreeViewer treeViewer; |
| |
| private DublinCoreToolTipHandler dcTTipHandler; |
| |
| /** |
| * This is the selection that is in effect at the start of a drag operation |
| */ |
| protected ISelection selection; |
| |
| /** |
| * This map keeps track of the {@link Identifiable} that we've deserialized |
| * so we don't need to do that more than once. |
| * |
| * @see #getIdentifiable(URI) |
| */ |
| protected Map<URI, Identifiable> deserializedIdentifiablesMap = new HashMap<URI, Identifiable>(); |
| |
| /** |
| * Constructor |
| */ |
| public IdentifiablePluginView() { |
| super(); |
| } |
| |
| /** |
| * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) |
| */ |
| @Override |
| public void createPartControl(final Composite parent) { |
| dcTTipHandler = new DublinCoreToolTipHandler(parent.getShell()); |
| |
| treeViewer = new TreeViewer(parent); |
| treeViewer |
| .setContentProvider(new IdentifiablePluginViewTreeContentProvider()); |
| treeViewer |
| .setLabelProvider(getIdentifiablePluginViewLabelContentProvider()); |
| treeViewer.setUseHashlookup(true); |
| treeViewer.setInput(getInput()); |
| |
| // Hook up the dublin core tool tip handler |
| dcTTipHandler.addDCToolTipHelp(treeViewer.getTree()); |
| |
| // We become a selection provider too |
| getSite().setSelectionProvider(treeViewer); |
| |
| // Context Menu |
| final MenuManager contextMenuManager = new MenuManager(); |
| // Place Holder for Menu Additions |
| contextMenuManager.add(new Separator("execution")); |
| |
| // Set the context menu for the viewer |
| treeViewer.getControl().setMenu( |
| contextMenuManager.createContextMenu(treeViewer.getControl())); |
| getSite().registerContextMenu(contextMenuManager, treeViewer); |
| |
| // Listen for double-clicks on Executables |
| treeViewer.addDoubleClickListener(new IDoubleClickListener() { |
| public void doubleClick(final DoubleClickEvent event) { |
| final IExecutable executable = (IExecutable) Platform.getAdapterManager().getAdapter(((StructuredSelection) event.getSelection()).toList().get(0), IExecutable.class); |
| |
| // Were we successful in adapting? |
| if (executable != null) { |
| // Yes |
| executable.run(); |
| |
| // Only switch to the Simulation Persepctive when the executable is a standard |
| // run (scenario). For other executables we may want to stay in other special |
| // perspectives |
| if(executable instanceof Adapter) { |
| Adapter a = (Adapter) executable; |
| Object obj = a.getTarget(); |
| if( obj instanceof org.eclipse.stem.core.scenario.impl.ScenarioImpl ) { |
| Activator.switchToPerspective(Simulation.ID_STEM_SIMULATION_PERSPECTIVE); |
| } |
| } // if adapter (usually true) |
| |
| } // if |
| } // doubleClick |
| }); |
| |
| // Set up drag support |
| final int ops = DND.DROP_LINK | DND.DROP_COPY | DND.DROP_MOVE; |
| final Transfer[] transfers = new Transfer[] { |
| LocalSelectionTransfer.getTransfer(), |
| LocalTransfer.getInstance() }; |
| treeViewer.addDragSupport(ops, transfers, new DragSourceListener() { |
| |
| /** |
| * @see org.eclipse.swt.dnd.DragSourceListener#dragStart(org.eclipse.swt.dnd.DragSourceEvent) |
| */ |
| public void dragStart(final DragSourceEvent event) { |
| // We need to figure out when the drag can start here |
| // Just say "yes" right now |
| event.doit = true; |
| selection = treeViewer.getSelection(); |
| // LocalSelectionTransfer.getTransfer().setSelection(selection); |
| } // dragStart |
| |
| /** |
| * @see org.eclipse.swt.dnd.DragSourceListener#dragSetData(org.eclipse.swt.dnd.DragSourceEvent) |
| */ |
| public void dragSetData(final DragSourceEvent event) { |
| |
| if (LocalSelectionTransfer.getTransfer().isSupportedType( |
| event.dataType)) { |
| // Yes |
| event.data = extractURIStringsFromIdentifiableDelegates((IStructuredSelection) selection); |
| LocalSelectionTransfer.getTransfer().setSelection( |
| (IStructuredSelection) event.data); |
| } // if |
| else if (LocalTransfer.getInstance().isSupportedType( |
| event.dataType)) { |
| // Yes |
| event.data = extractURIStringsFromIdentifiableDelegates((IStructuredSelection) selection); |
| } // if |
| |
| } // dragSetData |
| |
| private IStructuredSelection extractURIStringsFromIdentifiableDelegates( |
| final IStructuredSelection selectedDelegates) { |
| final List<String> collection = new ArrayList<String>(); |
| for (final Iterator selectionIter = selectedDelegates |
| .iterator(); selectionIter.hasNext();) { |
| final Object element = selectionIter.next(); |
| // Was an Identifiable Delegate selected? |
| if (element instanceof IdentifiableDelegate) { |
| // Yes |
| // It has a URI that specifies the serialized |
| // representation of the Identifiable |
| final String uriString = ((IdentifiableDelegate) element) |
| .getDublinCore().getIdentifier(); |
| // Were we successful in getting the uri string? |
| if (uriString != null) { |
| // Yes |
| collection.add(uriString); |
| } |
| } // if |
| } // for each selection |
| |
| return new IStructuredSelection() { |
| |
| final List<String> list; |
| { |
| list = collection; |
| } |
| |
| public Object getFirstElement() { |
| return list.get(0); |
| } |
| |
| public Iterator<String> iterator() { |
| return list.iterator(); |
| } |
| |
| public int size() { |
| return list.size(); |
| } |
| |
| public Object[] toArray() { |
| return list.toArray(); |
| } |
| |
| public List<String> toList() { |
| return list; |
| } |
| |
| public boolean isEmpty() { |
| return list.isEmpty(); |
| } |
| }; |
| } // extractURIStrings |
| |
| /** |
| * @see org.eclipse.swt.dnd.DragSourceListener#dragFinished(org.eclipse.swt.dnd.DragSourceEvent) |
| */ |
| public void dragFinished( |
| @SuppressWarnings("unused") final DragSourceEvent event) { |
| selection = null; |
| LocalTransfer.getInstance().javaToNative(null, null); |
| } // dragFinished |
| |
| }); |
| } // createPartControl |
| |
| /** |
| * @see org.eclipse.ui.part.WorkbenchPart#setFocus() |
| */ |
| @Override |
| public void setFocus() { |
| // Nothing |
| } |
| |
| /** |
| * @return the input model specific to this view |
| */ |
| protected abstract IdentifiableViewModel getInput(); |
| |
| /** |
| * @return the {@link IdentifiablePluginViewLabelContentProvider} |
| * appropriate for the model |
| */ |
| protected abstract IdentifiablePluginViewLabelContentProvider getIdentifiablePluginViewLabelContentProvider(); |
| |
| /** |
| * This class represents the model of the {@link Identifiable}'s that extend |
| * a particular extension point. |
| */ |
| protected abstract static class IdentifiableViewModel { |
| // The root of the tree of categories and identifiables |
| private final Category root; |
| |
| // Mapping between a category id and a category |
| private final Map<String, Category> categoryMap; |
| |
| /** |
| * @param extensionPointID |
| * the identifier of the extension point that Identifiables |
| * use to plug-in. |
| */ |
| public IdentifiableViewModel(final String extensionPointID) { |
| root = new Category(Constants.IDENTIFIABLE_ROOT_CATEGORY_NAME, |
| Constants.IDENTIFIABLE_ROOT_CATEGORY_ID, ""); //$NON-NLS-1$ |
| categoryMap = new HashMap<String, Category>(); |
| categoryMap.put(root.getCategoryId(), root); |
| |
| // Get the configuration elements for this extension point |
| final IExtensionRegistry registry = Platform.getExtensionRegistry(); |
| final IConfigurationElement[] configElements = registry |
| .getConfigurationElementsFor(extensionPointID); |
| |
| // Make a first pass through the elements looking for categories |
| for (final IConfigurationElement element : configElements) { |
| // Is this a Category? |
| if (Constants.CATEGORY_ELEMENT.equals(element.getName())) { |
| // Yes |
| if(element.getAttribute(Constants.CATEGORY_NAME_ATTRIBUTE).startsWith("%")) |
| continue; // Skip untranslated categories |
| addCategory(element); |
| } |
| } // for each configuration element |
| |
| // Resolve the connections between parent and child categories |
| resolveCategories(); |
| |
| // Iterate through the elements. Processing the identifiables |
| for (final IConfigurationElement element : configElements) { |
| // Is this a Category? |
| if (Constants.CATEGORY_ELEMENT.equals(element.getName())) { |
| // Yes |
| continue; |
| } |
| // Is this a dublin core element? |
| else if (Constants.DUBLIN_CORE_ELEMENT |
| .equals(element.getName())) { |
| // Yes |
| // Was a category id specified in the element? |
| Category category = root; |
| final String categoryId = element |
| .getAttribute("category_id"); //$NON-NLS-1$ |
| if (categoryId != null) { |
| // Yes |
| category = categoryMap.get(categoryId); |
| // Did we find the category? |
| if (category == null) { |
| // No |
| Activator.logError(MessageFormat.format(Messages |
| .getString("IPView.No_Category"), //$NON-NLS-1$ |
| categoryId), null); |
| category = root; |
| } |
| |
| category = category == null ? root : category; |
| } |
| addIdentifiableDelegate(category, element); |
| } // if dublin core |
| // Is it an element with a "name" attribute? |
| else if (element.getAttribute("name") != null) { |
| // Yes |
| addIdentifiableDelegate(root, element); |
| } // if |
| else { |
| Activator.logError(MessageFormat.format(Messages |
| .getString("IPView.Unexpected_Element"), element |
| .getName(), extensionPointID), null); |
| } // else |
| } // for each configuration element |
| |
| } // IdentifiableViewModel |
| |
| /** |
| * Add an {@link IdentifiableDelegate} to the model. |
| * |
| * @param category |
| * the {@link Category} to add the delegate to |
| * |
| * @param element |
| * the {@link DublinCore} element that defines the delegate |
| */ |
| private void addIdentifiableDelegate(final Category category, |
| final IConfigurationElement element) { |
| final IdentifiableDelegate identifiableDelegate = new IdentifiableDelegate( |
| element); |
| category.addIdentifiableDelegate(identifiableDelegate); |
| } // addIdentifiableDelegate |
| |
| /** |
| * Add a {@link Category} to the model. |
| * |
| * @param element |
| * the category element that defines the category |
| */ |
| private Category addCategory(final IConfigurationElement element) { |
| final Category category = new Category(element); |
| // Does the category already exist? |
| Category retValue = categoryMap.get(category.getCategoryId()); |
| |
| if (retValue == null) { |
| // No |
| // It's new |
| retValue = category; |
| categoryMap.put(category.getCategoryId(), category); |
| } |
| |
| return retValue; |
| } // addCategory |
| |
| /** |
| * Hook up parent and child categories. |
| */ |
| private void resolveCategories() { |
| // Go through each of the categories hooking up parent with child |
| for (final Category category : categoryMap.values()) { |
| // Is this the root category? |
| if (category == root) { |
| // Yes |
| continue; |
| } |
| |
| // Does it's parent exist? |
| Category parentCategory = categoryMap.get(category |
| .getParentId()); |
| if (parentCategory == null) { |
| // No |
| Activator |
| .logInformation( |
| "When organizing categories, the specified parent category \"" //$NON-NLS-1$ |
| + category.getParentId() |
| + "\" for the category \"" //$NON-NLS-1$ |
| + category.getCategoryId() |
| + "\" could not be found. Using \"/\" instead.", //$NON-NLS-1$ |
| null); |
| parentCategory = root; |
| } // if parent exists |
| |
| category.setParent(parentCategory); |
| parentCategory.addChildCategory(category); |
| |
| } // for each category |
| } // resolveCategories |
| |
| /** |
| * @return the root |
| */ |
| protected final Category getRoot() { |
| return root; |
| } |
| |
| } // IdentifiableViewModel |
| |
| /** |
| * This class represents an element in the tree that is the model of the |
| * plugged in graphs. |
| */ |
| protected static class Category implements Comparable<Object> { |
| Category parent; |
| |
| String parentId; |
| |
| String categoryId; |
| |
| String categoryName; |
| |
| List<Category> childCategories; |
| |
| List<IdentifiableDelegate> childIdentifiables; |
| |
| protected Category(final String categoryName, final String categoryId, |
| final String parentId) { |
| this.categoryName = categoryName; |
| this.categoryId = categoryId; |
| this.parentId = parentId; |
| this.parent = null; |
| this.childCategories = new ArrayList<Category>(); |
| this.childIdentifiables = new ArrayList<IdentifiableDelegate>(); |
| } |
| |
| protected Category(final IConfigurationElement element) { |
| this(getNLSCatagoryName(element |
| .getAttribute(Constants.CATEGORY_NAME_ATTRIBUTE)), element |
| .getAttribute(Constants.CATEGORY_ID_ATTRIBUTE), element |
| .getAttribute(Constants.PARENT_ID_ATTRIBUTE)); |
| } |
| |
| /** |
| * @param category |
| * a child {@link Category} to add to this parent |
| */ |
| public void addChildCategory(final Category category) { |
| childCategories.add(category); |
| } |
| |
| /** |
| * @param identifiableDelegate |
| * the {@link IdentifiableDelegate} to add to the category |
| */ |
| public void addIdentifiableDelegate( |
| final IdentifiableDelegate identifiableDelegate) { |
| childIdentifiables.add(identifiableDelegate); |
| } |
| |
| /** |
| * @param attribute |
| * the value of {@link Constants#CATEGORY_NAME_ATTRIBUTE} |
| * @return the NLS'd version of the category name |
| */ |
| private static String getNLSCatagoryName(final String attribute) { |
| final String name = GeographicNames.getName(attribute); |
| return name.startsWith("!") ? attribute : name; |
| } // getNLSCatagoryName |
| |
| /** |
| * @return the categoryId of this {@link Category} |
| */ |
| protected final String getCategoryId() { |
| return categoryId; |
| } |
| |
| /** |
| * @return the parentId |
| */ |
| protected final String getParentId() { |
| return parentId; |
| } |
| |
| /** |
| * @return the parent |
| */ |
| protected final Category getParent() { |
| return parent; |
| } |
| |
| /** |
| * @param parent |
| * the parent to set |
| */ |
| protected final void setParent(final Category parent) { |
| this.parent = parent; |
| } |
| |
| /** |
| * @return the children of the {@link Category} |
| */ |
| public Object[] getChildren() { |
| final List<Object> kidList = new ArrayList<Object>(); |
| Collections.sort(childCategories); |
| Collections.sort(childIdentifiables); |
| kidList.addAll(childCategories); |
| kidList.addAll(childIdentifiables); |
| return kidList.toArray(); |
| } // getChildren |
| |
| /** |
| * @see java.lang.Object#toString() |
| */ |
| @Override |
| public String toString() { |
| final StringBuilder retValue = new StringBuilder(categoryName); |
| retValue.append(", "); //$NON-NLS-1$ |
| retValue.append(categoryId); |
| retValue.append(", "); //$NON-NLS-1$ |
| retValue.append(parentId); |
| return retValue.toString(); |
| } |
| |
| /** |
| * @see java.lang.Object#hashCode() |
| */ |
| @Override |
| public int hashCode() { |
| final int PRIME = 31; |
| int result = 1; |
| result = PRIME * result |
| + ((categoryId == null) ? 0 : categoryId.hashCode()); |
| return result; |
| } |
| |
| /** |
| * @see java.lang.Object#equals(java.lang.Object) |
| */ |
| @Override |
| public boolean equals(final Object obj) { |
| if (this == obj) { |
| return true; |
| } |
| if (obj == null) { |
| return false; |
| } |
| if (getClass() != obj.getClass()) { |
| return false; |
| } |
| final Category other = (Category) obj; |
| if (categoryId == null) { |
| if (other.categoryId != null) { |
| return false; |
| } |
| } else if (!categoryId.equals(other.categoryId)) { |
| return false; |
| } |
| return true; |
| } |
| |
| /** |
| * @param o |
| * @return the value of the compare |
| * @see java.lang.Comparable#compareTo(java.lang.Object) |
| */ |
| public int compareTo(final Object o) { |
| int retValue = 0; |
| if (o instanceof Category) { |
| // Yes |
| final Category category = (Category) o; |
| retValue = categoryName.compareTo(category.categoryName); |
| } // if Category |
| else if (o instanceof IdentifiableDelegate) { |
| // Yes |
| // In a tree listing that mixes categories and |
| // IdentifiableDelegates we want the categories to appear first, |
| // so we always return the same value. |
| retValue = 1; |
| } // if IdentifiableDelegate |
| return retValue; |
| } // compareTo |
| |
| } // Category |
| |
| /** |
| * This class provides content for the tree view of the {@link Identifiable} |
| * s that are available as parts of plug-ins. |
| */ |
| protected static class IdentifiablePluginViewTreeContentProvider implements |
| ITreeContentProvider { |
| |
| /** |
| * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object) |
| */ |
| public Object[] getChildren(final Object parentElement) { |
| Object[] retValue = null; |
| if (parentElement instanceof Category) { |
| final Category category = (Category) parentElement; |
| final List<Object> kidList = new ArrayList<Object>(); |
| Collections.sort(category.childCategories); |
| Collections.sort(category.childIdentifiables); |
| kidList.addAll(category.childCategories); |
| kidList.addAll(category.childIdentifiables); |
| retValue = kidList.toArray(); |
| } |
| return retValue; |
| } // getChildren |
| |
| /** |
| * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object) |
| */ |
| public Object getParent(final Object element) { |
| Object retValue = null; |
| if (element instanceof Category) { |
| retValue = ((Category) element).parent; |
| } else { |
| retValue = ((IdentifiableDelegate) element).getParent(); |
| } |
| return retValue; |
| } // getParent |
| |
| /** |
| * @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object) |
| */ |
| public boolean hasChildren(final Object element) { |
| boolean retValue = false; |
| if (element instanceof Category) { |
| final Category cagatory = (Category) element; |
| retValue = cagatory.childCategories.size() > 0 |
| || cagatory.childIdentifiables.size() > 0; |
| } |
| return retValue; |
| } // hasChildren |
| |
| /** |
| * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object) |
| */ |
| public Object[] getElements(final Object inputElement) { |
| final IdentifiableViewModel model = (IdentifiableViewModel) inputElement; |
| // return new Object[] { model.getRoot() }; |
| Arrays.sort(model.getRoot().getChildren()); |
| return model.getRoot().getChildren(); |
| } // getElements |
| |
| /** |
| * @see org.eclipse.jface.viewers.IContentProvider#dispose() |
| */ |
| public void dispose() { |
| // Nothing to dispose |
| } // dispose |
| |
| /** |
| * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, |
| * java.lang.Object, java.lang.Object) |
| */ |
| public void inputChanged( |
| @SuppressWarnings("unused") final Viewer viewer, |
| @SuppressWarnings("unused") final Object oldInput, |
| @SuppressWarnings("unused") final Object newInput) { |
| // Nothing to do right now |
| } // inputChanged |
| |
| } // IdentifiablePluginViewTreeContentProvider |
| |
| /** |
| * This class provides labels the describe the {@link Identifiable}s |
| * available as part of plug-ins. |
| */ |
| protected static abstract class IdentifiablePluginViewLabelContentProvider |
| implements ILabelProvider { |
| |
| private static Image categoryIcon = null; |
| |
| // If true then we've never tried to get the icon |
| static boolean categoryIconFirstTime = true; |
| |
| private final List<ILabelProviderListener> listeners; |
| |
| /** |
| * Constructor |
| */ |
| public IdentifiablePluginViewLabelContentProvider() { |
| listeners = new ArrayList<ILabelProviderListener>(); |
| } // IdentifiablePluginViewLabelContentProvider |
| |
| /** |
| * @see org.eclipse.jface.viewers.ILabelProvider#getImage(java.lang.Object) |
| */ |
| public Image getImage(final Object element) { |
| Image retValue = null; |
| if (element instanceof Category) { |
| retValue = getCategoryIcon(); |
| } |
| return retValue; |
| } // getImage |
| |
| /** |
| * @return the icon to be used to represent {@link Category}s, or |
| * <code>null</code> if it can't be loaded. |
| */ |
| protected Image getCategoryIcon() { |
| // Should we try to load the icon? |
| if (categoryIconFirstTime && categoryIcon == null) { |
| // Yes |
| categoryIconFirstTime = false; |
| categoryIcon = PlatformUI.getWorkbench().getSharedImages() |
| .getImage(ISharedImages.IMG_OBJ_FOLDER); |
| } // if we should load the icon |
| return categoryIcon; |
| } // getCategoryIcon |
| |
| /** |
| * @see org.eclipse.jface.viewers.ILabelProvider#getText(java.lang.Object) |
| */ |
| public String getText(final Object element) { |
| String retValue = ""; //$NON-NLS-1$ |
| if (element instanceof Category) { |
| final Category category = (Category) element; |
| retValue = category.categoryName; |
| } else if (element instanceof IdentifiableDelegate) { |
| final IdentifiableDelegate identifiableDelegate = (IdentifiableDelegate) element; |
| retValue = identifiableDelegate.toString(); |
| } |
| return retValue; |
| } // getText |
| |
| /** |
| * @see org.eclipse.jface.viewers.IBaseLabelProvider#addListener(org.eclipse.jface.viewers.ILabelProviderListener) |
| */ |
| public void addListener(final ILabelProviderListener listener) { |
| listeners.add(listener); |
| } // addListener |
| |
| /** |
| * @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose() |
| */ |
| public void dispose() { |
| // Nothing to do. The images are disposed of elsewhere, |
| } // dispose |
| |
| /** |
| * @see org.eclipse.jface.viewers.IBaseLabelProvider#isLabelProperty(java.lang.Object, |
| * java.lang.String) |
| */ |
| public boolean isLabelProperty( |
| @SuppressWarnings("unused") final Object element, |
| @SuppressWarnings("unused") final String property) { |
| return false; |
| } // isLabelProperty |
| |
| /** |
| * @see org.eclipse.jface.viewers.IBaseLabelProvider#removeListener(org.eclipse.jface.viewers.ILabelProviderListener) |
| */ |
| public void removeListener(final ILabelProviderListener listener) { |
| listeners.remove(listener); |
| } // removeListener |
| |
| } // IdentifiablePluginViewLabelContentProvider |
| |
| /** |
| * This class displays the {@link DublinCore} metadata of |
| * {@link Identifiable}s when the mouse hovers over it. |
| */ |
| private static class DublinCoreToolTipHandler { |
| // This is the number of pixels below the current mouse position at |
| // which to position the dublin core |
| protected static final int Y_OFFSET = 16; |
| |
| protected Shell dcTipShell; |
| |
| Label dcDescriptionText; |
| |
| Label dcCreatorText; |
| |
| Label dcValidText; |
| |
| Label dcSourceText; |
| |
| DublinCoreToolTipHandler(final Shell parent) { |
| final Display display = parent.getDisplay(); |
| |
| dcTipShell = new Shell(parent, SWT.ON_TOP | SWT.TOOL); |
| final GridLayout gridLayout = new GridLayout(); |
| gridLayout.numColumns = 1; |
| dcTipShell.setLayout(gridLayout); |
| |
| final Color backgroundColor = display |
| .getSystemColor(SWT.COLOR_INFO_BACKGROUND); |
| final Color foregroundColor = display |
| .getSystemColor(SWT.COLOR_INFO_FOREGROUND); |
| |
| dcTipShell.setBackground(backgroundColor); |
| |
| dcDescriptionText = createDCAttributeLabel(dcTipShell, |
| backgroundColor, foregroundColor); |
| |
| dcCreatorText = createDCAttributeLabel(dcTipShell, backgroundColor, |
| foregroundColor); |
| |
| dcValidText = createDCAttributeLabel(dcTipShell, backgroundColor, |
| foregroundColor); |
| dcSourceText = createDCAttributeLabel(dcTipShell, backgroundColor, |
| foregroundColor); |
| |
| dcTipShell.pack(); |
| } // DublinCoreToolTipHandler |
| |
| private Label createDCAttributeLabel(final Shell parent, |
| final Color backgroundColor, final Color foregroundColor) { |
| final Label retValue = new Label(parent, SWT.NONE); |
| retValue.setBackground(backgroundColor); |
| retValue.setForeground(foregroundColor); |
| retValue.setLayoutData(new GridData(GridData.FILL_HORIZONTAL |
| | GridData.VERTICAL_ALIGN_CENTER)); |
| return retValue; |
| } // createDCAttributeLabel |
| |
| /** |
| * Add the necessary listeners to the {@link Control} to catch the mouse |
| * events and pop the tool tip up. |
| * |
| * @param control |
| */ |
| public void addDCToolTipHelp(final Control control) { |
| // If the user clicks with the mouse we want to get rid of the |
| // dublin core |
| control.addMouseListener(new MouseAdapter() { |
| |
| /** |
| * @see org.eclipse.swt.events.MouseAdapter#mouseDown(org.eclipse.swt.events.MouseEvent) |
| */ |
| @Override |
| public void mouseDown( |
| @SuppressWarnings("unused") final MouseEvent e) { |
| // Is the dublin core visible? |
| if (dcTipShell.isVisible()) { |
| // Yes |
| // Not any more |
| dcTipShell.setVisible(false); |
| } // if visible |
| } // mouseDown |
| |
| }); |
| |
| // If the mouse hovers we want to pop up the dublin core, but if it |
| // exits we want to get right of it. |
| control.addMouseTrackListener(new MouseTrackAdapter() { |
| |
| /** |
| * @see org.eclipse.swt.events.MouseTrackAdapter#mouseHover(org.eclipse.swt.events.MouseEvent) |
| */ |
| @Override |
| public void mouseHover(final MouseEvent e) { |
| final Point pt = new Point(e.x, e.y); |
| // Is the event's Widget a Tree (it should be)? |
| if (e.widget instanceof Tree) { |
| // Yes |
| final Tree tree = (Tree) e.widget; |
| final TreeItem treeItem = tree.getItem(pt); |
| // Are we over anything? |
| if (treeItem != null) { |
| // Yes |
| final Object obj = treeItem.getData(); |
| |
| // Does it have DC meta data? |
| if (obj instanceof IdentifiableDelegate) { |
| // Yes |
| final IdentifiableDelegate id = (IdentifiableDelegate) obj; |
| final DublinCore dc = id.getDublinCore(); |
| |
| final String description = dc.getDescription(); |
| final String creator = dc.getCreator(); |
| final String valid = dc.getValid(); |
| final String source = dc.getSource(); |
| |
| // Is there a description? |
| if (description != null |
| && !description.equals("")) { |
| // Yes |
| dcDescriptionText.setText(description); |
| dcDescriptionText.setVisible(true); |
| } // if |
| else { |
| // No |
| dcDescriptionText.setVisible(false); |
| } |
| |
| // Is there a creator? |
| if (creator != null && !creator.equals("")) { |
| // Yes |
| dcCreatorText.setText(creator); |
| dcCreatorText.setVisible(true); |
| } // if |
| else { |
| // No |
| dcCreatorText.setVisible(false); |
| } |
| // Is there a valid range? |
| if (valid != null && !valid.equals("")) { |
| // Yes |
| dcValidText.setText(valid); |
| dcValidText.setVisible(true); |
| } // if |
| else { |
| // No |
| dcValidText.setVisible(false); |
| } |
| |
| // Is there a source? |
| if (source != null && !source.equals("")) { |
| // Yes |
| dcSourceText.setText(source); |
| dcSourceText.setVisible(true); |
| } // if |
| else { |
| // No |
| dcSourceText.setVisible(false); |
| } |
| |
| dcTipShell.pack(); |
| |
| // Now we need to figure out where to position |
| // the shell containing the dublin core tool tip |
| // given the size of the tool tip and the bounds |
| // of the Display. |
| dcTipShell.setBounds(computeHoverLocation( |
| dcTipShell, control.toDisplay(pt))); |
| |
| // Make the Dublin Core tool tip visible |
| dcTipShell.setVisible(true); |
| } // if IConfigurationElement |
| |
| else { |
| // No |
| dcTipShell.setVisible(false); |
| } |
| } // if display DC |
| else { |
| // No |
| dcTipShell.setVisible(false); |
| } |
| |
| } // if Tree |
| |
| } // mouseHover |
| |
| /** |
| * Figure out where to position the tool tip |
| * |
| * @param dcTipShell |
| * the {@link Shell} that contains the dublin core |
| * @param mousePosition |
| * the current position of the Mouse relative to the |
| * Display |
| */ |
| private Rectangle computeHoverLocation(final Shell dcTipShell, |
| final Point mousePosition) { |
| // Get the current bounds of the toolTip |
| final Rectangle retValue = dcTipShell.getBounds(); |
| |
| final Rectangle displayBounds = dcTipShell.getDisplay() |
| .getBounds(); |
| // The x position is either the current mouse position if |
| // the dublin core can be displayed entirely to the right of |
| // that, or a value to the left of that that allows it to be |
| // displayed, with 0 being the limit. |
| retValue.x = Math.max(Math.min(mousePosition.x, |
| displayBounds.width - retValue.width), 0); |
| |
| // The y position is Y_OFFSET pixels below the current mouse |
| // position, or if the entire dublin core won't fit in the |
| // window at that position, then the lowest position above |
| // that where it can, with 0 (the top of the Display) being |
| // the limit |
| retValue.y = Math.max(Math.min(mousePosition.y + Y_OFFSET, |
| displayBounds.height - retValue.height), 0); |
| |
| return retValue; |
| } // computeHoverLocation |
| |
| /** |
| * @see org.eclipse.swt.events.MouseTrackAdapter#mouseExit(org.eclipse.swt.events.MouseEvent) |
| */ |
| @Override |
| public void mouseExit( |
| @SuppressWarnings("unused") final MouseEvent e) { |
| // Is the dublin core visible? |
| if (dcTipShell.isVisible()) { |
| // Yes |
| // Not any more |
| dcTipShell.setVisible(false); |
| } // if visible |
| } // mouseExit |
| }); |
| } // addDCToolTipHelp |
| } // DublinCoreToolTipHandler |
| } // IdentifiablePluginView |