tkMOO-light

An Example Application for tkMOO-light

The Browser Screen The Object Browser displays the inheritance tree for objects in the MOO database. Each object number is a hyperlink in blue which expands the inheritance tree below the selected generic object. Clicking on a link causes the client to invoke a short MOO program which delivers data back to the client and which is used to build the new display. The client has a simple caching mechanism so that once a link has been selected any subsequent clicks on that link will recover information from the cache.

Output of the @browse Command

The @browse command sends data back to the client using the XMCP/1.1 format. The command can be invoked by hand, but is usually invoked by the client. The browse* message is a multiline message, with a header containing the name and object id of the browsed object and its parent, and with data lines containing the name and object id of each of its subclasses or instances.

The client relies upon a single verb on the MOO which, in turn, communicates with the client using XMCP/1.1.

The following output is from the @browse command when invoked as

@browse #184 .br37
#184 is the object being browsed and .br37 is an optional tag which identifies the window that the client should use for the new data. If no tag is present then the client responds by creating a new window for the new data. All XMCP/1.1 messages carry an authentication key, in this instance the string 37748759, and each multi-line message has its own session-unique tag, in this instance the string 1686566601. The linebreak '\', in the browse* message is there for the sake of readability.
    $#$browse* 37748759 browser: .br37 this_name: generic containing object \
        this_obj: #184 parent_name: generic event dispatching object parent_obj: #127 tag: 1686566601 
    $#$data tag: 1686566601 data: name: "generic room" obj: #3 
    $#$data tag: 1686566601 data: name: "generic player" obj: #6 
    $#$data tag: 1686566601 data: name: "generic container" obj: #165 
    $#$END tag: 1686566601 

The Server-Client Interface

The Object Browser is written in Tcl/Tk and forms a distinct modular component of the client. The browser is written in a way which doesn't dictate which protocol you chose to use to send Out Of Band messages to the client. On most sites the client accepts XMCP/1.1 and passes the output of the @browse command to the Object Browser. On JHM the protocol being used is MCP/1.0, so there's a different set of routines defined which map MCP/1.0 requests onto the Object Browser. In order to speak to XMCP/1.1 aware sites the client uses the following Tcl procedures:
    proc xmcp11.do_browse* {} {
        if { [xmcp11.authenticated] == 1 } {
            request.set current xmcp11_multiline_procedure "browse*"
        }
    }

    proc xmcp11.do_callback_browse* {} {
        set which [request.current]
        set browser   [request.get $which browser]
        set this_name   [request.get $which this_name]
        set this_obj    [request.get $which this_obj]
        set parent_name [request.get $which parent_name]
        set parent_obj  [request.get $which parent_obj]
        set children    [request.get $which _lines]
        browser.SCbrowse $browser $this_name $this_obj $parent_name $parent_obj $children
    }
The procedure do_browse* is invoked by the first line of the XMCP/1.1 message and tells the client the name of a procedure to call when the multi-line message has been completed. The procedure do_callback_browse* is invoked when the final $#$END message is received. The interviening $#$data messages have been safely stored away in the client's request database and they are retrieved in do_callback_browse* and passed as parameters to the Browser proper in a call to browser.SCbrowse.

All of tkMOO-light's appliactions have SC procedures which define the public interface to the aplpication which should be called when dealing with information being sent from the Server to the Client.

The Object Browser

When the client receives a browse* message, or when an object's details are already in the browser's cache, the procedure browser.SCbrowse is called to display the new page of information.

The new information is entered in to the browser's cache using the procedure browser.set and if the special token "new" is present as the window identifier then a new broswer window is created. The window is then emptied of any data it might already contain and the browsed object's detail, and those of its parent are written to the window. The parent object's object id is printed and turned into a hyperlink using the procedure browser.link detailed below. If the object has children, either instances or subclasses then they are also printed on the window, but indented, using the procedure browser.recurse.

    proc browser.SCbrowse { browser this_name this_obj parent_name \
        parent_obj children } {

        browser.set $this_obj ok 1
        browser.set $this_obj name $this_name
        browser.set $this_obj parent $parent_obj
        browser.set $parent_obj name $parent_name
        browser.set $this_obj children $children
    
        if { $browser == "new" } {
            set browser [browser.create]
        }
    
        wm title $browser "Object Browser: $this_name ($this_obj)"
        wm iconname $browser "Object Browser"
    
        $browser.text configure -state normal
        $browser.text delete 1.0 end
    
        $browser.text insert insert "PARENT: $parent_name ("
            browser.link $browser $parent_obj
        $browser.text insert insert ")\n"
        $browser.text insert insert "  NAME: $this_name ($this_obj)\n"
    
        browser.recurse $browser $children 0
    
        $browser.text configure -state disabled
    }
The Browser's links are coloured blue, just like for a normal HTTP web browser. If a link points to an object that has already been cached by the browser then the link is darkblue. The Tcl bind command defines the shape of the cursor when it is over a link and also defines which commands are activeated when a link is selected. Clicking button one on the mouse will execute the procedure browser.try_cache, which means that if possible the data already present in the cache will be used to form the page. Holding down the shift key and pressing button 1 will force the browser to reload the information from the MOO. The procedure io.outgoing writes directly to the MOO.
    proc browser.link { browser obj } {
        set new_link [util.unique_id "link"]
        $browser.text tag bind $new_link <1> "browser.try_cache $obj $browser"
        $browser.text tag bind $new_link <Shift-1> "io.outgoing \"@browse $obj $browser\"" 
        $browser.text tag bind $new_link <Enter> "$browser.text configure -cursor hand2" 
        $browser.text tag bind $new_link <Leave> "$browser.text configure -cursor {}"   
        if { [browser.get $obj ok] == 1 } {  
            $browser.text tag configure $new_link -foreground darkblue
        } {
            $browser.text tag configure $new_link -foreground blue
        }
        $browser.text insert insert $obj $new_link
    }