OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

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