Loading...
Searching...
No Matches
MouseEventXML.h
1/*
2
3MIT License
4
5Copyright (c) 2026 FMI Open Development / Markus Peura, first.last@fmi.fi
6
7Permission is hereby granted, free of charge, to any person obtaining a copy
8of this software and associated documentation files (the "Software"), to deal
9in the Software without restriction, including without limitation the rights
10to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11copies of the Software, and to permit persons to whom the Software is
12furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice shall be included in all
15copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23SOFTWARE.
24
25*/
26/*
27 * MouseEventXML.h
28 *
29 * Created on: Aug 6, 2026
30 * Author: mpeura
31 */
32
33#ifndef DRAIN_IMAGE_MOUSEXML2_H_
34#define DRAIN_IMAGE_MOUSEXML2_H_
35
36#include <set>
37#include <string>
38
39#include "MouseXML.h"
40#include "TreeSVG.h"
41#include "drain/js/coords.h"
42
43namespace drain {
44
45namespace image {
46
50template <class N>
51class MouseEventXML : public MouseXML {
52
53public:
54
55 typedef DRAIN_XML_TREE(N) tree_t;
56 // typedef N node_t;
57
58 MouseEventXML(tree_t & root, drain::image::MouseXML::EventClass mouseEvent, const std::string & owner) :
59 root(root),
60 eventName(getEventFunctionName(mouseEvent)),
61 handlerName(getHandlerFunctionName(mouseEvent)),
62 initName(getInitialiserFunctionName(mouseEvent)),
63 scopeJS(ensureListenerHandler(root, handlerName)),
64 owner(owner) {
65 //: root(root), mouseEvent(mouseEvent), scopeJS(ensureListener(root, mouseEvent)), owner(owner) {
66 scopeJS[owner]->setProgramComment("Set by: ", owner);
67 }
68
69 /*
70 inline
71 bool listenerIsSet(tree_t & elem) const {
72 if (owner.empty()){
73 drain::Logger(__FILE__, __FUNCTION__).warn("Owner undefined, potential duplicate listeners cannot be identified");
74 return false;
75 }
76 else {
77 tree_t & listenerScope = MouseXML::getListenerScope(root, handlerName); // elem, mouseEvent);
78 return ((elem->getAttribute(eventName, "") == handlerName) && listenerScope.hasChild(owner));
79 }
80 }
81 */
82
83 inline
84 bool routineIsSet(tree_t & elem) const {
85 if (owner.empty()){
86 drain::Logger(__FILE__, __FUNCTION__).warn("Owner undefined, potential duplicate listeners cannot be identified");
87 return false;
88 }
89 else {
90 tree_t & listenerScope = MouseXML::getListenerScope(root, handlerName); // elem, mouseEvent);
91 return listenerScope.hasChild(owner);
92 }
93 }
94
95 // template <class ...TT>
96 inline
97 void setListenerNEW(tree_t & elem) const { //, const TT & ...args) const {
98 attachListener(elem, eventName, handlerName);
99 }
100
101 inline // tree_t & elem
102 tree_t & getListenerRoutine() const { //, const TT & ...args) const {
103 // connectElement(args...);
104 // tree_t & listenerScope = MouseXML::getListenerScope(root, elem, mouseEvent);
105 tree_t & listenerScope = MouseXML::getListenerScope(root, handlerName);
106 if (!owner.empty()){
107 // Marker!
108 listenerScope[owner]->setProgramComment(owner, ':', drain::sprinter(connectedObjects, drain::Sprinter::plainLayout));
109 // attachListener(elem, eventName, handlerName);
110 }
111 else {
112 listenerScope.addChild()->setProgramComment("undefined owner: ", drain::sprinter(connectedObjects, drain::Sprinter::plainLayout));
113 }
114 return listenerScope;
115 }
116
117
119 tree_t & getListenerInitSubScope() const;
120
121 template <class V>
122 inline
123 void defineVariable(const std::string & name, const V & value) const;
124 // void defineConstant(const std::string & name, const V & value) const;
125
126 inline
127 void useCoordinates(CoordinateProcessing level) const {
128 adjustListenerGeoRef(scopeJS, level);
129 }
130
131 void connectClass(const drain::ClassXML & cls) const;
132
133 void connectTag(const std::string & s) const;
134
135 inline
136 void connectTag(const typename N::tag_t & type) const {
137 connectTag(drain::Enum<typename N::tag_t>::dict.getKey(type));
138 }
139
140 inline
141 void connectElement(const drain::ClassXML & cls){
142 connectClass(cls);
143 }
144
145 inline
146 void connectElement(const typename N::tag_t & type) const {
147 connectTag(type);
148 }
149
150
151 inline
152 void connectElement(const std::string & arg) const {
153 connectTag(arg);
154 }
155
156 inline
157 void connectElement(const char *arg) const {
158 connectTag(arg);
159 }
160
161 /*
162 template <class ...TT>
163 void connectElement(const drain::ClassXML & cls, const TT & ...args) const {
164 connectClass(cls);
165 connectElement(args...);
166 }
167
168 template <class ...TT>
169 void connectElement(const std::string & arg, const TT & ...args) const {
170 connectTag(arg);
171 connectElement(args...);
172 }
173
174 template <class ...TT>
175 void connectElement(const typename N::tag_t & type, const TT & ...args) const {
176 connectTag(type);
177 connectElement(args...);
178 }
179
180 template <class ...TT>
181 void connectElement(const char *arg, const TT & ...args) const {
182 connectTag(arg);
183 connectElement(args...);
184 }
185 */
186
187
188protected:
189
190 tree_t & root;
191
192 //drain::image::MouseXML::EventClass mouseEvent;
193 const std::string eventName; // standard lower case, like "onmousemove"
194 const std::string handlerName; // camel case, like "handleMouseMove"
195 const std::string initName; // camel case, like "initMouseMove"
196
197 tree_t & scopeJS;
198
199 std::string owner;
200
201 // Terminal function for the variadic template
202 // inline
203 // void connectElement() const {}
204
205 mutable
206 std::set<std::string> connectedObjects;
207
208};
209
210
211
215template <class N>
216inline
217DRAIN_XML_TREE(N) & MouseEventXML<N>::getListenerInitSubScope() const {
218 DRAIN_XML_TREE(N) & scope = getListenerInitScope(root, initName);
219 DRAIN_XML_TREE(N) & subScope = scope[N::tag_t::SCOPE_CURLY](N::tag_t::SCOPE_CURLY);
220 if (subScope.empty()){
221 subScope->setText("with(listener.ctx)");
222 subScope.addChild()->setProgramComment("Scope exposed by ", __FUNCTION__);
223 }
224 return subScope;
225}
226
227/*
228template <class N>
229void MouseEventXML<N>::useCoordinates(CoordinateProcessing level) const {
230 adjustListenerGeoRef(scopeJS, level);
231}
232*/
233
237template <class N>
238inline
239void MouseEventXML<N>::connectClass(const drain::ClassXML & cls) const {
240 Logger mout(__FILE__, __FUNCTION__);
241
242 mout.debug("connecting CLASS ", cls, " = ", cls.strPrefixed());
243 DRAIN_XML_TREE(N) & scope = getListenerInitScope(root, initName);
244 scope[cls]->setText("listener.ctx['", cls, "'] = group.querySelector('", cls.strPrefixed(), "')");
245 connectedObjects.insert(cls);
246}
247
251template <class N>
252template <class V>
253inline
254void MouseEventXML<N>::defineVariable(const std::string & name, const V & value) const {
255 Logger mout(__FILE__, __FUNCTION__);
256
257 // mout.debug("connecting CLASS ", cls, " = ", cls.strPrefixed());
258 DRAIN_XML_TREE(N) & scope = getListenerInitScope(root, initName);
259 scope[name]->setText("listener.ctx['", name, "'] = ", sprinter(value, Sprinter::jsLayout), ';');
260 //connectedObjects.insert(cls);
261}
262
263
267template <class N>
268inline
269void MouseEventXML<N>::connectTag(const std::string & arg) const {
270 DRAIN_XML_TREE(N) & scope = getListenerInitScope(root, initName);
271 scope[arg]->setText("listener.ctx['", arg, "'] = group.querySelector('", arg, "')");
272 connectedObjects.insert(arg);
273}
274
275
276// MOVE to MouseXML(1)
280/*
281template <class N>
282inline
283void MouseEventXML<N>::addListenerInitGeoConf() const {
284 JavaScriptXML::ensureScript(root, "coords", javascript::coords);
285
286 DRAIN_XML_TREE(N) & scope = getListenerInitScope(root, mouseEvent);
287 scope["bbox"]->setProgramComment("bbox+epsg init removed");
288 // scope["bbox"]->setText("if (listener.hasAttribute('data-bbox')){ listener.ctx.geo_bbox = new BBox(listener.getAttribute('data-bbox'))}");
289 // consider other element (IMAGE title)
290 // scope["epsg"]->setText("if (listener.hasAttribute('data-epsg')){ listener.ctx.geo_epsg = listener.getAttribute('data-epsg') }");
291}
292*/
293
294} // namespace image
295
296} // namespace drain
297
298#endif // DRAIN_IMAGE_MOUSEXML2_H_
A wrapper marking string an CSS effect.
Definition ClassXML.h:57
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition Log.h:326
Logger & warn(const TT &... args)
Possible error, but execution can continue.
Definition Log.h:440
static const SprinterLayout plainLayout
Display plain values, concatenating them with comma (except for strings).
Definition Sprinter.h:212
static const SprinterLayout jsLayout
JavaScript layout. Like JSON layout, but keys without hyphens.
Definition Sprinter.h:227
Definition MouseEventXML.h:51
tree_t & getListenerInitSubScope() const
Scope inside ctx.
Definition MouseXML.h:64
static std::string getEventFunctionName(MouseXML::EventClass eventKey)
Modifies short mouse event name like "click" to "onmouseclick", or prefixed form "handleClick".
Definition MouseXML.cpp:73
Definition Data.h:1473
A container for a static dictionary of enumeration values.
Definition Enum.h:51