1 11 package org.eclipse.jface.resource; 12 13 import java.util.ArrayList ; 14 import java.util.Arrays ; 15 import java.util.Collections ; 16 import java.util.Enumeration ; 17 import java.util.HashMap ; 18 import java.util.Iterator ; 19 import java.util.List ; 20 import java.util.Map ; 21 import java.util.MissingResourceException ; 22 import java.util.ResourceBundle ; 23 import java.util.Set ; 24 25 import org.eclipse.core.runtime.Assert; 26 import org.eclipse.swt.SWT; 27 import org.eclipse.swt.graphics.Font; 28 import org.eclipse.swt.graphics.FontData; 29 import org.eclipse.swt.widgets.Display; 30 import org.eclipse.swt.widgets.Shell; 31 32 56 public class FontRegistry extends ResourceRegistry { 57 58 62 private class FontRecord { 63 64 Font baseFont; 65 66 Font boldFont; 67 68 Font italicFont; 69 70 FontData[] baseData; 71 72 78 FontRecord(Font plainFont, FontData[] data) { 79 baseFont = plainFont; 80 baseData = data; 81 } 82 83 86 void dispose() { 87 baseFont.dispose(); 88 if (boldFont != null) { 89 boldFont.dispose(); 90 } 91 if (italicFont != null) { 92 italicFont.dispose(); 93 } 94 } 95 96 100 public Font getBaseFont() { 101 return baseFont; 102 } 103 104 109 public Font getBoldFont() { 110 if (boldFont != null) { 111 return boldFont; 112 } 113 114 FontData[] boldData = getModifiedFontData(SWT.BOLD); 115 boldFont = new Font(Display.getCurrent(), boldData); 116 return boldFont; 117 } 118 119 129 private FontData[] getModifiedFontData(int style) { 130 FontData[] styleData = new FontData[baseData.length]; 131 for (int i = 0; i < styleData.length; i++) { 132 FontData base = baseData[i]; 133 styleData[i] = new FontData(base.getName(), base.getHeight(), 134 base.getStyle() | style); 135 } 136 137 return styleData; 138 } 139 140 145 public Font getItalicFont() { 146 if (italicFont != null) { 147 return italicFont; 148 } 149 150 FontData[] italicData = getModifiedFontData(SWT.ITALIC); 151 italicFont = new Font(Display.getCurrent(), italicData); 152 return italicFont; 153 } 154 155 161 void addAllocatedFontsToStale(Font defaultFont) { 162 if (defaultFont != baseFont && baseFont != null) { 165 staleFonts.add(baseFont); 166 } 167 if (defaultFont != boldFont && boldFont != null) { 168 staleFonts.add(boldFont); 169 } 170 if (defaultFont != italicFont && italicFont != null) { 171 staleFonts.add(italicFont); 172 } 173 } 174 } 175 176 181 private Map stringToFontRecord = new HashMap (7); 182 183 188 private Map stringToFontData = new HashMap (7); 189 190 195 private List staleFonts = new ArrayList (); 196 197 200 protected Runnable displayRunnable = new Runnable () { 201 public void run() { 202 clearCaches(); 203 } 204 }; 205 206 213 public FontRegistry() { 214 this(Display.getCurrent(), true); 215 } 216 217 273 public FontRegistry(String location, ClassLoader loader) 274 throws MissingResourceException { 275 Display display = Display.getCurrent(); 276 Assert.isNotNull(display); 277 readResourceBundle(location); 280 281 hookDisplayDispose(display); 282 } 283 284 290 public FontRegistry(String location) throws MissingResourceException { 291 this(location, null); 294 } 295 296 301 302 private void readResourceBundle(String location) { 303 String osname = System.getProperty("os.name").trim(); String wsname = SWT.getPlatform(); 305 osname = StringConverter.removeWhiteSpaces(osname).toLowerCase(); 306 wsname = StringConverter.removeWhiteSpaces(wsname).toLowerCase(); 307 String OSLocation = location; 308 String WSLocation = location; 309 ResourceBundle bundle = null; 310 if (osname != null) { 311 OSLocation = location + "_" + osname; if (wsname != null) { 313 WSLocation = OSLocation + "_" + wsname; } 315 } 316 317 try { 318 bundle = ResourceBundle.getBundle(WSLocation); 319 readResourceBundle(bundle, WSLocation); 320 } catch (MissingResourceException wsException) { 321 try { 322 bundle = ResourceBundle.getBundle(OSLocation); 323 readResourceBundle(bundle, WSLocation); 324 } catch (MissingResourceException osException) { 325 if (location != OSLocation) { 326 bundle = ResourceBundle.getBundle(location); 327 readResourceBundle(bundle, WSLocation); 328 } else { 329 throw osException; 330 } 331 } 332 } 333 } 334 335 340 public FontRegistry(Display display) { 341 this(display, true); 342 } 343 344 354 public FontRegistry(Display display, boolean cleanOnDisplayDisposal) { 355 Assert.isNotNull(display); 356 if (cleanOnDisplayDisposal) { 357 hookDisplayDispose(display); 358 } 359 } 360 361 373 public FontData bestData(FontData[] fonts, Display display) { 374 for (int i = 0; i < fonts.length; i++) { 375 FontData fd = fonts[i]; 376 377 if (fd == null) { 378 break; 379 } 380 381 FontData[] fixedFonts = display.getFontList(fd.getName(), false); 382 if (isFixedFont(fixedFonts, fd)) { 383 return fd; 384 } 385 386 FontData[] scalableFonts = display.getFontList(fd.getName(), true); 387 if (scalableFonts.length > 0) { 388 return fd; 389 } 390 } 391 392 if (fonts.length > 0) { 395 return fonts[0]; 396 } 397 398 return null; 400 } 401 402 413 public FontData[] bestDataArray(FontData[] fonts, Display display) { 414 415 FontData bestData = bestData(fonts, display); 416 if (bestData == null) { 417 return null; 418 } 419 420 FontData[] datas = new FontData[1]; 421 datas[0] = bestData; 422 return datas; 423 } 424 425 435 public FontData [] filterData(FontData [] fonts, Display display) { 436 ArrayList good = new ArrayList (fonts.length); 437 for (int i = 0; i < fonts.length; i++) { 438 FontData fd = fonts[i]; 439 440 if (fd == null) { 441 continue; 442 } 443 444 FontData[] fixedFonts = display.getFontList(fd.getName(), false); 445 if (isFixedFont(fixedFonts, fd)) { 446 good.add(fd); 447 } 448 449 FontData[] scalableFonts = display.getFontList(fd.getName(), true); 450 if (scalableFonts.length > 0) { 451 good.add(fd); 452 } 453 } 454 455 456 if (good.isEmpty() && fonts.length > 0) { 459 good.add(fonts[0]); 460 } 461 else if (fonts.length == 0) { 462 return null; 463 } 464 465 return (FontData[]) good.toArray(new FontData[good.size()]); 466 } 467 468 469 474 private FontRecord createFont(String symbolicName, FontData[] fonts) { 475 Display display = Display.getCurrent(); 476 if (display == null) { 477 return null; 478 } 479 480 FontData[] validData = filterData(fonts, display); 481 if (validData.length == 0) { 482 return null; 484 } 485 486 put(symbolicName, validData, false); 488 Font newFont = new Font(display, validData); 489 return new FontRecord(newFont, validData); 490 } 491 492 496 Font calculateDefaultFont() { 497 Display current = Display.getCurrent(); 498 if (current == null) { 499 Shell shell = new Shell(); 500 Font font = new Font(null, shell.getFont().getFontData()); 501 shell.dispose(); 502 return font; 503 } 504 return new Font(current, current.getSystemFont().getFontData()); 505 } 506 507 511 public Font defaultFont() { 512 return defaultFontRecord().getBaseFont(); 513 } 514 515 525 public FontDescriptor getDescriptor(String symbolicName) { 526 Assert.isNotNull(symbolicName); 527 return FontDescriptor.createFrom(getFontData(symbolicName)); 528 } 529 530 531 532 535 private FontRecord defaultFontRecord() { 536 537 FontRecord record = (FontRecord) stringToFontRecord 538 .get(JFaceResources.DEFAULT_FONT); 539 if (record == null) { 540 Font defaultFont = calculateDefaultFont(); 541 record = createFont(JFaceResources.DEFAULT_FONT, defaultFont 542 .getFontData()); 543 defaultFont.dispose(); 544 stringToFontRecord.put(JFaceResources.DEFAULT_FONT, record); 545 } 546 return record; 547 } 548 549 552 private FontData[] defaultFontData() { 553 return defaultFontRecord().baseData; 554 } 555 556 564 public FontData[] getFontData(String symbolicName) { 565 566 Assert.isNotNull(symbolicName); 567 Object result = stringToFontData.get(symbolicName); 568 if (result == null) { 569 return defaultFontData(); 570 } 571 572 return (FontData[]) result; 573 } 574 575 583 public Font get(String symbolicName) { 584 585 return getFontRecord(symbolicName).getBaseFont(); 586 } 587 588 597 public Font getBold(String symbolicName) { 598 599 return getFontRecord(symbolicName).getBoldFont(); 600 } 601 602 611 public Font getItalic(String symbolicName) { 612 613 return getFontRecord(symbolicName).getItalicFont(); 614 } 615 616 621 private FontRecord getFontRecord(String symbolicName) { 622 Assert.isNotNull(symbolicName); 623 Object result = stringToFontRecord.get(symbolicName); 624 if (result != null) { 625 return (FontRecord) result; 626 } 627 628 result = stringToFontData.get(symbolicName); 629 630 FontRecord fontRecord; 631 632 if (result == null) { 633 fontRecord = defaultFontRecord(); 634 } else { 635 fontRecord = createFont(symbolicName, (FontData[]) result); 636 } 637 638 if (fontRecord == null) { 639 fontRecord = defaultFontRecord(); 640 } 641 642 stringToFontRecord.put(symbolicName, fontRecord); 643 return fontRecord; 644 645 } 646 647 650 public Set getKeySet() { 651 return Collections.unmodifiableSet(stringToFontData.keySet()); 652 } 653 654 657 public boolean hasValueFor(String fontKey) { 658 return stringToFontData.containsKey(fontKey); 659 } 660 661 664 protected void clearCaches() { 665 666 Iterator iterator = stringToFontRecord.values().iterator(); 667 while (iterator.hasNext()) { 668 Object next = iterator.next(); 669 ((FontRecord) next).dispose(); 670 } 671 672 disposeFonts(staleFonts.iterator()); 673 stringToFontRecord.clear(); 674 staleFonts.clear(); 675 } 676 677 681 private void disposeFonts(Iterator iterator) { 682 while (iterator.hasNext()) { 683 Object next = iterator.next(); 684 ((Font) next).dispose(); 685 } 686 } 687 688 691 private void hookDisplayDispose(Display display) { 692 display.disposeExec(displayRunnable); 693 } 694 695 698 private boolean isFixedFont(FontData[] fixedFonts, FontData fd) { 699 int height = fd.getHeight(); 702 String name = fd.getName(); 703 for (int i = 0; i < fixedFonts.length; i++) { 704 FontData fixed = fixedFonts[i]; 705 if (fixed.getHeight() == height && fixed.getName().equals(name)) { 706 return true; 707 } 708 } 709 return false; 710 } 711 712 715 private FontData makeFontData(String value) throws MissingResourceException { 716 try { 717 return StringConverter.asFontData(value.trim()); 718 } catch (DataFormatException e) { 719 throw new MissingResourceException ( 720 "Wrong font data format. Value is: \"" + value + "\"", getClass().getName(), value); } 722 } 723 724 736 public void put(String symbolicName, FontData[] fontData) { 737 put(symbolicName, fontData, true); 738 } 739 740 755 private void put(String symbolicName, FontData[] fontData, boolean update) { 756 757 Assert.isNotNull(symbolicName); 758 Assert.isNotNull(fontData); 759 760 FontData[] existing = (FontData[]) stringToFontData.get(symbolicName); 761 if (Arrays.equals(existing, fontData)) { 762 return; 763 } 764 765 FontRecord oldFont = (FontRecord) stringToFontRecord 766 .remove(symbolicName); 767 stringToFontData.put(symbolicName, fontData); 768 if (update) { 769 fireMappingChanged(symbolicName, existing, fontData); 770 } 771 772 if (oldFont != null) { 773 oldFont.addAllocatedFontsToStale(defaultFontRecord().getBaseFont()); 774 } 775 } 776 777 782 private void readResourceBundle(ResourceBundle bundle, String bundleName) 783 throws MissingResourceException { 784 Enumeration keys = bundle.getKeys(); 785 while (keys.hasMoreElements()) { 786 String key = (String ) keys.nextElement(); 787 int pos = key.lastIndexOf('.'); 788 if (pos == -1) { 789 stringToFontData.put(key, new FontData[] { makeFontData(bundle 790 .getString(key)) }); 791 } else { 792 String name = key.substring(0, pos); 793 int i = 0; 794 try { 795 i = Integer.parseInt(key.substring(pos + 1)); 796 } catch (NumberFormatException e) { 797 throw new MissingResourceException ( 799 "Wrong key format ", bundleName, key); } 801 FontData[] elements = (FontData[]) stringToFontData.get(name); 802 if (elements == null) { 803 elements = new FontData[8]; 804 stringToFontData.put(name, elements); 805 } 806 if (i > elements.length) { 807 FontData[] na = new FontData[i + 8]; 808 System.arraycopy(elements, 0, na, 0, elements.length); 809 elements = na; 810 stringToFontData.put(name, elements); 811 } 812 elements[i] = makeFontData(bundle.getString(key)); 813 } 814 } 815 } 816 817 823 public FontDescriptor defaultFontDescriptor() { 824 return FontDescriptor.createFrom(defaultFontData()); 825 } 826 } 827 | Popular Tags |