Professional

Home
Learn Shen
Videos
Community 
Wiki
Community
OS Kernel
OS Library
Shen Professional


More Help

Concurrency
FTP
Graphics
Shilbert
Standard Extension
Web 

Programming SP Graphics  

 

Talking to TCL/tk

SP links directly to TCL/tk and all graphics commands are interpreted by TCL/tk.   

The lowest level form of communication is through the talk and tk functions.  tk is a zero-place function that invokes the TCL/tk stream.   talk is a 2-place function that directs a string output to a stream.  The format for the most basic form of communication to TCL/tk is

(talk <string> (tk))

where <string> is taken up by a TCL/tk command.

If you want to talk to TCL and receive a response then

(talk-and-listen-and-wait <string>)

will send a TCL/tk command in a string to TCL/tk and wait for a response. The response will be returned as a string.

Higher-level forms of communication are possible using Shen syntax and many of these commands are present from inception in your SP image.  They need not be loaded from the web because they are used in the SP IDE.   The type theory is loaded from the cloud under the package Tk Types because it is fairly large (TCL/tk is a big language) and is under continuous development.  .

Talking to TCL/tk
The Widget Command
Buttons
Entries and Labels
Check Buttons and Radio Buttons
Canvases
Placing Widgets
Fonts
Images
Menus
The Attribute-Value Model: putw and getw
Dialog Windows
Stuff to Watch Out For
Learning More About Widgets and Management

The Widget Command

The process of creating graphics is a two stage process.

  1. Creating the widgets you want.
  2. Placing them in a window.

What follows next is a precis of the commands needed to do that

The most important command is widget which creates a widget.  widget has the form

(widget <widget name> <widget-type> <options>)

A widget name begins with a dot followed by a symbol S. If S contains no dots then the widget is interpreted relative to the root window (the GUI window that appears when starting SP) and the widget will appear in that window.  A <widget type> can be any of the following.

label button checkbox radiobutton menubutton frame window entry textbox canvas

Options are multitudinous and consist of a series of attribute-value pairs.  An attribute have the form -<symbol>.  The available options are taken from TCL/tk. and the symbols are taken from TCL/tk.  For example

(widget .clickme button -text "Click me" -command (freeze (print howdy)))

creates a button called .clickme whose text reads "Click me" and which causes howdy to be printed in the command window.

Here is a brief inventory of the widgets recognised by the widget function.

button A button is an active area of the window that can be clicked to enable commands to be performed.   It can have text written on it.
label A label is exactly like a button except it does not support commands and cannot be clicked.
checkbutton A checkbutton is a button that exists in either a checked or a non-checked state.  It is displayed as a square box with or without a tick and toggles on/off in response to being clicked.
radiobuttton A radiobutton is a button that exists in either a checked or a non-checked state.  It is displayed as a circle with or without a dot and toggles on/off in response to being clicked.
menubutton A menubutton is a button that calls up a menu.
entry An entry is a place where a user can type in a line of text.
textbox A textbox is a place where a user can type in multiple lines of text.
canvas A canvas is a place where a user can draw shapes.
window A window exists to support the display of widgets.  Unless specified the window used by default is the root window (the one that pops up when SP is activated).
frame A frame is an invisible box in which widgets can be grouped together into a whole.  The entire group of widgets behaves like a single complex widget and can be placed in a window.

The next sections give examples 

Buttons

Here is a medley of buttons placed in a window called mywindow.  The final command pack packs all the widgets

(widget .mywin window)

(widget .mywin.b1 button)
(widget .mywin.b2 button -text "Button 2")
(widget
  .mywin.b3  button 
-text "Button 3" -background  "green")
(widget
  .mywin.b4  button -text "Button 4" -foreground  "blue")(widget .mywin.b5 button  -text "Button 5" -font "Impact")
(widget .mywin.b6 button   -text "Button 6" -relief sunken)(widget .mywin.b7 button
-text "Button 7" -highlightthickness 10)
(widget .mywin.b8 button -text "Button 8" -underline 6)(widget .mywin.b9 button -text "Button
9" -padx 30 -pady 10)(widget  .mywin.b10 button 
        -text "A very long line of text for a button"
         -justify right -wraplength 50)
(widget  .mywin.b11 button  
-text "A very long line of text for a button"  
 -justify left -wraplength 50)
(widget  .mywin.b12 button  
-text "A very long line of text for a button"  
-justify center -wraplength 50)


(pack [.mywin.b1 .mywin.b2 .mywin.b3 .mywin.b4 .mywin.b5 .mywin.b6 .mywin.b7 .mywin.b8 .mywin.b9 .mywin.b10 .mywin.b11 .mywin.b12])

Entries and Labels

Here is an entry form for a database system using labels and entries. Entries are active areas of text where the user can type his or her input.  This example shows a program that builds a grid of five labels and five entries.  (We will cover the analog-grid function in the section on widget management). 

(widget .mydb window)

(widget .mydb.name label -text "Name")
(widget .mydb.street label -text "Street Number")
(widget .mydb.city label -text "City")
(widget .mydb.state label -text "State/County")
(widget .mydb.country label -text "Country")

(widget  .mydb.namee entry -width 20)
(widget  .mydb.streete entry -width 20)
(widget  .mydb.citye entry -width 20)
(widget  .mydb.statee entry  -width 20)
(widget  .mydb.countrye entry  -width 20)
(putw .mydb.countrye -text "USA")

 (analog-grid [[.mydb.name  .mydb.namee]   [.mydb.street .mydb.streete] 
[.mydb.city .mydb.citye]                  [.mydb.state .mydb.statee]
[.mydb.country .mydb.countrye]]  
-padx 10 -pady 10)

 Suppose I type my name into the .name entry. The expression (getw .name -text) now returns "Mark Tarver".

Check Buttons and Radio Buttons 

A check button is similar to an ordinary button except that it carries around with it a binary internal state which toggles on/off according to whether the user has clicked on it.   The default (pre-clicked) state is off.  The check button appears as a small box which carries a tick when it  is in the 'on' state. The following program creates three check buttons.  

 (widget .mywin window)

(widget .mywin.cb1 checkbutton
-command (freeze (toggle .mywin.cb1))) 

(widget .mywin.cb2 checkbutton
-command (freeze (toggle .mywin.cb2))) 

(widget .mywin.cb3 checkbutton
-command (freeze (toggle .mywin.cb3) -text "hi"))

(set *cb1* false)
(set *cb2* false)
(set *cb3* false)

 (define toggle
.mywin.cb1 -> (set *cb1* (not (value *cb1*)))
.mywin.cb2 -> (set *cb2* (not (value *cb2*)))
.mywin.cb3  -> (set *cb3* (not (value *cb3*))))

   (pack [.mywin.cb1 .mywin.cb2 .mywin.cb3])

 

 

 Loading the program  allows us to change the value of a global.  

(4-) (value *cb2*)
false : boolean 

(5-) \\Here we first click on .cb2 as shown in picture and then type …
(value *cb2*)
true : boolean

If we want to use radiobuttons instead of checkbuttons, we use radiobutton instead of checkbutton in the program above (see below).

(widget .mywin window)

(widget .mywin.rb1 radiobutton)
(widget .mywin.rb2 radiobutton)
(widget .mywin.rb3 radiobutton -text "hi")

(pack [.mywin.rb1 .mywin.rb2 .mywin.rb3])

Canvases

A canvas is a widget on which shapes can be drawn.  A canvas is created by the canvas option.  

(widget .mywin window)
(widget .mywin.canvas canvas)

(pack [.mywin.canvas])

The basic canvas command is draw which has the format

(draw <canvas name> <shape> <coordinates> <options>)

Admissible values for <shape> are line, arc, rectangle, oval, polygon.  Coordinates are given by an even numbered list of 4 or more items.  Lines require at least 4 coordinates.  Here is an example with 6.

 (draw .mywin.canvas  line  [0 0 100 100 125 150])

 The origin of the line begins at the top left hand corner of the canvas and the line extends downwards.  


 

(draw .mywin.canvas rectangle [50 50 100 150]) produces the canvas below.

Placing Widgets

The three essential commands needed to master the the placing of widgets are pack, analog-grid and frame. pack has the syntax

(pack <list of widgets> <options>)

By default, pack always packs vertically from top to bottom, separating the buttons by a fixed space.  We can change this.  Assume that we have

(widget .mywin window)

(widget .mywin.b1 button -text "one")
(widget .mywin.b2 button -text "two")
(widget .mywin.b3 button -text "three")
(widget .mywin.b4 button -text "four")
(widget .mywin.b5 button -text "five")

Then the expression below packs a line of buttons from left to right.

 (pack [.mywin.b1 .mywin.b2 .mywin.b3 .mywin.b4 .mywin.b5] -side left) 

The permissible values to –side are left, right, top and bottomtop stacks the successive buttons one on top of the other (the default).  bottom places them underneath each.

Suppose we want to space the buttons; the –padx option will do this, spacing buttons in the x-axis direction.  To create this effect we change the previous pack command to

(pack [.mywin.b1 .mywin.b2 .mywin.b3 .mywin.b4 .mywin.b5] -side left –padx 20) 

The spacing is measured in pixels. 

 (pack [.mywin.b1 .mywin.b2 .mywin.b3 .mywin.b4 .mywin.b5] -side top -pady 20) gives the packing shown below.
 

There are two types of padding; internal and external.  External padding controls the space between the widgets.  Internal padding controls the space between the text on the widget and the edges of the widget.  The expression (pack [.mywin.b1 .mywin.b2 .mywin.b3 .mywin.b4 .mywin.b5] –ipady 25 -padx 50) packs the buttons vertically (the default) with a generous internal padding in the y axis (see the window in the right hand of figure 3.11).

We can tell the packer to pack the widgets so that they fill either the x axis or the y axis of the window or both.  The option –fill x/y/both does this.  This command packs five buttons so that they fill the x axis (figure 3.12).

 (pack [.mywin.b1 .mywin.b2 .mywin.b3 .mywin.b4 .mywin.b5] -fill x)

A very useful SP command is analog-grid which can be used in place of pack and has much the same options.  The format is

(analog-grid <list of lists of widgets> <options>)

This enables the creation of lists of lists of text widgets where the list structure mirrors the layout of the widgets.  Thus suppose we want to create 4 buttons in a square; then instead of using pack we can write.

(analog-grid [[.mywin.b1 .mywin.b2] [.mywin.b3 .mywin.b4]] -padx 10 -pady 10)

The items in each list are displayed horizontally, left to right and stacked vertically with the required padding to produce this effect. 

The frame widget command enables a set of widgets to be grouped into an object called a frame.  Once a frame has been created, it can be packed or placed like any other widget.  The effect of packing a frame is to place all its constituent widgets in the position determined by the packing command.

The power of frames is that they allow us to manipulate complex collections of widgets as if they were a single entity.  This is particularly useful when the GUI we want to build has many widgets laid out in different ways.  The widget layouts in SP work best when the layout follows a single format.  But when we want to mix formats then we need to use frames.

Here is a short program showing the use of frames.  We create two frames and four buttons.

(widget .mywin window)

(widget .mywin.f1 frame)
(widget .mywin.f2 frame)
(widget .mywin.f1.b1 button -text "inside frame f1")
(widget .mywin.f1.b2 button -text "also inside frame f1")
(widget .mywin.f2.b3 button -text "inside frame f2")
(widget .mywin.f2.b4 button -text "also inside frame f2")

The identifiers for the buttons, .mywin.f1.b1 .mywin.f1.b2 .mywin.f2.b3 .mywin.f2.b4, show that the first two buttons are embedded in the frame .mywin.f1 and the second two in the frame .mywin.f2.  The purpose of the dot is to isolate the name of the frame (thus neither .mywin.f1b2 or .mywinf1b2 would place the button in the .mywin.f1 frame).  The buttons are now created.

 To pack the buttons we

  1.  Pack them in their frames.
  2.  Pack the frames themselves.

The first two commands pack the buttons in the frames.

(pack [.mywin.f1.b1 .mywin.f1.b2] –side left)
(pack [.mywin.f2.b3 .mywin.f2.b4])

 The final command packs the frames

 (pack [.mywin.f1 .mywin.f2]) 

producing this result. 

(pack [.mywin.f1 .mywin.f2]) will unpack the widgets.

Fonts

The font command creates fonts by giving them a name; the options are -size, -family. For example the largefancy font on the root window showing Professional is created by the following commands.

(font largefancy -size 20 -family "Mistral")
(widget .top.title.prof label -text "Professional 10.2" -font largefancy)

Images

Labels and buttons can have images placed on them. The image in the root window is created by:

(image logo "logo.gif")
(widget .top.title.logo label -image logo)

Menus

Menus are created by creating menu buttons and attaching menus to them.

\\ create a window

(widget .mywin window)

\\ Create a menu button with text on it and give the menu it calls
(widget .mywin.mymenubutton menubutton -text "Just a Menu" -menu .mywin.mymenubutton.menu)

\\ create a popup tearoff menu called by the menu button
(widget .mywin.mymenubutton.menu menu)

\\ Place some menu items on the menu.
(menuitem .mywin.mymenubutton.menu add -label "Hello" -command (freeze (print hello)))
(menuitem .mywin.mymenubutton.menu add -label "Goobye" -command (freeze (print goodbye)))

\\ pack it!
(pack [.mywin.mymenubutton])

The Attribute-Value Model: putw and getw

Widgets in SP are modelled using an attribute-value model. A button has various attributes like foreground colour (-fg), command attached (-command) and the values of these attributes are the actual colour and commands attached. These values can be retrieved and changed by the getw and putw functions.

(getw <widget name> <attribute>) takes a widget and returns the value of its attribute. (putw <widget name> <attribute> <value>) changes the value of that attribute. Thus (putw .mywin.b -fg "green") will make the text green. (getw .mywin.b -fg) will return "green". Note that only values that are set through SP either by being declared through widget or putw can be retrieved by getw.

Dialog Windows

Dialog windows are windows that pop up according to the flow of control within a program and disable the other GUIs until the user replies to them.  We start with a series of predefined dialog windows called convenience dialog windows. Dialog windows are windows that pop up according to the flow of control within an SP program and disable the other GUIs until the user replies to them.  The most important command for invoking a dialog window is messagebox.

The messagebox function takes a list of options and produces a message box.  Depending on the nature of the user interaction, a string is returned. Here are some examples. 

Expression

Message Box

 

(messagebox)

 returns "ok"

 

 

 

(messagebox -message "File deleted")

returns "ok"

 

 

 

 

 

(messagebox  

-message "Are you sure?"  
-title "Deleting vital file!" 
-type yesnocancel  
-icon warning)

returns "yes"/"no"/"cancel"

 

 

  opencolour activates a dialog window that enables the user to choose a colour from a colour palette.  The function returns an rgb value that represents the colour selected.

 (2-) (opencolour)
"#8080c0"

opencolour returns "" if Cancel is chosen.

openfile and savefile both receive options and display the resident directory.   Selecting a file returns the path name of that file as a string.  savefile allows the user to create a new filename which is returned as a string.  "" is returned if Cancel is chosen.

 (3-) (openfile)
"C://Documents/Computer Science/Languages/Shen/Shen-tk 7.2/debug.txt"

 

Stuff to Watch Out For

When a set of widgets is created and packed into a window then recreating the same widgets and packing them again into the same window is not a good idea. Experience has proved that this leads to the IDE freezing. Use unpack to unpack the widgets and putw to change their attributes.

After updating a window with widgets, there is sometimes a need to clear the buffer. This shows in the IDE not reponding to the initial window events but behaving properly thereafter. This can be countered by terminating the update with (ide.ping) which sets the IDE to receive events.

The TCL/tk dot notation rather interferes with packaging. If you place your IDE in a package you need to make the widgets external to that package.

Learning More about Widgets and Management

This is just a summary. You can read about the many options to widgets and their management in the TCL/tk documentation.

button https://www.tcl.tk/man/tcl8.6/TkCmd/button.htm
label https://www.tcl.tk/man/tcl8.6/TkCmd/label.htm
checkbutton https://www.tcl.tk/man/tcl8.6/TkCmd/checkbutton.htm
radiobuttton https://www.tcl.tk/man/tcl8.6/TkCmd/radiobutton.htm
menubutton https://www.tcl.tk/man/tcl8.6/TkCmd/menubutton.htm
entry https://www.tcl.tk/man/tcl8.6/TkCmd/entry.htm
textbox https://www.tcl.tk/man/tcl8.6/TkCmd/textbox.htm
canvas https://www.tcl.tk/man/tcl8.6/TkCmd/canvas.htm
window https://www.tcl.tk/man/tcl8.6/TkCmd/toplevel.htm
frame https://www.tcl.tk/man/tcl8.6/TkCmd/frame.htm
pack https://www.tcl.tk/man/tcl8.6/TkCmd/pack.htm