1 /******************************************************************************* 2 * Copyright (c) 2000, 2005 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 *******************************************************************************/ 14 15 16 package org.eclipse.ui.texteditor; 17 18 19 import java.util.ResourceBundle; 20 21 import org.eclipse.swt.events.HelpListener; 22 23 import org.eclipse.jface.action.IAction; 24 import org.eclipse.jface.util.IPropertyChangeListener; 25 import org.eclipse.jface.util.PropertyChangeEvent; 26 27 28 /** 29 * Action used by an editor action bar contributor to establish placeholders in 30 * menus or action bars which can be retargeted to dynamically changing actions, 31 * for example, those which come from the active editor. This action assumes that 32 * the "wrapped" action sends out property change events in response to state 33 * changes. It uses these change notifications to adapt its enabling state and 34 * its visual presentation. 35 */ 36 public final class RetargetTextEditorAction extends ResourceAction { 37 38 /** The target action. */ 39 private IAction fAction; 40 /** The default label if there is no target action. */ 41 private String fDefaultText; 42 /** 43 * The local help listener 44 * @since 2.1 45 */ 46 private HelpListener fLocalHelpListener; 47 /** The listener to pick up changes of the target action. */ 48 private IPropertyChangeListener fListener= this::update; 49 50 /** 51 * Creates a new action. The action configures its initial visual 52 * representation from the given resource bundle. If this action's 53 * wrapped action is set to <code>null</code> it also uses the 54 * information in the resource bundle. 55 * 56 * @param bundle the resource bundle 57 * @param prefix a prefix to be prepended to the various resource keys 58 * (described in <code>ResourceAction</code> constructor), or 59 * <code>null</code> if none 60 * @param style one of <code>IAction.AS_PUSH_BUTTON</code>, <code>IAction.AS_CHECK_BOX</code>, 61 * and <code>IAction.AS_RADIO_BUTTON</code>. 62 * 63 * @see ResourceAction#ResourceAction(ResourceBundle, String, int) 64 * @see IAction#AS_CHECK_BOX 65 * @see IAction#AS_DROP_DOWN_MENU 66 * @see IAction#AS_PUSH_BUTTON 67 * @see IAction#AS_RADIO_BUTTON 68 * @since 2.1 69 */ RetargetTextEditorAction(ResourceBundle bundle, String prefix, int style)70 public RetargetTextEditorAction(ResourceBundle bundle, String prefix, int style) { 71 super(bundle, prefix, style); 72 fDefaultText= getText(); 73 installHelpListener(); 74 } 75 76 /** 77 * Creates a new action. The action configures its initial visual 78 * representation from the given resource bundle. If this action's 79 * wrapped action is set to <code>null</code> it also uses the 80 * information in the resource bundle. 81 * 82 * @param bundle the resource bundle 83 * @param prefix a prefix to be prepended to the various resource keys 84 * (described in <code>ResourceAction</code> constructor), or 85 * <code>null</code> if none 86 * @see ResourceAction#ResourceAction(ResourceBundle, String) 87 */ RetargetTextEditorAction(ResourceBundle bundle, String prefix)88 public RetargetTextEditorAction(ResourceBundle bundle, String prefix) { 89 super(bundle, prefix); 90 fDefaultText= getText(); 91 installHelpListener(); 92 } 93 94 /** 95 * Creates a new action. The action configures its initial visual 96 * representation from the given resource bundle. If this action's 97 * wrapped action is set to <code>null</code> it also uses the 98 * information in the resource bundle. The action gets the given 99 * action id. 100 * 101 * @param bundle the resource bundle 102 * @param prefix a prefix to be prepended to the various resource keys 103 * (described in <code>ResourceAction</code> constructor), or <code>null</code> if none 104 * @param actionId the action id 105 * @param style one of <code>IAction.AS_PUSH_BUTTON</code>, <code>IAction.AS_CHECK_BOX</code>, 106 * and <code>IAction.AS_RADIO_BUTTON</code>. 107 * 108 * @see ResourceAction#ResourceAction(ResourceBundle, String, int) 109 * @see IAction#AS_CHECK_BOX 110 * @see IAction#AS_DROP_DOWN_MENU 111 * @see IAction#AS_PUSH_BUTTON 112 * @see IAction#AS_RADIO_BUTTON 113 * @since 2.1 114 */ RetargetTextEditorAction(ResourceBundle bundle, String prefix, String actionId, int style)115 public RetargetTextEditorAction(ResourceBundle bundle, String prefix, String actionId, int style) { 116 super(bundle, prefix, style); 117 fDefaultText= getText(); 118 setId(actionId); 119 installHelpListener(); 120 } 121 122 /** 123 * Creates a new action. The action configures its initial visual 124 * representation from the given resource bundle. If this action's 125 * wrapped action is set to <code>null</code> it also uses the 126 * information in the resource bundle. The action gets the given 127 * action id. 128 * 129 * @param bundle the resource bundle 130 * @param prefix a prefix to be prepended to the various resource keys 131 * (described in <code>ResourceAction</code> constructor), or <code>null</code> if none 132 * @param actionId the action id 133 * @see ResourceAction#ResourceAction(ResourceBundle, String) 134 * @since 2.0 135 */ RetargetTextEditorAction(ResourceBundle bundle, String prefix, String actionId)136 public RetargetTextEditorAction(ResourceBundle bundle, String prefix, String actionId) { 137 super(bundle, prefix); 138 fDefaultText= getText(); 139 setId(actionId); 140 installHelpListener(); 141 } 142 143 /** 144 * Updates to the changes of the underlying action. 145 * 146 * @param event the change event describing the state change 147 */ update(PropertyChangeEvent event)148 private void update(PropertyChangeEvent event) { 149 if (ENABLED.equals(event.getProperty())) { 150 Boolean bool= (Boolean) event.getNewValue(); 151 setEnabled(bool.booleanValue()); 152 } else if (TEXT.equals(event.getProperty())) 153 setText((String) event.getNewValue()); 154 else if (TOOL_TIP_TEXT.equals(event.getProperty())) 155 setToolTipText((String) event.getNewValue()); 156 else if (CHECKED.equals(event.getProperty())) { 157 Boolean bool= (Boolean) event.getNewValue(); 158 setChecked(bool.booleanValue()); 159 } 160 } 161 162 /** 163 * Sets the underlying action. 164 * 165 * @param action the underlying action 166 */ setAction(IAction action)167 public void setAction(IAction action) { 168 169 if (fAction != null) { 170 fAction.removePropertyChangeListener(fListener); 171 fAction= null; 172 } 173 174 fAction= action; 175 176 if (fAction == null) { 177 178 setEnabled(false); 179 if (getStyle() == AS_CHECK_BOX || getStyle() == AS_RADIO_BUTTON) 180 setChecked(false); 181 setText(fDefaultText); 182 setToolTipText(""); //$NON-NLS-1$ 183 184 } else { 185 186 setEnabled(fAction.isEnabled()); 187 if (fAction.getStyle() == AS_CHECK_BOX || fAction.getStyle() == AS_RADIO_BUTTON) 188 super.setChecked(fAction.isChecked()); 189 setText(fAction.getText()); 190 setToolTipText(fAction.getToolTipText()); 191 fAction.addPropertyChangeListener(fListener); 192 } 193 } 194 195 /** 196 * Installs the help listener. 197 * 198 * @since 2.1 199 */ installHelpListener()200 private void installHelpListener() { 201 super.setHelpListener(e -> { 202 HelpListener listener= null; 203 if (fAction != null) { 204 // if we have a handler, see if it has a help listener 205 listener= fAction.getHelpListener(); 206 if (listener == null) 207 // use our own help listener 208 listener= fLocalHelpListener; 209 } 210 if (listener != null) 211 // pass on the event 212 listener.helpRequested(e); 213 }); 214 } 215 216 /** 217 * The <code>RetargetTextEditorAction</code> implementation of this method declared on 218 * <code>IAction</code> stores the help listener in a local field. The 219 * supplied listener is only used if there is no handler. 220 * 221 * @param listener the help listener 222 * @since 2.1 223 */ 224 @Override setHelpListener(HelpListener listener)225 public void setHelpListener(HelpListener listener) { 226 fLocalHelpListener= listener; 227 } 228 229 @Override run()230 public void run() { 231 if (fAction != null) 232 fAction.run(); 233 } 234 } 235