0054: MVC VII – TreeView Basics

We’ve all been told that the TreeView is a complex and difficult beast to tame, but it’s not so hard once you’ve got a few bits of information at your fingertips. And in the previous six instalments of this series, most of those bits have been presented which means it should come as no big surprise that…

There are only three Widgets we need to understand in order to make a TreeView work:

  • a ListStore which holds the data and acts as a TreeModel,
  • the TreeViewColumn which controls the content and look of a column, and
  • the TreeView itself.

And that’s it.

A Single-column TreeView

Results of this example:
Current example output
Current example output
Current example terminal output
Current example terminal output (click for enlarged view)

We derive a SignTreeView from the TreeView class and it looks like this:

class SignTreeView : TreeView
{
	SignTreeViewColumn signTreeViewColumn;
	SignListStore signListStore;
	
	this()
	{
		super();
		
		signListStore = new SignListStore();
		setModel(signListStore);
		
		signTreeViewColumn = new SignTreeViewColumn();
		appendColumn(signTreeViewColumn);
		
	} // this()
	
} // class SignTreeView

Once the TreeView is instantiated by calling the super-class constructor, we set up and assign the Model/Store (signListStore), then instantiate and append one or more TreeViewColumns.

The ListStore

The ListStore is used the same way with a TreeView as it was with the ComboBox and so we have:

class SignListStore : ListStore
{
	string[] items = ["bike", "bump", "cow", "deer", "crumbling cliff", "man with a stop sign", "skidding vehicle"];
	TreeIter treeIter;
	
	this()
	{
		super([GType.STRING]);
		
		foreach(ulong i; 0..items.length)
		{
			string message = items[i];
			treeIter = createIter();
			setValue(treeIter, 0, message);
		}

	} // this()

} // class SignListStore

This is the same SignListStore we used with a ComboBox in an earlier example, thus illustrating how the same data can be used in different ways by different Widgets.

And that just leaves…

The TreeViewColumn

Which looks like this:

class SignTreeViewColumn : TreeViewColumn
{
	CellRendererText cellRendererText;
	string columnTitle = "Sign Message";
	string attributeType = "text";
	int columnNumber = 0; // numbering starts at '0'

	this()
	{
		cellRendererText = new CellRendererText();
		
		super(columnTitle, cellRendererText, attributeType, columnNumber);
		
	} // this()

} // class SignTreeViewColumn

When we populated a ComboBox, a CellRenderer was packed directly into the ComboBox. But with a TreeView:

  • each TreeViewColumn takes care of its own CellRenderer(s), and
  • is appended to the TreeView as we saw earlier when we looked at the TreeView class itself.

So, it’s here in the TreeViewColumn constructor we deal with such things as:

  • instantiating the CellRenderer,
  • assigning a column number, and
  • defining the column type as “text”.

On top of that, we also name the column (columnTitle) and give it a number. And that’s pretty much it.

Two-column TreeView

Results of this example:
Current example output
Current example output
Current example terminal output
Current example terminal output (click for enlarged view)

You only have to do two things differently with a two-column TreeView:

  • add another column (naturally), and
  • decide if you want the column(s) sort-able.

And that means:

  • in the SignTreeView class, we appendColumn() the second column,
  • in one or both TreeViewColumn classes, we setSortColumnId() with the number of the column (starting from 0), and
  • in the ListStore, we add a second array of data.

Using ListStore’s set() Instead of setValue()

As mentioned in Blog Post #0053, as long as we’re using strings and only strings, we can get away with using set(). But it’s meant as a shorthand way of dealing with a single data type: the string. This means that even if you’re using numbers (which are rendered as text by ComboBox and TreeView) we still have to use setValue().

Conclusion

And that’s the basics of using the TreeView… create a storage model, whip up a TreeView, and stuff a column in there.

Next time around we’ll look at a second multi-column TreeView example which is dynamically loaded rather than using roll-yer-own arrays.

Comments? Questions? Observations?

Did we miss a tidbit of information that would make this post even more informative? Let's talk about it in the comments.

You can also subscribe via RSS so you won't miss anything. Thank you very much for dropping by.

© Copyright 2023 Ron Tarrant