View Javadoc

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__ */