3 This file is part of libmspgltk
4 Copyright © 2007-2009 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):
34 slider.signal_value_changed.connect(sigc::mem_fun(this, &List::slider_value_changed));
39 void List::append(const string &v)
42 recalculate_parameters();
45 void List::insert(unsigned i, const string &v)
48 throw InvalidParameterValue("Index out of range");
50 items.insert(items.begin()+i, v);
51 recalculate_parameters();
54 void List::remove(unsigned i)
57 throw InvalidParameterValue("Index out of range");
59 items.erase(items.begin()+i);
60 if(sel_index>static_cast<int>(i))
62 else if(sel_index==static_cast<int>(i))
65 recalculate_parameters();
73 recalculate_parameters();
76 void List::set_selected_index(int i)
80 else if(i<static_cast<int>(items.size()))
83 signal_item_selected.emit(sel_index, items[sel_index]);
86 throw InvalidParameterValue("Index out of range");
89 const string &List::get_selected() const
92 throw InvalidState("No selection");
94 return items[sel_index];
97 void List::button_press(int x, int y, unsigned btn)
99 Container::button_press(x, y, btn);
100 if(!click_focus && btn==1)
103 y += items_part->get_margin().top;
105 unsigned i = (geom.h-1-y)/row_height;
106 if(i<n_visible && first+i<items.size())
110 signal_item_selected.emit(sel_index, items[sel_index]);
115 void List::render_special(const Part &part) const
117 if(part.get_name()=="items")
119 const GL::Font &font = *style->get_font();
120 const float font_size = font.get_default_size();
121 const GL::Color &color = style->get_font_color();
122 const Sides &margin = part.get_margin();
124 Geometry pgeom = geom;
125 pgeom.h = row_height;
126 pgeom.w -= margin.left+margin.right;
128 for(unsigned i=0; (i<n_visible && first+i<items.size()); ++i)
131 rgeom.w = static_cast<unsigned>(font.get_string_width(items[first+i])*font_size);
132 rgeom.h = row_height;
133 rgeom.x = margin.left;
134 rgeom.y = geom.h-margin.top-(i+1)*row_height-static_cast<int>(font.get_descent()*font_size);
135 part.get_alignment().apply(rgeom, pgeom);
138 GL::translate(rgeom.x, rgeom.y, 0);
139 GL::scale_uniform(font_size);
140 GL::Immediate imm((GL::COLOR4_UBYTE, GL::TEXCOORD2, GL::VERTEX2));
141 imm.color(color.r, color.g, color.b);
142 font.draw_string(items[first+i], imm);
146 else if(part.get_name()=="selection")
148 if(sel_index>=static_cast<int>(first) && sel_index<static_cast<int>(first+n_visible))
150 const Sides &margin = part.get_margin();
152 Geometry pgeom = geom;
153 pgeom.h = row_height;
154 pgeom.w -= margin.left+margin.right;
156 Geometry rgeom = part.get_geometry();
157 rgeom.y += geom.h-margin.top-row_height*(sel_index-first+1);
158 rgeom.x += margin.left;
159 part.get_alignment().apply(rgeom, pgeom);
162 GL::translate(rgeom.x, rgeom.y, 0);
163 part.get_graphic(state)->render(rgeom.w, rgeom.h);
167 else if(part.get_name()=="slider")
171 void List::on_geometry_change()
175 recalculate_parameters();
178 void List::on_style_change()
183 for(list<Part>::const_iterator i=style->get_parts().begin(); i!=style->get_parts().end(); ++i)
184 if(i->get_name()=="items")
187 const GL::Font &font = *style->get_font();
188 row_height = static_cast<unsigned>((font.get_ascent()-font.get_descent())*font.get_default_size());
190 recalculate_parameters();
193 void List::reposition_slider()
195 for(list<Part>::const_iterator i=style->get_parts().begin(); i!=style->get_parts().end(); ++i)
196 if(i->get_name()=="slider")
198 Geometry sgeom = i->get_geometry();
199 i->get_alignment().apply(sgeom, geom, i->get_margin());
200 slider.set_geometry(sgeom);
204 void List::recalculate_parameters()
209 const Sides &margin = items_part->get_margin();
210 h -= margin.top+margin.bottom;
213 n_visible = h/row_height;
215 if(first+n_visible>items.size())
217 if(items.size()>n_visible)
218 first = items.size()-n_visible;
223 if(items.size()>n_visible)
225 slider.set_range(0, items.size()-n_visible);
226 slider.set_value(items.size()-n_visible-first);
230 slider.set_range(0, 0);
235 void List::slider_value_changed(double value)
237 if(items.size()>n_visible)
238 first = items.size()-n_visible-static_cast<unsigned>(value);
242 List::Loader::Loader(List &l):
245 add("item", &Loader::item);
248 void List::Loader::item(const string &v)
250 dynamic_cast<List &>(wdg).append(v);