1 /*******************************************************************************
2  * Copyright (c) 2000, 2015 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 package org.eclipse.ui.actions;
15 
16 import org.eclipse.jface.action.IAction;
17 import org.eclipse.jface.action.LegacyActionTools;
18 import org.eclipse.jface.resource.ImageDescriptor;
19 import org.eclipse.jface.util.PropertyChangeEvent;
20 
21 /**
22  * A <code>LabelRetargetAction</code> extends the behavior of RetargetAction. It
23  * will track the enable state, label, and tool tip text of the target action..
24  * <p>
25  * This class may be instantiated. It is not intented to be subclassed.
26  * </p>
27  *
28  * @since 2.0
29  * @noextend This class is not intended to be subclassed by clients.
30  */
31 public class LabelRetargetAction extends RetargetAction {
32 	private String defaultText;
33 
34 	private String defaultToolTipText;
35 
36 	private ImageDescriptor defaultHoverImage;
37 
38 	private ImageDescriptor defaultImage;
39 
40 	private ImageDescriptor defaultDisabledImage;
41 
42 	private String acceleratorText;
43 
44 	/**
45 	 * Constructs a LabelRetargetAction with the given action id and text.
46 	 *
47 	 * @param actionID the retargetable action id
48 	 * @param text     the action's text, or <code>null</code> if there is no text
49 	 */
LabelRetargetAction(String actionID, String text)50 	public LabelRetargetAction(String actionID, String text) {
51 		this(actionID, text, IAction.AS_UNSPECIFIED);
52 	}
53 
54 	/**
55 	 * Constructs a RetargetAction with the given action id, text and style.
56 	 *
57 	 * @param actionID the retargetable action id
58 	 * @param text     the action's text, or <code>null</code> if there is no text
59 	 * @param style    one of <code>AS_PUSH_BUTTON</code>,
60 	 *                 <code>AS_CHECK_BOX</code>, <code>AS_DROP_DOWN_MENU</code>,
61 	 *                 <code>AS_RADIO_BUTTON</code>, and
62 	 *                 <code>AS_UNSPECIFIED</code>.
63 	 * @since 3.0
64 	 */
LabelRetargetAction(String actionID, String text, int style)65 	public LabelRetargetAction(String actionID, String text, int style) {
66 		super(actionID, text, style);
67 		this.defaultText = text;
68 		this.defaultToolTipText = text;
69 		acceleratorText = LegacyActionTools.extractAcceleratorText(text);
70 	}
71 
72 	/**
73 	 * The action handler has changed. Update self.
74 	 */
75 	@Override
propagateChange(PropertyChangeEvent event)76 	protected void propagateChange(PropertyChangeEvent event) {
77 		super.propagateChange(event);
78 		String prop = event.getProperty();
79 		if (prop.equals(IAction.TEXT)) {
80 			String str = (String) event.getNewValue();
81 			super.setText(appendAccelerator(str));
82 		} else if (prop.equals(IAction.TOOL_TIP_TEXT)) {
83 			String str = (String) event.getNewValue();
84 			super.setToolTipText(str);
85 		} else if (prop.equals(IAction.IMAGE)) {
86 			updateImages(getActionHandler());
87 		}
88 	}
89 
90 	/**
91 	 * Sets the action handler. Update self.
92 	 */
93 	@Override
setActionHandler(IAction handler)94 	protected void setActionHandler(IAction handler) {
95 		// Run the default behavior.
96 		super.setActionHandler(handler);
97 
98 		// Now update the label, tooltip and images.
99 		if (handler == null) {
100 			super.setText(defaultText);
101 			super.setToolTipText(defaultToolTipText);
102 		} else {
103 			// If no text is specified by the handler, use the default text. Fixes 22529.
104 			String handlerText = handler.getText();
105 			if (handlerText == null || handlerText.length() == 0) {
106 				handlerText = defaultText;
107 			}
108 			super.setText(appendAccelerator(handlerText));
109 			super.setToolTipText(handler.getToolTipText());
110 		}
111 		updateImages(handler);
112 	}
113 
114 	@Override
setDisabledImageDescriptor(ImageDescriptor image)115 	public void setDisabledImageDescriptor(ImageDescriptor image) {
116 		super.setDisabledImageDescriptor(image);
117 		defaultDisabledImage = image;
118 	}
119 
120 	@Override
setHoverImageDescriptor(ImageDescriptor image)121 	public void setHoverImageDescriptor(ImageDescriptor image) {
122 		super.setHoverImageDescriptor(image);
123 		defaultHoverImage = image;
124 	}
125 
126 	@Override
setImageDescriptor(ImageDescriptor image)127 	public void setImageDescriptor(ImageDescriptor image) {
128 		super.setImageDescriptor(image);
129 		defaultImage = image;
130 	}
131 
132 	/**
133 	 * Sets the action's label text to the given value.
134 	 */
135 	@Override
setText(String text)136 	public void setText(String text) {
137 		super.setText(text);
138 		acceleratorText = LegacyActionTools.extractAcceleratorText(text);
139 		defaultText = text;
140 	}
141 
142 	/**
143 	 * Sets the tooltip text to the given text. The value <code>null</code> clears
144 	 * the tooltip text.
145 	 */
146 	@Override
setToolTipText(String text)147 	public void setToolTipText(String text) {
148 		super.setToolTipText(text);
149 		defaultToolTipText = text;
150 	}
151 
152 	/**
153 	 * Ensures the accelerator is correct in the text (handlers are not allowed to
154 	 * change the accelerator).
155 	 */
appendAccelerator(String newText)156 	private String appendAccelerator(String newText) {
157 		if (newText == null) {
158 			return null;
159 		}
160 
161 		// Remove any accelerator
162 		String str = removeAcceleratorText(newText);
163 		// Append our accelerator
164 		if (acceleratorText != null) {
165 			str = str + '\t' + acceleratorText;
166 		} else if (str != newText) {
167 			str = str + '\t';
168 		}
169 		return str;
170 	}
171 
172 	/**
173 	 * Updates the images for this action based on the given handler.
174 	 */
updateImages(IAction handler)175 	private void updateImages(IAction handler) {
176 		if (handler == null) {
177 			super.setHoverImageDescriptor(defaultHoverImage);
178 			super.setImageDescriptor(defaultImage);
179 			super.setDisabledImageDescriptor(defaultDisabledImage);
180 		} else {
181 			// use the default images if the handler has no images set
182 			ImageDescriptor hoverImage = handler.getHoverImageDescriptor();
183 			ImageDescriptor image = handler.getImageDescriptor();
184 			ImageDescriptor disabledImage = handler.getDisabledImageDescriptor();
185 			if (hoverImage != null || image != null || disabledImage != null) {
186 				super.setHoverImageDescriptor(hoverImage);
187 				super.setImageDescriptor(image);
188 				super.setDisabledImageDescriptor(disabledImage);
189 			} else {
190 				super.setHoverImageDescriptor(defaultHoverImage);
191 				super.setImageDescriptor(defaultImage);
192 				super.setDisabledImageDescriptor(defaultDisabledImage);
193 			}
194 		}
195 	}
196 
197 }
198