]> matita.cs.unibo.it Git - helm.git/blob - helm/DEVEL/mathml_editor/src/TDocument.cc
* this is a large commit
[helm.git] / helm / DEVEL / mathml_editor / src / TDocument.cc
1
2 #include <sstream>
3
4 #include "globals.hh"
5 #include "dom.hh"
6 #include "TDocument.hh"
7
8 TDocument::TDocument()
9 {
10   DOM::DOMImplementation di;
11   DOM::DocumentType dt;
12   doc = di.createDocument(TML_NS_URI, "tml:tex", dt);
13   DOM::Element root = doc.get_documentElement();
14   assert(root);
15   root.setAttributeNS(XMLNS_NS_URI, "xmlns:tml", TML_NS_URI);
16
17   DOM::EventTarget et(doc);
18   assert(et);
19   et.addEventListener("DOMSubtreeModified", *this, false);
20 }
21
22 TDocument::~TDocument()
23 {
24   //DOM::Element root = doc.get_documentElement();
25   DOM::EventTarget et(doc);
26   assert(doc);
27   et.removeEventListener("DOMSubtreeModified", *this, false);
28 }
29
30 void
31 TDocument::serialize(const char* filename) const
32 {
33   DOM::DOMImplementation di;
34   di.saveDocumentToFile(doc, filename, GDOME_SAVE_LIBXML_INDENT);
35 }
36
37 std::string
38 TDocument::makeId(unsigned id)
39 {
40   ostringstream os;
41   os << "I" << id;
42   return os.str();
43 }
44
45 TNode
46 TDocument::create(const std::string& name, unsigned id) const
47 {
48   DOM::Element elem = doc.createElementNS(TML_NS_URI, "tml:" + name);
49   if (id > 0) elem.setAttribute("id", makeId(id));
50   return elem;
51 }
52
53 TNode
54 TDocument::createC(const std::string& name, unsigned id) const
55 {
56   TNode m = create("c", id);
57   m["name"] = name;
58   return m;
59 }
60
61 TNode
62 TDocument::createT(const std::string& name, const std::string& text, unsigned id) const
63 {
64   TNode t = create(name, id);
65   t["val"] = text;
66   return t;
67 }
68
69 unsigned
70 TDocument::nodeDepth(const DOM::Node& node)
71 {
72   DOM::Node n = node;
73
74   unsigned depth = 0;
75   while (n)
76     {
77       depth++;
78       n = n.get_parentNode();
79     }
80   return depth;
81 }
82
83 DOM::Node
84 TDocument::findCommonAncestor(const DOM::Node& node1, const DOM::Node& node2)
85 {
86   DOM::Node n1 = node1;
87   DOM::Node n2 = node2;
88
89   unsigned d1 = nodeDepth(n1);
90   unsigned d2 = nodeDepth(n2);
91
92   cout << "finding common ancestor " << d1 << " " << d2 << endl;
93
94   while (d1 < d2)
95     {
96       assert(n2);
97       n2 = n2.get_parentNode();
98       d2--;
99     }
100
101   while (d1 > d2)
102     {
103       assert(n1);
104       n1 = n1.get_parentNode();
105       d1--;
106     }
107
108   while (n1 != n2)
109     {
110       assert(n1);
111       assert(n2);
112       n1 = n1.get_parentNode();
113       n2 = n2.get_parentNode();
114     }
115
116   return n1;
117 }
118
119 DOM::Node
120 TDocument::findIdNode(const DOM::Node& node)
121 {
122   DOM::Node n = node;
123   while (n)
124     {
125       if (n.get_nodeType() == DOM::Node::ELEMENT_NODE)
126         {
127           DOM::Element el = n;
128           if (el.hasAttribute("id")) return el;
129         }
130       n = n.get_parentNode();
131     }
132
133   return DOM::Node(0);
134 }
135
136 TNode
137 TDocument::getNodeByIdAux(const TNode& node, const std::string& id)
138 {
139   if (node.hasId(id)) return node;
140   else
141     for (TNode p = node.first(); p; p = p.next())
142       if (TNode res = getNodeByIdAux(p, id)) return res;
143   return TNode();
144 }
145
146 TNode
147 TDocument::getNodeById(unsigned id) const
148 {
149   DOM::Element root = doc.get_documentElement();
150   assert(root);
151   return getNodeByIdAux(root, makeId(id));
152 }
153
154 void
155 TDocument::handleEvent(const DOM::Event& ev)
156 {
157   DOM::MutationEvent me(ev);
158   assert(me);
159
160   if (dirty)
161     cout << "TDocument::handleEvent DIRTY BEFORE = " << dirty.getAttribute("id") << endl;
162   else
163     cout << "TDocument::handleEvent DIRTY BEFORE = (nil)" << endl;
164
165   if (DOM::Node node = me.get_target())
166     if (dirty)
167       dirty = findIdNode(findCommonAncestor(dirty, node));
168     else
169       dirty = findIdNode(node);
170   else
171     assert(0);
172
173   cout << "TDocument::handleEvent target = " << DOM::Node(me.get_target()).get_nodeName() << " DIRTY AFTER = "
174        << dirty.getAttribute("id") << " ME = " << DOM::Node(me.get_target()).get_nodeName() << endl;
175   
176 }