#include "NasalWidget.hxx"
#include <simgear/canvas/Canvas.hxx>
+#include <simgear/nasal/cppbind/NasalContext.hxx>
#include <simgear/nasal/cppbind/Ghost.hxx>
namespace simgear
//----------------------------------------------------------------------------
NasalWidget::NasalWidget(naRef impl):
- _nasal_impl(impl)
+ Object(impl),
+ _layout_size_hint(32, 32),
+ _layout_min_size(16, 16),
+ _layout_max_size(MAX_SIZE),
+ _user_size_hint(0, 0),
+ _user_min_size(0, 0),
+ _user_max_size(MAX_SIZE)
{
- assert( naIsHash(_nasal_impl.get_naRef()) );
+
}
//----------------------------------------------------------------------------
- void NasalWidget::setGeometry(const SGRect<int>& geom)
+ NasalWidget::~NasalWidget()
{
- if( _geometry == geom )
- return;
-
- _geometry = geom;
+ onRemove();
+ }
- if( _set_geometry )
- _set_geometry(_nasal_impl.get_naRef(), geom);
+ //----------------------------------------------------------------------------
+ void NasalWidget::onRemove()
+ {
+ try
+ {
+ callMethod<void>("onRemove");
+ }
+ catch( std::exception const& ex )
+ {
+ SG_LOG(
+ SG_GUI,
+ SG_WARN,
+ "NasalWidget::onRemove: callback error: '" << ex.what() << "'"
+ );
+ }
}
//----------------------------------------------------------------------------
}
//----------------------------------------------------------------------------
- void NasalWidget::setImpl(naRef obj)
+ void NasalWidget::setHeightForWidthFunc(const HeightForWidthFunc& func)
{
- _nasal_impl.reset(obj);
+ _height_for_width = func;
+ invalidate();
}
//----------------------------------------------------------------------------
- naRef NasalWidget::getImpl() const
+ void NasalWidget::setMinimumHeightForWidthFunc(const HeightForWidthFunc& func)
{
- return _nasal_impl.get_naRef();
+ _min_height_for_width = func;
+ invalidate();
}
//----------------------------------------------------------------------------
void NasalWidget::setSizeHint(const SGVec2i& s)
{
- if( _size_hint == s )
+ if( _user_size_hint == s )
return;
- _size_hint = s;
+ _user_size_hint = s;
// TODO just invalidate size_hint? Probably not a performance issue...
- invalidateParent();
+ invalidate();
}
//----------------------------------------------------------------------------
void NasalWidget::setMinimumSize(const SGVec2i& s)
{
- if( _min_size == s )
+ if( _user_min_size == s )
return;
- _min_size = s;
- invalidateParent();
+ _user_min_size = s;
+ invalidate();
}
//----------------------------------------------------------------------------
void NasalWidget::setMaximumSize(const SGVec2i& s)
{
- if( _max_size == s )
+ if( _user_max_size == s )
return;
- _max_size = s;
- invalidateParent();
+ _user_max_size = s;
+ invalidate();
}
//----------------------------------------------------------------------------
- bool NasalWidget::_set(naContext c, const std::string& key, naRef val)
+ void NasalWidget::setLayoutSizeHint(const SGVec2i& s)
{
- if( !_nasal_impl.valid() )
- return false;
+ if( _layout_size_hint == s )
+ return;
+
+ _layout_size_hint = s;
+ invalidate();
+ }
- nasal::Hash(_nasal_impl.get_naRef(), c).set(key, val);
- return true;
+ //----------------------------------------------------------------------------
+ void NasalWidget::setLayoutMinimumSize(const SGVec2i& s)
+ {
+ if( _layout_min_size == s )
+ return;
+
+ _layout_min_size = s;
+ invalidate();
+ }
+
+ //----------------------------------------------------------------------------
+ void NasalWidget::setLayoutMaximumSize(const SGVec2i& s)
+ {
+ if( _layout_max_size == s )
+ return;
+
+ _layout_max_size = s;
+ invalidate();
+ }
+
+ //----------------------------------------------------------------------------
+ bool NasalWidget::hasHeightForWidth() const
+ {
+ return !_height_for_width.empty() || !_min_height_for_width.empty();
}
//----------------------------------------------------------------------------
{
nasal::Ghost<NasalWidgetRef>::init("canvas.Widget")
.bases<LayoutItemRef>()
- ._set(&NasalWidget::_set)
- .member("parents", &NasalWidget::getParents)
+ .bases<nasal::ObjectRef>()
.method("setSetGeometryFunc", &NasalWidget::setSetGeometryFunc)
+ .method("setMinimumHeightForWidthFunc",
+ &NasalWidget::setMinimumHeightForWidthFunc)
+ .method("setHeightForWidthFunc", &NasalWidget::setHeightForWidthFunc)
.method("setSizeHint", &NasalWidget::setSizeHint)
.method("setMinimumSize", &NasalWidget::setMinimumSize)
- .method("setMaximumSize", &NasalWidget::setMaximumSize);
+ .method("setMaximumSize", &NasalWidget::setMaximumSize)
+ .method("setLayoutSizeHint", &NasalWidget::setLayoutSizeHint)
+ .method("setLayoutMinimumSize", &NasalWidget::setLayoutMinimumSize)
+ .method("setLayoutMaximumSize", &NasalWidget::setLayoutMaximumSize);
nasal::Hash widget_hash = ns.createHash("Widget");
widget_hash.set("new", &f_makeNasalWidget);
}
//----------------------------------------------------------------------------
- naRef NasalWidget::getParents(NasalWidget& w, naContext c)
+ int NasalWidget::callHeightForWidthFunc( const HeightForWidthFunc& hfw,
+ int w ) const
{
- naRef parents[] = { w._nasal_impl.get_naRef() };
- return nasal::to_nasal(c, parents);
+ if( hfw.empty() )
+ return -1;
+
+ naContext c = naNewContext();
+ try
+ {
+ return hfw(nasal::to_nasal(c, const_cast<NasalWidget*>(this)), w);
+ }
+ catch( std::exception const& ex )
+ {
+ SG_LOG(
+ SG_GUI,
+ SG_WARN,
+ "NasalWidget.heightForWidth: callback error: '" << ex.what() << "'"
+ );
+ }
+ naFreeContext(c);
+
+ return -1;
}
//----------------------------------------------------------------------------
SGVec2i NasalWidget::sizeHintImpl() const
{
- return _size_hint;
+ return SGVec2i(
+ _user_size_hint.x() > 0 ? _user_size_hint.x() : _layout_size_hint.x(),
+ _user_size_hint.y() > 0 ? _user_size_hint.y() : _layout_size_hint.y()
+ );
}
//----------------------------------------------------------------------------
SGVec2i NasalWidget::minimumSizeImpl() const
{
- return _min_size;
+ return SGVec2i(
+ _user_min_size.x() > 0 ? _user_min_size.x() : _layout_min_size.x(),
+ _user_min_size.y() > 0 ? _user_min_size.y() : _layout_min_size.y()
+ );
}
//----------------------------------------------------------------------------
SGVec2i NasalWidget::maximumSizeImpl() const
{
- return _max_size;
+ return SGVec2i(
+ _user_max_size.x() < MAX_SIZE.x() ? _user_max_size.x()
+ : _layout_max_size.x(),
+ _user_max_size.y() < MAX_SIZE.y() ? _user_max_size.y()
+ : _layout_max_size.y()
+ );
+ }
+
+
+ //----------------------------------------------------------------------------
+ int NasalWidget::heightForWidthImpl(int w) const
+ {
+ return callHeightForWidthFunc( _height_for_width.empty()
+ ? _min_height_for_width
+ : _height_for_width, w );
+ }
+
+ //----------------------------------------------------------------------------
+ int NasalWidget::minimumHeightForWidthImpl(int w) const
+ {
+ return callHeightForWidthFunc( _min_height_for_width.empty()
+ ? _height_for_width
+ : _min_height_for_width, w );
+ }
+
+
+ //----------------------------------------------------------------------------
+ void NasalWidget::contentsRectChanged(const SGRect<int>& rect)
+ {
+ if( !_set_geometry )
+ return;
+
+ try
+ {
+ nasal::Context c;
+ _set_geometry(nasal::to_nasal(c, this), rect);
+ _flags &= ~LAYOUT_DIRTY;
+ }
+ catch( std::exception const& ex )
+ {
+ SG_LOG(
+ SG_GUI,
+ SG_WARN,
+ "NasalWidget::setGeometry: callback error: '" << ex.what() << "'"
+ );
+ }
+ }
+
+ //----------------------------------------------------------------------------
+ void NasalWidget::visibilityChanged(bool visible)
+ {
+ try
+ {
+ callMethod<void>("visibilityChanged", visible);
+ }
+ catch( std::exception const& ex )
+ {
+ SG_LOG(
+ SG_GUI,
+ SG_WARN,
+ "NasalWidget::visibilityChanged: callback error: '" << ex.what() << "'"
+ );
+ }
}
} // namespace canvas