KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > spi > enode > IconSet


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Nokia. Portions Copyright 2003-2004 Nokia.
17  * All Rights Reserved.
18  */

19
20 package org.netbeans.spi.enode;
21
22 import java.util.Enumeration JavaDoc;
23 import java.util.HashMap JavaDoc;
24 import java.util.Iterator JavaDoc;
25 import java.util.Map JavaDoc;
26 import java.util.MissingResourceException JavaDoc;
27 import java.util.ArrayList JavaDoc;
28 import java.util.logging.Logger JavaDoc;
29
30 import javax.swing.ImageIcon JavaDoc;
31
32 import org.openide.ErrorManager;
33
34 import org.openide.filesystems.FileObject;
35
36 import org.openide.util.NbBundle;
37
38 import org.netbeans.modules.enode.TimedSoftReference;
39
40
41 /**
42  * This class describes a set of icons that have been deployed by one
43  * or a set of modules. The icons can be defined for different sizes.
44  * Each icon is identified by a name. The following example shows an
45  * <tt>IconSet</tt> definition in <tt>layer.xml</tt>:
46  * <p><tt><pre>
47  * <file name="BSC.instance">
48  * <attr name="instanceClass" stringvalue="org.netbeans.spi.enode.IconSet" />
49  * <attr name="instanceCreate" methodvalue="org.netbeans.spi.enode.IconSet.getInstance" />
50  * <attr name="basedir" stringvalue="com/nokia/oss/bsmoc/resources/"/>
51  * <attr name="bundle" stringvalue="bssmoc"/>
52  * <attr name="defaultSize" stringvalue="32"/>
53  * <attr name="description" stringvalue="BSC_OBJECT_CLASS" />
54  *
55  * <attr name="*BSC#32" stringvalue="bmatbsc___bmx.gif"/>
56  * <attr name="DAXW#32" stringvalue="bmatdaxwllbmx.gif"/>
57  * <attr name="OLD_BSC_BM#32" stringvalue="guib32mx.gif"/>
58  * <attr name="BSC#32" stringvalue="bmatbsc___bmx.gif"/>
59  *
60  * <attr name="SMALL_OLD_BSC_BM#20" stringvalue="guib20mx.gif"/>
61  * <attr name="*BSC#20" stringvalue="bmatbsc___smx.gif"/>
62  * <attr name="DAXW#20" stringvalue="bmatdaxwllsmx.gif"/>
63  * <attr name="BSC#20" stringvalue="bmatbsc___smx.gif"/>
64  *
65  * </file>
66  * </pre></tt><p>
67  * Th attributes <tt>instanceClass</tt> and <tt>instanceCreate</tt> define
68  * a factory method of this class. The other attributes have the following
69  * meaning:
70  * <ul>
71  * <li>
72  * <tt>basedir</tt><br>
73  * Defines the base folder containing the resources of the <tt>IconSet</tt>.
74  * Resources includes the icons and optional a bundle file for mapping icon
75  * names to display names. This attribute is optional. If it is ommited, all
76  * other entries pointing to resources must contain absolute paths.
77  * </li><p>
78  * <li>
79  * <tt>bundle</tt><br>
80  * The name of the proprties file that contains the mapping from icon names to
81  * display names. This attribute is optional. If it is ommitted, the icon names
82  * will be used as display names. The value of the attribute should contains
83  * the name of a properties file without file suffix, e.g. when the file is
84  * called <tt>bundle.properties</tt> the configured value should be only
85  * <tt>bundle</tt>.
86  * </li><p>
87  * <li>
88  * <tt>defaultSize</tt><br>
89  * Defines the default icon size. When an <tt>IconSet</tt> contains icons of
90  * different sizes, this attribute allows to define the default size. The
91  * attribute is optional. When omitted 16 will be the default size (as needed
92  * for nodes).
93  * </li><p>
94  * <li>
95  * <tt>description</tt><br>
96  * A description of the <tt>IconSet</tt>. The attribute is optional. It makes
97  * it more easy to read the <tt>layer.xml</tt> configuration.
98  * </li><p>
99  * <li>
100  * All other entries will be treated as icon definitions. The attribute name
101  * of an icon should follow the syntax <tt>*&lt;name&gt;#&lt;size&gt;</tt>.
102  * The leading * marks the icon as default icon. For each icon size there
103  * should be only one default icon( when several defaults are configured one
104  * of them will be chosen). The &lt;name&gt; template defines the name of the
105  * icon, while the &lt;size&gt template should contain the icon size in pixels.
106  * In case no icon size is defined, the default size will be assumed.
107  * </li><p>
108  * </ul>
109  * To define display names for icons a bundle file needs to be written that
110  * contains the configured name of the icon as key and the display name as
111  * value.
112  * <p>
113  * When an icon is requested from the <tt>IconSet</tt> that cannot be found
114  * then all resulting exceptions will be logged and a default icon is returned.
115  * This prevents to pop up many error dialogs in case icons cannot be loaded
116  * for any kind of reason.
117  *
118  * @author John Stuwe
119  */

120 public class IconSet {
121     //=======================================================================
122
// Private data members
123

124     //
125
// Special characters in icon names (marked as default
126
// icon and size separator).
127
//
128
private static final char DEFAULT_MARK = '*';
129     private static final char SIZE_MARK = '#';
130     
131     //
132
// Supported attribute names
133
//
134
private static final String JavaDoc DESCRIPTION_ATTRIBUTE = "description";
135     private static final String JavaDoc BASE_DIR_ATTRIBUTE = "basedir";
136     private static final String JavaDoc DEFAULT_SIZE_ATTRIBUTE = "defaultSize";
137     private static final String JavaDoc BUNDLE_ATTRIBUTE = "bundle";
138     private static final String JavaDoc INSTANCE_CLASS = "instanceClass";
139     private static final String JavaDoc INSTANCE_CREATE = "instanceCreate";
140     
141     //
142
// Suffix of properties file
143
//
144
private static final String JavaDoc PROPERTIES = ".properties";
145     
146     //
147
// IconSet cache
148
//
149
private static Map JavaDoc theIconSetCache;
150     
151     //
152
// HashMap mapping icon names and paths,
153
// delegate IconSet to forward icon requests,
154
// default icon size,
155
// bundle file containing localized display names of the icons,
156
// and finally the description coded in the layer.xml entry
157
//
158
private Map JavaDoc myIcons;
159     private IconSet myDelegate;
160     private int myDefaultSize;
161     private String JavaDoc myBundle;
162     private String JavaDoc myDescription;
163     
164     //=======================================================================
165
// Private constructors
166

167     /**
168      * Creates a new empty <tt>IconSet</tt>.
169      */

170     public IconSet( ) {
171         myIcons = new HashMap JavaDoc( );
172         myDefaultSize = NbIcon.SIZE_16x16;
173     }
174     
175     
176     /**
177      * Creates a new <tt>IconSet</tt> that contains the icon configured
178      * by the given file system entry.
179      *
180      * @param file The file system entry defining this <tt>IconSet</tt>.
181      */

182     IconSet( FileObject file ) {
183         this( );
184         
185         try {
186             if( file == null ) {
187                 throw new IllegalArgumentException JavaDoc( );
188             }
189             
190             String JavaDoc baseDir = (String JavaDoc)file.getAttribute( BASE_DIR_ATTRIBUTE );
191             if( baseDir != null ) {
192                 baseDir = parseBaseDirAttribute( baseDir );
193             }
194             
195             Enumeration JavaDoc attributes = file.getAttributes( );
196             
197             while( attributes.hasMoreElements( ) ) {
198                 String JavaDoc attr = (String JavaDoc)attributes.nextElement( );
199                 
200                 if( !attr.equals( INSTANCE_CLASS ) &&
201                 !attr.equals( INSTANCE_CREATE ) &&
202                 !attr.equals( BASE_DIR_ATTRIBUTE ) ) {
203                     String JavaDoc value = (String JavaDoc)file.getAttribute( attr );
204                     parseAttribute( attr, value, baseDir );
205                 }
206             }
207         }
208         catch( Exception JavaDoc e ) {
209             ErrorManager manager =
210             ErrorManager.getDefault( ).getInstance( "org.netbeans.spi.enode" );
211             manager.notify( ErrorManager.INFORMATIONAL, e );
212         }
213     }
214     
215     //=======================================================================
216
// Public methods
217

218     /**
219      * Factory method that creates a new <tt>IconSet</tt> from the given
220      * file object.
221      *
222      * @param file The file defining the contents of the <tt>IconSet</tt>.
223      */

224     public static IconSet getInstance( FileObject file ) {
225         if( theIconSetCache == null ) {
226             theIconSetCache = new HashMap JavaDoc( );
227         }
228
229         Object JavaDoc key = file.getPath( );
230         TimedSoftReference ref = null;
231         synchronized (theIconSetCache) {
232             ref = (TimedSoftReference)theIconSetCache.get(key);
233         }
234         IconSet instance = null;
235         if (ref != null) {
236             instance = (IconSet)ref.get();
237         }
238         if (instance == null) {
239             instance = new IconSet( file );
240             synchronized (theIconSetCache) {
241                 theIconSetCache.put(key, new TimedSoftReference(instance, theIconSetCache, key));
242             }
243         }
244         
245         return instance;
246     }
247     
248     
249     /**
250      * Sets the delegate <tt>IconSet</tt>. Delegates allow to chain
251      * icon sets. When the icon cannot be found in this set, it will
252      * be taken from the delegate instead.
253      *
254      * @param set The icon set that shall be used as delegate.
255      *
256      * @throws IllegalStateException The delegate was defined already.
257      */

258     public void setDelegate( IconSet set ) {
259         if( myDelegate != null ) {
260             throw new IllegalStateException JavaDoc();
261         }
262         
263         myDelegate = set;
264     }
265     
266     /**
267      * Returns the delegate <tt>IconSet</tt>. Delegates allow to chain
268      * icon sets. When the icon cannot be found in this set, it will
269      * be taken from the delegate instead.
270      *
271      * @return the delegate or <code>null</code> if the delegate has not
272      * been set
273      */

274     public IconSet getDelegate() {
275         return myDelegate;
276     }
277     
278     
279     /**
280      * Returns the default icon size of this <tt>IconSet</tt>.
281      *
282      * @return The default icon size.
283      */

284     public int getDefaultSize( ) {
285         return myDefaultSize;
286     }
287     
288     
289     /**
290      * Returns the icon defined by the name and icon size.
291      *
292      * @param name The name of the icon.
293      * @param size The size of the icon.
294      *
295      * @return The icon defined by the name or size or a default
296      * icon with the given size.
297      */

298     public ImageIcon JavaDoc getIcon(String JavaDoc name, int size) {
299         ImageIcon JavaDoc icon = null;
300         String JavaDoc file = null;
301         
302         //
303
// Name not defined -> load default icon
304
//
305
if (name == null) {
306             String JavaDoc key = "" + DEFAULT_MARK + size;
307             name = (String JavaDoc) myIcons.get(key);
308             
309             if (name == null) {
310                 if (myDelegate != null) {
311                     return myDelegate.getIcon(name,size) ;
312                 } else {
313                     ErrorManager.getDefault().getInstance("org.netbeans.spi.enode").notify(
314                         ErrorManager.INFORMATIONAL,
315                         new IllegalStateException JavaDoc(
316                             "Icon with the size " + size + " does not exist")
317                     );
318                 }
319             }
320             
321             file = (String JavaDoc)myIcons.get(makeKey(name, size));
322             
323         } else {
324             file = (String JavaDoc)myIcons.get(makeKey(name, size));
325             
326             //
327
// Try default icon if needed -> max 1 recursion
328
//
329
if( file == null ) {
330                 return getIcon(null, size);
331             }
332         }
333         
334         if (file == null && myDelegate != null ) {
335             icon = myDelegate.getIcon(name, size);
336         } else {
337             Logger JavaDoc logger = Logger.getLogger("org.netbeans.spi.enode");
338             logger.finest( "Loading MO symbol from file " + file );
339             
340             if (file == null) {
341                 ErrorManager.getDefault().getInstance("org.netbeans.spi.enode").notify(
342                 ErrorManager.INFORMATIONAL,
343                 new IllegalStateException JavaDoc("File cannot be computed for name " + name));
344             }
345             
346             icon = NbIcon.loadIcon( file, size, name );
347         }
348         
349         return icon;
350     }
351     
352     
353     /**
354      * Returns the default icon for the given size.
355      *
356      * @return The default icon for the given size. If no default icon
357      * is defined a default icon with the given size is returned.
358      */

359     public ImageIcon JavaDoc getDefaultIcon( int size ) {
360         return getIcon( null, size );
361     }
362     
363     
364     /**
365      * Returns the default icon with the default size.
366      *
367      * @return The default icon for the default size. If no default icon
368      * is defined a default icon with the default size is returned.
369      *
370      * qsee #getDefaultSize
371      */

372     public ImageIcon JavaDoc getDefaultIcon( ) {
373         return getIcon( null, getDefaultSize( ) );
374     }
375     
376     /**
377      * Returns the description of this <tt>IconSet</tt>.
378      *
379      * @return The description of this <tt>IconSet</tt>.
380      */

381     public String JavaDoc getDescription( ) {
382         return myDescription;
383     }
384     
385     /**
386      * provides the display name of the icon taken from the bundle file
387      * configured for the <tt>IconSet</tt>. If no bundle file was defined
388      * or if no entry was found the internal name is returned and an
389      * exception is logged.
390      *
391      * @param name The internal name of the icon.
392      *
393      * @return The localized display name of the icon.
394      */

395     public String JavaDoc getIconDisplayName( String JavaDoc name ) {
396         String JavaDoc display = null;
397         
398         try {
399             display = NbBundle.getBundle( myBundle ).getString( name );
400         }
401         catch( MissingResourceException JavaDoc e ) {
402             ErrorManager manager =
403             ErrorManager.getDefault( ).getInstance( "org.netbeans.spi.enode" );
404             manager.notify( ErrorManager.INFORMATIONAL, e );
405             
406             display = name;
407         }
408         
409         return display;
410     }
411     
412     
413     /**
414      * Returns the names of all icons configured in this <tt>IconSet</tt>
415      * that match the given size.
416      *
417      * @param size The icon size.
418      *
419      * @return The names of all icons with the given size.
420      */

421     public String JavaDoc[] getAllIconNames( int size ) {
422         ArrayList JavaDoc list = new ArrayList JavaDoc( );
423         Iterator JavaDoc iterator = myIcons.keySet( ).iterator( );
424         
425         while( iterator.hasNext( ) ) {
426             String JavaDoc key = (String JavaDoc)iterator.next( );
427             
428             if( !isDefaultKey( key ) ) {
429                 int iconSize = parseSize( key, getDefaultSize( ) );
430                 
431                 if( iconSize == size ) {
432                     list.add( parseName( key ) );
433                 }
434             }
435         }
436         
437         String JavaDoc[] icons = new String JavaDoc[list.size( )];
438         
439         return (String JavaDoc[])list.toArray( icons );
440     }
441     
442     
443     //=======================================================================
444
// Private methods
445

446     /**
447      * Truncates the suffix <tt>.properties</tt> from the given attribute
448      * value and prepends the base dir if it was defined.
449      *
450      * @param value The value of the <tt>bundle</tt> attribute.
451      *
452      * @return The bundle file name without <tt>.properties</tt> suffix.
453      */

454     private void parseBundleAttribute( String JavaDoc baseDir, String JavaDoc bundle ) {
455         myBundle = bundle;
456         
457         if( myBundle != null &&
458         myBundle.toLowerCase( ).endsWith( PROPERTIES ) ) {
459             int index = myBundle.length( ) - PROPERTIES.length( );
460             myBundle = myBundle.substring( 0, index );
461         }
462         
463         if( baseDir != null ) {
464             myBundle = baseDir + myBundle;
465         }
466         
467     }
468     
469     
470     /**
471      * Parses the given attribute value into an integer.
472      *
473      * @param value The value of the <tt>defaultSize</tt> attribute.
474      *
475      * @return The value of the <tt>defaultSize</tt> attribute or
476      * <tt>SIZE_16x16</tt> if the value could not be parsed into
477      * an integer.
478      */

479     private void parseDefaultSizeAttribute( String JavaDoc value ) {
480         myDefaultSize = NbIcon.SIZE_16x16;
481         
482         try {
483             myDefaultSize = Integer.parseInt( value );
484         }
485         catch( NumberFormatException JavaDoc nfe ) {
486             ErrorManager manager =
487             ErrorManager.getDefault( ).getInstance( "org.netbeans.spi.enode" );
488             manager.notify( ErrorManager.INFORMATIONAL, nfe );
489         }
490     }
491     
492     
493     /**
494      * Adds tailing / to the value if needed and removes leading /
495      * from the path.
496      *
497      * @param value The value of the <tt>baseDir</tt> attribute.
498      *
499      * @return The base dir path without leading / and with tailing /.
500      */

501     private static String JavaDoc parseBaseDirAttribute( String JavaDoc value ) {
502         String JavaDoc baseDir = value;
503         
504         if( baseDir.charAt( baseDir.length( ) - 1 ) != '/' ) {
505             baseDir = value + '/';
506         }
507         
508         if( value.charAt( 0 ) == '/' ) {
509             baseDir = baseDir.substring( 1 );
510         }
511         
512         return baseDir;
513     }
514     
515     
516     /**
517      * Parses the attribute with the given name and value. For any well
518      * known attribute this means to parse the value and store it in a
519      * data member. All other attributes are treated as icon definitions.
520      *
521      * @param attribute The name of the attribute.
522      * @param value The value of the attribute.
523      */

524     private void parseAttribute( String JavaDoc attribute, String JavaDoc value, String JavaDoc baseDir ) {
525         //
526
// Get rid of leading or tailing spaces
527
//
528
value = value.trim( );
529         attribute = attribute.trim( );
530         
531         if( attribute.equals( DESCRIPTION_ATTRIBUTE ) ) {
532             myDescription = value;
533         }
534         else if( attribute.equals( BUNDLE_ATTRIBUTE ) ) {
535             parseBundleAttribute( baseDir, value );
536         }
537         else if( attribute.equals( DEFAULT_SIZE_ATTRIBUTE ) ) {
538             parseDefaultSizeAttribute( value );
539         }
540         else {
541             parseIconAttribute( attribute, baseDir, value );
542         }
543     }
544     
545     /**
546      * Adds an icon defintion to this <tt>IconSet</tt>.
547      *
548      * @param attribute The attribute name. Defines name and size
549      * of the icon (and might mark the icon as default icon).
550      * @param baseDir The base dir of the icon set.
551      * @param bitmap The file name of the icon.
552      */

553     private void parseIconAttribute( String JavaDoc attribute, String JavaDoc baseDir, String JavaDoc bitmap ) {
554         boolean defaultIcon = false;
555         
556         //
557
// Attribute name starts with * -> remove
558
// the star and set the defaultIcon flag
559
//
560
if( attribute.charAt( 0 ) == DEFAULT_MARK ) {
561             defaultIcon = true;
562             attribute = attribute.substring( 1 );
563         }
564         
565         if( baseDir != null ) {
566             bitmap = baseDir + bitmap;
567         }
568         
569         myIcons.put( attribute, bitmap );
570         
571         //
572
// Keep indirect reference to default icon key
573
//
574
if( defaultIcon ) {
575             int size = parseSize( attribute, getDefaultSize( ) );
576             String JavaDoc key = "" + DEFAULT_MARK + size;
577             attribute = parseName( attribute );
578             myIcons.put( key, attribute );
579         }
580     }
581     
582     
583     /**
584      * Checks if the given string starts with the {@link
585      * #DEFAULT_MARK} character indicating that it refers to a default
586      * icon entry.
587      *
588      * @param key The key to be checked.
589      *
590      * @return <tt>true</tt> if the key starts with the {@link
591      * #DEFAULT_MARK} character, <tt>false</tt> otherwise.
592      */

593     private static boolean isDefaultKey( String JavaDoc key ) {
594         return key.charAt( 0 ) == DEFAULT_MARK;
595     }
596     
597     
598     /**
599      * Parses the size out of the attribute name. The size is the
600      * suffix of the attribute name after the {@link #SIZE_MARK}
601      * character.
602      *
603      * @param attribute The attribute name.
604      * @param defaultSize The default size.
605      *
606      * @return The size coded in the attribute name or the default
607      * size if the attribute name did not contain any proper
608      * size value.
609      */

610     private static int parseSize( String JavaDoc attribute, int defaultSize ) {
611         int size = defaultSize;
612         
613         try {
614             int start = attribute.lastIndexOf( SIZE_MARK );
615             String JavaDoc suffix = attribute.substring( start + 1 );
616             size = Integer.parseInt( suffix );
617         }
618         catch( Exception JavaDoc e ) {
619             ErrorManager manager =
620             ErrorManager.getDefault( ).getInstance( "org.netbeans.spi.enode" );
621             manager.notify( ErrorManager.INFORMATIONAL, e );
622         }
623         
624         return size;
625     }
626     
627     /**
628      * Parses the name of an icon from an icon attribute name. The name is
629      * the prefix of the attribute name before the {@link #SIZE_MARK}
630      * character without leading {@link #DEFAULT_MARK} character.
631      *
632      * @param attribute The attribute name.
633      *
634      * @return The name of the icon without tailing size value or leading
635      * default marker.
636      */

637     private static String JavaDoc parseName( String JavaDoc attribute ) {
638         String JavaDoc name = attribute;
639         
640         int index = attribute.lastIndexOf( SIZE_MARK );
641         
642         if( index > 0 ) {
643             name = attribute.substring( 0, index );
644         }
645         
646         return name;
647     }
648     
649     /**
650      * Creates a lookup key for this icon set. The key contains out of
651      * the icon name and the icon size.
652      *
653      * @param name The name of the icon.
654      * @param size The icon size.
655      *
656      * @return A string with pattern &lt;name&lt;#&lt;size&gt;
657      */

658     private static String JavaDoc makeKey( String JavaDoc name, int size ) {
659         return name + SIZE_MARK + size;
660     }
661 }
662
663
Popular Tags