OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

Rev 181 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
181 ilm 1
package org.openconcerto.modules.label;
2
 
3
import java.awt.FlowLayout;
4
import java.awt.GridBagConstraints;
5
import java.awt.GridBagLayout;
6
import java.awt.event.ActionEvent;
7
import java.awt.event.ActionListener;
8
import java.awt.print.PrinterJob;
9
import java.io.BufferedReader;
10
import java.io.DataOutputStream;
11
import java.io.File;
12
import java.io.FileInputStream;
13
import java.io.FileOutputStream;
14
import java.io.IOException;
15
import java.io.StringReader;
183 ilm 16
import java.math.BigDecimal;
181 ilm 17
import java.net.Socket;
18
import java.nio.charset.StandardCharsets;
19
import java.text.DecimalFormat;
20
import java.util.ArrayList;
21
import java.util.HashMap;
22
import java.util.HashSet;
23
import java.util.List;
24
import java.util.Map;
25
import java.util.Properties;
26
import java.util.Set;
27
 
28
import javax.print.DocFlavor;
29
import javax.print.DocPrintJob;
30
import javax.print.PrintService;
31
import javax.print.SimpleDoc;
32
import javax.swing.ButtonGroup;
33
import javax.swing.JButton;
34
import javax.swing.JFrame;
35
import javax.swing.JLabel;
36
import javax.swing.JOptionPane;
37
import javax.swing.JPanel;
38
import javax.swing.JRadioButton;
39
import javax.swing.JSpinner;
40
import javax.swing.JTextField;
41
import javax.swing.SpinnerNumberModel;
42
import javax.swing.SwingConstants;
43
import javax.swing.SwingUtilities;
44
import javax.swing.UIManager;
45
import javax.swing.UnsupportedLookAndFeelException;
46
 
47
import org.openconcerto.sql.model.SQLRowAccessor;
48
import org.openconcerto.ui.DefaultGridBagConstraints;
49
import org.openconcerto.ui.JLabelBold;
50
import org.openconcerto.utils.BaseDirs;
51
import org.openconcerto.utils.ExceptionHandler;
52
import org.openconcerto.utils.FileUtils;
53
import org.openconcerto.utils.ProductInfo;
54
 
55
public class ZPLPrinterPanel extends JPanel {
56
    private final HashMap<String, String> mapName = new HashMap<>();
57
    private final List<String> variables;
58
    private final List<String> knownVariables = new ArrayList<>();
59
    private Map<String, JTextField> editorMap = new HashMap<>();
60
    private String zpl;
61
    private final Properties properties = new Properties();
62
 
63
    public static void main(String[] args) throws IOException {
64
        // final File f = new File("Templates/Labels", "50x50.zpl");
65
        final File file = new File("Template/Labels", "57x32.zpl");
66
        String zpl = FileUtils.read(file);
67
        SwingUtilities.invokeLater(new Runnable() {
68
 
69
            @Override
70
            public void run() {
71
                try {
72
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
73
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {
74
                    e.printStackTrace();
75
                }
76
                ZPLPrinterPanel p = new ZPLPrinterPanel(zpl);
77
                p.initUI(null);
78
                JFrame f = new JFrame();
79
                f.setTitle(file.getName());
80
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
81
                f.setContentPane(p);
82
                f.pack();
83
                f.setLocationRelativeTo(null);
84
                f.setVisible(true);
85
            }
86
        });
87
 
88
    }
89
 
90
    public ZPLPrinterPanel(String zpl) {
91
        this.zpl = zpl;
92
        this.variables = getVariables(zpl);
183 ilm 93
        this.knownVariables.add("product.code");
94
        this.knownVariables.add("product.name");
95
        this.knownVariables.add("product.material");
96
        this.knownVariables.add("product.color");
97
        this.knownVariables.add("product.size");
98
        this.knownVariables.add("product.ean13");
99
        this.knownVariables.add("product.price");
100
        this.knownVariables.add("product.pricewithtax");
181 ilm 101
        //
183 ilm 102
        this.mapName.put("product.name", "Nom");
103
        this.mapName.put("product.code", "Code");
104
        this.mapName.put("product.ean13", "Code à barres");
105
        this.mapName.put("product.price", "Prix HT");
106
        this.mapName.put("product.pricewithtax", "Prix TTC");
107
        this.mapName.put("product.treatment", "Traitement");
108
        this.mapName.put("product.origin", "Origine");
109
        this.mapName.put("product.batch", "Lot");
110
        this.mapName.put("product.size", "Taille");
111
        this.mapName.put("product.color", "Couleur");
112
        this.mapName.put("product.material", "Matière");
181 ilm 113
    }
114
 
115
    private final File getPrefFile() {
116
        final File prefsFolder = BaseDirs.create(ProductInfo.getInstance()).getPreferencesFolder();
117
        if (!prefsFolder.exists()) {
118
            prefsFolder.mkdirs();
119
        }
120
        return new File(prefsFolder, "labels.properties");
121
    }
122
 
123
    protected void initUI(SQLRowAccessor row) {
124
        final File prefsFolder = BaseDirs.create(ProductInfo.getInstance()).getPreferencesFolder();
125
        if (!prefsFolder.exists()) {
126
            prefsFolder.mkdirs();
127
        }
128
 
129
        final File file = getPrefFile();
130
        System.out.println(file.getAbsolutePath());
131
        if (file.exists()) {
132
            try {
183 ilm 133
                this.properties.load(new FileInputStream(file));
181 ilm 134
            } catch (IOException e) {
135
                e.printStackTrace();
136
            }
137
        }
138
 
139
        this.setLayout(new GridBagLayout());
140
        GridBagConstraints c = new DefaultGridBagConstraints();
141
        c.fill = GridBagConstraints.HORIZONTAL;
142
        this.removeAll();
143
 
144
        // Fields
145
 
146
        Set<String> added = new HashSet<>();
147
        for (String v : this.knownVariables) {
183 ilm 148
            if (this.variables.contains(v)) {
181 ilm 149
                // Non editable
150
                String label = getName(v);
151
                c.gridx = 0;
152
                c.weightx = 0;
153
                this.add(new JLabel(label, SwingConstants.RIGHT), c);
154
                c.gridx++;
155
                c.weightx = 1;
156
 
157
                String value = getValueAsString(row, v);
158
                JTextField txt = new JTextField(20);
159
                if (value != null) {
160
                    txt.setText(value);
161
                    txt.setEditable(false);
162
                }
183 ilm 163
                this.editorMap.put(v, txt);
181 ilm 164
                this.add(txt, c);
165
                added.add(v);
166
                c.gridy++;
167
            }
168
        }
169
        for (String v : this.variables) {
170
            if (!added.contains(v)) {
171
                // Editable
172
                String label = getName(v);
173
                c.gridx = 0;
174
                c.weightx = 0;
175
                this.add(new JLabel(label, SwingConstants.RIGHT), c);
176
                c.gridx++;
177
                c.weightx = 1;
178
                JTextField txt = new JTextField(20);
183 ilm 179
                this.editorMap.put(v, txt);
181 ilm 180
                this.add(txt, c);
181
                added.add(v);
182
                c.gridy++;
183
            }
184
 
185
        }
186
 
187
        c.gridwidth = 2;
188
        c.gridx = 0;
189
        this.add(new JLabelBold("Paramètres d'impression"), c);
190
        // Printer selector
191
        c.gridx = 0;
192
        c.gridy++;
193
        final JPanel l1 = new JPanel();
194
        l1.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0));
195
 
196
        l1.add(new JLabel("Nombre d'étiquettes"));
197
        final JSpinner nbLabels = new JSpinner(new SpinnerNumberModel(1, 1, 1000, 10));
198
        l1.add(nbLabels);
199
        this.add(l1, c);
200
        // Delay
201
        l1.add(new JLabel(" Pause entre chaque impression"));
202
        final JSpinner delayLabels = new JSpinner(new SpinnerNumberModel(800, 100, 10000, 100));
203
        l1.add(delayLabels);
204
        this.add(l1, c);
205
        l1.add(new JLabel("ms"));
206
 
207
        c.gridy++;
208
 
209
        final JPanel lPrintNetwork = new JPanel();
210
        lPrintNetwork.setLayout(new FlowLayout(FlowLayout.LEFT, 2, 0));
211
        JRadioButton radioNetworkPrinter = new JRadioButton("imprimante réseau    IP :");
212
        lPrintNetwork.add(radioNetworkPrinter);
213
        JTextField textPrinterIP = new JTextField(16);
214
        lPrintNetwork.add(textPrinterIP);
215
        lPrintNetwork.add(new JLabel(" Port :"));
216
        JSpinner portZPL = new JSpinner(new SpinnerNumberModel(9100, 24, 10000, 1));
217
        lPrintNetwork.add(portZPL);
218
        this.add(lPrintNetwork, c);
219
 
220
        c.gridy++;
221
        final JPanel lPrintLocal = new JPanel();
222
        lPrintLocal.setLayout(new FlowLayout(FlowLayout.LEFT, 2, 0));
223
        JRadioButton radioLocalPrinter = new JRadioButton("imprimante locale");
224
        lPrintLocal.add(radioLocalPrinter);
225
        radioLocalPrinter.setSelected(true);
226
        this.add(lPrintLocal, c);
227
 
228
        final ButtonGroup gr = new ButtonGroup();
229
        gr.add(radioLocalPrinter);
230
        gr.add(radioNetworkPrinter);
231
        c.gridy++;
232
        c.weighty = 1;
233
        c.gridx = 1;
234
        c.fill = GridBagConstraints.NONE;
235
        c.anchor = GridBagConstraints.SOUTHEAST;
236
 
237
        // Restore state from properties
183 ilm 238
        if (this.properties.getOrDefault("printerType", "local").equals("local")) {
181 ilm 239
            radioLocalPrinter.setSelected(true);
240
        } else {
241
            radioNetworkPrinter.setSelected(true);
242
        }
183 ilm 243
        textPrinterIP.setText(this.properties.getOrDefault("printerIp", "").toString());
244
        portZPL.setValue(Long.parseLong(this.properties.getOrDefault("printerPort", "9100").toString()));
245
        nbLabels.setValue(Long.parseLong(this.properties.getOrDefault("nbLabels", "1").toString()));
246
        delayLabels.setValue(Long.parseLong(this.properties.getOrDefault("delay", "800").toString()));
181 ilm 247
        // Print
248
 
249
        JButton printButton = new JButton("Imprimer");
250
        this.add(printButton, c);
251
        printButton.addActionListener(new ActionListener() {
252
 
253
            @Override
254
            public void actionPerformed(ActionEvent e) {
255
                try {
256
                    if (radioLocalPrinter.isSelected()) {
183 ilm 257
                        ZPLPrinterPanel.this.properties.put("printerType", "local");
181 ilm 258
                    } else {
183 ilm 259
                        ZPLPrinterPanel.this.properties.put("printerType", "network");
260
                        ZPLPrinterPanel.this.properties.put("printerIp", textPrinterIP.getText());
261
                        ZPLPrinterPanel.this.properties.put("printerPort", portZPL.getValue().toString());
181 ilm 262
                    }
183 ilm 263
                    ZPLPrinterPanel.this.properties.put("nbLabels", nbLabels.getValue().toString());
264
                    ZPLPrinterPanel.this.properties.put("delay", delayLabels.getValue().toString());
181 ilm 265
                    // Save Prefs
183 ilm 266
                    ZPLPrinterPanel.this.properties.store(new FileOutputStream(getPrefFile()), "");
181 ilm 267
                } catch (Exception e1) {
268
                    ExceptionHandler.handle("Erreur de sauvegarde de " + getPrefFile().getAbsolutePath(), e1);
269
                }
270
                final String code = createZPLCode();
271
                System.out.println("ZPL:");
272
                System.out.println(code);
273
                byte[] data = code.getBytes(StandardCharsets.UTF_8);
274
                if (radioNetworkPrinter.isSelected()) {
275
                    Socket socket = null;
276
                    try {
277
                        socket = new Socket(textPrinterIP.getText(), ((Number) portZPL.getValue()).intValue());
278
                        final DataOutputStream out = new DataOutputStream(socket.getOutputStream());
279
                        final int nb = ((Number) nbLabels.getValue()).intValue();
280
                        for (int i = 0; i < nb; i++) {
281
                            out.write(data);
282
                        }
283
                    } catch (Exception ex) {
284
                        ex.printStackTrace();
285
                        JOptionPane.showMessageDialog(printButton, "Erreur d'impression réseau : " + ex.getMessage());
286
                    } finally {
287
                        if (socket != null) {
288
                            try {
289
                                socket.close();
290
                            } catch (IOException e1) {
291
                                e1.printStackTrace();
292
                            }
293
                        }
294
 
295
                    }
296
                } else {
297
                    try {
298
                        final PrinterJob pj1 = PrinterJob.getPrinterJob();
299
                        if (pj1.printDialog()) {
300
                            final PrintService ps = pj1.getPrintService();
301
                            final int nb = ((Number) nbLabels.getValue()).intValue();
302
                            for (int i = 0; i < nb; i++) {
183 ilm 303
                                final DocPrintJob pj = ps.createPrintJob();
304
                                final SimpleDoc doc = new SimpleDoc(data, DocFlavor.BYTE_ARRAY.AUTOSENSE, null);
181 ilm 305
                                pj.print(doc, null);
306
                                Thread.sleep(((Number) delayLabels.getValue()).intValue());
307
                            }
308
                        }
309
                    } catch (Exception ex) {
310
                        ex.printStackTrace();
311
                        JOptionPane.showMessageDialog(printButton, "Erreur d'impression locale : " + ex.getMessage());
312
                    }
313
                }
314
 
315
            }
316
        });
317
 
318
    }
319
 
320
    private String createZPLCode() {
321
 
322
        final BufferedReader reader = new BufferedReader(new StringReader(this.zpl));
323
        final StringBuilder builder = new StringBuilder();
324
 
325
        try {
326
            String line = reader.readLine();
327
            while (line != null) {
328
                if (line.contains("${")) {
329
                    boolean add = false;
330
                    for (String v : this.editorMap.keySet()) {
331
                        if (line.contains("${" + v + "}")) {
332
                            final String value = this.editorMap.get(v).getText();
333
                            line = line.replace("${" + v + "}", value);
334
                            if (!value.trim().isEmpty()) {
335
                                add = true;
336
                            }
337
                        }
338
                    }
339
                    if (add) {
340
                        builder.append(line);
341
                        builder.append("\n");
342
                    }
343
 
344
                } else {
345
                    builder.append(line);
346
                    builder.append("\n");
347
                }
348
                line = reader.readLine();
349
            }
350
 
351
        } catch (Exception e) {
352
            e.printStackTrace();
353
        }
354
 
355
        return builder.toString();
356
    }
357
 
358
    public String getValueAsString(SQLRowAccessor row, String variableName) {
359
        if (row == null) {
360
            return null;
361
        }
183 ilm 362
        System.err.println("ZPLPrinterPanel.getValueAsString()" + variableName + " : " + row);
181 ilm 363
        if (variableName.equals("product.code")) {
364
            return row.getString("CODE");
365
        } else if (variableName.equals("product.name")) {
366
            return row.getString("NOM");
367
        } else if (variableName.equals("product.ean13")) {
368
            return row.getString("CODE_BARRE");
369
        } else if (variableName.equals("product.price")) {
183 ilm 370
            final BigDecimal bigDecimal = row.getBigDecimal("PV_HT");
371
            return new DecimalFormat("#0.00").format(bigDecimal);
181 ilm 372
        } else if (variableName.equals("product.pricewithtax")) {
183 ilm 373
            final BigDecimal bigDecimal = row.getBigDecimal("PV_TTC");
374
            return new DecimalFormat("#0.00").format(bigDecimal);
181 ilm 375
        } else if (variableName.equals("product.material")) {
376
            return row.getString("MATIERE");
183 ilm 377
        } else if (variableName.equals("product.color")) {
378
            if (row.getTable().contains("ID_ARTICLE_DECLINAISON_COULEUR")) {
379
                if (row.getObject("ID_ARTICLE_DECLINAISON_COULEUR") != null && !row.isForeignEmpty("ID_ARTICLE_DECLINAISON_COULEUR")) {
380
                    return row.getForeign("ID_ARTICLE_DECLINAISON_COULEUR").getString("NOM");
381
                }
382
            }
383
        } else if (variableName.equals("product.size")) {
384
            if (row.getTable().contains("ID_ARTICLE_DECLINAISON_TAILLE")) {
385
                if (row.getObject("ID_ARTICLE_DECLINAISON_TAILLE") != null && !row.isForeignEmpty("ID_ARTICLE_DECLINAISON_TAILLE")) {
386
                    return row.getForeign("ID_ARTICLE_DECLINAISON_TAILLE").getString("NOM");
387
                }
388
            }
181 ilm 389
        }
390
        return "";
391
    }
392
 
393
    public String getName(String variableName) {
183 ilm 394
        String n = this.mapName.get(variableName);
181 ilm 395
        if (n == null) {
396
            return variableName;
397
        }
398
        return n;
399
    }
400
 
401
    public List<String> getVariables(String str) {
402
        final List<String> result = new ArrayList<>();
403
        if (str == null || str.length() < 4) {
404
            return result;
405
        }
406
        final int l = str.length() - 1;
407
        int start = 0;
408
        boolean inName = false;
409
        for (int i = 0; i < l; i++) {
410
            char c1 = str.charAt(i);
411
            char c2 = str.charAt(i + 1);
412
            if (!inName) {
413
                if (c1 == '$' && c2 == '{') {
414
                    start = i + 2;
415
                    inName = true;
416
                }
417
            } else if (c2 == '}') {
418
                final int stop = i + 1;
419
                String v = str.substring(start, stop);
420
                result.add(v);
421
                inName = false;
422
            }
423
        }
424
        return result;
425
    }
426
}