OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

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

Rev Author Line No. Line
17 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.ui;
15
 
16
import org.openconcerto.utils.text.DocumentFilterList;
156 ilm 17
import org.openconcerto.utils.text.DocumentFilterList.FilterType;
17 ilm 18
import org.openconcerto.utils.text.LimitedSizeDocumentFilter;
19
 
19 ilm 20
import java.awt.Color;
17 ilm 21
import java.awt.Component;
22
import java.awt.Rectangle;
23
import java.awt.event.ActionEvent;
24
import java.awt.event.ActionListener;
25
import java.awt.event.ComponentEvent;
26
import java.awt.event.ComponentListener;
27
import java.awt.event.KeyAdapter;
28
import java.awt.event.KeyEvent;
29
import java.util.Iterator;
30
 
31
import javax.swing.AbstractCellEditor;
32
import javax.swing.JTable;
33
import javax.swing.JTextArea;
34
import javax.swing.SwingUtilities;
19 ilm 35
import javax.swing.border.LineBorder;
17 ilm 36
import javax.swing.event.DocumentEvent;
37
import javax.swing.event.DocumentListener;
38
import javax.swing.table.TableCellEditor;
39
import javax.swing.text.AbstractDocument;
40
import javax.swing.text.BadLocationException;
41
import javax.swing.text.DocumentFilter;
42
 
43
public class TextAreaTableCellEditor extends AbstractCellEditor implements TableCellEditor, ActionListener {
44
 
45
    final JTextArea textArea = new JTextArea();
46
 
47
    public TextAreaTableCellEditor(final JTable t) {
19 ilm 48
        // Mimic JTable.GenericEditor behavior
49
        this.textArea.setBorder(new LineBorder(Color.black));
17 ilm 50
        textArea.addKeyListener(new KeyAdapter() {
51
            @Override
52
            public void keyPressed(KeyEvent e) {
53
                if (e.getKeyCode() == KeyEvent.VK_TAB) {
54
                    e.consume();
55
 
56
                    final int column;
57
                    final int row = t.getEditingRow();
58
 
59
                    // gestion tab ou shift+tab
60
                    if (e.getModifiers() == KeyEvent.SHIFT_MASK) {
61
                        column = t.getEditingColumn() - 1;
62
                    } else {
63
                        column = t.getEditingColumn() + 1;
64
                    }
65
 
66
                    SwingUtilities.invokeLater(new Runnable() {
65 ilm 67
 
17 ilm 68
                        public void run() {
93 ilm 69
                            if (t.getCellEditor() != null && t.getCellEditor().stopCellEditing()) {
65 ilm 70
                                if (column >= 0 && column < t.getColumnCount()) {
71
                                    t.setColumnSelectionInterval(column, column);
72
                                    t.setRowSelectionInterval(row, row);
73 ilm 73
                                    // Need to postpone editCell because selection with cancel
74
                                    // selection
75
                                    SwingUtilities.invokeLater(new Runnable() {
17 ilm 76
 
73 ilm 77
                                        public void run() {
78
                                            if (t.editCellAt(row, column)) {
79
                                                t.getEditorComponent().requestFocusInWindow();
80
                                            }
81
                                        }
82
                                    });
17 ilm 83
                                }
84
                            }
85
                        }
86
                    });
87
                } else {
88
                    if (e.getKeyCode() == KeyEvent.VK_SPACE && e.getModifiers() == KeyEvent.SHIFT_MASK) {
89
                        // FIXME Utiliser une autre méthode
90
                        e.setModifiers(0);
91
                    }
92
                }
93
            }
94
        });
95
 
96
        textArea.setWrapStyleWord(true);
97
        textArea.setLineWrap(true);
98
        textArea.setFont(t.getFont());
99
        textArea.addComponentListener(new ComponentListener() {
100
 
101
            public void componentHidden(ComponentEvent e) {
102
            }
103
 
104
            public void componentMoved(ComponentEvent e) {
105
            }
106
 
107
            public void componentResized(ComponentEvent e) {
108
                updateRowHeight(t, textArea.getText());
109
            }
110
 
111
            public void componentShown(ComponentEvent e) {
112
            }
113
        });
114
        textArea.getDocument().addDocumentListener(new DocumentListener() {
115
 
116
            public void changedUpdate(DocumentEvent e) {
117
                updateRowHeight(t, e);
118
            }
119
 
120
            public void insertUpdate(DocumentEvent e) {
121
 
122
                updateRowHeight(t, e);
123
 
124
            }
125
 
126
            public void removeUpdate(DocumentEvent e) {
127
                updateRowHeight(t, e);
128
 
129
            }
130
        });
131
 
132
        // FIXME si on supprime une ligne sur laquelle on est en train d'éditer, il faut arréter
133
        // l'édition de la ligne
134
        // t.getModel().addTableModelListener(new TableModelListener() {
135
        // @Override
136
        // public void tableChanged(TableModelEvent e) {
137
        // // TODO Auto-generated method stub
138
        // if (e.getType() == TableModelEvent.DELETE) {
139
        // cancelCellEditing();
140
        // }
141
        // }
142
        // });
143
        // JScrollPane scrollPane = new JScrollPane(textArea);
144
        // scrollPane.setBorder(null);
145
        // editorComponent = textArea;
146
 
147
        // delegate = new DefaultCellEditor.EditorDelegate() {
148
        // public void setValue(Object value) {
149
        // System.err.println("TextAreaTableCell setValue ____ " + value);
150
        // textArea.setText((value != null) ? value.toString() : "");
151
        // }
152
        //
153
        // public Object getCellEditorValue() {
154
        // return textArea.getText();
155
        // }
156
        //
157
        // };
158
    }
159
 
160
    private void updateRowHeight(final JTable t, DocumentEvent e) {
161
        // Le nouveau text qui ira dans le textArea
162
        String newText = "";
163
        try {
164
            newText = e.getDocument().getText(0, e.getDocument().getLength());
165
 
166
        } catch (BadLocationException e1) {
167
            e1.printStackTrace();
168
        }
169
        updateRowHeight(t, newText);
170
        t.invalidate();
171
        t.repaint();
172
    }
173
 
174
    // retourne la hauteur qu'aurait le textArea si on lui mettait
175
    // le text passé en paramètre
176
    public static int getHeightFor(String s, JTextArea textArea) {
177
        Rectangle r = null;
178
        try {
179
            r = textArea.modelToView(s.length());
156 ilm 180
        } catch (BadLocationException | IllegalArgumentException e2) {
181
            // java.lang.IllegalArgumentException: TextHitInfo is out of range
182
            // from java.awt.font.TextLayout.checkTextHit(Unknown Source)
17 ilm 183
            return -1;
184
        }
185
        int h = 0;
186
        // if the component does not yet have a positive size
187
        if (r != null) {
188
            final int newHeight = r.y + r.height + 2;
189
            h = Math.max(textArea.getMinimumSize().height, newHeight);
190
        }
191
        return h;
192
    }
193
 
194
    public void updateRowHeight(final JTable t, String newText) {
195
 
196
        // On recupere la vraie taille du textarea
197
        int preferredHeight = getHeightFor(newText, textArea);// textArea.getPreferredSize().height;
198
        // Il peut arriver que ca ne fonctionne pas.. on se rabat alors sur le textarea
199
        if (preferredHeight == -1) {
200
            preferredHeight = textArea.getPreferredSize().height + 17;
201
        }
202
        EnhancedTable eTable = (EnhancedTable) t;
203
        int editingRow = eTable.getEditingRow();
204
        int editingCol = eTable.getEditingColumn();
205
        eTable.setPreferredRowHeight(editingRow, editingCol, preferredHeight);
206
 
207
        // Hauteur preferrée max de la ligne
208
        int maxHeight = eTable.getMaxRowHeight(editingRow);
209
 
210
        if (t.getRowHeight(editingRow) != maxHeight) {
211
            t.setRowHeight(editingRow, maxHeight);
212
 
213
        }
214
        t.repaint();
215
    }
216
 
217
    /**
218
     * @return Returns the textArea.
219
     */
220
    protected JTextArea getTextArea() {
221
        return textArea;
222
    }
223
 
224
    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
225
 
226
        final Object o = value;
227
        textArea.setText((o != null) ? o.toString() : "");
228
        textArea.selectAll();
229
 
230
        Runnable r = new Runnable() {
231
 
232
            public void run() {
233
                textArea.grabFocus();
234
            }
235
        };
236
        SwingUtilities.invokeLater(r);
237
        return textArea;
238
    }
239
 
240
    public Object getCellEditorValue() {
241
        return textArea.getText();
242
    }
243
 
244
    public void actionPerformed(ActionEvent e) {
245
        this.stopCellEditing();
246
    }
247
 
248
    public void setLimitedSize(int nbChar) {
249
        // rm previous ones
250
        final DocumentFilterList dfl = DocumentFilterList.get((AbstractDocument) textArea.getDocument());
251
        final Iterator<DocumentFilter> iter = dfl.getFilters().iterator();
252
        while (iter.hasNext()) {
253
            final DocumentFilter df = iter.next();
254
            if (df instanceof LimitedSizeDocumentFilter)
255
                iter.remove();
256
        }
257
        // add the new one
258
        DocumentFilterList.add((AbstractDocument) textArea.getDocument(), new LimitedSizeDocumentFilter(nbChar), FilterType.SIMPLE_FILTER);
259
    }
260
}