Dylan TK library
The TK Library
1. Introduction and Warning
Dylan/TK is an experimental TK binding for the Mindy Dylan interpreter. Although it is definitely usable, it is not intended to be an "industrial strength" product. The implementation strategy virtually guarantees that there will be some rough edges.
This binding operates by starting a wish interpreter as a slave process and passing both Tcl routines and data between the Mindy interpreter and the slave process. However, Dylan/TK provides an abstraction layer that should vastly reduce or even eliminate the need for users to be familiar with the Tcl extension language. For example, the following Dylan code:
define constant text-frame
= make(<frame>, height: 500, fill: "both", side: "bottom", expand: #t);
define constant text-window
= make(<text>, in: text-frame, relief: "sunken", font: normal-font,
fill: "both", side: "right", expand: #t);
define constant text-scroll
= scroll(text-window, in: text-frame, fill: "y");
could be used to produce the effect as the following Tcl/Tk code:
frame .text-frame -height 500
pack .text-frame -fill both -side bottom -expand 1
text .text-frame.text -relief sunken -font normal-font
pack .text-frame.text -in .text-frame -fill both -side right -expand 1
scrollbar .text-frame.scroll -command {.text-frame.text yview }
.text-frame.text configure -yscrollcommand {.text-frame.scroll set }
pack .text-frame.scroll -in .text-frame -fill y
while being considerably clearer to the average Dylan programmer.
Note: In order for this implementation to work you must have a copy of wish available on your system. This implementation was developed upon version 4.0 of Tcl/Tk but should work any version Tk implementation after 4.0. Since version 4 introduces incompatible changes, you should not (at present) expect all features to work with earlier versions.
2. General Principles
In order to use Dylan/Tk, you should import module Tk from library Tk. This defines the <window> class, a variety of subclasses representing most of the Tk widgets, and a variety of support routines. All of these will be explained in some detail below. However, the user will sometimes find that he can gain more information by going to the book Tcl and the Tk Toolkit by John Osterhout, which explains the widgets behavior in more depth than is practical for this document.
Any Dylan program which uses the Tk library will automatically create a top level window (which is accessible via the *root-window* variable) and a separate thread to process events upon that window. You build an interface by making widgets and "packing" them into windows -- either the root window, newly created top-level windows, or into subwindows of these windows.
An simple application might be the following:
define method main (program-name :: <string>, #rest args);
make(<message>, text: "Hello, world!", aspect: 500, side: "top");
make(<button>, text: "Okay", relief: "raised",
command: curry(destroy-window, *root-window*), expand: #t);
map-window(*root-window*);
end method main;
This creates a text message and a pushbutton, packs them into the root window, and then exits, and makes the root window visible. It then exits the main thread, leaving just the event processing thread active. When the button is pressed, it will destroy the root window (and all its subwindows). Since there are no windows left, the event thread exits, and the program terminates. We could just as easily specified "command: exit", which would force the Dylan program to exit, killing off all threads, and thus destroying the windows. Go ahead and try it, if you like.
Widgets, like any other Dylan object, are typically created via make. There are three different varieties of keywords which can be specified:
- Widget Specific Options:
- These include the aspect: and command: keywords in the above example. Their precise effects depend upon the definition of the widget.
- Standard Options:
- These include the relief: keyword in the above example. They are accepted by most (if not all) widgets, and have pretty much the same effect for all of them. (Some keywords, like text:, are not accepted by all widgets, but are common and predictable enough that users may be left to infer their effects.)
- Packing Options:
- These include the side: and expand: keywords in the above example. They are used to control the positioning and resizing of the new widgets within their "parent" windows. They are, for the most part, passed on directly to the pack function. In very rare cases, you will wish to create a window without (yet) packing it into another window. In this case, you can specify pack: #f to defer calling pack until you are ready to do so.
3. Parameter and Return Values
The values which are passed into make or into many other Tcl/Tk functions are passed into to Tcl/Tk as strings, and thus it is sometimes most convenient to write them as strings in Dylan. Most Dylan/Tk functions therefore accept strings as parameter values. However, you will usually find it easier to work with a richer set of types within Dylans type system. Parameters values can commonly include instances of the following native Dylan classes:
- <boolean>
- <integer>
- <function>
- <string>
- <sequence>
- <class>
and will occasionally include others on a case-by-case basis. In addition, the following new classes are also frequently accepted as parameter values:
- <window>
- <tk-variable>
- <text-index>
- <text-mark>
Those Dylan/Tk functions which return values typically cast the results back into meaningful Dylan types before returning them. However, there are some occasions where this proves impractical, and result values remain as <string>s which must be explicitly cast into appropriate types. For example, the configuration function returns the values of all the configuration options for a widget. Since it cant guess what the types of these values ought to be, they simply remain as <string>s.
In some cases you must specify callback functions for Dylan/Tk widgets. These are typically specified via the command: keyword to make. On the few occasions where these functions take parameters, they will be passed in as <string>, and may include "\" quotation characters. You may need to call tk-unquote to strip out backslashes or to call tk-as to convert this to another type. For example: tk-as(<boolean>, "1") returns #t.
4. The "Standard" Options
The following options seem to apply universally to all widgets. They are mostly concerned with presentation details of the widgets window, as opposed to the widgets function.
- background:
- This specifies the background color to be used within the widget. Typically it is a color name, like Black or LightBrown, or as hexadecimal integers, like #x3a7 or #x3000a0007000.
- borderwidth:
- This specifies the size of the border to be placed around the window. Typically this will be an integer which specifies the number of pixels, but you may also use string values like "1c", "1m", "1i", "1p", which specify centimeters, millimeters, inches, and points respectively. This keyword is typically combined with the relief: keyword.
- cursor:
- This specifies a bitmap which will be displayed when the users cursor is in this widget. The most useful forms will be name to specify a name from the standard cursor font, or @Sourcefile fgColor to load the cursor from a file.
- foreground:
- This specifies the background color to be used within the widget. Typically it is a color name, like Black or LightBrown, or as hexadecimal integers, like #x3a7 or #x3000a0007000.
- highlightbackground:
- This specifies the color of the highlight area (a thin border surronding the widget) when it is disabled. This is normally a color name, like Black or LightBrown, or as hexadecimal integers, like #x3a7 or #x3000a0007000.
- highlightforeground:
- This specifies the color of the highlight area (a thin border surronding the widget) when it is enabled. This is normally a color name, like Black or LightBrown, or as a hexadecimal integer, like #x3a7 or #x3000a0007000.
- highlightthickness:
- This specifies the thickness of the highlight area. Typically this will be an integer which specifies the number of pixels, but you may also use string values like "1c", "1m", "1i", "1p", which specify centimeters, millimeters, inches, and points respectively. A value of zero will remove the highlight ring.
- relief:
- This specifies what sort of 3D border should be displayed around the widget. This must be one of: "flat" (default), "groove", "raised", "ridge", or "sunken".
Other options are by no means universal, but tend to mean the same thing whenever they occur:
- bitmap:
- This specifies a bitmap which will be displayed in the given widget. The most useful forms will be name to specify a name from the standard cursor font, or @Sourcefile fgColor to load the cursor from a file.
- command:
- This specifies an action to be taken when a particular widget is invoked or when values associated with the widget change. Typically this will be a Dylan function, but it may also be a bit of Tcl code which can be executed directly by the interpreter. The number of parameters which might be passed to the function vary depending on the widget, but they will all be passed in as <string>s.
- font:
- This is a string which specifies the font to be used for any text which is displayed within the widget.
- justify:
- This is a string which specifies how the text within the widget is to be justified. Possible valuse are "left", "center", and "right".
- state:
This specifies whether the given widget is in an active state. Typically, any widget which accepts a command: keyword will accept this keyword as well. Acceptable values are "normal", "disabled", and sometimes "active" (for buttons only).
- text:
This is a string which will be displayed in the widget in an implementation dependent way. A few widgets also take a label: keyword which acts much the same way.
- textvariable:
This specifies a "variable" containing a value which will be displayed in the widget. If the variables value changes, the widget is updated. If the widget allows editing, the variable will be updated after each change. Dylan/Tk programs will typically supply a <tk-variable> object for this keyword. (These will be explained in a later section.)
- underline:
This specifies a charater in the text string of a widget to underline.
- variable:
This functions much like the textvariable: keyword, but tends to be displayed somewhat differently.
5. Windows
The abstract type <window> represents any one of a wide variety of widgets, although it doesnt include pseudo-widgets like menu entries, text tags, or canvas items (which will be discussed later). They are almost always created via make, which accepts all of the standard options described above, as well as the packer options name:, in:, after:, before:, side:, expand:, padx:, pady:, and pack:. (Packing will be described briefly in the next section.) All windows except <toplevel>s must specify their parents by some means -- either directly via in: or indirectly via after: or before:.
You also have the right to specify a debug name for the window via the name: option. If you refuse this right, one will be created for you automatically.
One window is automatically created as a result of importing the tk library. This is the top level window *root-window*.
There are a small set of methods which operate upon all windows:
configure (widget :: <window>, #all-keys) [Function]
Configure accepts pretty much the same options as initialize, and uses them to change the state of the object.
configuration (widget :: <window>) => (result :: <sequence>) [Function]
Returns a complete list of options for the given widget. Each option consists of a sequence of the switch name, rdb name, rdb class, default, and value. The "value" will be a string, which may be converted to a more pleasing form via either tk-as or tk-unquote.
map-window (window :: <window>) => () [Function]
Make sure that a window is displayed on the screen. *root-window* is unmapped initially, so nothing will appear until you call map-window(*root-window*).
unmap-window (window :: <window>) => () [Function]
Remove a window from the display. This is handy to keep from showing intermediate states of newly defined windows.
destroy-window (window :: <window>) => () [Function]
Completely obliterate a window, removing it from the screen and all knowledge of mankind.
pack (window :: <window>, #all-keys) => (window :: <window>) [Function]
This is explained in the next section. You should never need to call pack unless you either specified "pack: #f" when making the window or you used the unpack function to remove it from the display.
unpack (window :: <window>) => (window :: <window>) [Function]
This hides a window which has previously been packed into another window. The window still exists, and may be updated or repacked into its parent. You may not pack the window into a different parent -- this will result in errors.
\= (window :: <window>, window :: <window>) => equal? :: <boolean> [Method]
\= (window :: <window>, path-name :: <string>) => equal? :: <boolean> [Method]
\= (path-name :: <string>, window :: <window>) => equal? :: <boolean> [Method]
The three \= methods are useful for comparing two windows to see if they are, in fact, the same widget. Most function which should return windows will return them as <window> objects, but if you are dealing with lower level Tk, it may be useful to compare a Tk window path-name to a Dylan <window> object.
6. Packing
Unless they are some sort of top level window (i.e. *root-window* or instances of <toplevel> or <menu>), windows must be "packed" into some containing window before they will appear on the screen. Normally, all Dylan/Tk windows are automatically packed when they are created, using the procedure and options described below. The exception to this is if the pack: option is given a value of #f or is the window was unpacked; in these cases, the pack function will need to be called explicity to display the window. The Dylan/Tk pack function closely follows the Tcl/Tk function described in "Tcl and the Tk Toolkit", and you should look there for more complete information. However, we will provide a brief overview here.
Each "slave" (i.e. non-top-level) window must be packed into some other window. You specify this window either directly, via "in: parent" or indirectly via "before: sibling" or "after: sibling". (The latter options specify that the window should have the same parent as the specified "sibling", and that they should be placed just before or after the sibling in the parents "packing order".) If no parent is specified explicitly, Dylan/Tk implicitly assumes "in: *root-window*".
The side: option specifies where the widget should be placed relative to the ones which follow it in the "packing order". If you specify "side: "left"", then all widgets which are packed into the parent after this one (either because they were created later or because of a before: or after: option) will be placed somewhere to the right of this widget. Note that it will not necessarily be placed on the parents absolute left side, because all windows which precede this one in the packing order have "first dibs" on prime real estate. Possible values for this option are "left", "right", "top", and "bottom" -- the default is "left".
If you were to execute:
let w1 = make(<listbox>, in: *root-window*, side: "left");
let w2 = make(<text>, before: w1, side: "top");
let w3 = make(<scrollbar>, after: w1);
you would end up with something like:
Window W2 comes first in the packing order (because of the before: option) and preempts the top of the root window. W1 comes second, and grabs the left side of the remaining space, leaving a small chunk on the right for W3 (and any windows which might be packed after W3).
The other options available are anchor:, expand:, fill:, padx:, and pady:, which are explained in the book. Expand: typically takes a boolean value, while fill: takes one of "x", "y", "both", or "none".
The unpack function will remove a window from the control of the "packer" and, as a side effect, remove it from the display. The window will still exist and can be updated or repacked via the pack function. You will, however, get errors if you try to specify a different parent when you repack it.
7. Event bindings
Each Dylan/Tk widget has a default set of "bindings" which determine how they react to X events like button or key presses. These may be changed or extended via the "bind" function. Windows, "tag" strings, and subclasses of <window> can have bindings, and more than one binding may apply to an event. All of the applicable bindings will get called, unless explicitly avoided, and the call order can be changed.
bind (window-tag-or-class, event :: <string>, command) => (window)
This function specifies an action to be performed when an X event matching "event" occurs. Typically this is a nil-adic Dylan function, but it may also be an arbitrary line of Tcl code. A typical binding might be the following:
bind(l1, "<Double-Button-1>", method ()
do(print-config, current-selection(l1))
end method);
This would cause Dylan/Tk to call print-config on each of the current selections in the <listbox> "l1" whenever the leftmost mouse button is double-clicked.
The first argument to this function may be a <window> object, in which case it acts on only that window, a "tag" string, which acts on all windows with that tag, or a subclass of <window>, which acts on all objects of that type.
There are five other utility functions which allow you to determine and manipulate the bindings for windows:
get-binding (window-tag-or-class, event) => (result :: <string>) [Function]
Returns the window, tag, or classs binding for a single event. Unless you have specified an explicit binding, this will be an empty string.
get-bindings (window-tag-or-class) => (result :: <sequence>) [Function]
Returns a complete list of explicit bindings for a window, tag string, or class. Each element of the sequence will be a <pair> of event-name and binding.
binding-call-order (window :: <window>) => (result :: <sequence>) [Function]
Returns a list of bindings that apply to a window, in the order that they are called. Each element is a Tk text string which could represent a window, a tag, or a class.
binding-call-order-setter (bindings :: <sequence>, window :: <window>) => (bindings :: <sequence>) [Function]
Sets the calling order for bindings. The elements of the sequence may be <window> objects, tag strings, or subclasses of <window>
tk-break () [Function]
If you dont want to call all bindings which apply to an event, use the tk-break command to stop the execution of bindings. This command must be executed on the top level of the binding, and not in any functions that the command calls.
8. Active Variables
Some widgets have the ability to take an obsessive interest in the value of some "variable". They may update their contents or appearance when the variables value changes, or they might update the variable in response to some user action. Because this level of monitoring is not supported by ordinary Dylan variables, Dylan/Tk users must instead use instances of <active-variable>.
Make on <active-variable> requires a value: keyword and accepts an optional class: keyword. If specified, the class defines the logical type of the variables value. The value slot will always contain a value of that type, although value-setter will accept arbitrary types (especially <string>) and attempt to convert them to the given type.
You may also specify a Dylan function to be executed when an active variables value changes (i.e. becomes \~= to the old value). This method is specified via the command: keyword to make. It will be invoked with both the new and the old value at some point after the value is changed. Note that the value is updated immediately (i.e. asynchronously), while the calls to the given command are executed sequentially along with event callbacks.
Active variables will typically be passed as values of variable: or text-variable: keywords.
9. The widget types
Dylan/Tk provides types corresponding to all of the standard Tcl/Tk widgets:
<button>:
- Options:
- Functions:
- activate (button) => button
- deactivate (button) => button
- invoke (button) => button
<checkbutton>:
- Options:
- Functions:
- select-value (button) => button
- deselect-value (button) => button
- toggle-value (button) => button
<menubutton>
- Options:
- Functions:
- activate (button) => button
- deactivate (button) => button
<radiobutton>:
- Options:
- Functions:
- select-value (button) => button
- deselect-value (button) => button
<canvas>:
- Options:
- Functions:
- xview (canvas :: <canvas>, index) => canvas
- yview (canvas :: <canvas>, index) => canvas
- find-items (canvas :: <canvas>, spec, spec-args) => found-items
- focus (canvas :: <canvas>) => result :: <canvas-item>
- focus-setter (value :: <canvas-item>, canvas :: <canvas>) => ()
- scan-mark (window :: <canvas>, #rest coords) => window
- scan-dragto (window :: <canvas>, #rest coords) => window
- select-item (window :: <canvas>, index) => window
- canvas-x (canvas :: <canvas>, screen-x, #key grid-spacing = 1) => x
- canvas-y (canvas :: <canvas>, screen-y, #key grid-spacing = 1) => y
- create-arc (canvas, x1, y1, x2, y2, #rest opts) => item
- Options include: #"extent", #"fill", #"outline", #"outlinestipple:", #"start", #"stipple", #"style", #"tags",, #"width"
- create-bitmap (canvas, x1, y1, #rest opts) => item
- Options include: #"anchor", #"bitmap", #"background", #"foreground", #"tags"
- create-line (canvas, points :: <sequence>, #rest opts) => item
- Options include: #"arrow", #"arrowshape", #"capstyle", #"fill", #"joinstyle", #"smooth", #"splinesteps", #"stipple", #"tags", #"width"
- create-oval (canvas, x1, y1, x2, y2, #rest opts) => item
- Options include: #"fill", #"outline", #"stipple", #"tags", #"width"
- create-polygon (canvas, pnts :: <sequence>, #rest opts) => item
- Options include: #"fill", #"outline", #"smooth", #"splinesteps", #"stipple", #"tags", #"width"
- create-rectangle (canvas, x1, y1, x2, y2, #rest opts) => item
- Options include: #"fill", #"outline", #"stipple", #"tags", #"width"
- create-text (canvas, x1, y, #rest opts) => item
- Options include: #"anchor", #"fill", #"font", #"justify", #"stipple", #"tags", #"text", #"width"
- create-window (canvas, x1, y1, #rest opts) => item
- Options include: #"anchor", #"height", #"tags", #"width", #"window"
- postscript (canvas, #rest opts) => result :: <string>
- Options include: #"colormap", #"colormode", #"fontmap", #"height", #"pageanchor", #"pageheight", #"pagewidth", #"pagex", #"pagey", #"rotate", #"width", #"x", #"y".
<entry>:
- Options:
- Functions:
- icursor (entry, index) => entry
- xview (entry, index) => entry
- delete (entry, index, #key end: last) => entry
- insert (entry, index, #rest elements) => entry
- get-all (entry) => result :: <string>
- get-elements (entry, index, #key end) => result :: <string>
- scan-mark (entry, #rest coords) => entry
- scan-dragto (entry, #rest coords) => entry
- select-adjust (entry, index) => entry
- select-clear (entry) => entry
- select-from (entry, index) => entry
- select-to (entry, index) => entry
<frame>:
- Options:
- Supports no operations.
<label>:
- Options:
- Supports no operations.
<listbox>:
- Options:
- Functions:
- clear-selection (listbox, first :: <integer>,#rest last) => ()
- current-selection(listbox, #rest rest) => indices :: <sequence>
- nearest(listbox, y-coord) => index :: <integer>
- size(listbox) => result :: <integer>
- xview(listbox, index) => listbox
- yview(listbox, index) => listbox
- delete (listbox, index, #key end) => listbox
- insert (listbox, index, #rest elements) => listbox
- get-all (listbox) => result :: <string>
- get-elements (listbox, index, #key end) => result :: <string>
- scan-mark (listbox, #rest coords) => listbox
- scan-dragto (listbox, #rest coords) => listbox
- see (listbox, index) => ()
- select-adjust (listbox, index) => listbox
- select-clear (listbox) => listbox
- select-from (listbox, index) => listbox
- select-to (listbox, index) => listbox
- selection-anchor-setter (listbox, index) => listbox
- selection-includes? (listbox, index) => in-selection? :: <boolean>
- set-selection (listbox, first :: <integer>, #rest last) => ()
<menu>:
- Options:
- Functions:
- activate-entry (menu, index) => menu
- delete (menu, index, #key end) => menu
- configure-entry (menu, index, #rest options) => menu
- entry-configuration (menu, index) => result :: <sequence>
- invoke-entry (menu, index) => result
- post-cascade (menu, index) => ()
- yposition-entry (menu, index) => result :: <integer>
- add-command (menu, #key state, command, label) => ()
- add-checkbutton (menu, #key variable, label) => ()
- add-radiobutton (menu, #key variable, value, label) => ()
- add-cascade (menu, #key menu, label) => ()
- add-separator (menu) => ()
- Note that if you wish to assocaiate a menu with a menubutton, you must create it in: that button.
<message>:
- Options:
- Supports no operations.
<scale>:
- Options:
- Functions:
- get-value (scale) => result :: <integer>
- set-value (scale, value) => scale;
<scrollbar>:
- Options:
- Functions:
- scroll (widget, #key, #all-keys) => scrollbar
- get-units (scrollbar) => (#rest units :: <integer>)
- set-units (scrollbar, #rest Units) => scrollbar
- The scroll function exists to reduce the inefficiency inherent in "standard" method of connecting widgets to scrollbars. This function creates a new scrollbar with the given orientation (i.e. "vertical" or "horizontal") and connects it via lower level mechanisms to the given widget. All of the applicable creation and packing options for scrollbars are accepted.
<text>:
- Options:
- Functions:
- yview (text, index) => text
- delete (text, index, #key end) => text
- insert (text, index, #rest elements) => text
- get-all (text) => result :: <string>
- get-elements (text, index, #key end) => result :: <string>
- scan-mark (text, #rest coords) => text
- scan-dragto (text, #rest coords) => text
- select-adjust (text, index) => text
- select-clear (text) => text
- select-from (text, index) => text
- select-to (text, index) => text
- tags (text) => result :: <sequence>
<toplevel>:
- Options:
- Functions:
- tk-dialog (toplevel, title, text, bitmap, default, #rest buttons) => button :: <integer>
- Tk-dialog automatically creates a dialog box with the given title, text, bitmap and buttons. The default argument is an integer that corresponds to the button that should be made the default (beginning at zero for the left-most button)
These operations will hopefully be described at greater length in future editions of this document, but for now you are encouraged to check the Tcl/Tk manual for further information.
10. Text indices
The types <text-index>, <text-mark>, and <text-tag> all represent references to the contents of a <text> window. Functions are provided to let you create and manipulate instances of these types.
<Text-index>s represent an "absolute" index within a <text> object. They have two slots -- line and character. Make on <text-index> requires a line: keyword and accepts an optional character: keyword (which defaults to 0). Lines numbers start at 1, while characters start at 0, so you could specify the first character of a <text> by calling make(<text-index>, line: 1, character: 0)
The following functions create and manipulate <text-index>s:
- text-at (line, character) => result :: <text-index>
- line-end (line) => result :: <string>
- as (cls == <text-index>, value :: <string>) => string
- as (cls == <string>, value :: <text-index>) => text-index
The text-at function provides a convenient shorthand for making <text-index>s. You might, for example replace the above make call with text-at(1, 0);
Line-end creates a reference to the last character of the named line.
11. Text marks
<Text-mark> objects represent more abstract character positions. It will continue to refer to the same character even if other text is added or deleted. They have two slots -- value and name, and are associated with a particular <text> widget via the required make keyword in:.
If you make a <text-mark> with the name of a "standard" Tcl/Tk mark, such as "end" or "insert", then the new object will pick up the values already associated with the Tcl/Tk mark.
The following functions create or manipulate <text-mark>s:
- as (cls == <string>, object :: <text-mark>) => string
- as (cls == <text-index>, mark :: <text-mark>) => text-index
- marks (text :: <text>) => result :: <sequence>
The marks function returns a sequence containing all of the marks within a given <text>. This will include both the "standard" Tcl/Tk marks and any that you have created. These will not necessarily be == to the original objects.
12. Text tags
<Text-tag>s represent attributes which may be associated with zero or more sequences of characters in a specific <text>. You may specify different display properties or event bindings for the characters that have been associated with a particular <text-tag>.
<Text-tag>s are created within a particular <text> via make, which requires an in: keyword. Optional keywords include name:, bgstipple:, fgstipple:, font:, justify:, lmargin1:, lmargin2:, offset:, overstrike:, relief:, rmargin:, spacing1:, spacing2:, spacing3:, tabs:, wrap:, and underline:. Although tags are not widgets, they support the configure, configuration, and bind functions. You may add ranges of characters to <text-tag>s via add-tag. A complete list of functions upon <text-tag>s follows:
- configure (tag, #rest options) => tag
- configuration (tag, index) => result :: <sequence>
- bind (tag, event :: <string>, command) => tag
- as (cls == <string>, object :: <text-tag>) => string
- add-tag (tag, #key start, end: last) => tag
- remove-tag (tag, #key start, end: last) => tag
- tags (text :: <text>) => result :: <sequence>
- delete-tag (tag) => ()
- raise-tag (tag, #key past :: <text-tag>) => ()
- lower-tag (tag, #key past :: <text-tag>) => ()
- next-range (tag, #key start, end) => result :: false-or(<pair>)
13. Canvas items and tags
<canvas-item>s represent different graphical entity within a <canvas>. Each create-shape function returns a <canvas-item> corresponding to the newly created shape. These may be used to delete, resize, move, or respecify the shape. Although canvas items are not widgets, they support the configure, configuration and bind functions. The configuration options which are accepted for a given item depend upon its type. You should consult the list of create-... functions for a list of options.
<canvas-tag>s are a convienient way of grouping various canvas items. If more than one item has a given tag, then any operation performed on the tag will be applied to all items with that tag. Tags may be created using the make method with required keywords #"in", the canvas that contains that tag, and #"name", a string identifier. Tags may be assigned to <canvas-item>s when they are created, by giving a single <canvas-tag> or a sequence of <canvas-tag>s in the #"tags" keyword.
The following functions operate upon canvas items and canvas tags:
- configure (item, #rest options) => item
- configuration (item, index) => result :: <sequence>
- bind (item, event :: <string>, command) => item
- delete-item (item) => ()
- raise-item (item, #key past :: <canvas-item>) => ()
- lower-item (item, #key past :: <canvas-item>) => ()
- move-item (item, x :: <object>, y :: <object>) => ()
- scale-item (item, x-origin, y-origin, x-scale, y-scale) => ()
- item-coords (item) => result :: <sequence>
- item-coords-setter (value :: <sequence>, item) => ()
- item-type (item) => result :: <string>
- add-canvas-tag (item, spec, spec-args) => ()
- get-canvas-tags (item) => tags :: <sequence>
- delete-canvas-tag (item, tag-to-delete) => ()
14. Window Information commands
There are a variety of window information commands that return various data about the state of the widgets, most of these corresponding to Tcl/TK "winfo" commands. There are also two new objects that are returned by some of these functions, <point> and <rgb-color>. <point> has slots x and y, both integers, and <rgb-color> has slots red, green, and blue, all integers. Functions that return these classes come in two forms for flexibility in programming. One form has the class name appended to the function name , which returns the named object (e.g. mouse-point returns a <point>). The second form lists the components as part of the function name, and returns each component individually, as multiple values (e.g. mouse-x-y returns the values x and y). A complete list of the window information functions follows.
- colormap-cells (window) => c-m-cells :: <integer>
- colormap-full? (window) => c-m-full? :: <boolean>
- children (window) => child-seq :: <sequence>
- window-containing-x-y (x, y, #key on-display-of = #f) => window
- window-containing-point (point :: <point>, #key on-display-of = #f) => window
- depth (window)=> colors :: <integer>
- exists? (window) => exist? :: <boolean>
- distance-to-float-pixels (dist, #rest units) => pixels
- geometry (window) => geom-string
- height (window) => h
- X-id (window) => id :: <integer>
- mapped? (window) => map? :: <boolean>
- geometry-manager (window) => manager :: <string>
- window-with-X-id (id :: <integer>, #key on-display-of = #f) => window
- distance-to-pixels (dist, #rest units) => pixels :: <integer>
- mouse-x-y (window) => (x, y)
- mouse-point (window) => point :: <point>
- requested-height (window) => h
- requested-width (window) => w
- width (window) => w
- color-to-r-g-b (window, color :: <string>) => (red, green, blue)
- color-to-rgb-color (window, color :: <string>) => rgb-color :: <rgb-color>
- abs-position-x-y (window) => (x, y)
- abs-position-point (window) => point :: <point>
- screen-name (window) => name
- screen-colormap-cells (window) => num-cells :: <integer>
- screen-depth (window) => bit-depth :: <integer>
- screen-height (window) => h
- screen-width (window) => w
- server (window) => srv :: <integer>
- toplevel (window) => top :: <window>
- viewable? (window) => view?
- visual-class (window) => vis-class :: <string>
- available-visuals (window) => avail-vis :: <sequence>
- virtual-root-height (window) => h
- virtual-root-width (window) => w
- virtual-root-position-x-y (window) => (x, y)
- virtual-root-position-point (window) => point :: <point>
- x-y-in-parent (window) => (x, y)
- point-in-parent (window) => point :: <point>
Notes on the functions:
Distance-to-pixels and distance-to-float-pixels take a units paramater that could be one of #"centimeters", #"inches", #"millimeters", or #"points".
X-y-in-parent and point-in-parent return the position of the upper-left corner of the window in its parent window.
Abs-position-x-y and abs-position-point return the position of the upper-left corner of the window relative to the root window.
Mouse-x-y and mouse-point return the position of the pointer relative to the argument window.
Anything that returns a <window> or a sequence of <window>s will return a new object which refers to the same Tk widget. A \= method is provided for comparing these to the previously existing ones.
15. Requested Enhancements
Allow event bindings to access the window, mouse coords, character, and other "%" substitutions.
Add better support for scale and scrollbar widgets.
Provide a "focus" command.
Revise the interface to provide a more uniform object-oriented integration of <window>s, <text-tag>s, and <canvas-item>s. (This would probably be an incompatible change.)
16. The Extension Protocol
Because early versions of Dylan/Tk dont support the entire functionality of Tcl/Tk, users may wish to interface directly with the underlying Tcl/Tk interpreter. This capability is provided by the Tk-extension module. (Note: if any user decides to use these capabilities to provide a firm interface to a Tcl/Tk subsystem (e.g. the "wm" command), we would willingly incorporate such code into future versions of this library.)
The following functions are exported:
tk-as (cls :: <class>, value) => result :: <object> [Generic Function]
Performs conversions comparable to as, but adds some which do not generalize outside Tk -- for example, tk-as(<boolean>, "1") == #t.
You may wish to add methods to this function for any new Dylan types you add.
put-tk-line (#rest pieces) => () [Function]
Converts all of the input arguments into strings (using tk-as), concatentates them into a line of tk input, and sends then to the running tk process. This routine expects no results and therefore does not wait around for them.
You should be careful to include spaces between distinct tokens in the input, since put-tk-line will cheerfully combine several strings into a single Tk token.
call-tk-function (#rest pieces) => result :: <string> [Function]
Concatenates the input into a tk command, executes it, and returns the result as a string. Pauses execution of the current thread until the tk function returns. You may need to call tk-as, tk-unquote, or parse-tk-list on the result depending upon the expected result type.
join-tk-args (#rest object) => result :: <string> [Function]
Creates a string containing the tk representation (via tk-as) of each argument, separated by spaces.
make-option (option, value) => option :: <string> [Function]
Creates a tk "option" switch out of option name and an arbitrary value. The value may be an <integer>, <string>, <symbol>, or <true>. If the option is #f, then an empty string (i.e. no option) will be returned.
parse-tk-list (string, #key depth, unquote, start, end) => sequence [Function]
Takes a string returned by a tk function and converts it into a sequence of values. Values will either be words or subsequences, depending upon whether the string contains list grouping (i.e. { and }) characters. If depth is not #f, all groupings below the given depth will be returned as simple strings. If unquote is true, then result strings will be filtered through tk-unquote.
tk-quote (object :: <object>) => result :: <string> [Function]
Performs whatever quotation is necessary to get the data to WISH intact. For most objects, this is the same as tk-as(<string>, ...), but it does extra quotation on strings to make sure brackets and such like come out OK.
tk-unquote (string :: <string>) => result :: <string> [Function]
Strips away all quotation from a string. This will undo the various escapes required to imbed brackets and such like inside a tk list. This should be called for any user level string, just as tk-as might be called for any other data type.
anonymous-name (#key prefix = "w") => result :: <string> [Function]
Generates a unique new (but unexciting) name for a window.
Copyright 1994, 1995, 1996, 1997 Carnegie Mellon University. All rights reserved.
Send comments and bug reports to gwydion-bugs@cs.cmu.edu