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}