/* TEACH GO_GROUP                            Ben Rabau, 27th Aug 1993

This file shows a few examples of groups which can be dragged around
without losing their go_components. Other go_components can be added.

For more general detailed information see

HELP * GO
REF * GO


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

 -- SMALL EXAMPLE
 -- MOVING A GROUP
 -- MEMBERSHIP OF A GROUP
 -- COLOURS
 -- EDITING ELEMENTS OF A GROUP
 -- SCALING

 */

;;; Requires the following files to be loaded:
uses go;
uses go_rectangle;
uses go_circle;

;;; It also requires a GO window to be active:
go_init_rc();

/*
-- SMALL EXAMPLE ------------------------------------------------------
 */
;;; Create some objects (3 polygons and 1 go_rectangle)

;;; First we define a go_group which has already two elements:
;;; one go_rectangle and one go_circle.
;;; - The two objects are offset from the centre of the object
;;;   as descibed in the go_local_coords slot: the go_circle
;;;   will be above (in the positive go_yscale sense) and left (in
;;;   the positive go_xscale sense) from the go_rectangle.

define :class test_group;
    isa go_mouse_sensitive, go_key_sensitive, go_group;

    slot go_components          == [% go_rectangle_key, go_circle_key %];
    slot stored_go_local_coords == [ 0  0  0 30];
enddefine;

;;; Then we can create a go_group and go_add_to it on the screen:
vars group1 = instance test_group; endinstance;
go_add_to( group1 , go_default_pane );

/*
-- MOVING A GROUP -----------------------------------------------------
 */
;;; If the go_group is moved the go_components follow:
go_centre_to( 200, -200, group1 );

;;; It is an expensive procedure to go_drag bigger groups so it might
;;; necessitate at least motion hints (see TEACH * GO_DRAG and
;;; REF * GO_XDRAG):
go_motionhint( go_default_pane ) =>
;;; Try dragging the group with both values of:
false -> go_motionhint( go_default_pane );
true -> go_motionhint( go_default_pane );

/*
-- MEMBERSHIP OF A GROUP ----------------------------------------------
 */
;;; We can add new go_components to the go_group if they are existing
;;; screen_objects (e.g another go_rectangle or an go_oblong).
;;; To create an go_oblong object do:
vars extra_component = instance go_oblong; endinstance;

go_add_to( extra_component , go_default_pane );

;;; Then position the go_oblong where you want it relative to the other
;;; go_components. Then you can check that it is not already in the go_group:
go_is_in( extra_component, group1 ) =>

;;; To add it to the go_group do:
go_add_to( extra_component, group1 );

;;; NOTE: After executing go_add_to(), the object always appears
;;;       on top of all other objects in that go_group. This can be seen
;;;       easiest by filling it with a light colour (see LIB * GO_FILLABLE):
'lightblue' -> go_bgcolour( extra_component );
true -> go_filled( extra_component );

;;; Or to delete it from the go_group do:
go_remove_from( extra_component, group1 );

;;; NOTE: After executing go_remove_from(), the object always appears
;;;       on top of all other objects in that pane.

;;; An alternative is to annex it to the back of the group:
go_annex_to( extra_component, group1 );

;;; NOTE: After executing go_remove_from(), the object again appears
;;;       on top of all other objects in that pane.
go_remove_from( extra_component, group1 );


/*
-- COLOURS ------------------------------------------------------------
 */
;;; If the colours of a group (go_fgcolour and go_bgcolour) are changed this
;;; is reflected in all the go_components. The same is true for the filling
;;; of a go_group: all go_fillable go_components will be filled
;;; Try changing the foreground color to blue:
'blue' -> go_fgcolour( group1 );

;;; To visualize the change in the background color the objects need also
;;; to be go_filled:
true -> go_filled( group1 );
'aquamarine' -> go_bgcolour( group1 );

;;; elements of a go_group may of course still be changed individually.
;;; Anonymous go_components (those who have not been added with the
;;; go_add_to() method can be accessed via the slot: the_go_components:
'red' -> go_bgcolour( the_go_components( group1 )(1) );

;;; If you want the defaults back do:
false -> go_fgcolour( group1 );
false -> go_bgcolour( group1 );
false -> go_filled ( group1 );

/*
-- EDITING ELEMENTS OF A GROUP ----------------------------------------
 */

;;; WARNING: THE FOLLOWING NO LONGER WORKS CLEANLY (date: 5th March 1993)

;;; The elements of the go_group can be individually moved when the
;;; go_group is made go_editable with go_make_editable():

go_make_editable( group1 );
;;; NOTES:
;;;        - Currently there is no feedback of this go_editable state.
;;;        - Methods which move groups, e.g. go_centre_to(), will not
;;;          interact correctly with the go_group: the changes to the
;;;          positions of the go_group's elements will be lost!
;;;        - The stacking order ( depth ) of the elements can be wrong.
;;;        - If the group is moved with anything else than the editors
;;;          then editors can be left as garbage on the screen...
;;;          see also: go_redraw( go_default_pane );

;;; After the elements of the go_group have been moved around, the
;;; go_editable mode is turned off with:
go_make_uneditable( group1 );

/*
-- SCALING ------------------------------------------------------------
 */

;;; You can scale the group like all other screen objects; the effect
;;; is that all objects get the same scale and the offsets are also
;;; scaled accordingly.

2.0 -> go_yscale( group1 );
0.5 -> go_xscale( group1 );

0.5 -> go_scale( group1 );
1.0 -> go_scale( group1 );


/*
-- ROTATION -----------------------------------------------------------
 */

;;; You can rotate the group like all rotatable screen objects; the effect
;;; is that all rotatable objects get the same angle and the offsets are also
;;; rotated accordingly. Non rotatable objects in the group are only moved.
;;; Note that the centre of rotation remains the original point although the
;;; centre of the group moves with each addition of an element.

20 -> go_angle( group1 );
90 -> go_angle( group1 );

;;; Rotate around to an angle of 360 degrees in steps of 15 degrees

;;; The rotation point can be moved (e.g. to the centre):
go_position_of_centre( group1 ) -> go_position_of_rotation( group1 );
go_rotate( 360, 15, group1 );

;;; eof

--- C.all/lib/proto/go/teach/go_group
--- Copyright University of Sussex 1993. All rights reserved.
