Statistics
| Revision:

root / trunk / frameworks / _fwAndami / src / com / iver / andami / iconthemes / IconThemeManager.java @ 11064

History | View | Annotate | Download (12 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2007 IVER T.I. and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 *
19
 * For more information, contact:
20
 *
21
 *  Generalitat Valenciana
22
 *   Conselleria d'Infraestructures i Transport
23
 *   Av. Blasco Ib??ez, 50
24
 *   46010 VALENCIA
25
 *   SPAIN
26
 *
27
 *      +34 963862235
28
 *   gvsig@gva.es
29
 *      www.gvsig.gva.es
30
 *
31
 *    or
32
 *
33
 *   IVER T.I. S.A
34
 *   Salamanca 50
35
 *   46005 Valencia
36
 *   Spain
37
 *
38
 *   +34 963163400
39
 *   dac@iver.es
40
 */
41

    
42
package com.iver.andami.iconthemes;
43

    
44
import java.io.File;
45
import java.io.FileInputStream;
46
import java.io.FileNotFoundException;
47
import java.io.FilenameFilter;
48
import java.io.IOException;
49
import java.io.InputStream;
50
import java.net.MalformedURLException;
51
import java.util.ArrayList;
52
import java.util.Enumeration;
53
import java.util.zip.ZipEntry;
54
import java.util.zip.ZipException;
55
import java.util.zip.ZipFile;
56

    
57
import org.kxml2.io.KXmlParser;
58
import org.xmlpull.v1.XmlPullParserException;
59

    
60
import com.iver.andami.Launcher;
61

    
62
/**
63
 * <p>This class deals with icon themes, it understands the on-disk theme
64
 * format, it is able to list the availabe themes, to get the default
65
 * theme and to change it.</p>
66
 * 
67
 * <p>A XML theme description file should look similar to:
68
 * <pre>
69
 * &lt;?xml version="1.0" encoding="utf-8"?&gt;
70
 * &lt;theme&gt;
71
 *        &lt;name&gt;Default gvSIG icon theme&lt;/name&gt;
72
 *        &lt;description&gt;Clear fancy super great icon theme for gvSIG. Author: Salvador Dal?, &amp;lt;salvador.dali@art.org&amp;gt;&lt;/description&gt;
73
 *        &lt;version&gt;1.2&lt;/version&gt;
74
 * &lt;/theme&gt;
75
 * </pre>
76
 *   
77
 * 
78
 * @author Cesar Martinez Izquierdo <cesar.martinez@iver.es>
79
 *
80
 */
81
public class IconThemeManager {
82
        private File themesDir = null;
83
        private final String themeDefinitionFile = "theme.xml";
84
        private IconTheme defaultTheme = null;
85

    
86
        /**
87
         * 
88
         * @param themesDir
89
         */
90
        public IconThemeManager(File themesDir) throws FileNotFoundException {
91
                if (!themesDir.exists())
92
                        throw new FileNotFoundException();
93
                this.themesDir = themesDir;        
94
        }
95
        
96
        /**
97
         * 
98
         * @param themesDir
99
         */
100
        public IconThemeManager() {        }
101
        
102
        
103
        public IconTheme get(String themeName) {
104
                IconThemeInfo[] themeList = list();
105
                for (int i=0; i<themeList.length; i++) {
106
                        if (themeList[i].getName().equals(themeName)) {
107
                                return get(themeList[i]);
108
                        }
109
                }
110
                return null;
111
        }
112
        
113
        public IconTheme get(IconThemeInfo themeInfo) {
114
                IconTheme theme = new IconTheme(themeInfo);
115
                if (themeInfo.getResource()==null) {
116
                        // no real theme was selected
117
                        return theme;
118
                }
119
                if (themeInfo.getResource() instanceof File) {
120
                        File basedir = (File) themeInfo.getResource();
121
                        if (basedir.isDirectory()) {
122
                                //TODO: crear el filtro de im?genes
123
                                File[] imageList = basedir.listFiles(new ImageFileFilter());
124
                                String name;
125
                                for (int i=imageList.length-1; i>=0; i--) {
126
                                        name = computeKey(imageList[i].getName());
127
                                        try {
128
                                                theme.register(name, imageList[i].toURL());
129
                                                System.out.println("registerning "+name+": "+imageList[i].toURL());
130
                                        } catch (MalformedURLException e) {}
131
                                }
132
                        }
133
                        else {
134
                                return null;
135
                        }
136
                }
137
                else if (themeInfo.getResource() instanceof ZipFile) {
138
                        ZipFile zipFile = (ZipFile) themeInfo.getResource();
139
                        ImageFileFilter filter = new ImageFileFilter();
140
                        Enumeration entries = zipFile.entries();
141
                        while (entries.hasMoreElements()) {
142
                                ZipEntry entry = (ZipEntry) entries.nextElement();
143
                                if (!entry.isDirectory() ) {
144
                                        if (filter.accept(new File(zipFile.getName()), entry.getName())) {
145
                                                theme.register(computeKey(entry.getName()), entry);
146
                                                System.out.println("registerning "+computeKey(entry.getName())+": "+entry.getName());
147
                                        }
148
                                }
149
                        }
150
                }
151
                return theme;
152
        }
153
        
154

    
155
        public IconTheme getDefault() {
156
                if (defaultTheme!=null) 
157
                        return defaultTheme;
158
                init();
159
                return defaultTheme;
160
        }
161
        
162
        public void init() {
163
                IconThemeInfo info = readSelectedFromAndamiConfig();
164
                defaultTheme = get(info);
165
        }
166
        
167

    
168
        
169
        public void setDefault(IconThemeInfo iconTheme) {
170
                /*
171
                 *  TODO Currently we just change it in AndamiConfig, so that on next
172
                 *  gvSIG restart the theme gets changed. However, we could implement
173
                 *  here a real on-the-fly theme change.
174
                 */
175
                saveSelectedInAndamiConfig(iconTheme);
176
        }
177
        
178
        public void setDefault(IconTheme iconTheme) {
179
                setDefault(iconTheme.getInfo());
180
        }
181
        
182
        /**
183
         * 
184
         * @return
185
         */
186
        public IconThemeInfo[] list() {
187
                File[] files = themesDir.listFiles();
188
                if (files==null) return null;
189
                
190
                ArrayList themeList = new ArrayList();
191
                IconThemeInfo info;
192
                for (int i=0; i<files.length; i++) {
193
                        if (files[i].isDirectory()) {
194
                                info = readInfoFromDir(files[i]);
195
                                if (info!=null)
196
                                        themeList.add(info);
197
                        }
198
                        else if (files[i].isFile()) { // ensure it's a regular file
199
                                info = readInfoFromZip(files[i]);
200
                                if (info!=null)
201
                                        themeList.add(info);
202
                        }
203
                }
204
                
205
                return (IconThemeInfo[]) themeList.toArray(new IconThemeInfo[0]);
206
        }
207
        
208
        private IconThemeInfo readInfoFromDir(File dir){
209
                File themeDefinition = new File(dir + File.separator + themeDefinitionFile);
210
                IconThemeInfo themeInfo;
211
                try {
212
                        // try reading the XML file
213
                        if (themeDefinition.exists() && themeDefinition.isFile()) {
214
                                themeInfo = readXML(new FileInputStream(themeDefinition));
215
                                if (themeInfo.getDescription()==null)
216
                                        themeInfo.setDescription(dir.getName());
217
                                if (themeInfo.getName()==null)
218
                                        themeInfo.setName(themeInfo.getDescription());
219
                                themeInfo.setResource(dir);
220
                                return themeInfo;
221
                        }
222
                } catch (IOException e) {}
223
                catch (XmlPullParserException e) {
224
                        e.printStackTrace();
225
                }
226
                // the XML parsing failed, just show the dir name
227
                themeInfo = new IconThemeInfo();
228
                themeInfo.setName(dir.getName());
229
                themeInfo.setDescription(dir.getName());
230
                themeInfo.setResource(dir);
231
                return themeInfo;
232
        }
233
        
234
        private IconThemeInfo readXML(InputStream xmlStream) throws XmlPullParserException, IOException {
235
                KXmlParser parser = new KXmlParser();
236
                // we use null encoding, in this way kxml2 tries to detect the encoding                
237
                parser.setInput(xmlStream, null);
238
                IconThemeInfo themeInfo = new IconThemeInfo();
239
                for (parser.next(); parser.getEventType()!=KXmlParser.END_DOCUMENT; parser.next()) {
240
                        // este bucle externo recorre las etiquetas de primer y segundo nivel
241
                        if (parser.getEventType()==KXmlParser.START_TAG) {
242
                                if (parser.getName().equals("name")) {
243
                                        themeInfo.setName(parser.nextText());
244
                                }
245
                                else if (parser.getName().equals("description")) {
246
                                        themeInfo.setDescription(parser.nextText());
247
                                }
248
                                else if (parser.getName().equals("version")) {
249
                                        themeInfo.setVersion(parser.nextText());
250
                                }
251
                        }
252
                }
253
                return themeInfo;
254
        }
255
        
256
        private IconThemeInfo readInfoFromZip(File zipFile) {
257
                try {
258
                        ZipFile file = new ZipFile(zipFile);
259
                        IconThemeInfo themeInfo;
260
                        Enumeration entries = file.entries();
261
                        ZipEntry xmlEntry=null, dirEntry=null;
262
                        // search for theme.xml and the directory names
263
                        while (entries.hasMoreElements() && (xmlEntry==null||dirEntry==null)) {
264
                                ZipEntry entry = (ZipEntry) entries.nextElement();
265
                                if (entry.isDirectory()) {
266
                                        dirEntry = entry;
267
                                }
268
                                if (basename(entry.getName()).equals(themeDefinitionFile)) {
269
                                        xmlEntry = entry;
270
                                }
271
                        }
272

    
273
                        try {
274
                                // try with the XML file
275
                                if (xmlEntry!=null) {
276
                                        themeInfo = readXML(file.getInputStream(xmlEntry));
277
                                        if (themeInfo.getDescription()==null)
278
                                                themeInfo.setDescription(zipFile.getName());
279
                                        if (themeInfo.getName()==null)
280
                                                themeInfo.setName(themeInfo.getDescription());
281
                                        themeInfo.setResource(zipFile);
282
                                        return themeInfo;
283
                                }
284
                        } catch (XmlPullParserException e) {
285
                                e.printStackTrace();
286
                                System.out.println(file.getName());
287
                        }
288
                        
289
                        themeInfo = new IconThemeInfo();
290
                        themeInfo.setResource(zipFile);
291
                        // now try with the directory
292
                        if (dirEntry!=null) {                
293
                                themeInfo.setName(dirEntry.getName());
294
                                themeInfo.setDescription(dirEntry.getName());
295
                                return themeInfo;
296
                        }
297
                        else { // otherwise just use the zipName
298
                                themeInfo.setName(zipFile.getName());
299
                                themeInfo.setDescription(zipFile.getName());
300
                                return themeInfo;
301
                        }
302
                        
303
                } catch (ZipException e) {
304
                        // TODO Auto-generated catch block
305
                        e.printStackTrace();
306
                } catch (IOException e) {
307
                        // TODO Auto-generated catch block
308
                        e.printStackTrace();
309
                }
310
                return null;
311
        }
312
        
313
        private String basename(String fullname) {
314
                String[] parts = fullname.split(File.separator+"|/");
315
                return parts[parts.length-1];
316
        }
317
        
318
        public File getThemesDir() {
319
                return themesDir;
320
        }
321
        
322
        public void setThemesDir(File themesDir) {
323
                this.themesDir = themesDir;
324
        }
325
        
326
        private IconThemeInfo readSelectedFromAndamiConfig() {
327
                com.iver.andami.config.generate.IconTheme selectedTheme = null;
328
                if (Launcher.getAndamiConfig().getAndamiOptions()!=null && Launcher.getAndamiConfig().getAndamiOptions().getIconTheme()!=null)
329
                        selectedTheme = Launcher.getAndamiConfig().getAndamiOptions().getIconTheme();
330
                IconThemeInfo info = new IconThemeInfo();
331
                if (selectedTheme!=null) {
332
                        info.setName(selectedTheme.getName());
333
                        if (selectedTheme.getResource()!=null) {
334
                                try {
335
                                        info.setResource(new ZipFile(selectedTheme.getResource()));
336
                                } catch (ZipException e) {
337
                                        info.setResource(new File(selectedTheme.getResource()));
338
                                } catch (IOException e) {
339
                                        info.setResource(new File(selectedTheme.getResource()));
340
                                }
341
                        }
342
                        else {
343
                                info.setResource(null);
344
                        }
345
                        setThemesDir(new File(selectedTheme.getBasedir()));
346
                        if (selectedTheme.getVersion()!=null)
347
                                info.setVersion(selectedTheme.getVersion());
348
                        if (selectedTheme.getDescription()!=null) {
349
                                info.setDescription(selectedTheme.getDescription());
350
                        }
351
                        else {
352
                                info.setDescription(selectedTheme.getName());
353
                        }
354
                }
355
                else {
356
                        info.setName("default");
357
                        info.setDescription("default");
358
                        info.setResource(null); // null resource means that no real theme is loaded
359
                }
360
                return info;
361
        }
362
        
363
        private void saveSelectedInAndamiConfig(IconThemeInfo selectedTheme) {
364
                com.iver.andami.config.generate.AndamiOptions options = Launcher.getAndamiConfig().getAndamiOptions();
365
                if (options==null) {
366
                        options = new com.iver.andami.config.generate.AndamiOptions();
367
                }
368
                com.iver.andami.config.generate.IconTheme themeConfig = options.getIconTheme();
369
                if (themeConfig==null) {
370
                        themeConfig = new com.iver.andami.config.generate.IconTheme(); 
371
                }
372
                themeConfig.setName(selectedTheme.getName());
373
                themeConfig.setDescription(selectedTheme.getDescription());
374
                themeConfig.setVersion(selectedTheme.getVersion());
375
                if (selectedTheme.getResource()!=null) {
376
                        if (selectedTheme.getResource() instanceof File) {
377
                                File resource = (File) selectedTheme.getResource();
378
                                themeConfig.setResource(resource.getName());                                
379
                        }
380
                        else if (selectedTheme.getResource() instanceof ZipFile) {
381
                                ZipFile resource = (ZipFile) selectedTheme.getResource();
382
                                themeConfig.setResource(resource.getName());                                
383
                        }
384
                }
385
        }
386
        
387
        class ImageFileFilter implements FilenameFilter {
388
                public boolean accept(File dir, String fileName) {
389
                        String extension = "";
390
                        int pointPos = fileName.lastIndexOf(".");
391
                        if (pointPos>0 && pointPos < (fileName.length()-1) )
392
                                extension = fileName.substring(pointPos+1).toLowerCase();
393
                        if ( extension.equals("jpg") || extension.equals("jpeg")
394
                                        || extension.equals("png")
395
                                        || extension.equals("gif")
396
                                        
397
                                        )
398
                                return true;
399
                        else
400
                                return false;
401
                }
402
        }
403
        
404
        private String computeKey(String fileName) {
405
                int pointPos = fileName.lastIndexOf(".");
406
                if (pointPos!=-1)
407
                        return fileName.substring(0, pointPos);
408
                else
409
                        return fileName;
410
        }
411
}