Lumiera 0.pre.04~rc.1
»edit your freedom«
Loading...
Searching...
No Matches
ui-coord-resolver.hpp
Go to the documentation of this file.
1/*
2 UI-COORD-RESOLVER.hpp - 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
106#ifndef STAGE_INTERACT_UI_COORD_RESOLVER_H
107#define STAGE_INTERACT_UI_COORD_RESOLVER_H
108
109#include "lib/error.hpp"
110#include "lib/symbol.hpp"
111#include "lib/format-string.hpp"
113#include "lib/iter-explorer.hpp"
114#include "lib/iter-source.hpp"
115#include "lib/depend.hpp"
116#include "lib/util.hpp"
117
118#include <utility>
119#include <memory>
120
121
122namespace stage {
123namespace interact {
124
125 namespace error = lumiera::error;
126
127 using std::unique_ptr;
128 using util::unConst;
129 using lib::Literal;
130 using lib::Symbol;
131
132
133
134
141 : public lib::IterSource<Literal>
142 {
143 public:
144 virtual ~TreeStructureNavigator();
145
159
160
168 static auto
170 {
171 return lib::explore (source)
172 .expand([](TreeStructureNavigator& parent){ return parent.expandChildren(); });
173 }
174 };
175
176
177
178
179
192 {
193 public:
194 virtual ~LocationQuery();
195
198
199
201
202
214 virtual Literal determineAnchor (UICoord const& path) =0;
215
216
226 virtual size_t determineCoverage (UICoord const& path) =0;
227
239 virtual ChildIter getChildren (UICoord const& path, size_t pos) =0;
240 };
241
242
243
244
245
246
277 : public UICoord::Builder
278 {
279
281 {
282 CStr anchor = nullptr;
283 size_t depth = 0;
284 unique_ptr<UICoord> covfefe{};
285 bool isResolved = false;
286 };
287
290
291 public:
292 UICoordResolver (UICoord const& uic, LocationQuery& queryAPI)
293 : Builder{uic}
294 , query_{queryAPI}
295 , res_{}
296 {
298 }
299
301 : Builder{std::move(uic)}
302 , query_{queryAPI}
303 , res_{}
304 {
306 }
307
308
309 /* === query functions === */
310
314 bool
316 {
317 return res_.anchor
319 }
320
328 bool
329 canAnchor() const
330 {
331 return isAnchored()
332 or (res_.isResolved and res_.covfefe)
333 or unConst(this)->pathResolution()
334 or isAnchored(); // resolution failed, but computed at least an anchor
335 }
336
343 bool
345 {
346 return res_.isResolved
347 and res_.depth > 0;
348 }
349
354 bool
355 isCovered() const
356 {
357 return res_.isResolved
358 and res_.depth == this->uic_.size();
359 }
360
362 bool
364 {
365 return isCovered();
366 }
367
368
378 bool
379 canCover() const
380 {
381 return isCovered() // either explicit coverage known
382 or (res_.isResolved and res_.covfefe) // or previous matching run found (partial) solution
383 or unConst(this)->pathResolution() // perform matching run now to find total coverage
384 or (res_.covfefe); // or at least partial coverage was found
385 }
386
387
388
389 /* === mutation functions === */
390
401 {
402 if (isCoveredPartially() and not res_.covfefe)
403 {
404 ASSERT (res_.anchor); // depth > 0 implies anchorage
405 window (res_.anchor); // thus make this anchor explicit
407 }
408 else if (canCover())
409 {
410 ASSERT (res_.isResolved);
411 REQUIRE (res_.covfefe);
412 res_.depth = res_.covfefe->size();
413 this->uic_ = std::move (*res_.covfefe);
414 res_.covfefe.reset();
415 }
416 else
417 {
418 ASSERT (res_.isResolved);
419 REQUIRE (res_.depth == 0);
420 REQUIRE (not res_.covfefe);
421 truncateTo (0);
422 }
423 ENSURE (isCovered());
424 return std::move (*this);
425 }
426
427
436 {
437 if (isCoveredPartially() and not res_.covfefe)
438 {
439 ASSERT (res_.anchor);
440 window (res_.anchor); // just ensure the anchor info is explicit,
441 } // the rest is already in place and explicit
442 else if (canCover())
443 {
444 ASSERT (res_.isResolved);
445 REQUIRE (res_.covfefe);
446 REQUIRE (uic_.size() >= res_.covfefe->size());
447 res_.depth = res_.covfefe->size();
448 // possibly overwrite placeholders by explicitly resolved info...
449 for (size_t pos = 0; pos < res_.depth; ++pos )
450 overwrite (pos, (*res_.covfefe)[pos]);
451 res_.covfefe.reset();
452 }
453 else
454 {
455 ASSERT (res_.isResolved);
456 REQUIRE (res_.depth == 0);
457 REQUIRE (not res_.covfefe);
458 truncateTo (0);
459 }
460 ENSURE (empty() or (isCoveredPartially() and uic_.isExplicit()));
461 return std::move (*this); // no wildcards remain
462 }
463
464
476 {
477 if (canAnchor())
478 {
480 normalise();
481 }
482 return std::move (*this);
483 }
484
485
486
493 extend (Literal pathExtension)
494 {
495 if (not isCovered())
496 cover();
497 ENSURE (isCovered());
498 append (pathExtension);
499 res_.depth = query_.determineCoverage (this->uic_); // coverage may grow
500 return std::move (*this);
501 }
502
510 extend (UICoord const& partialExtensionSpec)
511 {
512 if (not canCover())
513 uic_ = partialExtensionSpec;
514 else
515 {
516 REQUIRE (res_.isResolved);
517 size_t coverable = res_.covfefe? res_.covfefe->size() : res_.depth;
518 auto newContent = partialExtensionSpec.begin();
519 size_t extensionPos = newContent? partialExtensionSpec.indexOf(*newContent) : coverable;
520 if (coverable > extensionPos)
521 throw error::Invalid (util::_Fmt{"Attempt to extend covered path %s with %s "
522 "would overwrite positions %d to %d (incl)"}
524 % partialExtensionSpec
525 % extensionPos
526 % (coverable-1));
527 cover();
528 for ( ; newContent; ++newContent, ++extensionPos )
529 overwrite (extensionPos, *newContent);
530 normalise();
531 }
532 res_ = Resolution{}; // start over with pristine resolution state
534 canCover();
535 return std::move (*this);
536 }
537
538
550 {
551 if (pos < uic_.size() and not uic_.isPresent(pos))
552 overwrite (pos, UIC_ELIDED);
553 return std::move (*this);
554 }
555
556
557
559 operator string() const { return string(this->uic_); }
560 size_t coverDepth() const { return res_.depth; }
561
562
563
564 private:
572 void
574 {
576 if (not uic_.isExplicit()) return;
578 if (util::contains (this->uic_, UIC_ELIDED)) return; // existentially quantified
579 res_.isResolved = true;
580 }
581
586 bool pathResolution();
587 };
588
589
590
591}}// namespace stage::interact
592#endif /*STAGE_INTERACT_UI_COORD_RESOLVER_H*/
Access point to singletons and other kinds of dependencies designated by type.
Definition depend.hpp:281
Iteration source interface to abstract a data source, which then can be accessed through IterAdapter ...
Inline string literal.
Definition symbol.hpp:78
iterator begin() const
size_t indexOf(Literal const &content) const
reverse lookup of actual path content
size_t size() const
Token or Atom with distinct identity.
Definition symbol.hpp:120
static Symbol BOTTOM
Definition symbol.hpp:124
Interface to discover a backing structure for the purpose of path navigation and resolution.
virtual Literal determineAnchor(UICoord const &path)=0
make the real anchor point explicit.
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
decltype(TreeStructureNavigator::buildIterator(0)) ChildIter
virtual ~LocationQuery()
this is an interface
Interface to locate and move within a tree shaped structure.
virtual TreeStructureNavigator * expandChildren() const =0
expand into exploration of child elements at "current position".
static auto buildIterator(TreeStructureNavigator *source)
build a Lumiera Forward Iterator as front-end and managing Handle for a TreeStructureNavigator or sub...
virtual ~TreeStructureNavigator()
this is an interface
Query and mutate UICoord specifications in relation to actual UI topology.
bool isCovered() const
this path is completely covered by the currently existing UI structure;
bool isCoveredTotally() const
synonymous to isCovered()
bool pathResolution()
Since UICoord path specifications may contain gaps and wildcards, we may attempt to fill in these mis...
UICoordResolver(UICoord const &uic, LocationQuery &queryAPI)
UICoordResolver && existentiallyQuantify(size_t pos)
mutate to turn a wildcard into existentially quantified.
bool isAnchored() const
is this path explicitly anchored at an existing window?
bool canAnchor() const
determine if a mutation is possible to anchor the path explicitly
UICoordResolver && cover()
mutate the path to get it totally covered
UICoordResolver && anchor()
mutate the window part of the path such as to make the anchorage explicit, if possible
UICoordResolver && extend(UICoord const &partialExtensionSpec)
mutate the path and extend it with components at fixed positions
UICoordResolver && extend(Literal pathExtension)
mutate the path to extend it while keeping it partially covered
UICoordResolver(UICoord &&uic, LocationQuery &queryAPI)
bool canCover() const
determine if a mutation is possible to get the path (partially) covered.
bool isCoveredPartially() const
is this path at least partially covered? A covered path describes an access path through widgets actu...
UICoordResolver && coverPartially()
mutate the path by resolving all wildcards to achieve partial coverage
void attempt_trivialResolution()
establish a trivial anchorage and coverage, if possible.
Builder && overwrite(size_t depth, Literal newSpec)
Definition ui-coord.hpp:644
Builder && window(Literal windowID)
change UI coordinate spec to define it to be rooted within the given window
Definition ui-coord.hpp:531
Builder && truncateTo(size_t depth)
possibly shorten this path specification to a limited depth
Definition ui-coord.hpp:625
Builder && append(Literal elm)
augment UI coordinates by appending a further component at the end.
Definition ui-coord.hpp:592
Describe a location within the UI through structural/topological coordinates.
Definition ui-coord.hpp:131
Builder rebuild() const
Definition ui-coord.hpp:755
bool isPresent(size_t idx) const
Definition ui-coord.hpp:233
A front-end for using printf-style formatting.
Singleton services and Dependency Injection.
Lumiera error handling (C++ interface).
const char * CStr
Definition error.hpp:42
Front-end for printf-style string template interpolation.
Building tree expanding and backtracking evaluations within hierarchical scopes.
Extension module to build an opaque data source, accessible as Lumiera Forward Iterator.
auto explore(IT &&srcSeq)
start building a IterExplorer by suitably wrapping the given iterable source.
LumieraError< LERR_(INVALID)> Invalid
Definition error.hpp:211
const Symbol UIC_ELIDED
indicate that a component is elided or irrelevant here
Lumiera GTK UI implementation root.
Definition guifacade.cpp:37
STL namespace.
bool contains(MAP &map, typename MAP::key_type const &key)
shortcut for containment test on a map
Definition util.hpp:230
OBJ * unConst(const OBJ *)
shortcut to save some typing when having to define const and non-const variants of member functions
Definition util.hpp:358
Marker types to indicate a literal string and a Symbol.
A topological addressing scheme to designate structural locations within the UI.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...