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) Lumiera.org
5  2017, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 * *****************************************************/
22 
23 
32 #include "lib/util.hpp"
33 
34 using util::isnil;
35 using lib::Symbol;
36 
37 
38 namespace stage {
39 namespace interact {
40 
41  // emit typeinfo and VTables here....
43 
45 
48 
49 
50 
51 
52  namespace { // Helpers for patch matching algorithm
53 
62  : public UICoord
63  {
64  size_t currDepth_;
65 
66  public:
68  : UICoord{}
69  , currDepth_{0}
70  { }
71  // inherited copy operations
72 
73  UICoord const&
74  retrieveResult()
75  {
76  PathArray::truncateTo(currDepth_);
77  return *this;
78  }
79 
80  void
81  setAt (size_t depth, Literal newSpec)
82  {
83  Literal* storage = PathArray::expandPosition (depth);
84  PathArray::setContent (storage, newSpec);
85  currDepth_ = depth+1;
86  }
87  };
88 
89 
90  size_t
91  find_wildcardFree_suffix (UICoord const& uic)
92  {
93  size_t pos = uic.size();
94  for ( ; 0 < pos; --pos)
95  {
96  Literal const& elm = uic[pos-1];
97  if (elm == Symbol::ANY or elm == Symbol::EMPTY)
98  break;
99  }
100  return pos;
101  }
102 
103 
104  }//(End) implementation details
105 
106 
107 
126  bool
128  {
129  // Helper to detect a wildcard match
130  auto wildMatch = [&](Literal patt, Literal curr, size_t depth)
131  {
132  return patt == Symbol::ANY
133  or patt == Symbol::EMPTY
134  or patt == UIC_ELIDED // "existentially quantified"
135  or (isAnchored() and curr == res_.anchor and depth == UIC_WINDOW);
136  }; // transitive argument: assuming res_.anchor was computed for
137  // the same coordinate pattern used here for patch resolution
138  // algorithm state
139  size_t maxDepth = 0;
140  PathManipulator coverage;
141  const size_t coordDepth = this->uic_.size();
142  const size_t minSolutionDepth = find_wildcardFree_suffix (uic_);
143 
144  auto searchAlgo = query_.getChildren (uic_, 0)
145  .expandOnIteration()
146  .filter ([&](auto& iter)
147  {
148  size_t depth = iter.depth(); // we are at that depth in target tree
149  if (depth >= coordDepth) // search pattern exhausted without match...
150  return false;
151  Literal patt = uic_[depth]; // pick search pattern component at that depth
152  Literal curr = *iter; // iterator points at current tree position (ID)
153  if (patt == curr or // if either direct match
154  wildMatch(patt,curr,depth)) // or wildcard match
155  {
156  coverage.setAt (depth,curr); // record match rsp. interpolate wildcard into output
157  iter.expandChildren(); // next iteration will match one level down into the tree
158  }
159  return patt == curr // direct match counts as (partial) solution
160  or patt == UIC_ELIDED; // existentially quantified elements also accepted
161  })
162  .filter ([&](auto& iter)
163  {
164  if (iter.depth() < minSolutionDepth)
165  return false; // filter solutions which did not bind all wildcards
166  if (iter.depth()+1 <= maxDepth) // filter for maximum solution length
167  return false;
168  maxDepth = 1 + iter.depth();
169  return true;
170  })
171  .transform ([&](auto&) -> UICoord const&
172  {
173  return coverage.retrieveResult();
174  });
175  // is (partial) coverage possible?
176  // search computes definitive answer!
177  res_.isResolved = true;
178 
179  // perform the matching
180  if (isnil (searchAlgo))
181  return false; // no solution found
182 
183  while (searchAlgo) // pull first maximal solution
184  {
185  if (not res_.covfefe)
186  res_.covfefe.reset (new UICoord {*searchAlgo});
187  else
188  *res_.covfefe = *searchAlgo;
189  ++searchAlgo;
190  }
191 
192  ENSURE (res_.covfefe and res_.covfefe->size() >= 1);
193  res_.anchor = res_.covfefe->getWindow();
194 
195  // but depth reflects only that part coverable without wildcards
196  if (res_.depth == 0)
197  res_.depth = query_.determineCoverage(uic_);
198  if (res_.depth == 0 and res_.anchor)
199  res_.depth = 1;
200 
201  // signal success only when total coverage is possible
202  return res_.covfefe->size() == uic_.size();
203  }
204 
205 
206 
207 }}// namespace stage::interact
Describe a location within the UI through structural/topological coordinates.
Definition: ui-coord.hpp:138
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:85
Access point to singletons and other kinds of dependencies designated by type.
Definition: depend.hpp:289
const Symbol UIC_ELIDED
indicate that a component is elided or irrelevant here
Token or Atom with distinct identity.
Definition: symbol.hpp:126
Lumiera GTK UI implementation root.
Definition: guifacade.cpp:46
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...