TIP #369: Widget cargo command
_____________________________________________________________________________
TIP:	369
Title:	Widget cargo command
Version:	$Revision: 1.7 $
Authors:	Russell Davidson <russelld@actarg.com>
	Trevor Davel <twylite@crypt.co.za>
State:	Draft
Type:	Project
Tcl-Version:	8.7
Vote:	Pending
Created:	Thu Jul 15 00:00:00 UTC 2010
Keywords:	Tk, user-defined data, dictionary
Abstract
This TIP is to add a cargo subcommand to widgets for storing data in a data dictionary. This TIP is related to [349].
Specification
It is proposed that a cargo subcommand be added to most widgets that will allow the user to store data related to the widget in a data dictionary. With the cargo command there are three parameters that can go with it: set, unset, and get.
Set adds and alters entries in the cargo dictionary.
pathName cargo set name value ?name value ...?
Unset, with the name of an entry, will delete the entry from the cargo dictionary and free the memory that entry used. Unset, without an entry name, will delete the entire dictionary and free all memory.
pathName cargo unset ?name ...?
Get with the name of an entry will return the associated value. Get without an entry will return all entry-value pairs.
pathName cargo get ?name?
Usage
The following is based on a widget called .wgt that has already been created:
.wgt cargo set help "This is a widget" use "Shows a widget"
This puts two entries into the cargo dictionary, one called help, with the value "This is a widget", and one called use with the value "Shows a widget".
.wgt cargo set help "This is a wonderful widget" use2 "Shows a great widget"
This alters the value of the entry help to "This is a wonderful widget", and adds the entry use2 with the value "Shows a great widget"
.wgt cargo unset use
This erases the entry use and frees the memory.
puts [.wgt cargo get help]
This prints "This is a wonderful widget", the value of the entry help.
puts [.wgt cargo get use]
This prints an empty string because the entry use has been deleted. When an entry that doesn't exist is accessed with get, a blank string is returned.
puts [.wgt cargo get use2]
This prints "Shows a great widget", the value of the entry use2.
 puts [.wgt cargo get]
This prints "help This is a wonderful widget use2 Shows a great widget".
.wgt cargo unset
This deletes all entries and frees the memory
Note that when a widget is destroyed, the cargo dictionary associated with it is erased and the memory is freed.
Rationale
It is possible to duplicate this functionality by creating additional procedures and variables. But doing this in Tcl has the downside of creating more overhead when running the script. It also makes more things for the coder to keep track of. By putting the dictionary in the base code, there is less overhead and less for the developer to keep track of. If no cargo dictionary at all is wanted there is no additional overhead beyond an unused pointer in each widget.
Memory management is a big benefit. As widgets are created/destroyed, it is easy to inadvertently generate memory leaks where structures are created for new widgets, filled with data, and then inadvertently left around after the widget is destroyed. When the data is stored with the widget instance, garbage gets cleaned up much more reliably.
The cargo subcommand can also be used to help implement tool-tip funcionality. We could suggest that tool tips be supported natively in Tk, but that request would be easily argued against with the logic that it can be easily re-created in Tcl. So cargo is suggested instead as a very general way of facilitating a whole host of functionality to be implemented in widget wrappers without having to keep and maintain scads of external data in auxiliary hashes.
One of the biggest challenges we face with Tcl/Tk is keeping it somewhat object oriented (without having to inherit the whole overhead structure of one of the multitude of available OOPs). When a new instance of a widget or a megawidget gets created, it is important to be able to keep track of which variables are related to instances and which ones apply to a whole class. We currently solve this by including the instance name in the hash index. While this works, it does get messy sometimes. And it would be appealing to be able to make individual instances of widgets responsible for storing their own data. It would certainly allow for a greater degree of isolation between instances.
In short, cargo does not actually implement any specific functionality in the widget which a megawidget might otherwise handle. But it does facilitate easier implementation of a broad range of compound and megawidget functionality.
Implementation
A patch exists in SourceForge (FRQ 3023578 [https://sourceforge.net/support/tracker.php?aid=3023578])
_____________________________________________________________________________
Comments
Twylite 2010/08/10:
The performance overhead for doing this in a script rather than in the core is minimal.
Developer overhead is easily dealt with by means of an appropriate abstraction.
Script-level resource management can be achieved by binding to <Destroy>.
This proposal fails to address some variables that may need to be associated with a widget, in particular those used with -variable or -textvariable which require the ability to reference the variable by name. These are also instance-related variables that can benefit from automated resource management and a cleaner abstraction.
For a pure-Tcl implementation of functionality equivalent to cargo plus direct reference by name, take a look at my tk::wprop module (doc [http://dev.crypt.co.za/incubator/doc/tcltm/tk/wprop.wiki], source [http://dev.crypt.co.za/incubator/artifact/d480935465]) 
_____________________________________________________________________________
Copyright
This document has been placed in the public domain.
_____________________________________________________________________________
Colophon
TIP AutoGenerator - written by Donal K. Fellows