1 30 31 package com.jgoodies.forms.util; 32 33 import java.awt.Component ; 34 import java.awt.Font ; 35 import java.awt.FontMetrics ; 36 import java.awt.Toolkit ; 37 import java.beans.PropertyChangeEvent ; 38 import java.beans.PropertyChangeListener ; 39 import java.beans.PropertyChangeSupport ; 40 import java.util.HashMap ; 41 import java.util.Map ; 42 43 import javax.swing.JButton ; 44 import javax.swing.UIManager ; 45 46 67 public final class DefaultUnitConverter extends AbstractUnitConverter { 68 69 75 78 private static DefaultUnitConverter instance; 79 80 81 85 private String averageCharWidthTestString = "X"; 86 87 88 93 private Font defaultDialogFont; 94 95 96 105 private PropertyChangeSupport changeSupport; 106 107 108 110 114 private DialogBaseUnits cachedGlobalDialogBaseUnits = 115 computeGlobalDialogBaseUnits(); 116 117 122 private Map cachedDialogBaseUnits = new HashMap (); 123 124 125 127 131 private DefaultUnitConverter () { 132 UIManager.addPropertyChangeListener(new LAFChangeHandler()); 133 } 134 135 138 public static DefaultUnitConverter getInstance() { 139 if (instance == null) { 140 instance = new DefaultUnitConverter(); 141 } 142 return instance; 143 } 144 145 146 148 154 public String getAverageCharacterWidthTestString() { 155 return averageCharWidthTestString; 156 } 157 158 172 public void setAverageCharacterWidthTestString(String newTestString) { 173 if (newTestString == null) 174 throw new NullPointerException ("The test string must not be null."); 175 if (newTestString.length() == 0) 176 throw new IllegalArgumentException ("The test string must not be empty."); 177 178 String oldTestString = averageCharWidthTestString; 179 averageCharWidthTestString = newTestString; 180 changeSupport.firePropertyChange("averageCharacterWidthTestString", 181 oldTestString, newTestString); 182 } 183 184 185 191 public Font getDefaultDialogFont() { 192 if (defaultDialogFont == null) { 193 defaultDialogFont = lookupDefaultDialogFont(); 194 } 195 return defaultDialogFont; 196 } 197 198 203 public void setDefaultDialogFont(Font newFont) { 204 Font oldFont = defaultDialogFont; defaultDialogFont = newFont; 206 changeSupport.firePropertyChange("defaultDialogFont", oldFont, newFont); 207 } 208 209 210 212 218 protected double getDialogBaseUnitsX(Component component) { 219 return getDialogBaseUnits(component).x; 220 } 221 222 229 protected double getDialogBaseUnitsY(Component component) { 230 return getDialogBaseUnits(component).y; 231 } 232 233 234 236 240 private DialogBaseUnits getGlobalDialogBaseUnits() { 241 if (cachedGlobalDialogBaseUnits == null) { 242 cachedGlobalDialogBaseUnits = computeGlobalDialogBaseUnits(); 243 } 244 return cachedGlobalDialogBaseUnits; 245 } 246 247 259 private DialogBaseUnits getDialogBaseUnits(Component c) { 260 if (c == null) { logInfo("Missing font metrics: " + c); 262 return getGlobalDialogBaseUnits(); 263 } 264 FontMetrics fm = c.getFontMetrics(getDefaultDialogFont()); 265 DialogBaseUnits dialogBaseUnits = (DialogBaseUnits) cachedDialogBaseUnits.get(fm); 266 if (dialogBaseUnits == null) { 267 dialogBaseUnits = computeDialogBaseUnits(fm); 268 cachedDialogBaseUnits.put(fm, dialogBaseUnits); 269 } 270 return dialogBaseUnits; 271 } 272 273 286 private DialogBaseUnits computeDialogBaseUnits(FontMetrics metrics) { 287 double averageCharWidth = 288 computeAverageCharWidth(metrics, averageCharWidthTestString); 289 int ascent = metrics.getAscent(); 290 double height = ascent > 14 ? ascent : ascent + (15 - ascent) / 3; 291 DialogBaseUnits dialogBaseUnits = 292 new DialogBaseUnits(averageCharWidth, height); 293 logInfo( 294 "Computed dialog base units " 295 + dialogBaseUnits 296 + " for: " 297 + metrics.getFont()); 298 return dialogBaseUnits; 299 } 300 301 309 private DialogBaseUnits computeGlobalDialogBaseUnits() { 310 logInfo("Computing global dialog base units..."); 311 Font dialogFont = getDefaultDialogFont(); 312 FontMetrics metrics = Toolkit.getDefaultToolkit().getFontMetrics(dialogFont); 313 DialogBaseUnits globalDialogBaseUnits = computeDialogBaseUnits(metrics); 314 return globalDialogBaseUnits; 315 } 321 322 329 private Font lookupDefaultDialogFont() { 330 Font buttonFont = UIManager.getFont("Button.font"); 331 return buttonFont != null 332 ? buttonFont 333 : new JButton ().getFont(); 334 } 335 336 341 private void invalidateCaches() { 342 cachedGlobalDialogBaseUnits = null; 343 cachedDialogBaseUnits.clear(); 344 } 345 346 347 349 361 public final synchronized void addPropertyChangeListener( 362 PropertyChangeListener listener) { 363 if (listener == null) { 364 return; 365 } 366 if (changeSupport == null) { 367 changeSupport = new PropertyChangeSupport (this); 368 } 369 changeSupport.addPropertyChangeListener(listener); 370 } 371 372 373 385 public final synchronized void removePropertyChangeListener( 386 PropertyChangeListener listener) { 387 if (listener == null || changeSupport == null) { 388 return; 389 } 390 changeSupport.removePropertyChangeListener(listener); 391 } 392 393 394 409 public final synchronized void addPropertyChangeListener( 410 String propertyName, 411 PropertyChangeListener listener) { 412 if (listener == null) { 413 return; 414 } 415 if (changeSupport == null) { 416 changeSupport = new java.beans.PropertyChangeSupport (this); 417 } 418 changeSupport.addPropertyChangeListener(propertyName, listener); 419 } 420 421 422 435 public final synchronized void removePropertyChangeListener( 436 String propertyName, 437 PropertyChangeListener listener) { 438 if (listener == null || changeSupport == null) { 439 return; 440 } 441 changeSupport.removePropertyChangeListener(propertyName, listener); 442 } 443 444 445 447 451 private void logInfo(String message) { 452 } 454 455 456 private static class DialogBaseUnits { 458 459 final double x; 460 final double y; 461 462 DialogBaseUnits(double dialogBaseUnitsX, double dialogBaseUnitsY) { 463 this.x = dialogBaseUnitsX; 464 this.y = dialogBaseUnitsY; 465 } 466 467 public String toString() { 468 return "DBU(x=" + x + "; y=" + y + ")"; 469 } 470 } 471 472 private class LAFChangeHandler implements PropertyChangeListener { 474 public void propertyChange(PropertyChangeEvent evt) { 475 invalidateCaches(); 476 } 477 } 478 479 } | Popular Tags |