Lumiera 0.pre.04
»edit your freedom«
Loading...
Searching...
No Matches
ui-coord-resolver.cpp
Go to the documentation of this file.
1/*
2 UICoordResolver - resolve UI coordinate spec against actual window topology
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
23#include "lib/util.hpp"
24
25using util::isnil;
26using lib::Symbol;
27
28
29namespace stage {
30namespace interact {
31
32 // emit typeinfo and VTables here....
34
36
39
40
41
42
43 namespace { // Helpers for patch matching algorithm
44
53 : public UICoord
54 {
55 size_t currDepth_;
56
57 public:
59 : UICoord{}
60 , currDepth_{0}
61 { }
62 // inherited copy operations
63
64 UICoord const&
66 {
67 PathArray::truncateTo(currDepth_);
68 return *this;
69 }
70
71 void
72 setAt (size_t depth, Literal newSpec)
73 {
74 Literal* storage = PathArray::expandPosition (depth);
75 PathArray::setContent (storage, newSpec);
76 currDepth_ = depth+1;
77 }
78 };
79
80
81 size_t
83 {
84 size_t pos = uic.size();
85 for ( ; 0 < pos; --pos)
86 {
87 Literal const& elm = uic[pos-1];
88 if (elm == Symbol::ANY or elm == Symbol::EMPTY)
89 break;
90 }
91 return pos;
92 }
93
94
95 }//(End) implementation details
96
97
98
117 bool
119 {
120 // Helper to detect a wildcard match
121 auto wildMatch = [&](Literal patt, Literal curr, size_t depth)
122 {
123 return patt == Symbol::ANY
124 or patt == Symbol::EMPTY
125 or patt == UIC_ELIDED // "existentially quantified"
126 or (isAnchored() and curr == res_.anchor and depth == UIC_WINDOW);
127 }; // transitive argument: assuming res_.anchor was computed for
128 // the same coordinate pattern used here for patch resolution
129 // algorithm state
130 size_t maxDepth = 0;
131 PathManipulator coverage;
132 const size_t coordDepth = this->uic_.size();
133 const size_t minSolutionDepth = find_wildcardFree_suffix (uic_);
134
135 auto searchAlgo = query_.getChildren (uic_, 0)
136 .expandOnIteration()
137 .filter ([&](auto& iter)
138 {
139 size_t depth = iter.depth(); // we are at that depth in target tree
140 if (depth >= coordDepth) // search pattern exhausted without match...
141 return false;
142 Literal patt = uic_[depth]; // pick search pattern component at that depth
143 Literal curr = *iter; // iterator points at current tree position (ID)
144 if (patt == curr or // if either direct match
145 wildMatch(patt,curr,depth)) // or wildcard match
146 {
147 coverage.setAt (depth,curr); // record match rsp. interpolate wildcard into output
148 iter.expandChildren(); // next iteration will match one level down into the tree
149 }
150 return patt == curr // direct match counts as (partial) solution
151 or patt == UIC_ELIDED; // existentially quantified elements also accepted
152 })
153 .filter ([&](auto& iter)
154 {
155 if (iter.depth() < minSolutionDepth)
156 return false; // filter solutions which did not bind all wildcards
157 if (iter.depth()+1 <= maxDepth) // filter for maximum solution length
158 return false;
159 maxDepth = 1 + iter.depth();
160 return true;
161 })
162 .transform ([&](auto&) -> UICoord const&
163 {
164 return coverage.retrieveResult();
165 });
166 // is (partial) coverage possible?
167 // search computes definitive answer!
168 res_.isResolved = true;
169
170 // perform the matching
171 if (isnil (searchAlgo))
172 return false; // no solution found
173
174 while (searchAlgo) // pull first maximal solution
175 {
176 if (not res_.covfefe)
177 res_.covfefe.reset (new UICoord {*searchAlgo});
178 else
179 *res_.covfefe = *searchAlgo;
180 ++searchAlgo;
181 }
182
183 ENSURE (res_.covfefe and res_.covfefe->size() >= 1);
184 res_.anchor = res_.covfefe->getWindow();
185
186 // but depth reflects only that part coverable without wildcards
187 if (res_.depth == 0)
189 if (res_.depth == 0 and res_.anchor)
190 res_.depth = 1;
191
192 // signal success only when total coverage is possible
193 return res_.covfefe->size() == uic_.size();
194 }
195
196
197
198}}// namespace stage::interact
Access point to singletons and other kinds of dependencies designated by type.
Definition depend.hpp:281
Inline string literal.
Definition symbol.hpp:78
size_t size() const
Token or Atom with distinct identity.
Definition symbol.hpp:120
static Symbol ANY
Definition symbol.hpp:122
static Symbol EMPTY
Definition symbol.hpp:123
virtual ChildIter getChildren(UICoord const &path, size_t pos)=0
get the sequence of child components at a designated position in the actual UI
static lib::Depend< LocationQuery > service
access point to global LocationQuery service implementation
virtual size_t determineCoverage(UICoord const &path)=0
evaluate to what extent a UIcoord spec matches the actual UI
virtual ~LocationQuery()
this is an interface
virtual ~TreeStructureNavigator()
this is an interface
bool pathResolution()
Since UICoord path specifications may contain gaps and wildcards, we may attempt to fill in these mis...
bool isAnchored() const
is this path explicitly anchored at an existing window?
Describe a location within the UI through structural/topological coordinates.
Definition ui-coord.hpp:131
Special UI-Coordinate builder to define the solution path step by step while we recurse down into the...
const Symbol UIC_ELIDED
indicate that a component is elided or irrelevant here
Lumiera GTK UI implementation root.
Definition guifacade.cpp:37
bool isnil(lib::time::Duration const &dur)
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...