PreviousUpNext

15.3.677  src/lib/x-kit/widget/old/basic/widget.api

## 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.pkg

stipulate
    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.pkg
herein

    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


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext