\documentclass[]{article}
\usepackage{amsmath,graphicx,supertabular,hyperref,tabularx,ifthen}
\title{TIP \#369: Widget cargo command}
\date{July 15, 2010}
\author{Russell Davidson, Trevor Davel}
\urlstyle{sf}
\setlength{\parskip}{1ex}
\setlength{\parindent}{0pt}
\def\tipversion$#1${\texttt{\$#1\$}}
\def\tiplangle#1{\ensuremath{<}}
\def\tiprangle#1{\ensuremath{>}}
\def\tipbar#1{\ensuremath{|}}
\def\tipmail#1#2{\(\langle\){\small\expandafter\url{#1@#2}}\(\rangle\)}
\ifx\pdfoutput\undefined
\newcommand{\tipimage}[2]{\typeout{Make sure you download #1.eps}\ifthenelse{\lengthtest{0.8\textwidth>#2}\and\lengthtest{0pt<#2}}{\includegraphics{#1.eps}}{\includegraphics[width=0.8\textwidth]{#1.eps}}}
\newcommand{\tipxref}[1]{}
\newcommand{\tipxrefend}{}
\else
\newcommand{\tipimage}[2]{\typeout{Make sure you create #1.pdf}\ifthenelse{\lengthtest{0.8\textwidth>#2}\and\lengthtest{0pt<#2}}{\includegraphics{#1.pdf}}{\includegraphics[width=0.8\textwidth]{#1.pdf}}}
\pdfcatalog{/PageMode /UseOutlines}
\newcommand{\tipxref}[1]{\pdfannotlink attr {/C [0.5 0.5 1.0] /Border [0 0 1]} goto name {#1}}
\newcommand{\tipxrefend}{\pdfendlink}
\fi
\newenvironment{tipabstract}{\begin{abstract}}{\end{abstract}}
\begin{document}\maketitle
\begin{center}\begin{tabularx}{\linewidth}{|r@{: }X|}\hline
\textbf{TIP \#369}&\textbf{Widget cargo command}\\\hline
Author&

Russell Davidson \tipmail{russelld}{actarg.com}
\par
Trevor Davel \tipmail{twylite}{crypt.co.za}
\\
Created&Thursday, \(\text{15}^{\text{th}}\) July 2010\\
Type&Project\\
Tcl Version&\(8.7\)\\
State&Draft\\
Vote&Pending\\
Version&\tipversion$Revision: 1.7 $\\
Keywords&Tk, user-defined data, dictionary\\
Post History&\\
\hline\end{tabularx}\end{center}
\thispagestyle{empty}\pagestyle{empty}
\begin{tipabstract}

This TIP is to add a \textbf{cargo} subcommand to widgets for storing data in a data dictionary. This TIP is related to \cite{tip349}.
\end{tipabstract}
\tableofcontents\setcounter{page}{0}\clearpage\pagestyle{plain}

\section{Specification}

It is proposed that a \textbf{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 \textbf{cargo} command there are three parameters that can go with it: \textbf{set}, \textbf{unset}, and \textbf{get}.

\textbf{Set} adds and alters entries in the cargo dictionary.

\begin{quote}
\textit{pathName} \textbf{cargo set} \textit{name value} ?\textit{name value ...}?
\end{quote}

\textbf{Unset}, with the name of an entry, will delete the entry from the cargo dictionary and free the memory that entry used. \textbf{Unset}, without an entry name, will delete the entire dictionary and free all memory.

\begin{quote}
\textit{pathName} \textbf{cargo unset} ?\textit{name ...}?
\end{quote}

\textbf{Get} with the name of an entry will return the associated value. \textbf{Get} without an entry will return all entry-value pairs.

\begin{quote}
\textit{pathName} \textbf{cargo get} ?\textit{name}?
\end{quote}

\section{Usage}

The following is based on a widget called \textit{.wgt} that has already been created:
\begingroup\small\begin{verbatim}
.wgt cargo set help "This is a widget" use "Shows a widget"
\end{verbatim}
\endgroup

This puts two entries into the cargo dictionary, one called \textit{help}, with the value ``\textit{This is a widget}'', and one called \textit{use} with the value ``\textit{Shows a widget}''.
\begingroup\small\begin{verbatim}
.wgt cargo set help "This is a wonderful widget" use2 "Shows a great widget"
\end{verbatim}
\endgroup

This alters the value of the entry \textit{help} to ``\textit{This is a wonderful widget}'', and adds the entry \textit{use2} with the value ``\textit{Shows a great widget}''
\begingroup\small\begin{verbatim}
.wgt cargo unset use
\end{verbatim}
\endgroup

This erases the entry \textit{use} and frees the memory.
\begingroup\small\begin{verbatim}
puts [.wgt cargo get help]
\end{verbatim}
\endgroup

This prints ``\textit{This is a wonderful widget}'', the value of the entry \textit{help}.
\begingroup\small\begin{verbatim}
puts [.wgt cargo get use]
\end{verbatim}
\endgroup

This prints an empty string because the entry \textit{use} has been deleted. When an entry that doesn't exist is accessed with \textbf{get}, a blank string is returned.
\begingroup\small\begin{verbatim}
puts [.wgt cargo get use2]
\end{verbatim}
\endgroup

This prints ``\textit{Shows a great widget}'', the value of the entry \textit{use2}.
\begingroup\small\begin{verbatim}
 puts [.wgt cargo get]
\end{verbatim}
\endgroup

This prints ``\textit{help \{This is a wonderful widget\} use2 \{Shows a great widget\}}''.
\begingroup\small\begin{verbatim}
.wgt cargo unset
\end{verbatim}
\endgroup

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.

\section{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 \textbf{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 \textbf{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, \textbf{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.

\section{Implementation}

A patch exists in SourceForge (FRQ 3023578 [\url{https://sourceforge.net/support/tracker.php?aid=3023578}])

\vspace{3ex}\hrule\vspace{1.5ex}

\section{Comments}

Twylite 2010/08/10:
\begin{itemize}
\item{}
The performance overhead for doing this in a script rather than in the core is minimal.
\item{}
Developer overhead is easily dealt with by means of an appropriate abstraction.
\item{}
Script-level resource management can be achieved by binding to \tiplangle{}Destroy\tiprangle{}.
\item{}
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.
\item{}
For a pure-Tcl implementation of functionality equivalent to \textbf{cargo} plus direct reference by name, take a look at my tk::wprop module (doc [\url{http://dev.crypt.co.za/incubator/doc/tcltm/tk/wprop.wiki}], source [\url{http://dev.crypt.co.za/incubator/artifact/d480935465}]) 
\end{itemize}

\vspace{3ex}\hrule\vspace{1.5ex}

\section{Copyright}

This document has been placed in the public domain.

\section{Colophon}

\textit{TIP AutoGenerator --- written by Donal K. Fellows}
\begin{thebibliography}{TIP \#1}
\addcontentsline{toc}{section}{References}
\bibitem[TIP \#349]{tip349}
Zbigniew Baniewski,
\emph{New "-cargo" option for every Tk widget},
on-line at \url{http://purl.org/tcl/tip/349.html}
\end{thebibliography}
\end{document}
