namespace GLtk {
List::List():
- sel_index(-1),
- first(0),
- n_visible(1),
- row_height(1),
- items_part(0)
+ data(new BasicListData<string>),
+ own_data(true)
{
+ init();
+}
+
+List::List(ListData &d):
+ data(&d),
+ own_data(false)
+{
+ init();
+}
+
+void List::init()
+{
+ sel_index = -1;
+ first = 0;
+ n_visible = 1;
+ row_height = 1;
+ items_part = 0;
+
+ observer = new DataObserver(*this);
+
add(slider);
slider.set_step(1);
slider.signal_value_changed.connect(sigc::mem_fun(this, &List::slider_value_changed));
}
+List::~List()
+{
+ delete observer;
+ if(own_data)
+ delete data;
+}
+
void List::autosize()
{
autosize_rows(5);
float font_size = style->get_font_size();
unsigned max_w = 0;
- for(vector<string>::iterator i=items.begin(); i!=items.end(); ++i)
+ unsigned n_items = data->size();
+ for(unsigned i=0; i<n_items; ++i)
{
- unsigned w = static_cast<unsigned>(font.get_string_width(*i)*font_size);
+ unsigned w = static_cast<unsigned>(font.get_string_width(data->get_string(i))*font_size);
max_w = max(max_w, w);
}
void List::autosize_all()
{
- autosize_rows(items.size());
+ autosize_rows(data->size());
}
-void List::append(const string &v)
+void List::set_data(ListData &d)
{
- items.push_back(v);
- items_changed();
-}
-
-void List::insert(unsigned i, const string &v)
-{
- if(i>items.size())
- throw out_of_range("List::insert");
-
- items.insert(items.begin()+i, v);
- items_changed();
-}
+ delete observer;
+ if(own_data)
+ delete data;
-void List::remove(unsigned i)
-{
- if(i>items.size())
- throw out_of_range("List::remove");
-
- items.erase(items.begin()+i);
- if(sel_index>static_cast<int>(i))
- --sel_index;
- else if(sel_index==static_cast<int>(i))
- sel_index = -1;
+ data = &d;
+ own_data = false;
+ observer = new DataObserver(*this);
items_changed();
}
-void List::clear()
-{
- items.clear();
- sel_index = -1;
- items_changed();
-}
-
void List::items_changed()
{
check_view_range();
{
if(i<0)
sel_index = -1;
- else if(i<static_cast<int>(items.size()))
+ else if(i<static_cast<int>(data->size()))
{
sel_index = i;
- signal_item_selected.emit(sel_index, items[sel_index]);
+ signal_item_selected.emit(sel_index);
rebuild();
}
else
throw out_of_range("List::set_selected_index");
}
-const string &List::get_selected() const
-{
- if(sel_index<0)
- throw logic_error("sel_index<0");
-
- return items[sel_index];
-}
-
void List::rebuild_special(const Part &part, CachedPart &cache)
{
if(part.get_name()=="items")
bld.color(style->get_font_color());
bld.matrix() *= GL::Matrix::translation(margin.left, geom.h-pgeom.h-font.get_descent()*style->get_font_size(), 0);
- for(unsigned i=0; (i<n_visible && first+i<items.size()); ++i)
+ for(unsigned i=0; (i<n_visible && first+i<data->size()); ++i)
{
if(i!=0)
bld.matrix() *= GL::Matrix::translation(0, -static_cast<int>(row_height), 0);
GL::MatrixStack::Push _pushm(bld.matrix());
bld.matrix() *= GL::Matrix::scaling(style->get_font_size());
- style->get_font().build_string(items[first+i], bld);
+ style->get_font().build_string(data->get_string(first+i), bld);
}
}
else if(part.get_name()=="selection")
y += items_part->get_margin().top;
unsigned i = (geom.h-1-y)/row_height;
- if(i<n_visible && first+i<items.size())
+ if(i<n_visible && first+i<data->size())
{
sel_index = first+i;
- signal_item_selected.emit(sel_index, items[sel_index]);
+ signal_item_selected.emit(sel_index);
rebuild();
}
}
n_visible = h/row_height;
- if(first+n_visible>items.size())
+ if(first+n_visible>data->size())
{
- if(items.size()>n_visible)
- first = items.size()-n_visible;
+ if(data->size()>n_visible)
+ first = data->size()-n_visible;
else
first = 0;
}
- if(items.size()>n_visible)
+ if(data->size()>n_visible)
{
- slider.set_range(0, items.size()-n_visible);
- slider.set_value(items.size()-n_visible-first);
+ slider.set_range(0, data->size()-n_visible);
+ slider.set_value(data->size()-n_visible-first);
}
else
{
void List::slider_value_changed(double value)
{
- if(items.size()>n_visible)
+ if(data->size()>n_visible)
{
- first = items.size()-n_visible-static_cast<unsigned>(value);
+ first = data->size()-n_visible-static_cast<unsigned>(value);
rebuild();
}
}
+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_strings.connect(sigc::mem_fun(this, &DataObserver::refresh_strings));
+}
+
+void List::DataObserver::item_added(unsigned i)
+{
+ if(list.sel_index>=static_cast<int>(i))
+ ++list.sel_index;
+
+ 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;
+
+ list.items_changed();
+}
+
+void List::DataObserver::cleared()
+{
+ list.sel_index = -1;
+ list.items_changed();
+}
+
+void List::DataObserver::refresh_strings()
+{
+ list.items_changed();
+}
+
+
List::Loader::Loader(List &l):
Widget::Loader(l)
{
void List::Loader::item(const string &v)
{
- dynamic_cast<List &>(obj).append(v);
+ dynamic_cast<BasicListData<string> &>(*dynamic_cast<List &>(obj).data).append(v);
}
} // namespace GLtk