Lumiera 0.pre.04~rc.1
»edit your freedom«
Loading...
Searching...
No Matches
gen-node-location-query.hpp
Go to the documentation of this file.
1/*
2 GEN-NODE-LOCATION-QUERY.hpp - pose UI-coordinate location queries against a GenNode structure
3
4 Copyright (C)
5 2017, Hermann Vosseler <Ichthyostega@web.de>
6
7  **Lumiera** is free software; you can redistribute it and/or modify it
8  under the terms of the GNU General Public License as published by the
9  Free Software Foundation; either version 2 of the License, or (at your
10  option) any later version. See the file COPYING for further details.
11
12*/
13
14
52#ifndef STAGE_INTERACT_GEN_NODE_LOCATION_QUERY_H
53#define STAGE_INTERACT_GEN_NODE_LOCATION_QUERY_H
54
55#include "lib/error.hpp"
56#include "lib/symbol.hpp"
58#include "lib/diff/gen-node.hpp"
59#include "lib/format-string.hpp"
60#include "lib/iter-explorer.hpp"
61#include "lib/iter-source.hpp"
62#include "lib/itertools.hpp"
63#include "lib/util.hpp"
64
65#include <utility>
66#include <string>
67
68
69namespace stage {
70namespace interact {
71
72 namespace error = lumiera::error;
73
74 using lib::Symbol;
75 using lib::Literal;
76 using lib::diff::Rec;
77 using util::isnil;
78 using util::_Fmt;
79 using std::forward;
80 using std::string;
81
82
83
84
91 : public LocationQuery
92 {
93 Rec tree_;
94
95 public:
96 template<class REC>
97 GenNodeLocationQuery(REC&& backingStructure)
98 : tree_(std::forward<REC>(backingStructure))
99 { }
100
101
102 /* === LocationQuery interface === */
103
105 virtual Literal
106 determineAnchor (UICoord const& path) override
107 {
108 if (isnil(tree_) or not path.isPresent(UIC_WINDOW))
109 return Symbol::BOTTOM;
110 if (UIC_FIRST_WINDOW == path.getWindow())
111 return getFirstWindow();
112 if (UIC_CURRENT_WINDOW == path.getWindow())
113 return getCurrentWindow();
114 if (not tree_.hasAttribute(string{path.getWindow()}))
115 return Symbol::BOTTOM;
116 return path.getWindow();
117 }
118
119
121 virtual size_t
122 determineCoverage (UICoord const& path) override
123 {
124 size_t depth = 0;
125 drillDown (tree_, path, path.size(), depth);
126 return depth;
127 }
128
130 virtual ChildIter
131 getChildren (UICoord const& path, size_t pos) override
132 {
133 size_t depth = 0;
134 Rec const& node = drillDown (tree_, path, pos, depth);
135 if (depth != pos)
136 throw error::State(_Fmt{"unable to drill down to depth %d: "
137 "element %s at pos %d in path %s is in "
138 "contradiction to actual UI structure"}
139 % pos
140 % (depth<path.size()? path[depth] : Symbol::BOTTOM)
141 % depth
142 % path
143 );
145 childNavigator (node, depth));
146 }
147
148 private:
149 Literal
151 {
152 return Symbol{*tree_.keys()};
153 }
154 Literal
156 {
157 return Symbol{lib::pull_last (tree_.keys())};
158 } // special convention for unit-tests
159
160 Literal
161 resolveElm (UICoord const& path, size_t depth)
162 {
163 REQUIRE (path.isPresent(depth));
165 : path[depth];
166 }
167
168
169 Rec const&
170 drillDown (Rec const& tree, UICoord const& path, size_t maxDepth, size_t& depth)
171 {
172 if (depth<maxDepth and path.isPresent(depth))
173 {
174 CStr pathElm = resolveElm (path, depth);
175 if (hasNode (tree, pathElm, depth))
176 {
177 ++depth;
178 return drillDown (descendInto(tree,depth-1,pathElm), path, maxDepth, depth);
179 }
180 }
181 return tree;
182 }
183
191 static bool
192 hasNode (Rec const& tree, CStr pathElm, size_t depth)
193 {
194 return depth==UIC_PERSP? pathElm == tree.getType()
195 : tree.hasAttribute(pathElm);
196 }
197
199 static Rec const&
200 descendInto (Rec const& tree, size_t depth, CStr pathElm)
201 {
202 return depth==UIC_PERSP? tree // perspective info is attached as type at the parent node
203 : tree.get(pathElm).data.get<Rec>();
204 }
205
206
207
208
209 /* ==== iterate over siblings with the ability to expand one node's children ==== */
210
215 childNavigator (Rec const& node, size_t depth)
216 {
218 auto internedString = [](string const& id) -> Literal
219 {
220 return Symbol{id};
221 };
222 return depth==UIC_PERSP? buildNavigator (node, depth, singleValIterator (internedString (node.getType())))
223 : buildNavigator (node, depth, transformIterator (node.keys(), internedString));
224 }
225
226
234 template<class PAR>
236 : public PAR
237 {
238 Rec const& pos_;
239 size_t depth_;
240
242 expandChildren() const override
243 {
245 }
246
248 // The design of IterSource attempts to be too clever, and we have to pay for it now...
249 // If IterSource would just work like a StateCore and expose the "current element" via API call,
250 // then we'd be able to retrieve the name of the current child node. Unfortunately it doesn't
251 // and thus we rig a "wire tap" here and capture the node names whenever an iteration happens.
252 //
254
255 using Pos = PAR::Pos;
256
257 virtual Pos
258 firstResult () override
259 {
260 Pos pos = PAR::firstResult();
261 if (pos) currentChild_ = *pos;
262 return pos;
263 }
264
265 virtual void
266 nextResult(Pos& pos) override
267 {
268 PAR::nextResult (pos);
269 if (pos) currentChild_ = *pos;
270 }
272
273
274 public:
275 template<class IT>
276 GenNodeNavigator(Rec const& node, size_t depth, IT&& rawChildIter)
277 : PAR{forward<IT> (rawChildIter)}
278 , pos_{node}
279 , depth_{depth}
280 { }
281 };
282
283
285 template<class IT>
287 buildNavigator (Rec const& node, size_t depth, IT && rawIterator)
288 {
289 return new GenNodeNavigator<
291 TreeStructureNavigator>> {node, depth, forward<IT> (rawIterator)};
292 }
293 };
294
295
296
297}}// namespace stage::interact
298#endif /*STAGE_INTERACT_GEN_NODE_LOCATION_QUERY_H*/
Inline string literal.
Definition symbol.hpp:78
size_t size() const
Token or Atom with distinct identity.
Definition symbol.hpp:120
static Symbol BOTTOM
Definition symbol.hpp:124
Standard implementation of the IterSource interface: a wrapped "Lumiera Forward Iterator".
object-like record of data.
Definition record.hpp:142
Helper to navigate a tree topology represented as GenNode tree.
GenNodeNavigator(Rec const &node, size_t depth, IT &&rawChildIter)
virtual TreeStructureNavigator * expandChildren() const override
Test/Diagnostics: implementation of the LocationQuery-API based on a abstract topological structure g...
virtual Literal determineAnchor(UICoord const &path) override
resolve Anchor against GenNode tree
static bool hasNode(Rec const &tree, CStr pathElm, size_t depth)
does the guiding tree contain the element as requested by the UICoord path?
Literal resolveElm(UICoord const &path, size_t depth)
static TreeStructureNavigator * childNavigator(Rec const &node, size_t depth)
virtual size_t determineCoverage(UICoord const &path) override
evaluate to what extent a UIcoord spec matches the structure given as GenNode tree
Rec const & drillDown(Rec const &tree, UICoord const &path, size_t maxDepth, size_t &depth)
static TreeStructureNavigator * buildNavigator(Rec const &node, size_t depth, IT &&rawIterator)
type rebinding helper to pick up the concrete child iterator type IT
static Rec const & descendInto(Rec const &tree, size_t depth, CStr pathElm)
within tree at level depth descend into the child element designated by pathElm
virtual ChildIter getChildren(UICoord const &path, size_t pos) override
get the sequence of child IDs at a designated position in the backing GenNode tree
Interface to discover a backing structure for the purpose of path navigation and resolution.
decltype(TreeStructureNavigator::buildIterator(0)) ChildIter
Interface to locate and move within a tree shaped structure.
static auto buildIterator(TreeStructureNavigator *source)
build a Lumiera Forward Iterator as front-end and managing Handle for a TreeStructureNavigator or sub...
Describe a location within the UI through structural/topological coordinates.
Definition ui-coord.hpp:131
Literal getWindow() const
Definition ui-coord.hpp:190
bool isPresent(size_t idx) const
Definition ui-coord.hpp:233
A front-end for using printf-style formatting.
Lumiera error handling (C++ interface).
const char * CStr
Definition error.hpp:42
Front-end for printf-style string template interpolation.
Generic building block for tree shaped (meta)data structures.
Building tree expanding and backtracking evaluations within hierarchical scopes.
Extension module to build an opaque data source, accessible as Lumiera Forward Iterator.
Helpers for working with iterators based on the pipeline model.
IT::value_type pull_last(IT iter)
LumieraError< LERR_(STATE)> State
Definition error.hpp:209
const Symbol UIC_FIRST_WINDOW
window spec to refer to the first window of the application
const Symbol UIC_CURRENT_WINDOW
window spec to refer to the current window
Lumiera GTK UI implementation root.
Definition guifacade.cpp:37
STL namespace.
bool isnil(lib::time::Duration const &dur)
Marker types to indicate a literal string and a Symbol.
Evaluation of UI coordinates against a concrete window topology.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...