[gtkmm] TreeView Design



Hi,
I'm trying to understand the design rational of TreeView, and have some
questions please:

(The examples are from example_treeview_editable_cells.cc in gtkmm-1.3.18)

Looking at the way TreeView is used, it seems there are three levels:
1. the underlying model - eg. CellItem_Product
2. another model - eg. Gtk::ListStore
3. the view - eg. Gtk::TreeView

My understanding is that level 2 contains a complete copy of the data in
level 1 and that the programmer is responsible for keeping those in synch.
Why?   It seems unnecessary, a bit complicated and potentially a source of
problems (as whereever data is duplicated).

In the past, I have worked with a C++ graphical toolkit where we didn't have
the extra layer (or at least in was hidden), and am trying to think of
advantages/disadvantages of the approaches.  The equivalent of the treeview
took as a model a collection of underlying model objects, that had no direct
ties to the GUI library.  Each row of the table represented one object.
Each column would be defined by a 'get' function on an underlying model
object, and optionally a 'set' function.  (If the set function was provided,
then it was editable).  When an editable field was changed, the underlying
model was automatically changed.   Then the view would redraw the row,
calling the get functions for each cell.  Some columns may show derived
values that were only available through the class interface, e.g.  getSum()
below, and so these would automatically update.

eg. (very simplified)

class UnderlyingModel
{
public:
  int getX() const     { return m_x; }
  int getY()  const    { return m_y; }
  int getSum()  { return m_x + m_y; }
  void setX(int x_) { m_x = x_; }
  void setY(int y_) { m_y = y_; }
private:
  int m_x;
  int m_y;
};

Then in the view creation code you could say something like this (from
memory the treeview was templatized based on the model):

  treeview->addColumn(&UnderlyingModel::getX, &UnderlyingModel::setY);
  treeview->addColumn(&UnderlyingModel::getY, &UnderlyingModel::setY);
  treeview->addColumn(&UnderlyingModel::getSum);

The advantage is the user of the View class didn't have to worry about
keeping data in synch, but the model layer could still be free from any GUI
specific stuff.

------

Also, there was an alternative interface which had three levels, but the
level 2 was just an adapter level, that forwarded functions to the
underlying model.  There was still no duplication of the data, and the user
of the class didn't have to keep everything in sync.  So instead of the
current code which copies by value:

  row[m_columns.number]   = foo.m_number;
  row[m_columns.product]  = foo.m_product;
  row[m_columns.editable] = foo.m_editable;

It could do something like this (just trying to remember and thinking out
loud here):

  row[m_columns.number].attach(boost::bind(&CellItemBug::getNumber, foo) ,
boost::bind(&CellItemBug::setNumber, foo));

where the attach function would take two function objects, one that returned
a value, and the second that took a single value parameter.

I wasn't involved in the design or implementation of the gui libraries I
used before, but did use them extensively.  It was a few years ago though
and I've forgotten some of the detail - sorry that these examples/ideas
aren't perfect.

I may be missing the advantages in having the copy of the data - I'd
appreciate any insight into the design.

thanks,
Dan






[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]