/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.designer.ui.common.util;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.util.WrappedException;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.resource.JFaceColors;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Sash;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.ElementTreeSelectionDialog;
import org.eclipse.ui.dialogs.ISelectionStatusValidator;
import org.eclipse.ui.forms.HyperlinkSettings;
import org.eclipse.ui.forms.widgets.FormText;
import org.eclipse.ui.model.WorkbenchContentProvider;
import org.eclipse.ui.model.WorkbenchLabelProvider;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.teiid.core.designer.util.CoreArgCheck;
import org.teiid.core.designer.util.CoreStringUtil;
import org.teiid.core.designer.util.I18nUtil;
import org.teiid.core.designer.util.StringUtilities;
import org.teiid.designer.core.ModelerCore;
import org.teiid.designer.ui.common.InternalUiConstants;
import org.teiid.designer.ui.common.UiConstants;
import org.teiid.designer.ui.common.widget.ITreeViewerController;
/**
* @since 8.0
*/
public final class WidgetUtil implements
InternalUiConstants.Widgets,
CoreStringUtil.Constants,
UiConstants {
// ============================================================================================================================
// Constants
private static final String I18N_PREFIX = I18nUtil.getPropertyPrefix(WidgetUtil.class);
private static final String FOLDER_SELECTION_DIALOG_TITLE = getString("folderSelectionDialogTitle"); //$NON-NLS-1$
private static final String CONFIRM_OVERWRITE_MESSAGE_ID = "confirmOverwriteMessage"; //$NON-NLS-1$
private static final String ERROR_CAUSE_MESSAGE_ID = "errorCauseMessage"; //$NON-NLS-1$
private static final String FILE_EXISTS_MESSAGE_ID = "fileExistsMessage"; //$NON-NLS-1$
private static final String FILE_EXISTS_BUT_NOT_IN_WORKSPACE_MESSAGE_ID = "fileExistsButNotInWorkspaceMessage"; //$NON-NLS-1$
private static final String INVALID_SEVERITY_MESSAGE = getString("invalidSeverityMessage"); //$NON-NLS-1$
private static final String NOT_RADIO_BUTTON_MESSAGE = getString("notRadioButtonMessage"); //$NON-NLS-1$
private static final String FOLDER_SELECTION_DIALOG_MESSAGE = getString("folderSelectionDialogMessage"); //$NON-NLS-1$
private static final int COMBO_ITEM_LIMIT = 15;
public static final String A_END_TAG = "</a>"; //$NON-NLS-1$
public static final String A_START_TAG = "<a>"; //$NON-NLS-1$
public static final String FORM_TEXT_END_TAG = "</p></html>"; //$NON-NLS-1$
public static final String FORM_TEXT_START_TAG = "<html><p>"; //$NON-NLS-1$
public static final int TEXT_COLOR_DEFAULT = 0;
public static final int TEXT_COLOR_BLUE = 1;
private static final String EMPTY_STR = ""; //$NON-NLS-1$
// ============================================================================================================================
// Static Methods
/**
* @since 4.0
*/
public static boolean confirmOverwrite(final File file) {
return showConfirmation(getString(CONFIRM_OVERWRITE_MESSAGE_ID, getFileExistsMessage(file)));
}
/**
* Stores the enabled state of the specified controls, and their descendents if they are {@link Composite composites}, in the
* specified map, then disables these controls and, if any, their descendents. The controls may be later
* {@link #restore(Map) enabled}such that their descendents, if any, will be restored to their original enabled states.
*
* @param controls
* A list of controls to disable; may not be null.
* @return A map of the original enabled states of the controls and, if any, their descendents; never null.
* @since 4.0
*/
public static Map disable(final Control[] controls) {
CoreArgCheck.isNotNull(controls);
final Map map = new HashMap(0);
for (int ndx = controls.length; --ndx >= 0;) {
final Control ctrl = controls[ndx];
CoreArgCheck.isNotNull(ctrl);
disable(ctrl, map);
}
return map;
}
/**
* @since 4.0
*/
private static void disable(final Control control,
final Map map) {
if (!map.containsKey(control)) {
map.put(control, new Boolean(control.getEnabled()));
}
control.setEnabled(false);
if (control instanceof Composite) {
final Control[] ctrls = ((Composite)control).getChildren();
for (int ndx = ctrls.length; --ndx >= 0;) {
disable(ctrls[ndx], map);
}
}
}
public static void disableFormText(FormText formText) {
HyperlinkSettings settings = formText.getHyperlinkSettings();
settings.setHyperlinkUnderlineMode(HyperlinkSettings.UNDERLINE_NEVER);
settings.setForeground(formText.getForeground());
settings.setActiveForeground(formText.getForeground());
formText.redraw();
}
/**
* Convenience method that simply calls {@link #disable(Control[])}, passing the specified container in a single element
* array.
*
* @param container
* A container to disable; may not be null.
* @return A map of the original enabled states of the container and, if any, its descendents; never null.
* @since 4.0
*/
public static Map disable(final Composite container) {
CoreArgCheck.isNotNull(container);
return disable(new Control[] {
container
});
}
/**
* Enables the specified controls and, if any, their descendents.
*
* @param controls
* A list of controls to enable; may not be null.
* @since 4.0
*/
public static void enable(final Control[] controls) {
CoreArgCheck.isNotNull(controls);
for (int ndx = controls.length; --ndx >= 0;) {
final Control ctrl = controls[ndx];
CoreArgCheck.isNotNull(ctrl);
if (ctrl instanceof Composite) {
enable(((Composite)ctrl).getChildren());
}
ctrl.setEnabled(true);
}
}
/**
* Convenience method that simply calls {@link #enable(Control[])}, passing the specified container in a single element
* array.
*
* @param container
* A container to enable; may not be null.
* @since 4.0
*/
public static void enable(final Composite container) {
enable(new Control[] {
container
});
}
public static void enableFormText(FormText formText) {
HyperlinkSettings settings = formText.getHyperlinkSettings();
settings.setHyperlinkUnderlineMode(HyperlinkSettings.UNDERLINE_ALWAYS);
settings.setForeground(JFaceColors.getHyperlinkText(formText.getDisplay()));
settings.setActiveForeground(JFaceColors.getActiveHyperlinkText(formText.getDisplay()));
formText.redraw();
}
/**
* @return The TreeItem in the specified Tree containing the specified node, or null if not found.
* @since 4.1
*/
public static TreeItem findTreeItem(final Object node,
final Tree tree) {
CoreArgCheck.isNotNull(node);
CoreArgCheck.isNotNull(tree);
return findTreeItem(node, tree.getItems());
}
/**
* @return The TreeItem in the Tree controlled by the specified TreeViewer containing the specified node, or null if not
* found.
* @since 4.1
*/
public static TreeItem findTreeItem(final Object node,
final TreeViewer viewer) {
CoreArgCheck.isNotNull(viewer);
return findTreeItem(node, viewer.getTree());
}
/**
* @since 4.1
*/
private static TreeItem findTreeItem(final Object node,
final TreeItem[] items) {
for (int ndx = items.length; --ndx >= 0;) {
TreeItem item = items[ndx];
if (node == item.getData()) {
return item;
}
// Search children
if (item.getItemCount() > 0) {
item = findTreeItem(node, item.getItems());
if (item != null) {
return item;
}
}
}
return null;
}
/**
* @param prefix
* The prefix of the message to display.
* @param status
* The status containing the cause of the error or warning.
* @return A message that includes the specified prefix, followed by a statement to see the log for details, and finally
* followed by the specified status' message.
* @since 4.0
*/
public static String getCauseMessage(final String prefix,
final IStatus status) {
return getString(ERROR_CAUSE_MESSAGE_ID, prefix, status.getMessage());
}
/**
* @param prefix
* The prefix of the message to display.
* @param throwable
* The throwable containing the cause of the error or warning.
* @return A message that includes the specified prefix, followed by a statement to see the log for details, and finally
* followed by the specified throwable's message.
* @since 4.0
*/
public static String getCauseMessage(final String prefix,
final Throwable throwable) {
return getString(ERROR_CAUSE_MESSAGE_ID, prefix, throwable.getLocalizedMessage());
}
/**
* @since 4.0
*/
public static int getCheckedState(final TreeItem item) {
CoreArgCheck.isNotNull(item);
final Object obj = item.getData(CHECKED_STATE_PROPERTY);
if (obj == null || !(obj instanceof Integer)) {
return UNCHECKED;
}
return ((Integer)obj).intValue();
}
/**
* Stores the checked state of all of the TreeItems in the returned Map. The Map can later be used by setCheckedStates()
* to restore the checked state as it was when getCheckedStates() was called. If you wish to use the Map directly, its keys
* are TreeItem.getData(), and its values are Booleans. These utility methods are necessary because, unlike
* CheckboxTreeViewer, TreeViewer does not have this functionality itself.
*
* @param ttvViewer the TreeViewer whose checked states we wish to capture
* @return A map of the current checked state for all the nodes in the tree. {@link #setCheckedStates( TreeViewer, Map )}
* @since 4.2
*/
public static Map getCheckedStates(TreeViewer tvViewer) {
HashMap hmItemCheckedStates = new HashMap();
// get roots
TreeItem[] tiItems = tvViewer.getTree().getItems();
// start the recursive process on each root
for (int i = 0; i < tiItems.length; i++) {
TreeItem tiTemp = tiItems[i];
getCheckedStates(hmItemCheckedStates, tiTemp);
}
return hmItemCheckedStates;
}
private static void getCheckedStates(Map mapItemCheckedStates,
TreeItem tiItem) {
// process this item
mapItemCheckedStates.put(tiItem.getData(), new Boolean(tiItem.getChecked()));
// call this method on its children
TreeItem[] tiChildren = tiItem.getItems();
for (int i = 0; i < tiChildren.length; i++) {
getCheckedStates(mapItemCheckedStates, tiChildren[i]);
}
}
/**
* @param file
* An existing file.
* @return A standard "File already exists" message for the specified file.
* @since 4.0
*/
public static String getFileExistsMessage(final File file) {
return getString(FILE_EXISTS_MESSAGE_ID, file.getAbsolutePath());
}
/**
* @param file
* An existing file.
* @return A standard "File already exists" message for the specified file.
* @since 4.0
*/
public static String getFileExistsMessage(final IFile file) {
return getString(FILE_EXISTS_MESSAGE_ID, file.getFullPath().makeRelative());
}
/**
* Display this message when a file exists on the file system but not in the workspace.
*
* @param file An existing file.
* @return A standard "File already exists" message for the specified file.
* @since 4.0
*/
public static String getFileExistsButNotInWorkspaceMessage( final IFile file ) {
return getString(FILE_EXISTS_BUT_NOT_IN_WORKSPACE_MESSAGE_ID, file.getFullPath().makeRelative());
}
/**
* Returns the most appropriate displayable message contained within the specified error, analyzing embedded or chained errors
* when appropriate.
*
* @since 4.0
*/
public static String getMessage(Throwable error) {
CoreArgCheck.isNotNull(error);
if (error instanceof WrappedException) {
final Throwable err = ((WrappedException)error).exception();
if (err != null) {
error = err;
}
} else if (error instanceof InvocationTargetException) {
final Throwable err = ((InvocationTargetException)error).getTargetException();
if (err != null) {
error = err;
}
}
final String msg = error.getLocalizedMessage();
return (msg == null ? error.toString() : msg);
}
/**
* @since 4.0
*/
public static boolean hasState(final int state,
final int queriedState) {
return ((state & queriedState) == queriedState);
}
/**
* Indicates if the given <code>Widget</code> has the given style.
*
* @param widget
* the widget being checked
* @return <code>true</code> if widget has the given style; <code>false</code> otherwise.
* @since 4.0
*/
public static boolean hasStyle(final Widget widget,
final int style) {
CoreArgCheck.isNotNull(widget);
return hasState(widget.getStyle(), style);
}
public static Color getDarkBlueColor() {
return getSystemColor(SWT.COLOR_DARK_BLUE);
}
public static Color getReadOnlyBackgroundColor() {
return getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW);
}
public static Color getSystemColor(int colorId) {
return Display.getCurrent().getSystemColor(colorId);
}
public static void colorizeWidget(Control control, int colorStyle, boolean readOnly) {
if( colorStyle == TEXT_COLOR_BLUE ) {
control.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_DARK_BLUE));
}
if( readOnly ) {
control.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW));
}
}
/**
* Initializes the specified panel with a layout and layout data.
*
* @param panel
* @param gridStyle
* @param span
* @param columns
* @since 5.0.1
*/
public static void initializePanel(Composite panel,
int gridStyle,
int span,
int columns) {
final GridData gridData = new GridData(gridStyle);
gridData.horizontalSpan = span;
panel.setLayoutData(gridData);
final GridLayout layout = new GridLayout(columns, false);
if (WidgetUtil.hasStyle(panel, SWT.NO_TRIM)) {
layout.marginWidth = layout.marginHeight = 0;
}
panel.setLayout(layout);
}
/**
* Initializes dialog settings for the specified object.
*
* @return Dialog settings for the specified object; never null;
* @since 4.0
*/
public static IDialogSettings initializeSettings(final Object object,
final AbstractUIPlugin plugin) {
// Set dialog settings, creating section if necessary
final IDialogSettings settings = plugin.getDialogSettings();
final String name = object.getClass().getName();
IDialogSettings section = settings.getSection(name);
if (section == null) {
section = settings.addNewSection(name);
}
return section;
}
/**
* @since 4.0
*/
public static boolean isChecked(final TreeItem item) {
return hasState(getCheckedState(item), CHECKED);
}
/**
* @since 4.0
*/
public static boolean isPartiallyChecked(final TreeItem item) {
return hasState(getCheckedState(item), PARTIALLY_CHECKED);
}
/**
* @since 4.0
*/
public static boolean isUnchecked(final TreeItem item) {
return hasState(getCheckedState(item), UNCHECKED);
}
/**
* @since 4.0
*/
public static void pack(final TableViewer viewer) {
pack(viewer.getTable());
}
/**
* @since 4.0
*/
public static void pack(final Table table) {
final TableColumn[] cols = table.getColumns();
for (int ndx = 0; ndx < cols.length; ++ndx) {
cols[ndx].pack();
}
}
/**
* Removes any missing filesystem resources from the specified <code>IDialogSettings</code> for the given key. All item
* values found for the specified key will be considered to be a resource name. If that name does not represent a current
* filesystem resource it is removed from the list. Ideally this method should be called prior to using the settings in a
* dialog.
*
* @param settings
* The dialog settings needing to remove missing resource values from; may not be null.
* @param id
* The identifier of the text array containing resources; may not be null.
* @since 4.1
*/
public static void removeMissingResources(final IDialogSettings settings,
final String id) {
CoreArgCheck.isNotNull(settings);
CoreArgCheck.isNotNull(id);
String[] resourceItems = settings.getArray(id);
// check to see if resources still exist
if ((resourceItems != null) && (resourceItems.length > 0)) {
List newItems = new ArrayList(Arrays.asList(resourceItems));
File tmp = null;
Iterator itr = newItems.iterator();
while (itr.hasNext()) {
String sItem = (String)itr.next();
if (sItem == null) {
itr.remove();
continue;
}
tmp = new File(sItem);
if (!tmp.exists()) {
itr.remove();
}
}
// modify setting if needed
if (resourceItems.length != newItems.size()) {
// convert back to string array
String[] resourceNames = new String[newItems.size()];
for (int ndx = resourceNames.length; --ndx >= 0;) {
resourceNames[ndx] = (String)newItems.get(ndx);
}
// persist items
settings.put(id, resourceNames);
}
}
}
/**
* Restores the controls stored as keys in the specified map to their original enabled states, which were stored as values in
* the map when previously {@link #disable(Control[]) disabled}. Note that normally the specified map should be set to null
* in the calling code after calling this method, so that subsequent calls to this methods will be skipped if the map is
* determined to be null by the calling code. This procedure, thus, prevents this method from being called unless a the
* controls in question have been previously {@link #disable(Control[]) disabled}.
*
* @param A
* map of controls to their original enabled states; may not be null.
* @since 4.0
*/
public static void restore(final Map map) {
CoreArgCheck.isNotNull(map);
for (final Iterator iter = map.entrySet().iterator(); iter.hasNext();) {
final Entry entry = (Entry)iter.next();
((Control)entry.getKey()).setEnabled(((Boolean)entry.getValue()).booleanValue());
}
}
/**
* Adds the text from the specified Combo identified by the specified ID to the text array in the specified settings, if the
* text doesn't already exist in that array. A new array will be created if one doesn't exist. If the item count is greater
* than the default limit (@link #COMBO_ITEM_LIMIT), items will be deleted.
*
* @param settings
* The dialog settings in which to add the text; may not be null.
* @param id
* The identifier of the text array within the specified settings; may not be null.
* @param combo
* The Combo from which the text should be added; may not be null.
* @since 4.0
*/
public static void saveSettings(final IDialogSettings settings,
final String id,
final Combo combo) {
saveSettings(settings, id, combo, COMBO_ITEM_LIMIT);
}
/**
* Saves a <code>Combo</code>'s items in the specified dialog settings. If the number of items in the <code>Combo</code>
* is greater than the specified limit, least recently used items are deleted.
*
* @param theSettings
* the dialog settings being saved; may not be null.
* @param theId
* the settings identifier being saved; may not be null.
* @param theCombo
* the <code>Combo</code> whose items are being saved; may not be null.
* @param theLimit
* the max number of values to save; must be greater than zero.
*/
public static void saveSettings(final IDialogSettings theSettings,
final String theId,
final Combo theCombo,
final int theLimit) {
CoreArgCheck.isNotNull(theSettings);
CoreArgCheck.isNotNull(theId);
CoreArgCheck.isNotNull(theCombo);
CoreArgCheck.isPositive(theLimit);
String currentValue = theCombo.getText();
// add current value if necessary
if ((currentValue.length() > 0) && (theCombo.indexOf(currentValue) == -1)) {
theCombo.add(currentValue);
}
// prune values if over the limit
if (theCombo.getItemCount() > theLimit) {
theCombo.remove(0, (theCombo.getItemCount() - theLimit - 1));
}
// save settings
theSettings.put(theId, theCombo.getItems());
}
/**
* Selects and reveals the specified object in the specified viewer only if that object is not the one and only object
* currently selected.
*
* @param object
* @param viewer
* @since 5.0.1
*/
public static void select(Object object,
Viewer viewer) {
if (object != null) {
IStructuredSelection selection = (IStructuredSelection)viewer.getSelection();
if (selection.size() != 1 || selection.getFirstElement() != object) {
viewer.setSelection(new StructuredSelection(object), true);
}
}
}
/**
* Selects the given button. Also deselects the first radio button sibling it finds that is selected. The deselection event is
* fired first and then the selection event. If the given button is already selected no selection event is fired.
*
* @param theButton
* the button being selected
* @throws IllegalArgumentException
* if button is <code>null</code> or if button does not have radio style
*/
public static void selectRadioButton(final Button button) {
CoreArgCheck.isNotNull(button);
CoreArgCheck.isTrue(hasStyle(button, SWT.RADIO), NOT_RADIO_BUTTON_MESSAGE);
// first deselect currently selected button
Composite parent = button.getParent();
Control[] kids = parent.getChildren();
for (int i = 0; i < kids.length; i++) {
if ((kids[i] != button)
&& (kids[i] instanceof Button)
&& hasStyle(kids[i], SWT.RADIO)
&& ((Button)kids[i]).getSelection()) {
// deselect and fire event
final Button oldButton = (Button)kids[i];
oldButton.setSelection(false);
oldButton.notifyListeners(SWT.Selection, new Event());
break; // assume only one selected
}
}
// only fire selection if not already selected
if (!button.getSelection()) {
// select and fire event
button.setSelection(true);
button.notifyListeners(SWT.Selection, new Event());
}
}
/**
* @since 4.0
*/
public static void setChecked(final TreeItem item,
final boolean checked,
final boolean selected,
final ITreeViewerController controller) {
setCheckedState(item, checked ? CHECKED : UNCHECKED, selected, controller);
}
/**
* @since 4.0
*/
public static void setCheckedState(final TreeItem item,
final int state,
final boolean selected,
final ITreeViewerController controller) {
CoreArgCheck.isNotNull(item);
CoreArgCheck.isNotNull(controller);
item.setData(CHECKED_STATE_PROPERTY, new Integer(state));
controller.update(item, selected);
}
/**
* Applies the 'checked states' in the Map to all of the TreeItems in the Table Tree managed by the TreeViewer.
* These utility methods are needed because, unlike CheckboxTreeViewer, TreeViewer does not already have this
* functionality.
*
* @param ttvViewer
* the TreeViewer whose checked states we wish to restore
* @param mapItemCheckStates
* the Map containing the checked state of each TreeItem as it was when the Map was created by
* setCheckedStates(). {@link #getCheckedStates( TreeViewer )}
* @since 4.2
*/
public static void setCheckedStates(TreeViewer tvViewer,
Map mapItemCheckedStates) {
// get roots
TreeItem[] tiItems = tvViewer.getTree().getItems();
// start the recursive process on each root
for (int i = 0; i < tiItems.length; i++) {
TreeItem tiTemp = tiItems[i];
setCheckedStates(mapItemCheckedStates, tiTemp);
}
}
private static void setCheckedStates(Map mapItemCheckedStates,
TreeItem tiItem) {
// process this item
Boolean BChecked = (Boolean)mapItemCheckedStates.get(tiItem.getData());
tiItem.setChecked(BChecked.booleanValue());
// call this method on its children
TreeItem[] tiChildren = tiItem.getItems();
for (int i = 0; i < tiChildren.length; i++) {
setCheckedStates(mapItemCheckedStates, tiChildren[i]);
}
}
/**
* @since 4.0
*/
public static void setComboItems(final Combo combo,
final List items) {
setComboItems(combo, items, null);
}
/**
* @since 4.0
*/
public static void setComboItems(final Combo combo,
final List items,
final ILabelProvider provider) {
setComboItems(combo, items, provider, false);
}
/**
* @since 4.0
*/
public static void setComboItems(final Combo combo,
final Collection items,
final ILabelProvider provider,
final boolean sort) {
CoreArgCheck.isNotNull(combo);
setComboItems(combo, items, provider, sort, combo.getText());
}
/**
* @since 4.1
*/
public static void setComboItems(final Combo combo,
final Collection items,
final ILabelProvider provider,
final boolean sort,
final String selection) {
CoreArgCheck.isNotNull(combo);
CoreArgCheck.isNotNull(items);
combo.removeAll();
List<String> itemStrings = new ArrayList<String>(items.size());
for( Object item : items ) {
final String text = (provider == null ? item.toString() : provider.getText(item));
itemStrings.add(text);
}
List<String> sortedItems = new ArrayList<String>();
sortedItems.addAll(itemStrings);
Collections.sort(sortedItems);
combo.setItems((String[]) sortedItems.toArray(new String[0]));
if ((selection != null) && (selection.length() > 0)) {
combo.setText(selection);
}
}
/**
* @since 4.0
*/
public static void setComboText(final Combo combo,
final Object selection) {
setComboText(combo, selection, null);
}
/**
* @since 4.0
*/
public static void setComboText(final Combo combo,
final Object selection,
final ILabelProvider provider) {
setComboText(combo, selection, provider, false);
}
/**
* @param combo
* never null.
* @param selection
* may be null, which is converted to an empty string.
* @param provider
* may be null.
* @param add
* True if the specified selection should be added to the Combo's list if not present.
* @since 4.0
*/
public static void setComboText(final Combo combo,
Object selection,
final ILabelProvider provider,
final boolean add) {
CoreArgCheck.isNotNull(combo);
// Get string value of selection, using provider if provided
final String text = (selection == null ? EMPTY_STRING : (provider == null ? selection.toString()
: provider.getText(selection)));
// Add selection to list if requested and not already present
if (add) {
final ArrayList items = new ArrayList(Arrays.asList(combo.getItems()));
if (!items.contains(text)) {
items.add(text);
setComboItems(combo, items, provider);
}
}
// Set text on Combo
combo.setText(text);
}
/**
* Set the value of a {@link Text}'s text safely.
* If the textValue is null then an empty string
* is set instead.
*
* @param text widget
* @param textValue value to be set as text
*/
public static void setText(Text text, String textValue) {
if (text == null)
return;
if (textValue == null)
textValue = EMPTY_STR;
text.setText(textValue);
}
/**
* Sets the layout data to be {{@link GridData } with standard height and width suitable for display in a dialog.
*
* @param button the button whose layout data is being set
* @since 5.5.3
*/
public static void setLayoutData( Button button ) {
GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
GC gc = new GC(button);
gc.setFont(button.getFont());
int widthHint = Dialog.convertHorizontalDLUsToPixels(gc.getFontMetrics(), IDialogConstants.BUTTON_WIDTH);
Point minSize = button.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
gd.widthHint = Math.max(widthHint, minSize.x);
button.setLayoutData(gd);
gc.dispose();
}
/**
* Gets the preferred weights of the <code>SashForm</code> based on the preferred size of it's children. Therefore, all the
* children must have been added and completed prior to calling this method.
*
* @param theSash
* the <code>SashForm</code> whose children are being analyzed
* @return <code>null</code> if there are no children, otherwise the preferred weights
* @throws IllegalArgumentException
* if input is <code>null</code>
*/
public static int[] getSashFormWeights(SashForm theSash) {
CoreArgCheck.isNotNull(theSash);
Control[] kids = theSash.getChildren();
boolean vertical = hasStyle(theSash, SWT.VERTICAL);
int[] weights = null;
double total = 0;
if (kids.length > 0) {
List temp = new ArrayList();
for (int i = 0; i < kids.length; i++) {
// a Sash is put between children. these don't need a weight
if (kids[i] instanceof Sash) {
continue;
}
Point point = kids[i].computeSize(SWT.DEFAULT, SWT.DEFAULT);
int size = (vertical) ? point.y : point.x;
temp.add(new Integer(size));
total += size;
}
weights = new int[temp.size()];
for (int i = 0; i < weights.length; i++) {
int size = ((Integer)temp.get(i)).intValue();
weights[i] = (int)Math.round(size / total * 100.0);
}
}
return weights;
}
/**
* @return an workbench shared image representing the status severity or <code>null</code> if not error, warning, or info
* @since 5.5.3
*/
public static Image getStatusImage( IStatus status ) {
if (status.getSeverity() == IStatus.ERROR) {
return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJS_ERROR_TSK);
}
if (status.getSeverity() == IStatus.WARNING) {
return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJS_WARN_TSK);
}
if (status.getSeverity() == IStatus.INFO) {
return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJS_INFO_TSK);
}
return null;
}
/**
* Displays the specified status' message in the appropriate dialog relative to its severity.
*
* @since 4.0
*/
public static void show(final IStatus status) {
CoreArgCheck.isNotNull(status);
switch (status.getSeverity()) {
case IStatus.ERROR: {
showError(status.getMessage());
break;
}
case IStatus.WARNING: {
showWarning(status.getMessage());
break;
}
default: {
showNotification(status.getMessage());
break;
}
}
}
/**
* Displays an error dialog containing a message obtained from passing the specified prefix and throwable to
* {@link #getCauseMessage(String, Throwable)}.
*
* @param prefix
* The prefix of the message to display.
* @param throwable
* The throwable containing the cause of the error or warning.
* @since 4.0
*/
public static void showCause(final String prefix,
final Throwable throwable) {
showCause(prefix, throwable, IStatus.ERROR);
}
/**
* Displays the appropriate dialog according to the specified severity, containing a message obtained from passing the
* specified prefix and throwable to {@link #getCauseMessage(String, Throwable)}.
*
* @param prefix
* The prefix of the message to display.
* @param throwable
* The throwable containing the cause of the error or warning.
* @param severity
* Either {@link IStatus#ERROR}or {@link IStatus#WARNING}.
* @since 4.0
*/
public static void showCause(final String prefix,
final Throwable throwable,
final int severity) {
CoreArgCheck.isNotNull(prefix);
CoreArgCheck.isNotNull(throwable);
CoreArgCheck.isTrue(severity == IStatus.ERROR || severity == IStatus.WARNING, INVALID_SEVERITY_MESSAGE);
show(new Status(severity, PLUGIN_ID, 0, getCauseMessage(prefix, throwable), throwable));
}
/**
* Displays the specified message in a confirmation dialog.
*
* @param message
* The message to display; may not be null.
* @since 4.0
*/
public static boolean showConfirmation(final String message) {
CoreArgCheck.isNotNull(message);
final Shell shell = Display.getCurrent().getActiveShell();
return MessageDialog.openConfirm(shell, CONFIRM_MESSAGE_TITLE, message);
}
/**
* Displays the specified message in an error dialog.
*
* @param message
* The message to display; may not be null.
* @since 4.0
*/
public static void showError(final String message) {
CoreArgCheck.isNotNull(message);
final Shell shell = Display.getCurrent().getActiveShell();
MessageDialog.openError(shell, ERROR_MESSAGE_TITLE, message);
}
/**
* Displays the localize message contained within the specified Throwable in an error dialog.
*
* @param error
* The error containing the message to display; may not be null.
* @since 4.0
*/
public static void showError(final Throwable error) {
showError(getMessage(error));
}
/**
* @param selection
* An initial folder to be selected in the dialog; may be null.
* @param filter
* The filter that will be used to determine which folders will appear in the dialog; may be null. Whether null or
* not, only accessible folders will appear within the dialog or be passed to this filter (if not null).
* @param validator
* The validator that will determine whether the current selection is valid within the dialog caller's context.
* @since 4.0
*/
public static IContainer showFolderSelectionDialog(final IContainer selection,
final ViewerFilter filter,
final ISelectionStatusValidator validator) {
final ViewerFilter baseFilter = new ViewerFilter() {
@Override
public boolean select(final Viewer viewer,
final Object parent,
final Object element) {
return (element instanceof IContainer && ((IContainer)element).isAccessible() && (filter == null || filter.select(viewer,
parent,
element)));
}
};
final Object[] objs = showWorkspaceObjectSelectionDialog(FOLDER_SELECTION_DIALOG_TITLE,
FOLDER_SELECTION_DIALOG_MESSAGE,
false,
selection,
baseFilter,
validator);
return (objs.length == 0 ? null : (IContainer)objs[0]);
}
/**
* Displays the specified message in a notification dialog.
*
* @param message
* The message to display; may not be null.
* @since 4.0
*/
public static void showNotification(final String message) {
CoreArgCheck.isNotNull(message);
final Shell shell = Display.getCurrent().getActiveShell();
MessageDialog.openInformation(shell, NOTIFICATION_MESSAGE_TITLE, message);
}
/**
* Displays the specified message in a warning dialog.
*
* @param message
* The message to display; may not be null.
* @since 4.0
*/
public static void showWarning(final String message) {
CoreArgCheck.isNotNull(message);
final Shell shell = Display.getCurrent().getActiveShell();
MessageDialog.openWarning(shell, WARNING_MESSAGE_TITLE, message);
}
/**
* @param title
* The title of the selection dialog; may not be null.
* @param message
* The message to display within the dialog; may not be null.
* @param allowMultiple
* True if multiple objects may be selected.
* @param selection
* An initial workspace object to be selected in the dialog; may be null.
* @param filter
* A filter specifying which objects will appear in the dialog; may be null.
* @param validator
* A selection validator specifying which objects may be selected in the dialog; may be null.
* @since 4.0
*/
public static Object[] showWorkspaceObjectSelectionDialog(final String title,
final String message,
final boolean allowMultiple,
final Object selection,
final ViewerFilter filter,
final ISelectionStatusValidator validator) {
return showWorkspaceObjectSelectionDialog(title,
message,
allowMultiple,
selection,
filter,
validator,
new WorkbenchLabelProvider());
}
/**
* @param title
* The title of the selection dialog; may not be null.
* @param message
* The message to display within the dialog; may not be null.
* @param allowMultiple
* True if multiple objects may be selected.
* @param selection
* An initial workspace object to be selected in the dialog; may be null.
* @param filter
* A filter specifying which objects will appear in the dialog; may be null.
* @param validator
* A selection validator specifying which objects may be selected in the dialog; may be null.
* @param labelProvder
* A label provider to set on the dialog
* @since 4.0
*/
public static Object[] showWorkspaceObjectSelectionDialog(final String title,
final String message,
final boolean allowMultiple,
final Object selection,
final ViewerFilter filter,
final ISelectionStatusValidator validator,
final ILabelProvider labelProvider) {
final Shell shell = Display.getCurrent().getActiveShell();
final ElementTreeSelectionDialog dlg = new ElementTreeSelectionDialog(shell, labelProvider,
new WorkbenchContentProvider()) {
};
dlg.setAllowMultiple(allowMultiple);
dlg.setTitle(title);
dlg.setMessage(message);
if (filter != null) {
dlg.addFilter(filter);
}
if (validator != null) {
dlg.setValidator(validator);
}
dlg.setInput(ModelerCore.getWorkspace().getRoot());
if (selection != null) {
dlg.setInitialSelection(selection);
}
if (dlg.open() == Window.OK) {
return dlg.getResult();
}
return EMPTY_STRING_ARRAY;
}
/**
* @param title
* The title of the selection dialog; may not be null.
* @param message
* The message to display within the dialog; may not be null.
* @param allowMultiple
* True if multiple objects may be selected.
* @param selection
* An initial workspace object to be selected in the dialog; may be null.
* @param filter
* A filter specifying which objects will appear in the dialog; may be null.
* @param validator
* A selection validator specifying which objects may be selected in the dialog; may be null.
* @param labelProvder
* A label provider to set on the dialog
* @since 4.0
*/
public static Object[] showWorkspaceObjectSelectionDialog(final String title,
final String message,
final boolean allowMultiple,
final Object selection,
final ViewerFilter filter,
final ISelectionStatusValidator validator,
final ILabelProvider labelProvider,
final ITreeContentProvider contentProvider) {
final Shell shell = Display.getCurrent().getActiveShell();
final ElementTreeSelectionDialog dlg = new ElementTreeSelectionDialog(shell, labelProvider, contentProvider) {
};
dlg.setAllowMultiple(allowMultiple);
dlg.setTitle(title);
dlg.setMessage(message);
if (filter != null) {
dlg.addFilter(filter);
}
if (validator != null) {
dlg.setValidator(validator);
}
dlg.setInput(ModelerCore.getWorkspace().getRoot());
if (selection != null) {
dlg.setInitialSelection(selection);
}
if (dlg.open() == Window.OK) {
return dlg.getResult();
}
return EMPTY_STRING_ARRAY;
}
/**
* Utility method to check the changed status of a Text widget
*
* @param widget
* The Text widget; may not be null.
* @param targetValue
* The target string value of the widget
* @return true if the target value is different than current widget value, false otherwise
*/
public static boolean widgetValueChanged(Text widget, String targetValue) {
CoreArgCheck.isNotNull(widget);
return !StringUtilities.equals(widget.getText(), targetValue);
}
/**
* Utility method to check the changed status of a Text widget designed for integer input values
*
* @param widget
* The Text widget; may not be null.
* @param targetValue
* The target integer value of the widget
* @return true if the target value is different than current widget value, false otherwise
*/
public static boolean widgetValueChanged(Text widget, int targetValue) {
CoreArgCheck.isNotNull(widget);
if( widget.getText() == null || widget.getText().length() == 0 ) {
return true;
}
int widgetValue = Integer.valueOf(widget.getText());
return widgetValue != targetValue;
}
/**
* Utility method to check the changed status of a Combo widget
*
* @param widget
* The Combo widget; may not be null.
* @param targetValue
* The target string value of the widget
* @return true if the target value is different than current widget value, false otherwise
*/
public static boolean widgetValueChanged(Combo widget, String targetValue) {
CoreArgCheck.isNotNull(widget);
return !StringUtilities.equals(widget.getText(), targetValue);
}
/**
* Utility method to check the changed status of a Button widget
*
* @param widget
* The Button widget; may not be null.
* @param targetValue
* The target string value of the widget
* @return true if the target value is different than current widget value, false otherwise
*/
public static boolean widgetValueChanged(Button widget, boolean selected) {
CoreArgCheck.isNotNull(widget);
return widget.getSelection() != selected;
}
// ============================================================================================================================
// Static Utility Methods
/**
* @since 4.0
*/
private static String getString(final String id) {
return Util.getString(I18N_PREFIX + id);
}
/**
* @since 4.0
*/
private static String getString(final String id,
final Object parameter) {
return Util.getString(I18N_PREFIX + id, parameter);
}
/**
* @since 4.0
*/
private static String getString(final String id,
final Object parameter1,
final Object parameter2) {
return Util.getString(I18N_PREFIX + id, parameter1, parameter2);
}
// ============================================================================================================================
// Constructors
/**
* Prevents instantiation.
*
* @since 4.0
*/
private WidgetUtil() {
}
}