View Javadoc

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 }