Re: TreeView Design



On Thu, 31 Aug 2006 09:41:35 -0500, Gareth Foster <earthwormgaz googlemail com> wrote:

struct Derived: public Base { ... };


Yes, sorry.

it->member = <any pointer to a class/struct that derived from Base>;


But what about setting the data therein, using GTKmm, things like this
are possible:

Gtk::TreeModel::Row row = *(m_refTreeModel->append());
row[m_Columns.m_col_id] = 1;

I am trying to get my head around the magic that makes this possible.

Hope that makes more sense.

Gaz

Oh, now I see. You want similar behaviour as in GTKmm: the magic of putting something into a row when columns are specified somewhere else. I was thinking about the same yesterday /I am a newbie in GTKmm/ but here is what I have found /it is beautiful implementation and use of C++ templates/ :)

	row[m_Columns.m_col_id] = 1

is equivalent to:

	row.operator[]( mColumnst.m_col_id).operator=( 1);

[1] gtkmm/treeiter.h /TreeRow<A>::operator[](...) implementation/

template <class ColumnType> inline
TreeValueProxy<ColumnType> TreeRow::operator[](const TreeModelColumn<ColumnType>& column) const
{
  return TreeValueProxy<ColumnType>(*this, column);
}

this should be clear: operator=(...) is a member of Template: TreeValueProxy.

[2] gtkmm/treeiter.h /TreeValueProxy<A>::operator =(...) implementation/

template <class ColumnType> inline
TreeValueProxy<ColumnType>& TreeValueProxy<ColumnType>::operator=(const ColumnType& data)
{
  row_.set_value(column_, data);
  return *this;
}

data is your '1'

So, set_value for a given row is called and returned reference to a given object to make nested '=' operators possible. Not a surprise.

[3] gtkmm/treeiter.h /TreeValueProxy declaration/

template <class ColumnType>
class TreeValueProxy
{
public:
#ifndef DOXYGEN_SHOULD_SKIP_THIS
inline TreeValueProxy(const TreeRow& row, const TreeModelColumn<ColumnType>& column);
#endif

  inline TreeValueProxy<ColumnType>& operator=(const ColumnType& data);
  inline operator ColumnType() const;

private:
  const TreeRow&                      row_;
  const TreeModelColumn<ColumnType>&  column_;

  // no copy assignment
  TreeValueProxy<ColumnType>& operator=(const TreeValueProxy<ColumnType>&);
};

row_    is a reference to our recently added row
column_ is a reference to our TreeModelColumn where you specified type of a given column :)

Do you remember writing something like?:

class ModelColumns: public Gtk::TreeModelColumnRecord {
  public:
    ModelColumns();
    virtual ~ModelColumns() {}

    Gtk::TreeModelColumn<std::string>		      cFileName;
    Gtk::TreeModelColumn<std::string>		      cDescription;
    Gtk::TreeModelColumn< Glib::RefPtr<Gdk::Pixbuf> > oThumbnail;
    // Next column will be hidden unless it is not added to a list of
    // visible ones with TreeView::append_column(...)
    Gtk::TreeModelColumn<std::string>		      cHiddenData;
};

/In your case it is a little bit different/

[4] gtkmm/treeiter.h /TreeRow::set_value implementation/

template <class ColumnType>
void TreeRow::set_value(const TreeModelColumn<ColumnType>& column, const ColumnType& data) const
{
  typedef typename Gtk::TreeModelColumn<ColumnType>::ValueType ValueType;

  ValueType value;
  value.init(column.type());

  value.set(data);
  this->set_value_impl(column.index(), value);
}

Now you see that column /TreeModelColumn<A>/ is not used at all except grabbing a type of a given column. That's it. Very simple and very beautiful. Here you create some object of given type, assign value to it and that's it: you've got a cell in a given row/col.


So, if you want the same kind of flexibility in your code do something similar just don't mess with Templates.

--
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/



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