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)
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 
48 #ifndef STAGE_MODEL_W_LINK_H
49 #define STAGE_MODEL_W_LINK_H
50 
51 
52 #include "lib/error.hpp"
53 #include "lib/format-string.hpp"
54 
55 #include <type_traits>
56 #include <sigc++/trackable.h>
57 
58 
59 namespace stage {
60 namespace model {
61 
62  namespace error = lumiera::error;
63  using error::LUMIERA_ERROR_BOTTOM_VALUE;
64 
65  using util::_Fmt;
66 
67 
78  template<class TAR>
79  class WLink
80  {
81 
82  TAR* widget_;
83 
84 
85  public:
86  ~WLink()
87  {
88  try {
89  this->clear();
90  }
91  ERROR_LOG_AND_IGNORE (stage, "Detaching managed WLink from Widget")
92  }
93  WLink() noexcept
94  : widget_{nullptr}
95  { }
96 
97  explicit
98  WLink (TAR& targetWidget)
99  : widget_{attachTo (targetWidget)}
100  { }
101 
102  WLink (WLink const& r)
103  : widget_{r.widget_? attachTo(*r.widget_) : nullptr}
104  { }
105 
106  WLink (WLink && rr)
107  : widget_{rr.widget_? attachTo(*rr.widget_) : nullptr}
108  {
109  rr.clear();
110  }
111 
112  WLink&
114  {
115  swap (*this, other);
116  return *this;
117  }
118 
127  friend void
128  swap (WLink& l, WLink& r)
129  {
130  TAR* tl = l.widget_;
131  TAR* tr = r.widget_;
132  if (tl == tr) return;
133  r.clear();
134  l.clear();
135  if (tr) l.widget_ = l.attachTo (*tr);
136  if (tl) r.widget_ = r.attachTo (*tl);
137  }
138 
139 
140  explicit
141  operator bool() const
142  {
143  return bool{widget_};
144  }
145 
146  TAR&
147  operator* () const
148  {
149  __ensureAlive();
150  return *widget_;
151  }
152 
153  TAR*
154  operator-> () const
155  {
156  __ensureAlive();
157  return widget_;
158  }
159 
160 
161  bool isValid() const { return bool{*this}; }
162  bool isActive() const { return bool{*this}; }
163 
164 
169  void
171  {
172  if (widget_)
173  widget_->remove_destroy_notify_callback (&widget_);
174  widget_ = nullptr;
175  }
176 
183  void
184  connect (TAR& otherTarget)
185  {
186  if (widget_ == &otherTarget) return;
187  clear();
188  widget_ = attachTo (otherTarget);
189  }
190 
191  private:
192  void
193  __ensureAlive() const
194  {
195  if (not widget_)
196  throw error::State ("zombie widget encountered"
197  , LERR_(BOTTOM_VALUE));
198  }
199 
204  TAR*
205  attachTo (TAR& target)
206  {
207  static_assert (std::is_base_of<sigc::trackable, TAR>()
208  ,"target type required to be sigc::trackable");
209 
210  try {
211  target.add_destroy_notify_callback (&widget_
212  ,[](void* p)
213  {
214  TAR* & widgetPtr = *static_cast<TAR**>(p);
215  ASSERT (widgetPtr);
216  widgetPtr = nullptr;
217  return p;
218  });
219  return &target;
220  }
221  catch (std::exception& problem)
222  {
223  throw error::External (problem, _Fmt{"WLink could not attach to %s. Problem is %s"} % target % problem);
224  }
225  catch (...)
226  {
227  ERROR (stage, "Unknown exception while attaching WLink");
228  throw error::External (_Fmt{"WLink could not attach to %s due to unidentified Problems"} % target);
229  }
230  }
231  };
232 
233 
234 }} // namespace stage::model
235 #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:266
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:190
Lumiera GTK UI implementation root.
Definition: guifacade.cpp:37
Lumiera error handling (C++ interface).