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>
23 List::List(const Resources &r):
35 slider.signal_value_changed.connect(sigc::mem_fun(this, &List::slider_value_changed));
42 float font_size = style->get_font()->get_default_size();
45 for(vector<string>::iterator i=items.begin(); i!=items.end(); ++i)
47 unsigned w = static_cast<unsigned>(style->get_font()->get_string_width(*i)*font_size);
48 geom.w = max(geom.w, w);
51 geom.h = items.size()*row_height;
55 const Sides &margin = items_part->get_margin();
56 geom.w += margin.left+margin.right;
57 geom.h += margin.top+margin.bottom;
61 void List::append(const string &v)
67 void List::insert(unsigned i, const string &v)
70 throw InvalidParameterValue("Index out of range");
72 items.insert(items.begin()+i, v);
76 void List::remove(unsigned i)
79 throw InvalidParameterValue("Index out of range");
81 items.erase(items.begin()+i);
82 if(sel_index>static_cast<int>(i))
84 else if(sel_index==static_cast<int>(i))
98 void List::set_selected_index(int i)
102 else if(i<static_cast<int>(items.size()))
105 signal_item_selected.emit(sel_index, items[sel_index]);
108 throw InvalidParameterValue("Index out of range");
111 const string &List::get_selected() const
114 throw InvalidState("No selection");
116 return items[sel_index];
119 void List::button_press(int x, int y, unsigned btn)
121 Container::button_press(x, y, btn);
122 if(!click_focus && btn==1)
125 y += items_part->get_margin().top;
127 unsigned i = (geom.h-1-y)/row_height;
128 if(i<n_visible && first+i<items.size())
132 signal_item_selected.emit(sel_index, items[sel_index]);
137 void List::render_special(const Part &part) const
139 if(part.get_name()=="items")
141 const Sides &margin = part.get_margin();
142 Geometry pgeom = geom;
143 pgeom.h = row_height+margin.top+margin.bottom;
145 GL::PushMatrix push_mtx;
146 GL::translate(0, geom.h-pgeom.h, 0);
148 for(unsigned i=0; (i<n_visible && first+i<items.size()); ++i)
151 GL::translate(0, -static_cast<int>(row_height), 0);
152 Text(*style, items[first+i]).render(part, pgeom);
155 else if(part.get_name()=="selection")
157 if(sel_index>=static_cast<int>(first) && sel_index<static_cast<int>(first+n_visible))
159 const Sides &margin = part.get_margin();
161 Geometry pgeom = geom;
162 pgeom.h = row_height;
163 pgeom.w -= margin.left+margin.right;
165 Geometry rgeom = part.get_geometry();
166 rgeom.y += geom.h-margin.top-row_height*(sel_index-first+1);
167 rgeom.x += margin.left;
168 part.get_alignment().apply(rgeom, pgeom);
171 GL::translate(rgeom.x, rgeom.y, 0);
172 part.get_graphic(state)->render(rgeom.w, rgeom.h);
176 else if(part.get_name()=="slider")
180 void List::on_geometry_change()
187 void List::on_style_change()
191 items_part = style->get_part("items");
193 const GL::Font &font = *style->get_font();
194 row_height = static_cast<unsigned>((font.get_ascent()-font.get_descent())*font.get_default_size());
199 void List::reposition_slider()
201 if(const Part *slider_part = style->get_part("slider"))
203 Geometry sgeom = slider_part->get_geometry();
204 slider_part->get_alignment().apply(sgeom, geom, slider_part->get_margin());
205 slider.set_geometry(sgeom);
209 void List::check_view_range()
214 const Sides &margin = items_part->get_margin();
215 h -= margin.top+margin.bottom;
218 n_visible = h/row_height;
220 if(first+n_visible>items.size())
222 if(items.size()>n_visible)
223 first = items.size()-n_visible;
228 if(items.size()>n_visible)
230 slider.set_range(0, items.size()-n_visible);
231 slider.set_value(items.size()-n_visible-first);
235 slider.set_range(0, 0);
240 void List::slider_value_changed(double value)
242 if(items.size()>n_visible)
243 first = items.size()-n_visible-static_cast<unsigned>(value);
247 List::Loader::Loader(List &l):
250 add("item", &Loader::item);
253 void List::Loader::item(const string &v)
255 dynamic_cast<List &>(wdg).append(v);