Lumiera  0.pre.03
»edit your freedom«
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 
25 using util::isnil;
26 using lib::Symbol;
27 
28 
29 namespace stage {
30 namespace 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&
65  retrieveResult()
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
82  find_wildcardFree_suffix (UICoord const& uic)
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)
188  res_.depth = query_.determineCoverage(uic_);
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
Describe a location within the UI through structural/topological coordinates.
Definition: ui-coord.hpp:129
bool filter(Placement< DummyMO > const &candidate)
a filter predicate to pick some objects from a resultset.
inline string literal This is a marker type to indicate that
Definition: symbol.hpp:76
Access point to singletons and other kinds of dependencies designated by type.
Definition: depend.hpp:280
const Symbol UIC_ELIDED
indicate that a component is elided or irrelevant here
Token or Atom with distinct identity.
Definition: symbol.hpp:117
Lumiera GTK UI implementation root.
Definition: guifacade.cpp:37
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
Special UI-Coordinate builder to define the solution path step by step while we recurse down into the...
static lib::Depend< LocationQuery > service
access point to global LocationQuery service implementation
Evaluation of UI coordinates against a concrete window topology.
virtual ~TreeStructureNavigator()
this is an interface
virtual ~LocationQuery()
this is an interface
bool pathResolution()
Since UICoord path specifications may contain gaps and wildcards, we may attempt to fill in these mis...