TIP 369: Widget cargo command

Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2017 Conference, Houston/TX, US, Oct 16-20
Send your abstracts to tclconference@googlegroups.com
by Aug 21.
Author:         Russell Davidson <russelld@actarg.com>
Author:         Trevor Davel <twylite@crypt.co.za>
State:          Draft
Type:           Project
Vote:           Pending
Created:        15-Jul-2010
Keywords:       Tk,user-defined data,dictionary
Tcl-Version:    8.7


This TIP is to add a cargo subcommand to widgets for storing data in a data dictionary. This TIP is related to [349].


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?


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.


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.


A patch exists in SourceForge (FRQ 3023578 https://sourceforge.net/support/tracker.php?aid=3023578 )


Twylite 2010/08/10:


This document has been placed in the public domain.