Source code: org/gendiapo/editor/document/GenDiapoDocumentFactory.java
1 /*
2 * @(#)GenDiapoDocumentFactory.java 1.000 01/05/30
3 */
4 package org.gendiapo.editor.document;
5
6 import java.lang.reflect.Method;
7
8 import java.awt.*;
9 import java.awt.event.*;
10 import java.io.*;
11 import java.beans.*;
12 import java.util.*;
13
14 import javax.swing.*;
15 import javax.swing.text.*;
16 import javax.swing.text.html.*;
17 import javax.swing.event.*;
18
19 import org.gendiapo.editor.*;
20 import org.gendiapo.editor.document.*;
21
22 import org.merlotxml.merlot.*;
23 import org.merlotxml.util.xml.*;
24
25 public class GenDiapoDocumentFactory {
26
27 static final ArrayList EMPTY = new ArrayList();
28
29 static final Integer IntDummy = new java.lang.Integer(GenDiapoDocument.Dummy);
30 static final Integer IntFragment = new java.lang.Integer(org.w3c.dom.Node.DOCUMENT_FRAGMENT_NODE);
31 static final Integer IntAttribute = new java.lang.Integer(org.w3c.dom.Node.ATTRIBUTE_NODE);
32 static final Integer IntParagraph = new java.lang.Integer(GenDiapoDocument.Paragraph);
33 static final Integer IntText = new java.lang.Integer(GenDiapoDocument.Text);
34 static final Integer IntParagraphCSS = new java.lang.Integer(GenDiapoDocument.ParagraphCSS);
35 static final Integer IntTextCSS = new java.lang.Integer(GenDiapoDocument.TextCSS);
36
37 static final GenDiapoDocument.ElementSpec EndElementSpec = new GenDiapoDocument.ElementSpec(null, GenDiapoDocument.ElementSpec.EndTagType);
38
39 public GenDiapoDocumentFactory() {
40 }
41
42 /*--- affichage des noeuds du document ----*/
43 public static void debugViewChild(String tab, Element element) {
44 if (!element.isLeaf()) {
45 // Child
46 int nb = element.getElementCount();
47 for (int i=0; i<nb; i++) {
48 Element eChild = element.getElement(i);
49 AttributeSet eAttr = eChild.getAttributes();
50 Object oStyle = eAttr.getAttribute(GenDiapoDocument.ATTRIBUT_STYLENAME);
51 String style = "";
52 if (oStyle instanceof String) {
53 style = (String) oStyle;
54 }
55 System.out.println(tab+eChild.getName()+"("+eChild.getStartOffset()+","+eChild.getEndOffset()+") style:"+style);
56 debugViewChild(tab+" ",eChild);
57 }
58 }
59 }
60
61 static java.util.List getAttributesOrder(MerlotDOMNode node) {
62 java.util.List order = EMPTY;
63 MerlotDOMEditor editor = node.getEditor();
64 if (editor instanceof GenDiapoEditor) {
65 if (editor != null) {
66 GenDiapoEditor genDiapoEditor = (GenDiapoEditor) editor;
67 order=genDiapoEditor.attributesInStyledView(node);
68 }
69 }
70 return order;
71 }
72
73 static Map getDTDAttributes(MerlotDOMNode node) {
74 Map attributesMap = new Hashtable();
75
76 Enumeration dtdAttributes = node.getDTDAttributes();
77 if (dtdAttributes != null) {
78 DTDAttribute nodeAttr;
79
80 while (dtdAttributes.hasMoreElements()) {
81 nodeAttr = (DTDAttribute)dtdAttributes.nextElement();
82 attributesMap.put(nodeAttr.getName(), nodeAttr);
83 }
84 }
85
86 return attributesMap;
87 }
88
89 static java.util.List getDTDAttributesInStyledView(MerlotDOMNode node) {
90 java.util.List attributes = new ArrayList();
91
92 // init
93 java.util.List order = getAttributesOrder(node);
94 Map attributesMap = getDTDAttributes(node);
95
96 // fill attributes
97 Iterator i = order.iterator();
98 while (i.hasNext()) {
99 String attributeName = (String) i.next();
100 Object dtdAttribute = attributesMap.get(attributeName);
101 if (dtdAttribute != null) {
102 attributes.add(dtdAttribute);
103 }
104 }
105
106 return attributes;
107 }
108
109 /*
110 * parseStringLF
111 * Ajoute autant de ParagraphElement que de ligne
112 * Suppose que le dernier caractère soit une retour a la ligne
113 */
114 static void parseStringLF(Vector change, String str, Style textStyle) {
115 char[] buf = str.toCharArray();
116 int lastLF = 0;
117 SimpleAttributeSet text_attr, para_attr;
118
119 Object paragraphType, contentType;
120
121 if (textStyle != null) {
122 paragraphType = IntParagraphCSS;
123 contentType = IntTextCSS;
124 } else {
125 paragraphType = IntParagraph;
126 contentType = IntText;
127 }
128
129
130 for (int i=0; i<buf.length; i++) {
131 if (buf[i] == '\n' ) {
132 // start paragraph
133 text_attr= new SimpleAttributeSet();
134 text_attr.addAttribute(GenDiapoDocument.ATTRIBUT_TYPE, paragraphType);
135 if (textStyle != null) {
136 text_attr.addAttributes(textStyle);
137 }
138 change.add(new GenDiapoDocument.ElementSpec(text_attr, GenDiapoDocument.ElementSpec.StartTagType));
139
140 // texte
141 para_attr= new SimpleAttributeSet();
142 para_attr.addAttribute(GenDiapoDocument.ATTRIBUT_TYPE, contentType);
143 change.add(new GenDiapoDocument.ElementSpec(para_attr,
144 GenDiapoDocument.ElementSpec.ContentType,
145 buf,
146 lastLF,
147 i-lastLF+1));
148
149 // end paragraph
150 change.add(EndElementSpec);
151 lastLF = i+1;
152 }
153 }
154 }
155
156 /*
157 * parseString
158 * Ajoute une seul ligne en remplacant tout les retour a ligne par un espace
159 */
160 static void parseString(Vector change, String str, Style textStyle) {
161
162 char[] buf = str.toCharArray();
163 SimpleAttributeSet text_attr, para_attr;
164
165 // remplace tous les '\n' par ' '
166 for(int i=0; i<(buf.length-1); i++) {
167 if (buf[i] == '\n') {
168 buf[i] = ' ';
169 }
170 }
171
172 // start paragraph
173 text_attr= new SimpleAttributeSet();
174 Object paragraphType, contentType;
175 if (textStyle != null) {
176 text_attr.addAttributes(textStyle);
177 paragraphType = IntParagraphCSS;
178 contentType = IntTextCSS;
179 } else {
180 paragraphType = IntParagraph;
181 contentType = IntText;
182 }
183 text_attr.addAttribute(GenDiapoDocument.ATTRIBUT_TYPE, paragraphType);
184 change.add(new GenDiapoDocument.ElementSpec(text_attr, GenDiapoDocument.ElementSpec.StartTagType));
185
186 // texte
187 para_attr= new SimpleAttributeSet();
188 para_attr.addAttribute(GenDiapoDocument.ATTRIBUT_TYPE, contentType);
189 change.add(new GenDiapoDocument.ElementSpec(para_attr,
190 GenDiapoDocument.ElementSpec.ContentType,
191 buf,
192 0,
193 buf.length));
194 // end paragraph
195 change.add(EndElementSpec);
196 }
197
198 static void addPCDataTree(Vector change, Object position) {
199 String text,str;
200 SimpleAttributeSet attr_attr;
201
202 str = "\n";;
203
204 // attribut
205 // xmlNode, MerlotNode herités
206 attr_attr= new SimpleAttributeSet();
207 attr_attr.addAttribute(GenDiapoDocument.ATTRIBUT_TYPE, IntFragment);
208 attr_attr.addAttribute(GenDiapoDocument.ATTRIBUT_MERLOTTEXT, position);
209 change.add(new GenDiapoDocument.ElementSpec(attr_attr, GenDiapoDocument.ElementSpec.StartTagType));
210
211 // Ajout de la chaine de caractère
212 parseStringLF(change, str, null);
213
214 // EndTag
215 change.add(EndElementSpec);
216 }
217
218 static void parsePCDataTree(Vector change, MerlotDOMText node) {
219 String text,str;
220 SimpleAttributeSet attr_attr;
221
222 str = node.getText()+"\n";;
223
224 // attribut
225 // xmlNode, MerlotNode herités
226 attr_attr= new SimpleAttributeSet();
227 attr_attr.addAttribute(GenDiapoDocument.ATTRIBUT_TYPE, IntFragment);
228 attr_attr.addAttribute(GenDiapoDocument.ATTRIBUT_MERLOTTEXT, node);
229 change.add(new GenDiapoDocument.ElementSpec(attr_attr, GenDiapoDocument.ElementSpec.StartTagType));
230
231 // Ajout de la chaine de caractère
232 parseStringLF(change, str, null);
233
234 // EndTag
235 change.add(EndElementSpec);
236 }
237
238
239 static boolean pcDataAllowed(MerlotDOMNode node) {
240 org.w3c.dom.Node xmlNode = node.getRealNode();
241 Enumeration en = node.getAppendableElements();
242 DTDElement el;
243 String nm;
244 String text,str;
245 SimpleAttributeSet attr_attr, text_attr, para_attr;
246
247 while (en != null && en.hasMoreElements()) {
248 el = (DTDElement)en.nextElement();
249 if (el != null) {
250 nm = el.getName();
251 if (nm != null && nm.equals(DTDConstants.PCDATA_KEY)) {
252 return true;
253 }
254 }
255 }
256 return false;
257 }
258
259
260 public static void parseAttributes(Vector change, MerlotDOMNode node, StyleSheet style) {
261 org.w3c.dom.Node xmlNode = node.getRealNode();
262 java.util.List attributes = getDTDAttributesInStyledView(node);
263 Iterator i = attributes.iterator();
264 while (i.hasNext()) {
265 DTDAttribute nodeAttr = (DTDAttribute)i.next();
266
267 // Value
268 String attrValue="";
269 if (xmlNode instanceof org.w3c.dom.Element) {
270 attrValue = ((org.w3c.dom.Element)xmlNode).getAttribute(nodeAttr.getName());
271 }
272 if (attrValue == null) {
273 attrValue = "";
274 }
275 attrValue += "\n";
276
277 // Open AttributeSet
278 // XMLNODE, MERLOTNODE hérités
279 SimpleAttributeSet attr_attr= new SimpleAttributeSet();
280 attr_attr.addAttribute(GenDiapoDocument.ATTRIBUT_DTDATTRIBUTE, nodeAttr);
281 attr_attr.addAttribute(GenDiapoDocument.ATTRIBUT_TYPE, IntAttribute);
282 change.add(new GenDiapoDocument.ElementSpec(attr_attr, GenDiapoDocument.ElementSpec.StartTagType));
283
284 // Add string with style
285 Style textStyle;
286 if (style == null) {
287 textStyle = null;
288 } else {
289 textStyle = getStyleAttribute(style, node, nodeAttr);
290 }
291 parseString(change, attrValue, textStyle);
292
293 // Close AttributeSet
294 change.add(EndElementSpec);
295 }
296 }
297
298 /**
299 * Utilise par parseGlobalElementTree
300 * @return Un ElementSpec de type ElementSpec.ContentType
301 */
302 private static GenDiapoDocument.ElementSpec voidTextElementSpec() {
303 String paraValue="\n";
304 SimpleAttributeSet para_attr = new SimpleAttributeSet();
305 para_attr.addAttribute(GenDiapoDocument.ATTRIBUT_TYPE, IntText);
306 StyleConstants.setFontSize(para_attr, 20);
307 return new GenDiapoDocument.ElementSpec(para_attr,
308 GenDiapoDocument.ElementSpec.ContentType,
309 paraValue.toCharArray(),
310 0,
311 paraValue.length());
312 }
313
314 /**
315 * Ajoute un element (non editable) dans le cas le noeud ne comporte pas d'attribut ou pcdata visible
316 * @param change Vecteur contenant les ElementSpec du document a créer
317 * @param node Noeud a traiter
318 */
319 static void parseGlobalElementTree(Vector change, MerlotDOMNode node) {
320 if (node instanceof MerlotDOMElement) {
321 MerlotDOMEditor editor = node.getEditor();
322 if (editor instanceof GenDiapoEditor) {
323 GenDiapoEditor genDiapoEditor = (GenDiapoEditor) editor;
324 // Ajout le tag global uniquement si l'element est visible par l'utilisateur
325 if (!genDiapoEditor.suppressTag(node.getParentNode(), node.getNodeName())) {
326
327 SimpleAttributeSet attr_attr = new SimpleAttributeSet();
328 attr_attr.addAttribute(GenDiapoDocument.ATTRIBUT_TYPE, IntDummy);
329 change.add(new GenDiapoDocument.ElementSpec(attr_attr, GenDiapoDocument.ElementSpec.StartTagType));
330
331 SimpleAttributeSet para_attr = new SimpleAttributeSet();
332 para_attr.addAttribute(GenDiapoDocument.ATTRIBUT_TYPE, IntParagraph);
333 change.add(new GenDiapoDocument.ElementSpec(para_attr, GenDiapoDocument.ElementSpec.StartTagType));
334
335 change.add(voidTextElementSpec());
336
337 change.add(EndElementSpec);
338 change.add(EndElementSpec);
339 }
340 }
341 }
342 }
343
344 /**
345 * Traitement d'un noeud de Merlot
346 * @param change Vecteur contenant les ElementSpec du document a créer
347 * @param node MerlotDOMNode a ajouter au document sous forme d'ElementSpec
348 */
349 public static void parseMerlotNodeTree(Vector change, MerlotDOMNode node) {
350 String str;
351
352 // Lecture des fils
353 MerlotDOMNode childs[] = node.getChildNodes();
354
355 // creer une liste des fils sans les noeuds invisible
356 Vector realChildsV = new Vector();
357 for(int i=0; i<childs.length; i++) {
358 if (childs[i] instanceof MerlotDOMText) {
359 if (((MerlotDOMText) childs[i]).isVisible()) {
360 realChildsV.add(childs[i]);
361 }
362 } else {
363 realChildsV.add(childs[i]);
364 }
365 }
366 MerlotDOMNode[] realChilds = (MerlotDOMNode[]) realChildsV.toArray(new MerlotDOMNode[realChildsV.size()]);
367
368 // PCData authorise ?
369 boolean pcDataAllowed = pcDataAllowed(node);
370
371 // eventual empty pcdata as first child
372 if (pcDataAllowed) {
373 boolean addNewOne = false;
374 if (realChilds.length>0) {
375 if (!(realChilds[0] instanceof MerlotDOMText)) {
376 addNewOne = true;
377 }
378 } else if (realChilds.length == 0) {
379 addNewOne = true;
380 }
381 if (addNewOne) {
382 MerlotDOMNode firstChild = node.getFirstChild();
383 MerlotDOMText textNode;
384 if (firstChild == null) {
385 textNode = (MerlotDOMText) node.newChild(DTDConstants.PCDATA_KEY);
386 } else {
387 textNode = (MerlotDOMText) firstChild.newSiblingBefore(DTDConstants.PCDATA_KEY);
388 }
389 parsePCDataTree(change, textNode);
390 // addPCDataTree(change, GenDiapoDocument.ATTRIBUT_MERLOTTEXT_FIRST);
391 }
392 }
393
394 // add childs
395 for (int i=0; i<realChilds.length; i++) {
396 MerlotDOMNode child = realChilds[i];
397 if (child instanceof MerlotDOMElement) {
398 parseMerlotNode(change, child);
399 } else if (child instanceof MerlotDOMText) {
400 parsePCDataTree(change, (MerlotDOMText) child);
401 }
402 }
403
404 // eventual empty pcdata as last child
405 if (pcDataAllowed) {
406 if (realChilds.length>0) {
407 if (!(realChilds[realChilds.length-1] instanceof MerlotDOMText)) {
408 // Add a new node at the end
409 MerlotDOMText textNode = (MerlotDOMText) node.newChild(DTDConstants.PCDATA_KEY);
410 parsePCDataTree(change, textNode);
411 }
412 }
413 }
414
415 }
416
417 /*
418 * Gestion du style
419 */
420
421
422 static boolean inParagraph(Vector change) {
423 GenDiapoDocument.ElementSpec es = (GenDiapoDocument.ElementSpec) change.lastElement();
424 boolean retval = (es.getType() == GenDiapoDocument.ElementSpec.ContentType);
425 if (!retval) {
426 if (es.getType() == GenDiapoDocument.ElementSpec.StartTagType) {
427 AttributeSet attr = es.getAttributes();
428 Object o = attr.getAttribute(GenDiapoDocument.ATTRIBUT_TYPE);
429 if (o instanceof Integer) {
430 int type = ((Integer) o).intValue();
431 retval = (type == GenDiapoDocument.ParagraphCSS);
432 }
433 }
434 }
435 return retval;
436 }
437
438 static void pushParagraph(Vector change, MerlotDOMNode root, MerlotDOMNode node, StyleSheet style) {
439 // Paragraph
440 Style paraStyle = getStyle(style, root, root);
441 SimpleAttributeSet para_attr = new SimpleAttributeSet();
442 para_attr= new SimpleAttributeSet();
443 para_attr.addAttribute(GenDiapoDocument.ATTRIBUT_TYPE, IntParagraphCSS);
444 para_attr.addAttributes(paraStyle);
445 change.add(new GenDiapoDocument.ElementSpec(para_attr, GenDiapoDocument.ElementSpec.StartTagType));
446 }
447
448 static void popParagraph(Vector change, MerlotDOMNode root, MerlotDOMNode node, StyleSheet style) {
449 change.add(EndElementSpec);
450 }
451
452
453 /*---------------------------------*/
454 static void test(String selector) {
455 Vector elements = new Vector();
456 try {
457 boolean done;
458 int dotIndex = 0;
459 int spaceIndex = 0;
460 int poundIndex = 0;
461 int lastIndex = 0;
462 int length = selector.length();
463 while (lastIndex < length) {
464 if (dotIndex == lastIndex) {
465 dotIndex = selector.indexOf('.', lastIndex);
466 }
467 if (poundIndex == lastIndex) {
468 poundIndex = selector.indexOf('#', lastIndex);
469 }
470 spaceIndex = selector.indexOf(' ', lastIndex);
471 if (spaceIndex == -1) {
472 spaceIndex = length;
473 }
474 if (dotIndex != -1 && poundIndex != -1 &&
475 dotIndex < spaceIndex && poundIndex < spaceIndex) {
476 if (poundIndex < dotIndex) {
477 // #.
478 if (lastIndex == poundIndex) {
479 elements.addElement("");
480 }
481 else {
482 elements.addElement(selector.substring(lastIndex,
483 poundIndex));
484 }
485 if ((dotIndex + 1) < spaceIndex) {
486 elements.addElement(selector.substring
487 (dotIndex + 1, spaceIndex));
488 }
489 else {
490 elements.addElement(null);
491 }
492 if ((poundIndex + 1) == dotIndex) {
493 elements.addElement(null);
494 }
495 else {
496 elements.addElement(selector.substring
497 (poundIndex + 1, dotIndex));
498 }
499 }
500 else if(poundIndex < spaceIndex) {
501 // .#
502 if (lastIndex == dotIndex) {
503 elements.addElement("");
504 }
505 else {
506 elements.addElement(selector.substring(lastIndex,
507 dotIndex));
508 }
509 if ((dotIndex + 1) < poundIndex) {
510 elements.addElement(selector.substring
511 (dotIndex + 1, poundIndex));
512 }
513 else {
514 elements.addElement(null);
515 }
516 if ((poundIndex + 1) == spaceIndex) {
517 elements.addElement(null);
518 }
519 else {
520 elements.addElement(selector.substring
521 (poundIndex + 1, spaceIndex));
522 }
523 }
524 dotIndex = poundIndex = spaceIndex + 1;
525 }
526 else if (dotIndex != -1 && dotIndex < spaceIndex) {
527 // .
528 if (dotIndex == lastIndex) {
529 elements.addElement("");
530 }
531 else {
532 elements.addElement(selector.substring(lastIndex,
533 dotIndex));
534 }
535 if ((dotIndex + 1) == spaceIndex) {
536 elements.addElement(null);
537 }
538 else {
539 elements.addElement(selector.substring(dotIndex + 1,
540 spaceIndex));
541 }
542 elements.addElement(null);
543 dotIndex = spaceIndex + 1;
544 }
545 else if (poundIndex != -1 && poundIndex < spaceIndex) {
546 // #
547 if (poundIndex == lastIndex) {
548 elements.addElement("");
549 }
550 else {
551 elements.addElement(selector.substring(lastIndex,
552 poundIndex));
553 }
554 elements.addElement(null);
555 if ((poundIndex + 1) == spaceIndex) {
556 elements.addElement(null);
557 }
558 else {
559 elements.addElement(selector.substring(poundIndex + 1,
560 spaceIndex));
561 }
562 poundIndex = spaceIndex + 1;
563 }
564 else {
565 // id
566 elements.addElement(selector.substring(lastIndex,
567 spaceIndex));
568 elements.addElement(null);
569 elements.addElement(null);
570 }
571 lastIndex = spaceIndex + 1;
572 }
573
574
575 // Create the tag, id, and class arrays.
576 int total = elements.size();
577 int numTags = total / 3;
578 String[] tags = new String[numTags];
579 String[] ids = new String[numTags];
580 String[] classes = new String[numTags];
581 for (int index = 0, eIndex = total - 3; index < numTags;
582 index++, eIndex -= 3) {
583 tags[index] = (String)elements.elementAt(eIndex);
584 ids[index] = (String)elements.elementAt(eIndex + 1);
585 classes[index] = (String)elements.elementAt(eIndex + 2);
586 }
587
588 // print
589 System.out.println("test ------<");
590 System.out.print("tags=");
591 for (int i=0; i<tags.length; i++) {
592 System.out.print("'"+tags[i]+"' ");
593 }
594 System.out.print("\nids=");
595 for (int i=0; i<tags.length; i++) {
596 System.out.print("'"+ids[i]+"' ");
597 }
598 System.out.print("\nclasses=");
599 for (int i=0; i<tags.length; i++) {
600 System.out.print("'"+classes[i]+"' ");
601 }
602 System.out.println("\ntest ------>");
603 } catch (Exception e) {
604 System.out.println(e.getMessage());
605 }
606 }
607
608 /*---------------------------------*/
609
610 static Style getStyleAttribute(StyleSheet style, MerlotDOMNode node, DTDAttribute nodeAttr) {
611 String str = node.getNodeName()+":"+nodeAttr.getName();
612 Style retval = style.getRule(str);
613 return retval;
614 }
615
616 static Style getStyle(StyleSheet style, MerlotDOMNode root, MerlotDOMNode node) {
617 String str = "";
618 String glue = "";
619
620 String rootName;
621 root = root.getParentNode();
622 if (root == null) {
623 rootName = "";
624 } else {
625 rootName = root.getNodeName();
626 }
627
628 //str = "paragraph";
629 //glue = " ";
630
631 while (node != null) {
632 if (node instanceof MerlotDOMElement) {
633 str = node.getNodeName() + glue + str;
634 glue = " ";
635 }
636 node = node.getParentNode();
637 if (node != null) {
638 if (node.getNodeName().equals(rootName)) {
639 node = null;
640 }
641 }
642 }
643 Style retval = style.getRule(str);
644
645 /*
646 test(str);
647 System.out.println("getStyle----------------------<");
648 System.out.println("name="+str);
649 System.out.println("isBold : "+StyleConstants.isBold(retval));
650 System.out.println("isItalic : "+StyleConstants.isItalic(retval));
651 System.out.println("isUnderline: "+StyleConstants.isUnderline(retval));
652 System.out.println("getStyle---------------------->");
653 */
654
655 return retval;
656 }
657
658 public static HashMap getNodeAttributes(MerlotDOMNode node) {
659
660 HashMap attributes = new HashMap();
661
662 Enumeration dtdAttributes = node.getDTDAttributes();
663 org.w3c.dom.Node xmlNode = node.getRealNode();
664 if (dtdAttributes != null) {
665 DTDAttribute nodeAttr;
666 SimpleAttributeSet attr_attr, text_attr, para_attr;
667 String attrValue, attrName;
668
669 while (dtdAttributes.hasMoreElements()) {
670 nodeAttr = (DTDAttribute)dtdAttributes.nextElement();
671
672 attrName = nodeAttr.getName();
673
674 attrValue="";
675 if (xmlNode instanceof org.w3c.dom.Element) {
676 attrValue = ((org.w3c.dom.Element)xmlNode).getAttribute(nodeAttr.getName());
677 }
678
679 attributes.put(nodeAttr.getName(), attrValue);
680
681 }
682 }
683
684 return attributes;
685 }
686
687 static String getPath(MerlotDOMNode node) {
688 String path = "";
689 while (node != null) {
690 path = node.getNodeName()+"/"+path;
691 node = node.getParentNode();
692 }
693 path += GenDiapoDocument.ATTRIBUT_STYLEATTRIBUTES;
694 return path;
695 }
696
697 static SimpleAttributeSet getDocumentAttributes(MerlotDOMNode root, MerlotDOMNode node) {
698 SimpleAttributeSet attr = new SimpleAttributeSet();
699 root = root.getParentNode();
700 while ( (node != null) && (node != root) ) {
701 attr.addAttribute(getPath(node), getNodeAttributes(node));
702 node = node.getParentNode();
703 }
704 return attr;
705 }
706
707 public static AttributeSet getAttributesCSSLabel(MerlotDOMNode node, Style style) {
708 SimpleAttributeSet textAttr = new SimpleAttributeSet();
709 textAttr.addAttribute(GenDiapoDocument.ATTRIBUT_TYPE, IntTextCSS);
710 textAttr.addAttribute(GenDiapoDocument.ATTRIBUT_STYLENAME, style.getName());
711 textAttr.addAttributes(style);
712 // Ajout des attributes
713
714 return textAttr;
715 }
716
717 static void parsePCDataStyle(Vector change, MerlotDOMNode root, MerlotDOMNode node, StyleSheet style) {
718 // verifie s'il y a besoin d'un pushParagraph
719 if (!inParagraph(change)) {
720 pushParagraph(change, root, node, style);
721 }
722
723 // Text
724 String text = ((MerlotDOMText)node).getText();
725
726 Style cssStyle = getStyle(style, root, node);
727 AttributeSet textAttr = getAttributesCSSLabel(node, cssStyle);
728
729 ((SimpleAttributeSet) textAttr).addAttributes(getDocumentAttributes(root, node));
730
731 change.add(new GenDiapoDocument.ElementSpec(textAttr,
732 GenDiapoDocument.ElementSpec.ContentType,
733 text.toCharArray(),
734 0,
735 text.length()));
736
737 // s'il y a un retour a la ligne -> change de paragraphe
738 if (text.length() > 0) {
739 if (text.charAt(text.length()-1) == '\n') {
740 popParagraph(change, root, node, style);
741 }
742 }
743
744 }
745
746 static void parseEndNodeStyle(Vector change, MerlotDOMNode root, MerlotDOMNode node, StyleSheet style) {
747 // Text
748 String text = "\n";
749
750 Style cssStyle = getStyle(style, root, node);
751 AttributeSet textAttr = getAttributesCSSLabel(node, cssStyle);
752
753 change.add(new GenDiapoDocument.ElementSpec(textAttr,
754 GenDiapoDocument.ElementSpec.ContentType,
755 text.toCharArray(),
756 0,
757 text.length()));
758 }
759
760 static void parseMerlotNodeStyleInside(Vector change, MerlotDOMNode root, MerlotDOMNode node, StyleSheet style) {
761 // parse des enfants
762 MerlotDOMNode childs[] = node.getChildNodes();
763 for(int i=0; i<childs.length; i++) {
764 if (childs[i] instanceof MerlotDOMText) {
765 parsePCDataStyle(change, root, childs[i], style); // isVisible ignore
766 } else {
767 parseMerlotNodeStyleInside(change, root, childs[i], style);
768 }
769 }
770 }
771
772 public static void parseMerlotNodeStyle(Vector change, MerlotDOMNode node, StyleSheet style) {
773 // <pcdata>
774 SimpleAttributeSet attr_attr= new SimpleAttributeSet();
775 attr_attr.addAttribute(GenDiapoDocument.ATTRIBUT_TYPE, IntFragment);
776 change.add(new GenDiapoDocument.ElementSpec(attr_attr, GenDiapoDocument.ElementSpec.StartTagType));
777
778 // 1er paragraphe
779 pushParagraph(change, node, node, style);
780
781 // parse chaque noeud
782 parseMerlotNodeStyleInside(change, node, node, style);
783
784 // ferme le dernier paragraph
785 if (inParagraph(change)) {
786 parseEndNodeStyle(change, node, node, style);
787 popParagraph(change, node, node, style);
788 }
789
790 // </pcdata>
791 change.add(EndElementSpec);
792 }
793
794 static void parseMerlotNodeCustom(Vector change, MerlotDOMNode node, NodeControler nodeControler) {
795 nodeControler.parse(node, change);
796 }
797
798 public static void parseMerlotNode(Vector change, MerlotDOMNode node) {
799 if (!( (node instanceof MerlotDOMElement) || (node instanceof MerlotDOMDocument) )) {
800 // uniquement les tags de type element et le document
801 // Le reste ne sait pas etre traiter
802 return;
803 }
804
805 // Traitement du noeud "node"
806 int editionType = GenDiapoEditor.EDITION_TREE;
807 org.w3c.dom.Node xmlNode = node.getRealNode();
808 MerlotDOMEditor editor = node.getEditor();
809 ViewFactory viewFactory = null;
810 StyleSheet style = null;
811 NodeControler nodeControler = null;
812 boolean addVoid = true;
813 if (editor instanceof GenDiapoEditor) {
814 viewFactory = ((GenDiapoEditor)editor).getViewFactory(node);
815 style = ((GenDiapoEditor)editor).getStyleSheet(node);
816 editionType = ((GenDiapoEditor)editor).editionType(node);
817 nodeControler = ((GenDiapoEditor)editor).getNodeControler(node);
818 addVoid = ((GenDiapoEditor)editor).addVoid(node);
819 }
820
821 // Nom
822 SimpleAttributeSet node_attr = new SimpleAttributeSet();
823 node_attr.addAttribute(GenDiapoDocument.ATTRIBUT_MERLOTNODE, node);
824 node_attr.addAttribute(GenDiapoDocument.ATTRIBUT_XMLNODE, xmlNode);
825 node_attr.addAttribute(GenDiapoDocument.ATTRIBUT_TYPE, new java.lang.Integer(xmlNode.getNodeType()));
826 node_attr.addAttribute(GenDiapoDocument.EDITION_TYPE, new java.lang.Integer(editionType));
827 if (viewFactory != null) {
828 node_attr.addAttribute(GenDiapoDocument.VIEWFACTORY, viewFactory);
829 }
830 if (style != null) {
831 node_attr.addAttribute(GenDiapoDocument.STYLESHEET, style);
832 }
833 change.add(new GenDiapoDocument.ElementSpec(node_attr, GenDiapoDocument.ElementSpec.StartTagType));
834
835 // Global Element
836 if (addVoid) {
837 parseGlobalElementTree(change, node);
838 }
839
840 // Detection du type de node (tree ou style)
841 switch (editionType) {
842 case GenDiapoEditor.EDITION_TREE :
843 parseAttributes(change, node, style);
844 parseMerlotNodeTree(change, node);
845 break;
846 case GenDiapoEditor.EDITION_STYLE :
847 parseAttributes(change, node, style);
848 parseMerlotNodeStyle(change, node, style);
849 break;
850 case GenDiapoEditor.EDITION_CUSTOM :
851 parseMerlotNodeCustom(change, node, nodeControler);
852 break;
853 }
854
855 // EndTag
856 change.add(EndElementSpec);
857 }
858
859 private static void deleteLastElement(GenDiapoDocument doc) {
860 int length = doc.getLength();
861 Element[] none = new Element[0];
862
863 // Supression de la feuille
864 Element elem = doc.getParagraphElement(length);
865 int nb = elem.getElementCount();
866
867 ((GenDiapoDocument.NodeElement)elem).replace(nb-1,1,none);
868
869 // Supression du noeud
870 elem = ((GenDiapoDocument.NodeElement) elem).getParentElement();
871 nb = elem.getElementCount();
872 ((GenDiapoDocument.NodeElement)elem).replace(nb-1,1,none);
873 }
874
875 public static GenDiapoDocument create(MerlotDOMDocument merlotDocument) {
876 // Creation d'un vecteur d'ElementSpec a partir de merlotDocument
877 Vector all = new Vector();
878 parseMerlotNode(all, merlotDocument);
879
880 // Conversion en Array
881 GenDiapoDocument.ElementSpec es[] = new GenDiapoDocument.ElementSpec[all.size()];
882 es = (GenDiapoDocument.ElementSpec[]) all.toArray(es);
883 all = null;
884
885 // Creation du document
886 GenDiapoDocument document = new GenDiapoDocument(es);
887
888 // Supprime le ending element si le document n'est pas vide
889 if (document.getLength() > 0) {
890 deleteLastElement(document);
891 }
892
893 return document;
894 }
895
896 //
897 public static GenDiapoDocument insertNode(GenDiapoDocument document, MerlotDOMNode node)
898 throws javax.swing.text.BadLocationException {
899 // get previous visual element (logical previous or father)
900 boolean previousIsFather = false;
901 MerlotDOMNode previous = node.getPreviousSibling();
902
903 while (previous==null?false:((previous instanceof MerlotDOMText)?(!((MerlotDOMText) previous).isVisible()):false)) {
904 previous = previous.getPreviousSibling();
905 }
906
907 if (previous == null) {
908 previous = node.getParentNode();
909 previousIsFather = true;
910 }
911
912 // get element associate with node
913 javax.swing.text.Element nodeElement = document.findElementWithProperty(GenDiapoDocument.ATTRIBUT_MERLOTNODE, previous);
914 int offset = nodeElement.getEndOffset();
915 Vector elementspec = new Vector();
916
917 // up while not in node
918 javax.swing.text.Element e = nodeElement;
919 // skip one level is previousIsFather to be inside father (and not a sibling)
920 if (previousIsFather) {
921 int index = e.getElementIndex(offset);
922 e = e.getElement(index);
923 }
924 while (!e.isLeaf()) {
925 int index = e.getElementIndex(offset);
926 e = e.getElement(index);
927 elementspec.add(EndElementSpec);
928 }
929
930 // parse new node
931 GenDiapoDocumentFactory.parseMerlotNode(elementspec, node);
932 GenDiapoDocument.ElementSpec es[] = new GenDiapoDocument.ElementSpec[elementspec.size()];
933 es = (GenDiapoDocument.ElementSpec[]) elementspec.toArray(es);
934
935 // insert new node at the end
936 document.insert(offset, es);
937 return document;
938 }
939
940 public static GenDiapoDocument deleteNode(GenDiapoDocument document, MerlotDOMNode node)
941 throws javax.swing.text.BadLocationException {
942 javax.swing.text.Element nodeElement = document.findElementWithProperty(GenDiapoDocument.ATTRIBUT_MERLOTNODE, node);
943 int offsetStart = nodeElement.getStartOffset();
944 int offsetEnd = nodeElement.getEndOffset();
945 int length = offsetEnd-offsetStart;
946 document.removeUncheck(offsetStart, length);
947 return document;
948 }
949
950 }