Statistics
| Revision:

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

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
import com.iver.andami.Utilities;
62

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

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

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

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

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