Statistics
| Revision:

gvsig-projects-pool / org.gvsig.online / trunk / org.gvsig.online / org.gvsig.online.swing / org.gvsig.online.swing.impl / src / main / java / org / gvsig / online / swing / impl / OnlineEntitySelectorControllerJTree.java @ 9518

History | View | Annotate | Download (38.2 KB)

1
/*
2
 * gvSIG. Desktop Geographic Information System.
3
 * 
4
 * Copyright (C) 2007-2020 gvSIG Association.
5
 * 
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 * 
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 * 
16
 * You should have received a copy of the GNU General Public License 
17
 * along with this program. If not, see <https://www.gnu.org/licenses/>. 
18
 * 
19
 * For any additional information, do not hesitate to contact us
20
 * at info AT gvsig.com, or visit our website www.gvsig.com.
21
 */
22
package org.gvsig.online.swing.impl;
23

    
24
import java.awt.Color;
25
import java.awt.Component;
26
import java.awt.Cursor;
27
import java.awt.FlowLayout;
28
import java.awt.event.ActionEvent;
29
import java.awt.event.ActionListener;
30
import java.awt.event.MouseAdapter;
31
import java.awt.event.MouseEvent;
32
import java.awt.event.MouseMotionAdapter;
33
import java.util.ArrayList;
34
import java.util.Collection;
35
import java.util.Collections;
36
import java.util.HashMap;
37
import java.util.HashSet;
38
import java.util.List;
39
import java.util.Map;
40
import java.util.Objects;
41
import java.util.Set;
42
import java.util.TreeMap;
43
import java.util.function.Function;
44
import java.util.function.Predicate;
45
import javax.swing.AbstractCellEditor;
46
import javax.swing.JButton;
47
import javax.swing.JCheckBox;
48
import javax.swing.JLabel;
49
import javax.swing.JOptionPane;
50
import javax.swing.JPanel;
51
import javax.swing.JTextField;
52
import javax.swing.JTree;
53
import javax.swing.SwingUtilities;
54
import javax.swing.UIManager;
55
import javax.swing.event.ChangeListener;
56
import javax.swing.event.TreeSelectionEvent;
57
import javax.swing.event.TreeSelectionListener;
58
import javax.swing.text.JTextComponent;
59
import javax.swing.tree.DefaultMutableTreeNode;
60
import javax.swing.tree.DefaultTreeCellRenderer;
61
import javax.swing.tree.DefaultTreeModel;
62
import javax.swing.tree.TreeCellEditor;
63
import javax.swing.tree.TreeModel;
64
import javax.swing.tree.TreePath;
65
import static javax.swing.tree.TreeSelectionModel.SINGLE_TREE_SELECTION;
66
import org.apache.commons.collections.CollectionUtils;
67
import org.apache.commons.lang3.StringUtils;
68
import static org.gvsig.online.lib.api.OnlineManager.STATE_REMOTE_NEW;
69
import org.gvsig.online.lib.api.workingcopy.OnlineEntity;
70
import org.gvsig.online.lib.api.workingcopy.OnlineWorkingcopy;
71
import org.gvsig.online.swing.api.OnlineEntitySelectorController;
72
import static org.gvsig.online.swing.impl.OnlineSwingCommons.notInSwingThreadInvokeLater;
73
import org.gvsig.tools.ToolsLocator;
74
import org.gvsig.tools.dispose.DisposeUtils;
75
import org.gvsig.tools.dispose.impl.AbstractDisposable;
76
import org.gvsig.tools.exception.BaseException;
77
import org.gvsig.tools.i18n.I18nManager;
78
import org.gvsig.tools.swing.api.ActionListenerSupport;
79
import org.gvsig.tools.swing.api.ChangeListenerHelper;
80
import org.gvsig.tools.swing.api.FilteredTreeController;
81
import org.gvsig.tools.swing.api.ToolsSwingLocator;
82
import org.gvsig.tools.swing.api.ToolsSwingManager;
83
import static org.gvsig.tools.swing.api.ToolsSwingManager.COLOR_TREE_SELECTIONBACKGROUND;
84
import static org.gvsig.tools.swing.api.ToolsSwingManager.COLOR_TREE_SELECTIONFOREGROUND;
85
import static org.gvsig.tools.swing.api.ToolsSwingManager.COLOR_TREE_TEXTBACKGROUND;
86
import static org.gvsig.tools.swing.api.ToolsSwingManager.COLOR_TREE_TEXTFOREGROUND;
87
import org.gvsig.tools.swing.api.threadsafedialogs.ThreadSafeDialogsManager;
88
import org.gvsig.tools.util.CompareUtils;
89
import org.gvsig.tools.util.LabeledValue;
90
import org.gvsig.tools.util.LabeledValueImpl;
91
import org.slf4j.Logger;
92
import org.slf4j.LoggerFactory;
93

    
94
/**
95
 *
96
 * @author gvSIG Team
97
 */
98
public class OnlineEntitySelectorControllerJTree extends AbstractDisposable implements OnlineEntitySelectorController {
99

    
100
    private static final Logger LOGGER = LoggerFactory.getLogger(OnlineEntitySelectorControllerJTree.class);
101

    
102
    private final JTextComponent txtFilter;
103
    private final JTree treeEntities;
104
    private Set<String> checkedEntityCodes;
105
    private Map<String/*entityCode*/,String/*Category*/>categoryOfCheckedEntity;
106
    private Map<String, OnlineEntity> entities;
107
    private final JButton btnEntities;
108
    private FilteredTreeController filteredTree;
109
    private ActionListenerSupport actionListeners;
110
    private ChangeListenerHelper changeListeners;
111
    private OnlineWorkingcopy workspace;
112
    private boolean processing;
113
    private boolean enabled;
114
    private Predicate<OnlineEntity> viewFilter;
115
    private Predicate<OnlineEntity> filter;
116
    private boolean checksEnabled;
117
    private JButton btnCheckAll;
118
    private JButton btnUnCheckAll;
119
    private Thread lastThread;
120
    private Function<OnlineEntity, String> labelEntityFormatter;
121

    
122
    private class EntityCellEditor extends AbstractCellEditor implements TreeCellEditor {
123

    
124
        private final JCheckBox check;
125
        private final JPanel panel;
126
        private final JLabel label;
127
        private Object currentUserObject;
128
        private TreePath currentRow;
129

    
130
        public EntityCellEditor() {
131
            this.check = new JCheckBox();
132
            this.label = new JLabel();
133
            this.panel = new JPanel();
134
            this.label.setOpaque(true);
135
            this.panel.setOpaque(false);
136
            this.check.setOpaque(false);
137
            this.panel.setLayout(new FlowLayout(FlowLayout.RIGHT, 2,1));
138
            this.panel.add(this.check);
139
            this.panel.add(this.label);
140
            this.currentUserObject = null;
141
            this.currentRow = null;
142
            this.check.addActionListener(new ActionListener() {
143
                @Override
144
                public void actionPerformed(ActionEvent e) {
145
                    if( currentUserObject==null ) {
146
                        // Se ha pulsado en una entidad que no tiene ninguna categoria asignada.
147
//                        if( check.isSelected() ) {
148
//                            checkedEntityCodes.addAll(getAllEntityCodesFromCategory(null));
149
//                        } else {
150
//                            checkedEntityCodes.removeAll(getAllEntityCodesFromCategory(null));
151
//                        }
152
                        postCheck();
153
                        return;
154
                    }
155
//                    if( !(currentUserObject instanceof LabeledValue) ) { 
156
//                        // Se ha pulsado en una Category
157
//                        String category = (String)currentUserObject;
158
//                        if( check.isSelected() ) {
159
//                            Set<String> x = getAllEntityCodesFromCategory(category);
160
//                            checkedEntityCodes.addAll(x);
161
//                            for (String entityCode : x) {
162
//                                categoryOfCheckedEntity.put(entityCode, category);
163
//                            }
164
//                        } else {
165
//                            Set<String> x = getAllEntityCodesFromCategory(category);
166
//                            checkedEntityCodes.removeAll(x);
167
//                            for (String entityCode : x) {
168
//                                categoryOfCheckedEntity.remove(entityCode);
169
//                            }
170
//                        }
171
//                        postCheck();
172
//                        return;
173
//                    }
174
                    OnlineEntity entity = ((LabeledValue<OnlineEntity>) currentUserObject).getValue();
175
                    if( entity == null ) {
176
                        return;
177
                    }
178
                    // Se ha pulsado en una entidad
179
                    String entityCode = entity.getEntityCode();
180
                    if( check.isSelected() ) {
181
                        checkedEntityCodes.add(entityCode);
182
                        categoryOfCheckedEntity.put(entityCode, getCategoryFromCurrentRow());
183
                    } else {
184
                        checkedEntityCodes.remove(entityCode);
185
                        categoryOfCheckedEntity.remove(entityCode);
186
                    }
187
                    postCheck();
188
                }
189
            });
190
        }
191

    
192
        private String getCategoryFromCurrentRow() {
193
            try {
194
                DefaultMutableTreeNode parent = (DefaultMutableTreeNode) currentRow.getParentPath().getLastPathComponent();
195
                if( parent == null ) {
196
                    return null;
197
                }
198
                return (String) parent.getUserObject();
199
            } catch(Exception ex) {
200
                return null;
201
            }
202
        }
203
        
204
        private void postCheck() {
205
            this.stopCellEditing();
206
            treeEntities.repaint();
207
            fireActionEvent(new ActionEvent(this, ACTION_CHECK_ID, ACTION_CHECK));
208
        }
209

    
210
        @Override
211
        public Object getCellEditorValue() {
212
            return currentUserObject;
213
        }
214

    
215
        @Override
216
        public Component getTreeCellEditorComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row) {
217
//            LOGGER.info("Editor: selected=" +selected+", '"+Objects.toString(value)+"'+.");
218
            Color backgroundColor = UIManager.getColor(COLOR_TREE_TEXTBACKGROUND);
219
            Color foregroundColor = UIManager.getColor(COLOR_TREE_TEXTFOREGROUND);
220
            if( selected ) {
221
                backgroundColor = UIManager.getColor(COLOR_TREE_SELECTIONBACKGROUND);
222
                foregroundColor = UIManager.getColor(COLOR_TREE_SELECTIONFOREGROUND);
223
            }            
224
            this.label.setBackground(backgroundColor);
225
            this.label.setForeground(foregroundColor);
226
            I18nManager i18n = ToolsLocator.getI18nManager();
227
            if( checksEnabled ) {
228
                this.check.setVisible(true);
229
                this.check.setEnabled(false);
230
                this.check.setSelected(false);
231
                if(value instanceof DefaultMutableTreeNode){
232
                    currentUserObject = ((DefaultMutableTreeNode) value).getUserObject();
233
                    currentRow = tree.getPathForRow(row);
234
                    if( currentUserObject instanceof LabeledValue ) {
235
                        OnlineEntity entity = ((LabeledValue<OnlineEntity>) currentUserObject).getValue();
236
                        if( entity != null ) {
237
                            this.check.setEnabled(true);
238
                            this.check.setSelected(checkedEntityCodes.contains(entity.getEntityCode()));
239
                            this.label.setText(((LabeledValue<OnlineEntity>) currentUserObject).getLabel());
240
                        }
241
//                    } else if( currentUserObject instanceof String || currentUserObject == null) {
242
//                        this.check.setEnabled(true);
243
//                        this.check.setSelected(areSelectedAllEntitiesFromCategory((String)currentUserObject));
244
//                        if(StringUtils.isBlank((String)currentUserObject)){
245
//                            this.label.setText(i18n.getTranslation("_Others"));
246
//                        } else { 
247
//                            this.label.setText(i18n.getTranslation((String)currentUserObject)); 
248
//                        }
249
                    }
250
                }
251
            } else {
252
                this.check.setVisible(false);
253
            }
254
            return this.panel;
255
        }
256

    
257
    }
258
    
259
    private class EntityCellRenderer extends DefaultTreeCellRenderer {
260

    
261
        private final JCheckBox check;
262
        private final JPanel panel;
263
        private final JLabel label;
264
        
265
        public EntityCellRenderer() {
266
            this.check = new JCheckBox();
267
            this.label = new JLabel();
268
            this.panel = new JPanel();
269
            this.label.setOpaque(true);
270
            this.panel.setOpaque(false);
271
            this.check.setOpaque(false);
272
            this.panel.setLayout(new FlowLayout(FlowLayout.RIGHT, 2,1));
273
            this.panel.add(this.check);
274
            this.panel.add(this.label);
275
            this.setLeafIcon(null);
276
        }   
277
        
278
        @Override
279
        public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
280
            JLabel c = (JLabel) super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
281
//            LOGGER.info("Renderer: selected=" +selected+", '"+Objects.toString(value)+"'+.");
282
            Color backgroundColor = UIManager.getColor(COLOR_TREE_TEXTBACKGROUND);
283
            Color foregroundColor = UIManager.getColor(COLOR_TREE_TEXTFOREGROUND);
284
            if( selected ) {
285
                backgroundColor = UIManager.getColor(COLOR_TREE_SELECTIONBACKGROUND);
286
                foregroundColor = UIManager.getColor(COLOR_TREE_SELECTIONFOREGROUND);
287
            }            
288
            this.label.setBackground(backgroundColor);
289
            this.label.setForeground(foregroundColor);
290
            this.label.setText(Objects.toString(value));
291

    
292
//            LOGGER.info("1. "+ this.label.getText() +" foreground="+label.getForeground(),toString());
293
//            this.label.setOpaque(selected);
294

    
295
            if( checksEnabled ) {
296
                this.check.setVisible(true);
297
                this.check.setForeground(foregroundColor);
298
                this.check.setBackground(backgroundColor);
299
                this.check.setEnabled(false);
300
                this.check.setSelected(false);
301
                
302
                if(value instanceof DefaultMutableTreeNode){
303
                    Object userObject = ((DefaultMutableTreeNode) value).getUserObject();
304
                    if( userObject instanceof LabeledValue ) {
305
                        OnlineEntity entity = ((LabeledValue<OnlineEntity>) userObject).getValue();
306
                        if( entity != null ) {
307
                            this.check.setEnabled(true);
308
                            this.check.setSelected(checkedEntityCodes.contains(entity.getEntityCode()));
309
                        }
310
                    } else if( userObject instanceof String  || userObject == null) {
311
                        this.check.setEnabled(true);
312
//                        this.check.setSelected(areSelectedAllEntitiesFromCategory((String)userObject));
313
                        if(StringUtils.isBlank((String)userObject)){
314
                            I18nManager i18n = ToolsLocator.getI18nManager();
315
                            this.label.setText(i18n.getTranslation("_Others"));
316
                        } else { 
317
                            this.label.setText((String)userObject); 
318
                        }
319
                    }
320
                }
321
            } else {
322
                this.check.setVisible(false);
323
                if (value instanceof DefaultMutableTreeNode) {
324
                    Object userObject = ((DefaultMutableTreeNode) value).getUserObject();
325
                    if (userObject instanceof String || userObject == null) {
326
                        if (StringUtils.isBlank((String) userObject)) {
327
                            I18nManager i18n = ToolsLocator.getI18nManager();
328
                            this.label.setText(i18n.getTranslation("_Others"));
329
                        } else {
330
                            this.label.setText((String) userObject);
331
                        }
332
                    }
333
                }
334
            }
335
            return this.panel;
336
        }
337
        
338
        protected JCheckBox getCheckBox() {
339
            return this.check;
340
        }
341
        
342
    }
343
    
344
    public OnlineEntitySelectorControllerJTree(JTree treeEntities) {
345
        this(treeEntities, null, null, null, null);
346
    }
347

    
348
    public OnlineEntitySelectorControllerJTree(JTree treeEntities, JTextComponent txtFilter, JButton btnTable, JButton btnCheckAll, JButton btnUnCheckAll) {
349
        viewFilter = ALL_ENTITIES;
350
        filter = ALL_ENTITIES;
351

    
352
        this.treeEntities = treeEntities;
353
        this.checkedEntityCodes = new HashSet<>();
354
        this.categoryOfCheckedEntity = new HashMap<>();
355
        this.entities = new HashMap<>();
356
        if (txtFilter == null) {
357
            this.txtFilter = new JTextField();
358
        } else {
359
            this.txtFilter = txtFilter;
360
        }
361
        if (btnTable == null) {
362
            this.btnEntities = new JButton();
363
        } else {
364
            this.btnEntities = btnTable;
365
        }
366

    
367
        if( btnCheckAll==null ) {
368
            this.btnCheckAll = new JButton();
369
        } else {
370
            this.btnCheckAll = btnCheckAll;
371
        }
372
        if( btnUnCheckAll==null ) {
373
            this.btnUnCheckAll = new JButton();
374
        } else {
375
            this.btnUnCheckAll = btnCheckAll;
376
        }
377
        
378
        this.processing = false;
379
        
380

    
381
        this.initComponents();
382
    }
383

    
384
    private void initComponents() {
385
        ToolsSwingManager toolsSwingManager = ToolsSwingLocator.getToolsSwingManager();
386

    
387
        this.actionListeners = toolsSwingManager.createActionListenerSupport();
388
        this.changeListeners = toolsSwingManager.createChangeListenerHelper();
389

    
390
        this.btnEntities.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
391

    
392
        this.treeEntities.getSelectionModel().setSelectionMode(SINGLE_TREE_SELECTION);
393
        this.treeEntities.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() {
394
            @Override
395
            public void valueChanged(TreeSelectionEvent e) {
396
                try {
397
                    DefaultMutableTreeNode parent = (DefaultMutableTreeNode) e.getPath().getParentPath().getLastPathComponent();
398
                    DefaultMutableTreeNode current = (DefaultMutableTreeNode) e.getPath().getLastPathComponent();
399
                    if( parent != null ) {
400
                        String category = (String) parent.getUserObject();
401
                        OnlineEntity entity = ((LabeledValue<OnlineEntity>)current.getUserObject()).getValue();
402
                        if( entity!=null ) {
403
                            categoryOfCheckedEntity.put(entity.getEntityCode(), category);
404
                        }
405
                    }
406
                } catch (Exception ex) {
407
                    LOGGER.debug("Can't set category for current entity",ex);
408
                }
409
                fireActionEvent(new ActionEvent(this, 0, ACTION_SELECT));
410
            }
411
        });
412
        this.treeEntities.setRootVisible(false);
413
        this.treeEntities.setShowsRootHandles(true);
414
        
415
        filteredTree = toolsSwingManager.createFilteredTreeController(treeEntities, txtFilter, btnEntities);
416
        filteredTree.setModel(new DefaultTreeModel(new DefaultMutableTreeNode()));
417
        EntityCellRenderer cellRenderer = new EntityCellRenderer();
418
        this.treeEntities.setCellRenderer(cellRenderer);
419
        setChecksEnabled(true);
420

    
421
        this.btnCheckAll.addActionListener((ActionEvent e) -> { checkAll(); });
422
        this.btnUnCheckAll.addActionListener((ActionEvent e) -> { clearChecks(); });
423
        
424
        this.treeEntities.addMouseListener(new MouseAdapter() {
425
            @Override
426
            public void mouseClicked(MouseEvent e) {
427
                TreePath path = treeEntities.getPathForLocation(e.getX(), e.getY());
428
                if( path!=null ) {
429
                    treeEntities.startEditingAtPath(path);
430
                }
431
            }
432
        });
433
        this.treeEntities.addMouseMotionListener(new MouseMotionAdapter() {
434
            @Override
435
            public void mouseMoved(MouseEvent e) {
436
                super.mouseMoved(e); 
437
                TreePath path = treeEntities.getPathForLocation(e.getX(), e.getY());
438
                doMouseMoved(path);
439
            }
440
        });
441

    
442

    
443
    }
444

    
445
    private void doMouseMoved(TreePath path) {
446
        if(path == null){
447
            return;
448
        }
449
        Object x = ((DefaultMutableTreeNode)path.getLastPathComponent()).getUserObject();
450
        if(!(x instanceof LabeledValue)){
451
            this.treeEntities.setToolTipText("");
452
            return;
453
        }
454
        LabeledValue lv = (LabeledValue)x;
455
        if (lv.getValue() instanceof OnlineEntity) {
456
            OnlineEntity entity = (OnlineEntity) lv.getValue();
457

    
458
            OnlineEntity lentity = workspace.getWorkspaceEntityByCode(entity.getEntityCode());
459
            String s;
460
            //NO PODEMOS A?ADIR ENTIDADES NUEVAS
461
//            if (StringUtils.isBlank(entity.getRepositoryRevisionCode())) { //Es entidad local nueva
462
//                s = OnlineSwingCommons.getStateDescription(
463
//                        ((OnlineEntity) entity).getState()
464
//                );
465
//            } else {
466
                s = OnlineSwingCommons.getStateDescription(
467
                        lentity == null ? STATE_REMOTE_NEW : lentity.getState()
468
                );
469
//            }
470
            if( StringUtils.equalsIgnoreCase(entity.getEntityCode(), entity.getLabel()) ) {
471
                s = "<html>"+entity.getLabelOrName()+"<br>"+s+"</html>";
472
            } else {
473
                s = "<html>"+entity.getLabel()+"<br>"+entity.getEntityName()+"<br>"+s+"</html>";
474
            }
475
            this.treeEntities.setToolTipText(s);
476
            
477
        } else {
478
            this.treeEntities.setToolTipText("");
479
        }
480
    }
481

    
482
    @Override
483
    public boolean isProcessing() {
484
        return this.processing;
485
    }
486

    
487
    @Override
488
    public OnlineEntity getSelectedEntity() {
489
        if (this.workspace == null) {
490
            return null;
491
        }
492
        TreePath path = treeEntities.getSelectionPath();
493
        if (path == null) {
494
            return null;
495
        }
496
        DefaultMutableTreeNode lastComponent = (DefaultMutableTreeNode) path.getLastPathComponent();
497
        Object userObject = lastComponent.getUserObject();
498
        if(userObject == null || !(userObject instanceof LabeledValue)){
499
            return null;
500
        }
501
        LabeledValue selected = (LabeledValue) userObject;
502
        OnlineEntity entity = (OnlineEntity) selected.getValue();
503
        if (!this.filter.test(entity)) {
504
            return null;
505
        }
506
        return entity;
507
    }
508
    
509
    @Override
510
    public void setSelectedEntity(OnlineEntity entity) {
511
        if( this.workspace==null ) {
512
            return;
513
        }
514
        
515
        for (int i = 0; i < treeEntities.getRowCount(); i++) {
516
            TreePath path = treeEntities.getPathForRow(i);
517
            DefaultMutableTreeNode lc = (DefaultMutableTreeNode) path.getLastPathComponent();
518
            Object x = lc.getUserObject();
519
            if(x instanceof LabeledValue){
520
                OnlineEntity value = ((LabeledValue<OnlineEntity>)x).getValue();
521
                if(StringUtils.equals(entity.getEntityCode(), value.getEntityCode())){
522
                    treeEntities.setSelectionPath(path);
523
                    return;
524
                }
525
            }
526
        }
527
    }
528

    
529
    @Override
530
    public String getCategory(OnlineEntity entity) {
531
        String category = this.categoryOfCheckedEntity.get(entity.getEntityCode());
532
        if( StringUtils.isBlank(category) ) {
533
            category = entity.getFirstCategory();
534
        }
535
        return category;
536
    }
537

    
538
    @Override
539
    public List<OnlineEntity> getCheckedEntities() {
540
        List<OnlineEntity> checkedEntities = new ArrayList<>();
541
        for (String entityCode : this.checkedEntityCodes) {
542
            OnlineEntity entity = this.entities.get(entityCode);
543
            if(entity != null){
544
                checkedEntities.add(entity);
545
            }
546
        }
547
        Collections.sort(checkedEntities, new CompareUtils.NullSafeComparator<OnlineEntity>() {
548
            @Override
549
            public int safeCompare(OnlineEntity o1, OnlineEntity o2) {
550
                return StringUtils.compare(o1.getLabelOrName(), o2.getLabelOrName(), true);
551
            }
552
        });
553
        return checkedEntities;
554
    }
555

    
556
    @Override
557
    public void setWorkspace(OnlineWorkingcopy workspace) {
558
        this.checkedEntityCodes.clear();
559
        this.categoryOfCheckedEntity.clear();
560
        DisposeUtils.disposeQuietly(this.workspace);
561
        this.workspace = workspace;
562
        DisposeUtils.bind(this.workspace);
563
        reloadEntities();
564
    }
565

    
566
    @Override
567
    public OnlineWorkingcopy getWorkspace() {
568
        return this.workspace;
569
    }
570
    
571
    @Override
572
    public void reloadEntities() {
573
        this.entities.clear();
574
        if (workspace == null) {
575
            filteredTree.setModel(new DefaultTreeModel(new DefaultMutableTreeNode()));
576
            return;
577
        }
578
        if (this.processing ) {
579
            LOGGER.info("Reentrada");
580
            return;
581
        }
582
        Thread task = new Thread(() -> {
583
            reloadEntities(this.workspace);
584
        }, "VCSGisEntitySelectorTreeReloadEntities");
585
        task.start();
586
        this.lastThread = task;
587
    }
588
    
589
    private boolean  isCancelled(){
590
        return Thread.currentThread() != this.lastThread;
591
    }
592

    
593

    
594
    private void reloadEntities(OnlineWorkingcopy workspace) {
595
        I18nManager i18n = ToolsLocator.getI18nManager();
596
        try {
597
            fireActionEvent(new ActionEvent(this, ACTION_BEGIN_PROCESSING_ID, ACTION_BEGIN_PROCESSING));
598
            SwingUtilities.invokeLater(() -> {
599
                treeEntities.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
600
            });
601

    
602
            this.processing = true;
603
            this.doUpdateComponents();
604
//            workspace.updateEntitiesFromRepository();
605
//            List<OnlineEntity> allEntities = workspace.getRepositoryEntities();
606
            List<OnlineEntity> localEntities = workspace.getWorkspaceEntities();
607
//            for (OnlineEntity localEntity : localEntities) {
608
//                if(isCancelled()){
609
//                    return;
610
//                }
611
////                if (StringUtils.isBlank(localEntity.getRepositoryRevisionCode())) { //Es entidad local nueva
612
////                    allEntities.add(localEntity);
613
////                }
614
//            }
615
////            Collections.sort(allEntities, new CompareUtils.NullSafeComparator<OnlineEntity>() {
616
////                @Override
617
////                public int safeCompare(OnlineEntity o1, OnlineEntity o2) {
618
////                    return StringUtils.compare(o1.getLabelOrName(), o2.getLabelOrName(), true);
619
////                }
620
////            });
621

    
622
            
623
            Map<String, OnlineEntity> theEntities;
624
            Map<String, DefaultMutableTreeNode> theEntityNodes;
625

    
626
            theEntityNodes = new TreeMap<>((String o1, String o2) -> StringUtils.compare(o1, o2, false));
627
                    
628
            theEntities = new HashMap<>();
629

    
630
//            for (OnlineEntity entity : allEntities) {
631
            for (OnlineEntity entity : localEntities) {
632
                if(isCancelled()){
633
                    return;
634
                }
635
                OnlineEntity lentity = workspace.getWorkspaceEntityByCode(entity.getEntityCode());
636
                LabeledValue entry;
637
                String s;
638
//                if (StringUtils.isBlank(entity.getRepositoryRevisionCode())) { //Es entidad local nueva
639
//                    s = OnlineSwingCommons.getHTMLColorTag(
640
//                            ((OnlineEntity)entity).getState(),
641
//                            this.getLabelOfEntity(entity)
642
//                    );
643
//                } else {
644
                    s = OnlineSwingCommons.getHTMLColorTag(
645
                            lentity == null ? STATE_REMOTE_NEW : lentity.getState(),
646
                            this.getLabelOfEntity(entity)
647
                    );
648
//                }
649
                
650
                if(lentity != null && this.viewFilter.test(lentity)){
651
                        entity = lentity;
652
                } else {
653
                    if(!this.viewFilter.test(entity)){
654
                        entity = null;
655
                    }
656
                }
657

    
658
                if (entity!=null) {
659
                    theEntities.put(entity.getEntityCode(), entity);
660
                    entry = new LabeledValueImpl(s, entity);
661
//                    List<String> categories = entity.getCategoriesAsList();
662
//                    if( CollectionUtils.isNotEmpty(categories) ){
663
//                        for (String cat : categories) {
664
//                            String category = StringUtils.trimToNull(cat);
665
//                            addNodeEntity(theEntityNodes, category, entry);
666
//                        }
667
//                    } else {
668
//                        String category = StringUtils.trimToNull(entity.getCategory());
669
                        addNodeEntity(theEntityNodes, null, entry);
670
//                    }
671
                }
672
            }
673
            
674
            this.entities = theEntities;
675

    
676
            DefaultMutableTreeNode root = new DefaultMutableTreeNode();
677
            for (DefaultMutableTreeNode node : theEntityNodes.values()) {
678
                if(isCancelled()){
679
                    return;
680
                }
681
                root.add(node);
682
            }
683
            if(!isCancelled()){
684
                postReloadEntities(root);
685
            }
686

    
687
        } catch (Exception e) {
688
            LOGGER.warn("_Cant_retrieve_entities_from_repository", e);
689
            if(!isCancelled()){
690
                ThreadSafeDialogsManager dialogs = ToolsSwingLocator.getThreadSafeDialogsManager();
691
                dialogs.messageDialog(
692
                        i18n.getTranslation("_Cant_retrieve_entities_from_repository") + "\n" + e.getMessage(),
693
                        i18n.getTranslation("_VCS_Checkout"),
694
                        JOptionPane.WARNING_MESSAGE
695
                );
696
            }
697
        } finally {
698
            SwingUtilities.invokeLater(() -> {
699
                treeEntities.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
700
            });
701
            if (!isCancelled()) {
702
                this.processing = false;
703
                this.doUpdateComponents();
704
                fireActionEvent(new ActionEvent(this, ACTION_END_PROCESSING_ID, ACTION_END_PROCESSING));
705
            }
706
        }
707

    
708
    }
709
    
710
    private String getLabelOfEntity(OnlineEntity entity) {
711
        if( entity == null ) {
712
            return null;
713
        }
714
        
715
        if( this.labelEntityFormatter==null ) {
716
            return workspace.formatEntityLabel(entity);
717
        }
718
        String s;
719
        try {
720
            s = this.labelEntityFormatter.apply(entity);
721
        } catch(Exception ex) {
722
            s = entity.getLabelOrName();
723
        }
724
        return s;
725
    }
726
    
727
    @Override
728
    public void setLabelEntityFormatter(Function<OnlineEntity,String> formatter) {
729
        this.labelEntityFormatter = formatter;
730
    }
731

    
732
    @Override
733
    public Collection<OnlineEntity> getEntities() {
734
        return this.entities.values();
735
    }
736

    
737
    private void addNodeEntity(Map<String, DefaultMutableTreeNode> theEntityNodes, String category, LabeledValue entry) {
738
        DefaultMutableTreeNode branch = theEntityNodes.get(category);
739
        if (branch == null) {
740
            branch = new DefaultMutableTreeNode(category, true);
741
            theEntityNodes.put(category, branch);
742
        }
743
        branch.add(new DefaultMutableTreeNode(entry, false));
744
    }
745

    
746
    private void postReloadEntities(DefaultMutableTreeNode entities) {
747
        if (notInSwingThreadInvokeLater(() -> {
748
            postReloadEntities(entities);
749
        })) {
750
            return;
751
        }
752
        filteredTree.setModel(new DefaultTreeModel(entities));
753
        this.expandAllNodes(treeEntities);
754
        this.processing = false;
755
        fireActionEvent(new ActionEvent(this, ACTION_RELOAD_ID, ACTION_RELOAD));
756
    }
757

    
758
    private void doUpdateComponents() {
759
        if (notInSwingThreadInvokeLater(this::doUpdateComponents)) {
760
            return;
761
        }
762
        this.txtFilter.setEnabled(enabled && !processing);
763
        this.btnEntities.setEnabled(enabled && !processing);
764
        this.treeEntities.setEnabled(enabled && !processing);
765
    }
766

    
767
    @Override
768
    public void setEnabled(boolean enabled) {
769
        this.enabled = enabled;
770
        this.treeEntities.setEditable(enabled);
771
        doUpdateComponents();
772
    }
773

    
774
    @Override
775
    public boolean isEnabled() {
776
        return enabled;
777
    }
778

    
779
    @Override
780
    public void setChecksEnabled(boolean enabled) {
781
        this.checksEnabled = enabled;
782
        if(enabled){
783
            this.treeEntities.setCellEditor(new EntityCellEditor());
784
        } else {
785
            this.treeEntities.setCellEditor(null);
786
        }
787
        this.treeEntities.setEditable(enabled);
788
    }
789

    
790
    @Override
791
    public boolean isChecksEnabled() {
792
        return this.checksEnabled;
793
    }
794

    
795
    @Override
796
    public void addActionListener(ActionListener al) {
797
        this.actionListeners.addActionListener(al);
798
    }
799

    
800
    @Override
801
    public ActionListener[] getActionListeners() {
802
        return this.actionListeners.getActionListeners();
803
    }
804

    
805
    @Override
806
    public void removeActionListener(ActionListener al) {
807
        this.actionListeners.removeActionListener(al);
808
    }
809

    
810
    @Override
811
    public void removeAllActionListener() {
812
        this.actionListeners.removeAllActionListener();
813
    }
814

    
815
    @Override
816
    public void fireActionEvent(ActionEvent ae) {
817
        this.actionListeners.fireActionEvent(ae);
818
    }
819

    
820
    @Override
821
    public boolean hasActionListeners() {
822
        return this.actionListeners.hasActionListeners();
823
    }
824

    
825
    @Override
826
    public void addChangeListener(ChangeListener cl) {
827
        this.changeListeners.addChangeListener(cl);
828
    }
829

    
830
    @Override
831
    public ChangeListener[] getChangeListeners() {
832
        return this.changeListeners.getChangeListeners();
833
    }
834

    
835
    @Override
836
    public void removeChangeListener(ChangeListener cl) {
837
        this.changeListeners.removeChangeListener(cl);
838
    }
839

    
840
    @Override
841
    public void removeAllChangeListener() {
842
        this.changeListeners.removeAllChangeListener();
843
    }
844

    
845
    @Override
846
    public boolean hasChangeListeners() {
847
        return this.changeListeners.hasChangeListeners();
848
    }
849

    
850
    @Override
851
    public void setViewFilter(Predicate<OnlineEntity> viewFilter) {
852
        this.viewFilter = viewFilter;
853
    }
854

    
855
    @Override
856
    public void setFilter(Predicate<OnlineEntity> filter) {
857
        this.filter = filter;
858
    }
859

    
860
    @Override
861
    public void check(OnlineEntity entity) {
862
        this.checkedEntityCodes.add(entity.getEntityCode());
863
//        this.categoryOfCheckedEntity.put(entity.getEntityCode(), entity.getFirstCategory());
864
        this.treeEntities.repaint();
865
        fireActionEvent(new ActionEvent(this, ACTION_CHECK_ID, ACTION_CHECK));
866
    }
867

    
868
    public void setCheck(Collection<String> entityCodes, boolean check) {
869
        if( CollectionUtils.isEmpty(entityCodes) ) {
870
            return;
871
        }
872
        for (String entityCode : entityCodes) {
873
            if( check ) {
874
                this.checkedEntityCodes.add(entityCode);
875
//                OnlineEntity entity = this.entities.get(entityCode);
876
//                if( entity!=null ) {
877
//                    this.categoryOfCheckedEntity.put(entityCode, entity.getFirstCategory());
878
//                }
879
            } else {
880
                this.checkedEntityCodes.remove(entityCode);
881
            }
882
        }
883
        this.treeEntities.repaint();
884
        fireActionEvent(new ActionEvent(this, ACTION_CHECK_ID, ACTION_CHECK));
885
    }
886

    
887
    @Override
888
    public void unCheck(OnlineEntity entity) {
889
        this.checkedEntityCodes.remove(entity.getEntityCode());
890
        this.treeEntities.repaint();
891
        fireActionEvent(new ActionEvent(this, ACTION_CHECK_ID, ACTION_CHECK));
892
    }
893

    
894
    @Override
895
    public void checkAll() {
896
        for (Map.Entry<String, OnlineEntity> entry : entities.entrySet()) {
897
            this.checkedEntityCodes.add(entry.getValue().getEntityCode());
898
        }
899
        this.treeEntities.repaint();
900
        fireActionEvent(new ActionEvent(this, ACTION_CHECK_ID, ACTION_CHECK));
901
    }
902
    
903
    @Override
904
    public void clearChecks() {
905
        this.checkedEntityCodes.clear();
906
        this.treeEntities.stopEditing();
907
        this.treeEntities.repaint();
908
        fireActionEvent(new ActionEvent(this, ACTION_CHECK_ID, ACTION_CHECK));
909
    }
910
    
911
    private void expandAllNodes(JTree tree) {
912
        int j = tree.getRowCount();
913
        int i = 0;
914
        while(i < j) {
915
            tree.expandRow(i);
916
            i += 1;
917
            j = tree.getRowCount();
918
        }
919
    }
920

    
921
//    private boolean areSelectedAllEntitiesFromCategory(String category) {
922
//        
923
//        // Hay que tener cuiado con este metodo que durante el pintado del 
924
//        // arbol se llama bastantes mas veces de las que parece.
925
//        
926
//        for (Map.Entry<String, OnlineEntity> entry : this.entities.entrySet()) {
927
//            OnlineEntity entity = entry.getValue();
928
//            if(StringUtils.isBlank(category)){
929
//                if(StringUtils.isBlank(entity.getCategory())){
930
//                    if (!this.checkedEntityCodes.contains(entity.getEntityCode())) {
931
//                        return false;
932
//                    }
933
//                }
934
//            } else {
935
//                if (entity.getCategoriesAsList().contains(category)) {
936
//                    if (!this.checkedEntityCodes.contains(entity.getEntityCode())) {
937
//                        return false;
938
//                    }
939
//                }
940
//            }
941
//        }
942
//        return true;
943
//    }
944
    
945
//    private Set<String> getAllEntityCodesFromCategory(String category){
946
//        Set<String> entityCodes = new HashSet<>();
947
//        for (Map.Entry<String, OnlineEntity> entry : this.entities.entrySet()) {
948
//            OnlineEntity entity = entry.getValue();
949
//            if(StringUtils.isBlank(category)){
950
//                if(StringUtils.isBlank(entity.getCategory())){
951
//                    entityCodes.add(entity.getEntityCode());
952
//                }
953
//            } else {
954
//                if (entity.getCategoriesAsList().contains(category)) {
955
//                    entityCodes.add(entity.getEntityCode());
956
//                }
957
//            }
958
//        }
959
//        return entityCodes;
960
//    }
961

    
962
    @Override
963
    public void clear() {
964
        this.setWorkspace(null);
965
    }
966

    
967
    @Override
968
    protected void doDispose() throws BaseException {
969
        DisposeUtils.disposeQuietly(this.workspace);
970
    }
971

    
972
    public void collapseAll() {
973
      TreeModel model = this.treeEntities.getModel();
974
      Object root = model.getRoot();
975
      for (int i = 0; i < model.getChildCount(root); i++) {
976
        DefaultMutableTreeNode node = (DefaultMutableTreeNode) model.getChild(root, i);
977
        TreePath path = new TreePath(node.getPath());
978
        this.treeEntities.collapsePath(path);          
979
      }                
980
    }
981
    
982
    public void expandAll() {
983
        this.expandAllNodes(this.treeEntities);
984
    }
985
    
986
//          TreeModel model = this.treeEntities.getModel();
987
//      Object root = model.getRoot();
988
//        for (int i = 0; i < model.getChildCount(root); i++) {
989
//          DefaultTreeNode node = model.getChild(root, i);
990
//        }
991

    
992
}