Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te')
-rw-r--r--target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/AbstractViewerComparator.java105
-rw-r--r--target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/WorkbenchPartControl.java127
-rw-r--r--target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/activator/UIPlugin.java64
-rw-r--r--target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/dialogs/CustomTrayDialog.java180
-rw-r--r--target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/forms/CustomFormToolkit.java393
-rw-r--r--target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/images/AbstractImageDescriptor.java176
-rw-r--r--target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/images/AbstractImageRegistry.java218
-rw-r--r--target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/interfaces/IUIConstants.java25
-rw-r--r--target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/nls/Messages.java42
-rw-r--r--target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/nls/Messages.properties15
-rw-r--r--target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/nodes/PendingOperation.java45
-rw-r--r--target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/tables/TableNode.java39
-rw-r--r--target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/tables/TableViewerComparator.java135
-rw-r--r--target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/tables/properties/NodePropertiesTableControl.java417
-rw-r--r--target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/trees/AbstractTreeControl.java307
-rw-r--r--target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/trees/TreeViewerComparator.java178
16 files changed, 2466 insertions, 0 deletions
diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/AbstractViewerComparator.java b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/AbstractViewerComparator.java
new file mode 100644
index 000000000..4d4e1e9fe
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/AbstractViewerComparator.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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:
+ * Uwe Stieber (Wind River) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tm.te.ui;
+
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerComparator;
+
+/**
+ * Target Explorer: Common viewer comparator implementation.
+ */
+public abstract class AbstractViewerComparator extends ViewerComparator {
+ // Reference to the viewer
+ private final Viewer fViewer;
+
+ /**
+ * Constructor.
+ *
+ * @param viewer The parent viewer. Must be not <code>null</code>.
+ */
+ public AbstractViewerComparator(Viewer viewer) {
+ assert viewer != null;
+ fViewer = viewer;
+ }
+
+ /**
+ * Returns the parent viewer instance.
+ *
+ * @return The parent viewer instance.
+ */
+ protected final Viewer getParentViewer() {
+ return fViewer;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.ViewerComparator#compare(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
+ */
+ @Override
+ public int compare(Viewer viewer, Object e1, Object e2) {
+ if (viewer != null && viewer.getControl() != null && !viewer.getControl().isDisposed()) {
+ return doCompare(e1, e2, doGetSortColumnLabel(viewer), doGetSortColumnIndex(viewer) , doDetermineInverter(viewer));
+ }
+ return super.compare(viewer, e1, e2);
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
+ */
+ public int compare(Object o1, Object o2) {
+ return doCompare(o1, o2, null, -1, doDetermineInverter(getParentViewer()));
+ }
+
+ /**
+ * Compare the given nodes by the given sort column and inverter.
+ *
+ * @param node1 The first node or <code>null</code>.
+ * @param node2 The second node or <code>null</code>.
+ * @param sortColumn The sort column text or <code>null</code>.
+ * @param index The sort column index or <code>-1</code>.
+ * @param inverter The inverter.
+ *
+ * @return The compare result.
+ */
+ protected abstract int doCompare(Object node1, Object node2, String sortColumn, int index, int inverter);
+
+ /**
+ * Returns the text to compare for the given node and column index.
+ *
+ * @param node The node or <code>null</code>.
+ * @param index The column index or <code>-1</code>.
+ *
+ * @return The text for the given node and column index or <code>null</code>.
+ */
+ protected abstract String doGetText(Object node, int index);
+
+ /**
+ * Determine if or if not the sort direction needs to be inverted.
+ *
+ * @param viewer The viewer or <code>null</code>.
+ * @return <code>1</code> for original sort order, or <code>-1</code> for inverted sort order.
+ */
+ protected abstract int doDetermineInverter(Viewer viewer);
+
+ /**
+ * Return the label of the sort column of the given viewer.
+ *
+ * @param viewer The viewer or <code>null</code>.
+ * @return The label of the sort column or an empty string.
+ */
+ protected abstract String doGetSortColumnLabel(Viewer viewer);
+
+ /**
+ * Return the index of the sort column of the given viewer.
+ *
+ * @param viewer The viewer or <code>null</code>.
+ * @return The index of the sort column or <code>-1</code>.
+ */
+ protected abstract int doGetSortColumnIndex(Viewer viewer);
+}
diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/WorkbenchPartControl.java b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/WorkbenchPartControl.java
new file mode 100644
index 000000000..6dab3be48
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/WorkbenchPartControl.java
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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:
+ * Uwe Stieber (Wind River) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tm.te.ui;
+
+import org.eclipse.core.runtime.PlatformObject;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.tm.te.ui.activator.UIPlugin;
+import org.eclipse.tm.te.ui.forms.CustomFormToolkit;
+import org.eclipse.ui.ISelectionService;
+import org.eclipse.ui.IWorkbenchPart;
+
+
+/**
+ * Target Explorer: Common workbench part control implementation.
+ */
+public class WorkbenchPartControl extends PlatformObject {
+ /**
+ * Reference to the parent workbench part the control might be embedded in.
+ */
+ private final IWorkbenchPart fParentPart;
+
+ /**
+ * Reference to the form toolkit instance provided via {@link #setupFormPanel(Composite, CustomFormToolkit)}.
+ */
+ private CustomFormToolkit fFormToolkit = null;
+
+ /**
+ * Reference to the parent control.
+ */
+ private Composite fParentControl;
+
+ /**
+ * Constructor.
+ */
+ public WorkbenchPartControl() {
+ this(null);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param parentPart The parent workbench part this control is embedded in or <code>null</code>.
+ */
+ public WorkbenchPartControl(IWorkbenchPart parentPart) {
+ super();
+ fParentPart = parentPart;
+ }
+
+ /**
+ * Returns the parent workbench part the control might be embedded in.
+ *
+ * @return The parent workbench part or <code>null</code>.
+ */
+ public final IWorkbenchPart getParentPart() {
+ return fParentPart;
+ }
+
+ /**
+ * Returns if the <code>setupPanel(...)</code> method has been called at least once with
+ * a non-null parent control.
+ *
+ * @return <code>true</code> if the associated parent control is not <code>null</code>, <code>false</code> otherwise.
+ */
+ public final boolean isControlCreated() {
+ return (fParentControl != null);
+ }
+
+ /**
+ * Returns the parent control of the control.
+ *
+ * @return The parent control or <code>null</code>.
+ */
+ public final Composite getParentControl() {
+ return fParentControl;
+ }
+
+ /**
+ * Cleanup all resources the control might have been created.
+ */
+ public void dispose() {
+ fParentControl = null;
+ }
+
+ /**
+ * Creates the controls UI elements.
+ *
+ * @param parent The parent composite. Must not be <code>null</code>.
+ * @param toolkit The {@link CustomFormToolkit} instance. Must be not <code>null</code>.
+ */
+ public void setupFormPanel(Composite parent, CustomFormToolkit toolkit) {
+ assert parent != null && toolkit != null;
+ fParentControl = parent;
+ fFormToolkit = toolkit;
+ }
+
+ /**
+ * Returns the associated form toolkit instance.
+ *
+ * @return The form toolkit instance or <code>null</code> if not initialized yet.
+ */
+ protected final CustomFormToolkit getFormToolkit() {
+ return fFormToolkit;
+ }
+
+ /**
+ * Returns the selection service of the workbench.
+ *
+ * @return The selection service or <code>null</code>.
+ */
+ protected final ISelectionService getSelectionService() {
+ ISelectionService selectionService = null;
+ // Check if plugin, workbench and active workbench window are still valid
+ if (UIPlugin.getDefault() != null && UIPlugin.getDefault().getWorkbench() != null
+ && UIPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow() != null) {
+ selectionService = UIPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getSelectionService();
+ }
+ return selectionService;
+ }
+
+}
diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/activator/UIPlugin.java b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/activator/UIPlugin.java
new file mode 100644
index 000000000..d8d6e1e1b
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/activator/UIPlugin.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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:
+ * Uwe Stieber (Wind River) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tm.te.ui.activator;
+
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class UIPlugin extends AbstractUIPlugin {
+ // The shared instance
+ private static UIPlugin plugin;
+
+ /**
+ * The constructor
+ */
+ public UIPlugin() {
+ }
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static UIPlugin getDefault() {
+ return plugin;
+ }
+
+ /**
+ * Convenience method which returns the unique identifier of this plugin.
+ */
+ public static String getUniqueIdentifier() {
+ if (getDefault() != null && getDefault().getBundle() != null) {
+ return getDefault().getBundle().getSymbolicName();
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ plugin = this;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void stop(BundleContext context) throws Exception {
+ plugin = null;
+ super.stop(context);
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/dialogs/CustomTrayDialog.java b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/dialogs/CustomTrayDialog.java
new file mode 100644
index 000000000..702bab109
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/dialogs/CustomTrayDialog.java
@@ -0,0 +1,180 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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:
+ * Uwe Stieber (Wind River) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tm.te.ui.dialogs;
+
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.dialogs.TrayDialog;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Layout;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.tm.te.ui.activator.UIPlugin;
+import org.eclipse.ui.PlatformUI;
+
+
+/**
+ * Target Explorer: Custom tray dialog implementation.
+ */
+public class CustomTrayDialog extends TrayDialog {
+ private String fContextHelpId = null;
+
+ // the dialog storage
+ private IDialogSettings fDialogSettings;
+
+ /**
+ * Constructor.
+ *
+ * @param shell The parent shell or <code>null</code>.
+ */
+ public CustomTrayDialog(Shell shell) {
+ this(shell, null);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param shell The parent shell or <code>null</code>.
+ * @param contextHelpId The dialog context help id or <code>null</code>.
+ */
+ public CustomTrayDialog(Shell shell, String contextHelpId) {
+ super(shell);
+ initializeDialogSettings();
+ setContextHelpId(contextHelpId);
+ }
+
+ /**
+ * Configure the dialogs context help id.
+ *
+ * @param contextHelpId The context help id or <code>null</code>.
+ */
+ protected void setContextHelpId(String contextHelpId) {
+ fContextHelpId = contextHelpId;
+ setHelpAvailable(fContextHelpId != null);
+ }
+
+ /**
+ * Initialize the dialog settings storage.
+ */
+ protected void initializeDialogSettings() {
+ IDialogSettings settings = doGetDialogSettingsToInitialize();
+ assert settings != null;
+ IDialogSettings section = settings.getSection(getDialogSettingsSectionName());
+ if (section == null) {
+ section = settings.addNewSection(getDialogSettingsSectionName());
+ }
+ setDialogSettings(section);
+ }
+
+ /**
+ * Returns the dialog settings container to use and to initialize. This
+ * method is called from <code>initializeDialogSettings</code> and allows
+ * overriding the dialog settings container without changing the dialog
+ * settings structure.
+ *
+ * @return The dialog settings container to use. Must be not <code>null</code>.
+ */
+ protected IDialogSettings doGetDialogSettingsToInitialize() {
+ return UIPlugin.getDefault().getDialogSettings();
+ }
+
+ /**
+ * Returns the section name to use for separating different persistent
+ * dialog settings from different dialogs.
+ *
+ * @return The section name used to store the persistent dialog settings within the plugins persistent
+ * dialog settings store.
+ */
+ public String getDialogSettingsSectionName() {
+ return "CustomTrayDialog"; //$NON-NLS-1$
+ }
+
+ /**
+ * Returns the associated dialog settings storage.
+ *
+ * @return The dialog settings storage.
+ */
+ public IDialogSettings getDialogSettings() {
+ // The dialog settings may not been initialized here. Initialize first in this case
+ // to be sure that we do have always the correct dialog settings.
+ if (fDialogSettings == null) {
+ initializeDialogSettings();
+ }
+ return fDialogSettings;
+ }
+
+ /**
+ * Sets the associated dialog settings storage.
+ *
+ * @return The dialog settings storage.
+ */
+ public void setDialogSettings(IDialogSettings dialogSettings) {
+ fDialogSettings = dialogSettings;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite)
+ */
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ if (fContextHelpId != null) {
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, fContextHelpId);
+ }
+
+ // Let the super implementation create the dialog area control
+ Control control = super.createDialogArea(parent);
+ // But fix the layout data for the top control
+ if (control instanceof Composite) {
+ configureDialogAreaControl((Composite)control);
+ }
+
+ return control;
+ }
+
+ /**
+ * Configure the dialog top control.
+ *
+ * @param composite The dialog top control. Must be not <code>null</code>.
+ */
+ protected void configureDialogAreaControl(Composite composite) {
+ assert composite != null;
+ Layout layout = composite.getLayout();
+ if (layout == null || layout instanceof GridLayout) {
+ composite.setLayout(new GridLayout());
+ }
+ }
+
+ /**
+ * Cleanup when dialog is closed.
+ */
+ protected void dispose() {
+ fDialogSettings = null;
+ }
+
+ /**
+ * Cleanup the Dialog and close it.
+ */
+ @Override
+ public boolean close() {
+ dispose();
+ return super.close();
+ }
+
+ /**
+ * Sets the title for this dialog.
+ *
+ * @param title The title.
+ */
+ public void setDialogTitle(String title) {
+ if (getShell() != null && !getShell().isDisposed()) {
+ getShell().setText(title);
+ }
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/forms/CustomFormToolkit.java b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/forms/CustomFormToolkit.java
new file mode 100644
index 000000000..5cb96b578
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/forms/CustomFormToolkit.java
@@ -0,0 +1,393 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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:
+ * Uwe Stieber (Wind River) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tm.te.ui.forms;
+
+import org.eclipse.core.runtime.PlatformObject;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.GC;
+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.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.forms.events.ExpansionEvent;
+import org.eclipse.ui.forms.events.IExpansionListener;
+import org.eclipse.ui.forms.widgets.ExpandableComposite;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+import org.eclipse.ui.forms.widgets.ScrolledForm;
+import org.eclipse.ui.forms.widgets.Section;
+
+/**
+ * Target Explorer: Custom form toolkit for using form elements within
+ * dialog and wizard pages, or other containers.
+ */
+public class CustomFormToolkit extends PlatformObject {
+ // The reference of the wrapped toolkit
+ private final FormToolkit fToolkit;
+
+ /**
+ * Constructor.
+ *
+ * @param toolkit The {@link FormToolkit} instance to wrap. Must not be <code>null</code>.
+ */
+ public CustomFormToolkit(FormToolkit toolkit) {
+ super();
+ assert toolkit != null;
+ fToolkit = toolkit;
+ }
+
+ /**
+ * Returns the wrapped {@link FormToolkit} instance.
+ *
+ * @return The wrapped {@link FormToolkit} instance.
+ */
+ public final FormToolkit getFormToolkit() {
+ return fToolkit;
+ }
+
+ /**
+ * Dispose the form toolkit wrapper.
+ */
+ public void dispose() {
+ fToolkit.dispose();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.PlatformObject#getAdapter(java.lang.Class)
+ */
+ @Override
+ @SuppressWarnings("rawtypes")
+ public Object getAdapter(Class adapter) {
+ if (FormToolkit.class.isAssignableFrom(adapter))
+ return getFormToolkit();
+
+ return super.getAdapter(adapter);
+ }
+
+ /**
+ * Returns the number of pixels corresponding to the height of the given
+ * number of characters.
+ * <p>
+ * This methods uses the static {@link Dialog#convertHeightInCharsToPixels(org.eclipse.swt.graphics.FontMetrics, int)}
+ * method for calculation.
+ * <p>
+ * @param chars The number of characters
+ * @return The corresponding height in pixels
+ */
+ protected int convertHeightInCharsToPixels(Control control, int chars) {
+ int height = 0;
+ if (control != null && !control.isDisposed()) {
+ GC gc = new GC(control);
+ gc.setFont(JFaceResources.getDialogFont());
+ height = Dialog.convertHeightInCharsToPixels(gc.getFontMetrics(), chars);
+ gc.dispose();
+ }
+
+ return height;
+ }
+
+ /**
+ * Creates a new scrollable form container within the given parent. If
+ * <code>overwriteBackground</code> is set, the parent background color
+ * and background image is applied to the created scrollable form.
+ *
+ * @param parent The parent composite. Must not be <code>null</code>.
+ * @param title The form title or <code>null</code> if none.
+ * @param overwriteBackground If <code>true</code>, the parent background color and image are applied to the scrollable form.
+ *
+ * @return The scrollable form instance.
+ */
+ public ScrolledForm createScrolledForm(Composite parent, String title, boolean overwriteBackground) {
+ assert parent != null;
+
+ // Create the scrolled form which is the scrollable container for the expandable composite
+ final ScrolledForm scrollableForm = getFormToolkit().createScrolledForm(parent);
+
+ // Overwrite background color and image if requested
+ if (overwriteBackground) {
+ scrollableForm.setBackground(parent.getBackground());
+ scrollableForm.setBackgroundImage(parent.getBackgroundImage());
+ }
+
+ // If a title is given, set and decorate the header
+ if (title != null && scrollableForm.getForm() != null) {
+ scrollableForm.getForm().setText(title);
+ getFormToolkit().decorateFormHeading(scrollableForm.getForm());
+ }
+
+ return scrollableForm;
+ }
+
+ /**
+ * Creates an expandable composite within the given parent scrollable form using the given title.
+ * If <code>overwriteBackground</code> is set, the parent background color and background image
+ * is applied to the created expandable composite.
+ *
+ * @param scrolledForm The parent scrolled form. Must not be <code>null</code>.
+ * @param title The expandable composite title. Must not be <code>null</code>.
+ * @param entriesToShow The number of entries to show within the expanded area. Must be greater than 0.
+ * @param expanded The initial expanded state of the expandable composite.
+ * @param overwriteBackground If <code>true</code>, the parent background color and image are applied to the expandable composite.
+ *
+ * @return The expandable composite.
+ */
+ public final ExpandableComposite createExpandableComposite(final ScrolledForm scrolledForm,
+ String title, final int entriesToShow,
+ boolean expanded, boolean overwriteBackground) {
+ assert scrolledForm != null && title != null && entriesToShow > 0;
+
+ // Create the expandable composite within the scrollable container
+ final ExpandableComposite expandable = getFormToolkit().createExpandableComposite(scrolledForm.getBody(), ExpandableComposite.TWISTIE | ExpandableComposite.CLIENT_INDENT);
+ expandable.setText(title);
+
+ // Overwrite background color and image if requested
+ if (overwriteBackground) {
+ expandable.setBackground(scrolledForm.getBackground());
+ expandable.setBackgroundImage(scrolledForm.getBackgroundImage());
+ }
+
+ expandable.setLayout(new GridLayout());
+ expandable.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ // Create an associate an expansion listener to the expandable form
+ expandable.addExpansionListener(new IExpansionListener() {
+ boolean notExpanded = true;
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.forms.events.IExpansionListener#expansionStateChanged(org.eclipse.ui.forms.events.ExpansionEvent)
+ */
+ public void expansionStateChanged(ExpansionEvent e) {
+ // Always set the scrolled form to re-flow. Otherwise it wouldn't
+ // re-arrange the controls following this expandable composite on
+ // collapse.
+ scrolledForm.reflow(true);
+
+ // Get the shell from the scrolled form.
+ Shell shell = scrolledForm.getShell();
+ if (shell != null && !shell.isDisposed() && e.getState() && notExpanded) {
+ // And recalculate the bounds on expand
+ shell.setRedraw(false);
+ Rectangle shellBounds = shell.getBounds();
+
+ // Assume at minimum 4 controls within the expandable area.
+ shellBounds.height += convertHeightInCharsToPixels(expandable, Math.max(4, entriesToShow)) + IDialogConstants.VERTICAL_SPACING;
+
+ shell.setBounds(shellBounds);
+ shell.setRedraw(true);
+ notExpanded = false;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.forms.events.IExpansionListener#expansionStateChanging(org.eclipse.ui.forms.events.ExpansionEvent)
+ */
+ public void expansionStateChanging(ExpansionEvent e) {
+ }
+ });
+
+ // Create the client area the caller can use as parent for the control
+ Composite client = getFormToolkit().createComposite(expandable);
+ client.setLayout(new GridLayout());
+
+ // Overwrite background color and image if requested
+ if (overwriteBackground) {
+ client.setBackground(scrolledForm.getBackground());
+ client.setBackgroundImage(scrolledForm.getBackgroundImage());
+ }
+
+ // Set the initial expansion state
+ expandable.setExpanded(expanded);
+ // And associated the client
+ expandable.setClient(client);
+
+ return expandable;
+ }
+
+ /**
+ * Creates an expandable section within the given parent scrollable form using the given title.
+ * If <code>overwriteBackground</code> is set, the parent background color and background image
+ * is applied to the created section.
+ *
+ * @param parent The parent scrolled form. Must not be <code>null</code>.
+ * @param title The expandable composite title. Must not be <code>null</code>.
+ * @param entriesToShow The number of entries to show within the expanded area. Must be greater than 0.
+ * @param expanded The initial expanded state of the section.
+ * @param overwriteBackground If <code>true</code>, the parent background color and image are applied to the section.
+ *
+ * @return The section.
+ */
+ public final Section createSection(final ScrolledForm scrolledForm,
+ String title, final int entriesToShow,
+ boolean expanded, boolean overwriteBackground) {
+ assert scrolledForm != null && title != null && entriesToShow > 0;
+
+ // Create the section within the scrollable container
+ final Section section = getFormToolkit().createSection(scrolledForm.getBody(), ExpandableComposite.TITLE_BAR | ExpandableComposite.TWISTIE | ExpandableComposite.CLIENT_INDENT);
+ section.setText(title);
+
+ // Overwrite background color and image if requested
+ if (overwriteBackground) {
+ section.setBackground(scrolledForm.getBackground());
+ section.setBackgroundImage(scrolledForm.getBackgroundImage());
+ }
+
+ section.setLayout(new GridLayout());
+ section.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ // Create an associate an expansion listener to the expandable form
+ section.addExpansionListener(new IExpansionListener() {
+ boolean notExpanded = true;
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.forms.events.IExpansionListener#expansionStateChanged(org.eclipse.ui.forms.events.ExpansionEvent)
+ */
+ public void expansionStateChanged(ExpansionEvent e) {
+ // Always set the scrolled form to re-flow. Otherwise it wouldn't
+ // re-arrange the controls following this expandable composite on
+ // collapse.
+ scrolledForm.reflow(true);
+
+ // Get the shell from the scrolled form.
+ Shell shell = scrolledForm.getShell();
+ if (shell != null && !shell.isDisposed() && e.getState() && notExpanded) {
+ // And recalculate the bounds on expand
+ shell.setRedraw(false);
+ Rectangle shellBounds = shell.getBounds();
+
+ // Assume at minimum 4 controls within the expandable area.
+ shellBounds.height += convertHeightInCharsToPixels(section, Math.max(4, entriesToShow)) + IDialogConstants.VERTICAL_SPACING;
+
+ shell.setBounds(shellBounds);
+ shell.setRedraw(true);
+ notExpanded = false;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.forms.events.IExpansionListener#expansionStateChanging(org.eclipse.ui.forms.events.ExpansionEvent)
+ */
+ public void expansionStateChanging(ExpansionEvent e) {
+ }
+ });
+
+ // Create the client area the caller can use as parent for the control
+ Composite client = getFormToolkit().createComposite(section);
+ client.setLayout(new GridLayout());
+
+ // Overwrite background color and image if requested
+ if (overwriteBackground) {
+ client.setBackground(scrolledForm.getBackground());
+ client.setBackgroundImage(scrolledForm.getBackgroundImage());
+ }
+
+ // Set the initial expansion state
+ section.setExpanded(expanded);
+ // And associated the client
+ section.setClient(client);
+
+ return section;
+ }
+
+ /**
+ * Creates an non-expandable section within the given parent scrollable form using the given title.
+ * If <code>overwriteBackground</code> is set, the parent background color and background image
+ * is applied to the created section.
+ *
+ * @param parent The parent scrolled form. Must not be <code>null</code>.
+ * @param title The expandable composite title. Must not be <code>null</code>.
+ * @param overwriteBackground If <code>true</code>, the parent background color and image are applied to the section.
+ *
+ * @return The section.
+ */
+ public final Section createSection(final ScrolledForm scrolledForm, String title, boolean overwriteBackground) {
+ assert scrolledForm != null && title != null;
+
+ // Create the section within the scrollable container
+ final Section section = getFormToolkit().createSection(scrolledForm.getBody(), ExpandableComposite.TITLE_BAR | ExpandableComposite.CLIENT_INDENT);
+ section.setText(title);
+
+ // Overwrite background color and image if requested
+ if (overwriteBackground) {
+ section.setBackground(scrolledForm.getBackground());
+ section.setBackgroundImage(scrolledForm.getBackgroundImage());
+ }
+
+ // Configure the layout
+ section.setLayout(new GridLayout());
+ section.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ // Create the client area the caller can use as parent for the control
+ Composite client = getFormToolkit().createComposite(section);
+ client.setLayout(new GridLayout());
+
+ // Overwrite background color and image if requested
+ if (overwriteBackground) {
+ client.setBackground(section.getBackground());
+ client.setBackgroundImage(section.getBackgroundImage());
+ }
+
+ // And associated the client
+ section.setClient(client);
+
+ return section;
+ }
+
+ /**
+ * Creates a composite with a highlighted note entry and a message text.
+ * This is designed to take up the full width of the page.
+ *
+ * @param parent The parent composite. Must not be <code>null</code>.
+ * @param title The note title. Must not be <code>null</code>.
+ * @param message The note message Must not be <code>null</code>.
+ * @param widthHint The note message width hint in pixel or <code>SWT.DEFAULT</code>.
+ * @param overwriteBackground If <code>true</code>, the parent background color and image are applied to the note composite.
+ *
+ * @return The note composite.
+ */
+ public final Composite createNoteComposite(Composite parent, String title, String message, int widthHint, boolean overwriteBackground) {
+ assert parent != null && title != null && message != null;
+
+ Composite composite = getFormToolkit().createComposite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout(2, false);
+ layout.marginHeight = 0; layout.marginWidth = 0;
+ composite.setLayout(layout);
+ composite.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
+ composite.setFont(parent.getFont());
+
+ Label noteLabel = getFormToolkit().createLabel(composite, title, SWT.BOLD);
+ noteLabel.setFont(JFaceResources.getFontRegistry().getBold(JFaceResources.DIALOG_FONT));
+ noteLabel.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING));
+
+ Label messageLabel = getFormToolkit().createLabel(composite, message);
+ GridData layoutData = new GridData(GridData.FILL_HORIZONTAL);
+ layoutData.widthHint = widthHint;
+ messageLabel.setLayoutData(layoutData);
+ messageLabel.setFont(parent.getFont());
+
+ // Overwrite background color and image if requested
+ if (overwriteBackground) {
+ composite.setBackground(parent.getBackground());
+ composite.setBackgroundImage(parent.getBackgroundImage());
+
+ noteLabel.setBackground(parent.getBackground());
+ noteLabel.setBackgroundImage(parent.getBackgroundImage());
+
+ messageLabel.setBackground(parent.getBackground());
+ messageLabel.setBackgroundImage(parent.getBackgroundImage());
+ }
+
+ return composite;
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/images/AbstractImageDescriptor.java b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/images/AbstractImageDescriptor.java
new file mode 100644
index 000000000..626617b0a
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/images/AbstractImageDescriptor.java
@@ -0,0 +1,176 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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:
+ * Uwe Stieber (Wind River) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tm.te.ui.images;
+
+import org.eclipse.jface.resource.CompositeImageDescriptor;
+import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.Point;
+
+/**
+ * Target Explorer: Image descriptor for creating overlays.
+ */
+public abstract class AbstractImageDescriptor extends CompositeImageDescriptor {
+
+ private String fKey;
+ private ImageRegistry fRegistry;
+
+ public AbstractImageDescriptor(ImageRegistry reg) {
+ fRegistry = reg;
+ }
+
+ protected void setKey(String key) {
+ fKey = key;
+ }
+
+ public String getKey() {
+ return fKey;
+ }
+
+ protected ImageRegistry getRegistry() {
+ return fRegistry;
+ }
+
+ protected void drawCentered(String key, int width, int height) {
+ drawCentered(fRegistry.get(key), width, height);
+ }
+
+ protected void drawCentered(Image image, int width, int height) {
+ if (image != null) {
+ ImageData imageData = image.getImageData();
+ if (imageData != null) {
+ int x = StrictMath.max(0, (width - imageData.width + 1) / 2);
+ int y = StrictMath.max(0, (height - imageData.height + 1) / 2);
+ drawImage(imageData, x, y);
+ }
+ }
+ }
+
+ protected void drawCenterRight(String key, int width, int height) {
+ Image baseImage = fRegistry.get(key);
+ if (baseImage != null) {
+ ImageData imageData = baseImage.getImageData();
+ if (imageData != null) {
+ int x = StrictMath.max(0, width - imageData.width);
+ int y = StrictMath.max(0, (height - imageData.height + 1) / 2);
+ drawImage(imageData, x, y);
+ }
+ }
+ }
+
+ protected void drawTopLeft(String key) {
+ Image baseImage = fRegistry.get(key);
+ if (baseImage != null) {
+ ImageData imageData = baseImage.getImageData();
+ if (imageData != null) {
+ drawImage(imageData, 0, 0);
+ }
+ }
+ }
+
+ protected void drawTopRight(String key, int width, int height) {
+ Image baseImage = fRegistry.get(key);
+ if (baseImage != null) {
+ ImageData imageData = baseImage.getImageData();
+ if (imageData != null) {
+ int x = StrictMath.max(0, width - imageData.width);
+ drawImage(imageData, x, 0);
+ }
+ }
+ }
+
+ protected void drawBottomCenter(String key, int width, int height) {
+ Image image = fRegistry.get(key);
+ if (image != null) {
+ ImageData imageData = image.getImageData();
+ if (imageData != null) {
+ int x = StrictMath.max(0, (width - imageData.width + 1) / 2);
+ int y = StrictMath.max(0, height - imageData.height);
+ drawImage(imageData, x, y);
+ }
+ }
+ }
+
+ protected void drawBottomLeft(String key) {
+ if (getSize() != null) {
+ Point size = getSize();
+ drawBottomLeft(key, size.x, size.y);
+ } else {
+ // the default eclipse style guide recommendation is 16x16
+ drawBottomLeft(key, 16, 16);
+ }
+ }
+
+ protected void drawBottomLeft(String key, int width, int height) {
+ Image image = fRegistry.get(key);
+ if (image != null) {
+ ImageData imageData = image.getImageData();
+ if (imageData != null) {
+ int y = StrictMath.max(0, height - imageData.height);
+ drawImage(imageData, 0, y);
+ }
+ }
+ }
+
+ protected void drawCenterLeft(String key, int width, int height) {
+ Image image = fRegistry.get(key);
+ if (image != null) {
+ ImageData imageData = image.getImageData();
+ if (imageData != null) {
+ int y = StrictMath.max(0, (height - imageData.height) / 2);
+ drawImage(imageData, 0, y);
+ }
+ }
+ }
+
+ protected void drawBottomRight(String key) {
+ if (getSize() != null) {
+ Point size = getSize();
+ drawBottomRight(key, size.x, size.y);
+ } else {
+ // the default eclipse style guide recommendation is 16x16
+ drawBottomRight(key, 16, 16);
+ }
+ }
+
+ protected void drawBottomRight(String key, int width, int height) {
+ Image image = fRegistry.get(key);
+ if (image != null) {
+ ImageData imageData = image.getImageData();
+ if (imageData != null) {
+ int x = StrictMath.max(0, width - imageData.width);
+ int y = StrictMath.max(0, height - imageData.height);
+ drawImage(imageData, x, y);
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.resource.CompositeImageDescriptor#getTransparentPixel()
+ */
+ @Override
+ protected int getTransparentPixel() {
+ Image baseImage = getBaseImage();
+ if (baseImage != null && baseImage.getImageData() != null) {
+ return baseImage.getImageData().transparentPixel;
+ }
+ return super.getTransparentPixel();
+ }
+
+ /**
+ * Returns the base image used for the combined image description. This
+ * method is called from <code>getTransparentPixel()</code> to query the
+ * transparent color of the palette.
+ *
+ * @return The base image or <code>null</code> if none.
+ */
+ protected abstract Image getBaseImage();
+}
diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/images/AbstractImageRegistry.java b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/images/AbstractImageRegistry.java
new file mode 100644
index 000000000..849b7d875
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/images/AbstractImageRegistry.java
@@ -0,0 +1,218 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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:
+ * Uwe Stieber (Wind River) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tm.te.ui.images;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.tm.te.ui.activator.UIPlugin;
+import org.eclipse.tm.te.ui.nls.Messages;
+import org.osgi.framework.Bundle;
+
+
+
+/**
+ * Target Explorer: Abstract image registry that allows for defining fallback paths for images.
+ */
+public abstract class AbstractImageRegistry extends ImageRegistry {
+ private List<ImageRegistry> fDelegates = new ArrayList<ImageRegistry>();
+ private Map<String,String> fPlugins = new HashMap<String,String>();
+ private Map<String,String[]> fLocations = new HashMap<String,String[]>();
+ private URL fBaseUrl;
+
+ protected AbstractImageRegistry(Plugin plugin) {
+ fBaseUrl = plugin.getBundle().getEntry("/"); //$NON-NLS-1$
+ }
+
+ /**
+ * Adds the given image registry as delegate. Delegates are queried if
+ * an image or image descriptor cannot be found locally. If the image
+ * registry delegate had been added before, the method will do nothing.
+ *
+ * @param registry The image registry. Must be not <code>null</code>.
+ */
+ protected final void addImageRegistryDelegate(ImageRegistry registry) {
+ assert registry != null;
+ if (!fDelegates.contains(registry)) fDelegates.add(registry);
+ }
+
+ /**
+ * Removes the given image registry from the list of delegates.
+ *
+ * @param registry The image registry. Must be not <code>null</code>.
+ */
+ protected final void removeImageRegistryDelegate(ImageRegistry registry) {
+ assert registry != null;
+ fDelegates.remove(registry);
+ }
+
+ /**
+ * Defines the key for a local image, that must be found below the icons directory
+ * in the plugin.
+ * @param key Key by which the image can be referred by.
+ * @param dir Directory relative to icons/
+ * @param name The name of the file defining the icon. The name will be used as
+ * key.
+ */
+ protected void localImage(String key, String dir, String name) {
+ if (dir== null || dir.equals(""))//$NON-NLS-1$
+ fLocations.put(key, new String[] {"icons/" + name}); //$NON-NLS-1$
+ else
+ fLocations.put(key, new String[] {"icons/" + dir + "/" + name}); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ /**
+ * Defines the key for a non-local image, that must be found below the icons directory
+ * of some plugin.
+ * @param key Key by which the image can be referred by.
+ * @param plugin The plugin id, where the icon is searched.
+ * @param dirs A couple of directories below icons/ in the plugin. If loading fails,
+ * the next dir will be taken as fallback.
+ * @param name The name of the file defining the icon. The name will be used as
+ * key.
+ */
+ protected void externalImage(String key, String plugin, String[] dirs, String name) {
+ if (plugin != null) {
+ fPlugins.put(key, plugin);
+ }
+ String[] locations = new String[dirs.length];
+ for (int i = 0; i < dirs.length; i++) {
+ String dir = dirs[i];
+ if (dir== null || dir.equals(""))//$NON-NLS-1$
+ locations[i] = "icons/" + name; //$NON-NLS-1$
+ else
+ locations[i] = "icons/" + dir + "/" + name; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ fLocations.put(key, locations);
+ }
+
+ final private Image internalDoGet(String key) {
+ // First query the parent (local) image registry if
+ // an image for the given key is registered.
+ Image i = super.get(key);
+ if (i != null) return i;
+
+ // If no image had been returned, try the delegates
+ for (ImageRegistry delegate : fDelegates) {
+ i = delegate.get(key);
+ if (i != null) break;
+ }
+
+ return i;
+ }
+
+ final private ImageDescriptor internalDoGetDescriptor(String key) {
+ // First query the parent (local) image registry if
+ // an image for the given key is registered.
+ ImageDescriptor d = super.getDescriptor(key);
+ if (d != null) return d;
+
+ // If no image had been returned, try the delegates
+ for (ImageRegistry delegate : fDelegates) {
+ d = delegate.getDescriptor(key);
+ if (d != null) break;
+ }
+
+ return d;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.resource.ImageRegistry#get(java.lang.String)
+ */
+ @Override
+ final public Image get(String key) {
+ Image i = internalDoGet(key);
+ if (i != null) {
+ return i;
+ }
+
+ ImageDescriptor d = createFileImageDescriptor(key);
+ if (d != null) {
+ put(key, d);
+ return internalDoGet(key);
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.resource.ImageRegistry#getDescriptor(java.lang.String)
+ */
+ @Override
+ final public ImageDescriptor getDescriptor(String key) {
+ ImageDescriptor d = internalDoGetDescriptor(key);
+ if (d != null) {
+ return d;
+ }
+
+ d = createFileImageDescriptor(key);
+ if (d != null) {
+ put(key, d);
+ return d;
+ }
+ return null;
+ }
+
+ private ImageDescriptor createFileImageDescriptor(String key) {
+ URL url = fBaseUrl;
+ String pluginId = fPlugins.get(key);
+ if (pluginId != null) {
+ Bundle bundle= Platform.getBundle(pluginId);
+ if (bundle != null) {
+ url = bundle.getEntry("/"); //$NON-NLS-1$
+ }
+ }
+ String[] locations= fLocations.get(key);
+ if (locations != null) {
+ for (int i = 0; i < locations.length; i++) {
+ String loc = locations[i];
+ URL full;
+ try {
+ full = new URL(url, loc);
+ ImageDescriptor candidate = ImageDescriptor.createFromURL(full);
+ if (candidate != null && candidate.getImageData() != null) {
+ return candidate;
+ }
+ } catch (MalformedURLException e) {
+ IStatus status = new Status(IStatus.ERROR, UIPlugin.getUniqueIdentifier(),
+ Messages.AbstractImageRegistry_error_malformedImage, e);
+ UIPlugin.getDefault().getLog().log(status);
+ } catch (SWTException e) {
+ // try the next one.
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Get a shared Image for a given descriptor
+ */
+ public Image getSharedImage(AbstractImageDescriptor d) {
+ String key = d.getKey();
+ Image shared = super.get(key);
+ if (shared != null) {
+ return shared;
+ }
+ put(key, d);
+ return super.get(key);
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/interfaces/IUIConstants.java b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/interfaces/IUIConstants.java
new file mode 100644
index 000000000..3ff613ac9
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/interfaces/IUIConstants.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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:
+ * Uwe Stieber (Wind River) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tm.te.ui.interfaces;
+
+import org.eclipse.tm.te.ui.activator.UIPlugin;
+
+/**
+ * Target Explorer: Common UI constants.
+ *
+ * @author uwe.stieber@windriver.com
+ */
+public interface IUIConstants {
+
+ /**
+ * The Target Explorer common controls context menu id base part.
+ */
+ public static final String ID_CONTROL_MENUS_BASE = UIPlugin.getUniqueIdentifier() + ".controls"; //$NON-NLS-1$
+}
diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/nls/Messages.java b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/nls/Messages.java
new file mode 100644
index 000000000..297235b6b
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/nls/Messages.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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:
+ * Uwe Stieber (Wind River) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tm.te.ui.nls;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Target Explorer: Common UI plugin externalized strings management.
+ */
+public class Messages extends NLS {
+
+ // The plug-in resource bundle name
+ private static final String BUNDLE_NAME = "org.eclipse.tm.te.ui.nls.Messages"; //$NON-NLS-1$
+
+ /**
+ * Static constructor.
+ */
+ static {
+ // Load message values from bundle file
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+ // **** Declare externalized string id's down here *****
+
+ public static String AbstractImageRegistry_error_malformedImage;
+
+ public static String NodePropertiesTableControl_section_title;
+ public static String NodePropertiesTableControl_section_title_noSelection;
+ public static String NodePropertiesTableControl_column_name_label;
+ public static String NodePropertiesTableControl_column_value_label;
+
+ public static String PendingOperation_label;
+
+ public static String EditBrowseTextControl_button_label;
+}
diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/nls/Messages.properties b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/nls/Messages.properties
new file mode 100644
index 000000000..b943bab0c
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/nls/Messages.properties
@@ -0,0 +1,15 @@
+#
+# org.eclipse.tm.te.ui
+# Externalized Strings.
+#
+
+AbstractImageRegistry_error_malformedImage=Malformed Image
+
+NodePropertiesTableControl_section_title={0} Information
+NodePropertiesTableControl_section_title_noSelection=Node
+NodePropertiesTableControl_column_name_label=Property
+NodePropertiesTableControl_column_value_label=Value
+
+PendingOperation_label=Pending...
+
+EditBrowseTextControl_button_label=Browse...
diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/nodes/PendingOperation.java b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/nodes/PendingOperation.java
new file mode 100644
index 000000000..1859001c6
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/nodes/PendingOperation.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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:
+ * Uwe Stieber (Wind River) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tm.te.ui.nodes;
+
+import org.eclipse.core.runtime.PlatformObject;
+import org.eclipse.tm.te.ui.nls.Messages;
+
+
+/**
+ * Target Explorer: Pending operation data node.
+ */
+public class PendingOperation extends PlatformObject {
+
+ /**
+ * Returns the pending operation node name.
+ *
+ * @return The node name.
+ */
+ public final String getName() {
+ return Messages.PendingOperation_label;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public final int hashCode() {
+ return getName().hashCode();
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public final String toString() {
+ return getName();
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/tables/TableNode.java b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/tables/TableNode.java
new file mode 100644
index 000000000..e4daa98c9
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/tables/TableNode.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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:
+ * Uwe Stieber (Wind River) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tm.te.ui.tables;
+
+import org.eclipse.core.runtime.PlatformObject;
+
+/**
+ * Target Explorer: Immutable representation of a table node.
+ */
+public final class TableNode extends PlatformObject {
+ /**
+ * The node name.
+ */
+ public final String name;
+
+ /**
+ * The node value.
+ */
+ public final String value;
+
+ /**
+ * Constructor.
+ *
+ * @param name The node name. Must be not <code>null</code>.
+ * @param value The node value. Must be not <code>null</code>.
+ */
+ public TableNode(String name, String value) {
+ assert name != null && value != null;
+ this.name = name;
+ this.value = value;
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/tables/TableViewerComparator.java b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/tables/TableViewerComparator.java
new file mode 100644
index 000000000..c00691b66
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/tables/TableViewerComparator.java
@@ -0,0 +1,135 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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:
+ * Uwe Stieber (Wind River) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tm.te.ui.tables;
+
+import java.util.Arrays;
+
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.tm.te.ui.AbstractViewerComparator;
+
+
+/**
+ * Target Explorer: Common table control viewer comparator implementation.
+ */
+public class TableViewerComparator extends AbstractViewerComparator {
+ private final ITableLabelProvider fLabelProvider;
+
+ /**
+ * Constructor.
+ *
+ * @param viewer The parent viewer. Must be not <code>null</code>.
+ * @param labelProvider The table label provider. Must be not <code>null</code>.
+ */
+ public TableViewerComparator(Viewer viewer, ITableLabelProvider labelProvider) {
+ super(viewer);
+ assert labelProvider != null;
+ fLabelProvider = labelProvider;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tm.te.ui.controls.AbstractViewerComparator#doDetermineInverter(org.eclipse.jface.viewers.Viewer)
+ */
+ @Override
+ protected int doDetermineInverter(Viewer viewer) {
+ int inverter = 1;
+
+ // Viewer must be of type TableViewer and the table must not be disposed yet
+ if (viewer instanceof TableViewer && ((TableViewer)viewer).getTable() != null) {
+ Table table = ((TableViewer)viewer).getTable();
+ if (!table.isDisposed() && table.getSortDirection() == SWT.DOWN) inverter = -1;
+ }
+
+ return inverter;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tm.te.ui.controls.AbstractViewerComparator#doGetText(java.lang.Object, int)
+ */
+ @Override
+ protected String doGetText(Object node, int index) {
+ if (node != null && fLabelProvider != null) {
+ return index != -1 ? fLabelProvider.getColumnText(node, index) : ((ILabelProvider)fLabelProvider).getText(node);
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tm.te.ui.controls.AbstractViewerComparator#doGetSortColumnLabel(org.eclipse.jface.viewers.Viewer)
+ */
+ @Override
+ protected String doGetSortColumnLabel(Viewer viewer) {
+ // Viewer must be of type TableViewer and the table must not be disposed yet
+ if (viewer instanceof TableViewer && ((TableViewer)viewer).getTable() != null && !((TableViewer)viewer).getTable().isDisposed()) {
+ Table table = ((TableViewer)viewer).getTable();
+ return table.getSortColumn() != null ? table.getSortColumn().getText() : ""; //$NON-NLS-1$
+ }
+ return ""; //$NON-NLS-1$
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tm.te.ui.controls.AbstractViewerComparator#doGetSortColumnIndex(org.eclipse.jface.viewers.Viewer)
+ */
+ @Override
+ protected int doGetSortColumnIndex(Viewer viewer) {
+ // Viewer must be of type TableViewer and the table must not be disposed yet
+ if (viewer instanceof TableViewer && ((TableViewer)viewer).getTable() != null && !((TableViewer)viewer).getTable().isDisposed()) {
+ Table table = ((TableViewer)viewer).getTable();
+ return table.getSortColumn() != null ? Arrays.asList(table.getColumns()).indexOf(table.getSortColumn()) : -1;
+ }
+ return -1;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tm.te.ui.controls.AbstractViewerComparator#doCompare(java.lang.Object, java.lang.Object, java.lang.String, int, int)
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ protected int doCompare(Object node1, Object node2, String sortColumn, int index, int inverter) {
+ if (node1 == null && node2 == null) return 0;
+ if (node1 != null && node2 == null) return 1;
+ if (node1 == null && node2 != null) return -1;
+
+ // Get the labels
+ String text1 = doGetText(node1, index);
+ String text2 = doGetText(node2, index);
+
+ // If the text is matching ".*[0-9]+$" -> compare numerical instead of alphabetical
+ if (text1 != null && text1.matches(".*[0-9]+$") && text2 != null && text2.matches(".*[0-9]+$")) { //$NON-NLS-1$ //$NON-NLS-2$
+ // Split numbers and text (note that this effectively removes the number ... splitted[1] == "").
+ String[] splitted1 = text1.split("[0-9]+$", 2); //$NON-NLS-1$
+ String[] splitted2 = text2.split("[0-9]+$", 2); //$NON-NLS-1$
+
+ // Get the parts to match alphabetical
+ String alpha1 = splitted1[0];
+ String alpha2 = splitted2[0];
+
+ // The numerical parts is what remains if we strip the alpha parts from the original text
+ String num1 = text1.replace(alpha1, ""); //$NON-NLS-1$
+ String num2 = text2.replace(alpha2, ""); //$NON-NLS-1$
+
+ // Compare the alpha parts
+ int result = getComparator().compare(alpha1, alpha2) * inverter;
+ // Only if the alpha parts are equal, compare the numerical parts too
+ if (result == 0) {
+ result = Integer.decode(num1).compareTo(Integer.decode(num2)) * inverter;
+ }
+
+ return result;
+ }
+
+ // Compare the text alphabetical
+ return getComparator().compare(text1, text2) * inverter;
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/tables/properties/NodePropertiesTableControl.java b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/tables/properties/NodePropertiesTableControl.java
new file mode 100644
index 000000000..4fe2f3d68
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/tables/properties/NodePropertiesTableControl.java
@@ -0,0 +1,417 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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:
+ * Uwe Stieber (Wind River) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tm.te.ui.tables.properties;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.viewers.ColumnWeightData;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.TableLayout;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerComparator;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Cursor;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.tm.te.ui.WorkbenchPartControl;
+import org.eclipse.tm.te.ui.forms.CustomFormToolkit;
+import org.eclipse.tm.te.ui.interfaces.IUIConstants;
+import org.eclipse.tm.te.ui.nls.Messages;
+import org.eclipse.ui.ISelectionListener;
+import org.eclipse.ui.IWorkbenchActionConstants;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchPartSite;
+import org.eclipse.ui.forms.widgets.Section;
+
+
+/**
+ * Target Explorer: Abstract node properties table control implementation.
+ */
+public abstract class NodePropertiesTableControl extends WorkbenchPartControl {
+ // Reference to the table viewer
+ private TableViewer fViewer;
+ // Reference to the selection changed listener
+ private ISelectionChangedListener fEditorSelectionChangedListener;
+
+ // We remember the sorting order (ascending vs. descending) for each
+ // column separately. That way we can come up with the sort order switching
+ // correctly if the user changes from one column to the next. If set
+ // to Boolean.FALSE, the sort order for the column is descending (default)
+ private final Map<TableColumn, Boolean> fColumnSortOrder = new LinkedHashMap<TableColumn, Boolean>();
+
+ /**
+ * Default node properties table control selection changed listener implementation.
+ * The selection changed listener is registered to the editor tree control.
+ */
+ protected class NodePropertiesTableControlSelectionChangedListener implements ISelectionChangedListener {
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent)
+ */
+ public void selectionChanged(SelectionChangedEvent event) {
+ if (getViewer() != null) {
+ getViewer().setInput(event.getSelection());
+ }
+ }
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param parentPart The parent workbench part this control is embedded in or <code>null</code>.
+ */
+ public NodePropertiesTableControl(IWorkbenchPart parentPart) {
+ super(parentPart);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tm.te.ui.WorkbenchPartControl#dispose()
+ */
+ @Override
+ public void dispose() {
+ // Dispose the editor tree control selection changed listener
+ if (fEditorSelectionChangedListener != null) {
+ ISelectionProvider selectionProvider = (ISelectionProvider)getParentPart().getAdapter(ISelectionProvider.class);
+ if (selectionProvider != null) {
+ selectionProvider.removeSelectionChangedListener(fEditorSelectionChangedListener);
+ fEditorSelectionChangedListener = null;
+ }
+ }
+
+ super.dispose();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tm.te.ui.WorkbenchPartControl#setupFormPanel(org.eclipse.swt.widgets.Composite, org.eclipse.tm.te.ui.forms.CustomFormToolkit)
+ */
+ @Override
+ public void setupFormPanel(Composite parent, CustomFormToolkit toolkit) {
+ super.setupFormPanel(parent, toolkit);
+
+ // Create the table viewer
+ fViewer = doCreateTableViewer(parent);
+ // Configure the table viewer
+ configureTableViewer(fViewer);
+ // Configure the table
+ configureTable(fViewer.getTable(), fViewer.getComparator() != null);
+
+ // Register the control as selection listener to the editor control
+ ISelectionProvider selectionProvider = getParentPart() != null ? (ISelectionProvider)getParentPart().getAdapter(ISelectionProvider.class) : null;
+ if (selectionProvider != null) {
+ // Create the selection changed listener instance
+ fEditorSelectionChangedListener = doCreateEditorSelectionChangedListener();
+ selectionProvider.addSelectionChangedListener(fEditorSelectionChangedListener);
+ }
+
+ // Prepare popup menu and toolbar
+ createContributionItems(fViewer);
+
+ // Set the current selection as input
+ fViewer.setInput(selectionProvider != null ? selectionProvider.getSelection() : null);
+ }
+
+ /**
+ * Creates a new editor tree control selection changed listener instance.
+ *
+ * @return The editor tree control selection changed listener instance.
+ */
+ protected ISelectionChangedListener doCreateEditorSelectionChangedListener() {
+ return new NodePropertiesTableControlSelectionChangedListener();
+ }
+
+ /**
+ * Creates the table viewer instance.
+ *
+ * @param parent The parent composite. Must not be <code>null</code>.
+ * @return The table viewer.
+ */
+ protected TableViewer doCreateTableViewer(Composite parent) {
+ assert parent != null;
+
+ TableViewer tableViewer = new TableViewer(parent, SWT.FULL_SELECTION | SWT.MULTI | SWT.BORDER);
+
+ return tableViewer;
+ }
+
+ /**
+ * Configure the table Viewer.
+ *
+ * @param tableViewer The table viewer. Must not be <code>null</code>.
+ */
+ protected void configureTableViewer(TableViewer tableViewer) {
+ assert tableViewer != null;
+
+ tableViewer.setLabelProvider(doCreateTableViewerLabelProvider(tableViewer));
+ tableViewer.setContentProvider(doCreateTableViewerContentProvider(tableViewer));
+ tableViewer.setComparator(doCreateTableViewerComparator(tableViewer));
+ }
+
+ /**
+ * Creates the table viewer label provider instance.
+ *
+ * @param viewer The table viewer. Must be not <code>null</code>.
+ * @return The table viewer label provider instance.
+ */
+ protected abstract ITableLabelProvider doCreateTableViewerLabelProvider(TableViewer viewer);
+
+ /**
+ * Creates the table viewer content provider instance.
+ *
+ * @param viewer The table viewer. Must be not <code>null</code>.
+ * @return The table viewer content provider instance.
+ */
+ protected abstract IStructuredContentProvider doCreateTableViewerContentProvider(TableViewer viewer);
+
+ /**
+ * Creates the table viewer comparator instance.
+ *
+ * @param viewer The table viewer. Must be not <code>null</code>.
+ * @return The table viewer comparator instance or <code>null</code> to turn of sorting.
+ */
+ protected ViewerComparator doCreateTableViewerComparator(TableViewer viewer) {
+ return null;
+ }
+
+ /**
+ * Configure the table.
+ *
+ * @param table The table. Must not be <code>null</code>.
+ * @param sorted Specify <code>true</code> if the table shall support sorting, <code>false</code> otherwise.
+ */
+ protected void configureTable(Table table, boolean sorted) {
+ assert table != null;
+
+ // Create and configure the table columns
+ createTableColumns(table, sorted);
+
+ table.setHeaderVisible(true);
+ table.setLinesVisible(true);
+ }
+
+ /**
+ * Create the table columns.
+ *
+ * @param table The table. Must not be <code>null</code>.
+ * @param sorted Specify <code>true</code> if the table shall support sorting, <code>false</code> otherwise.
+ */
+ protected void createTableColumns(final Table table, boolean sorted) {
+ assert table != null;
+
+ TableColumn sortColumn = null;
+
+ TableColumn column = new TableColumn(table, SWT.LEFT);
+ column.setText(Messages.NodePropertiesTableControl_column_name_label);
+ fColumnSortOrder.put(column, Boolean.TRUE);
+ if (sorted) column.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ if (e.widget instanceof TableColumn) {
+ switchSortColumn(table, (TableColumn)e.widget);
+ }
+ }
+ });
+ // The property name is the default sorting column
+ sortColumn = column;
+
+ column = new TableColumn(table, SWT.LEFT);
+ column.setText(Messages.NodePropertiesTableControl_column_value_label);
+ fColumnSortOrder.put(column, Boolean.FALSE);
+ if (sorted) column.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ if (e.widget instanceof TableColumn) {
+ switchSortColumn(table, (TableColumn)e.widget);
+ }
+ }
+ });
+
+ TableLayout tableLayout = new TableLayout();
+ tableLayout.addColumnData(new ColumnWeightData(30));
+ tableLayout.addColumnData(new ColumnWeightData(70));
+ table.setLayout(tableLayout);
+
+ GridData layoutData = new GridData(GridData.FILL_BOTH | GridData.VERTICAL_ALIGN_BEGINNING);
+ table.setLayoutData(layoutData);
+
+ if (sorted) {
+ // set the default sort column
+ table.setSortColumn(sortColumn);
+ table.setSortDirection(fColumnSortOrder.get(sortColumn).booleanValue() ? SWT.UP : SWT.DOWN);
+ }
+ }
+
+ /**
+ * Switches the sort order for the given column and set the
+ * new sort order and sort column to the given table.
+ *
+ * @param table The table.
+ * @param column The table column
+ */
+ protected final void switchSortColumn(Table table, TableColumn column) {
+ if (table == null || table.isDisposed() || column == null || column.isDisposed()) {
+ return;
+ }
+ // Get the current sorting order for the given column
+ boolean newSortOrder = !fColumnSortOrder.get(column).booleanValue();
+ // Set sort column and sort direction
+ table.setSortColumn(column);
+ table.setSortDirection(newSortOrder ? SWT.UP : SWT.DOWN);
+ // And update the remembered sort order in the map
+ fColumnSortOrder.put(column, Boolean.valueOf(newSortOrder));
+
+ getViewer().refresh();
+ }
+
+ /**
+ * Create the context menu and toolbar groups.
+ *
+ * @param viewer The table viewer. Must not be <code>null</code>.
+ */
+ protected void createContributionItems(TableViewer viewer) {
+ assert viewer != null;
+
+ // Create the menu manager
+ MenuManager manager = new MenuManager("#PopupMenu"); //$NON-NLS-1$
+ // Attach the menu listener
+ manager.addMenuListener(new IMenuListener() {
+ public void menuAboutToShow(IMenuManager manager) {
+ manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
+ }
+ });
+ // All items are removed when menu is closing
+ manager.setRemoveAllWhenShown(true);
+ // Associated with the tree
+ viewer.getTable().setMenu(manager.createContextMenu(viewer.getTable()));
+
+ // Register the context menu at the parent workbench part site.
+ if (getParentPart() != null && getParentPart().getSite() != null && getContextMenuId() != null) {
+ IWorkbenchPartSite site = getParentPart().getSite();
+ site.registerContextMenu(getContextMenuId(), manager, viewer);
+ }
+
+ // The toolbar is a bit more complicated as we want to have the
+ // toolbar placed within the section title.
+ createToolbarContributionItem(viewer);
+ }
+
+ /**
+ * Returns the controls context menu id.
+ *
+ * @return The context menu id or <code>null</code>.
+ */
+ protected String getContextMenuId() {
+ return IUIConstants.ID_CONTROL_MENUS_BASE + ".menu.propertiesTable"; //$NON-NLS-1$
+ }
+
+ /**
+ * Creates the toolbar within the section parent of the given filtered tree.
+ *
+ * @param viewer The table viewer. Must not be <code>null</code>.
+ */
+ protected void createToolbarContributionItem(TableViewer viewer) {
+ assert viewer != null;
+
+ // Determine the section parent from the filtered tree
+ Composite parent = viewer.getTable().getParent();
+ while (parent != null && !(parent instanceof Section)) {
+ parent = parent.getParent();
+ }
+
+ // We are done here if we cannot find a section parent or the parent is disposed
+ if (parent == null || parent.isDisposed()) {
+ return;
+ }
+
+ // Create the toolbar control
+ ToolBar toolbar = new ToolBar(parent, SWT.FLAT | SWT.HORIZONTAL | SWT.RIGHT);
+
+ // The cursor within the toolbar shall change to an hand
+ final Cursor handCursor = new Cursor(parent.getDisplay(), SWT.CURSOR_HAND);
+ toolbar.setCursor(handCursor);
+ // Cursor needs to be explicitly disposed
+ toolbar.addDisposeListener(new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ if ((handCursor != null) && (handCursor.isDisposed() == false)) {
+ handCursor.dispose();
+ }
+ }
+ });
+
+ // If the parent composite is a forms section, set the toolbar
+ // as text client to the section header
+ if (parent instanceof Section) {
+ Section section = (Section)parent;
+ // Set the toolbar as text client
+ section.setTextClient(toolbar);
+ }
+
+ // create the toolbar items
+ createToolBarItems(toolbar);
+ }
+
+ /**
+ * Create the toolbar items to be added to the toolbar. Override
+ * to add the wanted toolbar items.
+ * <p>
+ * <b>Note:</b> The toolbar items are added from left to right.
+ *
+ * @param toolbar The toolbar to add the toolbar items too. Must not be <code>null</code>.
+ */
+ protected void createToolBarItems(ToolBar toolbar) {
+ assert toolbar != null;
+ }
+
+ /**
+ * Returns the viewer instance.
+ *
+ * @return The viewer instance or <code>null</code>.
+ */
+ public Viewer getViewer() {
+ return fViewer;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
+ */
+ @Override
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public Object getAdapter(Class adapter) {
+ if (Viewer.class.isAssignableFrom(adapter)) {
+ // We have to double check if our real viewer is assignable to
+ // the requested Viewer class.
+ Viewer viewer = getViewer();
+ if (!adapter.isAssignableFrom(viewer.getClass())) {
+ viewer = null;
+ }
+ return viewer;
+ } else if (ISelectionListener.class.isAssignableFrom(adapter)) {
+ return fEditorSelectionChangedListener;
+ }
+
+ return super.getAdapter(adapter);
+ }
+
+}
diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/trees/AbstractTreeControl.java b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/trees/AbstractTreeControl.java
new file mode 100644
index 000000000..e4ae46050
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/trees/AbstractTreeControl.java
@@ -0,0 +1,307 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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:
+ * Uwe Stieber (Wind River) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tm.te.ui.trees;
+
+
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+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.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.graphics.Cursor;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.tm.te.ui.WorkbenchPartControl;
+import org.eclipse.tm.te.ui.forms.CustomFormToolkit;
+import org.eclipse.ui.IWorkbenchActionConstants;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.forms.widgets.Section;
+
+
+/**
+ * Target Explorer: Abstract tree control implementation.
+ */
+public abstract class AbstractTreeControl extends WorkbenchPartControl {
+ // Reference to the tree viewer instance
+ private TreeViewer fViewer;
+ // Reference to the selection changed listener
+ private ISelectionChangedListener fSelectionChangedListener;
+
+ /**
+ * Constructor.
+ */
+ public AbstractTreeControl() {
+ super();
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param parentPart The parent workbench part this control is embedded in or <code>null</code>.
+ */
+ public AbstractTreeControl(IWorkbenchPart parentPart) {
+ super(parentPart);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tm.te.ui.WorkbenchPartControl#dispose()
+ */
+ @Override
+ public void dispose() {
+ // Unregister the selection changed listener
+ if (fSelectionChangedListener != null) {
+ if (getViewer() != null) {
+ getViewer().removeSelectionChangedListener(fSelectionChangedListener);
+ }
+ fSelectionChangedListener = null;
+ }
+
+ super.dispose();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tm.te.ui.WorkbenchPartControl#setupFormPanel(org.eclipse.swt.widgets.Composite, org.eclipse.tm.te.ui.forms.CustomFormToolkit)
+ */
+ @Override
+ public void setupFormPanel(Composite parent, CustomFormToolkit toolkit) {
+ super.setupFormPanel(parent, toolkit);
+
+ // Create the tree viewer
+ fViewer = doCreateTreeViewer(parent);
+ // And configure the tree viewer
+ configureTreeViewer(fViewer);
+
+ // Prepare popup menu and toolbar
+ createContributionItems(fViewer);
+ }
+
+ /**
+ * Creates the tree viewer instance.
+ *
+ * @param parent The parent composite. Must be not <code>null</code>.
+ * @return The tree viewer.
+ */
+ protected TreeViewer doCreateTreeViewer(Composite parent) {
+ assert parent != null;
+ return new TreeViewer(parent, SWT.FULL_SELECTION | SWT.SINGLE);
+ }
+
+ /**
+ * Configure the tree viewer.
+ *
+ * @param viewer The tree viewer. Must be not <code>null</code>.
+ */
+ protected void configureTreeViewer(TreeViewer viewer) {
+ assert viewer != null;
+
+ viewer.setAutoExpandLevel(getAutoExpandLevel());
+
+ viewer.setLabelProvider(doCreateTreeViewerLabelProvider(viewer));
+ viewer.setContentProvider(doCreateTreeViewerContentProvider(viewer));
+ viewer.setComparator(doCreateTreeViewerComparator(viewer));
+
+ viewer.getTree().setLayoutData(doCreateTreeViewerLayoutData(viewer));
+
+ // Attach the selection changed listener
+ fSelectionChangedListener = doCreateTreeViewerSelectionChangedListener(viewer);
+ if (fSelectionChangedListener != null) {
+ viewer.addSelectionChangedListener(fSelectionChangedListener);
+ }
+ }
+
+ /**
+ * Returns the number of levels to auto expand.
+ * If the method returns <code>0</code>, no auto expansion will happen
+ *
+ * @return The number of levels to auto expand or <code>0</code>.
+ */
+ protected int getAutoExpandLevel() {
+ return 2;
+ }
+
+ /**
+ * Creates the tree viewer layout data instance.
+ *
+ * @param viewer The tree viewer. Must be not <code>null</code>.
+ * @return The tree viewer layout data instance.
+ */
+ protected Object doCreateTreeViewerLayoutData(TreeViewer viewer) {
+ return new GridData(GridData.FILL_BOTH);
+ }
+
+ /**
+ * Creates the tree viewer label provider instance.
+ *
+ * @param viewer The tree viewer. Must be not <code>null</code>.
+ * @return The tree viewer label provider instance.
+ */
+ protected abstract ILabelProvider doCreateTreeViewerLabelProvider(TreeViewer viewer);
+
+ /**
+ * Creates the tree viewer content provider instance.
+ *
+ * @param viewer The tree viewer. Must be not <code>null</code>.
+ * @return The tree viewer content provider instance.
+ */
+ protected abstract ITreeContentProvider doCreateTreeViewerContentProvider(TreeViewer viewer);
+
+ /**
+ * Creates the tree viewer comparator instance.
+ *
+ * @param viewer The tree viewer. Must be not <code>null</code>.
+ * @return The tree viewer comparator instance or <code>null</code> to turn of sorting.
+ */
+ protected ViewerComparator doCreateTreeViewerComparator(TreeViewer viewer) {
+ assert viewer != null;
+ return null;
+ }
+
+ /**
+ * Creates a new selection changed listener instance.
+ *
+ * @param viewer The tree viewer. Must be not <code>null</code>.
+ * @return The selection changed listener instance.
+ */
+ protected abstract ISelectionChangedListener doCreateTreeViewerSelectionChangedListener(TreeViewer viewer);
+
+ /**
+ * Create the context menu and toolbar groups.
+ *
+ * @param viewer The tree viewer instance. Must not be <code>null</code>.
+ */
+ protected void createContributionItems(TreeViewer viewer) {
+ assert viewer != null;
+
+ // Create the menu manager
+ MenuManager manager = new MenuManager("#PopupMenu"); //$NON-NLS-1$
+ // Attach the menu listener
+ manager.addMenuListener(new IMenuListener() {
+ public void menuAboutToShow(IMenuManager manager) {
+ manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
+ }
+ });
+ // All items are removed when menu is closing
+ manager.setRemoveAllWhenShown(true);
+ // Associated with the tree
+ viewer.getTree().setMenu(manager.createContextMenu(viewer.getTree()));
+
+ // Register the context menu at the parent workbench part site.
+ if (getParentPart() != null && getParentPart().getSite() != null && getContextMenuId() != null) {
+ getParentPart().getSite().registerContextMenu(getContextMenuId(), manager, viewer);
+ }
+
+ // The toolbar is a bit more complicated as we want to have the
+ // toolbar placed within the section title.
+ createToolbarContributionItem(viewer);
+ }
+
+ /**
+ * Returns the context menu id.
+ *
+ * @return The context menu id.
+ */
+ protected abstract String getContextMenuId();
+
+ /**
+ * Creates the toolbar within the section parent of the given tree viewer.
+ *
+ * @param viewer The tree viewer instance. Must not be <code>null</code>.
+ */
+ protected void createToolbarContributionItem(TreeViewer viewer) {
+ assert viewer != null;
+
+ // Determine the section parent from the tree viewer
+ Composite parent = viewer.getTree().getParent();
+ while (parent != null && !(parent instanceof Section)) {
+ parent = parent.getParent();
+ }
+
+ // We are done here if we cannot find a section parent or the parent is disposed
+ if (parent == null || parent.isDisposed()) {
+ return;
+ }
+
+ // Create the toolbar control
+ ToolBar toolbar = new ToolBar(parent, SWT.FLAT | SWT.HORIZONTAL | SWT.RIGHT);
+
+ // The cursor within the toolbar shall change to an hand
+ final Cursor handCursor = new Cursor(parent.getDisplay(), SWT.CURSOR_HAND);
+ toolbar.setCursor(handCursor);
+ // Cursor needs to be explicitly disposed
+ toolbar.addDisposeListener(new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ if ((handCursor != null) && (handCursor.isDisposed() == false)) {
+ handCursor.dispose();
+ }
+ }
+ });
+
+ // If the parent composite is a forms section, set the toolbar
+ // as text client to the section header
+ if (parent instanceof Section) {
+ Section section = (Section)parent;
+ // Set the toolbar as text client
+ section.setTextClient(toolbar);
+ }
+
+ // create the toolbar items
+ createToolBarItems(toolbar);
+ }
+
+ /**
+ * Create the toolbar items to be added to the toolbar. Override
+ * to add the wanted toolbar items.
+ * <p>
+ * <b>Note:</b> The toolbar items are added from left to right.
+ *
+ * @param toolbar The toolbar to add the toolbar items too. Must not be <code>null</code>.
+ */
+ protected void createToolBarItems(ToolBar toolbar) {
+ assert toolbar != null;
+ }
+
+ /**
+ * Returns the viewer instance.
+ *
+ * @return The viewer instance or <code>null</code>.
+ */
+ public Viewer getViewer() {
+ return fViewer;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
+ */
+ @Override
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public Object getAdapter(Class adapter) {
+ if (Viewer.class.isAssignableFrom(adapter)) {
+ // We have to double check if our real viewer is assignable to
+ // the requested Viewer class.
+ Viewer viewer = getViewer();
+ if (!adapter.isAssignableFrom(viewer.getClass())) {
+ viewer = null;
+ }
+ return viewer;
+ }
+
+ return super.getAdapter(adapter);
+ }
+
+}
diff --git a/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/trees/TreeViewerComparator.java b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/trees/TreeViewerComparator.java
new file mode 100644
index 000000000..b24a4b2af
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tm.te.ui/src/org/eclipse/tm/te/ui/trees/TreeViewerComparator.java
@@ -0,0 +1,178 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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:
+ * Uwe Stieber (Wind River) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tm.te.ui.trees;
+
+import java.util.Arrays;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.tm.te.ui.AbstractViewerComparator;
+
+
+/**
+ * Target Explorer: Common tree control viewer comparator implementation.
+ */
+public class TreeViewerComparator extends AbstractViewerComparator {
+ private final ILabelProvider fLabelProvider;
+
+ /**
+ * Constructor.
+ *
+ * @param viewer The parent viewer. Must be not <code>null</code>.
+ * @param labelProvider The label provider. Must be not <code>null</code>.
+ */
+ public TreeViewerComparator(Viewer viewer, ILabelProvider labelProvider) {
+ super(viewer);
+ assert labelProvider != null;
+ fLabelProvider = labelProvider;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tm.te.ui.controls.AbstractViewerComparator#doDetermineInverter(org.eclipse.jface.viewers.Viewer)
+ */
+ @Override
+ protected int doDetermineInverter(Viewer viewer) {
+ int inverter = 1;
+
+ // Viewer must be of type TreeViewer and the tree must not be disposed yet
+ if (viewer instanceof TreeViewer && ((TreeViewer)viewer).getTree() != null) {
+ Tree tree = ((TreeViewer)viewer).getTree();
+ if (!tree.isDisposed() && tree.getSortDirection() == SWT.DOWN) inverter = -1;
+ }
+
+ return inverter;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tm.te.ui.controls.AbstractViewerComparator#doGetText(java.lang.Object, int)
+ */
+ @Override
+ protected String doGetText(Object node, int index) {
+ if (node != null && fLabelProvider != null) {
+ return fLabelProvider.getText(node);
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tm.te.ui.controls.AbstractViewerComparator#doGetSortColumnLabel(org.eclipse.jface.viewers.Viewer)
+ */
+ @Override
+ protected String doGetSortColumnLabel(Viewer viewer) {
+ // Viewer must be of type TreeViewer and the tree must not be disposed yet
+ if (viewer instanceof TreeViewer && ((TreeViewer)viewer).getTree() != null && !((TreeViewer)viewer).getTree().isDisposed()) {
+ Tree tree = ((TreeViewer)viewer).getTree();
+ return tree.getSortColumn() != null ? tree.getSortColumn().getText() : ""; //$NON-NLS-1$
+ }
+ return ""; //$NON-NLS-1$
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tm.te.ui.controls.AbstractViewerComparator#doGetSortColumnIndex(org.eclipse.jface.viewers.Viewer)
+ */
+ @Override
+ protected int doGetSortColumnIndex(Viewer viewer) {
+ if (viewer instanceof TreeViewer && ((TreeViewer)viewer).getTree() != null && !((TreeViewer)viewer).getTree().isDisposed()) {
+ Tree tree = ((TreeViewer)viewer).getTree();
+ return tree.getSortColumn() != null ? Arrays.asList(tree.getColumns()).indexOf(tree.getSortColumn()) : -1;
+ }
+ return -1;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tm.te.ui.controls.AbstractViewerComparator#doCompare(java.lang.Object, java.lang.Object, java.lang.String, int, int)
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ protected int doCompare(Object node1, Object node2, String sortColumn, int index, int inverter) {
+ if (node1 == null && node2 == null) return 0;
+ if (node1 != null && node2 == null) return 1;
+ if (node1 == null && node2 != null) return -1;
+
+ // Get the labels
+ String text1 = doGetText(node1, index);
+ String text2 = doGetText(node2, index);
+
+ // Normalize labels
+ if (text1 == null) text1 = ""; //$NON-NLS-1$
+ if (text2 == null) text2 = ""; //$NON-NLS-1$
+
+ // The tree sorts not strictly alphabetical. First comes entries starting with numbers,
+ // second entries starting with uppercase and than all the rest. Additional, if a label contains
+ // uppercase characters, it is sorted in before any labels being lowercase only.
+ if (text1.length() > 0 && text2.length() > 0) {
+ // Get the first characters of both
+ char c1 = text1.charAt(0);
+ char c2 = text2.charAt(0);
+
+ if (Character.isDigit(c1) || Character.isDigit(c2)) {
+ // Check on the differences. If both are digits, the standard compare will do it
+ if (Character.isDigit(c1) && !Character.isDigit(c2)) return -1 * inverter;
+ if (!Character.isDigit(c1) && Character.isDigit(c2)) return 1 * inverter;
+ }
+
+ if (Character.isUpperCase(c1) || Character.isUpperCase(c2)) {
+ // Check on the differences. If both are uppercase characters, the standard compare will do it
+ if (Character.isUpperCase(c1) && !Character.isUpperCase(c2)) return -1 * inverter;
+ if (!Character.isUpperCase(c1) && Character.isUpperCase(c2)) return 1 * inverter;
+ }
+
+ Matcher m1 = Pattern.compile("(\\D+)(\\d+)").matcher(text1); //$NON-NLS-1$
+ Matcher m2 = Pattern.compile("(\\D+)(\\d+)").matcher(text2); //$NON-NLS-1$
+ if (m1.matches() && m2.matches()) {
+ String p11 = m1.group(1);
+ String p12 = m1.group(2);
+
+ String p21 = m2.group(1);
+ String p22 = m2.group(2);
+
+ if (p11 != null && p11.equals(p21)) {
+ // Compare the second parts as number
+ try {
+ int result = 0;
+ long l1 = Long.parseLong(p12);
+ long l2 = Long.parseLong(p22);
+
+ if (l1 > l2) result = 1;
+ if (l1 < l2) result = -1;
+
+ return result;
+ } catch (NumberFormatException e) { /* ignored on purpose */ }
+ }
+ }
+
+ if (text1.matches(".*[A-Z]+.*") || text2.matches(".*[A-Z]+.*")) { //$NON-NLS-1$ //$NON-NLS-2$
+ if (text1.matches(".*[A-Z]+.*") && !text2.matches(".*[A-Z]+.*")) return -1 * inverter; //$NON-NLS-1$ //$NON-NLS-2$
+ if (!text1.matches(".*[A-Z]+.*") && text2.matches(".*[A-Z]+.*")) return 1 * inverter; //$NON-NLS-1$ //$NON-NLS-2$
+
+ // Additionally, it even depends on the position of the first uppercase
+ // character if both strings contains them :-(
+ int minLength = Math.min(text1.length(), text2.length());
+ for (int i = 0; i < minLength; i++) {
+ char ch1 = text1.charAt(i);
+ char ch2 = text2.charAt(i);
+
+ if (Character.isUpperCase(ch1) && !Character.isUpperCase(ch2)) return -1 * inverter;
+ if (!Character.isUpperCase(ch1) && Character.isUpperCase(ch2)) return 1 * inverter;
+ // If both are uppercase, we break the loop and compare as usual
+ if (Character.isUpperCase(ch1) && Character.isUpperCase(ch2)) break;
+ }
+ }
+ }
+
+ // Compare the text alphabetical
+ return getComparator().compare(text1, text2) * inverter;
+ }
+}

Back to the top