OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

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

Rev Author Line No. Line
142 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.core.edm;
15
 
16
import org.openconcerto.erp.core.common.ui.ScrollablePanel;
17
import org.openconcerto.sql.model.SQLRowAccessor;
18
import org.openconcerto.sql.model.SQLRowValues;
19
import org.openconcerto.sql.model.SQLRowValuesListFetcher;
20
import org.openconcerto.sql.model.SQLTable;
21
import org.openconcerto.sql.model.Where;
22
import org.openconcerto.ui.DefaultGridBagConstraints;
23
import org.openconcerto.ui.SwingThreadUtils;
24
import org.openconcerto.utils.ExceptionHandler;
25
import org.openconcerto.utils.FileUtils;
26
 
27
import java.awt.Color;
28
import java.awt.Component;
29
import java.awt.Dimension;
30
import java.awt.FileDialog;
31
import java.awt.FlowLayout;
32
import java.awt.Frame;
33
import java.awt.GridBagConstraints;
34
import java.awt.GridBagLayout;
35
import java.awt.datatransfer.DataFlavor;
36
import java.awt.datatransfer.Transferable;
37
import java.awt.dnd.DnDConstants;
38
import java.awt.dnd.DropTarget;
39
import java.awt.dnd.DropTargetDropEvent;
40
import java.awt.event.ActionEvent;
41
import java.awt.event.ActionListener;
42
import java.awt.event.MouseAdapter;
43
import java.awt.event.MouseEvent;
44
import java.io.File;
45
import java.io.IOException;
149 ilm 46
import java.sql.SQLException;
142 ilm 47
import java.util.ArrayList;
180 ilm 48
import java.util.Collection;
149 ilm 49
import java.util.Collections;
50
import java.util.Comparator;
51
import java.util.HashSet;
142 ilm 52
import java.util.List;
149 ilm 53
import java.util.Set;
142 ilm 54
 
149 ilm 55
import javax.swing.BorderFactory;
142 ilm 56
import javax.swing.JButton;
149 ilm 57
import javax.swing.JLabel;
142 ilm 58
import javax.swing.JOptionPane;
59
import javax.swing.JPanel;
60
import javax.swing.JProgressBar;
61
import javax.swing.JScrollPane;
62
import javax.swing.SwingUtilities;
63
import javax.swing.event.ListDataEvent;
64
import javax.swing.event.ListDataListener;
65
 
66
public class AttachmentPanel extends JPanel {
67
 
68
    private final SQLRowAccessor rowSource;
180 ilm 69
    private final Collection<SQLRowAccessor> rowSecondaires;
149 ilm 70
    private List<ListDataListener> listeners = new ArrayList<>();
142 ilm 71
 
149 ilm 72
    private int idParent = 1;
73
    private List<Integer> parents = new ArrayList<>();
74
    private List<String> parentsNames = new ArrayList<>();
75
    private Set<Attachment> selectedAttachments = new HashSet<>();
76
    private List<FilePanel> filePanels = new ArrayList<>();
77
 
142 ilm 78
    public AttachmentPanel(SQLRowAccessor rowSource) {
180 ilm 79
        this(rowSource, Collections.emptyList());
80
    }
81
 
82
    public AttachmentPanel(SQLRowAccessor rowSource, Collection<SQLRowAccessor> rowSecondaires) {
142 ilm 83
        super();
84
        this.rowSource = rowSource;
180 ilm 85
        this.rowSecondaires = rowSecondaires;
86
 
142 ilm 87
        this.setLayout(new GridBagLayout());
149 ilm 88
        this.parents.add(1);
89
        this.parentsNames.add("Racine");
142 ilm 90
        initUI();
91
        setFocusable(true);
92
    }
93
 
94
    public void addListener(ListDataListener l) {
95
        this.listeners.add(l);
96
    }
97
 
98
    public void removeListener(ListDataListener l) {
99
        this.listeners.remove(l);
100
    }
101
 
102
    public void fireDataChanged() {
180 ilm 103
        for (ListDataListener listDataListener : this.listeners) {
142 ilm 104
            listDataListener.contentsChanged(new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, 0, 0));
105
        }
106
    }
107
 
180 ilm 108
    public int getAttachementsSize() {
109
        return this.filePanels.size();
110
    }
111
 
142 ilm 112
    public void initUI() {
180 ilm 113
        this.filePanels.clear();
142 ilm 114
        this.invalidate();
115
        this.removeAll();
116
        GridBagConstraints c = new DefaultGridBagConstraints();
117
 
118
        // Recupération de la liste des fichiers
119
 
120
        // TODO requete dans un SwingWorker
180 ilm 121
        final SQLTable tableAttachment = this.rowSource.getTable().getTable("ATTACHMENT");
142 ilm 122
        SQLRowValues rowVals = new SQLRowValues(tableAttachment);
123
        rowVals.putNulls(tableAttachment.getFieldsName());
124
 
125
        SQLRowValuesListFetcher fetcher = SQLRowValuesListFetcher.create(rowVals);
126
        Where where = new Where(tableAttachment.getField("SOURCE_TABLE"), "=", this.rowSource.getTable().getName());
127
        where = where.and(new Where(tableAttachment.getField("SOURCE_ID"), "=", this.rowSource.getID()));
128
 
149 ilm 129
        where = where.and(new Where(tableAttachment.getField("ID_PARENT"), "=", this.idParent));
180 ilm 130
        for (SQLRowAccessor rowSecondaire : this.rowSecondaires) {
142 ilm 131
 
180 ilm 132
            Where whereSec = new Where(tableAttachment.getField("SOURCE_TABLE"), "=", rowSecondaire.getTable().getName());
133
            whereSec = whereSec.and(new Where(tableAttachment.getField("SOURCE_ID"), "=", rowSecondaire.getID()));
134
 
135
            where = where.or(whereSec);
136
        }
149 ilm 137
        final List<SQLRowValues> rAttachments = fetcher.fetch(where);
138
        c.fill = GridBagConstraints.BOTH;
139
        c.anchor = GridBagConstraints.WEST;
140
        c.gridx = 0;
141
        c.gridy = 0;
142
        // Folder paths
143
        if (this.parents.size() > 1) {
144
            JPanel navPanel = new JPanel();
145
            navPanel.setBackground(Color.WHITE);
146
            navPanel.setBorder(BorderFactory.createLineBorder(Color.GRAY));
147
            navPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 8, 2));
148
 
149
            for (int i = 0; i < this.parents.size(); i++) {
150
                JLabel b = new JLabel(" " + this.parentsNames.get(i) + " ");
151
                b.setOpaque(true);
152
                b.setBackground(new Color(230, 240, 255));
153
                navPanel.add(b);
154
                final int id = this.parents.get(i);
155
                final int index = i;
156
                if (i < this.parents.size() - 1) {
157
                    b.addMouseListener(new MouseAdapter() {
158
                        @Override
159
                        public void mousePressed(MouseEvent e) {
160
                            AttachmentPanel.this.idParent = id;
161
                            int nb = AttachmentPanel.this.parents.size() - index - 1;
162
                            for (int n = 0; n < nb; n++) {
163
                                final int pos = AttachmentPanel.this.parents.size() - 1;
164
                                AttachmentPanel.this.parents.remove(pos);
165
                                AttachmentPanel.this.parentsNames.remove(pos);
166
                            }
167
                            clearSelection();
168
                            initUI();
169
                        }
170
                    });
171
                }
172
                if (i < this.parents.size() - 1) {
173
                    b.setDropTarget(new DropTarget() {
174
 
175
                        @Override
176
                        public synchronized void drop(DropTargetDropEvent dtde) {
177
                            dtde.acceptDrop(DnDConstants.ACTION_MOVE);
178
                            Transferable t = dtde.getTransferable();
179
                            try {
180
                                for (int i = 0; i < t.getTransferDataFlavors().length; i++) {
181
                                    final DataFlavor dataFlavor = t.getTransferDataFlavors()[i];
182
                                    if (dataFlavor.isMimeTypeEqual(DataFlavor.javaSerializedObjectMimeType)) {
183
                                        @SuppressWarnings("unchecked")
184
                                        List<Attachment> attachments = (List<Attachment>) t.getTransferData(dataFlavor);
185
                                        AttachmentUtils utils = new AttachmentUtils();
186
                                        for (Attachment a : attachments) {
187
                                            if (a.getParentId() != id) {
188
                                                utils.move(a, id);
189
                                            }
190
                                        }
191
                                        initUI();
192
                                        break;
193
                                    }
194
                                }
195
 
196
                            } catch (Exception e) {
197
                                e.printStackTrace();
198
                            }
199
                        }
200
                    });
201
                }
202
 
203
            }
204
            this.add(navPanel, c);
205
            c.gridy++;
206
        }
207
 
208
        // Tools
209
        final JPanel toolbar = new JPanel();
210
        toolbar.setLayout(new FlowLayout(FlowLayout.LEFT));
211
        final JButton addFolderButton = new JButton("Nouveau dossier");
212
        toolbar.add(addFolderButton);
213
        final JButton addFileButton = new JButton("Ajouter un fichier");
214
        toolbar.add(addFileButton);
215
 
142 ilm 216
        final JProgressBar progressBar = new JProgressBar(0, 100);
217
        progressBar.setValue(100);
218
        progressBar.setStringPainted(true);
219
        progressBar.setVisible(false);
149 ilm 220
        toolbar.add(progressBar);
221
 
222
        this.add(toolbar, c);
223
 
142 ilm 224
        c.gridy++;
225
 
149 ilm 226
        addFolderButton.addActionListener(new ActionListener() {
142 ilm 227
 
228
            @Override
229
            public void actionPerformed(ActionEvent e) {
149 ilm 230
                AttachmentUtils utils = new AttachmentUtils();
231
                try {
180 ilm 232
                    utils.createFolder("Nouveau dossier", AttachmentPanel.this.rowSource, AttachmentPanel.this.idParent);
149 ilm 233
                } catch (SQLException e1) {
234
                    JOptionPane.showMessageDialog(null, "Impossible de créer le dossier.", "Erreur", JOptionPane.ERROR_MESSAGE);
235
                }
236
                initUI();
237
 
238
            }
239
        });
240
 
241
        addFileButton.addActionListener(new ActionListener() {
242
 
243
            @Override
244
            public void actionPerformed(ActionEvent e) {
142 ilm 245
                final Frame frame = SwingThreadUtils.getAncestorOrSelf(Frame.class, (Component) e.getSource());
246
                final FileDialog fd = new FileDialog(frame, "Ajouter un fichier", FileDialog.LOAD);
247
                fd.setVisible(true);
248
                final String fileName = fd.getFile();
249
                if (fileName != null) {
180 ilm 250
                    try {
251
                        File inFile = new File(fd.getDirectory(), fileName);
252
                        AttachmentUtils utils = new AttachmentUtils();
253
                        utils.uploadFile(inFile, AttachmentPanel.this.rowSource, AttachmentPanel.this.idParent);
254
                        initUI();
255
                    } catch (Exception ex) {
256
                        ex.printStackTrace();
257
                        JOptionPane.showMessageDialog(AttachmentPanel.this, "Erreur lors de l'ajout du fichier " + fileName + "(" + ex.getMessage() + ")");
258
                    }
142 ilm 259
                }
260
            }
261
        });
262
 
263
        ScrollablePanel files = new ScrollablePanel() {
264
            @Override
265
            public Dimension getPreferredSize() {
266
                int w = getSize().width;
149 ilm 267
                int nbPerRow = (w - 5) / (FilePanel.PREFERRED_WIDTH + 5);
142 ilm 268
                if (nbPerRow < 1) {
269
                    nbPerRow = 1;
270
                }
271
                int nbRow = 1 + (getComponentCount() / nbPerRow);
272
                if (nbRow < 1) {
273
                    nbRow = 1;
274
                }
149 ilm 275
                return new Dimension(w, 5 + nbRow * (FilePanel.PREFERRED_HEIGHT + 5));
142 ilm 276
            }
277
 
278
        };
279
        files.setOpaque(true);
280
        files.setBackground(Color.WHITE);
281
        files.setScrollableWidth(ScrollablePanel.ScrollableSizeHint.FIT);
282
        files.setScrollableHeight(ScrollablePanel.ScrollableSizeHint.NONE);
283
        files.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 5));
149 ilm 284
        final List<Attachment> attachments = new ArrayList<>(rAttachments.size());
285
        for (final SQLRowValues sqlRowValues : rAttachments) {
286
            final Attachment a = new Attachment(sqlRowValues);
287
            attachments.add(a);
288
        }
289
        Collections.sort(attachments, new Comparator<Attachment>() {
290
 
291
            @Override
292
            public int compare(Attachment o1, Attachment o2) {
293
                if (o1.isFolder() && !o2.isFolder()) {
294
                    return -1;
295
                }
296
                if (!o1.isFolder() && o2.isFolder()) {
297
                    return 1;
298
                }
299
                return o1.getName().compareTo(o2.getName());
300
            }
301
        });
302
 
142 ilm 303
        // Liste des fichiers
149 ilm 304
        for (final Attachment a : attachments) {
305
            final FilePanel filePanel = new FilePanel(a, this);
306
            this.filePanels.add(filePanel);
142 ilm 307
            filePanel.addMouseListener(new MouseAdapter() {
308
                @Override
309
                public void mousePressed(MouseEvent e) {
310
                    if (e.getClickCount() == 2) {
149 ilm 311
                        if (a.isFolder()) {
312
                            openFolder(a);
313
                        } else {
314
                            final Thread t = new Thread() {
315
                                @Override
316
                                public void run() {
317
                                    AttachmentUtils utils = new AttachmentUtils();
318
                                    File f = utils.getFile(a);
319
                                    if (f == null) {
320
                                        SwingUtilities.invokeLater(new Runnable() {
321
                                            public void run() {
322
                                                JOptionPane.showMessageDialog(null, "Impossible de récupérer le fichier.", "Erreur", JOptionPane.ERROR_MESSAGE);
323
                                            }
324
                                        });
325
                                    } else {
326
                                        try {
327
                                            FileUtils.openFile(f);
328
                                        } catch (IOException e1) {
329
                                            ExceptionHandler.handle("Erreur lors de l'ouverture du fichier.", e1);
142 ilm 330
                                        }
149 ilm 331
 
142 ilm 332
                                    }
333
                                }
149 ilm 334
                            };
335
                            t.start();
336
                        }
142 ilm 337
                    }
338
                }
149 ilm 339
 
142 ilm 340
            });
341
            files.add(filePanel);
342
 
343
        }
149 ilm 344
 
142 ilm 345
        c.gridx = 0;
346
        c.gridy++;
347
        c.weightx = 1;
348
        c.weighty = 1;
149 ilm 349
 
350
        final JScrollPane scroll = new JScrollPane(files);
142 ilm 351
        scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
352
        scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
353
        scroll.setMinimumSize(new Dimension((int) (400 * 1.618), 400));
354
        scroll.setPreferredSize(new Dimension((int) (400 * 1.618), 400));
355
        scroll.setBackground(Color.WHITE);
356
        scroll.getViewport().setBackground(Color.WHITE);
357
        this.add(scroll, c);
149 ilm 358
        scroll.addMouseListener(new MouseAdapter() {
359
            @Override
360
            public void mousePressed(MouseEvent e) {
361
                clearSelection();
362
                updatePanels();
363
            }
364
        });
142 ilm 365
 
366
        this.validate();
367
        this.repaint();
368
 
369
        DropTarget dt = new DropTarget() {
149 ilm 370
 
142 ilm 371
            @Override
372
            public synchronized void drop(DropTargetDropEvent dtde) {
373
                dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
374
                Transferable t = dtde.getTransferable();
375
                try {
376
                    if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
377
                        @SuppressWarnings("unchecked")
378
                        List<File> fileList = (List<File>) t.getTransferData(DataFlavor.javaFileListFlavor);
379
                        // TODO faire en arriere plan, mettre une jauge à droite du bouton ajouter
380
                        // et mettre un bouton d'annulation
381
                        AttachmentUtils utils = new AttachmentUtils();
382
                        boolean cancelledByUser = false;
383
                        for (File f : fileList) {
384
                            if (cancelledByUser) {
385
                                break;
386
                            }
180 ilm 387
                            try {
388
                                if (!f.isDirectory()) {
389
                                    utils.uploadFile(f, AttachmentPanel.this.rowSource, AttachmentPanel.this.idParent);
390
                                }
391
                            } catch (Exception ex) {
392
                                ex.printStackTrace();
393
                                JOptionPane.showMessageDialog(AttachmentPanel.this, "Erreur lors de l'ajout du fichier " + f.getAbsolutePath() + "(" + ex.getMessage() + ")");
149 ilm 394
                            }
142 ilm 395
                        }
396
                        initUI();
397
                    }
398
                } catch (Exception e) {
399
                    e.printStackTrace();
400
                }
401
            }
402
        };
403
        files.setDropTarget(dt);
404
        scroll.getViewport().setDropTarget(dt);
405
        fireDataChanged();
406
    }
407
 
149 ilm 408
    public Set<Attachment> getSelectedAttachments() {
180 ilm 409
        return this.selectedAttachments;
149 ilm 410
    }
411
 
412
    public void select(Attachment a) {
413
        this.selectedAttachments.add(a);
414
    }
415
 
416
    public void deselect(Attachment a) {
417
        this.selectedAttachments.remove(a);
418
    }
419
 
420
    public boolean isSelected(Attachment a) {
421
        return this.selectedAttachments.contains(a);
422
    }
423
 
424
    public void clearSelection() {
425
        this.selectedAttachments.clear();
426
    }
427
 
428
    public void updatePanels() {
429
        for (FilePanel p : this.filePanels) {
430
            p.updateBackgroundFromState();
431
        }
432
    }
433
 
434
    public void openFolder(final Attachment a) {
435
        if (!a.isFolder()) {
436
            throw new IllegalStateException(a.getName() + " is not a folder");
437
        }
438
        clearSelection();
439
        this.idParent = a.getId();
440
        this.parents.add(a.getId());
441
        this.parentsNames.add(a.getName());
442
        initUI();
443
    }
142 ilm 444
}