1 #include <msp/gl/matrix.h>
2 #include <msp/gl/meshbuilder.h>
24 slider.signal_value_changed.connect(sigc::mem_fun(this, &List::slider_value_changed));
32 void List::autosize_rows(unsigned n)
41 const Sides &margin = items_part->get_margin();
42 const GL::Font &font = style->get_font();
43 float font_size = style->get_font_size();
46 for(vector<string>::iterator i=items.begin(); i!=items.end(); ++i)
48 unsigned w = static_cast<unsigned>(font.get_string_width(*i)*font_size);
49 max_w = max(max_w, w);
52 geom.w = max(geom.w, max_w+margin.left+margin.right);
53 geom.h = max(geom.h, n*row_height+margin.top+margin.bottom);
56 if(const Part *slider_part = style->get_part("slider"))
58 Geometry sgeom = slider_part->get_geometry();
59 if(!sgeom.w || !sgeom.h)
63 sgeom.w = slider.get_geometry().w;
65 sgeom.h = slider.get_geometry().h;
68 const Sides &margin = slider_part->get_margin();
69 geom.w = max(geom.w, sgeom.w+margin.left+margin.right);
70 geom.h = max(geom.h, sgeom.h+margin.top+margin.bottom);
79 void List::autosize_all()
81 autosize_rows(items.size());
84 void List::append(const string &v)
90 void List::insert(unsigned i, const string &v)
93 throw out_of_range("List::insert");
95 items.insert(items.begin()+i, v);
99 void List::remove(unsigned i)
102 throw out_of_range("List::remove");
104 items.erase(items.begin()+i);
105 if(sel_index>static_cast<int>(i))
107 else if(sel_index==static_cast<int>(i))
120 void List::items_changed()
123 signal_autosize_changed.emit();
127 void List::set_selected_index(int i)
131 else if(i<static_cast<int>(items.size()))
134 signal_item_selected.emit(sel_index, items[sel_index]);
138 throw out_of_range("List::set_selected_index");
141 const string &List::get_selected() const
144 throw logic_error("sel_index<0");
146 return items[sel_index];
149 void List::rebuild_special(const Part &part, CachedPart &cache)
151 if(part.get_name()=="items")
153 const Sides &margin = part.get_margin();
154 Geometry pgeom = geom;
155 pgeom.h = row_height+margin.top+margin.bottom;
157 const GL::Font &font = style->get_font();
158 cache.texture = &font.get_texture();
161 GL::MeshBuilder bld(*cache.mesh);
162 bld.color(style->get_font_color());
163 bld.matrix() *= GL::Matrix::translation(margin.left, geom.h-pgeom.h-font.get_descent()*style->get_font_size(), 0);
165 for(unsigned i=0; (i<n_visible && first+i<items.size()); ++i)
168 bld.matrix() *= GL::Matrix::translation(0, -static_cast<int>(row_height), 0);
170 GL::MatrixStack::Push _pushm(bld.matrix());
171 bld.matrix() *= GL::Matrix::scaling(style->get_font_size());
173 style->get_font().build_string(items[first+i], bld);
176 else if(part.get_name()=="selection")
178 if(sel_index>=static_cast<int>(first) && sel_index<static_cast<int>(first+n_visible))
180 const Sides &margin = part.get_margin();
182 Geometry pgeom = geom;
183 pgeom.h = row_height;
184 pgeom.w -= margin.left+margin.right;
186 Geometry rgeom = part.get_geometry();
187 rgeom.y += geom.h-margin.top-row_height*(sel_index-first+1);
188 rgeom.x += margin.left;
189 part.get_alignment().apply(rgeom, pgeom);
191 cache.texture = part.get_graphic(state)->get_texture();
194 GL::MeshBuilder bld(*cache.mesh);
195 bld.matrix() *= GL::Matrix::translation(rgeom.x, rgeom.y, 0);
196 part.get_graphic(state)->build(rgeom.w, rgeom.h, bld);
203 void List::render_special(const Part &part, GL::Renderer &renderer) const
205 if(part.get_name()=="slider")
206 slider.render(renderer);
209 void List::button_press(int x, int y, unsigned btn)
211 Container::button_press(x, y, btn);
212 if(!click_focus && btn==1)
215 y += items_part->get_margin().top;
217 unsigned i = (geom.h-1-y)/row_height;
218 if(i<n_visible && first+i<items.size())
222 signal_item_selected.emit(sel_index, items[sel_index]);
228 void List::on_geometry_change()
235 void List::on_style_change()
245 items_part = style->get_part("items");
247 const GL::Font &font = style->get_font();
248 row_height = static_cast<unsigned>((font.get_ascent()-font.get_descent())*style->get_font_size());
253 void List::reposition_slider()
258 if(const Part *slider_part = style->get_part("slider"))
260 Geometry sgeom = slider_part->get_geometry();
261 slider_part->get_alignment().apply(sgeom, geom, slider_part->get_margin());
262 slider.set_geometry(sgeom);
266 void List::check_view_range()
271 const Sides &margin = items_part->get_margin();
272 h -= margin.top+margin.bottom;
275 n_visible = h/row_height;
277 if(first+n_visible>items.size())
279 if(items.size()>n_visible)
280 first = items.size()-n_visible;
285 if(items.size()>n_visible)
287 slider.set_range(0, items.size()-n_visible);
288 slider.set_value(items.size()-n_visible-first);
292 slider.set_range(0, 0);
297 void List::slider_value_changed(double value)
299 if(items.size()>n_visible)
301 first = items.size()-n_visible-static_cast<unsigned>(value);
307 List::Loader::Loader(List &l):
310 add("item", &Loader::item);
313 void List::Loader::item(const string &v)
315 dynamic_cast<List &>(obj).append(v);