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 */
019package com.izforge.izpack.installer;
020
021import java.awt.Component;
022import java.awt.Font;
023import java.awt.GridBagConstraints;
024import java.awt.GridBagLayout;
025import java.awt.Insets;
026
027import javax.swing.ImageIcon;
028import javax.swing.JComponent;
029import javax.swing.JLabel;
030import javax.swing.JOptionPane;
031import javax.swing.JPanel;
032import javax.swing.LookAndFeel;
033import javax.swing.UIManager;
034import javax.swing.plaf.metal.MetalLookAndFeel;
035
036import net.n3.nanoxml.XMLElement;
037
038import com.izforge.izpack.gui.LabelFactory;
039import com.izforge.izpack.util.AbstractUIHandler;
040import com.izforge.izpack.util.MultiLineLabel;
041
042/**
043 * Defines the base class for the IzPack panels. Any panel should be a subclass of it and should
044 * belong to the <code>com.izforge.izpack.panels</code> package.
045 * 
046 * @author Julien Ponge
047 */
048public class IzPanel extends JPanel implements AbstractUIHandler
049{
050
051    private static final long serialVersionUID = 3256442495255786038L;
052
053    /** Indicates whether grid bag layout was started or not */
054    protected boolean gridBagLayoutStarted = false;
055
056    /** The component which should get the focus at activation */
057    protected Component initialFocus = null;
058
059    /**
060     * The installer internal data (actually a melting-pot class with all-public fields.
061     */
062    protected InstallData idata;
063
064    /** The parent IzPack installer frame. */
065    protected InstallerFrame parent;
066
067    /** The default grid bag constraint. */
068    protected GridBagConstraints defaultGridBagConstraints = new GridBagConstraints();
069
070    /** Current x position of grid. */
071    protected int gridxCounter = -1;
072
073    /** Current y position of grid. */
074    protected int gridyCounter = -1;
075    
076    /** i.e. "com.izforge.izpack.panels.HelloPanel" */
077    protected String myFullClassname;
078
079    /** myClassname=i.e "FinishPanel" */
080    protected String myClassname;
081
082    /** i.e. "FinishPanel." useFull for getString() */
083    protected String myPrefix;
084
085    /** internal headline string */
086    protected String headline;
087    
088    /** internal layout */
089    protected GridBagLayout izPanelLayout;
090    
091    /** internal headline Label */
092    protected JLabel headLineLabel;
093    
094    /** HEADLINE = "headline" */
095    public final static String HEADLINE = "headline";
096    
097    /** X_ORIGIN = 0 */
098    public final static int X_ORIGIN = 0;
099
100    /** Y_ORIGIN = 0 */
101    public final static int Y_ORIGIN = 0;
102    /** D = "." ( dot ) */
103    public final static String D = ".";
104
105    /** d = D */
106    public final static String d = D;
107    
108    /** COLS_1 = 1 */
109    public final static int COLS_1 = 1;
110
111    /** ROWS_1 = 1 */
112    public final static int ROWS_1 = 1;
113
114
115    /**
116     * The constructor.
117     * 
118     * @param parent The parent IzPack installer frame.
119     * @param idata The installer internal data.
120     */
121    public IzPanel(InstallerFrame parent, InstallData idata)
122    {
123      super();
124      init( parent, idata );
125    }
126    
127    /**
128     * Creates a new IzPanel object.
129     *
130     * @param parent the Parent Frame
131     * @param idata Installers Runtime Data Set
132     * @param iconName The Headline IconName
133     */
134    public IzPanel( InstallerFrame parent, InstallData idata, String iconName )
135    {
136      this( parent, idata, iconName, -1 );
137    }    
138    
139    /**
140     * The constructor with Icon.
141     *
142     * @param parent The parent IzPack installer frame.
143     * @param idata The installer internal data.
144     * @param iconName A iconname to show as left oriented headline-leading Icon.
145     * @param instance An instance counter
146     */
147    public IzPanel( InstallerFrame parent, InstallData idata, String iconName, int instance )
148    {
149      super(  );
150      init( parent, idata );
151
152      setLayout(  );
153      buildHeadline( iconName, instance );
154      gridyCounter++;
155    }
156    
157    /** 
158     * Build the Headline
159     *
160     * @param imageIconName an Iconname
161     * @param instanceNumber an panel instance
162     *
163     * @return true if successful build
164     */
165    protected boolean buildHeadline( String imageIconName, int instanceNumber )
166    {
167      boolean result = false;
168
169      // TODO: proteced instancenumber
170      // TODO: is to be validated
171      // TODO: 
172      // TODO: first Test if a Resource for your protected Instance exists.
173      String headline;
174      String headlineSearchBaseKey = myClassname + d + "headline";
175
176      if( instanceNumber > -1 )
177      {
178        String instanceSearchKey = headlineSearchBaseKey + d + Integer.toString( instanceNumber );
179
180        String instanceHeadline = getString( instanceSearchKey );
181
182        //System.out.println( "found headline: " + instanceHeadline  +  d + S + ": "+  instanceNumber );
183        if( ! instanceSearchKey.equals( instanceHeadline ) )
184        {
185          headline = instanceHeadline;
186        }
187        else
188        {
189          headline = getString( headlineSearchBaseKey );
190        }
191      }
192      else
193      {
194        headline = getString( headlineSearchBaseKey );
195      }
196
197      if( headline != null )
198      {
199        if( ( imageIconName != null ) && ! "".equals( imageIconName ) )
200        {
201          headLineLabel = new JLabel( headline, getImageIcon( imageIconName ), JLabel.TRAILING );
202        }
203        else
204        {
205          headLineLabel = new JLabel( headline );
206        }
207
208        Font  font  = headLineLabel.getFont(  );
209        float size  = font.getSize(  );
210        int   style = 0;
211        font = font.deriveFont( style, ( size * 1.5f ) );
212        headLineLabel.setFont( font );
213
214        GridBagConstraints gbc = getNewGridBagConstraints( X_ORIGIN, Y_ORIGIN, COLS_1, ROWS_1 );
215        gbc.weightx =  0.0;
216        gbc.weighty = 1.0;        
217        
218        gbc.fill   = GridBagConstraints.NONE;
219        gbc.anchor = GridBagConstraints.NORTHWEST;
220        gbc.insets = new Insets( 0, 0, 5, 0 );
221        izPanelLayout.setConstraints( headLineLabel, gbc );
222        headLineLabel.setName( HEADLINE );
223        add( headLineLabel );
224      }
225
226      return result;
227    }
228    
229    /** 
230     * Gets a language Resource String from the parent, which  holds these global resource.
231     *
232     * @param key The Search key
233     *
234     * @return The Languageresource or the key if not found.
235     */
236    public String getString( String key )
237    {
238      return parent.langpack.getString( key );
239    }
240    
241    /** 
242     * Gets a named image icon
243     *
244     * @param iconName a valid image icon
245     *
246     * @return the icon
247     */
248    public ImageIcon getImageIcon( String iconName )
249    {
250      return parent.icons.getImageIcon( iconName );
251    }
252
253
254    
255    /** 
256     * Inits and sets teh internal LayoutObjects.
257     *
258     * @return true if finshed.
259     */
260    protected boolean setLayout(  )
261    {
262      izPanelLayout        = new GridBagLayout(  );
263      defaultGridBagConstraints = new GridBagConstraints(  );
264
265      setLayout( izPanelLayout );
266
267      return true;
268    }
269    
270
271    /** 
272     * Gets and fills the classname fields
273     */
274    protected void getClassName(  )
275    {
276      myFullClassname = getClass(  ).getName(  );
277      myClassname     = myFullClassname.substring( myFullClassname.lastIndexOf( "." ) + 1 );
278      myPrefix        = myClassname + ".";
279    }
280    
281    /** 
282     * Internal init method
283     *
284     * @param parent the parent frame
285     * @param idata installers runtime dataset
286     */
287    protected void init( InstallerFrame parent, InstallData idata )
288    { 
289      getClassName(  );
290      
291      this.idata           = idata;
292      this.parent          = parent;
293      
294      gridyCounter = -1;
295    }
296
297    /**
298     * Indicates wether the panel has been validated or not. The installer won't let the user go
299     * further through the installation process until the panel is validated. Default behaviour is
300     * to return <code>true</code>.
301     * 
302     * @return A boolean stating wether the panel has been validated or not.
303     */
304    public boolean isValidated()
305    {
306        return true;
307    }
308
309    /**
310     * This method is called when the panel becomes active. Default is to do nothing : feel free to
311     * implement what you need in your subclasses. A panel becomes active when the user reaches it
312     * during the installation process.
313     */
314    public void panelActivate()
315    {
316    }
317
318    /**
319     * This method is called when the panel gets desactivated, when the user switches to the next
320     * panel. By default it doesn't do anything.
321     */
322    public void panelDeactivate()
323    {
324    }
325
326    /**
327     * Asks the panel to set its own XML data that can be brought back for an automated installation
328     * process. Use it as a blackbox if your panel needs to do something even in automated mode.
329     * 
330     * @param panelRoot The XML root element of the panels blackbox tree.
331     */
332    public void makeXMLData(XMLElement panelRoot)
333    {
334    }
335
336    /**
337     * Ask the user a question.
338     * 
339     * @param title Message title.
340     * @param question The question.
341     * @param choices The set of choices to present.
342     * 
343     * @return The user's choice.
344     * 
345     * @see AbstractUIHandler#askQuestion(String, String, int)
346     */
347    public int askQuestion(String title, String question, int choices)
348    {
349        return askQuestion(title, question, choices, -1);
350    }
351
352    /**
353     * Ask the user a question.
354     * 
355     * @param title Message title.
356     * @param question The question.
357     * @param choices The set of choices to present.
358     * @param default_choice The default choice. (-1 = no default choice)
359     * 
360     * @return The user's choice.
361     * @see AbstractUIHandler#askQuestion(String, String, int, int)
362     */
363    public int askQuestion(String title, String question, int choices, int default_choice)
364    {
365        int jo_choices = 0;
366
367        if (choices == AbstractUIHandler.CHOICES_YES_NO)
368            jo_choices = JOptionPane.YES_NO_OPTION;
369        else if (choices == AbstractUIHandler.CHOICES_YES_NO_CANCEL)
370            jo_choices = JOptionPane.YES_NO_CANCEL_OPTION;
371
372        int user_choice = JOptionPane.showConfirmDialog(this, (Object) question, title, jo_choices,
373                JOptionPane.QUESTION_MESSAGE);
374
375        if (user_choice == JOptionPane.CANCEL_OPTION) return AbstractUIHandler.ANSWER_CANCEL;
376
377        if (user_choice == JOptionPane.YES_OPTION) return AbstractUIHandler.ANSWER_YES;
378
379        if (user_choice == JOptionPane.NO_OPTION) return AbstractUIHandler.ANSWER_NO;
380
381        return default_choice;
382    }
383
384    /**
385     * Notify the user about something.
386     * 
387     * @param message The notification.
388     */
389    public void emitNotification(String message)
390    {
391        JOptionPane.showMessageDialog(this, message);
392    }
393
394    /**
395     * Warn the user about something.
396     * 
397     * @param message The warning message.
398     */
399    public boolean emitWarning(String title, String message)
400    {
401        return (JOptionPane.showConfirmDialog(this, message, title, JOptionPane.WARNING_MESSAGE,
402                JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION);
403
404    }
405
406    /**
407     * Notify the user of some error.
408     * 
409     * @param message The error message.
410     */
411    public void emitError(String title, String message)
412    {
413        JOptionPane.showMessageDialog(this, message, title, JOptionPane.ERROR_MESSAGE);
414    }
415
416    /**
417     * Returns the component which should be get the focus at activation of this panel.
418     * 
419     * @return the component which should be get the focus at activation of this panel
420     */
421    public Component getInitialFocus()
422    {
423        return initialFocus;
424    }
425
426    /**
427     * Sets the component which should be get the focus at activation of this panel.
428     * 
429     * @param component which should be get the focus at activation of this panel
430     */
431    public void setInitialFocus(Component component)
432    {
433        initialFocus = component;
434    }
435
436    /**
437     * Calls the langpack of parent InstallerFrame for the String <tt>RuntimeClassName.subkey</tt>.
438     * Do not add a point infront of subkey, it is always added in this method.
439     * 
440     * @param subkey the subkey for the string which should be returned
441     * @param alternateClass the short name of the class which should be used if no string is
442     * present with the runtime class name
443     * @return the founded string
444     */
445    public String getI18nStringForClass(String subkey, String alternateClass)
446    {
447        String curClassName = this.getClass().getName();
448        int nameStart = curClassName.lastIndexOf('.') + 1;
449        curClassName = curClassName.substring(nameStart, curClassName.length());
450        StringBuffer buf = new StringBuffer();
451        buf.append(curClassName).append(".").append(subkey);
452        String fullkey = buf.toString();
453        String retval = parent.langpack.getString(fullkey);
454        if (retval == null || retval.startsWith(fullkey))
455        {
456            buf.delete(0, buf.length());
457            buf.append(alternateClass).append(".").append(subkey);
458            retval = parent.langpack.getString(buf.toString());
459        }
460        return (retval);
461    }
462
463    /**
464     * Returns the parent of this IzPanel (which is a InstallerFrame).
465     * 
466     * @return the parent of this IzPanel
467     */
468    public InstallerFrame getInstallerFrame()
469    {
470        return (parent);
471    }
472
473    // ------------- Helper for common used components ----- START ---
474
475    /**
476     * Creates a label via LabelFactory using iconId, pos and method getI18nStringForClass for
477     * resolving the text to be used. If the icon id is null, the label will be created also.
478     * 
479     * @param subkey the subkey which should be used for resolving the text
480     * @param alternateClass the short name of the class which should be used if no string is
481     * present with the runtime class name
482     * @param iconId id string for the icon
483     * @param pos horizontal alignment
484     * @return the newly created label
485     */
486    public JLabel createLabel(String subkey, String alternateClass, String iconId, int pos)
487    {
488        ImageIcon ii = (iconId != null) ? parent.icons.getImageIcon(iconId) : null;
489        String msg = getI18nStringForClass(subkey, alternateClass);
490        JLabel label = LabelFactory.create(msg, ii, pos);
491        if (label != null) label.setFont(getControlTextFont());
492        return (label);
493
494    }
495
496    /**
497     * Creates a label via LabelFactory with the given ids and the given horizontal alignment. If
498     * the icon id is null, the label will be created also. The strings are the ids for the text in
499     * langpack and the icon in icons of the installer frame.
500     * 
501     * @param textId id string for the text
502     * @param iconId id string for the icon
503     * @param pos horizontal alignment
504     * @return the newly created label
505     */
506    public JLabel createLabel(String textId, String iconId, int pos)
507    {
508        ImageIcon ii = (iconId != null) ? parent.icons.getImageIcon(iconId) : null;
509        JLabel label = LabelFactory.create(parent.langpack.getString(textId),ii, pos);
510        if (label != null) label.setFont(getControlTextFont());
511        return (label);
512
513    }
514    /**
515     * Creates a multi line label with the language dependent text given by the text id. The strings
516     * is the id for the text in langpack of the installer frame. The horizontal alignment will be
517     * LEFT.
518     * 
519     * @param textId id string for the text
520     * @return the newly created multi line label
521     */
522    public MultiLineLabel createMultiLineLabelLang(String textId)
523    {
524        return (createMultiLineLabel(parent.langpack.getString(textId)));
525    }
526
527    /**
528     * Creates a multi line label with the given text. The horizontal alignment will be LEFT.
529     * 
530     * @param text text to be used in the label
531     * @return the newly created multi line label
532     */
533    public MultiLineLabel createMultiLineLabel(String text)
534    {
535        return (createMultiLineLabel(text, null, JLabel.LEFT));
536    }
537
538    /**
539     * Creates a label via LabelFactory with the given text, the given icon id and the given
540     * horizontal alignment. If the icon id is null, the label will be created also. The strings are
541     * the ids for the text in langpack and the icon in icons of the installer frame.
542     * 
543     * @param text text to be used in the label
544     * @param iconId id string for the icon
545     * @param pos horizontal alignment
546     * @return the created multi line label
547     */
548    public MultiLineLabel createMultiLineLabel(String text, String iconId, int pos)
549    {
550        MultiLineLabel mll = null;
551        mll = new MultiLineLabel(text, 0, 0);
552        if (mll != null) mll.setFont(getControlTextFont());
553        return (mll);
554    }
555
556    /**
557     * The Font of Labels in many cases
558     */
559    public Font getControlTextFont()
560    {
561        return (getLAF() != null ? MetalLookAndFeel.getControlTextFont() : getFont());
562    }
563
564    protected static MetalLookAndFeel getLAF()
565    {
566        LookAndFeel laf = UIManager.getLookAndFeel();
567        if (laf instanceof MetalLookAndFeel) return ((MetalLookAndFeel) laf);
568        return (null);
569    }
570
571    // ------------- Helper for common used components ----- END ---
572    // ------------------- Layout stuff -------------------- START ---
573    /**
574     * Returns the default GridBagConstraints of this panel.
575     * 
576     * @return the default GridBagConstraints of this panel
577     */
578    public GridBagConstraints getDefaultGridBagConstraints()
579    {
580        startGridBagLayout();
581        return defaultGridBagConstraints;
582    }
583
584    /**
585     * Sets the default GridBagConstraints of this panel to the given object.
586     * 
587     * @param constraints which should be set as default for this object
588     */
589    public void setDefaultGridBagConstraints(GridBagConstraints constraints)
590    {
591        startGridBagLayout();
592        defaultGridBagConstraints = constraints;
593    }
594
595    /**
596     * Resets the grid counters which are used at getNextXGridBagConstraints and
597     * getNextYGridBagConstraints.
598     */
599    public void resetGridCounter()
600    {
601        gridxCounter = -1;
602        gridyCounter = -1;
603    }
604
605    /**
606     * Returns a newly created GridBagConstraints with the given values and the values from the
607     * defaultGridBagConstraints for the other parameters.
608     * 
609     * @param gridx value to be used for the new constraint
610     * @param gridy value to be used for the new constraint
611     * @return newly created GridBagConstraints with the given values and the values from the
612     * defaultGridBagConstraints for the other parameters
613     */
614    public GridBagConstraints getNewGridBagConstraints(int gridx, int gridy)
615    {
616        GridBagConstraints retval = (GridBagConstraints) getDefaultGridBagConstraints().clone();
617        retval.gridx = gridx;
618        retval.gridy = gridy;
619        return (retval);
620
621    }
622
623    /**
624     * Returns a newly created GridBagConstraints with the given values and the values from the
625     * defaultGridBagConstraints for the other parameters.
626     * 
627     * @param gridx value to be used for the new constraint
628     * @param gridy value to be used for the new constraint
629     * @param gridwidth value to be used for the new constraint
630     * @param gridheight value to be used for the new constraint
631     * @return newly created GridBagConstraints with the given values and the values from the
632     * defaultGridBagConstraints for the other parameters
633     */
634    public GridBagConstraints getNewGridBagConstraints(int gridx, int gridy, int gridwidth,
635            int gridheight)
636    {
637        GridBagConstraints retval = getNewGridBagConstraints(gridx, gridy);
638        retval.gridwidth = gridwidth;
639        retval.gridheight = gridheight;
640        return (retval);
641    }
642
643    /**
644     * Returns a newly created GridBagConstraints for the next column of the current layout row.
645     * 
646     * @return a newly created GridBagConstraints for the next column of the current layout row
647     * 
648     */
649    public GridBagConstraints getNextXGridBagConstraints()
650    {
651        gridxCounter++;
652        GridBagConstraints retval = getNewGridBagConstraints(gridxCounter, gridyCounter);
653        return (retval);
654    }
655
656    /**
657     * Returns a newly created GridBagConstraints for the next column of the current layout row
658     * using the given parameters.
659     * 
660     * @param gridwidth width for this constraint
661     * @param gridheight height for this constraint
662     * @return a newly created GridBagConstraints for the next column of the current layout row
663     * using the given parameters
664     */
665//    private GridBagConstraints getNextXGridBagConstraints(int gridwidth, int gridheight)
666//    {
667//        GridBagConstraints retval = getNextXGridBagConstraints();
668//        retval.gridwidth = gridwidth;
669//        retval.gridheight = gridheight;
670//        return (retval);
671//    }
672
673    /**
674     * Returns a newly created GridBagConstraints with column 0 for the next row.
675     * 
676     * @return a newly created GridBagConstraints with column 0 for the next row
677     * 
678     */
679    public GridBagConstraints getNextYGridBagConstraints()
680    {
681        gridyCounter++;
682        gridxCounter = 0;
683        GridBagConstraints retval = getNewGridBagConstraints(0, gridyCounter);
684        return (retval);
685    }
686
687    /**
688     * Returns a newly created GridBagConstraints with column 0 for the next row using the given
689     * parameters.
690     * 
691     * @param gridwidth width for this constraint
692     * @param gridheight height for this constraint
693     * @return a newly created GridBagConstraints with column 0 for the next row using the given
694     * parameters
695     */
696    public GridBagConstraints getNextYGridBagConstraints(int gridwidth, int gridheight)
697    {
698        startGridBagLayout();
699        GridBagConstraints retval = getNextYGridBagConstraints();
700        retval.gridwidth = gridwidth;
701        retval.gridheight = gridheight;
702        return (retval);
703    }
704
705    /**
706     * Start layout determining. If it is needed, a dummy component will be created as first row.
707     * This will be done, if the IzPack variable <code>IzPanel.LayoutType</code> has the value
708     * "BOTTOM".
709     */
710    public void startGridBagLayout()
711    {
712        if (gridBagLayoutStarted) return;
713        gridBagLayoutStarted = true;
714        GridBagLayout layout = new GridBagLayout();
715        defaultGridBagConstraints.insets = new Insets(0, 0, 20, 0);
716        defaultGridBagConstraints.anchor = GridBagConstraints.WEST;
717        setLayout(layout);
718        String todo = idata.getVariable("IzPanel.LayoutType");
719        if (todo == null) // No command, no work.
720            return;
721        if (todo.equals("BOTTOM"))
722        { // Make a header to push the rest to the bottom.
723            Filler dummy = new Filler();
724            GridBagConstraints gbConstraint = getNextYGridBagConstraints();
725            gbConstraint.weighty = 1.0;
726            gbConstraint.fill = GridBagConstraints.BOTH;
727            gbConstraint.anchor = GridBagConstraints.WEST;
728            this.add(dummy, gbConstraint);
729        }
730
731        // TODO: impl for layout type CENTER, ...
732    }
733
734    /**
735     * Complete layout determining. If it is needed, a dummy component will be created as last row.
736     * This will be done, if the IzPack variable <code>IzPanel.LayoutType</code> has the value
737     * "TOP".
738     */
739    public void completeGridBagLayout()
740    {
741        String todo = idata.getVariable("IzPanel.LayoutType");
742        if (todo == null) // No command, no work.
743            return;
744        if (todo.equals("TOP"))
745        { // Make a footer to push the rest to the top.
746            Filler dummy = new Filler();
747            GridBagConstraints gbConstraint = getNextYGridBagConstraints();
748            gbConstraint.weighty = 1.0;
749            gbConstraint.fill = GridBagConstraints.BOTH;
750            gbConstraint.anchor = GridBagConstraints.WEST;
751            this.add(dummy, gbConstraint);
752        }
753    }
754
755    // ------------------- Layout stuff -------------------- END ---
756
757    // ------------------- Summary stuff -------------------- START ---
758    /**
759     * This method will be called from the SummaryPanel to get the summary of this class which
760     * should be placed in the SummaryPanel. The returned text should not contain a caption of this
761     * item. The caption will be requested from the method getCaption. If <code>null</code>
762     * returns, no summary for this panel will be generated. Default behaviour is to return
763     * <code>null</code>.
764     * 
765     * @return the summary for this class
766     */
767    public String getSummaryBody()
768    {
769        return null;
770    }
771
772    /**
773     * This method will be called from the SummaryPanel to get the caption for this class which
774     * should be placed in the SummaryPanel. If <code>null</code> returns, no summary for this
775     * panel will be generated. Default behaviour is to return the string given by langpack for the
776     * key <code>&lt;current class name>.summaryCaption&gt;</code> if exist, else the string
777     * &quot;summaryCaption.&lt;ClassName&gt;&quot;.
778     * 
779     * @return the caption for this class
780     */
781    public String getSummaryCaption()
782    {
783        return (getI18nStringForClass("summaryCaption", this.getClass().getName()));
784    }
785
786    // ------------------- Summary stuff -------------------- END ---
787
788    // ------------------- Inner classes ------------------- START ---
789    public static class Filler extends JComponent
790    {
791
792        private static final long serialVersionUID = 3258416144414095153L;
793
794    }
795    // ------------------- Inner classes ------------------- END ---
796
797}