Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: jaxe/JaxeElement.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;
14  
15  import jaxe.elements.JEInconnu;
16  import jaxe.elements.JEStyle;
17  import jaxe.elements.JESwing;
18  import jaxe.elements.JETableTexte;
19  import jaxe.elements.JETexte;
20  
21  import java.awt.*;
22  import java.util.ArrayList;
23  import java.awt.event.MouseAdapter;
24  import java.awt.event.MouseEvent;
25  import javax.swing.*;
26  import javax.swing.text.AttributeSet;
27  import javax.swing.text.BadLocationException;
28  import javax.swing.text.Position;
29  import javax.swing.text.SimpleAttributeSet;
30  import javax.swing.text.Style;
31  import javax.swing.text.StyleConstants;
32  import org.w3c.dom.Element;
33  import org.w3c.dom.Node;
34  import org.w3c.dom.DOMException;
35  
36  /**
37   * Elément Jaxe, représentant à la fois l'affichage graphique et l'arbre DOM correspondant (noeud)
38   */
39  public abstract class JaxeElement {
40      
41      public final static String kNormal = "NORMAL";
42      public final static String kGras = "GRAS";
43      public final static String kItalique = "ITALIQUE";
44      public final static String kExposant = "EXPOSANT";
45      public final static String kIndice = "INDICE";
46      public final static String kSouligne = "SOULIGNE";
47      
48      //static String newline = Jaxe.newline;
49      public Position debut=null; // position du premier caractère de l'élément
50      public Position fin=null; // position du dernier caractère de l'élément
51      public Node noeud;
52      public JaxeDocument doc;
53      ArrayList jcomps = new ArrayList(); // de JComponent
54      ArrayList compos = new ArrayList(); // de Position (positions des composants)
55      private boolean effacementAutorise = true;
56      private boolean editionAutorisee = true;
57      
58      /**
59       * Insère le texte de l'élément à partir de l'arbre DOM, à la position pos dans le texte
60       */
61      public abstract void init(Position pos, Node noeud);
62      
63      /**
64       * Initialise le champ noeud, met à jour dom2JaxeElement, et appelle init(pos, noeud)
65       */
66      public void creer(Position pos, Node noeud) {
67          this.noeud = noeud;
68          doc.dom2JaxeElement.put(noeud, this);
69          init(pos, noeud);
70          Element defbalise = null;
71          if (doc.cfg != null) {
72              defbalise = doc.cfg.getBaliseDef(noeud.getNodeName());
73              if (defbalise != null) {
74                  String seffacement = doc.cfg.getParamFromDefinition(defbalise, "effacementAutorise", null);
75                  String sedition = doc.cfg.getParamFromDefinition(defbalise, "editionAutorisee", null);
76                  effacementAutorise = !("false".equals(seffacement));
77                  editionAutorisee = !("false".equals(sedition));
78              }
79          }
80      }
81      
82      public abstract Element nouvelElement(Element defbalise);
83      
84      /**
85       * Affiche le dialogue correspondant à l'élément
86       */
87      public void afficherDialogue(JFrame jframe) {
88          // à remplacer dans les sousclasses
89      }
90      
91      /**
92       * Mise à jour de l'affichage par rapport à l'arbre XML
93       */
94      public void majAffichage() {
95          // à remplacer dans les sousclasses
96      }
97      
98      /**
99       * Test et mise à jour de l'affichage de la validité
100      */
101     public void majValidite() {
102         // à remplacer dans les sousclasses
103     }
104     
105     /**
106      * Renvoit la liste des composants graphiques utilisés dans l'affichage en plus du texte
107      */
108     public ArrayList getComponents() {
109         return jcomps;
110     }
111     
112     /**
113      * Renvoit la liste des positions dans le texte des composants graphiques
114      */
115     public ArrayList getComponentPositions() {
116         return compos;
117     }
118     
119     /**
120      * Insère le texte dans le Textpane en mettant à jour debut et fin
121      */
122     public Position insertText(Position pos, String texte, AttributeSet attset) {
123         try {
124             int offsetdebut = pos.getOffset();
125             doc.insertString(pos.getOffset(), texte, attset);
126             if (debut == null)
127                 debut = doc.createPosition(offsetdebut);
128             if (pos.getOffset() == 0) // bug fix with insertString
129                 pos = doc.createPosition(1);
130             fin = doc.createPosition(pos.getOffset()-1);
131         } catch (BadLocationException ex) {
132             System.err.println("BadLocationException: " + ex.getMessage());
133         }
134         return(pos);
135     }
136     
137     /**
138      * Insère le texte dans le Textpane en mettant à jour debut et fin
139      */
140     public Position insertText(Position pos, String texte) {
141         SimpleAttributeSet att = null;
142         JaxeElement jeparent = doc.elementA(pos.getOffset());
143         if (jeparent != null) {
144             if (jeparent.debut.getOffset() == pos.getOffset() && !(jeparent instanceof JESwing))
145                 jeparent = jeparent.getParent();
146             att = jeparent.attStyle(null);
147         }
148         return(insertText(pos, texte, att));
149     }
150     
151     /**
152      * Insère le composant graphique dans le texte, en l'ajoutant dans la liste des composants
153      * et en mettant à jour debut et fin
154      */
155     public Position insertComponent(Position pos, JComponent comp) {
156         int offsetdebut = pos.getOffset();
157         Style s = doc.textPane.addStyle(null, null);
158         StyleConstants.setComponent(s, comp);
159         try {
160             doc.insertString(pos.getOffset(), "*", s);
161             jcomps.add(comp);
162             compos.add(doc.createPosition(pos.getOffset() - 1));
163             doc.fixbug(comp);
164             if (debut == null)
165                 debut = doc.createPosition(offsetdebut);
166             fin = doc.createPosition(offsetdebut);
167             if (pos.getOffset() == 0) // bug fix with insertString
168                 pos = doc.createPosition(1);
169         } catch (BadLocationException ex) {
170             System.err.println("BadLocationException: " + ex.getMessage());
171         }
172         return(pos);
173     }
174     
175     /**
176      * Insère l'icône dans le texte, en l'ajoutant dans la liste des composants
177      * et en mettant à jour debut et fin
178      */
179     public Position insertIcon(Position pos, Icon icon) {
180         int offsetdebut = pos.getOffset();
181         Style s = doc.textPane.addStyle(null, null);
182         StyleConstants.setIcon(s, icon);
183         try {
184             doc.insertString(pos.getOffset(), "*", s);
185             jcomps.add(icon);
186             compos.add(doc.createPosition(pos.getOffset() - 1));
187             //doc.fixbug(comp);
188             if (debut == null)
189                 debut = doc.createPosition(offsetdebut);
190             fin = doc.createPosition(offsetdebut);
191             if (pos.getOffset() == 0) // bug fix with insertString
192                 pos = doc.createPosition(1);
193         } catch (BadLocationException ex) {
194             System.err.println("BadLocationException: " + ex.getMessage());
195         }
196         return(pos);
197     }
198     
199     /**
200      * Renvoit l'élément de plus bas niveau se trouvant à la position donnée dans le texte
201      */
202     public JaxeElement elementA(int pos) {
203         if (debut == null || fin == null)
204             return null;
205         if (debut.getOffset() > pos || fin.getOffset() < pos)
206             return null;
207         for (Node n=noeud.getFirstChild(); n != null; n=n.getNextSibling()) {
208             if (n.getNodeType() == Node.ELEMENT_NODE || n.getNodeType() == Node.TEXT_NODE)  {
209                 JaxeElement je = doc.getElementForNode(n);
210                 if (je != null) {
211                     JaxeElement nje = je.elementA(pos);
212                     if (nje != null)
213                         return nje;
214                 }
215             }
216         }
217         return this;
218     }
219 
220     /**
221      * Renvoit les éléments se trouvant dans la zone du texte indiquée
222      */
223     public ArrayList elementsDans(int dpos, int fpos) {
224         ArrayList l = new ArrayList();
225         if (debut == null || fin == null)
226             return l;
227         if (debut.getOffset() > fpos || fin.getOffset() < dpos)
228             return l;
229         if (debut.getOffset() >= dpos && fin.getOffset() <= fpos)
230             l.add(this);
231         else
232             for (Node n=noeud.getFirstChild(); n != null; n=n.getNextSibling()) {
233                 if (n.getNodeType() == Node.ELEMENT_NODE || n.getNodeType() == Node.TEXT_NODE)  {
234                     JaxeElement je = doc.getElementForNode(n);
235                     if (je != null)
236                         l.addAll(je.elementsDans(dpos, fpos));
237                 }
238             }
239         return l;
240     }
241     
242     /**
243      * Renvoit le nombre XPath (le numéro de l'élément dans la liste des éléments
244      * avec ce nom), ou 0 si le noeud n'a pas de parent.
245      */
246     public int nombreXPath() {
247         JaxeElement p = getParent();
248         if (p == null)
249             return(0);
250         int no = 0;
251         String nomel = noeud.getNodeName();
252         for (Node n=p.noeud.getFirstChild(); n != null; n=n.getNextSibling()) {
253             if (nomel.equals(n.getNodeName()))
254                 no++;
255             if (n == noeud)
256                 break;
257         }
258         return(no);
259     }
260     
261     /**
262      * Renvoit le chemin XML pour la position pos
263      */
264     public String cheminA(int pos) {
265         if (debut == null || fin == null)
266             return null;
267         if (debut.getOffset() > pos || fin.getOffset() < pos)
268             return null;
269         if (noeud.getNodeType() == Node.TEXT_NODE)
270             return("texte");
271         if (!(noeud.getNodeType() == Node.ELEMENT_NODE))
272             return(null);
273         Element el = (Element)noeud;
274         String nomel = el.getTagName();
275         if (getParent() != null)
276             nomel += "[" + nombreXPath() + "]";
277         for (Node n=noeud.getFirstChild(); n != null; n=n.getNextSibling()) {
278             if (n.getNodeType() == Node.ELEMENT_NODE || n.getNodeType() == Node.TEXT_NODE) {
279                 JaxeElement je = doc.getElementForNode(n);
280                 if (je != null) {
281                     String chemin = je.cheminA(pos);
282                     if (chemin != null)
283                         return(nomel + "/" + chemin);
284                 }
285             }
286         }
287         return(nomel);
288     }
289     
290     /**
291      * Renvoit le premier élément enfant de celui-ci dont la position est pos ou après pos
292      */
293     public JaxeElement enfantApres(int pos) {
294         if (debut == null || fin == null)
295             return null;
296         if (debut.getOffset() > pos || fin.getOffset() < pos)
297             return null;
298         for (Node n=noeud.getFirstChild(); n != null; n=n.getNextSibling()) {
299             if (n.getNodeType() == Node.ELEMENT_NODE || n.getNodeType() == Node.TEXT_NODE)  {
300                 JaxeElement je = doc.getElementForNode(n);
301                 if (je != null) {
302                     if (je.debut.getOffset() == pos)
303                         return(je);
304                     JaxeElement nje = je.elementA(pos);
305                     if (nje != null && n.getNextSibling() != null) {
306                         return(doc.getElementForNode(n.getNextSibling()));
307                     }
308                 }
309             }
310         }
311         return null;
312     }
313     
314     /**
315      * appelé juste avant que l'élément soit effacé
316      */
317     public void effacer() {
318         for (Node n=noeud.getFirstChild(); n != null; n=n.getNextSibling()) {
319             if (n.getNodeType() == Node.ELEMENT_NODE || n.getNodeType() == Node.TEXT_NODE)  {
320                 JaxeElement je = doc.getElementForNode(n);
321                 if (je != null)
322                     je.effacer();
323             }
324         }
325         jcomps = new ArrayList();
326         compos = new ArrayList();
327     }
328     
329     /**
330      * met à jour l'arbre de JaxeElement et l'arbre DOM à partir de modifs de la zone de texte
331      */
332     public void mettreAJourDOM() {
333         if (debut == null || fin == null)
334             return;
335         try {
336             if (noeud.getNodeType() == Node.TEXT_NODE || this instanceof JEStyle) {
337                 Node nsuivant = noeud.getNextSibling();
338                 if (nsuivant != null) {
339                     JaxeElement jesuivant = doc.getElementForNode(nsuivant);
340                     if (jesuivant != null && jesuivant.debut.getOffset() > fin.getOffset() + 1) {
341                         // texte rajouté à la fin, avant un autre élément
342                         fin = doc.createPosition(jesuivant.debut.getOffset() - 1);
343                     }
344                 }
345                 String texte = doc.getText(debut.getOffset(), fin.getOffset() - debut.getOffset() + 1);
346                 if (texte == null || "".equals(texte))
347                     getParent().supprimerEnfant(this);
348                 else {
349                     if (noeud.getNodeType() == Node.TEXT_NODE)
350                         noeud.setNodeValue(texte);
351                     else if (noeud.getFirstChild() != null) //jestyle
352                         noeud.getFirstChild().setNodeValue(texte);
353                 }
354             } else {
355                 int offdebut = debut.getOffset();
356                 int debuttexte;
357                 if (this instanceof JESwing)
358                     debuttexte = offdebut;
359                 else
360                     debuttexte = offdebut + 1;
361                 for (Node n=noeud.getFirstChild(); n != null; n=n.getNextSibling()) {
362                     JaxeElement je = doc.getElementForNode(n);
363                     if (je != null) {
364                         if (debuttexte < je.debut.getOffset()) {
365                             JaxeElement jeprev = null;
366                             if (n.getPreviousSibling() != null)
367                                 jeprev = doc.getElementForNode(n.getPreviousSibling());
368                             if (jeprev != null &&
369                                 (jeprev instanceof JEStyle || jeprev instanceof JETexte)) {
370                                 // texte ajouté à la fin du précédent noeud
371                                 jeprev.fin = doc.createPosition(je.debut.getOffset() - 1);
372                             } else if (je instanceof JETexte)
373                                 // texte ajouté au début
374                                 je.debut = doc.createPosition(debuttexte);
375                             else {
376                                 // nouvelle zone de texte avant ce noeud
377                                 String texte = doc.getText(debuttexte,
378                                     je.debut.getOffset() - debuttexte);
379                                 JETexte newje = JETexte.nouveau(doc, doc.createPosition(debuttexte),
380                                     doc.createPosition(je.debut.getOffset() - 1), texte);
381                                 noeud.insertBefore(newje.noeud, n);
382                             }
383                         }
384                         offdebut = je.fin.getOffset();
385                         debuttexte = offdebut + 1;
386                     }
387                 }
388                 if (debuttexte < fin.getOffset()) { // texte à la fin, après le dernier enfant
389                     JaxeElement pje = null;
390                     if (noeud.getLastChild() != null)
391                         pje = doc.getElementForNode(noeud.getLastChild());
392                     if (pje instanceof JEStyle || pje instanceof JETexte)
393                         // texte ajouté à la fin du dernier enfant
394                         pje.fin = doc.createPosition(fin.getOffset() - 1);
395                     else {
396                         // nouvelle zone de texte à la fin
397                         String texte = doc.getText(debuttexte,
398                             fin.getOffset() - debuttexte);
399                         JETexte newje = JETexte.nouveau(doc, doc.createPosition(debuttexte),
400                             doc.createPosition(fin.getOffset() - 1), texte);
401                         noeud.appendChild(newje.noeud);
402                     }
403                 }
404                 for (Node n=noeud.getFirstChild(); n != null; n=n.getNextSibling()) {
405                     JaxeElement je = doc.getElementForNode(n);
406                     if (je != null)
407                         je.mettreAJourDOM();
408                 }
409             }
410         } catch (BadLocationException ex) {
411             System.err.println("mettreAJourDOM: BadLocationException: " + ex.getMessage());
412         }
413     }
414     
415     /**
416      * nouvel élément DOM
417      */
418     public static Element nouvelElementDOM(JaxeDocument doc, String nombalise) {
419         Element newel;
420         if (doc.cfg.namespace() == null)
421             newel = doc.DOMdoc.createElement(nombalise);
422         else {
423             Config conf = doc.cfg.getBaliseConf(nombalise);
424             if (conf == null)
425                 conf = doc.cfg;
426             if (conf.prefixe() != null)
427                 nombalise = conf.prefixe() + ":" + nombalise;
428             newel = doc.DOMdoc.createElementNS(conf.namespace(), nombalise);
429         }
430         return(newel);
431     }
432     
433     /**
434      * initialise et insère cet élément dans le texte et l'arbre DOM
435      */
436     public void inserer(Position pos, Node newel) {
437         doc.textPane.debutIgnorerEdition();
438         insererDOM(pos, newel);
439         creer(pos, newel);
440         doc.textPane.finIgnorerEdition();
441         
442         // JESwing: mise à jour du début des parents
443         JaxeElement jeparent = getParent();
444         while (jeparent instanceof JESwing && jeparent.debut.getOffset() > debut.getOffset()) {
445             jeparent.debut = debut;
446             jeparent = jeparent.getParent();
447         }
448     }
449     
450     /**
451      * insère newel dans l'arbre DOM
452      */
453     public void insererDOM(Position pos, Node newel) {
454         JaxeElement parent = doc.rootJE.elementA(pos.getOffset());
455         if (parent.debut.getOffset() == pos.getOffset() && !(parent instanceof JESwing))
456             parent = parent.getParent();
457         if (parent instanceof JETexte) {
458             int ic = pos.getOffset() - parent.debut.getOffset();
459             if (ic > 0) {
460              // nouvelle zone de texte... à revoir
461                 /*String s = parent.noeud.getNodeValue();
462                 String s1 = s.substring(0, ic);
463                 String s2 = s.substring(ic);
464                 parent.noeud.setNodeValue(s2);
465                 Node ns1 = doc.DOMdoc.createTextNode(s1);
466                 Node parent2 = parent.noeud.getParentNode();
467                 parent2.insertBefore(ns1, parent.noeud);
468                 parent2.insertBefore(newel, parent.noeud);*/
469                 JaxeElement je2 = parent.couper(pos);
470                 Node parent2 = parent.noeud.getParentNode();
471                 parent2.insertBefore(newel, je2.noeud);
472             } else {
473                 Node parent2 = parent.noeud.getParentNode();
474                 parent2.insertBefore(newel, parent.noeud);
475             }
476         } else {
477             JaxeElement jelbef = parent.enfantApres(pos.getOffset());
478             if (jelbef == null)
479                 parent.noeud.appendChild(newel);
480             else
481                 parent.noeud.insertBefore(newel, jelbef.noeud);
482         }
483     }
484     
485     /**
486      * creer les enfants de ce noeud, en supposant que c'est un élément DOM
487      */
488     public void creerEnfants(Position newpos) {
489         Element el = (Element)noeud;
490         for (Node n=el.getFirstChild(); n != null; n=n.getNextSibling())
491             creerEnfant(newpos, n);
492     }
493     
494     /**
495      * creer l'enfant n à la position newpos (avec JaxeElement.creer)
496      */
497     public void creerEnfant(Position newpos, Node n) {
498         int offsetdebut = newpos.getOffset();
499         if (n.getNodeType() == Node.ELEMENT_NODE) {
500             String balise = n.getNodeName();
501             Element bdef = null;
502             if (doc.cfg != null)
503                 bdef = doc.cfg.getBaliseDef(balise);
504             if (bdef == null) {
505                 JEInconnu newje = new JEInconnu(doc);
506                 newje.creer(newpos, (Element)n);
507             } else {
508                 String typebalise = bdef.getAttribute("type");
509                 if (typebalise.equals("style") && n.getChildNodes().getLength() == 0) {
510                     // on ne crée pas de JEStyle vide, sinon debut = fin = null -> pb
511                 } else {
512                     JaxeElement newje;
513                     JaxeElement oldje = doc.getElementForNode(n);
514                     if (oldje != null) {
515                         // il existe déjà un JaxeElement pour ce noeud, on va le réutiliser
516                         // (il est peut-être pointé par un JaxeUndoableEdit)
517                         newje = oldje;
518                         newje.debut = null;
519                         newje.fin = null;
520                         newje.jcomps = new ArrayList();
521                         newje.compos = new ArrayList();
522                     } else
523                         newje = JEFactory.createJE(typebalise, doc, bdef, (Element)n);
524                     newje.creer(newpos, (Element)n);
525                 }
526             }
527         } else if (n.getNodeType() == Node.TEXT_NODE) {
528             JETexte newje = new JETexte(doc);
529             newje.creer(newpos, n);
530         }
531         try {
532             if (debut == null)
533                 debut = doc.createPosition(offsetdebut);
534             if (newpos.getOffset() == 0) // bug fix with insertString
535                 newpos = doc.createPosition(1);
536             fin = doc.createPosition(newpos.getOffset()-1);
537         } catch (BadLocationException ex) {
538             System.err.println("BadLocationException: " + ex.getMessage());
539         }
540     }
541     
542     /**
543      * position pour setCaretPosition après création d'un nouvel élément
544      */
545     public Position insPosition() {
546         try {
547             Position p = doc.createPosition(fin.getOffset() + 1);
548             return(p);
549         } catch (BadLocationException ex) {
550             System.err.println("BadLocationException: " + ex.getMessage());
551             return(debut);
552         }
553     }
554     
555     /**
556      * Renvoit l'élément parent, en utilisant l'arbre DOM
557      */
558     public JaxeElement getParent() {
559         Node parent = noeud.getParentNode();
560         if (parent == null)
561             return null;
562         return(doc.getElementForNode(parent));
563     }
564     
565     /**
566      * supprime l'enfant je à la fois dans le texte et dans le DOM
567      */
568     public void supprimerEnfant(JaxeElement je) {
569         try {
570             int len = je.fin.getOffset() - je.debut.getOffset() + 1;
571             /*String cfin = doc.getText(je.fin.getOffset() + 1, 1);
572             if (newline.equals(cfin))
573                 len++;*/
574             int idebut = je.debut.getOffset();
575             /*
576             javax.swing.text.Element pel = doc.getParagraphElement(idebut - 1);
577             javax.swing.text.Element pel2 = doc.getParagraphElement(idebut);
578             if (pel2 != pel) {
579                 AttributeSet attavant = pel.getAttributes();
580                 doc.setParagraphAttributes(pel2.getStartOffset(), pel2.getEndOffset() - pel2.getStartOffset(), attavant, true);
581             }
582             */ // bug avec jdk 1.4
583             doc.remove(idebut, len);
584         } catch (BadLocationException ex) {
585             System.err.println("BadLocationException: " + ex.getMessage());
586         }
587         
588         supprimerEnfantDOM(je);
589     }
590     
591     /**
592      * supprime l'enfant je dans le DOM
593      */
594     public void supprimerEnfantDOM(JaxeElement je) {
595         try {
596             noeud.removeChild(je.noeud);
597         } catch (DOMException ex) {
598             System.err.println("DOMException: " + ex.getMessage());
599         }
600     }
601     
602     /**
603      * remplace l'enfant je à la fois dans le texte et dans le DOM
604      */
605     public void remplacerEnfant(JaxeElement je, JaxeElement newje) {
606         try {
607             doc.remove(je.debut.getOffset(), je.fin.getOffset() - je.debut.getOffset() + 1);
608         } catch (BadLocationException ex) {
609             System.err.println("BadLocationException: " + ex.getMessage());
610         }
611         newje.creer(newje.debut, newje.noeud);
612         
613         remplacerEnfantDOM(je, newje);
614     }
615     
616     /**
617      * remplace l'enfant je dans le DOM
618      */
619     public void remplacerEnfantDOM(JaxeElement je, JaxeElement newje) {
620         Node parent = je.noeud.getParentNode();
621         if (parent == null)
622             System.err.println("remplacerEnfantDOM: parent null !");
623         try {
624             parent.replaceChild(newje.noeud, je.noeud);
625         } catch (DOMException ex) {
626             System.err.println("DOMException: " + ex.getMessage());
627         }
628     }
629     
630     /**
631      * Renvoit la profondeur dans l'arbre XML.
632      */
633     /*public int profondeur() {
634         JaxeElement p = getParent();
635         if (p == null)
636             return(0);
637         else
638             return(p.profondeur() + 1);
639     }*/
640     
641     /**
642      * Indique si les descendants de l'élément doivent être indentés
643      */
644     public boolean avecIndentation() {
645         return(false);
646     }
647     
648     /**
649      * Renvoit les indentations dans l'arbre XML. 0 pour la racine de l'arbre et JETableTexte.
650      */
651     public int indentations() {
652         JaxeElement p = getParent();
653         if (p != null) {
654             JaxeElement p2 = p.getParent();
655             if (p2 != null) {
656                 p2 = p2.getParent();
657                 if (p2 instanceof JETableTexte)
658                     return(0);
659             }
660         }
661         if (p == null)
662             return(0);
663         else if (avecIndentation())
664             return(p.indentations() + 1);
665         else
666             return(p.indentations());
667     }
668     
669     /**
670      * coupe la zone de texte en 2, retourne la nouvelle zone créée après celle-ci
671      */
672     public JaxeElement couper(Position pos) {
673         String t = noeud.getNodeValue();
674         String t1 = t.substring(0, pos.getOffset() - debut.getOffset());
675         String t2 = t.substring(pos.getOffset() - debut.getOffset());
676         noeud.setNodeValue(t1);
677         Node textnode2 = doc.DOMdoc.createTextNode(t2);
678         Node nextnode = noeud.getNextSibling();
679         JaxeElement parent = getParent();
680         if (nextnode == null)
681             parent.noeud.appendChild(textnode2);
682         else
683             parent.noeud.insertBefore(textnode2, nextnode);
684         JETexte je2 = new JETexte(doc);
685         je2.noeud = textnode2;
686         je2.doc = parent.doc;
687         try {
688             je2.debut = doc.createPosition(pos.getOffset());
689             je2.fin = fin;
690             fin = doc.createPosition(pos.getOffset()-1);
691         } catch (BadLocationException ex) {
692             System.err.println("BadLocationException: " + ex.getMessage());
693         }
694         doc.dom2JaxeElement.put(je2.noeud, je2);
695         return(je2);
696     }
697     
698     /**
699      * fusionne cet élément avec celui donné, dans le DOM (aucun changement du texte)
700      */
701     public void fusionner(JaxeElement el) {
702         if (!(this instanceof JETexte && el instanceof JETexte))
703             return;
704         if (noeud.getNextSibling() == el.noeud) {
705             String t = el.noeud.getNodeValue();
706             noeud.setNodeValue(noeud.getNodeValue() + t);
707             fin = el.fin;
708             el.getParent().supprimerEnfantDOM(el);
709         } else if (el.noeud.getNextSibling() == noeud) {
710             String t = el.noeud.getNodeValue();
711             noeud.setNodeValue(t + noeud.getNodeValue());
712             debut = el.debut;
713             el.getParent().supprimerEnfantDOM(el);
714         }
715     }
716     
717     /**
718      * regroupe les JETexte dans les enfants
719      */
720     public void regrouperTextes() {
721         for (Node n=noeud.getFirstChild(); n != null; n=n.getNextSibling()) {
722             while (n.getNodeType() == Node.TEXT_NODE && n.getNextSibling() != null &&
723                 n.getNextSibling().getNodeType() == Node.TEXT_NODE)  {
724                 JaxeElement je1 = doc.getElementForNode(n);
725                 JaxeElement je2 = doc.getElementForNode(n.getNextSibling());
726                 je1.fusionner(je2);
727             }
728         }
729     }
730     
731     public void setEffacementAutorise(boolean autorise) {
732         effacementAutorise = autorise;
733     }
734     
735     public boolean getEffacementAutorise() {
736         return(effacementAutorise);
737     }
738     
739     public void setEditionAutorisee(boolean autorise) {
740         editionAutorisee = autorise;
741     }
742     
743     public boolean getEditionAutorisee() {
744         return(editionAutorisee);
745     }
746     
747     /**
748      * Sélection de la zone de texte où se trouve cet élément
749      */
750     public void selection(boolean select) {
751         for (int i=0; i<jcomps.size(); i++) {
752             Object comp = jcomps.get(i);
753             if (comp instanceof MonBouton)
754                 ((MonBouton)comp).selection(select);
755         }
756         for (Node n=noeud.getFirstChild(); n != null; n=n.getNextSibling()) {
757             JaxeElement je = doc.getElementForNode(n);
758             if (je != null)
759                 je.selection(select);
760         }
761     }
762 
763     /**
764      * MouseListener pour MonBouton: positionner le curseur à droite ou à gauche quand on clique sur un bord
765      */
766     public class MyMouseListener extends MouseAdapter {
767         JaxeElement jei;
768         JFrame jframe;
769         public MyMouseListener(JaxeElement obj, JFrame jframe) {
770             super();
771             jei = obj;
772             this.jframe = jframe;
773         }
774         public void mouseClicked(MouseEvent e) {
775             if (doc.textPane.isEditable() && jei.getEditionAutorisee()) {
776                 jei.afficherDialogue(jframe);
777             }
778         }
779     }
780 
781     /**
782      * Bouton représentant le début ou la fin d'un élément dans le texte
783      */
784     public class MonBouton extends JComponent {
785         final Color jauneLeger = new Color(255, 255, 150);
786         final Color rougeFonce = new Color(150, 0, 0);
787         final Color orange = new Color(255, 200, 150);
788         final Color bleuClair = new Color(210, 230, 255);
789         final Color violet = new Color(210, 200, 255);
790         final Color[][] ensembles = {{jauneLeger, rougeFonce, orange},
791                                      {bleuClair, rougeFonce, violet}};
792         JLabel label;
793         boolean valide = true;
794         boolean selectionne = false;
795         int noens = 0;
796         boolean division;
797         
798         public MonBouton(String texte, boolean division) {
799             this.division = division;
800             if (division)
801                 setLayout(new BorderLayout());
802             else
803                 setLayout(new FlowLayout(FlowLayout.CENTER,0,0));
804             label = new JLabel(texte);
805             label.setForeground(getForeground());
806             label.setBackground(getBackground());
807             label.setOpaque(true);
808             label.setBorder(BorderFactory.createRaisedBevelBorder());
809             if (division)
810                 add(label, BorderLayout.CENTER);
811             else
812                 add(label);
813             setBorder(BorderFactory.createEmptyBorder(0,2,0,2));
814             label.addMouseListener(new MyMouseListener(JaxeElement.this, doc.textPane.jframe));
815         }
816         public void setText(String texte) {
817             label.setText(texte);
818         }
819         public void setValidite(boolean valide) {
820             this.valide = valide;
821             label.setBackground(getBackground());
822         }
823         public Color getBackground() {
824             if (selectionne)
825                 return(ensembles[noens][1]);
826             else if (valide)
827                 return(ensembles[noens][0]);
828             else
829                 return(ensembles[noens][2]);
830         }
831         public Color getForeground() {
832             if (selectionne)
833                 return(ensembles[noens][0]);
834             else
835                 return(ensembles[noens][1]);
836         }
837         public Dimension getPreferredSize() {
838             if (division)
839                 return(super.getPreferredSize());
840             Dimension d = label.getMinimumSize();
841             d.width += 4;
842             return(d);
843         }
844         public Dimension getMaximumSize() {
845             if (division)
846                 return(super.getMaximumSize());
847             return(getPreferredSize());
848         }
849         public Dimension getMinimumSize() {
850             if (division)
851                 return(super.getMinimumSize());
852             return(getPreferredSize());
853         }
854         public void selection(boolean select) {
855             selectionne = select;
856             label.setForeground(getForeground());
857             label.setBackground(getBackground());
858         }
859         public void setEnsembleCouleurs(int noens) {
860             this.noens = noens - (noens / ensembles.length) * ensembles.length;
861             label.setForeground(getForeground());
862             label.setBackground(getBackground());
863         }
864     }
865 
866     protected String getString(String key) {
867         return(JaxeResourceBundle.getRB().getString(key));
868     }
869     
870     public void changerStyle(String style, int offset, int longueur) {
871         if (style != null) {
872             Style s = doc.textPane.addStyle(null, null);
873             if (style.equals(kExposant))
874                 StyleConstants.setSuperscript(s, true);
875             else if (style.equals(kIndice))
876                 StyleConstants.setSubscript(s, true);
877             else if (style.equals(kItalique))
878                 StyleConstants.setItalic(s, true);
879             else if (style.equals(kGras))
880                 StyleConstants.setBold(s, true);
881             else if (style.equals(kSouligne))
882                 StyleConstants.setUnderline(s, true);
883             else
884                 s = null;
885             if (s != null)
886                 doc.setCharacterAttributes(offset, longueur, s, false);
887         }
888     }
889     
890     public SimpleAttributeSet attStyle(SimpleAttributeSet attorig) {
891         SimpleAttributeSet att;
892         if (attorig == null)
893             att = new SimpleAttributeSet();
894         else
895             att = attorig;
896         Element el;
897         if (noeud.getNodeType() == Node.TEXT_NODE)
898             el = (Element)getParent().noeud;
899         else
900             el = (Element)noeud;
901         Element defbalise = null;
902         if (doc.cfg != null)
903             defbalise = doc.cfg.getBaliseDef(el.getTagName());
904         if (defbalise == null)
905             return(att);
906         String style = doc.cfg.getParamFromDefinition(defbalise, "style", null);
907         if (style != null) {
908             if (style.equals(kExposant))
909                 StyleConstants.setSuperscript(att, true);
910             else if (style.equals(kIndice))
911                 StyleConstants.setSubscript(att, true);
912             else if (style.equals(kItalique))
913                 StyleConstants.setItalic(att, true);
914             else if (style.equals(kGras))
915                 StyleConstants.setBold(att, true);
916             else if (style.equals(kSouligne))
917                 StyleConstants.setUnderline(att, true);
918         }
919         if (!att.isDefined(StyleConstants.FontFamily)) {
920             String police = doc.cfg.getParamFromDefinition(defbalise, "police", null);
921             if (police != null)
922                 StyleConstants.setFontFamily(att, police);
923         }
924         if (!att.isDefined(StyleConstants.FontSize)) {
925             String staille = doc.cfg.getParamFromDefinition(defbalise, "taille", null);
926             if (staille != null) {
927                 try {
928                     int taille = Integer.parseInt(staille);
929                     StyleConstants.setFontSize(att, taille);
930                 } catch (NumberFormatException ex) {
931                     System.err.println(ex.getClass().getName() + ": " + ex.getMessage());
932                 }
933             }
934         }
935         JaxeElement jp = getParent();
936         if (jp != null)
937             return(jp.attStyle(att));
938         else
939             return(att);
940     }
941 }