OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Rev 151 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
18 ilm 1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
7
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
8
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
9
 * language governing permissions and limitations under the License.
10
 *
11
 * When distributing the software, include this License Header Notice in each file.
12
 */
13
 
14
 package org.openconcerto.erp.panel;
15
 
16
import org.openconcerto.sql.Configuration;
17
import org.openconcerto.sql.element.SQLElement;
18
import org.openconcerto.sql.model.SQLRow;
67 ilm 19
import org.openconcerto.sql.model.SQLRowListRSH;
18 ilm 20
import org.openconcerto.sql.model.SQLRowValues;
21
import org.openconcerto.sql.model.SQLSelect;
22
import org.openconcerto.sql.model.SQLTable;
23
import org.openconcerto.sql.model.SQLTableListener;
67 ilm 24
import org.openconcerto.sql.model.UndefinedRowValuesCache;
18 ilm 25
import org.openconcerto.sql.request.SQLRowItemView;
26
import org.openconcerto.sql.sqlobject.itemview.RowItemViewComponent;
27
import org.openconcerto.sql.view.EditFrame;
151 ilm 28
import org.openconcerto.ui.FontUtils;
18 ilm 29
import org.openconcerto.ui.FrameUtil;
30
import org.openconcerto.ui.valuewrapper.ValueWrapper;
67 ilm 31
import org.openconcerto.utils.ExceptionHandler;
73 ilm 32
import org.openconcerto.utils.checks.EmptyChangeSupport;
18 ilm 33
import org.openconcerto.utils.checks.EmptyListener;
73 ilm 34
import org.openconcerto.utils.checks.EmptyObj;
18 ilm 35
import org.openconcerto.utils.checks.ValidListener;
21 ilm 36
import org.openconcerto.utils.checks.ValidState;
18 ilm 37
 
38
import java.awt.event.ActionEvent;
39
import java.awt.event.MouseEvent;
40
import java.awt.event.MouseListener;
41
import java.beans.PropertyChangeListener;
42
import java.beans.PropertyChangeSupport;
43
import java.sql.SQLException;
44
import java.util.HashMap;
156 ilm 45
import java.util.HashSet;
18 ilm 46
import java.util.List;
47
import java.util.Map;
156 ilm 48
import java.util.Set;
67 ilm 49
import java.util.concurrent.ExecutionException;
18 ilm 50
 
51
import javax.swing.AbstractAction;
52
import javax.swing.JComponent;
53
import javax.swing.JPopupMenu;
54
import javax.swing.JTree;
142 ilm 55
import javax.swing.SwingWorker;
18 ilm 56
import javax.swing.event.TreeSelectionEvent;
57
import javax.swing.event.TreeSelectionListener;
58
import javax.swing.tree.DefaultTreeCellRenderer;
59
import javax.swing.tree.DefaultTreeModel;
60
import javax.swing.tree.TreePath;
61
import javax.swing.tree.TreeSelectionModel;
62
 
63
// TODO Drag'n drop des nodes
73 ilm 64
public class ITreeSelection extends JTree implements MouseListener, EmptyObj, ValueWrapper<Integer>, RowItemViewComponent {
18 ilm 65
 
66
    private SQLElement element;
67
 
68
    private ITreeSelectionNode rootNode;
69
    private DefaultTreeModel model;
70
 
71
    // Map <Id, Node>
72
    private Map<Integer, ITreeSelectionNode> mapNode = new HashMap<Integer, ITreeSelectionNode>();
73
 
74
    protected static final int EMPTY_ID = SQLRow.MIN_VALID_ID - 1;
73 ilm 75
    private final EmptyChangeSupport helper;
18 ilm 76
    private final PropertyChangeSupport supp;
77
 
78
    public ITreeSelection() {
79
        this(null);
80
    }
81
 
82
    public ITreeSelection(SQLElement element) {
83
        super();
84
        DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer();
85
        renderer.setOpenIcon(null);
86
        renderer.setClosedIcon(null);
87
        renderer.setLeafIcon(null);
88
        this.setCellRenderer(renderer);
151 ilm 89
        // HighDPI
90
        this.setRowHeight(FontUtils.getPreferredRowHeight(this));
91
        // Selection
18 ilm 92
        this.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
93
        this.element = element;
94
 
95
        this.supp = new PropertyChangeSupport(this);
73 ilm 96
        this.helper = new EmptyChangeSupport(this);
18 ilm 97
 
98
        // Value changed
99
        this.addTreeSelectionListener(new TreeSelectionListener() {
100
            public void valueChanged(TreeSelectionEvent e) {
73 ilm 101
                ITreeSelection.this.supp.firePropertyChange("value", null, getValue());
102
                ITreeSelection.this.helper.fireEmptyChange(isEmpty());
18 ilm 103
            }
104
        });
105
 
106
    }
107
 
108
    private void initTree() {
109
        if (this.element == null) {
110
            this.rootNode = new ITreeSelectionNode(null);
111
        } else {
67 ilm 112
            SQLRowValues row = UndefinedRowValuesCache.getInstance().getDefaultRowValues(element.getTable());
18 ilm 113
            this.rootNode = new ITreeSelectionNode(row);
114
        }
115
        this.model = new DefaultTreeModel(this.rootNode);
116
        this.setModel(this.model);
117
        loadTree();
118
        setTableListener();
119
        this.addMouseListener(this);
120
    }
121
 
122
    public void mouseClicked(MouseEvent e) {
123
    }
124
 
125
    public void mouseEntered(MouseEvent e) {
126
    }
127
 
128
    public void mouseExited(MouseEvent e) {
83 ilm 129
    }
18 ilm 130
 
83 ilm 131
    public void mouseReleased(MouseEvent e) {
18 ilm 132
    }
133
 
134
    public void mousePressed(MouseEvent e) {
135
 
136
        TreePath path = this.getSelectionPath();
137
        if (path != null) {
138
            if (e.getButton() == MouseEvent.BUTTON3) {
139
 
140
                final int idSelect = getSelectedID();
141
 
142
                // Ajouter, supprimer, modifier un élément dans l'arbre
143
 
144
                JPopupMenu menu = new JPopupMenu();
145
                menu.add(new AbstractAction("Ajouter un élément") {
146
                    public void actionPerformed(ActionEvent e) {
147
                        addElement(idSelect);
148
                    }
149
                });
150
 
151
                if (idSelect > 1) {
152
                    menu.add(new AbstractAction("Modifier") {
153
                        public void actionPerformed(ActionEvent e) {
154
                            modifyElement(idSelect);
155
                        }
156
                    });
157
 
158
                    menu.add(new AbstractAction("Supprimer") {
159
                        public void actionPerformed(ActionEvent e) {
160
                            removeElement(idSelect);
161
                        }
162
                    });
163
                }
164
                menu.show(e.getComponent(), e.getPoint().x, e.getPoint().y);
165
            }
166
        }
167
    }
168
 
169
    public int getSelectedID() {
170
        TreePath path = this.getSelectionPath();
171
        int id = 1;
172
        if (path != null) {
173
            Object o = path.getLastPathComponent();
174
            if (o instanceof ITreeSelectionNode) {
175
                final ITreeSelectionNode nodeSelect = (ITreeSelectionNode) o;
176
                id = nodeSelect.getId();
177
            }
178
        }
179
        return id;
180
    }
181
 
182
    /**
183
     * Ajouter une feuille
184
     */
185
    public void addElement(int idRoot) {
186
        EditFrame frameAdd = new EditFrame(element, EditFrame.CREATION);
187
        SQLRowValues rowVals = new SQLRowValues(element.getTable());
188
        if (idRoot > 1) {
189
            rowVals.put("ID_" + element.getTable().getName() + "_PERE", idRoot);
190
            frameAdd.getSQLComponent().select(rowVals);
191
        }
192
        FrameUtil.showPacked(frameAdd);
193
 
194
    }
195
 
196
    /**
197
     * Supprimer la feuille
198
     */
199
    public void removeElement(int id) {
200
        if (id > 1) {
201
            try {
202
                element.archive(id);
203
            } catch (SQLException e1) {
204
                e1.printStackTrace();
205
            }
206
        }
207
    }
208
 
209
    /**
210
     * Modifier la feuille
211
     */
212
    public void modifyElement(int id) {
213
        if (id > 1) {
214
            EditFrame frameModFamille = new EditFrame(element, EditFrame.MODIFICATION);
215
            frameModFamille.selectionId(id, 1);
216
            FrameUtil.showPacked(frameModFamille);
217
        }
218
    }
219
 
220
    public JComponent getComp() {
221
        return this;
222
    }
223
 
224
    public void resetValue() {
225
        this.setValue(1);
226
    }
227
 
73 ilm 228
    @Override
18 ilm 229
    public void addEmptyListener(EmptyListener l) {
73 ilm 230
        this.helper.addEmptyListener(l);
18 ilm 231
    }
232
 
73 ilm 233
    @Override
234
    public void removeEmptyListener(EmptyListener l) {
235
        this.helper.removeEmptyListener(l);
236
    }
237
 
18 ilm 238
    public void addValueListener(PropertyChangeListener l) {
239
        this.supp.addPropertyChangeListener(l);
240
    }
241
 
242
    @Override
243
    public void rmValueListener(PropertyChangeListener l) {
244
        this.supp.removePropertyChangeListener(l);
245
    }
246
 
73 ilm 247
    public Integer getValue() {
18 ilm 248
        int id = 1;
249
        TreePath path = this.getSelectionPath();
250
 
251
        if (path != null) {
252
            Object o = path.getLastPathComponent();
253
 
254
            if (o instanceof ITreeSelectionNode) {
255
                final ITreeSelectionNode nodeSelect = (ITreeSelectionNode) o;
256
                id = nodeSelect.getId();
257
            }
258
        }
259
        return id;
260
    }
261
 
73 ilm 262
    @Override
18 ilm 263
    public boolean isEmpty() {
73 ilm 264
        return this.getValue().intValue() <= EMPTY_ID;
18 ilm 265
    }
266
 
267
    public void addValidListener(ValidListener l) {
268
    }
269
 
19 ilm 270
    @Override
271
    public void removeValidListener(ValidListener l) {
272
    }
273
 
21 ilm 274
    @Override
275
    public ValidState getValidState() {
276
        // return "Aucune valeur sélectionnée dans l'arbre";
277
        return ValidState.getTrueInstance();
18 ilm 278
    }
279
 
280
    @Override
281
    public void init(SQLRowItemView v) {
282
        if (this.element == null) {
283
            final SQLTable foreignTable = v.getField().getTable().getDBSystemRoot().getGraph().getForeignTable(v.getField());
284
            this.element = Configuration.getInstance().getDirectory().getElement(foreignTable);
285
        }
286
        initTree();
287
    }
288
 
289
    public void setValue(Integer val) {
83 ilm 290
        if (val == null) {
18 ilm 291
            val = EMPTY_ID;
83 ilm 292
        }
293
        final ITreeSelectionNode v = this.mapNode.get(val);
18 ilm 294
        if (v.getId() == val) {
295
            this.setExpandsSelectedPaths(true);
296
            this.setSelectionPath(new TreePath(v.getPath()));
297
        }
298
 
299
    }
300
 
301
    private void loadTree() {
142 ilm 302
        new SwingWorker<List<SQLRow>, Object>() {
67 ilm 303
            @Override
304
            protected List<SQLRow> doInBackground() throws Exception {
83 ilm 305
                final SQLTable table = element.getTable();
306
                final SQLSelect sel = new SQLSelect();
67 ilm 307
                sel.addSelectStar(table);
308
                return SQLRowListRSH.execute(sel);
309
            }
18 ilm 310
 
67 ilm 311
            @Override
312
            protected void done() {
313
                List<SQLRow> l;
314
                try {
315
                    l = get();
316
                    if (l != null) {
142 ilm 317
                        Map<Integer, SQLRow> familles = new HashMap<Integer, SQLRow>();
67 ilm 318
                        for (int i = 0; i < l.size(); i++) {
319
                            SQLRow row = l.get(i);
142 ilm 320
                            familles.put(row.getID(), row);
67 ilm 321
                        }
142 ilm 322
                        for (int i = 0; i < l.size(); i++) {
323
                            SQLRow row = l.get(i);
156 ilm 324
                            addNewNode(familles, row, row.getInt("ID_" + element.getTable().getName() + "_PERE"), new HashSet<>());
142 ilm 325
                        }
67 ilm 326
                        expandRow(0);
327
                    }
328
                } catch (InterruptedException e) {
329
                    ExceptionHandler.handle("", e);
330
                } catch (ExecutionException e) {
331
                    ExceptionHandler.handle("", e);
332
                }
18 ilm 333
            }
142 ilm 334
        }.execute();
18 ilm 335
    }
336
 
337
    /**
338
     * Ajoute une famille dans l'arbre
339
     *
340
     * @param id
341
     * @param idPere
342
     */
156 ilm 343
    private void addNewNode(Map<Integer, SQLRow> familles, SQLRow row, int idPere, Set<Integer> addedIDs) {
144 ilm 344
        if (row != null && this.mapNode.get(row.getID()) == null) {
142 ilm 345
            ITreeSelectionNode nodePere = this.mapNode.get(Integer.valueOf(idPere));
346
            if (idPere > 1 && nodePere == null && familles != null) {
144 ilm 347
                final SQLRow rowPere = familles.get(idPere);
156 ilm 348
                if (idPere != row.getID()) {
349
                    if (!addedIDs.contains(idPere)) {
350
                        addedIDs.add(idPere);
351
                        addNewNode(familles, rowPere, rowPere.getInt("ID_" + element.getTable().getName() + "_PERE"), addedIDs);
352
                    }
144 ilm 353
                }
142 ilm 354
                nodePere = this.mapNode.get(Integer.valueOf(idPere));
355
            }
144 ilm 356
            final ITreeSelectionNode newNode = new ITreeSelectionNode(row);
142 ilm 357
            this.mapNode.put(row.getID(), newNode);
144 ilm 358
            if (!row.isUndefined()) {
142 ilm 359
                if (nodePere != null && idPere > 1) {
360
                    addNode(newNode, nodePere);
361
                } else {
362
                    if (idPere == 1) {
363
                        addNode(newNode, rootNode);
364
                    }
18 ilm 365
                }
366
            }
367
        }
368
    }
369
 
370
    /**
371
     * Ajoute un noeud dans l'arbre dans l'ordre alphabétique
372
     *
373
     * @param nodeToAdd
374
     * @param nodeParent
375
     */
376
    private void addNode(ITreeSelectionNode nodeToAdd, ITreeSelectionNode nodeParent) {
377
        int n = 0;
83 ilm 378
        final int childCount = nodeParent.getChildCount();
379
        for (; n < childCount; n++) {
18 ilm 380
            if (nodeToAdd.toString().compareToIgnoreCase(nodeParent.getChildAt(n).toString()) < 0) {
381
                break;
382
            }
383
        }
384
        model.insertNodeInto(nodeToAdd, nodeParent, n);
385
    }
386
 
387
    /**
388
     *
389
     * @param row
390
     * @param nodeParent
391
     */
392
    private void modifyNode(SQLRow row, ITreeSelectionNode node) {
83 ilm 393
        if (row.isArchived() && node.getParent() != null) {
18 ilm 394
            model.removeNodeFromParent(node);
395
        } else {
396
            node.setRow(row);
397
            model.nodeChanged(node);
398
        }
399
    }
400
 
401
    /**
402
     * Suppression d'un noeud
403
     *
404
     * @param row
405
     * @param nodeParent
406
     */
407
    private void removeNode(SQLRow row, ITreeSelectionNode nodeParent) {
83 ilm 408
        final int childCount = nodeParent.getChildCount();
409
        for (int i = 0; i < childCount; i++) {
410
            final ITreeSelectionNode v = (ITreeSelectionNode) nodeParent.getChildAt(i);
18 ilm 411
            if (v.getId() == row.getID()) {
412
                model.removeNodeFromParent(v);
413
            }
414
        }
415
    }
416
 
417
    /**
418
     * Table listener permettant de rafraichir l'arbre
419
     *
420
     */
421
    private void setTableListener() {
83 ilm 422
        final SQLTableListener listener = new SQLTableListener() {
18 ilm 423
            public void rowModified(SQLTable table, int id) {
83 ilm 424
                final ITreeSelectionNode node = mapNode.get(Integer.valueOf(id));
18 ilm 425
                if (node != null) {
426
                    modifyNode(table.getRow(id), node);
427
                }
428
            }
429
 
430
            public void rowAdded(SQLTable table, int id) {
83 ilm 431
                final SQLRow row = table.getRow(id);
18 ilm 432
                int idPere = row.getInt("ID_" + element.getTable().getName() + "_PERE");
156 ilm 433
                addNewNode(null, row, idPere, new HashSet<>());
18 ilm 434
            }
435
 
436
            public void rowDeleted(SQLTable table, int id) {
83 ilm 437
                final ITreeSelectionNode node = mapNode.get(Integer.valueOf(id));
18 ilm 438
                for (int i = 0; i < node.getChildCount(); i++) {
439
                    removeNode(table.getRow(id), node);
440
                }
441
            }
442
        };
443
        this.element.getTable().addTableListener(listener);
444
    }
445
}