| /******************************************************************************* |
| * Copyright (c) 2006 Sybase, 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: |
| * Sybase, Inc. - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jst.jsf.common.ui.internal.dialogfield; |
| |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.MouseEvent; |
| import org.eclipse.swt.events.MouseTrackAdapter; |
| import org.eclipse.swt.graphics.Color; |
| import org.eclipse.swt.graphics.FontMetrics; |
| import org.eclipse.swt.graphics.GC; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.ui.forms.events.IHyperlinkListener; |
| import org.eclipse.ui.forms.widgets.FormToolkit; |
| import org.eclipse.ui.forms.widgets.Hyperlink; |
| |
| /** |
| * Base class of all Dialog fields. Dialog fields manage controls together with |
| * the model, independed from the creation time of the widgets. - support for |
| * automated layouting. - enable / disable, set focus a concept of the base |
| * class. DialogField have a label. |
| * |
| * DialogField may be used in two different context: |
| * <ol> |
| * <li> In side dialog. In this case, whenever there is anything change in the |
| * dialog field, such as user type anything, the dialog should listen to the |
| * dialogFieldChanged() events and do things like validation. When user press |
| * the "OK" button, dialog should call getXXX to get the value from the dialog |
| * field and apply them. |
| * <li> In side form based editor or properties view. In this case, whenever |
| * there is anything change in the dialog field, such as user type anything, the |
| * editor/view should listen to the dialogFieldChanged() events and do things |
| * like validation. When user press "Enter" or move the focus out of the control |
| * (finish editing), the dialog field will fire out dialogFieldApplied() events, |
| * and the editor/view should listen to this event and apply the value to the |
| * underlying model. |
| * </ol> |
| * |
| * The basic idea of the DialogField framework is comming from |
| * <code>org.eclipse.jface.preference.FieldEditor</code> and |
| * <code>org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField</code> |
| * |
| * @author mengbo |
| */ |
| public class DialogFieldBase implements DialogField { |
| private Label _label; |
| |
| private Label _requiredLabel; |
| |
| private String _labelText; |
| |
| private IDialogFieldChangeListener _dialogFieldChangeListener; |
| |
| private IDialogFieldApplyListener _dialogFieldApplyListener; |
| |
| private boolean _enabled; |
| |
| private FontMetrics _fontMetrics; |
| |
| private IHyperlinkListener _listener; |
| |
| private Hyperlink _hyperlink; |
| |
| private Map _attachedData; |
| |
| private boolean _isRequired; |
| |
| private String toolTip; |
| |
| /** |
| * default constructor |
| */ |
| public DialogFieldBase() { |
| _enabled = true; |
| _label = null; |
| _requiredLabel = null; |
| _hyperlink = null; |
| _labelText = ""; //$NON-NLS-1$ |
| } |
| |
| /** |
| * this method must be called directly after constructor, in this case, |
| * system will create a hyper link label, and when the hyper link is |
| * clicked, the corresponding method on the listene will be called. A |
| * RuntimeException will throw out if this method is called after the label |
| * has been created. |
| * |
| * @param listener |
| * can't be null |
| */ |
| public void setHyperLink(IHyperlinkListener listener) { |
| if (_label != null) { |
| throw new RuntimeException( |
| "The Label instance does not support the listener"); |
| } |
| this._listener = listener; |
| } |
| |
| /** |
| * Sets the label of the dialog field. |
| */ |
| public void setLabelText(String labeltext) { |
| _labelText = labeltext == null ? "" : labeltext; |
| // if (_isRequired) |
| // { |
| // _labelText = "* " + _labelText; |
| // } |
| // else |
| // { |
| // _labelText = " " + _labelText; |
| // } |
| if (_label != null && !_label.isDisposed()) { |
| _label.setText(_labelText); |
| } else if (_hyperlink != null && !_hyperlink.isDisposed()) { |
| _hyperlink.setText(_labelText); |
| } |
| } |
| |
| /** |
| * @return return the enclosing Shell or null if one cannot be determined |
| */ |
| public Shell getShell() { |
| if (_label != null && !_label.isDisposed()) { |
| return _label.getShell(); |
| } else if (_hyperlink != null && !_hyperlink.isDisposed()) { |
| return _hyperlink.getShell(); |
| } |
| return null; |
| } |
| |
| // ------ change listener |
| |
| /** |
| * Defines the listener for this dialog field. |
| */ |
| public final void setDialogFieldChangeListener( |
| IDialogFieldChangeListener listener) { |
| _dialogFieldChangeListener = listener; |
| } |
| |
| public final void setDialogFieldApplyListener( |
| IDialogFieldApplyListener listener) { |
| _dialogFieldApplyListener = listener; |
| } |
| |
| /** |
| * fire both dialogFieldChanged and dialogFieldApplied events. |
| */ |
| public void dialogFieldChangedAndApplied() { |
| if (_dialogFieldChangeListener != null) { |
| _dialogFieldChangeListener.dialogFieldChanged(this); |
| } |
| if (_dialogFieldApplyListener != null) { |
| _dialogFieldApplyListener.dialogFieldApplied(this); |
| } |
| } |
| |
| /** |
| * fire dialogFieldChanged event. |
| * |
| */ |
| public void dialogFieldChanged() { |
| if (_dialogFieldChangeListener != null) { |
| _dialogFieldChangeListener.dialogFieldChanged(this); |
| } |
| } |
| |
| /** |
| * fire dialogFieldApplied event. |
| * |
| */ |
| public void dialogFieldApplied() { |
| if (_dialogFieldApplyListener != null) { |
| _dialogFieldApplyListener.dialogFieldApplied(this); |
| } |
| } |
| |
| // ------- focus management |
| |
| |
| public boolean setFocus() { |
| return false; |
| } |
| |
| // |
| // /** |
| // * Posts <code>setFocus</code> to the display event queue. |
| // */ |
| // public void postSetFocusOnDialogField(Display display) |
| // { |
| // if (display != null) |
| // { |
| // display.asyncExec(new Runnable() |
| // { |
| // public void run() |
| // { |
| // setFocus(); |
| // } |
| // } |
| // ); |
| // } |
| // } |
| |
| // ------- layout helpers |
| |
| public Control[] doFillIntoGrid(FormToolkit toolkit, Composite parent, |
| int nColumns) { |
| assertEnoughColumns(nColumns); |
| |
| Control label = getLabelControl(toolkit, parent); |
| label.setLayoutData(gridDataForLabel(nColumns)); |
| |
| return new Control[] { label }; |
| } |
| |
| /** |
| * Initializes the computation of horizontal and vertical dialog units based |
| * on the size of current font. |
| * <p> |
| * This method must be called before any of the dialog unit based conversion |
| * methods are called. |
| * </p> |
| * |
| * @param control |
| * a control from which to obtain the current font |
| * @return the font metrics for control |
| */ |
| protected FontMetrics getDialogUnits(Control control) { |
| if (_fontMetrics == null) { |
| // Compute and store a font metric |
| GC gc = new GC(control); |
| gc.setFont(control.getFont()); |
| _fontMetrics = gc.getFontMetrics(); |
| gc.dispose(); |
| } |
| return _fontMetrics; |
| } |
| |
| /** |
| * Returns the number of columns of the dialog field. To be reimplemented by |
| * dialog field implementors. |
| */ |
| public int getNumberOfControls() { |
| return 1; |
| } |
| |
| /** |
| * @param span |
| * @return a new GridData for the horizontal 'span' value |
| */ |
| protected static GridData gridDataForLabel(int span) { |
| GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL); |
| gd.horizontalSpan = span; |
| return gd; |
| } |
| |
| // ------- ui creation |
| |
| /** |
| * Creates or returns the created label widget. |
| * |
| * @param parent |
| * The parent composite or <code>null</code> if the widget has |
| * already been created. |
| */ |
| public Control getLabelControl(FormToolkit _formToolkit, Composite parent) { |
| Control control = null; |
| if ((_label == null || _label.isDisposed()) && (_hyperlink == null || _hyperlink.isDisposed())) { |
| assertCompositeNotNull(parent); |
| |
| String label = null; |
| if (_labelText != null && !"".equals(_labelText)) { |
| //$NON-NLS-1$ |
| label = _labelText; |
| } else { |
| label = "."; |
| } |
| |
| if (_listener == null) { |
| control = createLabel(_formToolkit, parent, label); |
| } else { |
| control = createHyperlink(_formToolkit, parent, label); |
| } |
| /** |
| * if(isRequired) { FontData[] fontData = |
| * parent.getFont().getFontData(); FontData[] newFontData = new |
| * FontData[fontData.length]; for(int i=0; i<fontData.length; i++) { |
| * newFontData[i] = new FontData(fontData[i].getName(), |
| * fontData[i].getHeight(), fontData[i].getStyle() | SWT.BOLD); } |
| * final Font font = new Font(control.getDisplay(),newFontData); |
| * control.setFont(font); control.addDisposeListener(new |
| * DisposeListener() { |
| * |
| * public void widgetDisposed(DisposeEvent e) { font.dispose(); } |
| * }); } else { control.setFont(parent.getFont()); } |
| */ |
| control.setFont(parent.getFont()); |
| control.setEnabled(_enabled); |
| } else { |
| if (_label != null) { |
| control = _label; |
| } else { |
| control = _hyperlink; |
| } |
| } |
| return control; |
| } |
| |
| /** |
| * @param _formToolkit |
| * @param parent |
| * @return get the Label control for required |
| */ |
| public Control getRequiredLabelControl(FormToolkit _formToolkit, |
| Composite parent) { |
| if (_requiredLabel == null || _requiredLabel.isDisposed()) { |
| if (_formToolkit == null) { |
| _requiredLabel = new Label(parent, SWT.LEFT | SWT.WRAP); |
| } else { |
| _requiredLabel = _formToolkit.createLabel(parent, "", SWT.LEFT |
| | SWT.WRAP); |
| _requiredLabel.setForeground(getLabelColor()); |
| } |
| if (_isRequired) { |
| _requiredLabel.setText(DialogFieldResources.getInstance() |
| .getString("DialogFieldBase.Label.RequiredSymbol")); |
| } |
| } |
| return _requiredLabel; |
| } |
| |
| private Control createLabel(FormToolkit _formToolkit, Composite parent, |
| String labelString) { |
| if (_formToolkit == null) { |
| _label = new Label(parent, SWT.LEFT | SWT.WRAP); |
| _label.setText(labelString); |
| } else { |
| _label = _formToolkit.createLabel(parent, labelString, SWT.LEFT |
| | SWT.WRAP); |
| _label.setForeground(getLabelColor()); |
| } |
| return _label; |
| } |
| |
| /** |
| * get color for lable |
| */ |
| private Color getLabelColor() { |
| String osname = System.getProperty("os.name").toLowerCase(); |
| if (osname.startsWith("mac os")) { |
| return Display.getCurrent().getSystemColor( |
| SWT.COLOR_LIST_FOREGROUND); |
| } |
| return Display.getCurrent() |
| .getSystemColor(SWT.COLOR_LIST_SELECTION); |
| } |
| |
| private Control createHyperlink(FormToolkit _formToolkit, Composite parent, |
| String label) { |
| if (_formToolkit == null) { |
| _hyperlink = new Hyperlink(parent, SWT.LEFT | SWT.WRAP); |
| _hyperlink.setForeground(getLabelColor()); |
| _hyperlink.setUnderlined(true); |
| _hyperlink.addMouseTrackListener(new MouseTrackAdapter() { |
| |
| public void mouseEnter(MouseEvent e) { |
| _hyperlink.setForeground(Display.getCurrent() |
| .getSystemColor(SWT.COLOR_BLUE)); |
| } |
| |
| public void mouseExit(MouseEvent e) { |
| _hyperlink.setForeground(getLabelColor()); |
| } |
| }); |
| _hyperlink.setText(label); |
| } else { |
| _hyperlink = _formToolkit.createHyperlink(parent, label, SWT.LEFT |
| | SWT.WRAP); |
| } |
| _hyperlink.addHyperlinkListener(_listener); |
| return _hyperlink; |
| } |
| |
| /** |
| * Creates a spacer control. |
| * @param toolkit |
| * |
| * @param parent |
| * The parent composite |
| * @return a spacer control |
| */ |
| public Control createEmptySpace(FormToolkit toolkit, Composite parent) { |
| return createEmptySpace(toolkit, parent, 1); |
| } |
| |
| /** |
| * Creates a spacer control with the given span. The composite is assumed to |
| * have <code>MGridLayout</code> as layout. |
| * @param toolkit |
| * |
| * @param parent |
| * The parent composite |
| * @param span |
| * @return a label that creates empty space |
| */ |
| public Control createEmptySpace(FormToolkit toolkit, Composite parent, |
| int span) { |
| Label label; |
| if (toolkit != null) { |
| label = toolkit.createLabel(parent, ""); |
| } else { |
| label = new Label(parent, SWT.LEFT); |
| } |
| GridData gd = new GridData(); |
| gd.horizontalAlignment = GridData.BEGINNING; |
| gd.grabExcessHorizontalSpace = false; |
| gd.horizontalSpan = span; |
| gd.horizontalIndent = 0; |
| gd.widthHint = 0; |
| gd.heightHint = 0; |
| label.setLayoutData(gd); |
| return label; |
| } |
| |
| /** |
| * Tests is the control is not <code>null</code> and not disposed. |
| * @param control |
| * @return true if the control is valid for use |
| */ |
| protected final boolean isOkToUse(Control control) { |
| return (control != null) && !(control.isDisposed()); |
| } |
| |
| // --------- enable / disable management |
| |
| /** |
| * Sets the enable state of the dialog field. |
| */ |
| public final void setEnabled(boolean enabled) { |
| if (enabled != _enabled) { |
| _enabled = enabled; |
| updateEnableState(); |
| } |
| } |
| |
| /** |
| * Called when the enable state changed. To be extended by dialog field |
| * implementors. |
| */ |
| protected void updateEnableState() { |
| if (_label != null && !_label.isDisposed()) { |
| _label.setEnabled(_enabled); |
| } |
| if (_hyperlink != null && !_hyperlink.isDisposed()) { |
| _hyperlink.setEnabled(_enabled); |
| } |
| } |
| |
| /** |
| * Gets the enable state of the dialog field. |
| */ |
| public final boolean isEnabled() { |
| return _enabled; |
| } |
| |
| /** |
| * @param comp |
| */ |
| protected final void assertCompositeNotNull(Composite comp) { |
| Assert.isNotNull(comp, |
| "uncreated control requested with composite null"); //$NON-NLS-1$ |
| } |
| |
| /** |
| * @param nColumns |
| */ |
| protected final void assertEnoughColumns(int nColumns) { |
| Assert.isTrue(nColumns >= getNumberOfControls(), |
| "given number of columns is too small"); //$NON-NLS-1$ |
| } |
| |
| /** |
| * Get attached data by key. |
| * |
| * @param key |
| * @return the attached data object for key |
| */ |
| public Object getAttachedData(Object key) { |
| if (_attachedData != null) { |
| return _attachedData.get(key); |
| } |
| return null; |
| } |
| |
| /** |
| * You can attach any data to the DialogField, and get it using the |
| * <code>getAttachedData</code> method. |
| * |
| * @param key |
| * @param value |
| */ |
| public void putAttachedData(Object key, Object value) { |
| if (_attachedData == null) { |
| _attachedData = new HashMap(); |
| } |
| _attachedData.put(key, value); |
| } |
| |
| /** |
| * this method give the DialogField a chance to set the correct column to |
| * grab horizontal space. In the implementation of this method, should only |
| * change the GridData of control, should not do anything else. |
| * |
| * The caller is responsible to make sure the controls for the dialog field |
| * has been created before calling this method. |
| */ |
| public void handleGrabHorizontal() { |
| // do nothing. |
| } |
| |
| public boolean isRequired() { |
| return _isRequired; |
| } |
| |
| /** |
| * @param isRequired |
| */ |
| public void setRequired(boolean isRequired) { |
| this._isRequired = isRequired; |
| } |
| |
| /** |
| * @return gthe tool tip text |
| */ |
| protected String getToolTip() { |
| return toolTip; |
| } |
| |
| public void setToolTip(String toolTip) { |
| this.toolTip = toolTip; |
| } |
| } |