diff options
Diffstat (limited to 'target_explorer/plugins/org.eclipse.tcf.te.ui')
11 files changed, 744 insertions, 121 deletions
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.ui/icons/obj16/pending.gif b/target_explorer/plugins/org.eclipse.tcf.te.ui/icons/obj16/pending.gif Binary files differindex 0930dac23..592e88a65 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.ui/icons/obj16/pending.gif +++ b/target_explorer/plugins/org.eclipse.tcf.te.ui/icons/obj16/pending.gif diff --git a/target_explorer/plugins/org.eclipse.tcf.te.ui/schema/viewers.exsd b/target_explorer/plugins/org.eclipse.tcf.te.ui/schema/viewers.exsd index dca03934e..a5960af9a 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.ui/schema/viewers.exsd +++ b/target_explorer/plugins/org.eclipse.tcf.te.ui/schema/viewers.exsd @@ -23,6 +23,7 @@ <element ref="viewer"/> <element ref="columnContribution"/> <element ref="filterContribution"/> + <element ref="contentContribution"/> </choice> <attribute name="point" type="string" use="required"> <annotation> @@ -143,6 +144,29 @@ </complexType> </element> + <element name="contentContribution"> + <annotation> + <documentation> + The root of the content contributions. + </documentation> + </annotation> + <complexType> + <sequence> + <element ref="content" minOccurs="1" maxOccurs="unbounded"/> + </sequence> + <attribute name="viewerId" type="string" use="required"> + <annotation> + <documentation> + The id of the tree viewer which the content declared contribute to. + </documentation> + <appinfo> + <meta.attribute kind="identifier" basedOn="org.eclipse.tcf.te.ui.viewers/viewer/@id"/> + </appinfo> + </annotation> + </attribute> + </complexType> + </element> + <element name="column"> <annotation> <documentation> @@ -346,10 +370,42 @@ </complexType> </element> + <element name="content"> + <complexType> + <sequence minOccurs="0" maxOccurs="1"> + <element ref="activation" minOccurs="0" maxOccurs="1"/> + </sequence> + <attribute name="id" type="string" use="required"> + <annotation> + <documentation> + The id of the content contribution which must be unique in this viewer. + </documentation> + </annotation> + </attribute> + <attribute name="class" type="string" use="required"> + <annotation> + <documentation> + The content contribution that extends <samp>org.eclipse.tcf.te.ui.trees.AbstractContentContribution</samp>. + </documentation> + <appinfo> + <meta.attribute kind="java" basedOn="org.eclipse.tcf.te.ui.trees.AbstractContentContribution:"/> + </appinfo> + </annotation> + </attribute> + <attribute name="rank" type="string"> + <annotation> + <documentation> + The rank of the content contribution. Used to sort elements from different content contributions within the viewer. If not specified, the default rank 100 is associated. + </documentation> + </annotation> + </attribute> + </complexType> + </element> + <element name="activation"> <annotation> <documentation> - The <b>activation</b> expression defines a condition under which the column/filter should be activated. + The <b>activation</b> expression defines a condition under which the column, filter or content should be activated. </documentation> </annotation> <complexType> diff --git a/target_explorer/plugins/org.eclipse.tcf.te.ui/src/org/eclipse/tcf/te/ui/trees/AbstractContentContribution.java b/target_explorer/plugins/org.eclipse.tcf.te.ui/src/org/eclipse/tcf/te/ui/trees/AbstractContentContribution.java new file mode 100644 index 000000000..76075eff9 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.ui/src/org/eclipse/tcf/te/ui/trees/AbstractContentContribution.java @@ -0,0 +1,78 @@ +/******************************************************************************* + * Copyright (c) 2013 Wind River Systems, Inc. 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tcf.te.ui.trees; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.PlatformObject; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.swt.graphics.Image; + +/** + * Abstract tree control content contribution. + */ +public abstract class AbstractContentContribution extends PlatformObject { + // The reference to the tree content provider instance + private ITreeContentProvider contentProvider; + + /** + * Dispose the content contribution. + */ + public void dispose() { + if (contentProvider != null) { + contentProvider.dispose(); + contentProvider = null; + } + } + + /** + * Returns the tree content provider instance. If not yet created, + * this method will call {@link #doCreateTreeContentProvider()} to + * create the tree content provider instance. + * + * @return The tree content provider instance. + */ + public final ITreeContentProvider getContentProvider() { + if (contentProvider == null) { + contentProvider = doCreateTreeContentProvider(); + Assert.isNotNull(contentProvider); + } + return contentProvider; + } + + /** + * Creates the tree content provider instance. + * + * @return The tree content provider instance. Must not return <code>null</code>. + */ + protected abstract ITreeContentProvider doCreateTreeContentProvider(); + + /** + * Returns the column text for the column with the given id and the given element. + * + * @return The column text or <code>null</code>. + */ + protected abstract String getColumnText(String columnId, Object element); + + /** + * Returns the column image for the column with the given id and the given element. + * + * @return The column image or <code>null</code>. + */ + protected abstract Image getColumnImage(String columnId, Object element); + + /** + * Invoked from the tree control content and label provider to determine + * if a given element is handled by this content contribution. + * + * @param element The element or <code>null</code>. + * @return <code>True</code> if the element is handled by this content contribution, <code>false</code> otherwise. + */ + public abstract boolean isElementHandled(Object element); +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.ui/src/org/eclipse/tcf/te/ui/trees/AbstractTreeControl.java b/target_explorer/plugins/org.eclipse.tcf.te.ui/src/org/eclipse/tcf/te/ui/trees/AbstractTreeControl.java index 607332e43..d408488ab 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.ui/src/org/eclipse/tcf/te/ui/trees/AbstractTreeControl.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.ui/src/org/eclipse/tcf/te/ui/trees/AbstractTreeControl.java @@ -66,7 +66,9 @@ public abstract class AbstractTreeControl extends WorkbenchPartControl implement // The descriptors of the viewer filters configured for this viewer. private FilterDescriptor[] filterDescriptors; // The tree viewer columns of this viewer. - private ColumnDescriptor[] columns; + private ColumnDescriptor[] columnDescriptors; + // The content contributions configured for this viewer. + private ContentDescriptor[] contentDescriptors; // The state of the tree viewer used to restore and save the the tree viewer's state. private TreeViewerState viewerState; // The action to configure the filters. @@ -104,9 +106,19 @@ public abstract class AbstractTreeControl extends WorkbenchPartControl implement selectionChangedListener = null; } + // Dispose the descriptors + disposeDescriptors(); + + super.dispose(); + } + + /** + * Dispose all descriptors. + */ + protected void disposeDescriptors() { // Dispose the columns' resources. - if (columns != null) { - for (ColumnDescriptor column : columns) { + if (columnDescriptors != null) { + for (ColumnDescriptor column : columnDescriptors) { if (column.getImage() != null) { column.getImage().dispose(); } @@ -114,15 +126,22 @@ public abstract class AbstractTreeControl extends WorkbenchPartControl implement column.getLabelProvider().dispose(); } } + columnDescriptors = null; } - if(filterDescriptors != null) { - for(FilterDescriptor filterDescriptor : filterDescriptors) { - if(filterDescriptor.getImage() != null) { + if (filterDescriptors != null) { + for (FilterDescriptor filterDescriptor : filterDescriptors) { + if (filterDescriptor.getImage() != null) { filterDescriptor.getImage().dispose(); } } + filterDescriptors = null; + } + if (contentDescriptors != null) { + for (ContentDescriptor contentDescriptor : contentDescriptors) { + contentDescriptor.dispose(); + } + contentDescriptors = null; } - super.dispose(); } /* (non-Javadoc) @@ -162,14 +181,22 @@ public abstract class AbstractTreeControl extends WorkbenchPartControl implement viewer.setAutoExpandLevel(getAutoExpandLevel()); - viewer.setLabelProvider(doCreateTreeViewerLabelProvider(viewer)); + viewer.setLabelProvider(doCreateTreeViewerLabelProvider(this, viewer)); - final ITreeContentProvider contentProvider = doCreateTreeViewerContentProvider(viewer); + ITreeContentProvider mainContentProvider = doCreateTreeViewerContentProvider(viewer); + Assert.isNotNull(mainContentProvider); + final ITreeContentProvider contentProvider = new TreeViewerDelegatingContentProvider(this, mainContentProvider); InvocationHandler handler = new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (method.getName().equals("inputChanged")) { //$NON-NLS-1$ - onInputChanged(args[1], args[2]); + // Determine if the input really changed + Object oldInput = args[1]; + Object newInput = args[2]; + + if ((oldInput == null && newInput != null) || (oldInput != null && newInput == null) || !oldInput.equals(newInput)) { + onInputChanged(args[1], args[2]); + } } return method.invoke(contentProvider, args); } @@ -179,7 +206,7 @@ public abstract class AbstractTreeControl extends WorkbenchPartControl implement ITreeContentProvider proxy = (ITreeContentProvider) Proxy.newProxyInstance(classLoader, interfaces, handler); viewer.setContentProvider(proxy); - viewer.setComparator(doCreateTreeViewerComparator(viewer)); + viewer.setComparator(doCreateTreeViewerComparator(this, viewer)); viewer.getTree().setLayoutData(doCreateTreeViewerLayoutData(viewer)); @@ -203,11 +230,17 @@ public abstract class AbstractTreeControl extends WorkbenchPartControl implement */ protected void onInputChanged(Object oldInput, Object newInput) { if (newInput != null) { - columns = doCreateViewerColumns(newInput); + // Dispose the old descriptors first + disposeDescriptors(); + + columnDescriptors = doCreateViewerColumns(newInput); filterDescriptors = doCreateFilterDescriptors(newInput); + contentDescriptors = doCreateContentDescriptors(newInput); + if (isStatePersistent()) { updateViewerState(newInput); } + doCreateTreeColumns(viewer); viewer.getTree().setHeaderVisible(true); updateFilters(); @@ -241,11 +274,11 @@ public abstract class AbstractTreeControl extends WorkbenchPartControl implement inputId = getViewerId() + "." + inputId; //$NON-NLS-1$ viewerState = ViewerStateManager.getInstance().getViewerState(inputId); if (viewerState == null) { - viewerState = ViewerStateManager.createViewerState(columns, filterDescriptors); + viewerState = ViewerStateManager.createViewerState(columnDescriptors, filterDescriptors); ViewerStateManager.getInstance().putViewerState(inputId, viewerState); } else { - viewerState.updateColumnDescriptor(columns); + viewerState.updateColumnDescriptor(columnDescriptors); viewerState.updateFilterDescriptor(filterDescriptors); } } @@ -257,7 +290,7 @@ public abstract class AbstractTreeControl extends WorkbenchPartControl implement */ private void saveViewerState() { if (isStatePersistent() && viewerState != null) { - viewerState.updateColumnState(columns); + viewerState.updateColumnState(columnDescriptors); viewerState.updateFilterState(filterDescriptors); } } @@ -314,11 +347,11 @@ public abstract class AbstractTreeControl extends WorkbenchPartControl implement * @return The tree viewer columns. */ protected ColumnDescriptor[] doCreateViewerColumns(Object newInput) { - if(columns == null) { + if (columnDescriptors == null) { TreeViewerExtension viewerExtension = new TreeViewerExtension(getViewerId()); - columns = viewerExtension.parseColumns(newInput); + columnDescriptors = viewerExtension.parseColumns(newInput); } - return columns; + return columnDescriptors; } /** @@ -329,7 +362,7 @@ public abstract class AbstractTreeControl extends WorkbenchPartControl implement * @return The filter descriptors for the viewer. */ protected FilterDescriptor[] doCreateFilterDescriptors(Object newInput) { - if(filterDescriptors == null) { + if (filterDescriptors == null) { TreeViewerExtension viewerExtension = new TreeViewerExtension(getViewerId()); filterDescriptors = viewerExtension.parseFilters(newInput); } @@ -337,6 +370,31 @@ public abstract class AbstractTreeControl extends WorkbenchPartControl implement } /** + * Create the viewer content contributions from the viewers extension. Subclass may + * override it to provide its customized viewer content contributions. + * + * @param newInput the input when the content contributions are initialized. + * @return The content descriptors for the viewer. + */ + protected ContentDescriptor[] doCreateContentDescriptors(Object newInput) { + if (contentDescriptors == null) { + TreeViewerExtension viewerExtension = new TreeViewerExtension(getViewerId()); + contentDescriptors = viewerExtension.parseContents(newInput); + } + return contentDescriptors; + } + + /** + * Returns the current list of viewer content descriptors. The list of content + * descriptors may change if the viewers input element changes. + * + * @return The list of viewer content descriptors or <code>null</code>. + */ + public ContentDescriptor[] getContentDescriptors() { + return contentDescriptors; + } + + /** * Update the tree viewer's filters using the current filter descriptors. */ public void updateFilters() { @@ -360,9 +418,9 @@ public abstract class AbstractTreeControl extends WorkbenchPartControl implement * @param viewer The tree viewer. */ protected void doCreateTreeColumns(TreeViewer viewer) { - Assert.isTrue(columns != null && columns.length > 0); + Assert.isTrue(columnDescriptors != null && columnDescriptors.length > 0); List<ColumnDescriptor> visibleColumns = new ArrayList<ColumnDescriptor>(); - for (ColumnDescriptor column : columns) { + for (ColumnDescriptor column : columnDescriptors) { if (column.isVisible()) visibleColumns.add(column); } Collections.sort(visibleColumns, new Comparator<ColumnDescriptor>(){ @@ -459,12 +517,12 @@ public abstract class AbstractTreeControl extends WorkbenchPartControl implement * @return The column index. */ private int getColumnIndex(ColumnDescriptor column) { - Assert.isTrue(columns != null); + Assert.isTrue(columnDescriptors != null); int visibleCount = 0; - for(int i=0;i<columns.length;i++) { - if(columns[i] == column) + for(int i=0;i<columnDescriptors.length;i++) { + if(columnDescriptors[i] == column) break; - if(columns[i].isVisible()) { + if(columnDescriptors[i].isVisible()) { visibleCount++; } } @@ -505,11 +563,13 @@ public abstract class AbstractTreeControl extends WorkbenchPartControl implement /** * Creates the tree viewer label provider instance. * - * @param viewer The tree viewer. Must not be <code>null</code>. + * @param parentTreeControl The parent tree control instance. Must not be <code>null</code>. + * @param viewer The tree viewer. Must not be <code>null</code>., + * * @return The tree viewer label provider instance. */ - protected ILabelProvider doCreateTreeViewerLabelProvider(TreeViewer viewer) { - TreeViewerLabelProvider labelProvider = new TreeViewerLabelProvider(viewer); + protected ILabelProvider doCreateTreeViewerLabelProvider(AbstractTreeControl parentTreeControl, TreeViewer viewer) { + TreeViewerLabelProvider labelProvider = new TreeViewerLabelProvider(parentTreeControl, viewer); IWorkbench workbench = PlatformUI.getWorkbench(); IDecoratorManager manager = workbench.getDecoratorManager(); ILabelDecorator decorator = manager.getLabelDecorator(); @@ -527,11 +587,15 @@ public abstract class AbstractTreeControl extends WorkbenchPartControl implement /** * Creates the tree viewer comparator instance. * + * @param parentTreeControl The parent tree control. Must not be <code>null</code>. * @param viewer The tree viewer. Must not be <code>null</code>. - * @return The tree viewer comparator instance or <code>null</code> to turn of sorting. + * + * @return The tree viewer comparator instance or <code>null</code> to turn off sorting. */ - protected ViewerComparator doCreateTreeViewerComparator(TreeViewer viewer) { - return new TreeViewerComparator(); + protected ViewerComparator doCreateTreeViewerComparator(AbstractTreeControl parentTreeControl, TreeViewer viewer) { + Assert.isNotNull(parentTreeControl); + Assert.isNotNull(viewer); + return new TreeControlSorter(parentTreeControl); } /** @@ -602,7 +666,7 @@ public abstract class AbstractTreeControl extends WorkbenchPartControl implement * @return The current viewer columns. */ public ColumnDescriptor[] getViewerColumns() { - return columns != null ? Arrays.copyOf(columns, columns.length) : new ColumnDescriptor[0]; + return columnDescriptors != null ? Arrays.copyOf(columnDescriptors, columnDescriptors.length) : new ColumnDescriptor[0]; } /** diff --git a/target_explorer/plugins/org.eclipse.tcf.te.ui/src/org/eclipse/tcf/te/ui/trees/ContentDescriptor.java b/target_explorer/plugins/org.eclipse.tcf.te.ui/src/org/eclipse/tcf/te/ui/trees/ContentDescriptor.java new file mode 100644 index 000000000..79c6d166f --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.ui/src/org/eclipse/tcf/te/ui/trees/ContentDescriptor.java @@ -0,0 +1,114 @@ +/******************************************************************************* + * Copyright (c) 2013 Wind River Systems, Inc. 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tcf.te.ui.trees; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; + +/** + * A data structure to describe a content contribution. + * <p> + * A content contribution describes the content provider and the label provider. + */ +public class ContentDescriptor { + // The content contribution id, which is unique in a tree viewer. + private final String id; + // The content contribution configuration element. + private final IConfigurationElement element; + // The content contribution + private AbstractContentContribution contentContribution; + // The content contribution rank + private int rank = 100; + + /** + * Constructor + * + * @param id The content contribution id. Must not be <code>null</code>. + * @param element The content contribution configuration element. Must not be <code>null</code>. + */ + public ContentDescriptor(String id, IConfigurationElement element) { + super(); + + Assert.isNotNull(id); + this.id = id; + Assert.isNotNull(element); + this.element = element; + + // Determine the content contribution rank + String value = element.getAttribute("rank"); //$NON-NLS-1$ + if (value != null) { + try { + rank = Integer.decode(value).intValue(); + } catch (NumberFormatException e) { + /* ignored on purpose */ + } + } + } + + /** + * Get the content contribution id. + * + * @return The content contribution id. + */ + public String getId() { + return id; + } + + /** + * Returns the rank of the content contribution. + * + * @return The rank of the content contribution. + */ + public int getRank() { + return rank; + } + + /** + * Get the content contribution instance. + * + * @return The content contribution instance or <code>null</code>. + */ + public AbstractContentContribution getContentContribution() { + if (contentContribution == null) { + try { + contentContribution = (AbstractContentContribution) element.createExecutableExtension("class"); //$NON-NLS-1$ + } + catch (CoreException e) { /* ignored on purpose */ } + } + return contentContribution; + } + + /** + * Dispose the content descriptor. + */ + public void dispose() { + if (contentContribution != null) contentContribution.dispose(); + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + return id.hashCode() ^ element.hashCode(); + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (obj instanceof ContentDescriptor) { + return id.equals(((ContentDescriptor)obj).id) && element.equals(((ContentDescriptor)obj).element); + } + return super.equals(obj); + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.ui/src/org/eclipse/tcf/te/ui/trees/TreeControlSorter.java b/target_explorer/plugins/org.eclipse.tcf.te.ui/src/org/eclipse/tcf/te/ui/trees/TreeControlSorter.java new file mode 100644 index 000000000..ff46f6846 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.ui/src/org/eclipse/tcf/te/ui/trees/TreeControlSorter.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2013 Wind River Systems, Inc. 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tcf.te.ui.trees; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.jface.viewers.Viewer; + +/** + * The tree control sorter determines if the elements to sort are from the same + * content contribution. If not, elements from the main content provider comes + * first and the elements from different content contributions are sorted by rank. + */ +public class TreeControlSorter extends TreeViewerSorterCaseInsensitive { + // Reference to the parent tree control + private final AbstractTreeControl parentTreeControl; + + + /** + * Constructor + * + * @param parentTreeControl The parent tree control. Must not be <code>null</code>. + */ + public TreeControlSorter(AbstractTreeControl parentTreeControl) { + super(); + Assert.isNotNull(parentTreeControl); + this.parentTreeControl = parentTreeControl; + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.ui.trees.TreeViewerSorter#compare(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object) + */ + @Override + public int compare(Viewer viewer, Object e1, Object e2) { + ContentDescriptor c1 = null; + ContentDescriptor c2 = null; + + int inverter = doDetermineInverter(viewer); + + ContentDescriptor[] descriptors = parentTreeControl.getContentDescriptors(); + if (descriptors != null) { + for (ContentDescriptor descriptor : descriptors) { + if (descriptor.getContentContribution() == null) continue; + if (descriptor.getContentContribution().isElementHandled(e1)) { + c1 = descriptor; + break; + } + } + + for (ContentDescriptor descriptor : descriptors) { + if (descriptor.getContentContribution() == null) continue; + if (descriptor.getContentContribution().isElementHandled(e2)) { + c2 = descriptor; + break; + } + } + } + + if (c1 == null && c2 != null || c1 != null && c2 == null) { + // At least one of the elements is from the main content provider + return inverter * (c1 == null ? -1 : 1); + } + + if (c1 != null && c2 != null && !c1.equals(c2)) { + // Different contributions, the rank decides the order + return inverter * Integer.valueOf(c1.getRank()).compareTo(Integer.valueOf(c2.getRank())); + } + + return super.compare(viewer, e1, e2); + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.ui/src/org/eclipse/tcf/te/ui/trees/TreeViewerComparator.java b/target_explorer/plugins/org.eclipse.tcf.te.ui/src/org/eclipse/tcf/te/ui/trees/TreeViewerComparator.java deleted file mode 100644 index 14d592f75..000000000 --- a/target_explorer/plugins/org.eclipse.tcf.te.ui/src/org/eclipse/tcf/te/ui/trees/TreeViewerComparator.java +++ /dev/null @@ -1,84 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011, 2012 Wind River Systems, Inc. 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: - * Wind River Systems - initial API and implementation - *******************************************************************************/ -package org.eclipse.tcf.te.ui.trees; - -import java.util.Comparator; - -import org.eclipse.core.runtime.Assert; -import org.eclipse.jface.viewers.TreeViewer; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.jface.viewers.ViewerComparator; -import org.eclipse.swt.SWT; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Tree; -import org.eclipse.swt.widgets.TreeColumn; - -/** - * The tree control viewer comparator implementation. - */ -public class TreeViewerComparator extends ViewerComparator { - - /** - * Constructor. - */ - public TreeViewerComparator() { - } - - /* (non-Javadoc) - * @see org.eclipse.jface.viewers.ViewerComparator#compare(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object) - */ - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Override - public int compare(Viewer viewer, Object e1, Object e2) { - if (e1 instanceof Pending || e2 instanceof Pending) { - return (e1 instanceof Pending) ? (e2 instanceof Pending ? 0 : 1) : -1; - } - - Assert.isTrue(viewer instanceof TreeViewer); - - Tree tree = ((TreeViewer) viewer).getTree(); - int inverter = getSortDirection(tree) == SWT.DOWN ? -1 : 1; - TreeColumn treeColumn = tree.getSortColumn(); - if (treeColumn == null) { - // If the sort column is not set, then use the first column. - treeColumn = tree.getColumn(0); - } - if (treeColumn != null && !treeColumn.isDisposed()) { - ColumnDescriptor column = (ColumnDescriptor) treeColumn.getData(); - if (column != null) { - Comparator comparator = column.getComparator(); - if (comparator != null) { - return inverter * comparator.compare(e1, e2); - } - } - } - return inverter * super.compare(viewer, e1, e2); - } - - /** - * Get the sorting direction in a UI thread safely. - * - * @param tree The tree to get the direction from. - * @return the sorting direction of the tree. - */ - int getSortDirection(final Tree tree) { - if (Display.getCurrent() != null) { - return tree.getSortDirection(); - } - final int[] result = new int[1]; - tree.getDisplay().syncExec(new Runnable() { - @Override - public void run() { - result[0] = getSortDirection(tree); - } - }); - return result[0]; - } -} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.ui/src/org/eclipse/tcf/te/ui/trees/TreeViewerDelegatingContentProvider.java b/target_explorer/plugins/org.eclipse.tcf.te.ui/src/org/eclipse/tcf/te/ui/trees/TreeViewerDelegatingContentProvider.java new file mode 100644 index 000000000..261fd2721 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.ui/src/org/eclipse/tcf/te/ui/trees/TreeViewerDelegatingContentProvider.java @@ -0,0 +1,196 @@ +/******************************************************************************* + * Copyright (c) 2013 Wind River Systems, Inc. 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tcf.te.ui.trees; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.Viewer; + +/** + * Tree viewer tree control delegating label provider. + */ +public class TreeViewerDelegatingContentProvider implements ITreeContentProvider { + // The parent tree control instance + private final AbstractTreeControl parentTreeControl; + // The main content provider instance + private final ITreeContentProvider contentProvider; + + /** + * Constructor + * + * @param parentTreeControl The parent tree control instance. Must not be <code>null</code>. + * @param contentProvider The main content provider instance. Must not be <code>null</code>. + */ + public TreeViewerDelegatingContentProvider(AbstractTreeControl parentTreeControl, ITreeContentProvider contentProvider) { + super(); + + Assert.isNotNull(parentTreeControl); + this.parentTreeControl = parentTreeControl; + Assert.isNotNull(contentProvider); + this.contentProvider = contentProvider; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ITreeContentProvider#getElements(java.lang.Object) + */ + @Override + public Object[] getElements(Object inputElement) { + boolean nonNullElements = false; + List<Object> elements = new ArrayList<Object>(); + + // Pass on to the main content provider + Object[] candidates = contentProvider.getElements(inputElement); + if (candidates != null) { + nonNullElements = true; + elements.addAll(Arrays.asList(candidates)); + } + + // Pass on to the delegate content providers + ContentDescriptor[] descriptors = parentTreeControl.getContentDescriptors(); + if (descriptors != null) { + for (ContentDescriptor descriptor : descriptors) { + AbstractContentContribution contribution = descriptor.getContentContribution(); + if (contribution == null) continue; + ITreeContentProvider delegate = contribution.getContentProvider(); + if (delegate == null) continue; + candidates = delegate.getElements(inputElement); + if (candidates != null) { + nonNullElements = true; + elements.addAll(Arrays.asList(candidates)); + } + } + } + + return nonNullElements ? elements.toArray() : null; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object) + */ + @Override + public Object[] getChildren(Object parentElement) { + boolean nonNullChildren = false; + List<Object> children = new ArrayList<Object>(); + + // Pass on to the main content provider + Object[] candidates = contentProvider.getChildren(parentElement); + if (candidates != null) { + nonNullChildren = true; + children.addAll(Arrays.asList(candidates)); + } + + // Pass on to the delegate content providers + ContentDescriptor[] descriptors = parentTreeControl.getContentDescriptors(); + if (descriptors != null) { + for (ContentDescriptor descriptor : descriptors) { + AbstractContentContribution contribution = descriptor.getContentContribution(); + if (contribution == null) continue; + ITreeContentProvider delegate = contribution.getContentProvider(); + if (delegate == null) continue; + candidates = delegate.getChildren(parentElement); + if (candidates != null) { + nonNullChildren = true; + children.addAll(Arrays.asList(candidates)); + } + } + } + + return nonNullChildren ? children.toArray() : null; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object) + */ + @Override + public Object getParent(Object element) { + // Pass on to the main content provider + Object parent = contentProvider.getParent(element); + if (parent == null) { + // Pass on to the delegate content providers + ContentDescriptor[] descriptors = parentTreeControl.getContentDescriptors(); + if (descriptors != null) { + for (ContentDescriptor descriptor : descriptors) { + AbstractContentContribution contribution = descriptor.getContentContribution(); + if (contribution == null) continue; + if (contribution.isElementHandled(element)) { + ITreeContentProvider delegate = contribution.getContentProvider(); + if (delegate != null) { + parent = delegate.getParent(element); + break; + } + } + } + } + } + return parent; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object) + */ + @Override + public boolean hasChildren(Object element) { + // Pass on to the main content provider + boolean hasChildren = contentProvider.hasChildren(element); + if (!hasChildren) { + // Pass on to the delegate content providers + ContentDescriptor[] descriptors = parentTreeControl.getContentDescriptors(); + if (descriptors != null) { + for (ContentDescriptor descriptor : descriptors) { + AbstractContentContribution contribution = descriptor.getContentContribution(); + if (contribution == null) continue; + if (contribution.isElementHandled(element)) { + ITreeContentProvider delegate = contribution.getContentProvider(); + if (delegate != null) { + hasChildren = delegate.hasChildren(element); + break; + } + } + } + } + } + return hasChildren; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.IContentProvider#dispose() + */ + @Override + public void dispose() { + // Pass on to the main content provider + contentProvider.dispose(); + // The delegate content providers are disposed via the content descriptors + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object) + */ + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + // Pass on to the main content provider + contentProvider.inputChanged(viewer, oldInput, newInput); + + // Pass on to the delegate content providers + ContentDescriptor[] descriptors = parentTreeControl.getContentDescriptors(); + if (descriptors != null) { + for (ContentDescriptor descriptor : descriptors) { + AbstractContentContribution contribution = descriptor.getContentContribution(); + if (contribution == null) continue; + ITreeContentProvider delegate = contribution.getContentProvider(); + if (delegate == null) continue; + delegate.inputChanged(viewer, oldInput, newInput); + } + } + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.ui/src/org/eclipse/tcf/te/ui/trees/TreeViewerExtension.java b/target_explorer/plugins/org.eclipse.tcf.te.ui/src/org/eclipse/tcf/te/ui/trees/TreeViewerExtension.java index 71d80c18c..148845c34 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.ui/src/org/eclipse/tcf/te/ui/trees/TreeViewerExtension.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.ui/src/org/eclipse/tcf/te/ui/trees/TreeViewerExtension.java @@ -51,7 +51,8 @@ import org.osgi.framework.Bundle; /** * The implementation of the tree viewer extension which is used to parse - * the columns and the filters declared in this extension for a specified tree viewer. + * the column, filter and content contributions declared in this extension + * for a specified tree viewer. */ public class TreeViewerExtension { // The extension point id constant. @@ -176,7 +177,7 @@ public class TreeViewerExtension { * filter descriptors. * * @param input the new input - * @return The column descriptors from this extension point. + * @return The filter descriptors from this extension point. */ public FilterDescriptor[] parseFilters(Object input) { Assert.isNotNull(viewerId); @@ -295,6 +296,56 @@ public class TreeViewerExtension { } /** + * Parse the content contribution declarations of this extension point and return the + * content descriptors. + * + * @param input the new input + * @return The content descriptors from this extension point. + */ + public ContentDescriptor[] parseContents(Object input) { + Assert.isNotNull(viewerId); + List<ContentDescriptor> descriptors = Collections.synchronizedList(new ArrayList<ContentDescriptor>()); + IExtensionRegistry registry = Platform.getExtensionRegistry(); + IExtensionPoint extensionPoint = registry.getExtensionPoint(EXTENSION_POINT_ID); + IConfigurationElement[] configurations = extensionPoint.getConfigurationElements(); + for (IConfigurationElement configuration : configurations) { + String name = configuration.getName(); + if ("contentContribution".equals(name)) { //$NON-NLS-1$ + String aViewerId = configuration.getAttribute("viewerId"); //$NON-NLS-1$ + if (viewerId.equals(aViewerId)) { + IConfigurationElement[] children = configuration.getChildren("content"); //$NON-NLS-1$ + if (children != null && children.length > 0) { + for (IConfigurationElement child : children) { + createContentDescriptor(input, descriptors, child); + } + } + } + } + } + return descriptors.toArray(new ContentDescriptor[descriptors.size()]); + } + + /** + * Create an content descriptor from the specified configuration element and + * add it to the content descriptor list. + * + * @param input the input of the viewer to initialize the descriptors. + * @param descriptors The content descriptor list to add the created descriptor to. + * @param configuration The extension configuration element to create the descriptor from. + */ + private void createContentDescriptor(Object input, List<ContentDescriptor> descriptors, final IConfigurationElement configuration) { + Assert.isNotNull(descriptors); + Assert.isNotNull(configuration); + + if (isElementActivated(input, configuration)) { + String id = configuration.getAttribute("id"); //$NON-NLS-1$ + Assert.isNotNull(id); + final ContentDescriptor descriptor = new ContentDescriptor(id, configuration); + descriptors.add(descriptor); + } + } + + /** * If the specified configuration element is activated under the current input. * * @param input The input object. diff --git a/target_explorer/plugins/org.eclipse.tcf.te.ui/src/org/eclipse/tcf/te/ui/trees/TreeViewerLabelProvider.java b/target_explorer/plugins/org.eclipse.tcf.te.ui/src/org/eclipse/tcf/te/ui/trees/TreeViewerLabelProvider.java index f559f7d03..4db08f511 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.ui/src/org/eclipse/tcf/te/ui/trees/TreeViewerLabelProvider.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.ui/src/org/eclipse/tcf/te/ui/trees/TreeViewerLabelProvider.java @@ -9,6 +9,7 @@ *******************************************************************************/ package org.eclipse.tcf.te.ui.trees; +import org.eclipse.core.runtime.Assert; import org.eclipse.jface.viewers.IColorProvider; import org.eclipse.jface.viewers.IFontProvider; import org.eclipse.jface.viewers.ILabelProvider; @@ -23,19 +24,25 @@ import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeColumn; /** - * File system tree control label provider implementation. + * Tree viewer tree control label provider implementation. */ public class TreeViewerLabelProvider extends PendingAwareLabelProvider implements ITableLabelProvider, ITableColorProvider, ITableFontProvider { // Reference to the parent tree viewer private TreeViewer viewer; + // The parent tree control instance + private final AbstractTreeControl parentTreeControl; /** * Constructor. * + * @param parentTreeControl The parent tree control instance. Must not be <code>null</code>. * @param viewer The tree viewer or <code>null</code>. */ - public TreeViewerLabelProvider(TreeViewer viewer) { + public TreeViewerLabelProvider(AbstractTreeControl parentTreeControl, TreeViewer viewer) { super(); + + Assert.isNotNull(parentTreeControl); + this.parentTreeControl = parentTreeControl; this.viewer = viewer; } @@ -80,6 +87,18 @@ public class TreeViewerLabelProvider extends PendingAwareLabelProvider implement } ColumnDescriptor column = getColumn(columnIndex); if (column != null) { + // Determine if the element is handled by a content contribution + ContentDescriptor[] descriptors = parentTreeControl.getContentDescriptors(); + if (descriptors != null) { + for (ContentDescriptor descriptor : descriptors) { + AbstractContentContribution contribution = descriptor.getContentContribution(); + if (contribution == null) continue; + if (contribution.isElementHandled(element)) { + return contribution.getColumnImage(column.getId(), element); + } + } + } + // Pass on to the main column label provider ILabelProvider labelProvider = column.getLabelProvider(); if (labelProvider != null) { return labelProvider.getImage(element); @@ -98,6 +117,18 @@ public class TreeViewerLabelProvider extends PendingAwareLabelProvider implement } ColumnDescriptor column = getColumn(columnIndex); if (column != null) { + // Determine if the element is handled by a content contribution + ContentDescriptor[] descriptors = parentTreeControl.getContentDescriptors(); + if (descriptors != null) { + for (ContentDescriptor descriptor : descriptors) { + AbstractContentContribution contribution = descriptor.getContentContribution(); + if (contribution == null) continue; + if (contribution.isElementHandled(element)) { + return contribution.getColumnText(column.getId(), element); + } + } + } + // Pass on to the main column label provider ILabelProvider labelProvider = column.getLabelProvider(); if (labelProvider != null) { return labelProvider.getText(element); @@ -114,6 +145,18 @@ public class TreeViewerLabelProvider extends PendingAwareLabelProvider implement if (!(element instanceof Pending)) { ColumnDescriptor column = getColumn(columnIndex); if (column != null) { + // Determine if the element is handled by a content contribution + ContentDescriptor[] descriptors = parentTreeControl.getContentDescriptors(); + if (descriptors != null) { + for (ContentDescriptor descriptor : descriptors) { + AbstractContentContribution contribution = descriptor.getContentContribution(); + if (contribution == null) continue; + if (contribution.isElementHandled(element) && contribution instanceof IFontProvider) { + return ((IFontProvider)contribution).getFont(element); + } + } + } + // Pass on to the main column label provider ILabelProvider labelProvider = column.getLabelProvider(); if (labelProvider instanceof IFontProvider) { return ((IFontProvider)labelProvider).getFont(element); @@ -131,6 +174,18 @@ public class TreeViewerLabelProvider extends PendingAwareLabelProvider implement if (!(element instanceof Pending)) { ColumnDescriptor column = getColumn(columnIndex); if (column != null) { + // Determine if the element is handled by a content contribution + ContentDescriptor[] descriptors = parentTreeControl.getContentDescriptors(); + if (descriptors != null) { + for (ContentDescriptor descriptor : descriptors) { + AbstractContentContribution contribution = descriptor.getContentContribution(); + if (contribution == null) continue; + if (contribution.isElementHandled(element) && contribution instanceof IColorProvider) { + return ((IColorProvider)contribution).getForeground(element); + } + } + } + // Pass on to the main column label provider ILabelProvider labelProvider = column.getLabelProvider(); if (labelProvider instanceof IColorProvider) { return ((IColorProvider)labelProvider).getForeground(element); @@ -148,6 +203,18 @@ public class TreeViewerLabelProvider extends PendingAwareLabelProvider implement if (!(element instanceof Pending)) { ColumnDescriptor column = getColumn(columnIndex); if (column != null) { + // Determine if the element is handled by a content contribution + ContentDescriptor[] descriptors = parentTreeControl.getContentDescriptors(); + if (descriptors != null) { + for (ContentDescriptor descriptor : descriptors) { + AbstractContentContribution contribution = descriptor.getContentContribution(); + if (contribution == null) continue; + if (contribution.isElementHandled(element) && contribution instanceof IColorProvider) { + return ((IColorProvider)contribution).getBackground(element); + } + } + } + // Pass on to the main column label provider ILabelProvider labelProvider = column.getLabelProvider(); if (labelProvider instanceof IColorProvider) { return ((IColorProvider)labelProvider).getBackground(element); diff --git a/target_explorer/plugins/org.eclipse.tcf.te.ui/src/org/eclipse/tcf/te/ui/trees/TreeViewerSorter.java b/target_explorer/plugins/org.eclipse.tcf.te.ui/src/org/eclipse/tcf/te/ui/trees/TreeViewerSorter.java index 944a29333..770d12f9d 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.ui/src/org/eclipse/tcf/te/ui/trees/TreeViewerSorter.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.ui/src/org/eclipse/tcf/te/ui/trees/TreeViewerSorter.java @@ -19,6 +19,7 @@ import org.eclipse.jface.viewers.DecoratingStyledCellLabelProvider; import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider; import org.eclipse.jface.viewers.IBaseLabelProvider; import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.StyledString; import org.eclipse.jface.viewers.TreePathViewerSorter; import org.eclipse.jface.viewers.TreeViewer; @@ -71,6 +72,9 @@ public class TreeViewerSorter extends TreePathViewerSorter { protected String doGetText(Viewer viewer, Object node, int index) { if (node != null) { IBaseLabelProvider labelProvider = doGetLabelProvider(viewer); + if (labelProvider instanceof ITableLabelProvider) { + return ((ITableLabelProvider)labelProvider).getColumnText(node, index); + } if (labelProvider instanceof ILabelProvider) { return ((ILabelProvider)labelProvider).getText(node); } |