## widget.api
#
# Here we implement substrate functionality common
# to all widgets; this is a bit like a superclass
# that all widgets inherit from, in OOP-think: Every
# widget calls make_widget at some point, and every
# widget provides a widget_of() function to obtain
# its underlying widget record.
#
# See bottom-of-file comments
# for an extended overview.
# Compiled by:
#
src/lib/x-kit/widget/xkit-widget.sublib# This api is implemented in:
#
src/lib/x-kit/widget/old/basic/widget.pkgstipulate
include package threadkit; # threadkit is from
src/lib/src/lib/thread-kit/src/core-thread-kit/threadkit.pkg #
package xc = xclient; # xclient is from
src/lib/x-kit/xclient/xclient.pkg package g2d= geometry2d; # geometry2d is from
src/lib/std/2d/geometry2d.pkgherein
api Widget {
#
Relief = FLAT
| RAISED | SUNKEN | GROOVE | RIDGE;
include api Widget_Base; # Widget_Base is from
src/lib/x-kit/widget/old/basic/widget-base.api include api Root_Window_Old; # Root_Window_Old is from
src/lib/x-kit/widget/old/basic/root-window-old.api include api Widget_Attributes; # Widget_Attributes is from
src/lib/x-kit/widget/old/basic/widget-attributes.api Widget;
# Creating the widget-tree is a multi-phase process.
#
# In particular, we decouple widget "creation" from
# widget "realization".
#
# Each widget creation function (make_button, make_label...)
# calls "make_widget" below, which returns the core Widget value.
#
# Much later, that widget's parent calls its Realize_Widget,
# passing in the widget's size in pixels, the Window on which
# it is to draw itself, and the Kidplug from which it receives
# mouse, keyboard and other event input:
exception ALREADY_REALIZED;
Realize_Widget
=
{ kidplug: xc::Kidplug, # Source for X events, segregated into "keyboard", "mouse" and "other" events.
window_size: g2d::Size, # Pixel size widget has to draw itself.
window: xc::Window # X window on which widget should draw itself.
}
->
Void;
# Window_Args def in
src/lib/x-kit/widget/old/basic/widget-base.pkg make_widget
:
{ root_window: Root_Window,
args: Void -> Window_Args, # Current Window_Args just records background color.
realize_widget: Realize_Widget, # Our parent calls this to start us running.
#
size_preference_thunk_of # Parent calls this to find out what size we would like to be.
:
Void -> Widget_Size_Preference
}
->
Widget;
root_window_of: Widget -> Root_Window;
args_of: Widget -> Window_Args;
window_of: Widget -> xc::Window;
# size_of: Widget -> g2d::Size;
args_fn: Widget -> Void -> Window_Args;
realize_widget: Widget -> Realize_Widget;
same_widget: (Widget, Widget) -> Bool;
preferred_size: Widget -> g2d::Size;
okay_size: (Widget, g2d::Size) -> Bool;
filter_mouse: Widget -> (Widget, (Mailop( (Mailop( xc::Envelope( xc::Mouse_Mail ) ), Mailslot( xc::Envelope( xc::Mouse_Mail ) )) ) ));
filter_keyboard: Widget -> (Widget, (Mailop( (Mailop( xc::Envelope( xc::Keyboard_Mail) ), Mailslot( xc::Envelope( xc::Keyboard_Mail) )) ) ));
filter_other: Widget -> (Widget, (Mailop( (Mailop( xc::Envelope( xc::Other_Mail ) ), Mailslot( xc::Envelope( xc::Other_Mail ) )) ) ));
#
# Wrap a new widget around a given widget,
# intercepting the given mailstream and
# providing access to it.
ignore_mouse: Widget -> Widget;
ignore_keyboard: Widget -> Widget;
#
# Wrap a new widget around a given existing
# widget which intercepts and discards all
# messages on the given mail stream.
size_preference_of: Widget -> Widget_Size_Preference;
size_preference_thunk_of: Widget -> Void -> Widget_Size_Preference;
seen_first_redraw_oneshot_of: Widget -> Oneshot_Maildrop(Void);
#
# We often want to wait until a widget is fully
# operational before pestering it with requests.
# This call returns a condition variable on which
# we can wait via
#
# get (seen_first_redraw_oneshot_of widget);
#
# This condition variable gets set
# when the first EXPOSE event arrives for it from
# the X server; this gets done in
#
#
src/lib/x-kit/xclient/src/window/xsocket-to-hostwindow-router-old.pkg get_''gui_startup_complete''_oneshot_of # get_''gui_startup_complete''_oneshot_of def in
src/lib/x-kit/xclient/src/window/xsession-old.pkg :
Widget -> Oneshot_Maildrop(Void); # See comments in
src/lib/x-kit/xclient/src/window/xsocket-to-hostwindow-router-old.api
};
end;
#
# Motivation
# ----------
#
# Programming in conventional imperative languages has been
# compared to pushing blocks of wood around: Nothing happens
# unless you specifically make it happen. Less kindly, it
# has been compared to kicking a dead whale down the beach
# with your bare feet.
#
# Alan Kay's original Smalltalk-72 vision for object-oriented
# programming was that it should feel like commanding trained
# circus seals: You merely give the word and they enthusiastically
# flipper off and actively make stuff happen for you. Ork! Ork! Ork!
#
# Smalltalk-72 was a firestorm of fresh ideas but the practical
# limitations of 1970s hardware and software technology dragged on it
# and by the time Smalltalk-78 came out it had become a much more
# sedate language with many of the most outrageous ideas dropped in
# favor of practical operation on available technology. (The
# remaining innovations were still enough to change computing
# forever!) In particular, objects had been reduced to somnolent
# records that did nothing until you specifically invoked them and
# which went back to sleep as soon control returned from them.
#
# The enormous capacity of modern computer hardware together with
# Mythryl's cheap concurrency allow us to revive Alan's original vision
# by granting each widget one or more private control threads so that
# it can beaver away continually on its own even when our attention is
# elsewhere. Ork! Ork! Ork!
#
# Overview
# --------
#
# This is the Mythryl port of the eXene widget library described in
#
# The eXene Widgets Manual (Version 0.4)
# Emden R Gansner + John H Reppy February 11, 1993
# http://mythryl.org/pub/exene/1993-widgets.ps
#
# See additional comments at top of:
#
#
src/lib/x-kit/widget/old/basic/widget.api#
# Quoting from that manual:
#
# The design promoted by eXene for widgets and their interactions with
# each other and the application is based upon a collection of related
# techniques.
#
# o Most fundamental is concurrency. Highly interactive graphical
# user interfaces are inherently concurrent. This concurrency
# should be made explict and used. Allowing each widget its own
# thread separates it from other widgets and from the application
# code. This allows simpler structure inside the widget, with
# each widget synchronously reading its own input streams, and
# cleaner interfaces between widgets.
#
# o Dealing with widget input can be further simplified by dividing
# messages into three functionally distinct streams, one each for
# the keyboard, mouse and control. The control stream provides
# such messages as "your window has been resized" and "redraw yourself".
# With this division, code for handling the keyboard or mouse can be
# written in a natural synchronous fashion, with no need to maintain
# state explicitly.
#
# o Input is distributed hierarchically. Events are passed from the
# root widget down the hierarchy to the appropriate target widget.
# This allows the programmer to interpose widgets at any level to
# modify widget characteristics or alter the distribution of events.
#
# o Few things are as full of state as graphical widgets. This state
# can best be controlled, especially in the context of a language
# such as ML that encourages immutable values, by encapsulating
# it within threads and mailqueues. This avoids the need for the
# explicit classes, objects and inheritance that are usually
# used in building user interfaces. Additional object-oriented
# techniques can be replaced with wrapper widgets and delegation.
#
# The widget library is the most tentative part of the eXene system,
# and the most likely to undergo radical alterations in the near
# future. The current set of widgets is incomplete, and the individual
# widgets lack a finished look. The semantics of some widgets are not
# general enough, or are not what the user might expect. Some of the
# necessary protocols, and the underlying support have not been completely
# designed or implemented. Most of the data structures, most notably
# Widget itself, represent first passes at what will be necessary.
# Experience will require that some types be changed, that some fields
# be added, that some functions or types be judged wrong. There is, at
# present, no integration of X resources with the widget hierarchy.
#
# Despite these shortcomings, the widget library provides a workable
# fabric for embroidering a collection of widgets into a user interface.
# It serves as an initial proof-of-concept for the eXene design philosophy,
# and points in the direction for the construction of mature libraries
# based on the eXene design.
#
# The widget library provides a higher-level platform for the construction
# of graphical interfaces than the basic eXene library. In particular,
# it emphasizes the use of widget components as the basic building block,
# blocks that can be used modularly in a wide variety of applications.
# Necessary alterations can be done externally, through resources, parameter
# settings, or by wrapping the widget in othe widgets.
#
# In order for widgets to work together at this level, a certian uniformity
# must be assumed. This uniformity is achieved by requiring widgets to
# provide a certain external interface and to respect certain internal
# protocols, and requiring the programmer to obey a few additional constraints
# on the construction and use of the widget hierarchy. The basic types and
# values for working with the eXene widgets are given in the [widget package],
# which matches the [Widget api].
#
#
# Widget Anatomy
# --------------
#
# A widget is essentially a triple consisting of:
#
# o A Root_Window
# o A size_preference_of fn
# o A realize_widget fn.
#
# The Root_Window gives the display with which
# the widget is associated; more generally it
# gives the entire relevant Xsession.
#
# The widget's size, position and visibility are
# controlled by its parent window. That parent
# also creates and passes to it the window on which
# the widget is to draw, via its realize fn.
#
# A widget can be realized only once. Subsequent
# realization attempts will raise the ALREADY_REALIZED
# exception.
#
# The realization function is also handed the Kidplug
# end of the Widget_Cable via which it receives mouse,
# keyboard input and resize requests.
#
# Compound widgets query the size_preference_of
# function for advice in sizing and positioning
# subwidgets. They treat the results as hints
# rather than requirements, so widgets must be
# prepared to draw in any size window.
#
# Widgets can be active or inactive.
# Independently, they can be set or unset.
# Users are usually prevented from setting
# or unsetting inactive widgets.
#
# The widget lifecycle is tightly constrained:
# Creation
# Insertion into parent
# Realization
# Possible removal from parent.
# Widgets cannot be re-inserted once removed,
# not even into the same parent.
#
# Widget Programming
# ------------------
#
# o Ordinarily a Root_Window widget will be created early,
# since one is required as argument to create most
# other widgets.
#
# o Compound widgets often require that their children
# be supplied at creation time, thus widget hierarchies
# are typically created upward from the leafs.
#
# o At some point a completed widget tree must be
# inserted into a Hostwindow. Realizing the tree's
# widgets and mapping its windows is done by calling
# the 'init' function on the Hostwindow.
#
#
# Further reading:
#
# Widget Internals comments may be found at the bottom of
#
#
src/lib/x-kit/widget/old/basic/widget.pkg