3 This file is part of libmspgltk
4 Copyright © 2007 Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
8 #include <msp/gl/matrix.h>
9 #include <msp/gl/transform.h>
21 List::List(const Resources &r):
27 slider(new VSlider(res)),
31 slider->signal_value_changed.connect(sigc::mem_fun(this, &List::slider_value_changed));
41 void List::append(const string &v)
44 recalculate_parameters();
47 void List::insert(unsigned i, const string &v)
50 throw InvalidParameterValue("Index out of range");
52 items.insert(items.begin()+i, v);
53 recalculate_parameters();
56 void List::remove(unsigned i)
59 throw InvalidParameterValue("Index out of range");
61 items.erase(items.begin()+i);
62 if(sel_index>static_cast<int>(i))
64 else if(sel_index==static_cast<int>(i))
67 recalculate_parameters();
76 const string &List::get_selected() const
79 throw InvalidState("No selection");
81 return items[sel_index];
84 void List::button_press(int x, int y, unsigned btn)
86 if(slider->get_geometry().is_inside(x, y))
88 const Geometry &sgeom=slider->get_geometry();
89 slider->button_press(x-sgeom.x, y-sgeom.y, btn);
94 const GL::Font *const font=style->get_font();
95 const unsigned row_height=static_cast<unsigned>(font->get_default_size());
98 y+=items_part->get_margin().top;
100 unsigned i=(geom.h-1-y)/row_height;
101 if(i<n_visible && first+i<items.size())
105 signal_item_selected.emit(sel_index, items[sel_index]);
110 void List::button_release(int x, int y, unsigned btn)
114 const Geometry &sgeom=slider->get_geometry();
115 slider->button_release(x-sgeom.x, y-sgeom.y, btn);
120 void List::pointer_motion(int x, int y)
124 const Geometry &sgeom=slider->get_geometry();
125 slider->pointer_motion(x-sgeom.x, y-sgeom.y);
129 void List::render_special(const Part &part) const
131 if(part.get_name()=="items")
133 const GL::Font *const font=style->get_font();
134 const float font_size=font->get_default_size();
135 const unsigned row_height=static_cast<unsigned>(font_size);
136 const Sides &margin=part.get_margin();
141 for(unsigned i=0; (i<n_visible && first+i<items.size()); ++i)
144 rgeom.w=static_cast<unsigned>(font->get_string_width(items[first+i])*font_size);
145 rgeom.h=static_cast<unsigned>((font->get_ascent()-font->get_descent())*font_size);
146 rgeom.y=geom.h-margin.top-(i+1)*row_height-static_cast<int>(font->get_descent()*font_size);
147 part.get_alignment().apply(rgeom, pgeom);
150 GL::translate(rgeom.x, rgeom.y, 0);
151 GL::scale_uniform(font_size);
152 font->draw_string(items[first+i]);
156 else if(part.get_name()=="selection")
158 if(sel_index>=static_cast<int>(first) && sel_index<static_cast<int>(first+n_visible))
160 const GL::Font *const font=style->get_font();
161 const float font_size=font->get_default_size();
162 const unsigned row_height=static_cast<unsigned>(font_size);
163 const Sides &margin=part.get_margin();
167 pgeom.w-=margin.left+margin.right;
169 Geometry rgeom=part.get_geometry();
170 rgeom.y+=geom.h-margin.top-row_height*(sel_index-first+1);
171 rgeom.x+=margin.left;
172 part.get_alignment().apply(rgeom, pgeom);
175 GL::translate(rgeom.x, rgeom.y, 0);
176 part.get_graphic(state)->render(rgeom.w, rgeom.h);
180 else if(part.get_name()=="slider")
184 void List::on_geometry_change()
188 recalculate_parameters();
191 void List::on_style_change()
196 for(list<Part>::const_iterator i=style->get_parts().begin(); i!=style->get_parts().end(); ++i)
197 if(i->get_name()=="items")
200 recalculate_parameters();
203 void List::reposition_slider()
205 for(list<Part>::const_iterator i=style->get_parts().begin(); i!=style->get_parts().end(); ++i)
206 if(i->get_name()=="slider")
208 Geometry sgeom=i->get_geometry();
209 i->get_alignment().apply(sgeom, geom, i->get_margin());
210 slider->set_geometry(sgeom);
214 void List::recalculate_parameters()
216 const GL::Font *font=style->get_font();
217 unsigned row_height=static_cast<unsigned>(font->get_default_size());
222 const Sides &margin=items_part->get_margin();
223 h-=margin.top+margin.bottom;
226 n_visible=h/row_height;
228 if(first+n_visible>items.size())
230 if(items.size()>n_visible)
231 first=items.size()-n_visible;
236 if(items.size()>n_visible)
238 slider->set_range(0, items.size()-n_visible);
239 slider->set_value(items.size()-n_visible-first);
243 slider->set_range(0, 0);
244 slider->set_value(0);
248 void List::slider_value_changed(double value)
250 first=items.size()-n_visible-static_cast<unsigned>(value);
254 List::Loader::Loader(List &l):
257 add("item", &Loader::item);
260 void List::Loader::item(const string &v)
262 static_cast<List &>(wdg).append(v);