summaryrefslogtreecommitdiff
path: root/lib/database.tcl
diff options
context:
space:
mode:
authorShawn O. Pearce <spearce@spearce.org>2007-05-08 23:54:05 (GMT)
committerShawn O. Pearce <spearce@spearce.org>2007-05-09 01:38:54 (GMT)
commit1f07c4e5cefec88d825045ade24eee71f6a2df47 (patch)
tree3bc56152072b5fd172b19157defff15b9432b15f /lib/database.tcl
parentcc1f83fbdff1ae248c91ab231ab4100351e1ba0a (diff)
downloadgit-1f07c4e5cefec88d825045ade24eee71f6a2df47.zip
git-1f07c4e5cefec88d825045ade24eee71f6a2df47.tar.gz
git-1f07c4e5cefec88d825045ade24eee71f6a2df47.tar.bz2
git-gui: Define a simple class/method system
As most of the git-gui interface is based upon "meta-widgets" that need to carry around a good deal of state (e.g. console windows, browser windows, blame viewer) we have a good deal of messy code that tries to store this meta-widget state in global arrays, where keys into the array are formed from a union of a unique "object instance id" and the field name. This is a simple class system for Tcl that allows us to hide much of that mess by making Tcl do what it does best; process strings to manipulate its own code during startup. Each object instance is placed into its own namespace. The namespace is created when the object instance is created and the namespace is destroyed when the object instance is removed from the system. Within that namespace we place variables for each field within the class; these variables can themselves be scalar values or full-blown Tcl arrays. A simple class might be defined as: class map { field data field size 0 constructor {} { return $this } method set {name value} { set data($name) $value incr size } method size {} { return $size } ifdeleted { return 0 } } All fields must be declared before any constructors or methods. This allows our class to generate a list of the fields so it can properly alter the definition of the constructor and method bodies prior to passing them off to Tcl for definition with proc. A field may optionally be given a default/initial value. This can only be done for non-array type fields. Constructors are given full access to all fields of the class, so they can initialize the data values. The default values of fields (if any) are set before the constructor runs, and the implicit local variable $this is initialized to the instance identifier. Methods are given access to fields they actually use in their body. Every method has an implicit "this" argument inserted as its first parameter; callers of methods must be sure they supply this value. Some basic optimization tricks are performed (but not much). We try to only upvar (locally bind) fields that are accessed within a method, but we err on the side of caution and may upvar more than we need to. If a variable is accessed only once within a method and that access is by $foo (read) we avoid the upvar and instead use [set foo] to obtain the value. This is slightly faster as Tcl does not need to lookup the variable twice. We also offer some small syntatic sugar for interacting with Tk and the fileevent callback system in Tcl. If a field (say "foo") is used as "@foo" we insert instead the true global variable name of that variable into the body of the constructor or method. This allows easy binding to Tk textvariable options, e.g.: label $w.title -textvariable @title Proper namespace callbacks can also be setup with the special cb proc that is defined in each namespace. [cb _foo a] will invoke the method _foo in the current namespace, passing it $this as the first (implied) parameter and a as the second parameter. This makes it very simple to connect an object instance to a -command option for a Tk widget or to a fileevent readable or writable for a file channel. Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Diffstat (limited to 'lib/database.tcl')
0 files changed, 0 insertions, 0 deletions