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.platform.swing.builder.components;
17  
18  import java.awt.Component;
19  import java.awt.Dimension;
20  import java.awt.Font;
21  import java.awt.Insets;
22  
23  import javax.swing.JComponent;
24  import javax.swing.JScrollPane;
25  import javax.swing.Scrollable;
26  
27  import net.sf.jguiraffe.gui.builder.components.Color;
28  import net.sf.jguiraffe.gui.builder.components.FormBuilderRuntimeException;
29  
30  import org.apache.commons.lang.StringUtils;
31  import org.apache.commons.logging.Log;
32  import org.apache.commons.logging.LogFactory;
33  
34  /**
35   * <p>
36   * A class with utility methods for dealing with Swing components.
37   * </p>
38   * <p>
39   * This class is used internally by implementations for Swing widgets. It
40   * provides functionality for accessing certain properties of Swing components
41   * and converting between Swing-specific data types and platform-independent
42   * types.
43   * </p>
44   *
45   * @author Oliver Heger
46   * @version $Id: SwingComponentUtils.java 205 2012-01-29 18:29:57Z oheger $
47   */
48  final class SwingComponentUtils
49  {
50      /** Constant for the HTML start tag. */
51      private static final String HTML_START = "<html>";
52  
53      /** Constant for the HTML end tag. */
54      private static final String HTML_END = "</html>";
55  
56      /** Constant for the "br" tag. */
57      private static final String TAG_BR = "<br>";
58  
59      /** Constant for the line break string. */
60      private static final String LF = "\n";
61  
62      /** The logger. */
63      private static final Log LOG = LogFactory.getLog(SwingComponentUtils.class);
64  
65      /**
66       * Private constructor so that no instances can be created.
67       */
68      private SwingComponentUtils()
69      {
70      }
71  
72      /**
73       * Converts the passed in Swing (or AWT) color into a platform-independent
74       * logic color. <b>null</b> values are allowed as input values, the result
75       * will then be <b>null</b>, too.
76       *
77       * @param color the Swing color object
78       * @return the corresponding logic color object
79       */
80      public static Color swing2LogicColor(java.awt.Color color)
81      {
82          return (color != null) ? Color.newRGBInstance(color.getRed(), color
83                  .getGreen(), color.getBlue()) : null;
84      }
85  
86      /**
87       * Converts the passed in logic color description into a Swing (or AWT)
88       * specific color object. If the color is not supported (if it is based on a
89       * logic color definition), this method returns <b>null</b>. <b>null</b>
90       * values are allowed as input values, the result will then be <b>null</b>,
91       * too.
92       *
93       * @param color the logic color description
94       * @return the corresponding Swing color object
95       */
96      public static java.awt.Color logic2SwingColor(Color color)
97      {
98          if (color != null)
99          {
100             if (!color.isLogicColor())
101             {
102                 return new java.awt.Color(color.getRed(), color.getGreen(),
103                         color.getBlue());
104             }
105             else
106             {
107                 LOG.warn("Cannot convert color: " + color
108                         + "! Logic colors are not supported by Swing.");
109             }
110         }
111 
112         return null;
113     }
114 
115     /**
116      * Returns the background color of the specified component.
117      *
118      * @param component the component
119      * @return the background color of this component
120      */
121     public static Color getBackgroundColor(JComponent component)
122     {
123         return swing2LogicColor(component.getBackground());
124     }
125 
126     /**
127      * Returns the foreground color of the specified component.
128      *
129      * @param component the component
130      * @return the foreground color of this component
131      */
132     public static Color getForegroundColor(JComponent component)
133     {
134         return swing2LogicColor(component.getForeground());
135     }
136 
137     /**
138      * Sets the background color of the specified component. The passed in
139      * platform independent {@code Color} object will be transformed into an AWT
140      * color object (if possible). If the color is <b>null</b>, this method has
141      * no effect.
142      *
143      * @param component the component
144      * @param c the new background color
145      */
146     public static void setBackgroundColor(JComponent component, Color c)
147     {
148         java.awt.Color convertedColor = logic2SwingColor(c);
149         if (convertedColor != null)
150         {
151             component.setBackground(convertedColor);
152         }
153     }
154 
155     /**
156      * Sets the foreground color of the specified component. The passed in
157      * platform independent {@code Color} object will be transformed into an AWT
158      * color object (if possible). If the color is <b>null</b>, this method has
159      * no effect.
160      *
161      * @param component the component
162      * @param c the new foreground color
163      */
164     public static void setForegroundColor(JComponent component, Color c)
165     {
166         java.awt.Color convertedColor = logic2SwingColor(c);
167         if (convertedColor != null)
168         {
169             component.setForeground(convertedColor);
170         }
171     }
172 
173     /**
174      * Returns the font object of the specified component.
175      *
176      * @param component the component
177      * @return the font object of this component
178      */
179     public static Object getFont(JComponent component)
180     {
181         return component.getFont();
182     }
183 
184     /**
185      * Sets the font object for the specified component. This implementation
186      * checks whether the specified font object is of type {@code java.awt.Font}
187      * . If not, a runtime exception is thrown.
188      *
189      * @param component the component
190      * @param font the font to be set
191      * @throws FormBuilderRuntimeException if the font object is invalid
192      */
193     public static void setFont(JComponent component, Object font)
194     {
195         try
196         {
197             component.setFont((Font) font);
198         }
199         catch (ClassCastException ccex)
200         {
201             throw new FormBuilderRuntimeException(
202                     "Cannot cast object to Font: " + font, ccex);
203         }
204     }
205 
206     /**
207      * Returns the tool tip of the associated component.
208      *
209      * @param component the component
210      * @return the tool tip
211      */
212     public static String getToolTip(JComponent component)
213     {
214         return component.getToolTipText();
215     }
216 
217     /**
218      * Sets the tool tip of the specified component. If required, the text of
219      * the tip is transformed to HTML first.
220      *
221      * @param component the component
222      * @param tip the new tool tip text
223      */
224     public static void setToolTip(JComponent component, String tip)
225     {
226         component.setToolTipText(toHtml(tip));
227     }
228 
229     /**
230      * Sets a tool tip of the specified component that is a concatenation of two
231      * strings. Some components use tool tips combined of two components. This
232      * method combines the components and sets the tool tip text accordingly.
233      * One or both components of the tip can be <b>null</b> or empty strings. In
234      * these case no separator is placed in the resulting string.
235      *
236      * @param component the component
237      * @param tip1 component 1 of the tool tip
238      * @param tip2 component 2 of the tool tip
239      * @param separator the separator between the tip components
240      */
241     public static void setToolTip(JComponent component, String tip1,
242             String tip2, String separator)
243     {
244         component.setToolTipText(combineToolTips(tip1, tip2, separator));
245     }
246 
247     /**
248      * Combines two tool tips. Some components use tool tips combined of two
249      * components. This method generates such a combined tool tip by creating
250      * the concatenation of the passed in strings. The strings can be
251      * <b>null</b> or empty; then no separator is placed in the resulting
252      * string. The resulting combined tip is also converted to HTML if necessary
253      * by calling {@link #toHtml(String)}.
254      *
255      * @param tip1 component 1 of the tool tip
256      * @param tip2 component 2 of the tool tip
257      * @param separator the separator between the tip components
258      * @return the combined tool tip
259      */
260     public static String combineToolTips(String tip1, String tip2,
261             String separator)
262     {
263         String tip;
264         if (StringUtils.isEmpty(tip1))
265         {
266             tip = tip2;
267         }
268         else if (StringUtils.isEmpty(tip2))
269         {
270             tip = tip1;
271         }
272         else
273         {
274             StringBuilder buf = new StringBuilder();
275             buf.append(tip1);
276             buf.append(separator);
277             buf.append(tip2);
278             tip = buf.toString();
279         }
280 
281         return toHtml(tip);
282     }
283 
284     /**
285      * Transforms the specified string to an HTML string. Swing components can
286      * deal with HTML code. This method is called if HTML may be required to
287      * display a text correctly, e.g. because it contains line breaks. This
288      * implementation checks whether a transformation to HTML is necessary. If
289      * this is the case, HTML code is returned. Otherwise, result is the same
290      * text as passed in. We check here for the existence of line breaks. If
291      * some are found, HTML code is returned which contains {@code <br>} tags for the
292      * line breaks.
293      *
294      * @param s the string to be processed (can be <b>null</b>)
295      * @return the processed string
296      */
297     public static String toHtml(String s)
298     {
299         if (s != null)
300         {
301             if (s.indexOf(LF) >= 0)
302             {
303                 StringBuilder buf = new StringBuilder();
304                 buf.append(HTML_START);
305                 buf.append(s.replace(LF, TAG_BR));
306                 buf.append(HTML_END);
307                 return buf.toString();
308             }
309         }
310 
311         return s;
312     }
313 
314     /**
315      * Converts the specified character to a mnemonic code. The Swing key codes
316      * {@code VK_A} to {@code VK_Z} are only defined on upper case letters. So
317      * this implementation converts the given character to upper case. Note that
318      * this might not work out for all languages and codes.
319      *
320      * @param c the mnemonic character
321      * @return the key code to use
322      */
323     public static int toMnemonic(char c)
324     {
325         return Character.toUpperCase(c);
326     }
327 
328     /**
329      * Creates a scroll pane for the specified component. The preferred with of
330      * the scroll pane is properly initialized. If values greater than 0 are
331      * provided for the scroll width and scroll height, these values are set for
332      * the scroll pane's preferred width. Otherwise, the the preferred width is
333      * determined based on the preferred viewport size of the component.
334      *
335      * @param comp the component to be added to the scroll pane
336      * @param scrWidth the preferred scroll width (&lt;= 0 for undefined)
337      * @param scrHeight the preferred scroll height (&lt;= 0 for undefined)
338      * @return the scroll pane
339      */
340     public static JScrollPane scrollPaneFor(Scrollable comp, int scrWidth,
341             int scrHeight)
342     {
343         JScrollPane scr = new JScrollPane((Component) comp);
344         Dimension prefSize;
345         Insets is;
346 
347         if (scrWidth <= 0 || scrHeight <= 0)
348         {
349             is = scr.getInsets();
350             prefSize = comp.getPreferredScrollableViewportSize();
351         }
352         else
353         {
354             is = null;
355             prefSize = new Dimension();
356         }
357 
358         if (scrWidth <= 0)
359         {
360             prefSize.width += scr.getVerticalScrollBar().getPreferredSize()
361                     .getWidth()
362                     + is.left + is.right;
363         }
364         else
365         {
366             prefSize.width = scrWidth;
367         }
368 
369         if (scrHeight <= 0)
370         {
371             prefSize.height += scr.getHorizontalScrollBar().getPreferredSize()
372                     .getHeight()
373                     + is.top + is.bottom;
374         }
375         else
376         {
377             prefSize.height = scrHeight;
378         }
379 
380         scr.setPreferredSize(prefSize);
381         return scr;
382     }
383 }