]> git.tdb.fi Git - libs/gltk.git/blobdiff - source/list.cpp
Fix a segfault when refreshing an item in a list with MultiColumnItems
[libs/gltk.git] / source / list.cpp
index 042eb20ab7b85dbd052d3274351b03287c09614e..14c779f0f579dc236eae5049e5c4720e94760591 100644 (file)
@@ -110,9 +110,8 @@ void List::set_data(ListData &d)
 
 void List::items_changed()
 {
-       check_view_range();
        signal_autosize_changed.emit();
-       reposition_items();
+       rebuild();
 }
 
 List::Item *List::create_item(unsigned index)
@@ -123,7 +122,8 @@ List::Item *List::create_item(unsigned index)
        else
                item = new BasicItem(data->get_string(index));
        add(*item);
-       item->signal_autosize_changed.connect(sigc::mem_fun(this, &List::item_autosize_changed));
+       item->autosize();
+       item->signal_autosize_changed.connect(sigc::bind(sigc::mem_fun(this, &List::item_autosize_changed), item));
        return item;
 }
 
@@ -162,6 +162,38 @@ void List::rebuild_special(const Part &part)
 {
        if(part.get_name()=="slider")
                reposition_child(slider, part);
+       else if(part.get_name()=="items")
+       {
+               const Sides &margin = part.get_margin();
+               unsigned w = geom.w-min(geom.w, margin.left+margin.right);
+               unsigned y = geom.h-min(geom.h, margin.top);
+               for(unsigned i=0; i<items.size(); ++i)
+               {
+                       if(i<first || !y)
+                               items[i]->set_visible(false);
+                       else
+                       {
+                               Geometry igeom = items[i]->get_geometry();
+                               if(igeom.h+margin.bottom<=y)
+                               {
+                                       items[i]->set_visible(true);
+                                       y -= igeom.h;
+                                       igeom.x = margin.left;
+                                       igeom.y = y;
+                                       igeom.w = w;
+                                       items[i]->set_geometry(igeom);
+                               }
+                               else
+                               {
+                                       items[i]->set_visible(false);
+                                       y = 0;
+                               }
+                       }
+               }
+
+               check_view_range();
+       }
+
        Widget::rebuild_special(part);
 }
 
@@ -190,64 +222,11 @@ void List::button_press(int x, int y, unsigned btn)
        }
 }
 
-void List::on_geometry_change()
-{
-       reposition_items();
-
-       check_view_range();
-}
-
-void List::on_style_change()
-{
-       if(!style)
-               return;
-
-       reposition_items();
-
-       check_view_range();
-}
-
-void List::item_autosize_changed()
+void List::item_autosize_changed(Item *item)
 {
+       item->autosize();
        signal_autosize_changed.emit();
-       reposition_items();
-}
-
-void List::reposition_items()
-{
-       if(!style)
-               return;
-
-       if(const Part *items_part = style->get_part("items"))
-       {
-               const Sides &margin = items_part->get_margin();
-               unsigned w = geom.w-min(geom.w, margin.left+margin.right);
-               unsigned y = geom.h-min(geom.h, margin.top);
-               for(unsigned i=0; i<items.size(); ++i)
-               {
-                       if(i<first || !y)
-                               items[i]->set_visible(false);
-                       else
-                       {
-                               Geometry igeom;
-                               items[i]->autosize(igeom);
-                               if(igeom.h+margin.bottom<=y)
-                               {
-                                       items[i]->set_visible(true);
-                                       y -= igeom.h;
-                                       igeom.x = margin.left;
-                                       igeom.y = y;
-                                       igeom.w = w;
-                                       items[i]->set_geometry(igeom);
-                               }
-                               else
-                               {
-                                       items[i]->set_visible(false);
-                                       y = 0;
-                               }
-                       }
-               }
-       }
+       rebuild();
 }
 
 void List::check_view_range()
@@ -285,7 +264,7 @@ void List::slider_value_changed(double value)
        if(max_scroll>0)
        {
                first = max_scroll-static_cast<unsigned>(value);
-               reposition_items();
+               rebuild();
        }
 }
 
@@ -333,6 +312,8 @@ void List::DataObserver::cleared()
 void List::DataObserver::refresh_item(unsigned i)
 {
        delete list.items[i];
+       // Avoid stale pointer while create_item is executing
+       list.items[i] = 0;
        list.items[i] = list.create_item(i);
        list.items_changed();
 }