/* HELP GO_LIVE                                   Ben Rabau, 18th Jan 1993

This file explains the reasoning followed by the GO library regarding live
objects. These are objects to which behaviour has been attached.

    _______WARNING: This  is  the  first  version of  a  class  library  of
    graphical objects and is distributed with this release of Poplog
    for evaluation and comment. As a  result of feedback and in  the
    interests of  better  integration with  Poplog,  the  facilities
    described may be modified. While all reasonable endeavours  will
    be made to limit incompatible changes, programs which use  these
    facilities may require modification to run on later versions.

For more general detailed information see REF * GO.


         CONTENTS - (Use <ENTER> g to access required sections)

 -- 1. Live versus edit and go_editable mode
 -- 1.1. Live mode
 -- 1.2. Edit mode
 -- 1.3. Editable object
 -- 2. Objects which accept events
 -- 2.1. The mixins go_mouse_sensitive and go_key_sensitive
 -- 2.2. Button presses
 -- 2.3. Low level implementation
 -- 2.4. Example of transparent class
 -- 3. Special mouse down action: The go_drag_and_drop method
 -- 4. The go_keyboard action

-- 1. Live versus edit and go_editable mode ---------------------------

The GO library has two basic modes: an object is either fixed or it can
be changed.

-- 1.1. Live mode ----------------------------------------------------

The fixed mode is what is called "live" mode, which only allows the
program itself to change attributes or appearances of the objects. Only
behaviour go_attached to the object will have effect. This live mode can
either be set on a per object bases (the "go_live_object" slot) or on a
per pane bases (the "go_edit_mode" slot). If a pane is in "live mode"
then all objects inside it will be "live". If the pane is in "edit mode"
only the objects which are explicitely set to be "go_live_object"s will
be "live".

If not fixed the object can be changed by Direct Manipulation (DM). This
is further subdivided into two categories:
    - edit mode
    - editable object

-- 1.2. Edit mode ----------------------------------------------------

The "edit" mode relates to the pane and offers DM features such as
relocation of objects. The "edit" mode can be user (re-)defined by
attaching methods to a number of mouse or go_keyboard actions. In "edit"
mode only five actions are offered for simplicity reasons:
    - Left hand mouse button down
    - Left hand mouse button down and moved (drag)
    - Middle mouse button down
    - Right hand mouse button down
    - Keyboard key down

As can be seen above, the actions are based on a logical three-button
mouse- device which corresponds to the most wide-spread use of a mouse
(e.g. in the X-windows environment). See also further.

These actions are mapped onto five methods which can be overriden or
encapsulated by the users:
    - go_edit_left_action( event_data, obj )
    - go_edit_drag_action( event_data, obj )
    - go_edit_middle_action( event_data, obj )
    - go_edit_right_action( event_data, obj )
    - go_edit_key_action( char, event_data, obj )

All of these actions are directed towards the specific object which at
that moment is pointed at. For key strokes this corresponds to
click-to-type (see also further). The "char" argument represents the
go_keyboard character typed in over the object. The "event_data"
argument is the result of the go_expand_event_data() method which is
explained below for the "live" mode actions. Currently it is not being
used for any defaults edit actions, but it can be used

Note that relocation (dragging) of objects is triggered by the default
definition of the go_edit_left_action() method. This calls the
go_drag_and_drop function: see below.

-- 1.3. Editable object -----------------------------------------------

For each type of predefined screen object the GO library also allows a
number of more advanced features.

See TEACH * GO_MAKE_EDITABLE.


-- 2. Objects which accept events -------------------------------------

The objects in "live" mode can also accept events, so that behaviour
can be attached to them. The way the system recognises whether an
object will accept the event is through a method called:

    go_accepts_events( TYPE, RAW_EVENT_DATA, OBJECT ) -> BOOLEAN;

The types currently accepted by the GO library are "mouse" events and
"keyboard" events. The method can if needed get more details of the
event from the second argument or from the go_expand_event_data()
method explained below for the "live" actions.

Furthermore, the event which is normally consumed by this acceptance
can if need be also be passed on to underlying objects. This is
achieved by setting the following global variable: see also
REF * go_transparent_to_events.

    true -> go_transparent_to_events;

This will result in a list which consists of all the objects accepting
the event. The user can investigate or intervene with this list in the
global variable: REF * go_forward_event_to

    go_forward_event_to =>

An example of a class which is transparent to events is given below.

-- 2.1. The mixins go_mouse_sensitive and go_key_sensitive ------------

Together with the definitions in the go_xaction library, the definitions
in the sensitive libraries provide methods for objects to which the
user wants to attach "live" actions. These actions can either be
buttonpresses from the mouse device or keystrokes from the go_keyboard.

Objects which inherit from the go_mouse_sensitive mixin can have
behaviour go_attached to the mouse-device. Objects which inherit from
the go_key_sensitive mixin can have behaviour go_attached to the
go_keyboard (including the function keys).

The two mixins are not mutualy exlusive although care has to be taken
with multiple inheritance...

-- 2.2. Button presses ------------------------------------------------

The current definitions allow you to attach actions on either the mouse
button down event, the button up event or the mouse go_drag (with a
specific button down) event.

There are a number of different actions possible, namely three times the
number of mouse-buttons, which on the most widespread mouse-devices with
three buttons, results in nine different actions. Note that some mouse-
devices have only two physical buttons although most X-window
implementations then simulate the third button by mapping the "both
buttons together" event with a logical third button.

The implementation allows the user to extend this definition to have
more mouse-buttons if necessarry. Although this might need additional
coding in a similar style as the definitions in the sensitivedefs
library.

The <action name down>() will be called first if defined. Then if the
user starts moving the mouse with the button still down, the <action
name move>() method will be called if defined. Finally when the button
is released, the <action name up>() method will be called if defined.

For the go_drag action there is an interaction with the state of the
pane's go_motion_hint flag. If the motion hints are on the method will
make sure that everytime the method is handled, the next motion hint is
asked for. If the motion hints are off, then the user must ensure that
the behaviour go_attached to this method does not take too long,
otherwise this will result in a number of events being queued and delays
in reaction to the movement.

-- 2.3. Low level implementation --------------------------------------

The high level implementation only allows for a certain number of these
actions to be attached (three up and one go_drag function). A more
structured approach is now called for, to allow all nine actions, and to
allow to retrieve more information about the general state of all the
devices at the time of the event (location, modifier keys, time,
etc...).

The rest of this paragraph represents the low level implementation.
The four high level actions are simulated by low level methods.
The high level methods will eventually be separated in a different
file.

The three different actions up/move/down will have a single method. Each
of these methods will have an extra piece of data go_attached to it in
the form of a data vector. This vector contains information about the
event. This vector is created by a method go_expand_event_data() which
can be overridden or encapsulated by a user-defined method.

The default method will return:
        - the X-location of the event ( in world coordinates )
        - the Y-loaction of the event ( in world coordinates)
        - the button pressed ( a number 1..3; extendable in the future)
        - the Xpw widget in which the event occurred

This go_expand_event_data() method also allows the user to investigate
other features of an event, such as modifier keys. Note that some window
systems (like Motif under X-windows) have facilities to redefine event
combinations such as button/modifier key combinations.

Great care should be taken to keep this method as fast as possible,
since the state of the devices might change rapidly. Things to consider
also include the recompilation of methods in ObjectClass. This always
gives a delay which should be avoided at key-go_points in the program,
such as this event driven method.

The go_mouse_down_action() method will call the user-defined method with
this event data vector. It is up to the user to avoid conflicts with the
structure returned by the go_expand_event_data() method for a specific
class. The same is true for go_mouse_drag_action() and go_mouse_up_action()
methods.

Example:
    define :method go_mouse_up_action( event_data, obj :<object_type> );
    lvars event_data, obj;
    lvars x=event_data(1), y=event_data(2), butt=event_data(3);
        printf('Button %p pressed on object: %p on position %p,%p\n',
               [%     butt,            datakey(obj),        x, y %]);
    enddefine;

The user can extend the event data vector by including new data. For
example in X-windows the modifier keys can be retrieved whenever an
event happens (See also REF * XtNmodifiers):

    define :method go_expand_event_data( event_data, obj :<object_type> );
    lvars new_event_data, event_data, obj;
    lvars x=event_data(1), y=event_data(2), butt=event_data(3),
        widgt=event_data(4), modifs = XptValue( widgt, XtN modifiers );
        {% x, y, butt, modifs, widgt %};
    enddefine;

-- 2.4. Example of transparent class ----------------------------------

The following class reports events which happen but then passes this on
to underlying objects. See REF * go_transparent_to_events.

    define :class gotcha; isa go_polygon; enddefine;

    define :method go_accepts_events(type,evdata,g:gotcha) -> r;
    lvars r = true;
        if( type == "mouse" ) then true -> go_transparent_to_events;
        endif;
    enddefine;

    define :method report_event(event_data, g:gotcha); enddefine;

    define :method go_mouse_down_action(button, g:gotcha);
        'I feel down' =>;
        report_event;
    enddefine;

    define :method go_mouse_up_action(b,g:gotcha);
        'I feel up' =>;
        report_event;
    enddefine;

The following will create an instance of this class:

    vars reporter = newgotcha();
    go_show( reporter, background_pane );

If the object is moved over another object then it can be made live to
start the reporting.

    true -> go_live_object( reporter );


-- 3. Special mouse down action: The go_drag_and_drop method ----------

The go_drag_and_drop method is a special behaviour which each object can
use. It allows to capture the behaviour for a go_drag-action. The
go_drag_and_drop method is based on the go_drag library (see TEACH *
GO_DRAG).

Unlike the go_mouse_drag_action() method, the go_drag_and_drop method is
designed to be attached to the go_mouse_down_action() method since it
encapsulates the whole of the cycle of dragging an object: it includes
the picking up, dragging and dropping. If it is attached to the drag
action handler then a possible gap between the mouse and the object
can remain.

The go_drag_and_drop method calls two sub-methods:
        - go_clear_drag
        - go_draw_drag

This allows the user to redefine the action which should happen when an
object is picked up (normally go_clear the object from the screen), then
dragged accross the screen (normally go_draw it repeatedly). Finally,
the object will be dropped somewhere. This calls the same go_draw_drag
function, but this time the flag "inDrag" in the client data argument
will be false. Hence extra behaviour can be go_attached to the drop
action.

Example:
    define :class my_object isa go_screen_object; enddefine;

    define :method go_clear_drag( client, obj :my_object );
        'The object is picked up' =>
        call_next_method( client, obj );
    enddefine;

    define :method go_draw_drag( client, obj :my_object );
        if client.inDrag then
            'The object is dragged' =>
        else
            'The object is dropped' =>
        endif;
        call_next_method( client, obj );
    enddefine;


-- 4. The go_keyboard action -----------------------------------------

If the object inherits from the go_key_sensitive method then behaviour
can be attached to the key presses. These can be categorised into a
number of categories such as ascii-keys and fuction keys.

The go_label_editing() method is a predefined function capturing all the
characters directed to a specific object (this is obtained by
positioning the mouse over that object [*]) and can form a basis for
user defined methods. Most of the unprintable characters give warning
messages revealing the category of the key-stroke (see also:
REF * go_label_editing and TEACH * GO_KEY_SENSITIVE).

(*) This does not correspond to a click-to-type window environment. This
    will not be provided in the current release which is limited to a
    point-to-type system.
--- C.all/lib/proto/go/help/go_live
--- Copyright University of Sussex 1993. All rights reserved.
