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 (<= 0 for undefined)
337 * @param scrHeight the preferred scroll height (<= 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 }