[Xotcl] Re: [Xotcl] Re: [Xotcl] Widgets
Catherine Letondal
letondal at pasteur.fr
Tue Feb 6 16:15:56 CET 2001
Gustaf Neumann wrote:
>
> Catherine, you seem to be quite happy with your Tk integration. Can
> you post a small but complete introductory example. Do you use Tk
> features like "-command"?
>
Yes I do, as well as -variable -textvariable and bindings.
I use [incr tk] as well (for which I have to help the Xotcl widgets
tree to correspond to the actual tk tree).
The aim was to be able to keep the actual tk creation/layout code that you can
borrow in books, ftp sites, application examples, ... it's very important
to me to keep such examples usable without any adaptation.
Another aim is to be able to have a memory image of the Tk widgets state, for
I want my application to be persistent, or just to be able to edit or clone objects
with their tk widgets.
A 3rd goal is to keep advantages of the composite pattern.
For instance, as the general idea of the application (very influenced by the Self
environment although much more modest) is to have a graphical handle for application
objects (I don't mean all XOtcl objects, but application level ones), I need to be
able to find this object from a menu which may be posted from any location in the GUI.
So I will try to summarize a small example - it's impossible to make
it complete though, there is too much code and it's not ready for
distribution - at all.
# -----------------------------------------------------------------------------
# composite pattern
[... same as in the Xotcl paper...]
Composite AbstractNode
AbstractNode filter compositeFilter
AbstractNode abstract instproc iterate v
# -----------------------------------------------------------------------------
# GraphObject is the general graphical object class
GraphObject instproc draw args {
[...]
# generic frame for all graphical objects
set frame ${object_name}_frame
widgets build $frame {
frame $path -borderwidth 2 -relief sunken
}
widgets layout $frame {
pack $path -expand 1 -fill both
}
# location for custom widgets (as in [incr tk])
[self] instvar childsite
set childsite ${frame}::widgets
[...]
}
# -----------------------------------------------------------------------------
# example: a field object
# (containing an entry widget and a button)
Class Field -superclass GraphObject
Field instproc init args {
[...]
[self] draw
}
Field instproc draw args {
next
[self] instvar childsite
set path [$childsite set path]
widgets build $childsite {
frame $path
}
widgets layout $childsite {
pack $path -expand 1 -fill both
}
# -------------------------------------------------------------
# 1st tk widget: an entry
[self] instvar data
# datavar contains the name of a global variable
set datavar [$data set datavar]
widgets build ${childsite}::datafield {
entry $path.datafield -textvariable $datavar
}
widgets layout ${childsite}::datafield {
pack $path.datafield -side top -expand 1 -fill x
}
::bind $path.datafield <Return> {
set object [names object %W]
# MVC protocol
[$object set data] update
}
# -------------------------------------------------------------
# 2nd tk widget: a button
widgets build ${childsite}::doit {
button $path.doit -command [list [self] do_something] -text "DoIt"
}
widgets layout ${childsite}::doit {
pack $path.doit -side left
}
# -------------------------------------------------------------
# connect all widgets to the current graphical object
$childsite iterate setObjectName [self]
# bind button3 to a "meta" menu for all the widgets hierarchy
$childsite iterate bindMetaButton
}
# -----------------------------------------------------------------------------
# Widgets
Class Widgets -superclass AbstractNode
Class Widget -superclass Widgets
Object widgets
widgets proc build {widget body} {
# XOtcl Widget creation
uplevel Widget $widget
# actual tk creation
if [catch {set path [uplevel $body]} err] {
global errorInfo
puts stderr "widgets (build) err:$err\n$errorInfo"
} else {
[self] setwidget $widget $path
}
}
widgets proc setwidget {widget path} {
# data structure initializations
$widget set path $path
$widget set type [string tolower [winfo class $path]]
$widget set options [[self] buildoptions $path]
}
widgets proc layout {widget body} {
# actual layout
if [catch {uplevel $body} err] {
global errorInfo
puts stderr "Widget (layout) err:$err\n$errorInfo"
} else {
# data structure initializations...
$widget set layout [[self] buildlayout [$widget set path]]
}
}
# -----------------------------------------------------------------------------
# visitors for widgets hierarchy
Class TreeVisitor
TreeVisitor abstract instproc visit objectName
# menu for graphical objects
TreeVisitor bindMetaButton
bindMetaButton proc visit args {
set node [lindex $args 0]
set path [$node set path]
if [::winfo exists $path] {
::bind $path <ButtonPress-3> {
set object [names object %W]
${object}::menu display $object [$object set commands] %x %y %X %Y %W
break
}
}
}
TreeVisitor setObjectName
setObjectName proc visit args {
set node [lindex $args 0]
set obj [lindex $args 1]
$node instvar object
if { $obj != "" } {
set object $obj
}
if { [names object [$node set path]] == "" } {
names object [$node set path] $obj
}
}
# -----------------------------------------------------------------------------
# names: name server (alias, graphical objects, widgets,...)
Object names
# bind graphical objects and tk widgets
names proc object {widget {object ""}} {
[self] instvar objects
if {$object == ""} {
if [info exists objects($widget)] {
[self] set objects($widget)
}
} else {
[self] set objects($widget) $object
}
}
--
Catherine Letondal -- Pasteur Institute Computing Center
More information about the Xotcl
mailing list