Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.swing / org.gvsig.fmap.dal.swing.impl / src / main / java / org / gvsig / fmap / dal / swing / impl / featuretype / DefaultFeatureAttributesSelectionPanel.java @ 47426

History | View | Annotate | Download (19.6 KB)

1
package org.gvsig.fmap.dal.swing.impl.featuretype;
2

    
3
import java.awt.Dimension;
4
import java.awt.event.ActionEvent;
5
import java.awt.event.ActionListener;
6
import java.awt.event.FocusAdapter;
7
import java.awt.event.FocusEvent;
8
import java.awt.event.MouseAdapter;
9
import java.awt.event.MouseEvent;
10
import java.net.URL;
11
import java.util.ArrayList;
12
import java.util.Collections;
13
import java.util.Comparator;
14
import java.util.List;
15
import javax.swing.ImageIcon;
16
import javax.swing.JComponent;
17
import javax.swing.ListCellRenderer;
18
import javax.swing.ListModel;
19
import javax.swing.event.DocumentEvent;
20
import javax.swing.event.DocumentListener;
21
import javax.swing.event.ListSelectionEvent;
22
import org.apache.commons.io.FilenameUtils;
23
import org.apache.commons.lang3.StringUtils;
24
import org.gvsig.expressionevaluator.Expression;
25
import org.gvsig.expressionevaluator.ExpressionEvaluatorLocator;
26
import org.gvsig.expressionevaluator.ExpressionUtils;
27
import org.gvsig.expressionevaluator.swing.ExpressionPickerController;
28
import org.gvsig.fmap.dal.DALLocator;
29
import org.gvsig.fmap.dal.DataTypes;
30
import org.gvsig.fmap.dal.exception.DataException;
31
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
32
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
33
import org.gvsig.fmap.dal.feature.FeatureStore;
34
import org.gvsig.fmap.dal.feature.FeatureType;
35
import org.gvsig.fmap.dal.swing.DALSwingLocator;
36
import org.gvsig.fmap.dal.swing.DataSwingManager;
37
import org.gvsig.fmap.dal.swing.featuretype.FeatureAttributesSelectionPanel;
38
import static org.gvsig.fmap.dal.swing.impl.DefaultDALSwingLibrary.LIBRARY_NAME;
39
import org.gvsig.fmap.dal.swing.impl.expressionevaluator.FeatureStoreElementFactory;
40
import org.gvsig.tools.locator.ReferenceNotRegisteredException;
41
import org.gvsig.tools.swing.api.ActionListenerSupport;
42
import org.gvsig.tools.swing.api.FilteredListController;
43
import org.gvsig.tools.swing.api.FilteredListModel;
44
import org.gvsig.tools.swing.api.ToolsSwingLocator;
45
import org.gvsig.tools.swing.api.ToolsSwingManager;
46
import org.gvsig.tools.swing.api.ToolsSwingUtils;
47
import org.gvsig.tools.swing.icontheme.IconTheme;
48
import org.gvsig.tools.util.LabeledValue;
49

    
50
/**
51
 *
52
 * @author jjdelcerro
53
 */
54
public class DefaultFeatureAttributesSelectionPanel 
55
        extends DefaultFeatureAttributesSelectionPanelView
56
        implements FeatureAttributesSelectionPanel 
57
    {
58

    
59
    private static final String ATTR_IS_EXPRESSION = "DefaultFeatureAttributesSelectionPanel_isExpression";
60

    
61
    private FeatureType featureType;
62
    private final ActionListenerSupport actionListenerSupport;
63
    private FilteredListController availableFieldsController;
64
    private final List<FeatureAttributeDescriptor> selecteds;
65
    private ExpressionPickerController expressionPicker = null;
66
    private boolean allowCalculatedAttributes = false;
67
    private List<EditableFeatureAttributeDescriptor> extraColumns;
68
    private List<String> selectedNames;
69
    
70
    public DefaultFeatureAttributesSelectionPanel() {
71
        this.actionListenerSupport = ToolsSwingLocator.getToolsSwingManager().createActionListenerSupport();
72
        this.selecteds = new ArrayList<>();
73
        this.initComponents();
74
    }
75
    
76
    private void initComponents() {
77
        ToolsSwingManager toolsSwingManager = ToolsSwingLocator.getToolsSwingManager();
78
        ListCellRenderer renderer = DALSwingLocator.getDataSwingManager().createDefaultFeatureAttributeListCellRenderer();
79
//        DefaultListCellRenderer renderer = new DefaultListCellRenderer();
80
        this.lstAvailableColumns.setCellRenderer(renderer);
81
        this.lstSelectedColumns.setCellRenderer(renderer);
82
        
83
        this.lstAvailableColumns.addListSelectionListener((ListSelectionEvent e) -> {
84
          if( e.getValueIsAdjusting() ) {
85
            return;
86
          }
87
          doSelectAvailableColumn();
88
        });
89
        this.lstAvailableColumns.addMouseListener(new MouseAdapter() {
90
            @Override
91
            public void mouseClicked(MouseEvent e) {
92
                if( e.getClickCount()==2 ) {
93
                    doColumnAdd();
94
                }
95
            }
96
            
97
        });
98
        this.lstSelectedColumns.addListSelectionListener((ListSelectionEvent e) -> {
99
          if( e.getValueIsAdjusting() ) {
100
            return;
101
          }
102
          doSelectColumn();
103
        });
104
        this.txtExpression.getDocument().addDocumentListener(new DocumentListener() {
105
            public void changedUpdate(DocumentEvent e) {
106
              doSelectAvailableColumn();
107
            }
108
            @Override
109
            public void insertUpdate(DocumentEvent de) {
110
                 doSelectAvailableColumn();
111
            }
112

    
113
            @Override
114
            public void removeUpdate(DocumentEvent de) {
115
                 doSelectAvailableColumn();
116
            }
117
        });
118
        
119
        this.txtExpression.addFocusListener(new FocusAdapter() {
120
            @Override
121
            public void focusGained(FocusEvent e) {
122
                lstAvailableColumns.getSelectionModel().clearSelection();
123
            }
124
            
125
        });
126
        this.btnColumnAdd.addActionListener((ActionEvent e) -> {
127
          doColumnAdd();
128
        });
129
        this.btnColumnRemove.addActionListener((ActionEvent e) -> {
130
          doColumnRemove();
131
        });
132
        this.btnColumnDown.addActionListener((ActionEvent e) -> {
133
          doColumnDown();
134
        });
135
        this.btnColumnUp.addActionListener((ActionEvent e) -> {
136
          doColumnUp();
137
        });
138
        this.availableFieldsController = toolsSwingManager.createFilteredListController(
139
                lstAvailableColumns, 
140
                txtColumnsFilter, 
141
                btnColumnsFilter
142
        );     
143
        Dimension sz = this.getPreferredSize();
144
        if( sz.width<450 ) {
145
            sz.width = 450;
146
        }
147
        if( sz.height < 320 ) {
148
            sz.height = 320;
149
        }
150
        this.setPreferredSize(sz);
151
    }
152

    
153
    @Override
154
    public List<String> getSelectedNames() {
155
        List<String> names = new ArrayList<>();
156
        for (FeatureAttributeDescriptor selected : selecteds) {
157
                names.add(selected.getName());
158
        }
159
      return names;
160
    }
161

    
162
    @Override
163
    public void setSelectedNames(List<String> names) {
164
        this.selecteds.clear();
165
        if (names != null) {
166
            this.selectedNames = new ArrayList<>(names);
167
            for (String name : names) {
168
                FeatureAttributeDescriptor attr = this.getAttributeDescriptor(name);
169
                if(attr == null){
170
                    if(this.allowCalculatedAttributes && !ExpressionUtils.isValidIdentifier(name)){
171
                        attr = createAttributeFromExpression(name);
172
                    } else {
173
                        continue;
174
                    }
175
                } 
176
                if (selectedContains(attr)) {
177
                    continue;
178
                }
179
                this.selecteds.add(attr);
180
            }
181
        } else {
182
            this.selectedNames = new ArrayList<>();
183
        }
184
        updateControls();
185
    }
186
    
187
    private boolean selectedContains(FeatureAttributeDescriptor attr) {
188
        for (FeatureAttributeDescriptor selected : selecteds) {
189
            if(StringUtils.equalsIgnoreCase(selected.getName(), attr.getName())){
190
                return true;
191
            }
192
        }
193
        return false;
194
    }
195

    
196
    private void doSelectAvailableColumn() {
197
        if( this.lstAvailableColumns.getSelectedIndex()>=0 || !this.expressionPicker.isEmpty()) {
198
            this.btnColumnAdd.setEnabled(true);
199
            return;
200
        }
201
        this.btnColumnAdd.setEnabled(false);
202
    }
203
    
204
    private void doSelectColumn() {
205
        int indexSelecteds = this.lstSelectedColumns.getSelectedIndex();
206
        ListModel modelSelecteds = this.lstSelectedColumns.getModel();
207
        this.btnColumnUp.setEnabled(indexSelecteds >= 1);
208
        this.btnColumnDown.setEnabled(indexSelecteds>=0 && indexSelecteds < modelSelecteds.getSize() - 1);
209

    
210
        
211
        if( this.lstSelectedColumns.getSelectedIndex()>=0 ) {
212
//            FeatureAttributeDescriptor attr = (FeatureAttributeDescriptor) this.lstSelectedColumns.getSelectedValue();
213
//            if( attr != null ) {
214
//              this.selecteds.add(attr.getName());
215
              this.btnColumnRemove.setEnabled(true);
216
//              this.btnColumnDown.setEnabled(true);
217
//              this.btnColumnUp.setEnabled(true);
218
              return;
219
//            }
220
        }
221
        this.btnColumnRemove.setEnabled(false);
222
//        this.btnColumnDown.setEnabled(false);
223
//        this.btnColumnUp.setEnabled(false);
224
    }
225
    
226
    private void doColumnUp() {
227
        LabeledValue attr = (LabeledValue) this.lstSelectedColumns.getSelectedValue();
228
        if( attr == null ) {
229
            return;
230
        }
231
        int n = this.selecteds.indexOf(attr.getValue());
232
        if( n<1 ) {
233
          return;
234
        }
235
        Collections.swap(selecteds, n, n-1);
236
        this.lstSelectedColumns.setSelectedIndex(n-1);
237
        this.updateControls();
238
    }
239

    
240
    private void doColumnDown() {
241
        LabeledValue attr = (LabeledValue) this.lstSelectedColumns.getSelectedValue();
242
        if( attr == null ) {
243
            return;
244
        }
245
        int n = this.selecteds.indexOf(attr.getValue());
246
        if( n<0 || n>=this.selecteds.size()-1 ) {
247
          return;
248
        }
249
        Collections.swap(selecteds, n, n+1);
250
        this.lstSelectedColumns.setSelectedIndex(n+1);
251
        this.updateControls();
252
    }
253
    
254
    private boolean checkIfAttributeInFeatureType(String myAttr) {
255
        for (FeatureAttributeDescriptor attr : featureType) {
256
            if(attr.getName().equalsIgnoreCase(myAttr) ) {
257
               return true;
258
            }
259
        }
260
        List<EditableFeatureAttributeDescriptor> columns = featureType.getExtraColumns().getColumns();
261
        if (columns!=null && !columns.isEmpty()) {
262
            for (EditableFeatureAttributeDescriptor extraCol : columns) {
263
                if(extraCol.getName().equalsIgnoreCase(myAttr)) {
264
                    return true;
265
                }
266
            }
267
        }
268
        if (this.extraColumns!=null && !extraColumns.isEmpty()) {
269
            for (EditableFeatureAttributeDescriptor extraCol : extraColumns) {
270
                if(extraCol.getName().equalsIgnoreCase(myAttr)) {
271
                    return true;
272
                }
273
            }
274
        }
275
        
276
        return false;
277
    }
278

    
279
    private void doColumnRemove() {
280
        FeatureAttributeDescriptor attr = (FeatureAttributeDescriptor) this.lstSelectedColumns.getSelectedValue();
281
        if( attr == null ) {
282
            return;
283
        }
284
        int n = this.selecteds.indexOf(attr);
285
        if( n<0 ) {
286
          return;
287
        }
288
        if(attr.getTags().getBoolean(ATTR_IS_EXPRESSION,false)){
289
            Expression toExp = ExpressionEvaluatorLocator.getManager().createExpression();
290
            toExp.setPhrase(attr.getLabel());
291
            this.expressionPicker.set(toExp);
292
        }
293
        this.selecteds.remove(n);
294
        this.updateControls();
295
    }
296

    
297
    private void doColumnAdd() {
298
        if(this.lstAvailableColumns.getSelectedIndex() >= 0) {
299
            FeatureAttributeDescriptor attr = (FeatureAttributeDescriptor) this.lstAvailableColumns.getSelectedValue();
300
            if( attr == null ) {
301
                return;
302
            }
303
            int n = this.selecteds.indexOf(attr);
304
            if( n>=0 ) {
305
              return;
306
            }
307
            this.selecteds.add(attr);
308
        } else if(!this.expressionPicker.isEmpty()) {
309
            if (this.expressionPicker.isValid()) {
310
                Expression exp = this.expressionPicker.get();
311
                String expressionField = exp.getPhrase();
312
                FeatureAttributeDescriptor attr = createAttributeFromExpression(expressionField);
313
                for (FeatureAttributeDescriptor selected : this.selecteds) {
314
                    if(StringUtils.equals(attr.getName(),selected.getName())){
315
                        return;
316
                    }
317
                }
318
                this.selecteds.add(attr);
319
                this.expressionPicker.set(null);
320
            }
321
        }
322
        this.updateControls();
323
    }
324
    
325
    private FeatureAttributeDescriptor createAttributeFromExpression(String expressionField) {
326
        EditableFeatureAttributeDescriptor attr = DALLocator.getDataManager().createFeatureAttributeDescriptor(expressionField, DataTypes.STRING);
327
        attr.getTags().set(ATTR_IS_EXPRESSION, true);
328
        attr.setLabel(expressionField);
329
        return attr;
330
    }
331

    
332
    @Override
333
    public void setStore(FeatureStore store) {
334
        try {
335
            this.setFeatureType(store.getDefaultFeatureType());
336
        } catch (DataException ex) {
337
            throw new RuntimeException("Can't assign store", ex);
338
        }
339
    }
340

    
341
    @Override
342
    public void setFeatureType(FeatureType featureType) {
343
        this.featureType = featureType;
344
        if(this.selectedNames != null){
345
            this.setSelectedNames(this.selectedNames);
346
        }  else {
347
            this.updateControls();
348
        }
349
    }
350
    @Override
351
    public void setExtraColumns(List<EditableFeatureAttributeDescriptor> extraColumns) {
352
        this.extraColumns = extraColumns;
353
        if(this.selectedNames != null){
354
            this.setSelectedNames(this.selectedNames);
355
        }  else {
356
            this.updateControls();
357
        }
358
    }
359

    
360
    @Override
361
    public FeatureType getFeatureType() {
362
        return this.featureType;
363
    }
364

    
365
    @Override
366
    public JComponent asJComponent() {
367
        return this;
368
    }
369

    
370
    @Override
371
    public void addActionListener(ActionListener al) {
372
        this.actionListenerSupport.addActionListener(al);
373
    }
374

    
375
    @Override
376
    public ActionListener[] getActionListeners() {
377
        return this.actionListenerSupport.getActionListeners();
378
    }
379

    
380
    @Override
381
    public void removeActionListener(ActionListener al) {
382
        this.actionListenerSupport.removeActionListener(al);
383
    }
384

    
385
    @Override
386
    public void removeAllActionListener() {
387
        this.actionListenerSupport.removeAllActionListener();
388
    }
389

    
390
    @Override
391
    public void fireActionEvent(ActionEvent ae) {
392
        this.actionListenerSupport.fireActionEvent(ae);
393
    }
394

    
395
    @Override
396
    public boolean hasActionListeners() {
397
        return this.actionListenerSupport.hasActionListeners();
398
    }
399
    
400
    private void updateControls() {
401
        
402
        if (this.expressionPicker == null) {
403
                this.expressionPicker = 
404
                DALSwingLocator.getDataSwingManager().createExpressionPickerController(
405
                        this.featureType.getStore(), 
406
                        txtExpression, 
407
                        btnExpression, 
408
                        btnBookmarks, 
409
                        btnHistory);
410
        }
411
        int indexAvailables = this.lstAvailableColumns.getSelectedIndex();
412
        int indexSelecteds = this.lstSelectedColumns.getSelectedIndex();
413
        FilteredListModel modelAvailables = ToolsSwingLocator.getToolsSwingManager().createFilteredListModel();
414
        FilteredListModel modelSelecteds = ToolsSwingLocator.getToolsSwingManager().createFilteredListModel();
415
        DataSwingManager dataSwingManager = DALSwingLocator.getDataSwingManager();
416
        List<FeatureAttributeDescriptor> availables = new ArrayList<>();
417
        for (FeatureAttributeDescriptor attr : featureType) {
418
            if (!selectedContains(attr)) {
419
                availables.add(attr);
420
            }
421
        }
422

    
423
        List<EditableFeatureAttributeDescriptor> columns = featureType.getExtraColumns().getColumns();
424
        if (columns!=null && !columns.isEmpty()) {
425
            for (EditableFeatureAttributeDescriptor extraCol : columns) {
426
                if (!selectedContains(extraCol)) {
427
                    availables.add(extraCol);
428
                }
429
            }
430
        }
431
        
432
        if (this.extraColumns!=null && !this.extraColumns.isEmpty()) {
433
            for (FeatureAttributeDescriptor extraCol : this.extraColumns) {
434
                if (!selectedContains(extraCol)) {
435
                    availables.add(extraCol);
436
                }
437
            }
438
        }
439
        DataSwingManager dalSwingManager = DALSwingLocator.getDataSwingManager();
440
        Collections.sort(availables, (FeatureAttributeDescriptor o1, FeatureAttributeDescriptor o2) -> StringUtils.compare(
441
                dalSwingManager.getAttributeDescriptorLabel(o1),
442
                dalSwingManager.getAttributeDescriptorLabel(o2)
443
        ));
444
        for (FeatureAttributeDescriptor available : availables) {
445
            modelAvailables.addElement(available);
446
        }
447
        
448
        modelAvailables.setFilter(this.txtColumnsFilter.getText());
449
        modelAvailables.sort(true);
450
        for (FeatureAttributeDescriptor attr : this.selecteds) {
451
            modelSelecteds.addElement(attr);
452
        }
453
        modelAvailables.sort(true);
454
        this.lstAvailableColumns.setModel(modelAvailables);
455
        this.lstSelectedColumns.setModel(modelSelecteds);
456
        if( indexAvailables >= 0 && modelAvailables.getSize()>0 ) {
457
            if( indexAvailables >= modelAvailables.getSize() ) {
458
                indexAvailables = modelAvailables.getSize()-1;
459
            }
460
            this.lstAvailableColumns.setSelectedIndex(indexAvailables);
461
            this.btnColumnAdd.setEnabled(true);
462
        } else {
463
            if(!this.expressionPicker.isEmpty()) {
464
                this.btnColumnAdd.setEnabled(true);  
465
            } else {
466
                this.btnColumnAdd.setEnabled(false);
467
            }
468
        }
469
        
470
        this.btnColumnUp.setEnabled(indexSelecteds >= 1);
471
        this.btnColumnDown.setEnabled(indexSelecteds>=0 && indexSelecteds < modelSelecteds.getSize() - 1);
472
        
473
        if( indexSelecteds >= 0 && modelSelecteds.getSize()>0 ) {
474
            if( indexSelecteds >= modelSelecteds.getSize() ) {
475
                indexSelecteds = modelSelecteds.getSize()-1;
476
            }
477
            this.lstSelectedColumns.setSelectedIndex(indexSelecteds);
478
            this.lstSelectedColumns.ensureIndexIsVisible(indexSelecteds);
479
            this.btnColumnRemove.setEnabled(true);
480
        } else {
481
            this.btnColumnRemove.setEnabled(false);
482
        }
483
    }
484

    
485
    @Override
486
    public ImageIcon loadImage(String imageName) {
487
        return ToolsSwingUtils.loadImage(this, imageName);
488
    }
489

    
490
    public static void selfRegister() {
491
//        boolean n = ToolsSwingUtils.registerIcons( 
492
//                DefaultFeatureAttributesSelectionPanel.class,
493
//                null,
494
//                LIBRARY_NAME,
495
//                new String[]{ "featuretype", "featuretype-column-add-arrow"},
496
//                new String[]{ "featuretype", "featuretype-column-remove-arrow"},
497
//                new String[]{ "featuretype", "featuretype-column-down"},
498
//                new String[]{ "featuretype", "featuretype-column-up"}
499
//        );          
500
    }
501
    
502
    @Override
503
    public void allowCalculatedAttributes(boolean allowCalculatedAttributes) {
504
        this.allowCalculatedAttributes = allowCalculatedAttributes;
505
        this.btnBookmarks.setVisible(this.allowCalculatedAttributes);
506
        this.btnHistory.setVisible(this.allowCalculatedAttributes);
507
        this.btnExpression.setVisible(this.allowCalculatedAttributes);
508
        this.txtExpression.setVisible(this.allowCalculatedAttributes);
509
    }
510
    
511
    private FeatureAttributeDescriptor getAttributeDescriptor(String name) {
512
        if(this.featureType == null){
513
            return null;
514
        }
515
        FeatureAttributeDescriptor attr = this.featureType.getAttributeDescriptorFromAll(name);
516
        if(attr != null){
517
            return attr;
518
        }
519
        if(this.extraColumns == null){
520
            return null;
521
        }
522
        for (EditableFeatureAttributeDescriptor extraColumn : this.extraColumns) {
523
            if(StringUtils.equalsIgnoreCase(extraColumn.getName(), name)){
524
                return extraColumn;
525
            }
526
        }
527
        return null;
528
    }
529
}