Statistics
| Revision:

root / trunk / libraries / libFMap / src / com / iver / cit / gvsig / fmap / rendering / ZSort.java @ 30082

History | View | Annotate | Download (10.5 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2005 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
package com.iver.cit.gvsig.fmap.rendering;
42

    
43
import java.util.Hashtable;
44

    
45
import com.iver.cit.gvsig.fmap.core.symbols.IMultiLayerSymbol;
46
import com.iver.cit.gvsig.fmap.core.symbols.ISymbol;
47
import com.iver.cit.gvsig.fmap.layers.LegendChangedEvent;
48
import com.iver.utiles.IPersistence;
49
import com.iver.utiles.XMLEntity;
50

    
51
/**
52
 * Class ZSort is used in order to store information about the symbols
53
 * which are placed in the Z axis (because a level of symbols has been
54
 * used).
55
 *
56
 * @author jaume dominguez faus - jaume.dominguez@iver.es
57
 */
58
public class ZSort implements IPersistence, LegendContentsChangedListener {
59
        private static final String COLUMN_SEPARATOR = ",";
60
        private static final String ROW_SEPARATOR = ";";
61
        private int[][] matrix;
62
        private boolean usingZSort;
63
        private Hashtable<ISymbol, Integer> symbols = new Hashtable<ISymbol, Integer>();
64

    
65
        public ZSort(ILegend legend) {
66
                initialize(legend);
67
        }
68

    
69
        private void initialize(ILegend legend) {
70
                ISymbol[] symbols;
71
                if (legend instanceof IClassifiedLegend) {
72
                        symbols = ((IClassifiedLegend) legend).getSymbols();
73

    
74
                } else {
75
                        symbols = new ISymbol[] {legend.getDefaultSymbol()};
76
                }
77
                matrix = new int[symbols.length][];
78

    
79
                for (int i = 0; i < symbols.length; i++) {
80
                        this.symbols.put(symbols[i], i);
81
                        int rowLength =  symbols[i] instanceof IMultiLayerSymbol ?
82
                           ((IMultiLayerSymbol) symbols[i]).getLayerCount() :
83
                         1;
84
                        matrix[i] = new int[rowLength];
85
                }
86
                legend.addLegendListener(this);
87
        }
88

    
89
        private void addSymbol(ISymbol sym){
90
                if(!symbols.contains(sym)){
91
                        int rowLength =  sym instanceof IMultiLayerSymbol ?
92
                                        ((IMultiLayerSymbol) sym).getLayerCount() : 1;
93
                        int[][] auxMatrix = new int[matrix.length+1][];
94
                        int newIndex = matrix.length;
95
                        for (int i=0; i<newIndex; i++){
96
                                auxMatrix[i] = matrix[i];
97
                        }
98
                        int[] row = new int[rowLength];
99
                        for (int i=0; i<rowLength; i++){
100
                                row[i] = 0;
101
                        }
102
                        auxMatrix[newIndex] = row;
103
                        matrix = auxMatrix;
104
                        this.symbols.put(sym, newIndex);
105
                }
106
        }
107

    
108
        public void legendChanged(LegendChangedEvent e) {
109
                symbols.clear();
110
                usingZSort = false;
111
                initialize(e.getNewLegend());
112

    
113
        }
114

    
115
        public String getClassName() {
116
                return getClass().getName();
117
        }
118

    
119
        public XMLEntity getXMLEntity() {
120
                XMLEntity xml = new XMLEntity();
121
                xml.putProperty("className", getClassName());
122

    
123
                /*
124
                 * ADVICE:
125
                 * don't try to persist symbols!!
126
                 * they are already persisted by the legend!!!
127
                 */
128

    
129
                xml.putProperty("usingZSort", isUsingZSort());
130

    
131

    
132
                String strMatrix = "";
133
                for (int i = 0; i < matrix.length; i++) {
134
                        int[] row = matrix[i];
135
                        String strRow = "";
136
                        for (int j = 0; j < row.length; j++) {
137
                                strRow += matrix[i][j] + COLUMN_SEPARATOR;
138
                        }
139
                        strMatrix += strRow + ROW_SEPARATOR;
140
                }
141

    
142
                xml.putProperty("matrix", strMatrix);
143
                return xml;
144
        }
145

    
146
        public void setXMLEntity(XMLEntity xml) {
147
                setUsingZSort(xml.getBooleanProperty("usingZSort"));
148

    
149
                /*
150
                 * ADVICE:
151
                 * don't try to initialize the symbols!!
152
                 * they must be initialized by the legend!!!
153
                 */
154

    
155
                String strMatrix = xml.getStringProperty("matrix");
156
                String[] strRows = strMatrix.split(ROW_SEPARATOR);
157

    
158
                matrix = new int[strRows.length][];
159
                for (int i = 0; i < strRows.length; i++) {
160
                        String[] strColumns = strRows[i].split(COLUMN_SEPARATOR);
161
                        matrix[i] = new int[strColumns.length];
162
                        for (int j = 0; j < strColumns.length; j++) {
163
                                matrix[i][j] = Integer.parseInt(strColumns[j]);
164
                        }
165
                }
166
        }
167

    
168

    
169
        public int getLevelCount() {
170
                int count = -1;
171
                for (int i = 0; i < matrix.length; i++) {
172
                        for (int j = 0; j < matrix[i].length; j++) {
173
                                count = Math.max(count, matrix[i][j]);
174
                        }
175
                }
176
                return count + 1;
177
        }
178

    
179

    
180
        public void setUsingZSort(boolean usingZSort) {
181
                this.usingZSort = usingZSort;
182
        }
183

    
184
        public void setLevels(ISymbol sym, int[] values) {
185
                setLevels(symbols.get(sym), values);
186
        }
187

    
188

    
189
        public void setLevels(int row, int[] values) {
190
                matrix[row] = values;
191
        }
192

    
193
        public int[] getLevels(ISymbol sym) {
194
                Integer row = symbols.get(sym);
195
                if (row != null) {
196
                        return getLevels(row);
197
                } else {
198
                        ISymbol[] theSymbols = getSymbols();
199
                        for (int i = 0; i < theSymbols.length; i++) {
200
                                ISymbol auxSymbol = theSymbols[i];
201
                                if (auxSymbol.equals(sym)){
202
                                        return getLevels(symbols.get(auxSymbol));
203
                                }
204
                        }
205
                }
206
                return null;
207
        }
208

    
209

    
210
        public int[] getLevels(int row) {
211
                return matrix[row];
212
        }
213

    
214

    
215
        public boolean isUsingZSort() {
216
                return usingZSort;
217
        }
218

    
219

    
220
        public ISymbol[] getSymbols() {
221
                return symbols.keySet().toArray(new ISymbol[0]);
222
        }
223

    
224

    
225
        public String[] getDescriptions() {
226
                ISymbol[] symbols = getSymbols();
227
                String[] descs = new String[symbols.length];
228
                for (int i = 0; i < descs.length; i++) {
229
                        descs[i] = symbols[i].getDescription();
230
                }
231
                return descs;
232
        }
233
        
234
        public void copyLevels(ZSort zsort) {
235
                ISymbol[] syms = zsort.getSymbols();
236
                for (int i=0; i<syms.length; i++){
237
                        ISymbol sym = syms[i];
238
                        int[] levels = zsort.getLevels(sym);
239
                        if (levels!=null){
240
                                ISymbol[] mySymbols = getSymbols();
241
                                for (int j = 0; j < mySymbols.length; j++) {
242
                                        ISymbol auxSymbol = mySymbols[j];
243
                                        if (auxSymbol.equals(sym)){
244
                                                setLevels(auxSymbol, levels);
245
                                        }
246
                                }
247
                        }
248
                }
249
        }
250

    
251

    
252
        /*
253
         * [PACO] Comentarizado porque no hace lo que se esperar?a de ?l.
254
         * Si tenemos una leyenda con un simbolo Multilayer compuesto
255
         * por, entre otros, un simbolo simple que coincide con otro de
256
         * los simbolos de la leyenda, este metodo devuelve el nivel
257
         * del s?mbolo que encuentra primero.
258
         *
259
         * Se ha eliminado cualquier referencia a este metodo en el resto
260
         * del workspace, sustituyendola convenientemente por
261
         * referencias a getLevels.
262
         */
263
//        public int getSymbolLevel(ISymbol layer) {
264
//                ISymbol[] theSymbols = getSymbols();
265
//
266
//                for (int i = 0; i < theSymbols.length; i++) {
267
//                        ISymbol mySymbol = theSymbols[i];
268
//
269
//                        if (mySymbol instanceof IMultiLayerSymbol) {
270
//                                IMultiLayerSymbol multiSym = (IMultiLayerSymbol) mySymbol;
271
//                                for (int j = 0; j < multiSym.getLayerCount(); j++) {
272
//                                        ISymbol myInnerSymbol = multiSym.getLayer(j);
273
//                                        if (myInnerSymbol.equals(layer)) {
274
//                                                int row = symbols.get(multiSym);
275
//                                                return matrix[row][j];
276
//                                        }
277
//                                }
278
//                        } else {
279
//                                if (mySymbol.equals(layer)){
280
//                                        return matrix[symbols.get(mySymbol)][0];
281
//                                }
282
//                        }
283
//                }
284
//
285
////                return 0;
286
//                return -1;
287
//        }
288

    
289

    
290
        public int getTopLevelIndexAllowed() {
291
                ISymbol[] symbols = getSymbols();
292
                int count=0;
293
                for (int i = 0; i < symbols.length; i++) {
294
                        if (symbols[i] instanceof IMultiLayerSymbol) {
295
                                IMultiLayerSymbol mSymbol = (IMultiLayerSymbol) symbols[i];
296
                                count = Math.max(count, mSymbol.getLayerCount());
297
                        } else
298
                                count = Math.max(count, 1);
299
                }
300
                return count;
301
        }
302

    
303
        @Override
304
        public String toString() {
305
                String out = "Symbols:\n---------\n\n";
306
                ISymbol[] syms = getSymbols();
307
                for (int i = 0; i < syms.length; i++) {
308
                        out += syms.getClass()+":\t"+syms[i].getDescription();
309
                }
310
                out += "\nMatrix:\n--------\n\n";
311
                out += "    \t";
312
                for (int i = 0; i < getTopLevelIndexAllowed(); i++) {
313
                        out += "column"+i+"\t\t";
314
                }
315
                out += "\n";
316
                for (int i = 0; i < matrix.length; i++) {
317
                        out += "row "+i+":\t";
318
                        for (int j = 0; j < matrix[i].length; j++) {
319
                                out += matrix[i][j]+"\t\t";
320
                        }
321
                        out += "\n";
322
                }
323
                return out;
324
        }
325

    
326
        private void replaceSymbol(ISymbol oldSymbol, ISymbol newSymbol) {
327
                if (oldSymbol == newSymbol) return;
328

    
329
                if(oldSymbol != null){
330
                        Integer value = symbols.get(oldSymbol);
331
                        if (value != null){
332
                                if (newSymbol == null) {
333
                                        // emptying
334
                                        symbols.remove(oldSymbol);
335
                                        matrix[value] = new int[1];
336
                                } else {
337
                                        symbols.remove(oldSymbol);
338

    
339
                                        symbols.put(newSymbol, value);
340

    
341
                                        // update matrix values if need
342
                                        int newArrayLength = newSymbol instanceof IMultiLayerSymbol ?
343
                                                        ((IMultiLayerSymbol) newSymbol).getLayerCount() : 1;
344

    
345
                                                        int[] newRow = new int[newArrayLength];
346
                                                        if (matrix[value].length == newArrayLength) {
347
                                                                /*
348
                                                                 * the new row is exactly the same long than the
349
                                                                 * old one. Will use the old values
350
                                                                 */
351
                                                                newRow = matrix[value];
352
                                                        } else        if (matrix[value].length < newArrayLength) {
353
                                                                /*
354
                                                                 * the new row is larger than the old one,
355
                                                                 * let's copy all the first values and fill
356
                                                                 * the rest with the last copied value
357
                                                                 */
358
                                                                int val=0;
359
                                                                for (int i = 0; i < newRow.length; i++) {
360
                                                                        if (i<matrix[value].length) {
361
                                                                                val = matrix[value][i];
362
                                                                        }
363

    
364
                                                                        newRow[i] = val;
365
                                                                }
366
                                                        } else if (matrix[value].length > newArrayLength) {
367
                                                                /*
368
                                                                 * the new row is smaller than the old one,
369
                                                                 * let's copy the first values
370
                                                                 */
371
                                                                for (int i = 0; i < newRow.length; i++) {
372
                                                                        newRow[i] = matrix[value][i];
373
                                                                }
374
                                                        }
375
                                                        matrix[value] = newRow;
376
                                }
377
                        }
378
                } else {
379
                        addSymbol(newSymbol);
380
                }
381
        }
382

    
383
        public boolean symbolChanged(SymbolLegendEvent e) {
384
                replaceSymbol(e.getOldSymbol(), e.getNewSymbol());
385
                return true;
386
        }
387

    
388

    
389
        public boolean classifiedSymbolChange(SymbolLegendEvent e) {
390
                replaceSymbol(e.getOldSymbol(), e.getNewSymbol());
391
                return true;
392
        }
393

    
394
        public boolean intervalChange(IntervalLegendEvent e) {
395
                return false;
396
        }
397

    
398
        public boolean valueChange(ValueLegendEvent e) {
399
                return false;
400
        }
401

    
402
        // TODO should not exist here
403
        public boolean labelFieldChange(LabelLegendEvent e) {
404
                return false;
405
        }
406

    
407

    
408
        public void legendCleared(LegendClearEvent event) {
409
//                this.usingZSort = false;
410
//                symbols.clear();
411
//                matrix = null;
412
        }
413
}
414