+ max_scroll = items.size();
+ for(unsigned i=items.size(); i-->0; )
+ {
+ unsigned ih = items[i]->get_geometry().h;
+ if(ih<=h)
+ {
+ h -= ih;
+ --max_scroll;
+ }
+ }
+
+ if(first>max_scroll)
+ first = max_scroll;
+
+ slider.set_range(0, max_scroll);
+ slider.set_value(max_scroll-first);
+}
+
+void List::slider_value_changed(double value)
+{
+ if(max_scroll>0)
+ {
+ first = max_scroll-static_cast<unsigned>(value);
+ reposition_items();
+ }
+}
+
+
+List::DataObserver::DataObserver(List &l):
+ list(l)
+{
+ list.data->signal_item_added.connect(sigc::mem_fun(this, &DataObserver::item_added));
+ list.data->signal_item_removed.connect(sigc::mem_fun(this, &DataObserver::item_removed));
+ list.data->signal_cleared.connect(sigc::mem_fun(this, &DataObserver::cleared));
+ list.data->signal_refresh_item.connect(sigc::mem_fun(this, &DataObserver::refresh_item));
+}
+
+void List::DataObserver::item_added(unsigned i)
+{
+ if(list.sel_index>=static_cast<int>(i))
+ ++list.sel_index;
+
+ Item *item = list.create_item(i);
+ list.items.insert(list.items.begin()+i, item);
+ list.items_changed();
+}
+
+void List::DataObserver::item_removed(unsigned i)
+{
+ if(list.sel_index>static_cast<int>(i))
+ --list.sel_index;
+ else if(list.sel_index==static_cast<int>(i))
+ list.sel_index = -1;
+
+ delete list.items[i];
+ list.items.erase(list.items.begin()+i);
+ list.items_changed();
+}
+
+void List::DataObserver::cleared()
+{
+ list.sel_index = -1;
+ for(vector<Item *>::iterator i=list.items.begin(); i!=list.items.end(); ++i)
+ delete *i;
+ list.items.clear();
+ list.items_changed();
+}
+
+void List::DataObserver::refresh_item(unsigned i)
+{
+ delete list.items[i];
+ list.items[i] = list.create_item(i);
+ list.items_changed();
+}
+
+
+void List::Item::autosize_special(const Part &part, Geometry &ageom) const
+{
+ if(part.get_name()=="children")
+ {
+ const Sides &margin = part.get_margin();
+ for(list<Child *>::const_iterator i=children.begin(); i!=children.end(); ++i)
+ {
+ Geometry cgeom;
+ (*i)->widget->autosize(cgeom);
+ ageom.w = max(ageom.w, cgeom.x+cgeom.w+margin.right);
+ ageom.h = max(ageom.h, cgeom.y+cgeom.h+margin.top);
+ }
+ }
+}
+
+void List::Item::set_active(bool a)
+{
+ set_state(ACTIVE, (a ? ACTIVE : NORMAL));
+}