At this point we can correctly create and move ideas, with the ideas appearing in the correct place on every user's screen. Lets now extend the program to identify who entered each idea. GroupKit keeps track of a designated color for each user which we can use to do this (participants can specify their personal color in their preferences file or via the "Pick Color" menu item in their session manager).
GroupKit stores each user's color (as well as other information) in a data structure called an environment. Environments are structured as a tree, where each node can contain either other nodes or a value. A node is referred to by its position in the tree, with each level of the tree separated by a dot. So for example, local.usernum refers to the node usernum which is a child of local which is a child of the root node of the environment. This is similar to how Tk refers to windows in the window hierarchy.
Information about each user is stored in the environment called gk::users, stored underneath a key holding the user's number. The special key "local" is an alias pointing to the local user's information. So for example if the local usernum (retrieved as "gk::users get local.usernum") was 20, you could access the local user's color as either "gk::users get local.color" or "gk::users get 20.color".
Information on other user's is stored under their respective user numbers. You can get a list of all the user numbers of remote users via the special alias "gk::users keys remote". More examples of how to use environments are described in the sidebar "Using Environments".
Figure XX. Users environment.
Using Environments
Environments have a number of different commands used to manipulate them. If you're familiar with Extended Tcl's keyed lists, you'll find some similarities. Some of the commands include:
- gk::environment envname. Create a new environment, which also creates a Tcl command called "envname" used to access the environment.
- envname set key value. Set the value of the node located at key.
- envname get key. Get the value of the node located at key.
- envname keys key. List the children of the node located at key.
- envname delete key. Delete the node located at key (and all nodes below it).
- envname exists key. Check if a node located at key exists in the environment.
- envname destroy. Destroy an environment, all data in it, and its Tcl command.
GroupKit maintains a number of environments internally. You've seen the gk::users environment which holds information about all the users in the conference, including their color (the key "color"), their full name ("username"), their userid ("userid"), and host ("host"). You can also store your own information in the users environment, to be used by your application. The other environment you've encountered briefly is the gk::preferences environment, which is used within the preferences file to specify where different conferences exist. Environments are also used extensively throughout the internals in GroupKit.
Lets add this into our program now. When we create an idea, we'll send our user number along with the idea. When creating the text item to display the idea, we'll change its color to be that of the user who created it. We'll also add a canvas tag to the text item identifying the user who created it, which we'll come back to later. Here are the changes in the code:
proc addNewIdea {} { ... gk::to all doAddIdea $id [gk::users get local.usernum] $notes(x) $notes(y) $idea ... } proc doAddIdea {id usernum x y idea} { ... set color [users get $usernum.color] .notepad create text $x $y -text $idea -anchor nw -font $notes(notefont) \ -fill $color -tags [list $id user$usernum] ... }Environments provide a convenient way to find out information on other users. They also have other features that can help in building groupware, which we'll return to later. In the meantime however, we'll look at another GroupKit feature called conference events.