OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

Rev 83 | Rev 142 | 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.core.sales.pos.io;
15
 
16
import org.openconcerto.erp.core.sales.pos.ui.BarcodeListener;
83 ilm 17
import org.openconcerto.ui.DefaultGridBagConstraints;
18
import org.openconcerto.ui.component.ITextArea;
18 ilm 19
 
83 ilm 20
import java.awt.Dimension;
21
import java.awt.GridBagConstraints;
22
import java.awt.GridBagLayout;
18 ilm 23
import java.awt.KeyEventDispatcher;
24
import java.awt.KeyboardFocusManager;
25
import java.awt.event.KeyEvent;
26
import java.util.ArrayList;
27
import java.util.List;
28
import java.util.Timer;
29
import java.util.TimerTask;
30
 
83 ilm 31
import javax.swing.JFrame;
32
import javax.swing.JLabel;
33
import javax.swing.JPanel;
34
import javax.swing.JScrollPane;
18 ilm 35
import javax.swing.SwingUtilities;
83 ilm 36
import javax.swing.UIManager;
18 ilm 37
 
38
/**
39
 * Lecteur code barres, intercepte les événements clavier pour détecter un scan de code. Le code
40
 * barre doit terminer par un retour à la ligne.
41
 * */
42
public class BarcodeReader implements KeyEventDispatcher {
43
 
83 ilm 44
    public int maxInterKeyDelay = 80;
18 ilm 45
    private static final int MIN_BARCODE_LENGTH = 2;
46
    private final List<BarcodeListener> listeners = new ArrayList<BarcodeListener>(1);
47
    private String value = "";
48
    private final List<KeyEvent> eve = new ArrayList<KeyEvent>();
49
    private long firstTime = -1;
50
    private Timer timer;
51
    // non final car un TimerTask n'est pas reutilisable
52
    private TimerTask task;
53
 
83 ilm 54
    public BarcodeReader(int maxInterKeyDelay) {
18 ilm 55
        this.timer = null;
56
        this.task = null;
83 ilm 57
        this.maxInterKeyDelay = maxInterKeyDelay;
18 ilm 58
    }
59
 
60
    public synchronized void removeBarcodeListener(BarcodeListener l) {
61
        this.listeners.remove(l);
62
        if (this.listeners.size() == 0) {
63
            stop();
64
        }
65
    }
66
 
67
    public synchronized void addBarcodeListener(final BarcodeListener l) {
68
        if (this.timer == null) {
69
            start();
70
        }
71
        this.listeners.add(l);
72
 
73
    }
74
 
75
    private void fire(String code) {
76
        for (int i = 0; i < this.listeners.size(); i++) {
77
            this.listeners.get(i).barcodeRead(code);
78
        }
79
    }
80
 
81
    /**
82
     * Commence à ecouter les évenements clavier pour intercepter les codes barres
83
     * */
84
 
85
    public void start() {
86
        // init avant que les listeners s'en servent
87
        this.timer = new Timer(getClass().getName(), true);
88
        KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(this);
89
    }
90
 
91
    /**
92
     * Stoppe l'écoute sur les évenements clavier
93
     * */
94
    public void stop() {
95
        if (this.timer != null) {
96
            this.timer.cancel();
93 ilm 97
            this.timer = null;
18 ilm 98
        }
99
        KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventDispatcher(this);
100
    }
101
 
102
    @Override
103
    public boolean dispatchKeyEvent(KeyEvent e) {
104
        if (this.task != null)
105
            this.task.cancel();
106
 
107
        final long t = e.getWhen();
108
        if (this.firstTime < 0) {
109
            this.firstTime = t;
110
        }
111
        int key = e.getKeyCode();
112
 
83 ilm 113
        if (t - this.firstTime > maxInterKeyDelay && key != KeyEvent.VK_SHIFT) {
18 ilm 114
            // touche normale
115
            redispatch();
116
        }
117
 
118
        final char key2 = e.getKeyChar();
119
        this.eve.add(e);
120
        if (key != KeyEvent.VK_UNDEFINED && e.getID() == KeyEvent.KEY_RELEASED) {
121
            if (key == KeyEvent.VK_SHIFT) {
122
                // rien
123
            } else if (key2 == '*' || key2 == '$' || key2 == '+' || key2 == '/' || key2 == '%' || key2 == '-' | key2 == ' ') {
124
                this.value += key2;
125
            } else if (key >= KeyEvent.VK_0 && key <= KeyEvent.VK_9 || key >= KeyEvent.VK_A && key <= KeyEvent.VK_Z) {
126
                // from KeyEvent : same as ASCII
127
                this.value += (char) key;
128
            } else if (key == KeyEvent.VK_ENTER && this.value.length() >= MIN_BARCODE_LENGTH) {
129
                // fin de code barre
130
                this.value = this.value.trim();
131
                fire(this.value);
132
                reset();
133
            } else {
134
                // Caractere non code barre
135
                redispatch();
136
            }
137
            // lance un timer s'il reste des evenements non dispatchés
138
            if (this.eve.size() > 0) {
139
                this.firstTime = t;
140
                this.task = new TimerTask() {
141
                    @Override
142
                    public void run() {
143
                        redispatchLater();
144
                    }
145
                };
83 ilm 146
                this.timer.schedule(this.task, maxInterKeyDelay);
18 ilm 147
            }
148
            // si pas d'evenement, pas de temps associé
149
            assert this.eve.size() > 0 || this.firstTime == -1;
150
        }
151
        return true;
152
    }
153
 
154
    private void redispatchLater() {
155
        SwingUtilities.invokeLater(new Runnable() {
156
            @Override
157
            public void run() {
158
                redispatch();
159
            }
160
        });
161
    }
162
 
163
    private void redispatch() {
164
        for (int i = 0; i < this.eve.size(); i++) {
165
            final KeyEvent ee = this.eve.get(i);
166
            KeyboardFocusManager.getCurrentKeyboardFocusManager().redispatchEvent(ee.getComponent(), ee);
167
            for (int j = 0; j < this.listeners.size(); j++) {
168
                this.listeners.get(j).keyReceived(ee);
169
            }
170
        }
171
        reset();
172
    }
173
 
174
    private void reset() {
175
        this.value = "";
176
        this.eve.clear();
177
        this.firstTime = -1;
178
    }
179
 
83 ilm 180
    public static void main(String[] args) {
181
        String delay = "80";
182
        if (args.length > 0) {
183
            delay = args[0];
184
        }
185
        final int d = Integer.parseInt(delay);
186
        SwingUtilities.invokeLater(new Runnable() {
187
 
188
            @Override
189
            public void run() {
190
                try {
191
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
192
                } catch (Exception e) {
193
                    e.printStackTrace();
194
                }
195
                System.out.println("BarCode reader");
196
                System.out.println("Using inter key delay: " + d);
197
                JFrame f = new JFrame();
198
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
199
                JPanel panel = new JPanel();
200
                f.setTitle("Barcode reader test");
201
                f.setContentPane(panel);
202
                panel.setLayout(new GridBagLayout());
203
                GridBagConstraints c = new DefaultGridBagConstraints();
204
                final JLabel l = new JLabel("BarCode reader output :");
205
                panel.add(l, c);
206
                c.gridy++;
207
                c.weighty = 1;
208
                c.weightx = 1;
209
                c.fill = GridBagConstraints.BOTH;
210
                final ITextArea t1 = new ITextArea();
211
                panel.add(new JScrollPane(t1), c);
212
 
213
                BarcodeReader reader = new BarcodeReader(d);
214
                reader.addBarcodeListener(new BarcodeListener() {
215
 
216
                    @Override
217
                    public void keyReceived(KeyEvent ee) {
218
                        System.err.println("BarcodeReader keyReceived() : " + ee);
219
                    }
220
 
221
                    @Override
222
                    public void barcodeRead(String code) {
223
                        t1.append("Barcode OK : '" + code + "'\n");
224
                    }
225
                });
226
 
227
                f.setSize(new Dimension(640, 480));
228
                f.setLocationRelativeTo(null);
229
                f.setVisible(true);
230
 
231
            }
232
        });
233
 
234
    }
18 ilm 235
}