OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

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