Lumiera  0.pre.03
»edit your freedom«
w-link.hpp
Go to the documentation of this file.
1 /*
2  W-LINK.hpp - smart-link to GTK widget
3 
4  Copyright (C) Lumiera.org
5  2018, 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 
57 #ifndef STAGE_MODEL_W_LINK_H
58 #define STAGE_MODEL_W_LINK_H
59 
60 
61 #include "lib/error.hpp"
62 #include "lib/format-string.hpp"
63 
64 #include <type_traits>
65 #include <sigc++/trackable.h>
66 
67 
68 namespace stage {
69 namespace model {
70 
71  namespace error = lumiera::error;
72  using error::LUMIERA_ERROR_BOTTOM_VALUE;
73 
74  using util::_Fmt;
75 
76 
87  template<class TAR>
88  class WLink
89  {
90 
91  TAR* widget_;
92 
93 
94  public:
95  ~WLink()
96  {
97  try {
98  this->clear();
99  }
100  ERROR_LOG_AND_IGNORE (stage, "Detaching managed WLink from Widget")
101  }
102  WLink() noexcept
103  : widget_{nullptr}
104  { }
105 
106  explicit
107  WLink (TAR& targetWidget)
108  : widget_{attachTo (targetWidget)}
109  { }
110 
111  WLink (WLink const& r)
112  : widget_{r.widget_? attachTo(*r.widget_) : nullptr}
113  { }
114 
115  WLink (WLink && rr)
116  : widget_{rr.widget_? attachTo(*rr.widget_) : nullptr}
117  {
118  rr.clear();
119  }
120 
121  WLink&
123  {
124  swap (*this, other);
125  return *this;
126  }
127 
136  friend void
137  swap (WLink& l, WLink& r)
138  {
139  TAR* tl = l.widget_;
140  TAR* tr = r.widget_;
141  if (tl == tr) return;
142  r.clear();
143  l.clear();
144  if (tr) l.widget_ = l.attachTo (*tr);
145  if (tl) r.widget_ = r.attachTo (*tl);
146  }
147 
148 
149  explicit
150  operator bool() const
151  {
152  return bool{widget_};
153  }
154 
155  TAR&
156  operator* () const
157  {
158  __ensureAlive();
159  return *widget_;
160  }
161 
162  TAR*
163  operator-> () const
164  {
165  __ensureAlive();
166  return widget_;
167  }
168 
169 
170  bool isValid() const { return bool{*this}; }
171  bool isActive() const { return bool{*this}; }
172 
173 
178  void
180  {
181  if (widget_)
182  widget_->remove_destroy_notify_callback (&widget_);
183  widget_ = nullptr;
184  }
185 
192  void
193  connect (TAR& otherTarget)
194  {
195  if (widget_ == &otherTarget) return;
196  clear();
197  widget_ = attachTo (otherTarget);
198  }
199 
200  private:
201  void
202  __ensureAlive() const
203  {
204  if (not widget_)
205  throw error::State ("zombie widget encountered"
206  , LERR_(BOTTOM_VALUE));
207  }
208 
213  TAR*
214  attachTo (TAR& target)
215  {
216  static_assert (std::is_base_of<sigc::trackable, TAR>()
217  ,"target type required to be sigc::trackable");
218 
219  try {
220  target.add_destroy_notify_callback (&widget_
221  ,[](void* p)
222  {
223  TAR* & widgetPtr = *static_cast<TAR**>(p);
224  ASSERT (widgetPtr);
225  widgetPtr = nullptr;
226  return p;
227  });
228  return &target;
229  }
230  catch (std::exception& problem)
231  {
232  throw error::External (problem, _Fmt{"WLink could not attach to %s. Problem is %s"} % target % problem);
233  }
234  catch (...)
235  {
236  ERROR (stage, "Unknown exception while attaching WLink");
237  throw error::External (_Fmt{"WLink could not attach to %s due to unidentified Problems"} % target);
238  }
239  }
240  };
241 
242 
243 }} // namespace stage::model
244 #endif /*STAGE_MODEL_W_LINK_H*/
#define ERROR_LOG_AND_IGNORE(_FLAG_, _OP_DESCR_)
convenience shortcut for a sequence of catch blocks just logging and consuming an error...
Definition: error.hpp:275
Front-end for printf-style string template interpolation.
A front-end for using printf-style formatting.
Derived specific exceptions within Lumiera&#39;s exception hierarchy.
Definition: error.hpp:199
Lumiera GTK UI implementation root.
Definition: guifacade.cpp:46
Lumiera error handling (C++ interface).