1 /*
2 * Copyright 2006-2016 The JGUIraffe Team.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License")
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package net.sf.jguiraffe.gui.builder.components;
17
18 import java.util.HashMap;
19 import java.util.Map;
20
21 import net.sf.jguiraffe.gui.builder.utils.GUIRuntimeException;
22
23 /**
24 * <p>
25 * A default implementation of the {@code ToolTipManager} interface.
26 * </p>
27 * <p>
28 * This class provides fully functional implementations for all methods defined
29 * by the {@code ToolTipManager} interface. An instance is initialized with a
30 * reference to a {@link ComponentBuilderData} object. From this object the
31 * {@link WidgetHandler} objects associated with the components to manipulate
32 * are obtained. The instance also maintains data about the tool tips (both the
33 * static and the dynamic ones) of all components managed by the associated
34 * {@link ComponentBuilderData} object.
35 * </p>
36 * <p>
37 * Implementation note: This class is not thread-safe. It must only be accessed
38 * from the event dispatch thread. It can only be associated with a single
39 * {@link ComponentBuilderData} object.
40 * </p>
41 *
42 * @author Oliver Heger
43 * @version $Id: DefaultToolTipManager.java 205 2012-01-29 18:29:57Z oheger $
44 */
45 public class DefaultToolTipManager implements ToolTipManager
46 {
47 /** Constant for the default separator for the tip and the additional tip. */
48 private static final String TIP_SEPARATOR = "\n";
49
50 /** A map with the information about the tool tips for the known components. */
51 private final Map<Object, TipData> tipData;
52
53 /** Stores the associated component builder data object. */
54 private final ComponentBuilderData componentBuilderData;
55
56 /** Stores the separator between the standard and the additional tool tip. */
57 private String additionalTipSeparator;
58
59 /**
60 * Creates a new instance of {@code DefaultToolTipManager} and initializes
61 * it with the given {@code ComponentBuilderData} object.
62 *
63 * @param compData the {@code ComponentBuilderData} object (must not be
64 * <b>null</b>)
65 * @throws IllegalArgumentException if the {@code ComponentBuilderData}
66 * object is <b>null</b>
67 */
68 public DefaultToolTipManager(ComponentBuilderData compData)
69 {
70 if (compData == null)
71 {
72 throw new IllegalArgumentException(
73 "ComponentBuilderData must not be null!");
74 }
75
76 componentBuilderData = compData;
77 tipData = new HashMap<Object, TipData>();
78 }
79
80 /**
81 * Returns the separator between the standard and the additional tool tip.
82 *
83 * @return the tool tip separator
84 */
85 public String getAdditionalTipSeparator()
86 {
87 return (additionalTipSeparator != null) ? additionalTipSeparator
88 : TIP_SEPARATOR;
89 }
90
91 /**
92 * Sets the separator between the standard and the additional tool tip. If a
93 * component has both a standard and an additional tool tip, the final tool
94 * tip that is to be passed to the component is constructed by appending the
95 * additional tool tip to the standard tool tip using this string as
96 * separator. If no separator is set, a new line character is used as
97 * default.
98 *
99 * @param additionalTipSeparator the tool tip separator
100 */
101 public void setAdditionalTipSeparator(String additionalTipSeparator)
102 {
103 this.additionalTipSeparator = additionalTipSeparator;
104 }
105
106 /**
107 * Returns the associated {@code ComponentBuilderData}.
108 *
109 * @return the {@code ComponentBuilderData}
110 */
111 public final ComponentBuilderData getComponentBuilderData()
112 {
113 return componentBuilderData;
114 }
115
116 /**
117 * Queries the additional tool tip for the specified component.
118 *
119 * @param component the component in question
120 * @return the additional tool tip for this component
121 */
122 public String getAdditionalToolTip(Object component)
123 {
124 return fetchTipData(component).getAdditionalTip();
125 }
126
127 /**
128 * Returns the additional tool tip for the component with the given name.
129 *
130 * @param componentName the name of the component
131 * @return the additional tool tip for this component
132 * @throws GUIRuntimeException if the name cannot be resolved
133 */
134 public String getAdditionalToolTip(String componentName)
135 {
136 return getAdditionalToolTip(fetchComponent(componentName));
137 }
138
139 /**
140 * Queries the standard tool tip for the specified component.
141 *
142 * @param component the component in question
143 * @return the standard tool tip of this component
144 */
145 public String getToolTip(Object component)
146 {
147 return fetchTipData(component).getStandardTip();
148 }
149
150 /**
151 * Returns the standard tool tip for the component with the given name.
152 *
153 * @param componentName the name of the component
154 * @return the standard tool tip for this component
155 * @throws GUIRuntimeException if the name cannot be resolved
156 */
157 public String getToolTip(String componentName)
158 {
159 return getToolTip(fetchComponent(componentName));
160 }
161
162 /**
163 * Sets the additional tool tip for the specified component.
164 *
165 * @param component the component
166 * @param tip the new additional tool tip
167 */
168 public void setAdditionalToolTip(Object component, String tip)
169 {
170 TipData data = fetchTipData(component);
171 data.setAdditionalTip(tip);
172 fetchWidgetHandler(component).setToolTip(constructTip(data));
173 }
174
175 /**
176 * Sets the additional tool tip for the component with the given name.
177 *
178 * @param componentName the name of the component
179 * @param tip the new additional tool tip
180 * @throws GUIRuntimeException if the component name cannot be resolved
181 */
182 public void setAdditionalToolTip(String componentName, String tip)
183 {
184 setAdditionalToolTip(fetchComponent(componentName), tip);
185 }
186
187 /**
188 * Sets the tool tip for the specified component.
189 *
190 * @param component the component
191 * @param tip the new tool tip
192 */
193 public void setToolTip(Object component, String tip)
194 {
195 TipData data = fetchTipData(component);
196 data.setStandardTip(tip);
197 fetchWidgetHandler(component).setToolTip(constructTip(data));
198 }
199
200 /**
201 * Sets the standard tool tip for the component with the given name.
202 *
203 * @param componentName the name of the component
204 * @param tip the new standard tool tip
205 * @throws GUIRuntimeException if the component name cannot be resolved
206 */
207 public void setToolTip(String componentName, String tip)
208 {
209 setToolTip(fetchComponent(componentName), tip);
210 }
211
212 /**
213 * Creates a combined tool tip from the standard tool tip and the additional
214 * tool tip. This method is called whenever the tool tip of a widget needs
215 * to be changed and both components are specified. The default
216 * implementation appends the additional tip to the standard one using the
217 * separator defined by the {@link #setAdditionalTipSeparator(String)}
218 * method.
219 *
220 * @param stdTip the standard tool tip
221 * @param addTip the additional tool tip
222 * @return the combined tool tip
223 */
224 protected String combineTips(String stdTip, String addTip)
225 {
226 StringBuilder buf = new StringBuilder();
227 buf.append(stdTip);
228 buf.append(getAdditionalTipSeparator());
229 buf.append(addTip);
230 return buf.toString();
231 }
232
233 /**
234 * Obtains the component with the given name. This implementation delegates
235 * to the {@code ComponentBuilderData} object. If the name cannot be
236 * resolved, an exception is thrown.
237 *
238 * @param name the name of the component
239 * @return the corresponding component
240 * @throws GUIRuntimeException if the name cannot be resolved
241 */
242 private Object fetchComponent(String name)
243 {
244 Object comp = getComponentBuilderData().getComponent(name);
245 if (comp == null)
246 {
247 throw new GUIRuntimeException("Unknown component name: " + name);
248 }
249
250 return comp;
251 }
252
253 /**
254 * Helper method for obtaining the {@code WidgetHandler} for the specified
255 * component. This handler is fetched from the {@code ComponentBuilderData}.
256 *
257 * @param comp the component in question
258 * @return the corresponding {@code WidgetHandler}
259 */
260 private WidgetHandler fetchWidgetHandler(Object comp)
261 {
262 WidgetHandler handler = getComponentBuilderData()
263 .getWidgetHandlerForComponent(comp);
264 assert handler != null : "No WidgetHandler returned for component!";
265 return handler;
266 }
267
268 /**
269 * Fetches tool tip information for the specified component. Tests whether
270 * tool tip information for the specified component is already available. If
271 * not, it is fetched now.
272 *
273 * @param comp the component in question
274 * @return the tool tip information for this component
275 */
276 private TipData fetchTipData(Object comp)
277 {
278 TipData res = tipData.get(comp);
279
280 if (res == null)
281 {
282 res = new TipData();
283 res.setStandardTip(fetchWidgetHandler(comp).getToolTip());
284 tipData.put(comp, res);
285 }
286
287 return res;
288 }
289
290 /**
291 * Constructs the final tool tip for the specified tip data. If one of the
292 * components is undefined, the other one is returned. Only if both are
293 * defined, a combined tip is constructed by calling the
294 * {@link #combineTips(String, String)} method.
295 *
296 * @param data the tip data object
297 * @return the resulting tool tip
298 */
299 private String constructTip(TipData data)
300 {
301 if (data.getAdditionalTip() == null)
302 {
303 return data.getStandardTip();
304 }
305
306 if (data.getStandardTip() == null)
307 {
308 return data.getAdditionalTip();
309 }
310
311 return combineTips(data.getStandardTip(), data.getAdditionalTip());
312 }
313
314 /**
315 * A simple data class for storing information about the tool tips
316 * associated with a component.
317 */
318 private static class TipData
319 {
320 /** The standard tip. */
321 private String standardTip;
322
323 /** The additional tip. */
324 private String additionalTip;
325
326 /**
327 * Sets the standard tip.
328 *
329 * @param standardTip the standard tip
330 */
331 public void setStandardTip(String standardTip)
332 {
333 this.standardTip = standardTip;
334 }
335
336 /**
337 * Returns the standard tip.
338 *
339 * @return the standard tip
340 */
341 public String getStandardTip()
342 {
343 return standardTip;
344 }
345
346 /**
347 * Sets the additional tip.
348 *
349 * @param additionalTip the additional tip
350 */
351 private void setAdditionalTip(String additionalTip)
352 {
353 this.additionalTip = additionalTip;
354 }
355
356 /**
357 * Returns the additional tip.
358 *
359 * @return the additional tip
360 */
361 private String getAdditionalTip()
362 {
363 return additionalTip;
364 }
365 }
366 }