001/* 002 * IzPack - Copyright 2001-2005 Julien Ponge, All Rights Reserved. 003 * 004 * http://www.izforge.com/izpack/ 005 * http://developer.berlios.de/projects/izpack/ 006 * 007 * Licensed under the Apache License, Version 2.0 (the "License"); 008 * you may not use this file except in compliance with the License. 009 * You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 */ 019 020package com.izforge.izpack.installer; 021 022import java.awt.Color; 023import java.awt.Component; 024import java.awt.Dimension; 025import java.awt.Font; 026import java.awt.GridBagConstraints; 027import java.awt.GridBagLayout; 028import java.awt.Insets; 029import java.awt.Toolkit; 030import java.awt.event.ActionEvent; 031import java.awt.event.ActionListener; 032import java.awt.event.WindowAdapter; 033import java.awt.event.WindowEvent; 034import java.io.InputStream; 035import java.io.ObjectInputStream; 036import java.lang.reflect.Method; 037import java.util.HashMap; 038import java.util.Iterator; 039import java.util.List; 040import java.util.Locale; 041import java.util.Map; 042import java.util.TreeMap; 043 044import javax.swing.GrayFilter; 045import javax.swing.ImageIcon; 046import javax.swing.JButton; 047import javax.swing.JComboBox; 048import javax.swing.JDialog; 049import javax.swing.JFrame; 050import javax.swing.JLabel; 051import javax.swing.JList; 052import javax.swing.JOptionPane; 053import javax.swing.JPanel; 054import javax.swing.ListCellRenderer; 055import javax.swing.LookAndFeel; 056import javax.swing.SwingConstants; 057import javax.swing.UIManager; 058import javax.swing.plaf.metal.MetalLookAndFeel; 059import javax.swing.plaf.metal.MetalTheme; 060 061import com.izforge.izpack.GUIPrefs; 062import com.izforge.izpack.LocaleDatabase; 063import com.izforge.izpack.gui.ButtonFactory; 064import com.izforge.izpack.gui.IzPackMetalTheme; 065import com.izforge.izpack.gui.LabelFactory; 066import com.izforge.izpack.util.Debug; 067import com.izforge.izpack.util.OsVersion; 068 069/** 070 * The IzPack graphical installer class. 071 * 072 * @author Julien Ponge 073 */ 074public class GUIInstaller extends InstallerBase 075{ 076 077 /** The installation data. */ 078 private InstallData installdata; 079 080 /** The L&F. */ 081 protected String lnf; 082 083 /** defined modifier for language display type. */ 084 private static final String[] LANGUAGE_DISPLAY_TYPES = { "iso3", "native", "default"}; 085 086 private static final String[][] LANG_CODES = { { "cat", "ca"}, { "chn", "zh"}, { "cze", "cs"}, 087 { "dan", "da"}, { "deu", "de"}, { "eng", "en"}, { "fin", "fi"}, { "fra", "fr"}, 088 { "hun", "hu"}, { "ita", "it"}, { "jpn", "ja"}, { "mys", "ms"}, { "ned", "nl"}, 089 { "nor", "no"}, { "pol", "pl"}, { "por", "pt"}, { "rom", "or"}, { "rus", "ru"}, 090 { "spa", "es"}, { "svk", "sk"}, { "swe", "sv"}, { "tur", "tr"}, { "ukr", "uk"}}; 091 092 /** holds language to ISO-3 language code translation */ 093 private static HashMap isoTable; 094 095 /** 096 * The constructor. 097 * 098 * @exception Exception Description of the Exception 099 */ 100 public GUIInstaller() throws Exception 101 { 102 this.installdata = new InstallData(); 103 104 // Loads the installation data 105 loadInstallData(installdata); 106 107 // add the GUI install data 108 loadGUIInstallData(); 109 110 // Sets up the GUI L&F 111 loadLookAndFeel(); 112 113 // Checks the Java version 114 checkJavaVersion(); 115 116 // Loads the suitable langpack 117 loadLangPack(); 118 119 // create the resource manager (after the language selection!) 120 ResourceManager.create(this.installdata); 121 122 // Load custom langpack if exist. 123 addCustomLangpack(installdata); 124 125 // We launch the installer GUI 126 loadGUI(); 127 } 128 129 /** 130 * Load GUI preference information. 131 * 132 * @throws Exception 133 */ 134 public void loadGUIInstallData() throws Exception 135 { 136 InputStream in = GUIInstaller.class.getResourceAsStream("/GUIPrefs"); 137 ObjectInputStream objIn = new ObjectInputStream(in); 138 this.installdata.guiPrefs = (GUIPrefs) objIn.readObject(); 139 objIn.close(); 140 } 141 142 /** 143 * Checks the Java version. 144 * 145 * @exception Exception Description of the Exception 146 */ 147 private void checkJavaVersion() throws Exception 148 { 149 String version = System.getProperty("java.version"); 150 String required = this.installdata.info.getJavaVersion(); 151 if (version.compareTo(required) < 0) 152 { 153 StringBuffer msg = new StringBuffer(); 154 msg.append("The application that you are trying to install requires a "); 155 msg.append(required); 156 msg.append(" version or later of the Java platform.\n"); 157 msg.append("You are running a "); 158 msg.append(version); 159 msg.append(" version of the Java platform.\n"); 160 msg.append("Please upgrade to a newer version."); 161 162 System.out.println(msg.toString()); 163 JOptionPane.showMessageDialog(null, msg.toString(), "Error", JOptionPane.ERROR_MESSAGE); 164 System.exit(1); 165 } 166 } 167 168 /** 169 * Loads the suitable langpack. 170 * 171 * @exception Exception Description of the Exception 172 */ 173 private void loadLangPack() throws Exception 174 { 175 // Initialisations 176 List availableLangPacks = getAvailableLangPacks(); 177 int npacks = availableLangPacks.size(); 178 if (npacks == 0) throw new Exception("no language pack available"); 179 String selectedPack; 180 181 // Dummy Frame 182 JFrame frame = new JFrame(); 183 frame.setIconImage(new ImageIcon(this.getClass().getResource("/img/JFrameIcon.png")) 184 .getImage()); 185 186 Dimension frameSize = frame.getSize(); 187 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 188 frame.setLocation((screenSize.width - frameSize.width) / 2, 189 (screenSize.height - frameSize.height) / 2 - 10); 190 191 // We get the langpack name 192 if (npacks != 1) 193 { 194 LanguageDialog picker = new LanguageDialog(frame, availableLangPacks.toArray()); 195 picker.setSelection(Locale.getDefault().getISO3Country().toLowerCase()); 196 picker.setModal(true); 197 picker.toFront(); 198 //frame.setVisible(true); 199 frame.setVisible(false); 200 picker.setVisible(true); 201 202 selectedPack = (String) picker.getSelection(); 203 if (selectedPack == null) throw new Exception("installation canceled"); 204 } 205 else 206 selectedPack = (String) availableLangPacks.get(0); 207 208 // We add an xml data information 209 this.installdata.xmlData.setAttribute("langpack", selectedPack); 210 211 // We load the langpack 212 installdata.localeISO3 = selectedPack; 213 installdata.setVariable(ScriptParser.ISO3_LANG, installdata.localeISO3); 214 InputStream in = getClass().getResourceAsStream("/langpacks/" + selectedPack + ".xml"); 215 this.installdata.langpack = new LocaleDatabase(in); 216 } 217 218 /** 219 * Returns an ArrayList of the available langpacks ISO3 codes. 220 * 221 * @return The available langpacks list. 222 * @exception Exception Description of the Exception 223 */ 224 private List getAvailableLangPacks() throws Exception 225 { 226 // We read from the langpacks file in the jar 227 InputStream in = getClass().getResourceAsStream("/langpacks.info"); 228 ObjectInputStream objIn = new ObjectInputStream(in); 229 List available = (List) objIn.readObject(); 230 objIn.close(); 231 232 return available; 233 } 234 235 /** 236 * Loads the suitable L&F. 237 * 238 * @exception Exception Description of the Exception 239 */ 240 protected void loadLookAndFeel() throws Exception 241 { 242 // Do we have any preference for this OS ? 243 String syskey = "unix"; 244 if (OsVersion.IS_WINDOWS) 245 { 246 syskey = "windows"; 247 } 248 else if (OsVersion.IS_OSX) 249 { 250 syskey = "mac"; 251 } 252 String laf = null; 253 if (installdata.guiPrefs.lookAndFeelMapping.containsKey(syskey)) 254 { 255 laf = (String) installdata.guiPrefs.lookAndFeelMapping.get(syskey); 256 } 257 258 // Let's use the system LAF 259 // Resolve whether button icons should be used or not. 260 boolean useButtonIcons = true; 261 if (installdata.guiPrefs.modifier.containsKey("useButtonIcons") 262 && ((String) installdata.guiPrefs.modifier.get("useButtonIcons")) 263 .equalsIgnoreCase("no")) useButtonIcons = false; 264 ButtonFactory.useButtonIcons(useButtonIcons); 265 boolean useLabelIcons = true; 266 if (installdata.guiPrefs.modifier.containsKey("useLabelIcons") 267 && ((String) installdata.guiPrefs.modifier.get("useLabelIcons")) 268 .equalsIgnoreCase("no")) useLabelIcons = false; 269 LabelFactory.setUseLabelIcons(useLabelIcons); 270 if (laf == null) 271 { 272 if (!syskey.equals("mac")) 273 { 274 String syslaf = UIManager.getSystemLookAndFeelClassName(); 275 UIManager.setLookAndFeel(syslaf); 276 if (UIManager.getLookAndFeel() instanceof MetalLookAndFeel) 277 { 278 MetalLookAndFeel.setCurrentTheme(new IzPackMetalTheme()); 279 ButtonFactory.useHighlightButtons(); 280 // Reset the use button icons state because 281 // useHighlightButtons 282 // make it always true. 283 ButtonFactory.useButtonIcons(useButtonIcons); 284 installdata.buttonsHColor = new Color(182, 182, 204); 285 } 286 } 287 lnf = "swing"; 288 return; 289 } 290 291 // Kunststoff (http://www.incors.org/) 292 if (laf.equals("kunststoff")) 293 { 294 ButtonFactory.useHighlightButtons(); 295 // Reset the use button icons state because useHighlightButtons 296 // make it always true. 297 ButtonFactory.useButtonIcons(useButtonIcons); 298 installdata.buttonsHColor = new Color(255, 255, 255); 299 Class lafClass = Class.forName("com.incors.plaf.kunststoff.KunststoffLookAndFeel"); 300 Class mtheme = Class.forName("javax.swing.plaf.metal.MetalTheme"); 301 Class[] params = { mtheme}; 302 Class theme = Class.forName("com.izforge.izpack.gui.IzPackKMetalTheme"); 303 Method setCurrentThemeMethod = lafClass.getMethod("setCurrentTheme", params); 304 305 // We invoke and place Kunststoff as our L&F 306 LookAndFeel kunststoff = (LookAndFeel) lafClass.newInstance(); 307 MetalTheme ktheme = (MetalTheme) theme.newInstance(); 308 Object[] kparams = { ktheme}; 309 UIManager.setLookAndFeel(kunststoff); 310 setCurrentThemeMethod.invoke(kunststoff, kparams); 311 312 lnf = "kunststoff"; 313 return; 314 } 315 316 // Liquid (http://liquidlnf.sourceforge.net/) 317 if (laf.equals("liquid")) 318 { 319 UIManager.setLookAndFeel("com.birosoft.liquid.LiquidLookAndFeel"); 320 lnf = "liquid"; 321 322 Map params = (Map) installdata.guiPrefs.lookAndFeelParams.get(laf); 323 if (params.containsKey("decorate.frames")) 324 { 325 String value = (String) params.get("decorate.frames"); 326 if (value.equals("yes")) 327 { 328 JFrame.setDefaultLookAndFeelDecorated(true); 329 } 330 } 331 if (params.containsKey("decorate.dialogs")) 332 { 333 String value = (String) params.get("decorate.dialogs"); 334 if (value.equals("yes")) 335 { 336 JDialog.setDefaultLookAndFeelDecorated(true); 337 } 338 } 339 340 return; 341 } 342 343 // Metouia (http://mlf.sourceforge.net/) 344 if (laf.equals("metouia")) 345 { 346 UIManager.setLookAndFeel("net.sourceforge.mlf.metouia.MetouiaLookAndFeel"); 347 lnf = "metouia"; 348 return; 349 } 350 351 // JGoodies Looks (http://looks.dev.java.net/) 352 if (laf.equals("looks")) 353 { 354 Map variants = new TreeMap(); 355 variants.put("extwin", "com.jgoodies.plaf.windows.ExtWindowsLookAndFeel"); 356 variants.put("plastic", "com.jgoodies.plaf.plastic.PlasticLookAndFeel"); 357 variants.put("plastic3D", "com.jgoodies.plaf.plastic.Plastic3DLookAndFeel"); 358 variants.put("plasticXP", "com.jgoodies.plaf.plastic.PlasticXPLookAndFeel"); 359 String variant = (String) variants.get("plasticXP"); 360 361 Map params = (Map) installdata.guiPrefs.lookAndFeelParams.get(laf); 362 if (params.containsKey("variant")) 363 { 364 String param = (String) params.get("variant"); 365 if (variants.containsKey(param)) 366 { 367 variant = (String) variants.get(param); 368 } 369 } 370 371 UIManager.setLookAndFeel(variant); 372 } 373 } 374 375 /** 376 * Loads the GUI. 377 * 378 * @exception Exception Description of the Exception 379 */ 380 private void loadGUI() throws Exception 381 { 382 UIManager.put("OptionPane.yesButtonText", installdata.langpack.getString("installer.yes")); 383 UIManager.put("OptionPane.noButtonText", installdata.langpack.getString("installer.no")); 384 UIManager.put("OptionPane.cancelButtonText", installdata.langpack 385 .getString("installer.cancel")); 386 387 String title = installdata.langpack.getString("installer.title") 388 + this.installdata.info.getAppName(); 389 new InstallerFrame(title, this.installdata); 390 } 391 392 /** 393 * Returns whether flags should be used in the language selection dialog or not. 394 * 395 * @return whether flags should be used in the language selection dialog or not 396 */ 397 protected boolean useFlags() 398 { 399 if (installdata.guiPrefs.modifier.containsKey("useFlags") 400 && ((String) installdata.guiPrefs.modifier.get("useFlags")).equalsIgnoreCase("no")) 401 return (false); 402 return (true); 403 } 404 405 /** 406 * Returns the type in which the language should be displayed in the language selction dialog. 407 * Possible are "iso3", "native" and "usingDefault". 408 * 409 * @return language display type 410 */ 411 protected String getLangType() 412 { 413 if (installdata.guiPrefs.modifier.containsKey("langDisplayType")) 414 { 415 String val = (String) installdata.guiPrefs.modifier.get("langDisplayType"); 416 val = val.toLowerCase(); 417 // Verify that the value is valid, else return the default. 418 for (int i = 0; i < LANGUAGE_DISPLAY_TYPES.length; ++i) 419 if (val.equalsIgnoreCase(LANGUAGE_DISPLAY_TYPES[i])) return (val); 420 Debug.trace("Value for language display type not valid; value: " + val); 421 } 422 return (LANGUAGE_DISPLAY_TYPES[0]); 423 } 424 425 /** 426 * Used to prompt the user for the language. Languages can be displayed in iso3 or the native 427 * notation or the notation of the default locale. Revising to native notation is based on code 428 * from Christian Murphy (patch #395). 429 * 430 * @author Julien Ponge 431 * @author Christian Murphy 432 * @author Klaus Bartz 433 */ 434 private final class LanguageDialog extends JDialog implements ActionListener 435 { 436 437 private static final long serialVersionUID = 3256443616359887667L; 438 439 /** The combo box. */ 440 private JComboBox comboBox; 441 442 /** The ok button. */ 443 private JButton okButton; 444 445 /** The ISO3 to ISO2 HashMap */ 446 private HashMap iso3Toiso2 = null; 447 448 /** iso3Toiso2 expanded ? */ 449 private boolean isoMapExpanded = false; 450 451 /** 452 * The constructor. 453 * 454 * @param items The items to display in the box. 455 */ 456 public LanguageDialog(JFrame frame, Object[] items) 457 { 458 super(frame); 459 460 try 461 { 462 loadLookAndFeel(); 463 } 464 catch (Exception err) 465 { 466 err.printStackTrace(); 467 } 468 469 // We build the GUI 470 addWindowListener(new WindowHandler()); 471 JPanel contentPane = (JPanel) getContentPane(); 472 setTitle("Language selection"); 473 GridBagLayout layout = new GridBagLayout(); 474 contentPane.setLayout(layout); 475 GridBagConstraints gbConstraints = new GridBagConstraints(); 476 gbConstraints.anchor = GridBagConstraints.CENTER; 477 gbConstraints.insets = new Insets(5, 5, 5, 5); 478 gbConstraints.fill = GridBagConstraints.NONE; 479 gbConstraints.gridx = 0; 480 gbConstraints.weightx = 1.0; 481 gbConstraints.weighty = 1.0; 482 483 ImageIcon img = getImage(); 484 JLabel imgLabel = new JLabel(img); 485 gbConstraints.gridy = 0; 486 contentPane.add(imgLabel); 487 488 gbConstraints.fill = GridBagConstraints.HORIZONTAL; 489 String firstMessage = "Please select your language"; 490 if (getLangType().equals(LANGUAGE_DISPLAY_TYPES[0])) 491 // iso3 492 firstMessage = "Please select your language (ISO3 code)"; 493 494 JLabel label1 = new JLabel(firstMessage, SwingConstants.CENTER); 495 gbConstraints.gridy = 1; 496 gbConstraints.insets = new Insets(5, 5, 0, 5); 497 layout.addLayoutComponent(label1, gbConstraints); 498 contentPane.add(label1); 499 JLabel label2 = new JLabel("for install instructions:", SwingConstants.CENTER); 500 gbConstraints.gridy = 2; 501 gbConstraints.insets = new Insets(0, 5, 5, 5); 502 layout.addLayoutComponent(label2, gbConstraints); 503 contentPane.add(label2); 504 gbConstraints.insets = new Insets(5, 5, 5, 5); 505 506 items = reviseItems(items); 507 508 comboBox = new JComboBox(items); 509 if (useFlags()) comboBox.setRenderer(new FlagRenderer()); 510 gbConstraints.fill = GridBagConstraints.HORIZONTAL; 511 gbConstraints.gridy = 3; 512 layout.addLayoutComponent(comboBox, gbConstraints); 513 contentPane.add(comboBox); 514 515 okButton = new JButton("OK"); 516 okButton.addActionListener(this); 517 gbConstraints.fill = GridBagConstraints.NONE; 518 gbConstraints.gridy = 4; 519 gbConstraints.anchor = GridBagConstraints.CENTER; 520 layout.addLayoutComponent(okButton, gbConstraints); 521 contentPane.add(okButton); 522 getRootPane().setDefaultButton(okButton); 523 524 // Packs and centers 525 // Fix for bug "Installer won't show anything on OSX" 526 if (System.getProperty("mrj.version") == null) 527 pack(); 528 else 529 setSize(getPreferredSize()); 530 531 Dimension frameSize = getSize(); 532 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 533 setLocation((screenSize.width - frameSize.width) / 2, 534 (screenSize.height - frameSize.height) / 2 - 10); 535 setResizable(true); 536 } 537 538 /** 539 * Revises iso3 language items depending on the language display type. 540 * 541 * @param items item array to be revised 542 * @return the revised array 543 */ 544 private Object[] reviseItems(Object[] items) 545 { 546 String langType = getLangType(); 547 // iso3: nothing todo. 548 if (langType.equals(LANGUAGE_DISPLAY_TYPES[0])) return (items); 549 // native: get the names as they are written in that language. 550 if (langType.equals(LANGUAGE_DISPLAY_TYPES[1])) 551 return (expandItems(items, (new JComboBox()).getFont())); 552 // default: get the names as they are written in the default 553 // language. 554 if (langType.equals(LANGUAGE_DISPLAY_TYPES[2])) return (expandItems(items, null)); 555 // Should never be. 556 return (items); 557 } 558 559 /** 560 * Expands the given iso3 codes to language names. If a testFont is given, the codes are 561 * tested whether they can displayed or not. If not, or no font given, the language name 562 * will be returned as written in the default language of this VM. 563 * 564 * @param items item array to be expanded to the language name 565 * @param testFont font to test wheter a name is displayable 566 * @return aray of expanded items 567 */ 568 private Object[] expandItems(Object[] items, Font testFont) 569 { 570 int i; 571 if (iso3Toiso2 == null) 572 { // Loasd predefined langs into HashMap. 573 iso3Toiso2 = new HashMap(32); 574 isoTable = new HashMap(); 575 for (i = 0; i < LANG_CODES.length; ++i) 576 iso3Toiso2.put(LANG_CODES[i][0], LANG_CODES[i][1]); 577 } 578 for (i = 0; i < items.length; i++) 579 { 580 Object it = expandItem(items[i], testFont); 581 isoTable.put(it, items[i]); 582 items[i] = it; 583 } 584 return items; 585 } 586 587 /** 588 * Expands the given iso3 code to a language name. If a testFont is given, the code will be 589 * tested whether it is displayable or not. If not, or no font given, the language name will 590 * be returned as written in the default language of this VM. 591 * 592 * @param item item to be expanded to the language name 593 * @param testFont font to test wheter the name is displayable 594 * @return expanded item 595 */ 596 private Object expandItem(Object item, Font testFont) 597 { 598 Object iso2Str = iso3Toiso2.get(item); 599 int i; 600 if (iso2Str == null && !isoMapExpanded) 601 { // Expand iso3toiso2 only if needed because it needs some time. 602 isoMapExpanded = true; 603 Locale[] loc = Locale.getAvailableLocales(); 604 for (i = 0; i < loc.length; ++i) 605 iso3Toiso2.put(loc[i].getISO3Language(), loc[i].getLanguage()); 606 iso2Str = iso3Toiso2.get(item); 607 } 608 if (iso2Str == null) 609 // Unknown item, return it self. 610 return (item); 611 Locale locale = new Locale((String) iso2Str); 612 if (testFont == null) 613 // Return the language name in the spelling of the default locale. 614 return (locale.getDisplayLanguage()); 615 // Get the language name in the spelling of that language. 616 String str = locale.getDisplayLanguage(locale); 617 int cdut = testFont.canDisplayUpTo(str); 618 if (cdut > -1) 619 // Test font cannot render it; 620 // use language name in the spelling of the default locale. 621 str = locale.getDisplayLanguage(); 622 return (str); 623 } 624 625 /** 626 * Loads an image. 627 * 628 * @return The image icon. 629 */ 630 public ImageIcon getImage() 631 { 632 ImageIcon img; 633 try 634 { 635 img = new ImageIcon(LanguageDialog.class.getResource("/res/installer.langsel.img")); 636 } 637 catch (NullPointerException err) 638 { 639 img = null; 640 } 641 return img; 642 } 643 644 /** 645 * Gets the selected object. 646 * 647 * @return The selected item. 648 */ 649 public Object getSelection() 650 { 651 Object retval = null; 652 if (isoTable != null) retval = isoTable.get(comboBox.getSelectedItem()); 653 return (retval != null) ? retval : comboBox.getSelectedItem(); 654 } 655 656 /** 657 * Sets the selection. 658 * 659 * @param item The item to be selected. 660 */ 661 public void setSelection(Object item) 662 { 663 Object mapped = null; 664 if (isoTable != null) 665 { 666 Iterator iter = isoTable.keySet().iterator(); 667 while (iter.hasNext()) 668 { 669 Object key = iter.next(); 670 if (isoTable.get(key).equals(item)) 671 { 672 mapped = key; 673 break; 674 } 675 } 676 } 677 if (mapped == null) mapped = item; 678 comboBox.setSelectedItem(mapped); 679 } 680 681 /** 682 * Closer. 683 * 684 * @param e The event. 685 */ 686 public void actionPerformed(ActionEvent e) 687 { 688 dispose(); 689 } 690 691 /** 692 * The window events handler. 693 * 694 * @author Julien Ponge 695 */ 696 private class WindowHandler extends WindowAdapter 697 { 698 699 /** 700 * We can't avoid the exit here, so don't call exit anywhere else. 701 * 702 * @param e the event. 703 */ 704 public void windowClosing(WindowEvent e) 705 { 706 System.exit(0); 707 } 708 } 709 } 710 711 /** 712 * A list cell renderer that adds the flags on the display. 713 * 714 * @author Julien Ponge 715 */ 716 private static class FlagRenderer extends JLabel implements ListCellRenderer 717 { 718 719 private static final long serialVersionUID = 3832899961942782769L; 720 721 /** Icons cache. */ 722 private TreeMap icons = new TreeMap(); 723 724 /** Grayed icons cache. */ 725 private TreeMap grayIcons = new TreeMap(); 726 727 public FlagRenderer() 728 { 729 setOpaque(true); 730 } 731 732 /** 733 * Returns a suitable cell. 734 * 735 * @param list The list. 736 * @param value The object. 737 * @param index The index. 738 * @param isSelected true if it is selected. 739 * @param cellHasFocus Description of the Parameter 740 * @return The cell. 741 */ 742 public Component getListCellRendererComponent(JList list, Object value, int index, 743 boolean isSelected, boolean cellHasFocus) 744 { 745 // We put the label 746 String iso3 = (String) value; 747 setText(iso3); 748 if (isoTable != null) iso3 = (String) isoTable.get(iso3); 749 if (isSelected) 750 { 751 setForeground(list.getSelectionForeground()); 752 setBackground(list.getSelectionBackground()); 753 } 754 else 755 { 756 setForeground(list.getForeground()); 757 setBackground(list.getBackground()); 758 } 759 // We put the icon 760 761 if (!icons.containsKey(iso3)) 762 { 763 ImageIcon icon; 764 icon = new ImageIcon(this.getClass().getResource("/res/flag." + iso3)); 765 icons.put(iso3, icon); 766 icon = new ImageIcon(GrayFilter.createDisabledImage(icon.getImage())); 767 grayIcons.put(iso3, icon); 768 } 769 if (isSelected || index == -1) 770 setIcon((ImageIcon) icons.get(iso3)); 771 else 772 setIcon((ImageIcon) grayIcons.get(iso3)); 773 774 // We return 775 return this; 776 } 777 } 778}