Re: TreeView speedup
- From: "Andrew E. Makeev" <andrew solvo ru>
- To: =?koi8-r?q?Olaf_Fr=B1czyk?= <olaf cbk poznan pl>
- Cc: gtkmm-main <gtkmm-list gnome org>, GTK-MAIN <gtk-list gnome org>
- Subject: Re: TreeView speedup
- Date: Fri, 28 Mar 2003 14:53:01 +0300
On Mon, 2003-03-24 at 11:41, Andrew E. Makeev wrote:
2. Wrote our own simple TextRenderer with "cached" Pango::Layout where
only text could be changed.
Test case: 10000 rows with 4 string, 4 int, 4 double, 4 bool columns.
TreeView was filled with values in 3-4 x times faster. (8-9 sec
against 30 sec).
Hi,
Could you post code for these improvements?
I just use CList, because of TreeView being so slow.
But I would like to use TreeView, and it would be easier for me to write
TextRenderer if I see something similar.
Well, here is test sample with simple text renderer (column size is not
handled well though).
-andrew
#include <gtkmm.h>
#include <gtk/gtkliststore.h>
class CellRendererTextSimple : public Gtk::CellRenderer
{
public:
CellRendererTextSimple ();
virtual ~CellRendererTextSimple ()
{
}
Glib::PropertyProxy<Glib::ustring> property_text();
protected:
virtual void get_size_vfunc (Gtk::Widget& widget,
const Gdk::Rectangle* cell_area,
int* x_offset,
int* y_offset,
int* width,
int* height);
virtual void render_vfunc (const Glib::RefPtr<Gdk::Window>& window,
Gtk::Widget& widget,
const Gdk::Rectangle& background_area,
const Gdk::Rectangle& cell_area,
const Gdk::Rectangle& expose_area,
Gtk::CellRendererState flags);
private:
Glib::Property<Glib::ustring> property_text_;
Glib::RefPtr< Pango::Layout > m_ptrLayout;
bool m_needLayout;
};
CellRendererTextSimple::CellRendererTextSimple () :
Glib::ObjectBase (typeid(CellRendererTextSimple)),
Gtk::CellRenderer (),
property_text_ (*this, "text", ""),
m_needLayout (true)
{
property_mode () = Gtk::CELL_RENDERER_MODE_INERT;
property_xpad () = 2;
property_ypad () = 2;
property_xalign () = 0.0;
property_yalign () = 0.5;
}
Glib::PropertyProxy<Glib::ustring> CellRendererTextSimple::property_text ()
{
return property_text_.get_proxy();
}
void CellRendererTextSimple::get_size_vfunc
(Gtk::Widget& widget,
const Gdk::Rectangle* cell_area,
int* x_offset,
int* y_offset,
int* width,
int* height)
{
if (m_needLayout)
{
m_ptrLayout = widget.create_pango_layout ("");
m_needLayout = false;
}
Pango::Rectangle rect = m_ptrLayout->get_pixel_logical_extents ();
if (width)
{
*width = property_xpad ()*2 + rect.get_width ();
}
if (height)
{
*height = property_ypad ()*2 + rect.get_height ();
}
if (cell_area)
{
if (x_offset)
{
*x_offset = int (property_xalign ()*(cell_area->get_width ()
- rect.get_width ()
- 2*property_xpad ()));
*x_offset = std::max (*x_offset, 0);
}
if (y_offset)
{
*y_offset = int (property_yalign ()*(cell_area->get_height ()
- rect.get_height ()
- 2*property_ypad ()));
*y_offset = std::max (*y_offset, 0);
}
}
}
void CellRendererTextSimple::render_vfunc
(const Glib::RefPtr<Gdk::Window>& window,
Gtk::Widget& widget,
const Gdk::Rectangle& background_area,
const Gdk::Rectangle& cell_area,
const Gdk::Rectangle& expose_area,
Gtk::CellRendererState flags)
{
if (m_needLayout)
{
m_ptrLayout = widget.create_pango_layout ("");
m_needLayout = false;
}
m_ptrLayout->set_text (property_text ());
const unsigned int cell_xpad = property_xpad ();
const unsigned int cell_ypad = property_ypad ();
Gtk::StateType state;
int x_offset = 0, y_offset = 0, width = 0, height = 0;
get_size (widget, cell_area, x_offset, y_offset, width, height);
if((flags & Gtk::CELL_RENDERER_SELECTED) != 0)
{
state = (widget.has_focus()) ? Gtk::STATE_SELECTED : Gtk::STATE_ACTIVE;
}
else
{
state = (widget.is_sensitive()) ?
Gtk::STATE_NORMAL : Gtk::STATE_INSENSITIVE;
}
widget.get_style ()
->paint_layout (window,
state,
true,
cell_area,
widget,
"cellrenderertext",
cell_area.get_x () + x_offset + cell_xpad,
cell_area.get_y () + y_offset + cell_ypad,
m_ptrLayout);
}
class MyWindow : public Gtk::Window
{
struct MyColumnModel : Gtk::TreeModel::ColumnRecord
{
Gtk::TreeModelColumn< int > id;
Gtk::TreeModelColumn< Glib::ustring > label;
Gtk::TreeModelColumn< double > val;
Gtk::TreeModelColumn< bool > check;
Gtk::TreeModelColumn< int > id1;
Gtk::TreeModelColumn< Glib::ustring > label1;
Gtk::TreeModelColumn< double > val1;
Gtk::TreeModelColumn< bool > check1;
Gtk::TreeModelColumn< int > id2;
Gtk::TreeModelColumn< Glib::ustring > label2;
Gtk::TreeModelColumn< double > val2;
Gtk::TreeModelColumn< bool > check2;
Gtk::TreeModelColumn< int > id3;
Gtk::TreeModelColumn< Glib::ustring > label3;
Gtk::TreeModelColumn< double > val3;
Gtk::TreeModelColumn< bool > check3;
MyColumnModel ()
{
add (id); add (label); add (val); add (check);
add (id1); add (label1); add (val1); add (check1);
add (id2); add (label2); add (val2); add (check2);
add (id3); add (label3); add (val3); add (check3);
}
};
MyColumnModel m_cols;
Gtk::TreeView m_tree;
Glib::RefPtr< Gtk::ListStore > m_refModel;
public:
MyWindow ();
void fill_tree ();
void click_cb ();
Glib::RefPtr< Gtk::ListStore > create_model ();
};
MyWindow::MyWindow ()
{
set_default_size (-1, 500);
Gtk::VBox *box = manage (new Gtk::VBox);
add (*box);
Gtk::ScrolledWindow *sw = manage (new Gtk::ScrolledWindow);
sw->set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
box->add (*sw);
m_refModel = create_model ();
m_tree.set_model (m_refModel);
{
CellRendererTextSimple *render = new CellRendererTextSimple;
Gtk::TreeViewColumn *col =
new Gtk::TreeViewColumn ("ID",
*Gtk::manage (render));
m_tree.append_column (*Gtk::manage (col));
col->add_attribute (render->property_text (), m_cols.id);
}
{
CellRendererTextSimple *render = new CellRendererTextSimple;
Gtk::TreeViewColumn *col =
new Gtk::TreeViewColumn ("LABEL",
*Gtk::manage (render));
m_tree.append_column (*Gtk::manage (col));
col->add_attribute (render->property_text (), m_cols.label);
}
{
CellRendererTextSimple *render = new CellRendererTextSimple;
Gtk::TreeViewColumn *col =
new Gtk::TreeViewColumn ("VALUE",
*Gtk::manage (render));
m_tree.append_column (*Gtk::manage (col));
col->add_attribute (render->property_text (), m_cols.val);
}
m_tree.append_column ("CHECK", m_cols.check);
{
CellRendererTextSimple *render = new CellRendererTextSimple;
Gtk::TreeViewColumn *col =
new Gtk::TreeViewColumn ("ID",
*Gtk::manage (render));
m_tree.append_column (*Gtk::manage (col));
col->add_attribute (render->property_text (), m_cols.id1);
}
{
CellRendererTextSimple *render = new CellRendererTextSimple;
Gtk::TreeViewColumn *col =
new Gtk::TreeViewColumn ("LABEL",
*Gtk::manage (render));
m_tree.append_column (*Gtk::manage (col));
col->add_attribute (render->property_text (), m_cols.label1);
}
{
CellRendererTextSimple *render = new CellRendererTextSimple;
Gtk::TreeViewColumn *col =
new Gtk::TreeViewColumn ("VALUE",
*Gtk::manage (render));
m_tree.append_column (*Gtk::manage (col));
col->add_attribute (render->property_text (), m_cols.val1);
}
m_tree.append_column ("CHECK", m_cols.check1);
{
CellRendererTextSimple *render = new CellRendererTextSimple;
Gtk::TreeViewColumn *col =
new Gtk::TreeViewColumn ("ID",
*Gtk::manage (render));
m_tree.append_column (*Gtk::manage (col));
col->add_attribute (render->property_text (), m_cols.id2);
}
{
CellRendererTextSimple *render = new CellRendererTextSimple;
Gtk::TreeViewColumn *col =
new Gtk::TreeViewColumn ("LABEL",
*Gtk::manage (render));
m_tree.append_column (*Gtk::manage (col));
col->add_attribute (render->property_text (), m_cols.label2);
}
{
CellRendererTextSimple *render = new CellRendererTextSimple;
Gtk::TreeViewColumn *col =
new Gtk::TreeViewColumn ("VALUE",
*Gtk::manage (render));
m_tree.append_column (*Gtk::manage (col));
col->add_attribute (render->property_text (), m_cols.val2);
}
m_tree.append_column ("CHECK", m_cols.check2);
{
CellRendererTextSimple *render = new CellRendererTextSimple;
Gtk::TreeViewColumn *col =
new Gtk::TreeViewColumn ("ID",
*Gtk::manage (render));
m_tree.append_column (*Gtk::manage (col));
col->add_attribute (render->property_text (), m_cols.id3);
}
{
CellRendererTextSimple *render = new CellRendererTextSimple;
Gtk::TreeViewColumn *col =
new Gtk::TreeViewColumn ("LABEL",
*Gtk::manage (render));
m_tree.append_column (*Gtk::manage (col));
col->add_attribute (render->property_text (), m_cols.label3);
}
{
CellRendererTextSimple *render = new CellRendererTextSimple;
Gtk::TreeViewColumn *col =
new Gtk::TreeViewColumn ("VALUE",
*Gtk::manage (render));
m_tree.append_column (*Gtk::manage (col));
col->add_attribute (render->property_text (), m_cols.val3);
}
m_tree.append_column ("CHECK", m_cols.check3);
sw->add (m_tree);
Gtk::Button *b = manage (new Gtk::Button("FILL"));
box->pack_end (*b, Gtk::PACK_SHRINK);
b->signal_clicked ().connect (SigC::slot (*this, &MyWindow::click_cb));
show_all ();
}
void MyWindow::click_cb ()
{
m_refModel->clear ();
fill_tree ();
}
Glib::RefPtr< Gtk::ListStore > MyWindow::create_model ()
{
Glib::RefPtr<Gtk::ListStore> store = Gtk::ListStore::create (m_cols);
return store;
}
void MyWindow::fill_tree ()
{
for (int i = 0; i < 10000; i++)
{
Gtk::TreeIter iter = m_refModel->append ();
(*iter)[m_cols.id] = i;
(*iter)[m_cols.label] = "LABEL";
(*iter)[m_cols.val] = i/3.0;
(*iter)[m_cols.check] = i%2;
(*iter)[m_cols.id1] = i;
(*iter)[m_cols.label1] = "LABEL";
(*iter)[m_cols.val1] = i/3.0;
(*iter)[m_cols.check1] = i%2;
(*iter)[m_cols.id2] = i;
(*iter)[m_cols.label2] = "LABEL";
(*iter)[m_cols.val2] = i/3.0;
(*iter)[m_cols.check2] = i%2;
(*iter)[m_cols.id3] = i;
(*iter)[m_cols.label3] = "LABEL";
(*iter)[m_cols.val3] = i/3.0;
(*iter)[m_cols.check3] = i%2;
}
}
int main (int argc, char *argv[])
{
Gtk::Main kit (&argc, &argv);
MyWindow app;
kit.run (app);
return 0;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]