: zFindCallback \ zCbName -- entry true | 0
Search the default search order for the given callback name.
On success, the entry point is returned.
7 0 CCBproc: BuilderConnect_cb \ *Builder *object zSignal zHandler *ConnObj flags *User --
The main Glade signal connection callback. This is called for
each signal handler specified in the Glade file, i.e. handlers
named by the GUI designer. Handler names are looked up in the
current context. The words found are linked to the appropriate
object by way of the GTK signal connection bindings.
variable CurrBuilder \ -- addr
Holds the current builder handle.
: loadBuilderXML \ z$ -- builder|0
Load a Glade GtkBuilder XML file and return the pointer or
zero on error. On success, the connections are made and the
variable CurrBuilder
is set.
: BuilderObject \ z$ -- *widget
Obtain the widget pointer for the given named widget from the
current builder object.
: freeBuilder \ --
Free the current builder.
: runDlg \ dialog -- response
Given a *GtkDialog, run the dialog as a modal dialog
and return the result.
: ErrorBox \ zMessage zTitle parent --
Displays an error box with the given message, title and
parent window.
: AskSaveFileNameBox \ zaddr len parent -- flag
Given a buffer and parent window, ask for a file name. On
success, the filename is returned (clipped as required) in
the buffer as a zero terminated string. If no file name is
given the buffer is left unchanged.
: AskOpenFileNameBox \ zaddr len parent -- flag
Given a buffer and parent window, ask for an existing file name. On
success, the filename is returned (clipped as required) in
the buffer as a zero terminated string. If no file name is
given the buffer is left unchanged.
The GTK library calls back into Forth on various events. Here are some sample definitions. You may need to modify them or add new ones according to the complexity of your UI. You can also use this code to test your GTK installation.
Compile the file gtkbindings.fth. Then run
.libs .badExterns
This will display the load addresses of the libraries and show you any unresolved external functions. A library value of zero indicates that the library has not been found. If everything is good at this point, run the test window:
gtktest
which should display a "hello world" window.
: delete_event_fn \ *widget *event *data -- 0/1
Handles delete events. It returns zero so that the widget
is destroyed.
3 1 CCB: delete_event \ -- addr ; *widget *event *data -- 0/1
Callback for the delete event. Return 0 to perform the
default handling or return 1 to indicate that the callback
has done everything necessary.
: destroy_fn \ *widget data --
Handles the destroy event for the application. It calls
gtk_main_quit().
2 0 CCB: destroy_event
Callback for the destroy event.
: wd_destroy \ addr --
Destroy the widget
1 0 CCB: widget_destroy_cb \ -- entry
Callback to handle the destroy event.
0 value GTKstarted? \ -- x
Non-zero when GTK has been started.
0 value AppFinished? \ -- x
Non-zero when app must quit.
0 value gtk_main? \ -- x
Non-zero if gtk_main
is in use.
: noVfxGtk \ --
Mark the VFX Forth to GTK interface as unused.
: do_gtk_init { | temp[ cell ] -- }
Run gtk_init.
: do_gtk_main \ --
The tools version of gtk_main
.
: initGTK \ --
Call this to initialise the GTK system. Always call this
word to start the GTK system.
: GtkAppQuit \ --
The GTK+ app should finish.
: hello_world_window \ --
Launch the "hello world" window.
: gtktest \ --
Start GTK+, launch the hello world window, and wait until it
closes.
: hw \ --
As gtktest
but does not initialise GTK+ again.
struct /gwindow \ -- len
Structure to control a graphics window.
variable windows \ -- addr
Anchors chain for keeping track of all created windows.
CELL +USER CANVAS \ -- addr
The current drawing window.
: window> \ -- window
Get the current drawing window.
: penx \ -- addr
The current window's X coordinate for subsequent drawing
commands.
: peny \ -- addr
The current window's Y coordinate for subsequent drawing
commands.
: filled? \ -- addr
The current window's internal flag affecting drawing commands;
see filled
.
CREATE mycolor ( -- addr ) 0xffff0000 l, 0xffff w, 0 w, 0 w,
Initial foreground color for new windows
: window-dims \ window -- w h
Get the dimensions of a window from the window structure.
: load-pixbuf \ zaddr -- pixbuf
Load an image into a Gtk_Pixbuf, which can be drawn to the
current window using PUT
.
: redraw { window -- }
Make changes to a window's graphics visible.
: ?redraw { window -- }
Internal - redraw a window only if it is "dirty" (affected
by any drawing commands). Immediately resets the window's
dirty flag, making it "clean" again
: ChainEach \ ... xt anchor -- ...
Execute xt on the contents of chain with the following structure:
link | ...
The given xt must have the stack effect
... link -- ...
Where link is the address of the link field in the structure.
You can pass your own values to each link, just remember to clean up afterwards.
1 1 CCBproc: timeout_event_cb \ 0 -- true ; -- entry
Callback run from a timer to redraw all "dirty" windows.
: +gtimer \ --
Start the graphics event timer.
: -gtimer \ --
Stop the graphics event timer
: winResized \ window --
Perform this when the window has been resized.
3 0 CCBProc: GframeCallback \ window event data -- ; -- entry
Callback to force window size to be updated and the window
redrawn.
3 0 CCBProc: GExposeCallback \ window event data -- ; -- entry
Callback to force window to be redrawn.
: filled> \ -- flag
Fetch the filled flag
: drawdest> \ -- pixmap gc
Fetch the 2 objects from the current window that are passed
to all GDK graphics functions.
: dirty \ --
Mark the current window as dirty, which signals the GUI's
internal timer to make changes to that window visible. Note
that the flag is reset by redraw
.
: COLOR: \ -- ; --
Builds a new GTK color. When the color is executed, the
foreground color is set. Use in the form:
COLOR: red 0xffff0000 , 0xffff w, 0x0000 w, 0x0000 w,
The following colours are predefined:
red green blue yellow orange magenta
cyan white black ltgrey grey
dkred dkgreen dkblue dkyellow brown
violet dkcyan dkgrey
: onto \ window --
Set the current target window structure for graphics commands.
: pen \ -- x y
Get the current drawing coordinates.
: at \ x y --
Set the current drawing coordinates.
: filled \ --
Makes the next command, such as rectangle or circle, filled
instead of stroked.
: line { destx desty -- }
Draw a line from the pen to (destx,desty).
: lineto \ destx desty --
Draw a line from the pen to (destx,desty) and set the pen to
(destx,desty).
: linerel \ dx dy --
Draw a line relative to the pen.
: linerelto \ dx dy --
Draw a line relative to the pen and move the pen to the end
of the line
: ellipse { width height -- }
Draw an ellipse defined by width, height.
The ellipse is positioned such that the pen points to the
top left corner of an imaginary rectangle around the ellipse.
: circle \ diameter --
Draw a circle.
The circle is positioned such that the pen points to the top
left corner of an imaginary square around the circle.
: rectangle { width height -- }
Draw a rectangle.
: putpixel \ --
Plot a single pixel.
: cleardevice \ --
Clear the current drawing window using the current color.
: put { pixbuf -- }
Draw a Gtk_Pixbuf to the current window at the current pen position.
: gwin: \ <name> -- ; -- window
Declare a named graphics window. The returned window is the
address of a /gwindow
structure.
gwin: MyWin \ -- window
: setupGwin { w h window -- }
Initialize a window control structure. This word is used to
create a new window. SetupGwin
cannot be used with windows
defined in Glade.
: initGladeGwin \ z$name builder window --
Use the Glade widget name (usually a drawing area) in the
Glade builder to set up the given /gWindow
structure.
: initGwin \ *widget gwindow --
Use the widget to set up the given /gWindow
structure.
: addEvent \ cbentry zname event window --
Add a callback to handle the name and event for a window
structure.
: enable-graphics { window -- }
Enable the window for graphics operations and set the initial
state.
The original design and C code is by Micah Carrick, whose tutorial is well worth studying. It is at:
http://www.micahcarrick.com/gtk-glade-tutorial-part-1.html
The Forth code presented here is liberally derived from that presentation and code.
To compile the text editor demo, CD to the directory containing editor.fth and then:
include TextEdDemo.bld
To run the editor from the Forth console:
runTextEd
The code will run unchanged on VFX Forth for Windows, Mac and Linux.
struct /TextEd \ -- len
Everything we need to know about the editor can be derived
from this structure.
0 value pTextEd \ -- addr
Holds the address of a structure for the current text editor.
#1024 constant /NameBuffer \ -- len
Largest file name.
/NameBuffer buffer: zFilenameBuffer \ -- zaddr
Buffer to hold current file name.
#2048 constant /StatusBuffer \ -- len
Size of the status buffer
/StatusBuffer buffer: zStatusBuffer \ -- zaddr
Text buffer for status bar.
: EdErrBox \ zmessage --
Displays an error message box.
: sbParams \ -- sb context
REturn the status bar parameters
: setStatus \ z$1 z$2 --
set the status buffer, merging the two strings. Then update
the status bar.
: clearStatus \ --
Clear the status bar.
: modified? \ -- flag
Return true if the current text has been modified and not saved.
: modified \ --
Mark the current text buffer as modified.
: unmodified \ --
Mark the current text buffer as unmodified.
: inactive \ --
Set the current text window as inactive (unresponsive).
: active \ --
Set the current text window as active (responsive).
: getCurrText \ -- text
Get a copy of the current text. When you are finished with
it, you must release it with g_free ( text -- )
.
: CurrFilename \ -- z$
REturn the current text file name.
: MustSave? \ -- flag
Return true if the buffer has been modified and the user
wants to save it.
: getSaveFileName \ --
Set the current text file name for saving.
: getOpenFileName \ --
Set the current text file name for loading.
: sbSaving... \ --
Show status bar as saving.
: sbLoading... \ --
Show status bar as loading.
: fileStatus \ --
Show filename on status bar.
: loadCurrFile \ -- *text 0 | -1
Load the contents of the current file. On success, return a
pointer to the text and zero. On failure, just return -1.
When finished with, the text pointer must be freed with
g_free
.
: loadCurrText \ --
Load the text of the current window from the current file.
No action is taken if the filename is null.
: writeCurrText \ --
Save the text of the current window to the current file.
No action is taken if the filename is null.
: saveCurrText \ --
As writeCurrText
but asks for a file name if one has
not been set.
: saveAsCurrText \ --
As writeCurrText
but always asks for a file name.
: checkedSave \ --
If text has been modified and the user wants saving,
write the text to a file.
: openCurrText \ --
Open a new file.
: newCurrText \ --
Start with an empty buffer.
: CurrSelection \ -- clipboard
Get the clipboard item for the current selection.
: doCut \ --
Do the cut operation.
: doCopy \ --
Do the copy operation.
: doPaste \ --
Do the paste operation.
: doDelete \ --
Do the delete operation.
2 0 CCBproc: on_new_MainFileMenu_activate \ *widget *editor --
Callback for the "New" button.
2 0 CCBproc: on_Open_MainFileMenu_activate \ *widget *editor --
Callback for the "Open" button.
2 0 CCBproc: on_save_MainFileMenu_activate \ *widget *editor --
Callback for the "Save" button.
2 0 CCBproc: on_SaveAs_MainFileMenu_activate \ *widget *editor --
Callback for the "Save As" button.
2 0 CCBproc: on_MainWindow_destroy \ *wiget *editor --
Callback for final destroy of main window.
3 1 CCBProc: on_MainWindow_delete_event \ *widget *event *editor -- 0/1
When the window is requested to be closed, we need to check if
they have unsaved work. We use this callback to prompt the user to
save their work before they exit the application. From the
"delete-event" signal, we can choose to effectively cancel the
close based on the value we return.
2 0 CCBproc: on_quit_MainFileMenu_activate \ *wiget *editor --
Callback for the "Quit" button.
2 0 CCBproc: on_Cut_MainEditMenu_activate
Callback for the "Cut" button.
2 0 CCBproc: on_Copy_MainEditMenu_activate
Callback for the "Copy" button.
2 0 CCBproc: on_Paste_MainEditMenu_activate
Callback for the "Paste" button.
2 0 CCBproc: on_Delete_MainEditMenu_activate
Callback for the "Delete" button.
2 0 CCBproc: on_About_MainHelpMenu_activate \ *widget *user -- ; -- entry
Callback to run the About dialog.
2 0 CCBproc: on_aboutdialog1_close \ *widget *user -- ; -- entry
Callback when about box is closed.
: loadTeGUI \ --
Load the text editor's GUI. After the file has been loaded,
the widgets we need to access are extracted and their object
pointers saved in a /TextEd
structure. The design file
object is then released.
: termTextEd \ --
free up the application data and perform termination actions.
: RunTextEd \ --
Run the text editor.