Source code: jaxe/elements/JETable.java
1 /*
2 Jaxe - Editeur XML en Java
3
4 Copyright (C) 2002 Observatoire de Paris-Meudon
5
6 Ce programme est un logiciel libre ; vous pouvez le redistribuer et/ou le modifier conformément aux dispositions de la Licence Publique Générale GNU, telle que publiée par la Free Software Foundation ; version 2 de la licence, ou encore (à votre choix) toute version ultérieure.
7
8 Ce programme est distribué dans l'espoir qu'il sera utile, mais SANS AUCUNE GARANTIE ; sans même la garantie implicite de COMMERCIALISATION ou D'ADAPTATION A UN OBJET PARTICULIER. Pour plus de détail, voir la Licence Publique Générale GNU .
9
10 Vous devez avoir reçu un exemplaire de la Licence Publique Générale GNU en même temps que ce programme ; si ce n'est pas le cas, écrivez à la Free Software Foundation Inc., 675 Mass Ave, Cambridge, MA 02139, Etats-Unis.
11 */
12
13 package jaxe.elements;
14
15 import jaxe.DialogueChamps;
16 import jaxe.JaxeDocument;
17 import jaxe.JaxeElement;
18 import jaxe.JaxeResourceBundle;
19
20 import java.util.ArrayList;
21 import java.util.Hashtable;
22 import java.awt.*;
23 import java.awt.event.*;
24 import java.util.Vector;
25 import javax.swing.*;
26 import javax.swing.table.TableModel;
27 import javax.swing.table.AbstractTableModel;
28 import javax.swing.table.DefaultTableCellRenderer;
29 import javax.swing.text.JTextComponent;
30 import javax.swing.text.Position;
31 import javax.swing.text.BadLocationException;
32 import javax.swing.text.Style;
33 import javax.swing.text.StyleConstants;
34
35 import org.w3c.dom.*;
36
37
38 /**
39 * Tableau affiché comme tel dans le texte. Les éléments du tableau ne peuvent être que
40 * de courts textes.
41 * Type d'élément Jaxe: 'tableau'
42 * paramètre: trTag: un attribut correspondant à une ligne de tableau
43 * paramètre: tdTag: un attribut correspondant à une cellule de tableau
44 * paramètre: thTag: un attribut correspondant à une cellule d'entête de tableau
45 */
46 public class JETable extends JaxeElement implements ActionListener {
47
48 static String newline = "\n";
49 String TRtag = "tr";
50 String TDtag = "td";
51 String THtag = null;
52 JTable jtable = null;
53 boolean avecEntete;
54
55 /*
56 Comme les tables JETable ne permettent pas de mettre autre chose que du texte dans
57 les cases, il vaut mieux créer une zone à la place si le fichier ouvert contient
58 autre chose que du texte dans les cases du tableau ou si des attributs sont utilisés
59 dans les balises TD
60 */
61 public static boolean preferreZone(JaxeDocument doc, Element el) {
62 // la méthode est statique, il faut utiliser des variables locales...
63 String TRtag = "tr";
64 String TDtag = "td";
65 String THtag = null;
66
67 Element defbalise = doc.cfg.getBaliseAvecType("tableau");
68 if (defbalise != null) {
69 String paramatt = defbalise.getAttribute("param");
70 if (paramatt != null && !"".equals(paramatt) && paramatt.indexOf('/') != -1) {
71 int inds1 = paramatt.indexOf('/');
72 TRtag = paramatt.substring(0, inds1);
73 String param2 = paramatt.substring(inds1+1);
74 int inds2 = param2.indexOf('/');
75 if (inds2 == -1) {
76 TDtag = param2;
77 THtag = null;
78 } else {
79 TDtag = param2.substring(0, inds2);
80 THtag = param2.substring(inds2+1);
81 }
82 } else {
83 TRtag = doc.cfg.getParamFromDefinition(defbalise, "trTag", TRtag);
84 TDtag = doc.cfg.getParamFromDefinition(defbalise, "tdTag", TDtag);
85 THtag = doc.cfg.getParamFromDefinition(defbalise, "thTag", THtag);
86 }
87 }
88
89 for (Node n=el.getFirstChild(); n != null; n=n.getNextSibling()) {
90 if (n.getNodeType() == Node.ELEMENT_NODE) {
91 String bal = n.getNodeName();
92 if (bal.equals(TRtag)) {
93 for (Node n2=n.getFirstChild(); n2 != null; n2=n2.getNextSibling()) {
94 if (n2.getNodeType() == Node.ELEMENT_NODE) {
95 String bal2 = n2.getNodeName();
96 if (bal2.equals(TDtag) || bal2.equals(THtag)) {
97 if (n2.getAttributes() != null && n2.getAttributes().getLength() > 0)
98 return(true);
99 for (Node n3=n2.getFirstChild(); n3 != null; n3=n3.getNextSibling()) {
100 if (n3.getNodeType() == Node.ELEMENT_NODE)
101 return(true);
102 }
103 }
104 }
105 }
106 }
107 }
108 }
109 return(false);
110 }
111
112 public JETable(JaxeDocument doc) {
113 this.doc = doc;
114 }
115
116 protected void obtenirTags(Element defbalise) {
117 if (defbalise != null) {
118 String paramatt = defbalise.getAttribute("param");
119 if (paramatt != null && !"".equals(paramatt) && paramatt.indexOf('/') != -1) {
120 int inds1 = paramatt.indexOf('/');
121 TRtag = paramatt.substring(0, inds1);
122 String param2 = paramatt.substring(inds1+1);
123 int inds2 = param2.indexOf('/');
124 if (inds2 == -1) {
125 TDtag = param2;
126 THtag = null;
127 } else {
128 TDtag = param2.substring(0, inds2);
129 THtag = param2.substring(inds2+1);
130 }
131 } else {
132 TRtag = doc.cfg.getParamFromDefinition(defbalise, "trTag", TRtag);
133 TDtag = doc.cfg.getParamFromDefinition(defbalise, "tdTag", TDtag);
134 THtag = doc.cfg.getParamFromDefinition(defbalise, "thTag", THtag);
135 }
136 }
137 }
138
139 public void init(Position pos, Node noeud) {
140 Element el = (Element)noeud;
141 Element defbalise = doc.cfg.getBaliseNomType(el.getTagName(), "tableau");
142 obtenirTags(defbalise);
143
144 Style s = doc.textPane.addStyle(null, null);
145
146 jtable = makeTable(el);
147
148 //jtable.addMouseListener(new MyMouseListener(this, doc.jframe));
149
150 JPanel p = new JPanel(new BorderLayout());
151 p.add(jtable, BorderLayout.CENTER);
152 JPanel pboutons = new JPanel();
153 pboutons.setLayout(new BoxLayout(pboutons, BoxLayout.Y_AXIS));
154 if (THtag != null) {
155 NodeList thnl = el.getElementsByTagName(THtag);
156 avecEntete = (thnl != null && thnl.getLength() > 0);
157 JCheckBox bcheck = new JCheckBox(getString("table.Entete"), avecEntete);
158 bcheck.addActionListener(this);
159 bcheck.setActionCommand("entête");
160 bcheck.setFont(bcheck.getFont().deriveFont((float)9));
161 bcheck.setMargin(new Insets(0,0,0,0));
162 pboutons.add(bcheck);
163 } else
164 avecEntete = false;
165 JButton bajligne = new JButton(getString("table.AjouterLigne"));
166 bajligne.addActionListener(this);
167 bajligne.setActionCommand("ajligne");
168 bajligne.setFont(bajligne.getFont().deriveFont((float)9));
169 bajligne.setMargin(new Insets(0,0,0,0));
170 pboutons.add(bajligne);
171 JButton bajcolonne = new JButton(getString("table.AjouterColonne"));
172 bajcolonne.addActionListener(this);
173 bajcolonne.setActionCommand("ajcolonne");
174 bajcolonne.setFont(bajcolonne.getFont().deriveFont((float)9));
175 bajcolonne.setMargin(new Insets(0,0,0,0));
176 pboutons.add(bajcolonne);
177 JButton bsupligne = new JButton(getString("table.SupprimerLigne"));
178 bsupligne.addActionListener(this);
179 bsupligne.setActionCommand("supligne");
180 bsupligne.setFont(bsupligne.getFont().deriveFont((float)9));
181 bsupligne.setMargin(new Insets(0,0,0,0));
182 pboutons.add(bsupligne);
183 JButton bsupcolonne = new JButton(getString("table.SupprimerColonne"));
184 bsupcolonne.addActionListener(this);
185 bsupcolonne.setActionCommand("supcolonne");
186 bsupcolonne.setFont(bsupcolonne.getFont().deriveFont((float)9));
187 bsupcolonne.setMargin(new Insets(0,0,0,0));
188 pboutons.add(bsupcolonne);
189 p.add(pboutons, BorderLayout.EAST);
190
191 insertComponent(pos, p);
192 }
193
194 protected TableModel makeTableModel(Element el) {
195 Vector v = new Vector();
196 Vector ventete = new Vector();
197 int nligne = 0;
198 for (Node n=el.getFirstChild(); n != null; n=n.getNextSibling()) {
199 if (n.getNodeType() == Node.ELEMENT_NODE) {
200 String bal = n.getNodeName();
201 if (bal.equals(TRtag)) {
202 Vector v2 = new Vector();
203 for (Node n2=n.getFirstChild(); n2 != null; n2=n2.getNextSibling()) {
204 if (n2.getNodeType() == Node.ELEMENT_NODE) {
205 String bal2 = n2.getNodeName();
206 if (bal2.equals(TDtag) || bal2.equals(THtag)) {
207 Node n3 = n2.getFirstChild();
208 String sval;
209 if (n3 != null && n3.getNodeValue() != null)
210 sval = n3.getNodeValue().trim();
211 else
212 sval = "";
213 v2.add(sval);
214 if (nligne == 0)
215 ventete.add("");
216 }
217 }
218 }
219 if (nligne == 0 || v2.size() == ((Vector)v.get(0)).size()) {
220 v.add(v2);
221 nligne++;
222 } else
223 System.err.println("Erreur: nombre de <TD> incorrect dans la ligne");
224 }
225 }
226 // on ignore le reste
227 }
228 return(new MyTableModel(v, ventete));
229 }
230
231 class MyTableModel extends AbstractTableModel {
232 Vector rowData, columnNames;
233 public MyTableModel(Vector rowData, Vector columnNames) {
234 this.rowData = rowData;
235 this.columnNames = columnNames;
236 }
237 public int getRowCount() {
238 return(rowData.size());
239 }
240 public int getColumnCount() {
241 return(columnNames.size());
242 }
243 public Object getValueAt(int row, int column) {
244 return(((Vector)rowData.elementAt(row)).elementAt(column));
245 }
246 public String getColumnName(int column) {
247 return((String)columnNames.get(column));
248 }
249 public boolean isCellEditable(int row, int column) {
250 return(true);
251 }
252 public void setValueAt(Object aValue, int row, int column) {
253 ((Vector)rowData.elementAt(row)).setElementAt(aValue, column);
254 Element tr = findligne(row);
255 Element td = findcellule(tr, column);
256 String s = (String)aValue;
257 if (td.getFirstChild() == null) {
258 Node textnode = doc.DOMdoc.createTextNode(s);
259 td.appendChild(textnode);
260 } else
261 td.getFirstChild().setNodeValue(s);
262 }
263 }
264
265 protected JTable makeTable(Element el) {
266 JTable ntable = new JTable(makeTableModel(el));
267 ntable.setShowGrid(true);
268 ntable.setGridColor(Color.black);
269 ntable.setDefaultRenderer(Object.class, new CustomCellRenderer());
270 return(ntable);
271 }
272
273 public Element nouvelElement(Element defbalise) {
274 String nombalise = doc.cfg.nomBalise(defbalise);
275 String[] titres = {JaxeResourceBundle.getRB().getString("table.NbLignes"),
276 JaxeResourceBundle.getRB().getString("table.NbColonnes")};
277 JTextComponent[] champs = new JTextComponent[2];
278 champs[0] = new JTextField(10);
279 champs[1] = new JTextField(10);
280 DialogueChamps dlg = new DialogueChamps(doc.jframe,
281 JaxeResourceBundle.getRB().getString("table.NouvelleBalise"), titres, champs);
282 if (!dlg.afficher())
283 return null;
284 String slignes = champs[0].getText();
285 String scolonnes = champs[1].getText();
286
287 int nlignes, ncolonnes;
288 try {
289 nlignes = (Integer.valueOf(slignes)).intValue();
290 ncolonnes = (Integer.valueOf(scolonnes)).intValue();
291 } catch (NumberFormatException ex) {
292 JOptionPane.showMessageDialog(doc.jframe, JaxeResourceBundle.getRB().getString("erreur.Conversion"),
293 JaxeResourceBundle.getRB().getString("table.NouvelleBalise"), JOptionPane.ERROR_MESSAGE);
294 return(null);
295 }
296
297 obtenirTags(defbalise);
298 avecEntete = false;
299
300 Element newel = nouvelElementDOM(doc, nombalise);
301 for (int i=0; i<nlignes; i++) {
302 Element ligneel = doc.DOMdoc.createElement(TRtag);
303 newel.appendChild(ligneel);
304 for (int j=0; j<ncolonnes; j++) {
305 Element cellel = doc.DOMdoc.createElement(TDtag);
306 ligneel.appendChild(cellel);
307 }
308 Node textnode = doc.DOMdoc.createTextNode(newline);
309 newel.appendChild(textnode);
310 }
311
312 return(newel);
313 }
314
315 public void afficherDialogue(JFrame jframe) {
316 }
317
318 public void majAffichage() {
319 jtable.setModel(makeTableModel((Element)noeud));
320 }
321
322 public void mettreAJourDOM() {
323 Element el = (Element)noeud;
324 Element tr = null;
325 for (int l=0; l<jtable.getRowCount(); l++) {
326 Node nr;
327 if (tr == null)
328 nr = el.getFirstChild();
329 else
330 nr = tr.getNextSibling();
331 tr = null;
332 for (; nr != null && tr == null; nr=nr.getNextSibling())
333 if (nr.getNodeType() == Node.ELEMENT_NODE) {
334 String bal = nr.getNodeName();
335 if (bal.equals(TRtag))
336 tr = (Element)nr;
337 }
338 if (tr == null) {
339 System.err.println("Erreur: balise TR non trouvée dans JETable.mettreAJourDOM()");
340 return;
341 }
342 Element td = null;
343 for (int c=0; c<jtable.getColumnCount(); c++) {
344 Node nd;
345 if (td == null)
346 nd = tr.getFirstChild();
347 else
348 nd = td.getNextSibling();
349 td = null;
350 for (; nd != null && td == null; nd=nd.getNextSibling())
351 if (nd.getNodeType() == Node.ELEMENT_NODE) {
352 String bal = nd.getNodeName();
353 if (bal.equals(TDtag) || bal.equals(THtag))
354 td = (Element)nd;
355 }
356 if (td == null) {
357 System.err.println("Erreur: balise TD non trouvée dans JETable.mettreAJourDOM()");
358 return;
359 }
360 String s = (String)jtable.getValueAt(l, c);
361 if (td.getFirstChild() == null) {
362 Node textnode = doc.DOMdoc.createTextNode(s);
363 td.appendChild(textnode);
364 } else
365 td.getFirstChild().setNodeValue(s);
366 }
367 }
368 }
369
370 protected Element findligne(int lsel) {
371 Element el = (Element)noeud;
372 int l = 0;
373 for (Node n=el.getFirstChild(); n != null; n=n.getNextSibling()) {
374 if (n.getNodeType() == Node.ELEMENT_NODE) {
375 String bal = n.getNodeName();
376 if (bal.equals(TRtag)) {
377 if (l == lsel) {
378 Element tr = (Element)n;
379 return(tr);
380 }
381 l++;
382 }
383 }
384 }
385 return(null);
386 }
387
388 protected Element findcellule(Element tr, int csel) {
389 int c = 0;
390 for (Node n=tr.getFirstChild(); n != null; n=n.getNextSibling()) {
391 if (n.getNodeType() == Node.ELEMENT_NODE) {
392 String bal = n.getNodeName();
393 if (bal.equals(TDtag) || bal.equals(THtag)) {
394 if (c == csel) {
395 Element td = (Element)n;
396 return(td);
397 }
398 c++;
399 }
400 }
401 }
402 return(null);
403 }
404
405 public void ajligne() {
406 int lsel = jtable.getSelectedRow();
407 mettreAJourDOM();
408 Element el = (Element)noeud;
409 Element tr = doc.DOMdoc.createElement(TRtag);
410 if (lsel == -1) {
411 el.appendChild(tr);
412 } else {
413 Element trsel = findligne(lsel+1);
414 Node textnode = doc.DOMdoc.createTextNode(newline);
415 if (trsel == null) {
416 el.appendChild(tr);
417 el.appendChild(textnode);
418 } else {
419 el.insertBefore(tr, trsel);
420 el.insertBefore(textnode, trsel);
421 }
422 }
423 for (int j=0; j<jtable.getColumnCount(); j++) {
424 Element td = doc.DOMdoc.createElement(TDtag);
425 tr.appendChild(td);
426 }
427 jtable.setModel(makeTableModel(el));
428 }
429
430 public void ajcolonne() {
431 int csel = jtable.getSelectedColumn();
432 mettreAJourDOM();
433 Element el = (Element)noeud;
434 for (Node n=el.getFirstChild(); n != null; n=n.getNextSibling()) {
435 if (n.getNodeType() == Node.ELEMENT_NODE) {
436 String bal = n.getNodeName();
437 if (bal.equals(TRtag)) {
438 Element tr = (Element)n;
439 Element td;
440 if (n == el.getFirstChild() && avecEntete)
441 td = doc.DOMdoc.createElement(THtag);
442 else
443 td = doc.DOMdoc.createElement(TDtag);
444 if (csel == -1) {
445 tr.appendChild(td);
446 } else {
447 Element tdsel = findcellule(tr, csel+1);
448 if (tdsel == null)
449 tr.appendChild(td);
450 else
451 tr.insertBefore(td, tdsel);
452 }
453 }
454 }
455 }
456 jtable.setModel(makeTableModel(el));
457 }
458
459 public void supligne() {
460 int lsel = jtable.getSelectedRow();
461 if (lsel == -1)
462 return;
463 mettreAJourDOM();
464 Element el = (Element)noeud;
465 Element tr = findligne(lsel);
466 if (tr != null) {
467 if (tr.getNextSibling() != null && tr.getNextSibling().getNodeType() == Node.TEXT_NODE)
468 el.removeChild(tr.getNextSibling());
469 el.removeChild(tr);
470 jtable.setModel(makeTableModel(el));
471 }
472 }
473
474 public void supcolonne() {
475 int csel = jtable.getSelectedColumn();
476 if (csel == -1)
477 return;
478 mettreAJourDOM();
479 Element el = (Element)noeud;
480 for (Node n=el.getFirstChild(); n != null; n=n.getNextSibling()) {
481 if (n.getNodeType() == Node.ELEMENT_NODE) {
482 String bal = n.getNodeName();
483 if (bal.equals(TRtag)) {
484 Element td = findcellule((Element)n, csel);
485 if (td != null)
486 n.removeChild(td);
487 }
488 }
489 }
490 jtable.setModel(makeTableModel(el));
491 }
492
493 public void modifEntete() {
494 avecEntete = !avecEntete;
495 Element tr1 = findligne(0);
496 if (tr1 == null)
497 return;
498 if (avecEntete) {
499 for (Node n = tr1.getFirstChild(); n != null; n=n.getNextSibling()) {
500 if (n.getNodeType() == Node.ELEMENT_NODE && n.getNodeName().equals(TDtag)) {
501 Element td = (Element)n;
502 Node nval = n.getFirstChild();
503 String sval;
504 if (nval != null && nval.getNodeValue() != null)
505 sval = nval.getNodeValue().trim();
506 else
507 sval = "";
508 Element th = doc.DOMdoc.createElement(THtag);
509 Node textnode = doc.DOMdoc.createTextNode(sval);
510 th.appendChild(textnode);
511 tr1.replaceChild(th, td);
512 n = th;
513 }
514 }
515 } else {
516 for (Node n = tr1.getFirstChild(); n != null; n=n.getNextSibling()) {
517 if (n.getNodeType() == Node.ELEMENT_NODE && n.getNodeName().equals(THtag)) {
518 Element th = (Element)n;
519 Node nval = n.getFirstChild();
520 String sval;
521 if (nval != null && nval.getNodeValue() != null)
522 sval = nval.getNodeValue().trim();
523 else
524 sval = "";
525 Element td = doc.DOMdoc.createElement(TDtag);
526 Node textnode = doc.DOMdoc.createTextNode(sval);
527 td.appendChild(textnode);
528 tr1.replaceChild(td, th);
529 n = td;
530 }
531 }
532 }
533 jtable.repaint();
534 }
535
536 // pour avoir la première ligne en gras quand c'est un "entête"
537 class CustomCellRenderer extends DefaultTableCellRenderer {
538 public CustomCellRenderer() {
539 }
540
541 public Component getTableCellRendererComponent( JTable table, Object value,
542 boolean isSelected, boolean hasFocus, int row, int column ) {
543
544 if (avecEntete && row == 0)
545 setFont(new Font("Helvetica", Font.BOLD, 13));
546
547 super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column );
548
549 if (avecEntete && row == 0)
550 setFont(new Font("Helvetica", Font.BOLD, 13));
551
552 return this;
553 }
554 }
555
556 public void actionPerformed(ActionEvent e) {
557 String cmd = e.getActionCommand();
558 if ("ajligne".equals(cmd))
559 ajligne();
560 else if ("ajcolonne".equals(cmd))
561 ajcolonne();
562 else if ("supligne".equals(cmd))
563 supligne();
564 else if ("supcolonne".equals(cmd))
565 supcolonne();
566 else if ("entête".equals(cmd))
567 modifEntete();
568 }
569
570 /*
571 class MyMouseListener extends MouseAdapter {
572 JETable jei;
573 JFrame jframe;
574 public MyMouseListener(JETable obj, JFrame jframe) {
575 super();
576 jei = obj;
577 this.jframe = jframe;
578 }
579 public void mouseClicked(MouseEvent e) {
580 if (e.getClickCount() == 2) {
581 //int index = list.locationToIndex(e.getPoint());
582 //System.out.println("Double clicked on Item " + index);
583 jei.afficherDialogue(jframe);
584 }
585 }
586 }
587 */
588
589 }