NAME

Gtk2::Ex::TreeMaker - A high level widget to represent a set of relational records in a hierarchical spreadsheet kinda display. This task is typical to most of the business application user interfaces.

DESCRIPTION

Typically in business applications, users like to view data in a spreadsheet kind of display. (Columns represent timeline(typically) and rows represent measures like sales/inventory/blah/blah).

The data itself is typically stored internally as relational records. For example, here is some sales info (stored internally in a relational database)

-------------------------------------
Region, City, Product, Date, Quantity
-------------------------------------
Texas, Dallas, Fruits, Dec-2003, 300
Texas, Dallas, Veggies, Jan-2004, 120
Texas, Austin, Fruits, Nov-2003, 310
Texas, Austin, Veggies, Feb-2004, 20
-------------------------------------

The user will typically want to view the same data in a hierarchical(/spreadsheet) kinda display.

------------------------------------------------------
Prod / Date   Nov-2003  Dec-2003  Jan-2004  Feb-2004 
------------------------------------------------------
Texas
   Dallas
     Fruits                  300             
     Veggies                           120 
   Austin
     Fruits        310
     Veggies                                     20
------------------------------------------------------

With web-based business apps, similar views are created in the browser using lots of html/jsp coding.

The Gtk2::TreeView is an excellent widget to display a similar presentation of data in a desktop app. But creating a (hierarchical) TreeView from flat relational data can require some recursive function coding. It would be great if all this recursive code could be abstracted out and packaged separately.

This high level widget is designed with that purpose in mind. This module will accept a relational feed of records and automatically convert it into a hierarchical treeview using the Gtk2::TreeView. The process involves invoking some recursive functions to build a TreeModel and populate it. Also, since the spreadsheet itself can be rather long horizontally, the widget also has a FreezePane capability.

SYNOPSIS

use Gtk2 -init;
use Gtk2::Ex::TreeMaker;

# Initialize the treemaker
my $treemaker = Gtk2::Ex::TreeMaker->new();

# Create the column names. The first columnname has to be 'Name'
my $column_names = [
   'Name',
   'Nov-2003', 'Dec-2003', 'Jan-2004', 'Feb-2004'
];

# This api will have to be cleaned soon...
# Define all the attributes of your records here.
my $data_attributes = [
   {'text' => 'Glib::String'},
   {'editable' => 'Glib::Boolean'},
   {'hyperlinked' => 'Glib::Boolean'}, 
   {'background' => 'Glib::String'}, 
];

# Here is the set of relational records to be displayed
my $recordset = [
   ['Texas','Dallas','Fruits','Dec-2003','300',0,1,'red'],
   ['Texas','Dallas','Veggies','Jan-2004','120',1,0,'blue'],
   ['Texas','Austin','Fruits','Nov-2003','310',1,1,'white'],
   ['Texas','Austin','Veggies','Feb-2004','20',0,1,'green']
];

# Set the data_attributes and column_names first
$treemaker->set_meta_data($data_attributes, $column_names);

# Now set the data_flat using the relational records
$treemaker->set_data_flat($recordset);

# Build the model
$treemaker->build_model;

# Create a root window to display the widget
my $window = Gtk2::Window->new;
$window->signal_connect(destroy => sub { Gtk2->main_quit; });

# Add the widget to the root window
$window->add($treemaker->get_widget());

$window->set_default_size(500, 300);
$window->show_all;
Gtk2->main;

METHODS

Gtk2::Ex::TreeMaker->new($column_names, $data_attributes)

This is the constructor. Accepts two arguments.

First argument is the column_names list. Each element of the array is a hash. The hash uses 'ColumnName' as the key. For example,

my $column_names = [
   'Name',
   'Nov-2003', 'Dec-2003', 'Jan-2004', 'Feb-2004'
];

Second argument is the data_attributes list. Here you specify what attributes each record has. For example,

my $data_attributes = [
   {'text' => 'Glib::String'},
   {'editable' => 'Glib::Boolean'},
   {'hyperlinked' => 'Glib::Boolean'}, 
   {'background' => 'Glib::String'}, 
];

All the attributes of the cell in the treeview are specified here. The value for these attributes are to be populated from the recordset. The assumption is that the attributes are contained in the data record in the same order towards the **end** of the record. (the last few fields)

Since we are using Gtk2::CellRendererText in the TreeView, any of the properties of the Gtk2::CellRendererText can be passed using this mechanism In addition to the properties of the CellRendererText, I have also added a custom property called 'hyperlinked'.

Gtk2::Ex::TreeMaker->set_data_flat($data_flat)

This sub is used to inject the relational recordset into the widget. This sub accepts a set of relational records (an array of arrays) as the argument. For example,

my $recordset = [
   ['Texas','Dallas','Fruits','Dec-2003','300'],
   ['Texas','Dallas','Veggies','Jan-2004','120'],
   ['Texas','Austin','Fruits','Nov-2003','310'],
   ['Texas','Austin','Veggies','Feb-2004','20']
];

Gtk2::Ex::TreeMaker->signal_connect($signal_name, $action)

Currently, two signals are suppoted

  • cell-edited

  • cell-clicked

Gtk2::Ex::TreeMaker->build_model

This is the core recursive method that actually builds the tree.

Gtk2::Ex::TreeMaker->get_widget

Returns the widget that you can later attach to a root window or any other container.

Gtk2::Ex::TreeMaker->locate_record(Gtk2::TreePath, Integer, Text)

This sub maps a TreeCell location into a flat record in the original recordset that was used to create this tree. The location of the TreeCell itself is denoted using two arguments, the Gtk2::TreePath that points to the row and the Column_ID that points to the column.

Using this information, the function then traverses the internal data structure and returns a record (an array object).

TODO

Here is a list of stuff that I plan to add to this module.

  • Not all cells need to be editable (DONE ! Included in this version)

    Provide some kind of criteria to decide whether a cell should be editable or not.

  • Some cells may need to be "hyperlinked" (DONE ! Included in this version)

    Some of the cells may have to be made clickable (hyperlinks). When clicked, may be the cell can drop down a menu or lead you to another view. Provide a callback on click (or rightclick) on the cells.

  • Wake Up ! Add some tests.

AUTHOR

Ofey Aikon, <ofey.aikon at gmail dot com>

BUGS

You tell me. Send me an email !

COPYRIGHT & LICENSE

Copyright 2004 Ofey Aikon, All Rights Reserved.

This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details.

You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA.