This tutorial demonstrates how to create a tree to view data.

/* All user scripts should derive from the base "Application" class */
require ("Application");
require ("WindowsSupport");
class TreeViewDemo Application
{
window;
tree;
data = [["top_level_1",
["level_1_1",
["level_2_1",
"level_3_1",
["level_3_2", "level_4_1"],
"level_3_3"
],
["level_2_2",
"level_3_4", "level_3_5", "level_3_6"
]
],
["level_1_2",
"level_2_3", "level_2_4"
]
]
];
}
/* Use methods to create functions outside the 'main line'. */
method TreeViewDemo.FillTree (data)
{
local root = .tree.GetRootItem();
with descendants in data do
{
.FillTreeRecursive(root, descendants);
}
}
// Adding an item uses the InsertItem method.
method TreeViewDemo.FillTreeRecursive (parent, data)
{
local nodename = array_p(data) ? data[0] : data;
local htreeitem = .tree.InsertItem(nodename, 0, 0, parent, TVI_LAST);
local i;
if (array_p(data))
{
for (i=1; i<length(data); i++)
{
.FillTreeRecursive(htreeitem, data[i]);
}
}
}
// Find the full path name of the selected item in the tree
method TreeViewDemo.GetTreeSelection ()
{
local hitem = .tree.GetSelectedItem();
.GetTreeItemFullname (hitem);
}
// Get just the text label of the given item
method TreeViewDemo.GetTreeItemText (hitem)
{
local item = new TVITEM();
local buf;
item.hItem = hitem;
item.mask = TVIF_TEXT;
item.cchTextMax = 128;
item.pszText = make_buffer(128);
.tree.GetItem (item);
buf = item.pszText;
buffer_to_string (buf);
}
// Find the full path name of the given item. The path
// separator can be changed by modifying the / below
method TreeViewDemo.GetTreeItemFullname (hitem)
{
local itemtext, pname, hparent, hgrandparent, sep = "/";
if (hitem != 0)
{
itemtext = .GetTreeItemText (hitem);
hparent = .tree.GetParentItem(hitem);
if (hparent != 0)
{
hgrandparent = .tree.GetParentItem(hparent);
// If you want to make the first separator different from the
// rest, change it here.
if (hgrandparent == 0)
sep = "/";
}
pname = .GetTreeItemFullname (hparent);
if (pname)
string (pname, sep, itemtext);
else
itemtext;
}
else
nil;
}
// Callback when an item is selected
method TreeViewDemo.cbItemSelected (itemname)
{
princ ("You selected item: ", itemname, "\n");
}
// Callback before a branch in the tree is expanded or collapsed
method TreeViewDemo.cbPointExpanding ()
{
local item = map_volatile_pointer (pnmh, NMTREEVIEW);
local hitem = item.itemNew.hItem;
local pointname = .GetTreeItemFullname (hitem);
if (item.action == TVE_COLLAPSE)
{
princ ("Item: ", pointname, " is about to collapse\n");
}
else
{
princ ("Item: ", pointname, " is about to expand\n");
}
// Allow the tree to expand or collapse
0;
}
// Callback after a branch is expanded or collapsed
method TreeViewDemo.cbPointExpanded ()
{
local item = map_volatile_pointer (pnmh, NMTREEVIEW);
local hitem = item.itemNew.hItem;
local pointname = .GetTreeItemFullname (hitem);
if (item.action == TVE_COLLAPSE)
{
princ ("Item: ", pointname, " has collapsed\n");
}
else
{
princ ("Item: ", pointname, " has expanded\n");
}
// Allow the tree to expand or collapse
0;
}
/* Write the 'main line' of the program here. */
method TreeViewDemo.constructor ()
{
local win = new GWindow();
local rect = CreateRect(100, 100, 220, 220);
local clientrect = CreateRect(0,0,0,0);
win.Create (0, rect, "TreeView Example", WS_OVERLAPPEDWINDOW, 0);
win.MessageHandler (WM_DESTROY, `(!destroyed_p(@self) ? destroy(@self) : nil));
.window = win;
.window.SetBackground (0, GetSysColor (COLOR_3DFACE), 0);
// Find the interior size of the window so we can size the TreeView
win.GetClientRect(clientrect);
// ------- TreeView example starts here
// Create a TreeView. Use TVS_* to set the options.
local tv = win.CreateControl (GTreeViewCtrl, 5, 5,
clientrect.right - 10, clientrect.bottom - 10,
"ExampleTreeView", TVS_CHECKBOXES | TVS_HASLINES |
TVS_LINESATROOT | TVS_HASBUTTONS |
TVS_TRACKSELECT | TVS_NOHSCROLL);
.tree = tv;
// If the window has a different background, make sure the combo box
// stays white.
tv.SetChildBackground (0, GetSysColor (COLOR_WINDOW), 0);
// Fill the tree once at the start
.FillTree(.data);
// Trigger an event when the user selects an item
win.NotifyHandler (TVN_SELCHANGED, tv,
`(@self).cbItemSelected((@self).GetTreeSelection()));
win.NotifyHandler (TVN_ITEMEXPANDING, tv, `(@self).cbPointExpanding());
win.NotifyHandler (TVN_ITEMEXPANDED, tv, `(@self).cbPointExpanded());
// There is no event in Windows for changing a check-box state in a TreeView !?
// Checkbox events are absurdly difficult to deal with in C++, and impossible
//in Gamma.
// You can add events to handle other use cases as well...
//win.NotifyHandler (NM_DBLCLK, tv, `(@self).cbDoubleClick((@self).GetTreeSelection()));
//tv.MessageHandler (WM_RBUTTONDOWN, `((@self).cbRightClick()));
// Reize the TreeView when the window resizes
win.AddControlResizeFlags (tv, DLSZ_SIZE_X | DLSZ_SIZE_Y);
// ------- TreeView example ends here
win.ShowWindow (SW_SHOW);
}
/* Any code to be run when the program gets shut down. */
method TreeViewDemo.destructor ()
{
if (instance_p(.window))
destroy (.window);
}
/* Start the program by instantiating the class. If your
* constructor code does not create a persistent reference to
* the instance (self), then it will be destroyed by the
* garbage collector soon after creation. If you do not want
* this to happen, assign the instance to a global variable, or
* create a static data member in your class to which you assign
* 'self' during the construction process. ApplicationSingleton()
* does this for you automatically. */
ApplicationSingleton (TreeViewDemo);
Copyright © 1995-2010 by Cogent Real-Time Systems, Inc. All rights reserved.