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

Quick Search    Search Deep

Source code: org/gendiapo/editor/GenericGenDiapoEditPanel.java


1   
2   package org.gendiapo.editor;
3    
4    
5   import javax.swing.*;
6   import javax.swing.text.*;
7   import javax.swing.border.*;
8   
9   import java.awt.*; 
10  import java.awt.event.*;
11  
12  import java.util.*;
13  import java.util.Dictionary.*;
14  
15  import matthew.awt.StrutLayout;
16  import java.text.MessageFormat;
17  import java.beans.*;
18  
19  import org.merlotxml.merlot.*;
20  import org.merlotxml.merlot.plugin.*;
21  import org.merlotxml.merlot.plugin.dtd.*;
22  import org.merlotxml.util.xml.*;
23  
24  import org.gendiapo.editor.*;
25  
26  import org.w3c.dom.*; 
27  
28  
29  /*
30   * Gestion des onglets pour un element de l'arbre XML
31   */
32  public class GenericGenDiapoEditPanel extends GenericDOMEditPanel implements GenDiapoEditPanel, MerlotNodeListener, Comparator
33  
34  {
35      // id onglet par defaut 
36      private static final String ID_DEF = "def";
37      
38      // nom onglet par defaut 
39      private static final String ONG_NAME = "Attributs";
40      
41      // table de panel avec reference en cle
42      protected Hashtable _onglet;
43      
44      // table contenant le dernier élément ajouté dans chaque onglet
45      protected Hashtable _last;
46      
47      // table contenant boolean vrai si element a ajouter au panel est le premier
48      protected Hashtable _first;
49      
50      // onglet contenant les attributs
51      protected JTabbedPane _attributs;  
52      
53      // Vecteur contenant les references des panels vides de l'onglet
54      protected Vector _disabledPanel;
55      
56      // Indique si le noeud vient d'etre effacer
57      protected boolean _hasBeenDeleted;       
58      
59      /**
60       * Constructeur
61       */
62      public GenericGenDiapoEditPanel(MerlotDOMNode node)
63      {
64    super(node);
65    node.addMerlotNodeListener(this);
66    _hasBeenDeleted = false;
67      }
68  
69      protected void buildPanel()
70      {
71    init();
72    setupReadonlyTable();
73    setupHideTable();
74    
75    _vetoListeners = new Vector();
76    
77    initPanelLayout();
78    setupPanel();
79    addVetoableChangeListener(new StandardAttributeChecker());
80      }
81      
82      
83      //
84      public void nodeInserted(MerlotDOMNode parent, int[] indices,
85             MerlotDOMNode[] children) {
86      }
87      
88      public void nodeRemoved(MerlotDOMNode parent, int[] indices,
89            MerlotDOMNode[] children) {
90      }
91      
92      public void nodeDeleted(MerlotDOMNode node) {
93    _hasBeenDeleted = true;
94      }
95      
96      
97      public void nodeChanged(MerlotDOMNode parent, int[] indices,
98            MerlotDOMNode[] children) {
99      }    
100     
101     //
102     
103     /*
104      * Renvoie onglet contenant les attributs
105      */
106     public JTabbedPane getOngletAttributs(){
107   return _attributs;
108     } 
109     
110     
111     /* 
112      * Creation d'un panel pour l'onglet
113      * @param id : reference du panel dans table d'onglet
114      */  
115     public JScrollPane createTab(String id)    
116     {      
117   // Un onglet            
118   JPanel temp = new JPanel();
119       temp.setMinimumSize(new Dimension(4,4));
120   
121   StrutLayout slay = new StrutLayout();
122   slay.setDefaultStrutLength(10);      
123   temp.setLayout(slay);
124       
125   JLabel iconLabel = new JLabel(_node.getIcon());
126   
127   //Mise à jour _last avec dernier element ajoute pour panel de ref id
128   _last.put(id, iconLabel);
129   
130   temp.add(iconLabel);    
131   
132   //aucun element ajoute au panel
133   _first.put(id, Boolean.TRUE);  
134   
135   //ajout Panel dans table onglet avec indice : string id
136   _onglet.put(id, temp);
137   
138   // ajout reference panel dans _disabledPanel (panel vide par defaut)
139   _disabledPanel.addElement(id);
140   
141   // wrap a ScrollPane around it
142   ScrollablePanel scrollPanel = new ScrollablePanel(true,false);
143   StrutLayout lay = new StrutLayout();
144   scrollPanel.setLayout(lay);
145   scrollPanel.add(temp);
146   lay.setSprings(temp, StrutLayout.SPRING_BOTH);
147   scrollPanel.setMinimumSize(new Dimension(4,4));
148   scrollPanel.setBorder(new EmptyBorder(0,0,0,5));
149   
150   JScrollPane sp = new JScrollPane(scrollPanel,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
151            JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
152   
153   sp.setMinimumSize(new Dimension(4,4));
154   sp.getViewport().setMinimumSize(new Dimension(4,4));
155   
156   // met en propriete identifiant du srollpane identifiant id du panel      
157   sp.putClientProperty("identifiant", id);
158   
159   //return JScrollPane
160   return sp;              
161   
162     }
163     
164     
165     /*
166      * Initialisation des 3 tables : onglet, dernier element et premier element
167      */
168     protected void initTable()
169     {
170   // init _onglet et _last et _first
171   _onglet = new Hashtable();
172   _last   = new Hashtable();
173   _first   = new Hashtable();
174   
175   // init _disabledPanel
176   _disabledPanel = new Vector();
177   
178     }
179     
180     
181     /*
182      * Initialisation physique onglet associé a element de l'arbre
183      */
184     public JTabbedPane initOnglet()  
185     {
186   //init onglet
187   JTabbedPane ong = new JTabbedPane();
188   
189   //ajoute un onglet
190   ong.addTab(ONG_NAME,createTab(ID_DEF));  
191   
192   return ong;  
193   
194     }    
195     
196     
197     /* 
198      * Surcharge de la méthode d'initialisation du panel de gauche
199      */
200     protected void initPanelLayout()
201     {    
202   // init du panel global
203   _attributePanel = new JPanel(); 
204   _attributePanel.setMinimumSize(new Dimension(4,4));
205   
206   // layout _attributePanel
207   StrutLayout slay = new StrutLayout();
208   slay.setDefaultStrutLength(10);                   
209   _attributePanel.setLayout(slay);      
210   
211   // init tables
212   this.initTable();
213   
214   // onglet    
215   _attributs = initOnglet();
216   _attributePanel.add(_attributs);      
217   slay.setSprings(_attributs, StrutLayout.SPRING_BOTH);  
218   
219   
220   StrutLayout lay = new StrutLayout();
221   this.setLayout(lay);
222   this.add(_attributePanel);
223   lay.setSprings(_attributePanel, StrutLayout.SPRING_BOTH);
224   
225   
226     }
227     
228     /*
229      * Surcharge methode
230      * Grise les panels de _attributs contenant aucun attribut
231      */
232     protected void setupPanel() 
233     {
234   MerlotDebug.msg("SetupPanel");
235   
236   JComponent prev = null;
237   boolean newsubtext = false;
238         
239   DTDAttribute a;
240         
241   // get all the attributes and create a set of text fields,
242   // and labels
243   Enumeration e = _node.getDTDAttributes();
244   if (e != null) {
245       //  MerlotDebug.msg("Got attributes");
246       
247       int i = 0;
248             TreeSet attributes = new TreeSet(this);
249       
250       while (e.hasMoreElements()) {
251     a = (DTDAttribute)e.nextElement();
252     _dtd_attributes.put(a.getName(),a);
253                 attributes.add(a);
254     i++;
255       }
256       
257       i = 0;            
258             Iterator it = attributes.iterator();
259             while (it.hasNext()) {
260                 a = (DTDAttribute) it.next();
261                 if (!suppressAttribute(a)) {
262                     addAttribute(a);
263                     i++;
264                 }
265                 //  MerlotDebug.msg("Added "+c+" to panel");
266             }
267   }    
268   
269   // see if this node has a #text node possible under it
270   MerlotDOMNode[] children = _node.getChildNodes();
271   for (int i=0; i < children.length; i++) {
272       if (children[i] instanceof MerlotDOMText) {
273     MerlotDOMText textNode = (MerlotDOMText)children[i];
274     //  System.out.println("child["+i+"] = "+children[i]+" nodeValue='"+textNode.getText()+"'");
275     if (textNode.isVisible()) {
276         _subtext = textNode;
277         break;
278     }
279       }
280   }
281   // see if #text is a posibility
282   if (_subtext == null) {
283       Enumeration en = _node.getAppendableElements();
284       DTDElement el;
285       String nm;
286       
287       while (en != null && en.hasMoreElements()) {
288     el = (DTDElement)en.nextElement();
289     if (el != null) {
290         nm = el.getName();
291         if (nm != null && nm.equals(DTDConstants.PCDATA_KEY)) {
292       newsubtext = true;
293       break;
294         }
295     }
296       }
297   }
298   
299   // grise tous les panels de _attributs qui ne contienne pas d'attributs
300   this.disabledPanel();
301   
302     }   
303     
304     protected int compareAttribute(DTDAttribute a, DTDAttribute b) {
305         String aName = a.getName();
306         String bName = b.getName();
307         int aType = a.getDefaultType();
308         int bType = b.getDefaultType();
309         if (aType == bType) {            
310             return aName.compareTo(bName);
311         } else {
312             return bType - aType;
313         }
314     }
315 
316     public int compare(Object obj, Object obj1) {
317         return compareAttribute((DTDAttribute) obj, (DTDAttribute) obj1);
318     }
319     
320     public boolean equals(Object obj) {
321         return this == obj;
322     }        
323     
324     /*
325      * Renvoie un onglet ou les panels qui ne contiennent pas d'elements sont grisés
326      */
327     protected void disabledPanel() 
328     {
329   // faux car grise
330   Boolean grayed = Boolean.FALSE;
331   
332   // recherche dans 
333   for (int i = 0; i < _disabledPanel.size(); i++) {
334       
335       // recuperation du scrollPane
336       // vrai si panel trouve dans onglet
337       Boolean find = Boolean.FALSE;
338       // index du panel dans l'onglet
339       int j = 0;
340       
341       while ( (! find.booleanValue() ) & ( j < _attributs.getTabCount() ) ) {
342     
343     JScrollPane scroll = (JScrollPane)_attributs.getComponentAt(j);
344     
345     String ident = (String)scroll.getClientProperty("identifiant");
346     
347     if ( ident.equals((String)_disabledPanel.get(i)) ) {
348         find = Boolean.TRUE;
349         _attributs.setEnabledAt(j,grayed.booleanValue());    
350     } else {
351         j += 1;
352     }
353     
354       } // end while
355       
356       
357   } // end for
358   
359   
360     }     
361     
362     /*
363      * Renvoie la reference de l'onglet pour un attribut donné 
364      * ID_DEF : reference par defaut 
365      */
366     public String getTab(DTDAttribute a) 
367     {
368   return ID_DEF;
369     }
370     
371    
372     /* 
373      * Surcharge addAttribute de GenericDOMEditPanel 
374      * Faire intervenir le numero de l'onglet 
375      */
376     protected void addAttribute(DTDAttribute a) 
377     {
378   if (a != null) {
379       MerlotDOMEditor editor = _node.getEditor();
380       String label = a.getName();
381       if (editor instanceof GenDiapoEditor) {
382     label = ((GenDiapoEditor) editor).getUserName(_node, a);
383       }
384       if (!label.equals("")) {
385     label += ":";
386       }
387       JLabel l = new JLabel(label,JLabel.TRAILING);
388       if ((a.getDefaultType() == DTDAttribute.REQUIRED) && (!label.equals(""))) {
389     Icon reqIcon = getRequiredAttrIcon();
390     if (reqIcon != null) {
391         l.setIcon(reqIcon);
392     }
393       }
394       
395       JComponent c = getEditComponent(a);
396       
397       if (c == null) {
398          return;
399       }
400       
401       _attrComponents.put(a.getName(),c);
402       
403       String s = _node.getNodeName() + "." + a.getName();
404       String t = (String)_readonlyAttrs.get(s);
405       if (t != null) {
406     // System.out.println("disabling component: "+c);
407     
408     if (c instanceof JTextComponent) {
409         ((JTextComponent)c).setEditable(false);
410     }
411     c.setEnabled(false);
412      }
413       
414       addAttributeComponent(l,c,ALIGN_MIDDLE,getTab(a));
415       
416        }
417   
418     }
419     
420     
421     /* 
422      * Controle de la descendence
423      * Renvoie tout appel de la fonction vers nouvelle fonction
424      */
425     protected void addAttributeComponent(JLabel l, JComponent c, int align) {
426   addAttributeComponent(l, c, align, ID_DEF);
427     }
428     
429     
430     /*
431      * Surcharge fonction GenericDOMEditPanel
432      * Ajout du param ref donnant la reference de l'onglet
433      */
434     protected void addAttributeComponent(JLabel l, JComponent c, int align, String ref) 
435     {
436         addAttributeComponentTab(l,c,align,ref);    
437     }
438     
439     
440     /*
441      * Insere le composant dans l'onglet donné par la référence 
442      */
443     protected void addAttributeComponentTab(JLabel l, JComponent c, int align, String ref)
444     {
445   JPanel tabPanel = null; 
446   
447   // recuperation du panel ou le composant doit etre ajoute 
448   tabPanel = (JPanel)_onglet.get(ref);  
449   
450   // verif panel non nul
451   if (tabPanel == null) {
452       return;
453   }  
454   
455   // recuperation dernier composant ajoute a ref
456   JComponent prec = (JComponent)_last.get(ref); 
457   //verif non nul
458   if (prec == null) {
459       return;
460   }
461   
462   // verification si element est le premier du panel ou non
463   boolean prem = ((Boolean)_first.get(ref)).booleanValue();
464   
465   StrutLayout.StrutConstraint strut;
466         StrutLayout.StrutConstraint strut2;
467   
468   // premier composant                
469   if (prem) {
470       
471       strut = new StrutLayout.StrutConstraint(prec,StrutLayout.MID_RIGHT,StrutLayout.MID_LEFT,
472                                                     StrutLayout.SOUTH_EAST,20);
473       
474             strut2 = new StrutLayout.StrutConstraint(l,StrutLayout.MID_RIGHT, StrutLayout.MID_LEFT,
475                                                      StrutLayout.EAST);      
476       
477             tabPanel.add(l,strut);
478             tabPanel.add(c,strut2);
479       
480             _first_field = c;
481       
482       _first.put(ref, Boolean.FALSE);  
483       
484         } else {
485       
486       strut2 = new StrutLayout.StrutConstraint(prec,StrutLayout.BOTTOM_LEFT,StrutLayout.TOP_LEFT,
487                                                      StrutLayout.SOUTH);
488       
489             switch (align) {
490             case ALIGN_TOP: // top
491                 strut = new StrutLayout.StrutConstraint(c,StrutLayout.TOP_LEFT, StrutLayout.TOP_RIGHT,
492               StrutLayout.WEST);
493                 break;
494             default:
495             case ALIGN_MIDDLE: // middle
496                 strut = new StrutLayout.StrutConstraint(c,StrutLayout.MID_LEFT, StrutLayout.MID_RIGHT,
497                                                         StrutLayout.WEST);
498                 break;
499             case ALIGN_BOTTOM: // bot
500                 strut = new StrutLayout.StrutConstraint(c,StrutLayout.BOTTOM_LEFT, StrutLayout.BOTTOM_RIGHT,
501                                                         StrutLayout.WEST);
502                 break;
503             }
504             
505       tabPanel.add(c,strut2);
506             tabPanel.add(l,strut);
507           
508         }
509   
510   // JTextField
511         if (c instanceof JTextField) {
512             ((StrutLayout)tabPanel.getLayout()).setSprings(c,StrutLayout.SPRING_HORIZ);
513         }
514   
515   // JScrollPane
516         //if (c instanceof JScrollPane) {
517   if (c instanceof JPanel) {
518             ((StrutLayout)tabPanel.getLayout()).setSprings(c,StrutLayout.SPRING_BOTH);
519         }
520   
521   //JComboBox
522   if (c instanceof JComboBox) {
523             ((StrutLayout)tabPanel.getLayout()).setSprings(c,StrutLayout.SPRING_HORIZ);
524         }
525         
526   //maj dernier composant ajoute              
527         _last.put(ref,c);  
528   
529   
530   // enleve le panel de reference ref de _disabledPanel
531   _disabledPanel.remove(ref);    
532   
533     }
534     
535     /**
536      * Surcharge methode 
537      * Vrai si attribut ne doit pas être affiché dans les onglets
538      */
539     protected boolean suppressAttribute(DTDAttribute a) 
540     {
541   
542         // verifie que attribut pas supprime dans methode pere  
543   boolean suppr = super.suppressAttribute(a);
544   
545   // s'il est présent d'après la méthode père, test s'il est dans vue stylee (si c'est le cas il est supprimé)                
546         GenDiapoEditor edit = (GenDiapoEditor) _node.getEditor();
547         java.util.List attributesInStyledView = edit.attributesInStyledView(_node);                         
548   if ((! suppr) && (attributesInStyledView != null)) {                        
549             suppr = attributesInStyledView.contains(a.getName());
550   }        
551   
552   return suppr;
553   
554     }   
555     
556     
557     
558     /**
559      * Create a component based on the attribute type, and get the default from
560      * the node, or if the node doesn't have it set, get the default value from
561      * the attribute definition itself
562      */
563     protected JComponent getEditComponent(DTDAttribute attr) 
564     {
565   MerlotDebug.msg("getEditComponent("+attr+")");
566   
567   int t = attr.getType();
568   JComponent ret = null;
569   String value = null;
570   Attr a = null;
571   
572   if (_node_attributes != null) {
573       a = (Attr)_node_attributes.getNamedItem(attr.getName());
574   }
575   
576   //System.out.println("a " + a + " : " + a.getValue());
577   
578   if (a != null) {
579       value = a.getValue();
580   }
581   
582   switch (t) {
583       
584   case DTDConstants.NMTOKEN:
585       
586   case DTDConstants.CDATA:
587       ret = new JTextField();
588       if (value != null) {
589     ((JTextField)ret).setText(value);
590       }
591       else {
592     value = attr.getDefaultValue();
593     if (value != null) {
594         ((JTextField)ret).setText(value);
595     }
596       }
597       break;
598       
599   case DTDConstants.ID:
600       ret = getIdComponent(_node,attr.getName());
601       break;
602       
603   case DTDConstants.IDREF:
604       ret = getIdRefComponent(_node,attr.getName());
605       break;
606       
607   case DTDConstants.TOKEN_GROUP:
608       Enumeration e = attr.getTokens();
609       
610       boolean checkbox = true;
611       
612       if (e != null) {
613     Vector v = new Vector();
614     if (attr.getDefaultValue() == null) {
615         v.addElement("");
616     }
617     while (e.hasMoreElements()) {
618         MerlotDebug.msg("v = " + v + " e = " + e);
619         Object o = e.nextElement();
620         String s = o.toString();
621         
622         checkbox = checkbox && (s.equals("true") || s.equals("false"));
623                 
624                     v.addElement(new TokenValue(o, getUserName(attr, o)));
625     }
626     
627     if (v.size() == 2 && checkbox) {
628         ret = new JCheckBox();
629         ((JCheckBox) ret).setSelected(value != null && value.equals("true"));        
630     } else {    
631                     ret = new JComboBox(v);
632                     ((JComboBox)ret).setEditable(false);
633                     int i = getIndexInVector(v,value);
634                     
635                     if (i < 0) {
636                         i = getIndexInVector(v,attr.getDefaultValue());
637                     }
638                     
639                     if (i >= 0) {
640                         ((JComboBox)ret).setSelectedIndex(i);
641                     }                
642                 }
643     
644       }
645       break;
646       
647   case DTDConstants.IDREFS:
648       ret = getIdRefsComponent(_node,attr.getName());      
649       break;  
650       
651   default:
652       JLabel l = new JLabel(MerlotResource.getString(ERR,"xml.attr.type.unknown"));
653       ret = l;
654       break;
655       
656   }
657   
658   return ret;
659     }    
660     
661     /*
662      * Returns a panel aimed at editing the IDREFS attribute from a DOM node
663      * targetNode : noeud sélectionné
664      * targetAttrName : Nom de l'attribut
665      */
666     protected JComponent getIdRefsComponent (MerlotDOMNode targetNode, String targetAttrName)
667     {
668   
669   // recuperation tableau categories du document    
670   CategoryObject[] tmp = getCategories(targetNode.getMerlotDOMDocument(), targetNode, targetAttrName);  
671   
672   // Panel contenant la liste des checkbox      
673   JPanel panel = new JPanel();
674   
675   // met en propriete de panel listeCateg
676   // but : recuperer identifiant categories pour la sauvegarde
677   panel.putClientProperty("listeCateg", tmp);
678   
679   
680   // valeur de l'attribut targetAttrName
681   String value = null;
682   
683   // recuperation de la chaine associee à l'attribut targetAttrName  
684   Attr targetAttr = (Attr)targetNode.getAttributes().getNamedItem(targetAttrName);
685   if (targetAttr != null) {
686       value = targetAttr.getValue();
687   }      
688   
689   if (value != null) {
690       
691       String temp = "";
692       
693       for (int i = 0; i < value.length(); i++) {
694     
695     if ( value.charAt(i) == ' ') {
696         
697         // recup objet CategoryObject qui a temp comme identifiant
698         CategoryObject cat = getCategObject(temp,tmp);
699         
700         // met booleen a true si identifiant existe toujours
701         if ( cat != null ) { 
702       cat._boolCategory = Boolean.TRUE;
703         }
704         
705         temp = "";
706         
707     }else {
708         //caractere differrent espace 
709         temp += value.charAt(i);
710     }     
711       }
712       
713       // traitement dernier element 
714       // recup objet CategoryObject qui a temp comme identifiant
715       CategoryObject cat = getCategObject(temp,tmp);
716       
717       // met booleen a true si identifiant existe toujours
718       if ( cat != null ) { 
719     cat._boolCategory = Boolean.TRUE;
720       }
721       
722   }
723   
724   // init GridLayout avec taille hashtable
725   GridLayout gridLayout = new GridLayout(tmp.length,1);
726   panel.setLayout(gridLayout);
727   
728   
729   // init checkbox avec nom des categories    
730   for (int i = 0; i < tmp.length; i++) {
731       
732       // creation checkbox avec nom categorie et coché si booléen vrai
733       JCheckBox c = new JCheckBox(tmp[i]._nameCategory, tmp[i]._boolCategory == Boolean.TRUE);
734       
735       // maj proprietes du checkBox : tableau de booléen et son rang dans le tableau
736       c.putClientProperty("listeCateg", tmp);
737       c.putClientProperty("index", new Integer(i));
738       
739       // met listener
740       CheckBoxListener myListener = new CheckBoxListener();
741       c.addItemListener(myListener);
742       
743       // met le dernier CheckBox en propriete du panel 
744       // But : recuperer le tableau de booleen pour sauvegarde
745       panel.putClientProperty("comp", c);        
746       
747       // ajoute au panel
748       panel.add(c);
749       
750       
751   } // end for
752   
753   return panel;  
754   
755     }  
756     
757     
758     /**
759      * Recherche categories
760      * @param doc noeud de depart
761      * @param targetNode
762      * @param targetAttrName attribut pour lequel on recherche les choix d'id
763      */
764     protected CategoryObject[] getCategories(MerlotDOMDocument doc, MerlotDOMNode targetNode, String targetAttrName)
765     {
766   Vector choices = new Vector();
767   Hashtable idAttrs = getIdManager().getIDAttrs(targetNode, targetAttrName);
768   if (idAttrs != null) {
769       Enumeration e = idAttrs.keys();
770       int i = 0;
771       while (e.hasMoreElements()) {
772     Attr attr = (Attr)e.nextElement();
773     MerlotDOMNode node = (MerlotDOMNode)idAttrs.get(attr);
774     String id = getIdForNode( node );
775     if (IdAttributesAreCompatible(targetNode, targetAttrName, node, attr.getName())) {
776         CategoryObject idObject = new CategoryObject(id,   
777                   getDisplayTextForAttribute(targetNode, 
778                            targetAttrName, 
779                            node, 
780                            attr.getName()));
781         choices.add(idObject);
782     }
783       }
784   }
785   return (CategoryObject[]) choices.toArray(new CategoryObject[choices.size()]);
786     } 
787     
788     
789     /*
790      * renvoie l'index de la categorie 
791      * id : identifiant de la catgeorie
792      * tab : tablo d'objet CategoryObject
793      */
794     protected CategoryObject getCategObject(String id , CategoryObject[] tab)
795     {
796   CategoryObject obj = null;
797   int i = 0;
798   Boolean trouve = Boolean.FALSE;
799   
800   // non trouve et non fin de tableau
801   while ( !(trouve.booleanValue()) & (i < tab.length) ) {
802       
803       CategoryObject cat = tab[i];
804       // test nom de catgeorie
805       if (cat._idCategory.equals(id)) {
806     obj = cat;
807     trouve = Boolean.TRUE;
808       } else {
809     i += 1;
810       }
811       
812   }
813   
814   if (trouve.booleanValue()) {
815       return obj;
816   } else {
817       return null;
818   }
819   
820     }    
821 
822     
823     /**
824      * Surcharge methode pour cas des categories
825      */
826     protected void save(HashMap attributes) 
827   throws PropertyVetoException
828     {
829   if (_hasBeenDeleted) {
830       return;
831   }
832   
833   if (_text != null) {
834       if (_text.getText().trim().equals("")) {
835     if (_subtext != null) {
836         // it's empty and they didn't create it or edit it
837         // manually... remove it
838         _node.removeChild(_subtext);
839     }
840       } else {
841     if (_subtext == null) {
842         // create a new TextNode
843         MerlotDOMNode nd = _node.newChild(DTDConstants.PCDATA_KEY);
844         if (nd instanceof MerlotDOMText) {
845       _subtext = (MerlotDOMText)nd;
846         }
847     }
848     if (_subtext != null) {
849         _subtext.setText(_text.getText());
850     }
851       }
852   }
853   
854   // put together a hashtable of attributes to pass back to the node
855   Enumeration e = _attrComponents.keys();
856   while (e.hasMoreElements()) {
857       String key = (String)e.nextElement();
858       DTDAttribute dtdAttr = (DTDAttribute)_dtd_attributes.get(key);
859       Node oldnode = _node_attributes.getNamedItem(key);
860       String oldval;
861       if (oldnode != null) {
862     oldval = oldnode.getNodeValue();
863       } else {
864     oldval = "";
865       }
866       JComponent c = (JComponent)_attrComponents.get(key);
867       
868       String newval = null;
869       if (c instanceof JTextField) {
870     
871     newval = ((JTextField)c).getText();
872     
873       } else if (c instanceof JComboBox) {
874 
875     Object item = ((JComboBox)c).getSelectedItem();
876     if (item != null) {
877                     if (item instanceof TokenValue) {
878                         newval = ((TokenValue)item).getObject().toString().trim();
879                     } else {
880                         newval = item.toString().trim();
881                     }
882     }
883     
884       } else if (c instanceof JCheckBox) {
885     newval = ((JCheckBox) c).isSelected() ? "true" : "false";
886     
887       } else if ((c instanceof JPanel) && (c.getClientProperty("comp") instanceof JCheckBox)) {
888     
889     // recup checkbox et liste categories
890     JCheckBox box    = (JCheckBox)c.getClientProperty("comp"); 
891     
892     // au moins un checkbox
893     CategoryObject[] liste = (CategoryObject[])box.getClientProperty("listeCateg");
894     
895     // recherche les categories sauvees
896     for (int i = 0; i < liste.length; i++) {
897         
898         if ( liste[i]._boolCategory.toString().equals("true") ) {      
899       if ( newval == null ) {        
900           newval = "";                             // init newval
901       } else {        
902           newval = newval + " ";                   // categs separes par " " 
903       }       
904       newval = newval + liste[i]._idCategory;      // ajoute categ   
905         }       
906     }
907         
908       } else {
909     // nothing to do now
910     MerlotDebug.msg("Unknown editing component in GenericDOMEditPanel.save: "+c);
911     if (attributes.containsKey(key)) {
912         newval = (String)attributes.get(key);
913     }
914       }
915 
916       if (newval != null && newval.trim().equals("")) {
917     newval = null;
918       }
919 
920       if (newval == null && dtdAttr != null && dtdAttr.getDefaultType() == DTDAttribute.REQUIRED) {
921     String err[] = new String[2];
922     err[0] = _node.getNodeName();
923     err[1] = key;
924     throw new PropertyVetoException(MessageFormat.format(MerlotResource.getString(ERR,"required.field"),err),new PropertyChangeEvent(_node,key,oldval,newval));
925       }
926       
927       fireVetoableChange(new PropertyChangeEvent(_node,key,oldval,newval));
928       
929       // check if the attribute is already set in the hashtable
930       if (!attributes.containsKey(key)) {
931     attributes.put(key,newval);
932       }
933       
934   }
935   _node.setAttributes(attributes);
936   _node.removeMerlotNodeListener(this);    
937     }
938     
939    
940     /* 
941      * Listens to the check boxes
942      */
943     class CheckBoxListener implements ItemListener {
944   
945         public void itemStateChanged(ItemEvent e) {
946             
947       // recuperation checkbox selectionne
948             Object source = e.getItemSelectable();
949       JCheckBox c = (JCheckBox)source;
950       
951       // init liste categories et index
952       CategoryObject[] liste = null;
953       java.lang.Integer ind = new Integer(-1);
954       
955       // recupere liste categories et index associe au checkbox
956       liste = (CategoryObject[])c.getClientProperty("listeCateg"); 
957       ind = (java.lang.Integer)c.getClientProperty("index"); 
958       
959       // si selectionne, true dans vecteur sinon false
960       if (c.isSelected() ) {
961     liste[ind.intValue()]._boolCategory = Boolean.TRUE; 
962       } else {
963     liste[ind.intValue()]._boolCategory = Boolean.FALSE; 
964       }
965       
966       // maj vecteur associe au CheckBox et scrollPane
967       c.putClientProperty("listeCateg", liste); 
968             
969         }
970     }
971 
972 
973     /**
974      * Checks attributes according to their type. E.g. NMTOKEN is only of the characters specified
975      * by the XML spec
976      */
977     protected  class StandardAttributeChecker implements VetoableChangeListener 
978     {
979   public void vetoableChange(PropertyChangeEvent evt) 
980       throws PropertyVetoException
981   {
982 
983       Object n = evt.getSource();
984       if (!(n instanceof MerlotDOMNode)) {
985     return;
986       }
987       MerlotDOMNode node = (MerlotDOMNode)n;
988       
989       String attributeName = evt.getPropertyName();
990       Object o = evt.getNewValue();
991       String value = "";
992       if (o instanceof String) {
993     value = ((String)o).trim();
994       }
995       
996       
997 // [4]    NameChar    ::=    Letter | Digit | '.' | '-' | '_' | ':' | CombiningChar | Extender 
998 // [5]    Name        ::=    (Letter | '_' | ':') (NameChar)* 
999 // [6]    Names       ::=    Name (S Name)* 
1000// [7]    Nmtoken     ::=    (NameChar)+ 
1001// [8]    Nmtokens    ::=    Nmtoken (S Nmtoken)*
1002
1003
1004
1005      DTDAttribute attribute = (DTDAttribute)_dtd_attributes.get(attributeName);
1006      if (attribute != null) {
1007    int t = attribute.getType();
1008    char invalid = 0;
1009    switch (t) {
1010    case DTDConstants.NMTOKEN:
1011        // inspect the value and make sure it conforms to the restrictions on NMTOKEN's
1012        /*
1013          if (value.length() == 0) {
1014          throw new PropertyVetoException("NMTOKEN's require a value",evt);
1015          }
1016        */
1017        if (value.length() != 0) {
1018      invalid = checkNmtokenChars(value);
1019        }
1020        break;
1021        
1022    case DTDConstants.CDATA:
1023        break;
1024        
1025    case DTDConstants.ID:
1026        break;
1027    case DTDConstants.IDREF:
1028        break;
1029    case DTDConstants.TOKEN_GROUP:
1030        break;
1031        
1032    }
1033    if (invalid != 0) {
1034        String[] err = new String[3];
1035        err[0] = node.getNodeName();
1036        err[1] = attribute.getName();
1037        err[2] = "'" + invalid + "'";
1038      
1039        throw new PropertyVetoException(MessageFormat.format(MerlotResource.getString(ERR,"illegal.value.attr.char"),err),evt);
1040        
1041    }
1042    
1043      }
1044  }
1045    
1046    }
1047
1048    
1049    protected String getUserName(DTDAttribute attr, Object o) {
1050        String value = o.toString();
1051        DTDPluginConfig dpc = _node.getDTDPluginConfig();
1052  if (dpc instanceof GD_DTDPluginConfig) {
1053            value = ((GD_DTDPluginConfig) dpc).getValueName(_node.getNodeName(), attr.getName(), o.toString());
1054        } 
1055        return value;
1056    }
1057    
1058    protected class TokenValue {
1059        Object obj;
1060        String userValue;
1061        
1062        public TokenValue(Object o, String userValue) {
1063            this.obj = o;
1064            this.userValue = userValue;
1065        }
1066        
1067        public Object getObject() {
1068            return obj;
1069        }
1070        
1071        public String toString() {
1072            return userValue;
1073        }
1074        
1075        public boolean equals(Object o) {            
1076            return o.equals(obj);
1077        }
1078    }      
1079        
1080}