3 This file is part of libmspgltk
4 Copyright © 2007 Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
8 #include <msp/gl/immediate.h>
9 #include <msp/gl/matrix.h>
10 #include <msp/gl/transform.h>
22 List::List(const Resources &r):
29 slider(new VSlider(res)),
33 slider->signal_value_changed.connect(sigc::mem_fun(this, &List::slider_value_changed));
43 void List::append(const string &v)
46 recalculate_parameters();
49 void List::insert(unsigned i, const string &v)
52 throw InvalidParameterValue("Index out of range");
54 items.insert(items.begin()+i, v);
55 recalculate_parameters();
58 void List::remove(unsigned i)
61 throw InvalidParameterValue("Index out of range");
63 items.erase(items.begin()+i);
64 if(sel_index>static_cast<int>(i))
66 else if(sel_index==static_cast<int>(i))
69 recalculate_parameters();
77 recalculate_parameters();
80 void List::set_selected_index(int i)
84 else if(i<static_cast<int>(items.size()))
87 signal_item_selected.emit(sel_index, items[sel_index]);
90 throw InvalidParameterValue("Index out of range");
93 const string &List::get_selected() const
96 throw InvalidState("No selection");
98 return items[sel_index];
101 void List::button_press(int x, int y, unsigned btn)
103 if(slider->get_geometry().is_inside(x, y))
105 const Geometry &sgeom=slider->get_geometry();
106 slider->button_press(x-sgeom.x, y-sgeom.y, btn);
112 y+=items_part->get_margin().top;
114 unsigned i=(geom.h-1-y)/row_height;
115 if(i<n_visible && first+i<items.size())
119 signal_item_selected.emit(sel_index, items[sel_index]);
124 void List::button_release(int x, int y, unsigned btn)
128 const Geometry &sgeom=slider->get_geometry();
129 slider->button_release(x-sgeom.x, y-sgeom.y, btn);
134 void List::pointer_motion(int x, int y)
138 const Geometry &sgeom=slider->get_geometry();
139 slider->pointer_motion(x-sgeom.x, y-sgeom.y);
143 void List::render_special(const Part &part) const
145 if(part.get_name()=="items")
147 const GL::Font &font=*style->get_font();
148 const float font_size=font.get_default_size();
149 const GL::Color &color=style->get_font_color();
150 const Sides &margin=part.get_margin();
154 pgeom.w-=margin.left+margin.right;
156 for(unsigned i=0; (i<n_visible && first+i<items.size()); ++i)
159 rgeom.w=static_cast<unsigned>(font.get_string_width(items[first+i])*font_size);
162 rgeom.y=geom.h-margin.top-(i+1)*row_height-static_cast<int>(font.get_descent()*font_size);
163 part.get_alignment().apply(rgeom, pgeom);
166 GL::translate(rgeom.x, rgeom.y, 0);
167 GL::scale_uniform(font_size);
168 GL::Immediate imm((GL::COLOR4_UBYTE, GL::TEXCOORD2, GL::VERTEX2));
169 imm.color(color.r, color.g, color.b);
170 font.draw_string(items[first+i], imm);
174 else if(part.get_name()=="selection")
176 if(sel_index>=static_cast<int>(first) && sel_index<static_cast<int>(first+n_visible))
178 const Sides &margin=part.get_margin();
182 pgeom.w-=margin.left+margin.right;
184 Geometry rgeom=part.get_geometry();
185 rgeom.y+=geom.h-margin.top-row_height*(sel_index-first+1);
186 rgeom.x+=margin.left;
187 part.get_alignment().apply(rgeom, pgeom);
190 GL::translate(rgeom.x, rgeom.y, 0);
191 part.get_graphic(state)->render(rgeom.w, rgeom.h);
195 else if(part.get_name()=="slider")
199 void List::on_geometry_change()
203 recalculate_parameters();
206 void List::on_style_change()
211 for(list<Part>::const_iterator i=style->get_parts().begin(); i!=style->get_parts().end(); ++i)
212 if(i->get_name()=="items")
215 const GL::Font &font=*style->get_font();
216 row_height=static_cast<unsigned>((font.get_ascent()-font.get_descent())*font.get_default_size());
218 recalculate_parameters();
221 void List::reposition_slider()
223 for(list<Part>::const_iterator i=style->get_parts().begin(); i!=style->get_parts().end(); ++i)
224 if(i->get_name()=="slider")
226 Geometry sgeom=i->get_geometry();
227 i->get_alignment().apply(sgeom, geom, i->get_margin());
228 slider->set_geometry(sgeom);
232 void List::recalculate_parameters()
237 const Sides &margin=items_part->get_margin();
238 h-=margin.top+margin.bottom;
241 n_visible=h/row_height;
243 if(first+n_visible>items.size())
245 if(items.size()>n_visible)
246 first=items.size()-n_visible;
251 if(items.size()>n_visible)
253 slider->set_range(0, items.size()-n_visible);
254 slider->set_value(items.size()-n_visible-first);
258 slider->set_range(0, 0);
259 slider->set_value(0);
263 void List::slider_value_changed(double value)
265 if(items.size()>n_visible)
266 first=items.size()-n_visible-static_cast<unsigned>(value);
270 List::Loader::Loader(List &l):
273 add("item", &Loader::item);
276 void List::Loader::item(const string &v)
278 static_cast<List &>(wdg).append(v);