2 #include <msp/core/maputils.h>
3 #include <msp/core/refptr.h>
6 #include "draghandle.h"
12 #include "indicator.h"
30 input_type = INPUT_NAVIGATION;
39 void Panel::set_layout(Layout *l)
41 l->set_container(*this);
46 void Panel::autosize_special(const Part &part, Geometry &ageom) const
48 if(part.get_name()=="children" && layout)
49 layout->autosize(ageom);
52 void Panel::render_special(const Part &part, GL::Renderer &renderer) const
54 if(part.get_name()=="children")
56 for(list<Container::Child *>::const_iterator i=children.begin(); i!=children.end(); ++i)
57 if((*i)->widget->is_visible())
58 (*i)->widget->render(renderer);
62 bool Panel::navigate(Navigation nav)
64 if(Container::navigate(nav))
67 if(nav==NAV_UP || nav==NAV_DOWN || nav==NAV_LEFT || nav==NAV_RIGHT)
69 int nav_x = (nav==NAV_RIGHT ? 1 : nav==NAV_LEFT ? -1 : 0);
70 int nav_y = (nav==NAV_UP ? 1 : nav==NAV_DOWN ? -1 : 0);
72 int origin_x, origin_y, origin_dim;
75 const Geometry &fgeom = input_focus->get_geometry();
76 origin_x = fgeom.x+(nav_x*0.5+0.5)*fgeom.w;
77 origin_y = fgeom.y+(nav_y*0.5+0.5)*fgeom.h;
78 origin_dim = abs(nav_x)*fgeom.h+abs(nav_y)*fgeom.w;
82 origin_x = geom.w*(0.5-nav_x*0.5);
83 origin_y = geom.h*(0.5-nav_y*0.5);
84 origin_dim = abs(nav_x)*geom.h+abs(nav_y)*geom.w;
87 Widget *sibling = find_next_child(origin_x, origin_y, origin_dim, nav_x, nav_y);
88 if(!sibling && input_focus)
90 const Geometry &fgeom = input_focus->get_geometry();
91 origin_x -= fgeom.w*(nav_x*0.5);
92 origin_y -= fgeom.h*(nav_y*0.5);
93 sibling = find_next_child(origin_x, origin_y, origin_dim, nav_x, nav_y);
98 set_input_focus(sibling);
99 if(Panel *panel = dynamic_cast<Panel *>(sibling))
100 panel->navigate(nav);
108 Widget *Panel::find_next_child(int origin_x, int origin_y, int origin_dim, int nav_x, int nav_y) const
112 for(list<Child *>::const_iterator i=children.begin(); i!=children.end(); ++i)
114 if((*i)->widget==input_focus || !(*i)->widget->is_focusable())
117 const Geometry &cgeom = (*i)->widget->get_geometry();
118 int dx = compute_delta(cgeom.x, cgeom.w, origin_x, origin_dim, nav_x);
119 int dy = compute_delta(cgeom.y, cgeom.h, origin_y, origin_dim, nav_y);
122 if(nav_y && nav_y*dy>=0)
123 score = nav_y*dy+abs(dx)*4;
124 else if(nav_x && nav_x*dx>=0)
125 score = nav_x*dx+abs(dy)*4;
127 if(score>=0 && (!sibling || score<best_score))
129 sibling = (*i)->widget;
137 int Panel::compute_delta(int pos, int dim, int origin_pos, int origin_dim, int nav)
140 return pos+dim-origin_pos;
142 return pos-origin_pos;
143 else if(pos+dim<origin_pos-origin_dim/2)
144 return pos+dim+origin_dim/2-origin_pos;
145 else if(pos>origin_pos+origin_dim/2)
146 return pos-origin_pos-origin_dim/2;
151 void Panel::on_geometry_change()
157 void Panel::on_child_added(Widget &wdg)
161 layout->add_widget(wdg);
162 signal_autosize_changed.emit();
166 void Panel::on_child_removed(Widget &wdg)
170 layout->remove_widget(wdg);
171 signal_autosize_changed.emit();
176 Panel::Loader::Loader(Panel &p, map<string, Widget *> &m):
177 DataFile::DerivedObjectLoader<Panel, Widget::Loader>(p),
181 add("button", &Loader::child<Button>);
182 add("column", &Loader::arrangement<Column>);
183 add("constraint",&Loader::constraint);
184 add("draghandle",&Loader::child<DragHandle>);
185 add("dropdown", &Loader::child<Dropdown>);
186 add("entry", &Loader::child<Entry>);
187 add("expand", &Loader::expand);
188 add("ghost", &Loader::ghost);
189 add("gravity", &Loader::gravity);
190 add("grid", &Loader::grid);
191 add("hslider", &Loader::child<HSlider>);
192 add("image", &Loader::child<Image>);
193 add("indicator", &Loader::child<Indicator>);
194 add("label", &Loader::child<Label>);
195 add("layout", &Loader::layout);
196 add("list", &Loader::child<List>);
197 add("panel", &Loader::panel);
198 add("row", &Loader::arrangement<Row>);
199 add("stack", &Loader::arrangement<Stack>);
200 add("toggle", &Loader::child<Toggle>);
201 add("vslider", &Loader::child<VSlider>);
204 Layout &Panel::Loader::get_layout()
207 obj.set_layout(new Layout);
212 Widget &Panel::Loader::get_last_widget()
215 throw logic_error("no widget loaded");
221 void Panel::Loader::arrangement()
224 ArrangedLoader<T> ldr(*this, arr);
229 void Panel::Loader::child(const string &n)
231 RefPtr<T> chl = new T();
234 last_widget = wdg_map[n] = chl.release();
237 void Panel::Loader::constraint(Layout::ConstraintType type, const string &n)
239 Widget &src = get_last_widget();
240 Widget &tgt = *get_item(wdg_map, n);
241 get_layout().add_constraint(src, type, tgt);
244 void Panel::Loader::expand(bool h, bool v)
246 get_layout().set_expand(get_last_widget(), h, v);
249 void Panel::Loader::ghost(bool g)
251 get_layout().set_ghost(get_last_widget(), g);
254 void Panel::Loader::gravity(int h, int v)
256 get_layout().set_gravity(get_last_widget(), h, v);
259 void Panel::Loader::grid(unsigned cols)
261 Grid grd(get_layout(), cols);
262 ArrangedLoader<Grid> ldr(*this, grd);
266 void Panel::Loader::layout()
268 Layout::Loader ldr(get_layout(), wdg_map);
272 void Panel::Loader::panel(const string &n)
274 RefPtr<Panel> p = new Panel();
275 load_sub(*p, wdg_map);
277 last_widget = wdg_map[n] = p.release();
282 Panel::ArrangedLoader<T>::ArrangedLoader(Loader &ldr, T &arr):
285 add_auxiliary_loader(ldr);
286 add_auxiliary_loader(arr_loader);