1 /*
2 * Copyright (c) 2003-2008 by Cosylab d. d.
3 *
4 * This file is part of CosyBeans-Common.
5 *
6 * CosyBeans-Common is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * CosyBeans-Common is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with CosyBeans-Common. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 package com.cosylab.gui.components.util;
21
22 import java.awt.Component;
23 import java.awt.Font;
24
25 import javax.swing.plaf.metal.MetalLookAndFeel;
26
27
28 /**
29 * Helper class that provides simple access to Font UI resources
30 *
31 * @author <a href="mailto:jernej.kamenik@cosylab.com">Jernej Kamenik</a>
32 * @version $id$
33 *
34 * @see javax.swing.plaf.metal.MetalLookAndFeel
35 * @see java.awt.Font
36 */
37 public final class FontHelper
38 {
39 private static java.util.List<Font> fonts = new java.util.ArrayList<Font>();
40
41 /**
42 * Returns the default Font name
43 *
44 * @return String name
45 *
46 * @see javax.swing.plaf.metal.MetalLookAndFeel#getControlTextFont()
47 */
48 public static String getDefaultFontName()
49 {
50 return MetalLookAndFeel.getControlTextFont().getName();
51 }
52
53 /**
54 * Returns the default Font size
55 *
56 * @return int size
57 *
58 * @see javax.swing.plaf.metal.MetalLookAndFeel#getControlTextFont()
59 */
60 public static int getDefaultFontSize()
61 {
62 return MetalLookAndFeel.getControlTextFont().getSize();
63 }
64
65 /**
66 * Returns the default Font
67 *
68 * @return Font
69 *
70 * @see javax.swing.plaf.metal.MetalLookAndFeel#getUserTextFont()
71 */
72 public static Font getDefaultFont()
73 {
74 return MetalLookAndFeel.getUserTextFont();
75 }
76
77 /**
78 * Returns the specified Font with its style changed to the specified
79 * style.
80 *
81 * @param style style
82 * @param inFont inFont
83 *
84 * @return Font
85 */
86 public static Font getFontWithStyle(int style, Font inFont)
87 {
88 for (int i = 0; i < fonts.size(); i++) {
89 if ((fonts.get(i)).getName().equals(inFont.getName())
90 && ((fonts.get(i)).getSize() == inFont.getSize())
91 && ((fonts.get(i)).getStyle() == style)) {
92 return fonts.get(i);
93 }
94 }
95
96 fonts.add(inFont.deriveFont(style));
97
98 return fonts.get(fonts.size() - 1);
99 }
100
101 /**
102 * Returns the specified Font with its name changed to the specified name.
103 *
104 * @param name name
105 * @param inFont inFont
106 *
107 * @return Font
108 */
109 public static Font getFontWithName(String name, Font inFont)
110 {
111 for (int i = 0; i < fonts.size(); i++) {
112 if ((fonts.get(i)).getName().equals(name)
113 && ((fonts.get(i)).getSize() == inFont.getSize())
114 && ((fonts.get(i)).getStyle() == inFont.getStyle())) {
115 return fonts.get(i);
116 }
117 }
118
119 fonts.add(new Font(name, inFont.getStyle(), inFont.getSize()));
120
121 return fonts.get(fonts.size() - 1);
122 }
123
124 /**
125 * Returns the specified Font with its size changed to the specified size.
126 *
127 * @param size size
128 * @param inFont inFont
129 *
130 * @return Font
131 */
132 public static Font getFontWithSize(int size, Font inFont)
133 {
134 for (int i = 0; i < fonts.size(); i++) {
135 if ((fonts.get(i)).getName().equals(inFont.getName())
136 && ((fonts.get(i)).getSize() == size)
137 && ((fonts.get(i)).getStyle() == inFont.getStyle())) {
138 return fonts.get(i);
139 }
140 }
141
142 fonts.add(inFont.deriveFont((float)size));
143
144 return fonts.get(fonts.size() - 1);
145 }
146
147 /**
148 * Returns a new Font with the specified attributes
149 *
150 * @param name name
151 * @param style style
152 * @param size size
153 *
154 * @return Font
155 */
156 public static Font getFont(String name, int style, int size)
157 {
158 for (int i = 0; i < fonts.size(); i++) {
159 if ((fonts.get(i)).getName().equals(name)
160 && ((fonts.get(i)).getSize() == size)
161 && ((fonts.get(i)).getStyle() == style)) {
162 return fonts.get(i);
163 }
164 }
165
166 fonts.add(new Font(name, style, size));
167
168 return fonts.get(fonts.size() - 1);
169 }
170
171 /**
172 * Calculates new font, which would fit provided text inside component.
173 *
174 * @param comp the <code>Component</code> in which text should fit
175 * @param oldFont old font
176 * @param text a text to be fitted
177 * @param columns number of character columns to fit in component
178 * @param minFontSize minimal allowed font size
179 * @param maxFontSize maximal allowed font size
180 *
181 * @return new font, if calculation failes, old font is returned
182 */
183 public static Font calculateFittingFont(Component comp, Font oldFont,
184 String text, int columns, int minFontSize, int maxFontSize)
185 {
186 int newSize = comp.getHeight() * 14 / 20;
187
188 if (newSize <= 0) {
189 return oldFont;
190 }
191
192 if (newSize > maxFontSize) {
193 newSize = maxFontSize;
194 } else if (newSize < minFontSize) {
195 newSize = minFontSize;
196 }
197
198 /**
199 * stores data about text length. If columns equals zero, label font is
200 * immediately resized to fit text. If columns is non-zero, label min
201 * size is columns"m-width" (only use of columns!), but if text does
202 * not fit in it, font size is changed. Because newSize resets font
203 * size each time resize() is called, the columned-min width is
204 * defined as: length=getHeight()(14/20)columns"m-width-at-size-1";
205 * |---| why not (7/10)?? before the change, the code at CHECKPOINT
206 * 1 tested minWidth, that always retuned true for first #columns#
207 * characters, but didn't care about text length.
208 */
209 Font font = getFontWithSize(newSize, oldFont);
210
211 int textLength = comp.getFontMetrics(font).stringWidth("m") * columns;
212
213 if (text != null) {
214 int l = comp.getFontMetrics(font).stringWidth(text);
215
216 if (l > textLength) {
217 textLength = l;
218 }
219 }
220
221 /*System.out.println("newSize=" + newSize + " textLength=" + textLength
222 + " columns=" + columns + " height=" + comp.getHeight() + " width="
223 + comp.getWidth());*/
224
225 //CHECKPOINT 1_
226 if (textLength > comp.getWidth() * 0.9 && textLength != 0) {
227 //Debug.out("shrinking resizable label");
228 newSize = (int)(newSize * comp.getWidth() * 0.9 / textLength);
229
230 if (newSize < 1) {
231 newSize = 1;
232 }
233
234 font = getFontWithSize(newSize, font);
235
236 //System.out.println("shrinking newSize=" + newSize);
237 }
238
239 // we ignore if font is changed for less than 10%
240 if ((double)Math.abs(oldFont.getSize() - font.getSize()) / (double)oldFont
241 .getSize() < 0.1) {
242 /*System.out.println("change too small "
243 + (double)Math.abs(oldFont.getSize() - font.getSize()) / (double)oldFont
244 .getSize());*/
245 return oldFont;
246 }
247
248 return font;
249 }
250 }
251
252 /* __oOo__ */