1 // Glue for GUI layout items implemented in Nasal space
3 // Copyright (C) 2014 Thomas Geymayer <tomgey@gmail.com>
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.
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.
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
19 #include "NasalWidget.hxx"
21 #include <simgear/canvas/Canvas.hxx>
22 #include <simgear/nasal/cppbind/Ghost.hxx>
29 //----------------------------------------------------------------------------
30 NasalWidget::NasalWidget(naRef impl):
32 _layout_size_hint(32, 32),
33 _layout_min_size(16, 16),
34 _layout_max_size(MAX_SIZE),
35 _user_size_hint(0, 0),
37 _user_max_size(MAX_SIZE)
42 //----------------------------------------------------------------------------
43 NasalWidget::~NasalWidget()
48 //----------------------------------------------------------------------------
49 void NasalWidget::invalidate()
51 LayoutItem::invalidate();
52 _flags |= LAYOUT_DIRTY;
55 //----------------------------------------------------------------------------
56 void NasalWidget::setGeometry(const SGRect<int>& geom)
58 if( _geometry != geom )
60 else if( !(_flags & LAYOUT_DIRTY) || !_set_geometry )
63 naContext c = naNewContext();
66 _set_geometry(nasal::to_nasal(c, this), geom);
67 _flags &= ~LAYOUT_DIRTY;
69 catch( std::exception const& ex )
74 "NasalWidget::setGeometry: callback error: '" << ex.what() << "'"
80 //----------------------------------------------------------------------------
81 void NasalWidget::onRemove()
83 if( !_nasal_impl.valid() )
86 typedef boost::function<void(nasal::Me)> Deleter;
88 naContext c = naNewContext();
92 nasal::get_member<Deleter>(c, _nasal_impl.get_naRef(), "onRemove");
94 del(nasal::to_nasal(c, this));
96 catch( std::exception const& ex )
101 "NasalWidget::onRemove: callback error: '" << ex.what() << "'"
107 //----------------------------------------------------------------------------
108 void NasalWidget::setSetGeometryFunc(const SetGeometryFunc& func)
110 _set_geometry = func;
113 //----------------------------------------------------------------------------
114 void NasalWidget::setHeightForWidthFunc(const HeightForWidthFunc& func)
116 _height_for_width = func;
120 //----------------------------------------------------------------------------
121 void NasalWidget::setMinimumHeightForWidthFunc(const HeightForWidthFunc& func)
123 _min_height_for_width = func;
127 //----------------------------------------------------------------------------
128 void NasalWidget::setSizeHint(const SGVec2i& s)
130 if( _user_size_hint == s )
135 // TODO just invalidate size_hint? Probably not a performance issue...
139 //----------------------------------------------------------------------------
140 void NasalWidget::setMinimumSize(const SGVec2i& s)
142 if( _user_min_size == s )
149 //----------------------------------------------------------------------------
150 void NasalWidget::setMaximumSize(const SGVec2i& s)
152 if( _user_max_size == s )
159 //----------------------------------------------------------------------------
160 void NasalWidget::setLayoutSizeHint(const SGVec2i& s)
162 if( _layout_size_hint == s )
165 _layout_size_hint = s;
169 //----------------------------------------------------------------------------
170 void NasalWidget::setLayoutMinimumSize(const SGVec2i& s)
172 if( _layout_min_size == s )
175 _layout_min_size = s;
179 //----------------------------------------------------------------------------
180 void NasalWidget::setLayoutMaximumSize(const SGVec2i& s)
182 if( _layout_max_size == s )
185 _layout_max_size = s;
189 //----------------------------------------------------------------------------
190 bool NasalWidget::hasHeightForWidth() const
192 return !_height_for_width.empty() || !_min_height_for_width.empty();
195 //----------------------------------------------------------------------------
196 int NasalWidget::heightForWidth(int w) const
198 return callHeightForWidthFunc( _height_for_width.empty()
199 ? _min_height_for_width
200 : _height_for_width, w );
203 //----------------------------------------------------------------------------
204 int NasalWidget::minimumHeightForWidth(int w) const
206 return callHeightForWidthFunc( _min_height_for_width.empty()
208 : _min_height_for_width, w );
211 //----------------------------------------------------------------------------
212 static naRef f_makeNasalWidget(const nasal::CallContext& ctx)
214 return ctx.to_nasal(NasalWidgetRef(
215 new NasalWidget( ctx.requireArg<naRef>(0) )
219 //----------------------------------------------------------------------------
220 void NasalWidget::setupGhost(nasal::Hash& ns)
222 nasal::Ghost<NasalWidgetRef>::init("canvas.Widget")
223 .bases<LayoutItemRef>()
224 .bases<nasal::ObjectRef>()
225 .method("setSetGeometryFunc", &NasalWidget::setSetGeometryFunc)
226 .method("setMinimumHeightForWidthFunc",
227 &NasalWidget::setMinimumHeightForWidthFunc)
228 .method("setHeightForWidthFunc", &NasalWidget::setHeightForWidthFunc)
229 .method("setSizeHint", &NasalWidget::setSizeHint)
230 .method("setMinimumSize", &NasalWidget::setMinimumSize)
231 .method("setMaximumSize", &NasalWidget::setMaximumSize)
232 .method("setLayoutSizeHint", &NasalWidget::setLayoutSizeHint)
233 .method("setLayoutMinimumSize", &NasalWidget::setLayoutMinimumSize)
234 .method("setLayoutMaximumSize", &NasalWidget::setLayoutMaximumSize);
236 nasal::Hash widget_hash = ns.createHash("Widget");
237 widget_hash.set("new", &f_makeNasalWidget);
240 //----------------------------------------------------------------------------
241 int NasalWidget::callHeightForWidthFunc( const HeightForWidthFunc& hfw,
247 naContext c = naNewContext();
250 return hfw(nasal::to_nasal(c, const_cast<NasalWidget*>(this)), w);
252 catch( std::exception const& ex )
257 "NasalWidget.heightForWidth: callback error: '" << ex.what() << "'"
265 //----------------------------------------------------------------------------
266 SGVec2i NasalWidget::sizeHintImpl() const
269 _user_size_hint.x() > 0 ? _user_size_hint.x() : _layout_size_hint.x(),
270 _user_size_hint.y() > 0 ? _user_size_hint.y() : _layout_size_hint.y()
274 //----------------------------------------------------------------------------
275 SGVec2i NasalWidget::minimumSizeImpl() const
278 _user_min_size.x() > 0 ? _user_min_size.x() : _layout_min_size.x(),
279 _user_min_size.y() > 0 ? _user_min_size.y() : _layout_min_size.y()
283 //----------------------------------------------------------------------------
284 SGVec2i NasalWidget::maximumSizeImpl() const
287 _user_max_size.x() < MAX_SIZE.x() ? _user_max_size.x()
288 : _layout_max_size.x(),
289 _user_max_size.y() < MAX_SIZE.y() ? _user_max_size.y()
290 : _layout_max_size.y()
294 } // namespace canvas
295 } // namespace simgear