Mercurial > projects > dwt-addons
diff dwtx/jface/action/Action.d @ 16:e0f0aaf75edd
PopupDialog, bindings and actions
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Tue, 01 Apr 2008 08:00:31 +0200 |
parents | |
children | 46a6e0e6ccd4 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/action/Action.d Tue Apr 01 08:00:31 2008 +0200 @@ -0,0 +1,721 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit <benoit@tionex.de> + *******************************************************************************/ +module dwtx.jface.action.Action; + +import dwtx.jface.action.AbstractAction; +import dwtx.jface.action.IAction; +import dwtx.jface.action.IMenuCreator; +import dwtx.jface.action.LegacyActionTools; + +import dwtx.jface.util.IPropertyChangeListener; + +import dwt.events.HelpListener; +import dwt.widgets.Control; +import dwt.widgets.Event; +import dwt.widgets.Menu; +import dwtx.jface.resource.ImageDescriptor; + +import dwt.dwthelper.utils; + +/** + * The standard abstract implementation of an action. + * <p> + * Subclasses must implement the <code>IAction.run</code> method to carry out + * the action's semantics. + * </p> + */ +public abstract class Action : AbstractAction, IAction { + + public void addPropertyChangeListener(IPropertyChangeListener listener) { + super.addPropertyChangeListener(listener); + } + public void removePropertyChangeListener( IPropertyChangeListener listener) { + super.removePropertyChangeListener(listener); + } + + + private static const IMenuCreator VAL_DROP_DOWN_MENU; + static this(){ + VAL_DROP_DOWN_MENU = new class IMenuCreator { + public void dispose() { + // do nothing + } + + public Menu getMenu(Control parent) { + // do nothing + return null; + } + + public Menu getMenu(Menu parent) { + // do nothing + return null; + } + }; + VAL_RADIO_BTN_OFF = new ValueWrapperInt(0); + VAL_RADIO_BTN_ON = new ValueWrapperInt(1); + VAL_TOGGLE_BTN_OFF = new ValueWrapperBool(false); + VAL_TOGGLE_BTN_ON = new ValueWrapperBool(true); + } + + /* + * The list of default values the action can have. These values will + * determine the style of the action. + */ + private static const String VAL_PUSH_BTN = "PUSH_BTN"; //$NON-NLS-1$ + + private static const ValueWrapperInt VAL_RADIO_BTN_OFF; + + private static const ValueWrapperInt VAL_RADIO_BTN_ON; + + private static const ValueWrapperBool VAL_TOGGLE_BTN_OFF; + + private static const ValueWrapperBool VAL_TOGGLE_BTN_ON; + + /** + * Converts an accelerator key code to a string representation. + * + * @param keyCode + * the key code to be translated + * @return a string representation of the key code + */ + public static String convertAccelerator(int keyCode) { + return LegacyActionTools.convertAccelerator(keyCode); + } + + /** + * Parses the given accelerator text, and converts it to an accelerator key + * code. + * + * @param acceleratorText + * the accelerator text + * @return the DWT key code, or 0 if there is no accelerator + */ + public static int convertAccelerator(String acceleratorText) { + return LegacyActionTools.convertAccelerator(acceleratorText); + } + + /** + * Maps a standard keyboard key name to an DWT key code. Key names are + * converted to upper case before comparison. If the key name is a single + * letter, for example "S", its character code is returned. + * <p> + * The following key names are known (case is ignored): + * <ul> + * <li><code>"BACKSPACE"</code></li> + * <li><code>"TAB"</code></li> + * <li><code>"RETURN"</code></li> + * <li><code>"ENTER"</code></li> + * <li><code>"ESC"</code></li> + * <li><code>"ESCAPE"</code></li> + * <li><code>"DELETE"</code></li> + * <li><code>"SPACE"</code></li> + * <li><code>"ARROW_UP"</code>, <code>"ARROW_DOWN"</code>, + * <code>"ARROW_LEFT"</code>, and <code>"ARROW_RIGHT"</code></li> + * <li><code>"PAGE_UP"</code> and <code>"PAGE_DOWN"</code></li> + * <li><code>"HOME"</code></li> + * <li><code>"END"</code></li> + * <li><code>"INSERT"</code></li> + * <li><code>"F1"</code>, <code>"F2"</code> through <code>"F12"</code></li> + * </ul> + * </p> + * + * @param token + * the key name + * @return the DWT key code, <code>-1</code> if no match was found + * @see dwt.DWT + */ + public static int findKeyCode(String token) { + return LegacyActionTools.findKeyCode(token); + } + + /** + * Maps an DWT key code to a standard keyboard key name. The key code is + * stripped of modifiers (DWT.CTRL, DWT.ALT, DWT.SHIFT, and DWT.COMMAND). If + * the key code is not an DWT code (for example if it a key code for the key + * 'S'), a string containing a character representation of the key code is + * returned. + * + * @param keyCode + * the key code to be translated + * @return the string representation of the key code + * @see dwt.DWT + * @since 2.0 + */ + public static String findKeyString(int keyCode) { + return LegacyActionTools.findKeyString(keyCode); + } + + /** + * Maps standard keyboard modifier key names to the corresponding DWT + * modifier bit. The following modifier key names are recognized (case is + * ignored): <code>"CTRL"</code>, <code>"SHIFT"</code>, + * <code>"ALT"</code>, and <code>"COMMAND"</code>. The given modifier + * key name is converted to upper case before comparison. + * + * @param token + * the modifier key name + * @return the DWT modifier bit, or <code>0</code> if no match was found + * @see dwt.DWT + */ + public static int findModifier(String token) { + return LegacyActionTools.findModifier(token); + } + + /** + * Returns a string representation of an DWT modifier bit (DWT.CTRL, + * DWT.ALT, DWT.SHIFT, and DWT.COMMAND). Returns <code>null</code> if the + * key code is not an DWT modifier bit. + * + * @param keyCode + * the DWT modifier bit to be translated + * @return the string representation of the DWT modifier bit, or + * <code>null</code> if the key code was not an DWT modifier bit + * @see dwt.DWT + * @since 2.0 + */ + public static String findModifierString(int keyCode) { + return LegacyActionTools.findModifierString(keyCode); + } + + /** + * Convenience method for removing any optional accelerator text from the + * given string. The accelerator text appears at the end of the text, and is + * separated from the main part by a single tab character <code>'\t'</code>. + * + * @param text + * the text + * @return the text sans accelerator + */ + public static String removeAcceleratorText(String text) { + return LegacyActionTools.removeAcceleratorText(text); + } + + /** + * Convenience method for removing any mnemonics from the given string. For + * example, <code>removeMnemonics("&Open")</code> will return + * <code>"Open"</code>. + * + * @param text + * the text + * @return the text sans mnemonics + * + * @since 3.0 + */ + public static String removeMnemonics(String text) { + return LegacyActionTools.removeMnemonics(text); + } + + /** + * This action's accelerator; <code>0</code> means none. + */ + private int accelerator = 0; + + /** + * This action's action definition id, or <code>null</code> if none. + */ + private String actionDefinitionId; + + /** + * This action's description, or <code>null</code> if none. + */ + private String description; + + /** + * This action's disabled image, or <code>null</code> if none. + */ + private ImageDescriptor disabledImage; + + /** + * Indicates this action is enabled. + */ + private bool enabled = true; + + /** + * An action's help listener, or <code>null</code> if none. + */ + private HelpListener helpListener; + + /** + * This action's hover image, or <code>null</code> if none. + */ + private ImageDescriptor hoverImage; + + /** + * This action's id, or <code>null</code> if none. + */ + private String id; + + /** + * This action's image, or <code>null</code> if none. + */ + private ImageDescriptor image; + + /** + * This action's text, or <code>null</code> if none. + */ + private String text; + + /** + * This action's tool tip text, or <code>null</code> if none. + */ + private String toolTipText; + + /** + * Holds the action's menu creator (an IMenuCreator) or checked state (a + * bool for toggle button, or an Integer for radio button), or + * <code>null</code> if neither have been set. + * <p> + * The value of this field affects the value of <code>getStyle()</code>. + * </p> + */ + private Object value = null; + + /** + * Creates a new action with no text and no image. + * <p> + * Configure the action later using the set methods. + * </p> + */ + protected this() { + // do nothing + } + + /** + * Creates a new action with the given text and no image. Calls the zero-arg + * constructor, then <code>setText</code>. + * + * @param text + * the string used as the text for the action, or + * <code>null</code> if there is no text + * @see #setText + */ + protected this(String text) { + this(); + setText(text); + } + + /** + * Creates a new action with the given text and image. Calls the zero-arg + * constructor, then <code>setText</code> and + * <code>setImageDescriptor</code>. + * + * @param text + * the action's text, or <code>null</code> if there is no text + * @param image + * the action's image, or <code>null</code> if there is no + * image + * @see #setText + * @see #setImageDescriptor + */ + protected this(String text, ImageDescriptor image) { + this(text); + setImageDescriptor(image); + } + + /** + * Creates a new action with the given text and style. + * + * @param text + * the action's text, or <code>null</code> if there is no text + * @param style + * one of <code>AS_PUSH_BUTTON</code>, + * <code>AS_CHECK_BOX</code>, <code>AS_DROP_DOWN_MENU</code>, + * <code>AS_RADIO_BUTTON</code>, and + * <code>AS_UNSPECIFIED</code>. + */ + protected this(String text, int style) { + this(text); + switch (style) { + case AS_PUSH_BUTTON: + value = stringcast(VAL_PUSH_BTN); + break; + case AS_CHECK_BOX: + value = VAL_TOGGLE_BTN_OFF; + break; + case AS_DROP_DOWN_MENU: + value = cast(Object)VAL_DROP_DOWN_MENU; + break; + case AS_RADIO_BUTTON: + value = VAL_RADIO_BTN_OFF; + break; + } + } + + /* + * (non-Javadoc) Method declared on IAction. + */ + public int getAccelerator() { + return accelerator; + } + + /* + * (non-Javadoc) Method declared on IAction. + * + */ + public String getActionDefinitionId() { + return actionDefinitionId; + } + + /* + * (non-Javadoc) Method declared on IAction. + */ + public String getDescription() { + if (description !is null) { + return description; + } + return getToolTipText(); + } + + /* + * (non-Javadoc) Method declared on IAction. + */ + public ImageDescriptor getDisabledImageDescriptor() { + return disabledImage; + } + + /* + * (non-Javadoc) Method declared on IAction. + */ + public HelpListener getHelpListener() { + return helpListener; + } + + /* + * (non-Javadoc) Method declared on IAction. + */ + public ImageDescriptor getHoverImageDescriptor() { + return hoverImage; + } + + /* + * (non-Javadoc) Method declared on IAction. + */ + public String getId() { + return id; + } + + /* + * (non-Javadoc) Method declared on IAction. + */ + public ImageDescriptor getImageDescriptor() { + return image; + } + + /* + * (non-Javadoc) Method declared on IAction. + */ + public IMenuCreator getMenuCreator() { + // The default drop down menu value is only used + // to mark this action requested style. So do not + // return it. For backward compatibility reasons. + if (value is cast(Object)VAL_DROP_DOWN_MENU) { + return null; + } + if ( auto v = cast(IMenuCreator) value ) { + return v; + } + return null; + } + + /* + * (non-Javadoc) Method declared on IAction. + */ + public int getStyle() { + // Infer the style from the value field. + if (value is stringcast(VAL_PUSH_BTN) || value is null) { + return AS_PUSH_BUTTON; + } + if (value is VAL_TOGGLE_BTN_ON || value is VAL_TOGGLE_BTN_OFF) { + return AS_CHECK_BOX; + } + if (value is VAL_RADIO_BTN_ON || value is VAL_RADIO_BTN_OFF) { + return AS_RADIO_BUTTON; + } + if (cast(IMenuCreator)value ) { + return AS_DROP_DOWN_MENU; + } + + // We should never get to this line... + return AS_PUSH_BUTTON; + } + + /* + * (non-Javadoc) Method declared on IAction. + */ + public String getText() { + return text; + } + + /* + * (non-Javadoc) Method declared on IAction. + */ + public String getToolTipText() { + return toolTipText; + } + + /* + * (non-Javadoc) Method declared on IAction. + */ + public bool isChecked() { + return value is VAL_TOGGLE_BTN_ON || value is VAL_RADIO_BTN_ON; + } + + /* + * (non-Javadoc) Method declared on IAction. + */ + public bool isEnabled() { + return enabled; + } + + /* + * (non-Javadoc) Method declared on IAction. + */ + public bool isHandled() { + return true; + } + + /** + * Reports the outcome of the running of this action via the + * {@link IAction#RESULT} property. + * + * @param success + * <code>true</code> if the action succeeded and + * <code>false</code> if the action failed or was not completed + * @see IAction#RESULT + * @since 3.0 + */ + public final void notifyResult(bool success) { + // avoid bool.valueOf(bool) to allow compilation against JCL + // Foundation (bug 80059) + firePropertyChange(RESULT, null, new ValueWrapperBool(success)); + } + + /** + * The default implementation of this <code>IAction</code> method does + * nothing. Subclasses should override this method if they do not need + * information from the triggering event, or override + * <code>runWithEvent(Event)</code> if they do. + */ + public void run() { + // do nothing + } + + /** + * The default implementation of this <code>IAction</code> method ignores + * the event argument, and simply calls <code>run()</code>. Subclasses + * should override this method if they need information from the triggering + * event, or override <code>run()</code> if not. + * + * @param event + * the DWT event which triggered this action being run + * @since 2.0 + */ + public void runWithEvent(Event event) { + run(); + } + + /* + * @see IAction#setAccelerator(int) + */ + public void setAccelerator(int keycode) { + this.accelerator = keycode; + } + + /* + * (non-Javadoc) Method declared on IAction. + */ + public void setActionDefinitionId(String id) { + actionDefinitionId = id; + } + + /* + * (non-Javadoc) Method declared on IAction. + */ + public void setChecked(bool checked) { + Object newValue = null; + + // For backward compatibility, if the style is not + // set yet, then convert it to a toggle button. + if (value is null || value is VAL_TOGGLE_BTN_ON + || value is VAL_TOGGLE_BTN_OFF) { + newValue = checked ? VAL_TOGGLE_BTN_ON : VAL_TOGGLE_BTN_OFF; + } else if (value is VAL_RADIO_BTN_ON || value is VAL_RADIO_BTN_OFF) { + newValue = checked ? VAL_RADIO_BTN_ON : VAL_RADIO_BTN_OFF; + } else { + // Some other style already, so do nothing. + return; + } + + if (newValue !is value) { + value = newValue; + if (checked) { + firePropertyChange(CHECKED, new ValueWrapperBool(false), new ValueWrapperBool(true)); + } else { + firePropertyChange(CHECKED, new ValueWrapperBool(true), new ValueWrapperBool(false)); + } + } + } + + /* + * (non-Javadoc) Method declared on IAction. + */ + public void setDescription(String text) { + + if ((description is null && text !is null) + || (description !is null && text is null) + || (description !is null && text !is null && !text + .equals(description))) { + String oldDescription = description; + description = text; + firePropertyChange(DESCRIPTION, stringcast(oldDescription), stringcast(description)); + } + } + + /* + * (non-Javadoc) Method declared on IAction. + */ + public void setDisabledImageDescriptor(ImageDescriptor newImage) { + if (disabledImage !is newImage) { + ImageDescriptor oldImage = disabledImage; + disabledImage = newImage; + firePropertyChange(IMAGE, oldImage, newImage); + } + } + + /* + * (non-Javadoc) Method declared on IAction. + */ + public void setEnabled(bool enabled) { + if (enabled !is this.enabled) { + this.enabled = enabled; + firePropertyChange(ENABLED, new ValueWrapperBool(this.enabled), new ValueWrapperBool(enabled)); + } + } + + /* + * (non-Javadoc) Method declared on IAction. + */ + public void setHelpListener(HelpListener listener) { + helpListener = listener; + } + + /* + * (non-Javadoc) Method declared on IAction. + */ + public void setHoverImageDescriptor(ImageDescriptor newImage) { + if (hoverImage !is newImage) { + ImageDescriptor oldImage = hoverImage; + hoverImage = newImage; + firePropertyChange(IMAGE, oldImage, newImage); + } + } + + /* + * (non-Javadoc) Method declared on IAction. + */ + public void setId(String id) { + this.id = id; + } + + /* + * (non-Javadoc) Method declared on IAction. + */ + public void setImageDescriptor(ImageDescriptor newImage) { + if (image !is newImage) { + ImageDescriptor oldImage = image; + image = newImage; + firePropertyChange(IMAGE, oldImage, newImage); + } + } + + /** + * Sets the menu creator for this action. + * <p> + * Note that if this method is called, it overrides the check status. + * </p> + * + * @param creator + * the menu creator, or <code>null</code> if none + */ + public void setMenuCreator(IMenuCreator creator) { + // For backward compatibility, if the style is not + // set yet, then convert it to a drop down menu. + if (value is null) { + value = cast(Object)creator; + return; + } + + if ( cast(IMenuCreator)value ) { + value = creator is null ? cast(Object)VAL_DROP_DOWN_MENU : cast(Object)creator; + } + } + + /** + * Sets the text for this action. + * <p> + * Fires a property change event for the <code>TEXT</code> property if the + * text actually changes as a consequence. + * </p> + * <p> + * The accelerator is identified by the last index of a tab character. If + * there are no tab characters, then it is identified by the last index of a + * '@' character. If neither, then there is no accelerator text. Note that + * if you want to insert a '@' character into the text (but no accelerator, + * you can simply insert a '@' or a tab at the end of the text. + * </p> + * + * @param text + * the text, or <code>null</code> if none + */ + public void setText(String text) { + String oldText = this.text; + int oldAccel = this.accelerator; + this.text = text; + if (text !is null) { + String acceleratorText = LegacyActionTools + .extractAcceleratorText(text); + if (acceleratorText !is null) { + int newAccelerator = LegacyActionTools + .convertLocalizedAccelerator(acceleratorText); + // Be sure to not wipe out the accelerator if nothing found + if (newAccelerator > 0) { + setAccelerator(newAccelerator); + } + } + } + if (!(this.accelerator is oldAccel && (oldText is null ? this.text is null + : oldText.equals(this.text)))) { + firePropertyChange(TEXT, stringcast(oldText), stringcast(this.text)); + } + } + + /** + * Sets the tool tip text for this action. + * <p> + * Fires a property change event for the <code>TOOL_TIP_TEXT</code> + * property if the tool tip text actually changes as a consequence. + * </p> + * + * @param toolTipText + * the tool tip text, or <code>null</code> if none + */ + public void setToolTipText(String toolTipText) { + String oldToolTipText = this.toolTipText; + if (!(oldToolTipText is null ? toolTipText is null : oldToolTipText + .equals(toolTipText))) { + this.toolTipText = toolTipText; + firePropertyChange(TOOL_TIP_TEXT, stringcast(oldToolTipText), stringcast(toolTipText)); + } + } + +}