]> git.mxchange.org Git - simgear.git/blob - simgear/canvas/layout/NasalWidget.cxx
canvas::Layout: support height-for-width layouting.
[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/Ghost.hxx>
23
24 namespace simgear
25 {
26 namespace canvas
27 {
28
29   //----------------------------------------------------------------------------
30   NasalWidget::NasalWidget(naRef impl):
31     Object(impl)
32   {
33
34   }
35
36   //----------------------------------------------------------------------------
37   void NasalWidget::setGeometry(const SGRect<int>& geom)
38   {
39     if( _geometry == geom )
40       return;
41     _geometry = geom;
42
43     if( !_set_geometry )
44       return;
45
46     naContext c = naNewContext();
47     try
48     {
49       _set_geometry(nasal::to_nasal(c, this), geom);
50     }
51     catch( std::exception const& ex )
52     {
53       SG_LOG(
54         SG_GUI,
55         SG_WARN,
56         "NasalWidget::setGeometry: callback error: '" << ex.what() << "'"
57       );
58     }
59     naFreeContext(c);
60   }
61
62   //----------------------------------------------------------------------------
63   void NasalWidget::setSetGeometryFunc(const SetGeometryFunc& func)
64   {
65     _set_geometry = func;
66   }
67
68   //----------------------------------------------------------------------------
69   void NasalWidget::setHeightForWidthFunc(const HeightForWidthFunc& func)
70   {
71     _height_for_width = func;
72     invalidateParent();
73   }
74
75   //----------------------------------------------------------------------------
76   void NasalWidget::setMinimumHeightForWidthFunc(const HeightForWidthFunc& func)
77   {
78     _min_height_for_width = func;
79     invalidateParent();
80   }
81
82   //----------------------------------------------------------------------------
83   void NasalWidget::setSizeHint(const SGVec2i& s)
84   {
85     if( _size_hint == s )
86       return;
87
88     _size_hint = s;
89
90     // TODO just invalidate size_hint? Probably not a performance issue...
91     invalidateParent();
92   }
93
94   //----------------------------------------------------------------------------
95   void NasalWidget::setMinimumSize(const SGVec2i& s)
96   {
97     if( _min_size == s )
98       return;
99
100     _min_size = s;
101     invalidateParent();
102   }
103
104   //----------------------------------------------------------------------------
105   void NasalWidget::setMaximumSize(const SGVec2i& s)
106   {
107     if( _max_size == s )
108       return;
109
110     _max_size = s;
111     invalidateParent();
112   }
113
114   //----------------------------------------------------------------------------
115   bool NasalWidget::hasHeightForWidth() const
116   {
117     return !_height_for_width.empty() || !_min_height_for_width.empty();
118   }
119
120   //----------------------------------------------------------------------------
121   int NasalWidget::heightForWidth(int w) const
122   {
123     return callHeightForWidthFunc( _height_for_width.empty()
124                                  ? _min_height_for_width
125                                  : _height_for_width, w );
126   }
127
128   //----------------------------------------------------------------------------
129   int NasalWidget::minimumHeightForWidth(int w) const
130   {
131     return callHeightForWidthFunc( _min_height_for_width.empty()
132                                  ? _height_for_width
133                                  : _min_height_for_width, w );
134   }
135
136   //----------------------------------------------------------------------------
137   static naRef f_makeNasalWidget(const nasal::CallContext& ctx)
138   {
139     return ctx.to_nasal(NasalWidgetRef(
140       new NasalWidget( ctx.requireArg<naRef>(0) )
141     ));
142   }
143
144   //----------------------------------------------------------------------------
145   void NasalWidget::setupGhost(nasal::Hash& ns)
146   {
147     nasal::Ghost<NasalWidgetRef>::init("canvas.Widget")
148       .bases<LayoutItemRef>()
149       .bases<nasal::ObjectRef>()
150       .method("setSetGeometryFunc", &NasalWidget::setSetGeometryFunc)
151       .method("setMinimumHeightForWidthFunc",
152                                     &NasalWidget::setMinimumHeightForWidthFunc)
153       .method("setHeightForWidthFunc", &NasalWidget::setHeightForWidthFunc)
154       .method("setSizeHint", &NasalWidget::setSizeHint)
155       .method("setMinimumSize", &NasalWidget::setMinimumSize)
156       .method("setMaximumSize", &NasalWidget::setMaximumSize);
157
158     nasal::Hash widget_hash = ns.createHash("Widget");
159     widget_hash.set("new", &f_makeNasalWidget);
160   }
161
162   //----------------------------------------------------------------------------
163   int NasalWidget::callHeightForWidthFunc( const HeightForWidthFunc& hfw,
164                                            int w ) const
165   {
166     if( hfw.empty() )
167       return -1;
168
169     naContext c = naNewContext();
170     try
171     {
172       return hfw(nasal::to_nasal(c, const_cast<NasalWidget*>(this)), w);
173     }
174     catch( std::exception const& ex )
175     {
176       SG_LOG(
177         SG_GUI,
178         SG_WARN,
179         "NasalWidget.heightForWidth: callback error: '" << ex.what() << "'"
180       );
181     }
182     naFreeContext(c);
183
184     return -1;
185   }
186
187   //----------------------------------------------------------------------------
188   SGVec2i NasalWidget::sizeHintImpl() const
189   {
190     return _size_hint;
191   }
192
193   //----------------------------------------------------------------------------
194   SGVec2i NasalWidget::minimumSizeImpl() const
195   {
196     return _min_size;
197   }
198
199   //----------------------------------------------------------------------------
200   SGVec2i NasalWidget::maximumSizeImpl() const
201   {
202     return _max_size;
203   }
204
205 } // namespace canvas
206 } // namespace simgear