]> matita.cs.unibo.it Git - helm.git/blob - helm/DEVEL/mathml_editor/src/TDocument.cc
* added show/hide cursro methods
[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::reset()
32 {
33   DOM::Element root = doc.createElementNS(TML_NS_URI, "tml:tex");
34   root.setAttributeNS(XMLNS_NS_URI, "xmlns:tml", TML_NS_URI);
35   doc.replaceChild(root, doc.get_documentElement());
36   clearDirty();
37 }
38
39 void
40 TDocument::serialize(const char* filename) const
41 {
42   DOM::DOMImplementation di;
43   di.saveDocumentToFile(doc, filename, GDOME_SAVE_LIBXML_INDENT);
44 }
45
46 std::string
47 TDocument::makeId(unsigned id)
48 {
49   ostringstream os;
50   os << "I" << id;
51   return os.str();
52 }
53
54 TNode
55 TDocument::create(const std::string& name, unsigned id) const
56 {
57   DOM::Element elem = doc.createElementNS(TML_NS_URI, "tml:" + name);
58   if (id > 0) elem.setAttribute("id", makeId(id));
59   return elem;
60 }
61
62 TNode
63 TDocument::createC(const std::string& name, unsigned id) const
64 {
65   TNode m = create("c", id);
66   m["name"] = name;
67   return m;
68 }
69
70 TNode
71 TDocument::createT(const std::string& name, const std::string& text, unsigned id) const
72 {
73   TNode t = create(name, id);
74   t["val"] = text;
75   return t;
76 }
77
78 unsigned
79 TDocument::nodeDepth(const DOM::Node& node)
80 {
81   DOM::Node n = node;
82
83   unsigned depth = 0;
84   while (n)
85     {
86       depth++;
87       n = n.get_parentNode();
88     }
89   return depth;
90 }
91
92 DOM::Node
93 TDocument::findCommonAncestor(const DOM::Node& node1, const DOM::Node& node2)
94 {
95   DOM::Node n1 = node1;
96   DOM::Node n2 = node2;
97
98   unsigned d1 = nodeDepth(n1);
99   unsigned d2 = nodeDepth(n2);
100
101   // cout << "finding common ancestor " << d1 << " " << d2 << endl;
102
103   while (d1 < d2)
104     {
105       assert(n2);
106       n2 = n2.get_parentNode();
107       d2--;
108     }
109
110   while (d1 > d2)
111     {
112       assert(n1);
113       n1 = n1.get_parentNode();
114       d1--;
115     }
116
117   while (n1 != n2)
118     {
119       assert(n1);
120       assert(n2);
121       n1 = n1.get_parentNode();
122       n2 = n2.get_parentNode();
123     }
124
125   return n1;
126 }
127
128 DOM::Node
129 TDocument::findIdNode(const DOM::Node& node)
130 {
131   DOM::Node n = node;
132   while (n)
133     {
134       if (n.get_nodeType() == DOM::Node::ELEMENT_NODE)
135         {
136           DOM::Element el = n;
137           if (el.hasAttribute("id")) return el;
138         }
139       n = n.get_parentNode();
140     }
141
142   return DOM::Node(0);
143 }
144
145 TNode
146 TDocument::getNodeByIdAux(const TNode& node, const std::string& id)
147 {
148   if (node.hasId(id)) return node;
149   else
150     for (TNode p = node.first(); p; p = p.next())
151       if (TNode res = getNodeByIdAux(p, id)) return res;
152   return TNode();
153 }
154
155 TNode
156 TDocument::getNodeById(unsigned id) const
157 {
158   DOM::Element root = doc.get_documentElement();
159   assert(root);
160   return getNodeByIdAux(root, makeId(id));
161 }
162
163 void
164 TDocument::handleEvent(const DOM::Event& ev)
165 {
166   DOM::MutationEvent me(ev);
167   assert(me);
168
169 #if 0
170   if (dirty)
171     cout << "TDocument::handleEvent DIRTY BEFORE = " << dirty.getAttribute("id") << endl;
172   else
173     cout << "TDocument::handleEvent DIRTY BEFORE = (nil)" << endl;
174 #endif
175
176   if (DOM::Node node = me.get_target())
177     if (dirty)
178       dirty = findIdNode(findCommonAncestor(dirty, node));
179     else
180       dirty = findIdNode(node);
181   else
182     assert(0);
183
184 #if 0
185   cout << "TDocument::handleEvent target = " << DOM::Node(me.get_target()).get_nodeName() << " DIRTY AFTER = "
186        << dirty.getAttribute("id") << " ME = " << DOM::Node(me.get_target()).get_nodeName() << endl;
187 #endif
188 }