OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

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