]> git.mxchange.org Git - simgear.git/blob - simgear/canvas/layout/NasalWidget.cxx
Fixes for error handling in NetChannel
[simgear.git] / simgear / canvas / layout / NasalWidget.cxx
1 // Glue for GUI layout items implemented in Nasal space
2 //
3 // Copyright (C) 2014  Thomas Geymayer <tomgey@gmail.com>
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Library General Public
7 // License as published by the Free Software Foundation; either
8 // version 2 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 // Library General Public License for more details.
14 //
15 // You should have received a copy of the GNU Library General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA
18
19 #include "NasalWidget.hxx"
20
21 #include <simgear/canvas/Canvas.hxx>
22 #include <simgear/nasal/cppbind/NasalContext.hxx>
23 #include <simgear/nasal/cppbind/Ghost.hxx>
24
25 namespace simgear
26 {
27 namespace canvas
28 {
29
30   //----------------------------------------------------------------------------
31   NasalWidget::NasalWidget(naRef impl):
32     Object(impl),
33     _layout_size_hint(32, 32),
34     _layout_min_size(16, 16),
35     _layout_max_size(MAX_SIZE),
36     _user_size_hint(0, 0),
37     _user_min_size(0, 0),
38     _user_max_size(MAX_SIZE)
39   {
40
41   }
42
43   //----------------------------------------------------------------------------
44   NasalWidget::~NasalWidget()
45   {
46     onRemove();
47   }
48
49   //----------------------------------------------------------------------------
50   void NasalWidget::onRemove()
51   {
52     try
53     {
54       callMethod<void>("onRemove");
55     }
56     catch( std::exception const& ex )
57     {
58       SG_LOG(
59         SG_GUI,
60         SG_WARN,
61         "NasalWidget::onRemove: callback error: '" << ex.what() << "'"
62       );
63     }
64   }
65
66   //----------------------------------------------------------------------------
67   void NasalWidget::setSetGeometryFunc(const SetGeometryFunc& func)
68   {
69     _set_geometry = func;
70   }
71
72   //----------------------------------------------------------------------------
73   void NasalWidget::setHeightForWidthFunc(const HeightForWidthFunc& func)
74   {
75     _height_for_width = func;
76     invalidate();
77   }
78
79   //----------------------------------------------------------------------------
80   void NasalWidget::setMinimumHeightForWidthFunc(const HeightForWidthFunc& func)
81   {
82     _min_height_for_width = func;
83     invalidate();
84   }
85
86   //----------------------------------------------------------------------------
87   void NasalWidget::setSizeHint(const SGVec2i& s)
88   {
89     if( _user_size_hint == s )
90       return;
91
92     _user_size_hint = s;
93
94     // TODO just invalidate size_hint? Probably not a performance issue...
95     invalidate();
96   }
97
98   //----------------------------------------------------------------------------
99   void NasalWidget::setMinimumSize(const SGVec2i& s)
100   {
101     if( _user_min_size == s )
102       return;
103
104     _user_min_size = s;
105     invalidate();
106   }
107
108   //----------------------------------------------------------------------------
109   void NasalWidget::setMaximumSize(const SGVec2i& s)
110   {
111     if( _user_max_size == s )
112       return;
113
114     _user_max_size = s;
115     invalidate();
116   }
117
118   //----------------------------------------------------------------------------
119   void NasalWidget::setLayoutSizeHint(const SGVec2i& s)
120   {
121     if( _layout_size_hint == s )
122       return;
123
124     _layout_size_hint = s;
125     invalidate();
126   }
127
128   //----------------------------------------------------------------------------
129   void NasalWidget::setLayoutMinimumSize(const SGVec2i& s)
130   {
131     if( _layout_min_size == s )
132       return;
133
134     _layout_min_size = s;
135     invalidate();
136   }
137
138   //----------------------------------------------------------------------------
139   void NasalWidget::setLayoutMaximumSize(const SGVec2i& s)
140   {
141     if( _layout_max_size == s )
142       return;
143
144     _layout_max_size = s;
145     invalidate();
146   }
147
148   //----------------------------------------------------------------------------
149   bool NasalWidget::hasHeightForWidth() const
150   {
151     return !_height_for_width.empty() || !_min_height_for_width.empty();
152   }
153
154   //----------------------------------------------------------------------------
155   static naRef f_makeNasalWidget(const nasal::CallContext& ctx)
156   {
157     return ctx.to_nasal(NasalWidgetRef(
158       new NasalWidget( ctx.requireArg<naRef>(0) )
159     ));
160   }
161
162   //----------------------------------------------------------------------------
163   void NasalWidget::setupGhost(nasal::Hash& ns)
164   {
165     nasal::Ghost<NasalWidgetRef>::init("canvas.Widget")
166       .bases<LayoutItemRef>()
167       .bases<nasal::ObjectRef>()
168       .method("setSetGeometryFunc", &NasalWidget::setSetGeometryFunc)
169       .method("setMinimumHeightForWidthFunc",
170                                     &NasalWidget::setMinimumHeightForWidthFunc)
171       .method("setHeightForWidthFunc", &NasalWidget::setHeightForWidthFunc)
172       .method("setSizeHint", &NasalWidget::setSizeHint)
173       .method("setMinimumSize", &NasalWidget::setMinimumSize)
174       .method("setMaximumSize", &NasalWidget::setMaximumSize)
175       .method("setLayoutSizeHint", &NasalWidget::setLayoutSizeHint)
176       .method("setLayoutMinimumSize", &NasalWidget::setLayoutMinimumSize)
177       .method("setLayoutMaximumSize", &NasalWidget::setLayoutMaximumSize);
178
179     nasal::Hash widget_hash = ns.createHash("Widget");
180     widget_hash.set("new", &f_makeNasalWidget);
181   }
182
183   //----------------------------------------------------------------------------
184   int NasalWidget::callHeightForWidthFunc( const HeightForWidthFunc& hfw,
185                                            int w ) const
186   {
187     if( hfw.empty() )
188       return -1;
189
190     naContext c = naNewContext();
191     try
192     {
193       return hfw(nasal::to_nasal(c, const_cast<NasalWidget*>(this)), w);
194     }
195     catch( std::exception const& ex )
196     {
197       SG_LOG(
198         SG_GUI,
199         SG_WARN,
200         "NasalWidget.heightForWidth: callback error: '" << ex.what() << "'"
201       );
202     }
203     naFreeContext(c);
204
205     return -1;
206   }
207
208   //----------------------------------------------------------------------------
209   SGVec2i NasalWidget::sizeHintImpl() const
210   {
211     return SGVec2i(
212       _user_size_hint.x() > 0 ? _user_size_hint.x() : _layout_size_hint.x(),
213       _user_size_hint.y() > 0 ? _user_size_hint.y() : _layout_size_hint.y()
214     );
215   }
216
217   //----------------------------------------------------------------------------
218   SGVec2i NasalWidget::minimumSizeImpl() const
219   {
220     return SGVec2i(
221       _user_min_size.x() > 0 ? _user_min_size.x() : _layout_min_size.x(),
222       _user_min_size.y() > 0 ? _user_min_size.y() : _layout_min_size.y()
223     );
224   }
225
226   //----------------------------------------------------------------------------
227   SGVec2i NasalWidget::maximumSizeImpl() const
228   {
229     return SGVec2i(
230       _user_max_size.x() < MAX_SIZE.x() ? _user_max_size.x()
231                                         : _layout_max_size.x(),
232       _user_max_size.y() < MAX_SIZE.y() ? _user_max_size.y()
233                                         : _layout_max_size.y()
234     );
235   }
236
237
238   //----------------------------------------------------------------------------
239   int NasalWidget::heightForWidthImpl(int w) const
240   {
241     return callHeightForWidthFunc( _height_for_width.empty()
242                                  ? _min_height_for_width
243                                  : _height_for_width, w );
244   }
245
246   //----------------------------------------------------------------------------
247   int NasalWidget::minimumHeightForWidthImpl(int w) const
248   {
249     return callHeightForWidthFunc( _min_height_for_width.empty()
250                                  ? _height_for_width
251                                  : _min_height_for_width, w );
252   }
253
254
255   //----------------------------------------------------------------------------
256   void NasalWidget::contentsRectChanged(const SGRect<int>& rect)
257   {
258     if( !_set_geometry )
259       return;
260
261     try
262     {
263       nasal::Context c;
264       _set_geometry(nasal::to_nasal(c, this), rect);
265       _flags &= ~LAYOUT_DIRTY;
266     }
267     catch( std::exception const& ex )
268     {
269       SG_LOG(
270         SG_GUI,
271         SG_WARN,
272         "NasalWidget::setGeometry: callback error: '" << ex.what() << "'"
273       );
274     }
275   }
276
277   //----------------------------------------------------------------------------
278   void NasalWidget::visibilityChanged(bool visible)
279   {
280     try
281     {
282       callMethod<void>("visibilityChanged", visible);
283     }
284     catch( std::exception const& ex )
285     {
286       SG_LOG(
287         SG_GUI,
288         SG_WARN,
289         "NasalWidget::visibilityChanged: callback error: '" << ex.what() << "'"
290       );
291     }
292   }
293
294 } // namespace canvas
295 } // namespace simgear