4. GWindows fundamentals.


4.1 Fundamental classes

In GWindows, you define a user interface as a tree of objects. gwincls.h provides the following fundamental classes:

GWindow and WindowPair objects provide a winid property, which contains the Glk opaque reference for the window. If you wish to use a Glk function on a window, you pass this winid property to Glk:

Wrong:

glk_window_move_cursor(mywin,2,2);

Right:

glk_window_move_cursor(mywin.winid,2,2);

GWindows also provide a way for determining their actual size on the screen. The properties width and height contain the actual size of the window, in whatever units are appropriate (characters or pixels). These values are updated whenever the window is redrawn, so that they will be correct even if the user maliciously changes his screen size.

4.2 Widgets

Some techniques are common enough that GWindows provides predefined classes for a special-purpose window.

A widget is a GWindow which has special code to make the window do a certain task. GWindows ships with a large number of widgets to provide common tasks. Some examples of widgets are: GStatusLine (a widget which emulates the standard status line), GPopupWin (a widget which provides a window which changes its size when activated), and GMenu (a widget which generates a menu of options). Though new widgets are being created all the time, the ones which existed when this manual was written are documented in section 7.

Because you may not want all of the widgets, and because you may want to add new widgets later, each widget is kept in a separate file. Some widgets are based on other widgets. A well-written widget file will include its required widgets for you.

There are two fundamental types of widget:

An abstract widget encapsulates a single specific kind of behavior. An abstract widget isn't a complete GWindow on its own; it has to be combined with another widget. For example, GPopupWin is a widget for any kind of window that pops up. It is not a window on it's own though; a GPopupWin has to be combined with a TextGrid, TextBuffer, or GraphWin (or with another widget) to specify what sort of window should actually pop up.

There is a special abstract widget called GCombiner. This widget doesn't do anything on its own; its purpose is to combine two widgets which offer overlapping properties into a single widget. For example, a GPopupWin changes its size when it is "activated". A GMenu loads a new menu when it is "activated". To have both happen, the classes have to be combined using a GCombiner which connects the "activate" methods. gpopmen.h shows the GPopupMenu class, which does exactly this. Because GCombiner is such a powerful widget, it's recommended that you steer clear of it until you're very comfortable with GWindows programming.

A concrete widget is a widget which is a complete GWindow in and of itself. GMenu, for example, is a concrete widget. You can create a GMenu, and insert it directly in your user interface as you would a TextGrid or TextBuffer window.

4.4 Printables

This document will use the term printable for any value which can be output by the PrintAnything() library function. GWindows often uses printables to generate its output.

4.5 Event Handlers

An event handler is a function which is run in response to some event in the outside world. Examples of user events include character events (the player just typed a character), mouse events (The player just clicked with the mouse), and timer events (The computer's clock just went "tick"). Glk offers a wide variety of events. Line input events (The event caused when the player types out a whole command and presses enter) are handled by the standard library. GWindows offers event handlers for mouse and character events, and takes care of redraw events (The interpreter has lost track of the screen, and needs to have it redrawn) and arrange events (Something has caused some windows to change their sizes, so they should be updated to fit the new size). Other events are handled by your GWindowsGlkEvent function.  

4.6 GWindows Installation

Like Inform's standard library, GWindows consists of three files, gwincls.h, gwindefs.h, and gwindows.h. To use GWindows in a program, you must include gwindefs.h before parser.h, gwincls.h after parser.h, and gwindows.h before grammar.h.

Any configuration constants you wish to use should go before the inclusion of gwindefs.h. Any entry points you wish to use should go before the inclusion of gwindows.h.

Any GWindows widgets you wish to use should be included after gwincls.h.

GWindows requires L. Ross Raszewski's utility.h (version 4.0 or greater) and John Cater's infglk.h. These will be automatically included by GWindows.

4.7 GWindows global variables

GWindows uses the following global variables to monitor the state of the interface:

The first group of variables help GWindows interact with the standard library. You can read them whenever you like, but if you change them, you should re-start the window system to make the changes take effect. Failure to do this might confuse GWindows.

The next group of variables communicate information to GWindows. You can set them at any time.

The final global variables are read-only.

To be nice to players, you might want to check GW_Abilities when setting up your interface; if you're using a graphical interface like the one above, you should also create a textual version, and use that if GW_Abilities doesn't list GWIN_GWOK.

4.8 GWindows configuration constants

4.9 GWindows Entry Points

GWindows installs itself using the Glk entry points of the standard library. As such, it offers its own entry points to replace them:

GWindowsGlkEvent(x,y,z): Replaces HandleGlkEvent

GWindowsGlkIdentify(w,x,y,z): Replaces IdentifyGlkObject

GWindows also uses the InitGlkWindow entrypoint. It provides the entrypoint InitGWindows (which takes no parameters), which is equivalent to InitGlkWindow(0), and is called whenever the user interface is being created fresh. You are required to provide this function. It should, at the very least, do the following things:

Make sure Active_UI is set correctly.

Make sure Main_GWindow is set correctly.

If you're using a separate input window, make sure Input_GWindow is set correctly.

By "correctly", we mean that the variables have the proper values for this point in the game. If you use more than one user interface, then InitGWindows should set the variables to their initial states if they are zero -- if they are nonzero, you can assume that the interface is being recreated (say, after a restore), and the values are already set correctly.

GWindowsHandleError(x) is called whenever an otherwise-irrecoverable error occurs (That is, it will only be called for errors so heinous that the system cannot continue) . Return 2 from this function to indicate that the problem has been dealt with -- though it's usually far too late by then. The parameter describes the error. GWindows itself uses the following error codes: