OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

Rev 41 | Rev 67 | 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.common.ui;
15
 
16
import org.openconcerto.sql.model.SQLField;
17
import org.openconcerto.sql.model.SQLRowAccessor;
18
import org.openconcerto.sql.model.SQLRowValues;
19
import org.openconcerto.sql.model.SQLTable;
20
import org.openconcerto.sql.request.MutableRowItemView;
21
import org.openconcerto.utils.CollectionUtils;
22
import org.openconcerto.utils.GestionDevise;
23
import org.openconcerto.utils.checks.EmptyListener;
24
import org.openconcerto.utils.checks.EmptyObject;
25
import org.openconcerto.utils.checks.EmptyObjectHelper;
26
import org.openconcerto.utils.checks.ValidListener;
21 ilm 27
import org.openconcerto.utils.checks.ValidState;
18 ilm 28
import org.openconcerto.utils.doc.Documented;
29
import org.openconcerto.utils.text.SimpleDocumentListener;
30
 
31
import java.awt.Component;
32
import java.awt.Font;
33
import java.awt.event.FocusAdapter;
34
import java.awt.event.FocusEvent;
35
import java.awt.event.KeyAdapter;
36
import java.awt.event.KeyEvent;
37
import java.awt.event.MouseAdapter;
38
import java.awt.event.MouseEvent;
39
import java.beans.PropertyChangeListener;
40
import java.beans.PropertyChangeSupport;
41
import java.sql.ResultSet;
42
import java.sql.SQLException;
43
import java.util.List;
44
import java.util.Set;
45
import java.util.Vector;
46
 
47
import javax.swing.JTextField;
48
import javax.swing.event.DocumentEvent;
49
 
50
import org.apache.commons.collections.Predicate;
51
 
52
/**
53
 * Field permettant de stocker les devises au format 2 chiffres apres la virgule sous forme de long
54
 * dans la base, utiliser un champ de type BigInt signed sous mysql bigInt unsigned -->
55
 * java.math.BigInteger bigInt signed --> java.lang.Long
56
 */
57
public class DeviseField extends JTextField implements EmptyObject, MutableRowItemView, Documented {
58
    private boolean completing = false;
59
    private final boolean autoCompletion;
60
 
61
    private SQLField field;
62
    private String sqlName;
63
 
64
    private List<String> items;
65
 
66
    private EmptyObjectHelper helper;
67
    private final PropertyChangeSupport supp;
68
    // does this component just gained focus
69
    private boolean gained;
70
    private boolean mousePressed;
71
    // the content of this text field when it gained focus
72
    private String initialText;
73
 
41 ilm 74
    private boolean authorizedNegative = false;
75
 
18 ilm 76
    public DeviseField() {
77
        this(15, false, false);
78
    }
79
 
80
    public DeviseField(boolean bold) {
81
        this(15, false, bold);
82
    }
83
 
84
    public DeviseField(int columns) {
85
        this(columns, false);
86
    }
87
 
88
    private DeviseField(int columns, boolean autoCompletion) {
89
        this(columns, autoCompletion, false);
90
    }
91
 
92
    private DeviseField(int columns, boolean autoCompletion, boolean bold) {
93
        super(columns);
94
        if (bold) {
95
            this.setFont(getFont().deriveFont(Font.BOLD));
96
        }
97
        this.supp = new PropertyChangeSupport(this);
98
        this.gained = false;
99
        this.autoCompletion = autoCompletion;
100
        this.getDocument().addDocumentListener(new SimpleDocumentListener() {
101
            public void update(DocumentEvent e) {
102
                DeviseField.this.textModified();
103
            }
104
        });
105
    }
106
 
107
    /**
108
     * Methode appelée quand le texte est modifié
109
     */
110
    protected void textModified() {
111
        // execute la completion
112
        if (this.autoCompletion)
113
            complete();
114
        this.supp.firePropertyChange("value", null, this.getUncheckedValue());
115
    }
116
 
117
    @Override
118
    public void init(String sqlName, Set<SQLField> fields) {
119
        this.field = CollectionUtils.getSole(fields);
120
        this.sqlName = sqlName;
121
        this.helper = new EmptyObjectHelper(this, new Predicate() {
122
            public boolean evaluate(Object object) {
123
                return object == null;
124
 
125
                // final String val = GestionDevise.currencyToString(((Long)
126
                // object).longValue());
127
            }
128
        });
129
 
130
        // TODO use JFormattedTextField => conflit getValue()
131
        // DefaultFormatterFactory NumberFormatter (getAllowsInvalid) NumberFormat
132
 
133
        addFilteringKeyListener(this);
134
 
135
        // select all on focus gained
136
        // except if the user is selecting with the mouse
137
        this.addFocusListener(new FocusAdapter() {
138
            public void focusGained(FocusEvent e) {
139
                DeviseField.this.gained = true;
140
                DeviseField.this.initialText = getText();
141
                if (!DeviseField.this.mousePressed) {
142
                    selectAll();
143
                }
144
            }
145
        });
146
        this.addMouseListener(new MouseAdapter() {
147
            public void mousePressed(MouseEvent e) {
148
                DeviseField.this.mousePressed = true;
149
            }
150
 
151
            public void mouseReleased(MouseEvent e) {
152
                // don't override the user selection
153
                if (DeviseField.this.gained && getSelectedText() == null) {
154
                    selectAll();
155
                }
156
                // don't select all for each mouse released
157
                DeviseField.this.gained = false;
158
                DeviseField.this.mousePressed = false;
159
            }
160
        });
161
        this.addKeyListener(new KeyAdapter() {
162
            public void keyTyped(KeyEvent keyEvent) {
163
                // Sert a annuler une saisie
164
                if (keyEvent.getKeyChar() == KeyEvent.VK_ESCAPE) {
165
                    DeviseField.this.setValue(DeviseField.this.initialText);
166
                    selectAll();
167
                }
168
            }
169
        });
170
    }
171
 
41 ilm 172
    public boolean isAuthorizedNegative() {
173
        return this.authorizedNegative;
174
    }
18 ilm 175
 
41 ilm 176
    public void setAuthorizedNegative(boolean authorizedNegative) {
177
        this.authorizedNegative = authorizedNegative;
178
    }
179
 
180
    public static void addFilteringKeyListener(final DeviseField textField) {
181
 
18 ilm 182
        textField.addKeyListener(new KeyAdapter() {
183
            public void keyTyped(java.awt.event.KeyEvent keyEvent) {
184
 
185
                final char keychar = keyEvent.getKeyChar();
186
 
187
                if (keychar == KeyEvent.VK_BACK_SPACE) {
188
                    return;
189
                }
190
 
191
                // pas plus de 2 chiffres apres la virgule
192
                int pointPosition = textField.getText().indexOf('.');
193
                if (Character.isDigit(keychar)) {
194
                    if (pointPosition > -1) {
195
                        // System.err.println("Text Selected :: " + textField.getSelectedText());
196
                        if (textField.getSelectedText() == null) {
197
                            if (textField.getCaretPosition() <= pointPosition) {
198
                                return;
199
                            } else {
200
                                if (textField.getText().substring(pointPosition).length() <= 2) {
201
                                    return;
202
                                }
203
                            }
204
                        } else {
205
                            return;
206
                        }
207
                    } else {
208
                        return;
209
                    }
210
                }
211
 
212
                if (keychar == KeyEvent.VK_PERIOD && textField.getText().indexOf('.') < 0)
213
                    return;
214
 
41 ilm 215
                if (textField.isAuthorizedNegative() && keychar == KeyEvent.VK_MINUS && (textField.getText().indexOf('-') < 0) && textField.getCaretPosition() == 0)
216
                    return;
217
 
18 ilm 218
                keyEvent.consume();
219
            }
220
        });
221
    }
222
 
223
    public final void resetValue() {
224
        this.setValue("");
225
    }
226
 
227
    public final void setValue(String val) {
228
        if (!this.getText().equals(val))
229
            this.setText(val);
230
    }
231
 
232
    public void setBold() {
233
        this.setFont(getFont().deriveFont(Font.BOLD));
234
    }
235
 
236
    public Object getUncheckedValue() {
237
 
238
        if (this.getText().trim().length() == 0) {
239
            return null;
240
        } else {
241
            return new Long(GestionDevise.parseLongCurrency(this.getText()));
242
        }
243
        // return this.getText();
244
    }
245
 
246
    public final SQLTable getTable() {
247
        return this.field.getTable();
248
    }
249
 
250
    public String toString() {
251
        return this.getClass().getSimpleName() + " on " + this.field;
252
    }
253
 
254
    /**
255
     * Recherche si on peut completer la string avec les items de completion
256
     *
257
     * @param string
258
     * @return nulll si pas trouve, sinon le mot complet
259
     */
260
    private String getCompletion(String string) {
261
        int c = 0;
262
        if (string.length() < 1) {
263
            return null;
264
        }
265
        String result = null;
266
        for (int i = 0; i < this.items.size(); i++) {
267
            String obj = (String) this.items.get(i);
268
            if (obj.startsWith(string)) {
269
                c++;
270
                result = obj;
271
            }
272
        }
273
        if (c == 1)
274
            return result;
275
        else
276
            return null;
277
    }
278
 
279
    /**
280
     * @param string
281
     */
282
    private final void addItem(String string) {
283
        if (!this.items.contains(string) && string.length() > 1) {
284
 
285
            this.items.add(string);
286
            writeToCache(string);
287
 
288
        }
289
    }
290
 
291
    // charge les elements de completion si besoin
292
    private final void checkCache() {
293
        if (this.items == null) {
294
            this.items = new Vector(20);
295
            readCache();
296
        }
297
    }
298
 
299
    synchronized final void complete() {
300
        checkCache();
301
        if (!this.completing) {
302
            this.completing = true;
303
            String originalText = this.getText();
304
            // ne completer que si le texte fait plus de 2 char et n'est pas que des chiffres
305
            if (originalText.length() > 2 && !originalText.matches("^\\d*$")) {
306
                String completion = this.getCompletion(originalText);
307
                if (completion != null && !this.getText().trim().equalsIgnoreCase(completion.trim())) {
308
                    this.setText(completion);
309
                    this.setSelectionStart(originalText.length());
310
                    this.setSelectionEnd(completion.length());
311
                }
312
            }
313
            this.completing = false;
314
        }
315
    }
316
 
317
    // public void addTextModifiedListener(TextModifiedListener l) {
318
    // if (this.listeners == null) {
319
    // this.listeners = new Vector(1);
320
    // }
321
    // if (!listeners.contains(l)) {
322
    // listeners.addElement(l);
323
    // }
324
    // }
325
 
326
    protected final void addToCache(String s) {
327
        if (s != null) {
328
            if (s.length() > 0 && !this.items.contains(s))
329
                this.items.add(s);
330
        }
331
    }
332
 
333
    // A sous classer pour avoir un autre comportement:
334
 
335
    /**
336
     * Methode a sous classer pour remplir le cache doit appeller addToCache
337
     */
338
    protected void readCache() {
339
        String req = "SELECT * FROM COMPLETION WHERE CHAMP=\"" + this.field.getFullName() + "\"";
340
        ResultSet rs = this.getTable().getBase().execute(req);
341
        try {
342
            while (rs.next()) {
343
                addToCache(rs.getString("LABEL"));
344
            }
345
        } catch (SQLException e) {
346
            e.printStackTrace();
347
        }
348
    }
349
 
350
    protected void writeToCache(String string) {
351
        String req = "INSERT INTO COMPLETION (CHAMP,LABEL) VALUES (\"" + this.field.getFullName() + "\",\"" + string + "\")";
352
        this.getField().getTable().getBase().execute(req);
353
    }
354
 
355
    public Object getValue() {
356
        return this.helper.getValue();
357
    }
358
 
359
    public boolean isEmpty() {
360
        return this.helper.isEmpty();
361
    }
362
 
363
    public void addEmptyListener(EmptyListener l) {
364
        this.helper.addListener(l);
365
    }
366
 
367
    public void addValueListener(PropertyChangeListener l) {
368
        this.supp.addPropertyChangeListener(l);
369
    }
370
 
371
    public SQLField getField() {
372
        return this.field;
373
    }
374
 
21 ilm 375
    @Override
376
    public ValidState getValidState() {
18 ilm 377
        // TODO
21 ilm 378
        // return "Le montant saisi n'est pas correct";
379
        return ValidState.getTrueInstance();
18 ilm 380
    }
381
 
382
    public void addValidListener(ValidListener l) {
383
        // FIXME
384
    }
385
 
19 ilm 386
    @Override
387
    public void removeValidListener(ValidListener l) {
388
        // FIXME
389
    }
390
 
18 ilm 391
    public void show(SQLRowAccessor r) {
392
        if (r.getFields().contains(this.getField().getName())) {
393
            Object o = r.getObject(this.getField().getName());
394
            // if (o.getClass() == Long.class) {
395
            this.setValue(GestionDevise.currencyToString(((Long) o).longValue()));
396
            // } else {
397
            // this.setValue(GestionDevise.currencyToString(((BigInteger) o).longValue()));
398
            // }
399
        }
400
    }
401
 
402
    public void insert(SQLRowValues vals) {
403
        this.update(vals);
404
    }
405
 
406
    public void update(SQLRowValues vals) {
407
        vals.put(this.getField().getName(), this.isEmpty() ? SQLRowValues.SQL_DEFAULT : this.getUncheckedValue());
408
    }
409
 
410
    public String getSQLName() {
411
        return this.sqlName;
412
    }
413
 
414
    public Component getComp() {
415
        return this;
416
    }
417
 
418
    public String getDocId() {
419
        return "DEVISE";
420
    }
421
 
422
    public String getGenericDoc() {
423
        return "";
424
    }
425
 
426
    public boolean onScreen() {
427
        return true;
428
    }
429
 
430
    public boolean isDocTransversable() {
431
        return false;
432
    }
433
}