Lumiera 0.pre.04~rc.1
»edit your freedom«
Loading...
Searching...
No Matches
ui-location-solver.hpp
Go to the documentation of this file.
1/*
2 UI-LOCATION-SOLVER.hpp - decide upon a possible location for some UI component
3
4 Copyright (C)
5 2018, 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
61#ifndef STAGE_INTERACT_UI_LOCATION_SOLVER_H
62#define STAGE_INTERACT_UI_LOCATION_SOLVER_H
63
64#include "lib/error.hpp"
65#include "lib/symbol.hpp"
66#include "lib/format-util.hpp"
69#include "lib/nocopy.hpp"
70
71#include <utility>
72#include <vector>
73#include <string>
74
75
76namespace stage {
77namespace interact {
78
79 using lib::Literal;
80 using std::string;
81 using std::move;
82
83
84 class LocationQuery;
85 using LocationQueryAccess = std::function<LocationQuery&()>;
86
87
88
89
98 {
101
102
103 LocationClause (UICoord && locationPattern, bool allowCreate =false)
104 : pattern{move (locationPattern)}
105 , createParents{allowCreate}
106 { }
108 : pattern{move (rr.pattern)}
110 { }
111
112 operator string() const;
113 };
114
115
124 {
125 using Clauses = std::vector<LocationClause>;
126
128
129 public:
131 : clauses_{}
132 {
133 this->append (move (firstRule));
134 }
136 : clauses_{move (rr.clauses_)}
137 { }
138
139
141 append (LocationClause && furtherRule)
142 {
143 clauses_.emplace_back (move (furtherRule));
144 return move (*this);
145 }
146
147
149 iterator begin() const { return iterator{clauses_.begin(), clauses_.end()}; }
150 iterator end() const { return iterator(); }
151
152 operator string() const;
153 };
154
155
156
157
158 /* ==== Support of UI-Coordinate notation within the ViewSpec-DSL ==== */
159
166 inline
167 UICoord::Builder::operator LocationClause()
168 {
169 return LocationClause{move(*this), false};
170 }
171
174 inline LocationClause
176 {
177 return LocationClause{move(*this), true};
178 }
179
180
187 inline LocationRule
188 operator or (UICoord::Builder && firstRule, UICoord secondRule)
189 {
190 return LocationRule{move (firstRule)}
191 .append (move (secondRule));
192 }
193
194 inline LocationRule&&
195 operator or (LocationRule && ruleSet, UICoord furtherRule)
196 {
197 ruleSet.append (move (furtherRule));
198 return move(ruleSet);
199 }
200
201
202
203 /* === diagnostics === */
204
205 inline
206 LocationClause::operator string() const
207 {
208 return string{pattern}
209 + (createParents? " create!":"");
210 }
211 inline
212 LocationRule::operator string() const
213 {
214 return "=~\t.. "
215 + util::join(clauses_, "\n\tOR ");
216 }
217
218
219
220
228 {
230
231 public:
232 explicit
234 : getLocationQuery{accessor}
235 { }
236
237 explicit
238 UILocationSolver (LocationQuery& locationQueryService)
239 : getLocationQuery{[&]() -> LocationQuery& { return locationQueryService; }}
240 { }
241
242
256 UICoord
257 solve (LocationRule const& rule, size_t depth, Literal elementTypeID)
258 {
259 for (auto& clause : rule)
260 {
261 // Clauses which do not at least describe an element at parent level
262 // will never lead to a solution and can thus be skipped
263 if (depth+1 < clause.pattern.size()
264 or depth > clause.pattern.size())
265 continue;
266
267 // try to solve the current Clause by matching against real UI topology
268 UICoordResolver resolver{clause.pattern, getLocationQuery()};
269 preprocess (resolver, clause);
270 resolver.coverPartially(); // now either holds a solution or is empty
271
272 if (not isnil(resolver) // Solution found!
273 and (clause.createParents // The "create" case requires only some part to exist,
274 or resolver.isCoveredTotally())) // while in the default case we demand complete coverage
275 {
276 if (depth == clause.pattern.size())
277 // append ID of the new element to be created
278 // unless it's already there (and thus exists)
279 resolver.append (elementTypeID);
280 return move (resolver);
281 // use the first suitable solution and exit
282 }
283 else
284 if (clause.createParents and clause.pattern.isExplicit())
285 // allow creation of a totally new path from scratch
286 // as long as it is complete and explicitly given
287 {
288 if (depth == clause.pattern.size())
289 return clause.pattern.append (elementTypeID);
290 else
291 return clause.pattern;
292 }
293 }
294 //all clauses tried without success...
295 return UICoord();
296 }
297
298 private:
305 void
306 preprocess (UICoordResolver& builder, LocationClause const& clause)
307 {
308 if (clause.createParents
309 and clause.pattern.isComplete())
310 {
312 }
313 }
314 };
315
316
317
318
319}}// namespace stage::interact
320#endif /*STAGE_INTERACT_UI_LOCATION_SOLVER_H*/
Inline string literal.
Definition symbol.hpp:78
Accessing a STL element range through a Lumiera forward iterator, An instance of this iterator adapte...
Interface to discover a backing structure for the purpose of path navigation and resolution.
A rule to determine some location by matching against the UI-tree.
lib::RangeIter< Clauses::const_iterator > iterator
LocationRule && append(LocationClause &&furtherRule)
LocationRule(LocationClause &&firstRule)
std::vector< LocationClause > Clauses
Query and mutate UICoord specifications in relation to actual UI topology.
UICoordResolver && existentiallyQuantify(size_t pos)
mutate to turn a wildcard into existentially quantified.
LocationClause create()
interprets the current (inline) builder contents as create clause, which has the meaning "create a ne...
Describe a location within the UI through structural/topological coordinates.
Definition ui-coord.hpp:131
Service to determine the location of an UI component view.
UILocationSolver(LocationQuery &locationQueryService)
void preprocess(UICoordResolver &builder, LocationClause const &clause)
perform adjustments on the current pattern to support some very specific situations
UILocationSolver(LocationQueryAccess accessor)
UICoord solve(LocationRule const &rule, size_t depth, Literal elementTypeID)
Solve for a location according to the given location rule.
Any copy and copy construction prohibited.
Definition nocopy.hpp:38
Lumiera error handling (C++ interface).
Collection of small helpers and convenience shortcuts for diagnostics & formatting.
std::function< LocationQuery &()> LocationQueryAccess
Lumiera GTK UI implementation root.
Definition guifacade.cpp:37
string join(COLL &&coll, string const &delim=", ")
enumerate a collection's contents, separated by delimiter.
Mix-Ins to allow or prohibit various degrees of copying and cloning.
A single location specification to be matched and fulfilled.
LocationClause(UICoord &&locationPattern, bool allowCreate=false)
Marker types to indicate a literal string and a Symbol.
Evaluation of UI coordinates against a concrete window topology.
A topological addressing scheme to designate structural locations within the UI.