## guiboss-types-junk.pkg
#
# Support code relating to
src/lib/x-kit/widget/gui/guiboss-types.pkg# Compiled by:
#
src/lib/x-kit/widget/xkit-widget.sublibstipulate
include package threadkit; # threadkit is from
src/lib/src/lib/thread-kit/src/core-thread-kit/threadkit.pkg #
package g2d = geometry2d; # geometry2d is from
src/lib/std/2d/geometry2d.pkg package g2j = geometry2d_junk; # geometry2d_junk is from
src/lib/std/2d/geometry2d-junk.pkg package wt = widget_theme; # widget_theme is from
src/lib/x-kit/widget/theme/widget/widget-theme.pkg package evt = gui_event_types; # gui_event_types is from
src/lib/x-kit/widget/gui/gui-event-types.pkg package o2c = object_to_objectspace; # object_to_objectspace is from
src/lib/x-kit/widget/space/object/object-to-objectspace.pkg package c2o = objectspace_to_object; # objectspace_to_object is from
src/lib/x-kit/widget/space/object/objectspace-to-object.pkg package s2b = sprite_to_spritespace; # sprite_to_spritespace is from
src/lib/x-kit/widget/space/sprite/sprite-to-spritespace.pkg package b2s = spritespace_to_sprite; # spritespace_to_sprite is from
src/lib/x-kit/widget/space/sprite/spritespace-to-sprite.pkg package g2p = gadget_to_pixmap; # gadget_to_pixmap is from
src/lib/x-kit/widget/theme/gadget-to-pixmap.pkg package idm = id_map; # id_map is from
src/lib/src/id-map.pkg package im = int_red_black_map; # int_red_black_map is from
src/lib/src/int-red-black-map.pkg package gtg = guiboss_to_guishim; # guiboss_to_guishim is from
src/lib/x-kit/widget/theme/guiboss-to-guishim.pkg package pp = standard_prettyprinter; # standard_prettyprinter is from
src/lib/prettyprint/big/src/standard-prettyprinter.pkg package lms = list_mergesort; # list_mergesort is from
src/lib/src/list-mergesort.pkg package err = compiler::error_message; # compiler is from
src/lib/core/compiler/compiler.pkg # error_message is from
src/lib/compiler/front/basics/errormsg/error-message.pkg package gd = gui_displaylist; # gui_displaylist is from
src/lib/x-kit/widget/theme/gui-displaylist.pkg nb = log::note_on_stderr; # log is from
src/lib/std/src/log.pkg include package guiboss_types; # guiboss_types is from
src/lib/x-kit/widget/gui/guiboss-types.pkgherein
package guiboss_types_junk
{
Dummy = Int;
#
fun widget_layout_hint__to__string
(
h: Widget_Layout_Hint
)
=
sprintf "{ pixels_high_min => %d, pixels_wide_min => %d, pixels_high_cut => %g, pixels_wide_cut => %g }"
h.pixels_high_min h.pixels_wide_min h.pixels_high_cut h.pixels_wide_cut
;
fun make_nested_box
(
site: g2d::Box,
frame_indent_hint: Frame_Indent_Hint
)
=
{ site -> { col: Int,
row: Int,
#
wide: Int,
high: Int
};
#
frame_indent_hint -> { pixels_for_top_of_frame: Int,
pixels_for_bottom_of_frame: Int,
#
pixels_for_left_of_frame: Int,
pixels_for_right_of_frame: Int
};
col = col + pixels_for_left_of_frame;
row = row + pixels_for_top_of_frame;
wide = wide - (pixels_for_left_of_frame + pixels_for_right_of_frame );
high = high - (pixels_for_top_of_frame + pixels_for_bottom_of_frame);
col = int::min (col, site.col + site.wide);
row = int::min (row, site.row + site.high);
wide = int::max (wide, 0);
high = int::max (high, 0);
{ row, col, wide, high };
};
#########################################################################################
### Gadget_Imp_Info code
fun same_gadget_imp_info
(
{ guiboss_to_gadget => guiboss_to_gadget1, ... }: Gadget_Imp_Info,
{ guiboss_to_gadget => guiboss_to_gadget2, ... }: Gadget_Imp_Info
)
=
same_id ( guiboss_to_gadget1.id,
guiboss_to_gadget2.id
);
fun get_gadget_imp_info
(
gadget_imps: Gadget_Imps,
id: Id
)
=
case (idm::get (*gadget_imps, id))
#
THE gadget_imp_info => gadget_imp_info;
NULL => { msg = sprintf "imp %d not found in gadget_imps?! -- get_gadget_imp_info in guiboss-types-junk.pkg" (id_to_int id); # Should be impossible -- all widgets, sprites and objects should be in gadget_imps.
log::note_on_stderr {. msg; }; # [LATER:] But guis are getting more dynamic, we might be getting stale requests from recently-deceased widgets etc. Maybe we should silently ignore these.
raise exception DIE msg;
};
esac;
#########################################################################################
### Subwindow_Or_View code
fun subwindow_or_view_id_of (SUBWINDOW_INFO r) => (*r.pixmap).id;
subwindow_or_view_id_of (SCROLLABLE_INFO r) => r.pixmap.id;
subwindow_or_view_id_of (TABBABLE_INFO r) => r.pixmap.id;
end;
fun subwindow_info_id_of (SUBWINDOW_DATA r) = (*r.pixmap).id;
fun scrollable_info_id_of (r: Rg_Scrollport) = r.pixmap.id;
fun gadget_to_rw_pixmap__of (SUBWINDOW_INFO r) => *r.pixmap;
gadget_to_rw_pixmap__of (SCROLLABLE_INFO r) => r.pixmap;
gadget_to_rw_pixmap__of (TABBABLE_INFO r) => r.pixmap;
end;
# As of 2014-10-13 this appears to be nowhere used.
# If we don't find a use for it soon we should probably delete it.
# XXX SUCKO FIXME
fun subwindow_or_view_is_visible (SUBWINDOW_INFO _) # This fn is used for finding which widget was clicked on by user; we're just trying to exclude widgets on de-selected views
=> # in TABPORT sets. Consequently we don't worry about whether scrolling has made a pixmap actually not visible to user.
TRUE; # SUBWINDOW_INFO is by definition visible.
subwindow_or_view_is_visible (SCROLLABLE_INFO r) # A SCROLLABLE_INFO is visible if it has *is_visible==TRUE and some chain of parents leading to a SUBWINDOW_INFO are also visible.
=>
TRUE;
subwindow_or_view_is_visible (TABBABLE_INFO r) # A SCROLLABLE_INFO is visible if it has *is_visible==TRUE and some chain of parents leading to a SUBWINDOW_INFO are also visible.
=>
*r.is_visible;
end;
fun subwindow_or_view_id (bp: Subwindow_Or_View)
=
case bp
#
SUBWINDOW_INFO { #
pixmap: Ref( g2p::Gadget_To_Rw_Pixmap ), #
stacking_order: Int,
upperleft: Ref( g2d::Point),
...
}
=>
sprintf "SUBWINDOW_INFO with pixmap.id => %d pixmap.size => %s upperleft => %s stacking_order => %d" (id_to_int (*pixmap).id) (g2j::size_to_string (*pixmap).size) (g2j::point_to_string *upperleft) stacking_order;
SCROLLABLE_INFO { pixmap: g2p::Gadget_To_Rw_Pixmap, # The pixmap visible in the scrollport.
...
}
=>
sprintf "SCROLLABLE_INFO with pixmap.id => %d pixmap.size => %s" (id_to_int pixmap.id) (g2j::size_to_string pixmap.size);
TABBABLE_INFO { pixmap: g2p::Gadget_To_Rw_Pixmap, # The pixmap visible in the tabport.
...
}
=>
sprintf "TABBABLE_INFO with pixmap.id => %d pixmap.size => %s" (id_to_int pixmap.id) (g2j::size_to_string pixmap.size);
esac;
fun subwindow_info_id (bp: Subwindow_Data)
=
case bp
#
SUBWINDOW_DATA { #
pixmap: Ref( g2p::Gadget_To_Rw_Pixmap ), #
stacking_order: Int,
upperleft: Ref( g2d::Point),
...
}
=>
sprintf "SUBWINDOW_DATA with pixmap.id => %d pixmap.size => %s upperleft => %s stacking_order => %d" (id_to_int (*pixmap).id) (g2j::size_to_string (*pixmap).size) (g2j::point_to_string *upperleft) stacking_order;
esac;
stipulate
fun die ()
=
{ msg = "arg should never be a SCROLLABLE_INFO! -- find_all_subwindow_infos_above_given_subwindow_info_in_stacking_order in guiboss-types.pkg";
log::fatal msg;
raise exception DIE msg;
};
herein
fun root_pixmap (subwindow_info: Subwindow_Data)
=
case subwindow_info
#
SUBWINDOW_DATA r
=>
case r.parent
#
THE subwindow_info => root_pixmap subwindow_info;
NULL => subwindow_info;
esac;
esac;
fun subwindow_info_upperleft_in_base_window_coordinates # We support popups on popups, and each popup upperleft is relative to its parent, so we need to sum the upperlefts of given subwindow_info plus all of its parents.
(
subwindow_info: Subwindow_Info
)
: g2d::Point
=
*subwindow_info.upperleft
+
(sum_of_parent_upperlefts subwindow_info)
where
fun sum_of_parent_upperlefts subwindow_info
=
case subwindow_info.parent
#
NULL => g2d::point::zero;
#
THE (SUBWINDOW_DATA r)
=>
*r.upperleft + (sum_of_parent_upperlefts r);
esac;
end;
fun subwindow_info_of_subwindow_data
(
subwindow_info: Subwindow_Data
)
: Subwindow_Info
=
case subwindow_info
#
SUBWINDOW_DATA r => r;
esac;
fun subwindow_info_of_subwindow_or_view # Used in make_rw_pixmap() wrapper in display_one_frame() in
src/lib/x-kit/widget/gui/guiboss-imp.pkg (
subwindow_or_view: Subwindow_Or_View
)
: Subwindow_Info
=
case subwindow_or_view
#
SUBWINDOW_INFO r => r;
#
SCROLLABLE_INFO r
=>
subwindow_info_of_subwindow_or_view r.parent_subwindow_or_view;
#
TABBABLE_INFO r
=>
subwindow_info_of_subwindow_or_view r.parent_subwindow_or_view;
esac;
fun find_all_subwindow_datas_above_given_stacking_order # Called below and also by redraw_all_popups() in
src/lib/x-kit/widget/gui/guiboss-imp.pkg (
subwindow_info: Subwindow_Data,
our_stacking_order: Int
)
: List( Subwindow_Data ) #
=
case subwindow_info
#
SUBWINDOW_DATA r
=>
{
# nb {. sprintf "find_all_subwindow_datas_above_given_stacking_order our_stacking_order d=%d r.stacking_order d=%d r.pixmap.id d=%d r.parent=%s #popups d=%d" our_stacking_order r.stacking_order (id_to_int r.pixmap.id) (case r.parent NULL => "NULL"; _ => "NON-null"; esac) (list::length *r.popups); };
{
# nb {. sprintf "find_all_subwindow_datas_above_given_stacking_order subwindow_info s=%s" (subwindow_or_view_id subwindow_info); };
subwindow_info = root_pixmap subwindow_info;
# nb {. sprintf "find_all_subwindow_datas_above_given_stacking_order (root_pixmap subwindow_info) s=%s" (subwindow_or_view_id subwindow_info); };
# result =
find' subwindow_info;
# nb {. "find_all_subwindow_datas_above_given_stacking_order resultlist:"; };
# apply show_subwindow_or_view result
# where
# fun show_subwindow_or_view (subwindow_or_view: Subwindow_Or_View)
# =
# nb {. sprintf "resultlist element == %s" (subwindow_or_view_id subwindow_or_view); };
# end;
#
# result;
}
where
fun find' tp
=
{
# nb {. sprintf "find_all_subwindow_datas_above_given_stacking_order/find' tp s=%s" (subwindow_or_view_id tp); };
case tp
#
SUBWINDOW_DATA (pm: Subwindow_Info)
=>
{
# nb {. sprintf "find_all_subwindow_datas_above_given_stacking_order/find' our_stacking_order=%d r.stacking_order=%d pm.stacking_order=%d r.pixmap.id=%d r.parent=%s #popups=%d" our_stacking_order r.stacking_order pm.stacking_order (id_to_int (*r.pixmap).id) (case r.parent NULL => "NULL"; _ => "NON-null"; esac) (list::length *r.popups); };
results = if (pm.stacking_order > our_stacking_order) [ tp ];
else [ ];
fi;
# result =
list::cat (results ! (map find' *pm.popups));
# nb {. sprintf "find_all_subwindow_datas_above_given_stacking_order/find' our_stacking_order=%d r.stacking_order=%d r.pixmap.id=%d r.parent=%s #popups=%d #results=%d" our_stacking_order r.stacking_order (id_to_int (*r.pixmap).id) (case r.parent NULL => "NULL"; _ => "NON-null"; esac) (list::length *r.popups) (list::length result); };
# result;
};
esac;
};
end;
};
esac;
fun find_all_subwindow_infos_above_given_subwindow_or_view_in_stacking_order
(
subwindow_or_view: Subwindow_Or_View
)
: List( Subwindow_Info ) # By returning List(Subwindow_Info) rather than List(Subwindow_Or_View) we spare our caller the nuisance of dealing with all the impossible SCROLLABLE_INFO cases.
=
case subwindow_or_view
#
SUBWINDOW_INFO r
=>
{ subwindow_infos
=
find_all_subwindow_datas_above_given_stacking_order
(
SUBWINDOW_DATA r,
r.stacking_order
);
subwindow_infos
=
map subwindow_info_of_subwindow_data subwindow_infos;
subwindow_infos;
};
SCROLLABLE_INFO r # A scrollport/tabport does not have an independent stacking order, it lies at the same stacking order as its parent. (Every scrollport/tabport has a non-port ancestor.)
=>
find_all_subwindow_infos_above_given_subwindow_or_view_in_stacking_order #
#
r.parent_subwindow_or_view;
TABBABLE_INFO r # A scrollport/tabport does not have an independent stacking order, it lies at the same stacking order as its parent. (Every scrollport/tabport has a non-port ancestor.)
=>
find_all_subwindow_infos_above_given_subwindow_or_view_in_stacking_order #
#
r.parent_subwindow_or_view;
esac;
fun return_all_subwindow_infos_in_descending_stacking_order
(
null_or_subwindow_info: Null_Or (Subwindow_Data)
)
: List( Subwindow_Info ) # By returning List(Subwindow_Info) rather than List(Subwindow_Or_View) we spare our caller the nuisance of dealing with all the impossible SCROLLABLE_INFO cases.
=
case null_or_subwindow_info
#
THE (subwindow_info as SUBWINDOW_DATA r)
=>
{ subwindow_datas
=
find_all_subwindow_datas_above_given_stacking_order
(
subwindow_info,
0
);
subwindow_infos
=
map subwindow_info_of_subwindow_data subwindow_datas;
subwindow_infos
=
lms::sort_list subwindow_info_gt subwindow_infos
where
fun subwindow_info_gt
(
p1: Subwindow_Info,
p2: Subwindow_Info
)
=
p1.stacking_order < p2.stacking_order;
end;
# nb {. "subwindow_infos in order:"; };
# apply print_pixmap_order subwindow_infos
# where
# fun print_pixmap_order (p: Subwindow_Info)
# =
# nb {. sprintf "subwindow_info.stacking_order d=%d" p.stacking_order; };
# end;
subwindow_infos;
};
NULL => [];
esac;
fun find__guipane__containing_gadget
(
gadget_imp_info: Gadget_Imp_Info
)
=
{ subwindow_info
=
subwindow_info_of_subwindow_or_view
#
*gadget_imp_info.subwindow_or_view;
*subwindow_info.guipane;
};
fun adjust_origin (origin: g2d::Point, parent: Null_Or(Subwindow_Data))
=
case parent
#
NULL => origin;
#
THE p => case p
#
SUBWINDOW_DATA (pm: Subwindow_Info)
=>
adjust_origin (origin + *pm.upperleft, pm.parent);
esac;
esac;
fun subwindow_info_site_in_basewindow_coordinates
(
subwindow_info: Subwindow_Info
)
=
{
size = (*subwindow_info.pixmap).size;
#
origin = *subwindow_info.upperleft;
origin = adjust_origin (origin, subwindow_info.parent);
g2d::box::make (origin, size);
};
# This is unused and should probably be deleted XXX SUCKO FIXME
fun translate_frombox_to_basewindow_coordinates
(
subwindow_info: Subwindow_Info,
from_box: g2d::Box
)
=
{ box_origin = g2d::box::upperleft from_box;
#
origin = *subwindow_info.upperleft + box_origin;
origin = adjust_origin (origin, subwindow_info.parent);
g2d::box::clone_box_at (from_box, origin);
};
end;
#########################################################################################
### widgetspace-imp code
fun pprint_widgetspace_arg
(pp: pp::Prettyprinter)
(widgetspace_arg: Widgetspace_Arg)
=
{
widgetspace_arg
->
(
options: List(Widgetspace_Option)
);
pp.box {.
pp.txt "[ ";
pp::seqx {. pp.txt ", "; }
pprint_option
options
;
pp.txt " ]";
pp.lit ")";
};
}
where
fun pprint_option option
=
case option
#
PS_MICROTHREAD_NAME name => { pp.lit (sprintf "PS_MICROTHREAD_NAME \"%s\"" name); };
PS_ID id => { pp.lit (sprintf "PS_ID %d" (id_to_int id) ); };
PS_CALLBACK _ => { pp.lit "PS_CALLBACK (callback)"; };
esac;
end;
#########################################################################################
### objectspace-imp code
fun pprint_objectspace_arg
(pp: pp::Prettyprinter)
(objectspace_arg: Objectspace_Arg)
=
{
objectspace_arg
->
(
options: List(Objectspace_Option)
);
pp.box {.
pp.txt "[ ";
pp::seqx {. pp.txt ", "; }
pprint_option
options
;
pp.txt " ]";
pp.lit ")";
};
}
where
fun pprint_option option
=
case option
#
CS_MICROTHREAD_NAME name => { pp.lit (sprintf "CS_MICROTHREAD_NAME \"%s\"" name); };
CS_ID id => { pp.lit (sprintf "CS_ID %d" (id_to_int id) ); };
CS_OBJECTSPACE_CALLBACK _ => { pp.lit "CS_OBJECTSPACE_CALLBACK (callback)"; };
esac;
end;
#########################################################################################
### spritespace-imp code
fun pprint_spritespace_arg
(pp: pp::Prettyprinter)
(spritespace_arg: Spritespace_Arg)
=
{
spritespace_arg
->
(
options: List(Spritespace_Option)
);
pp.box {.
pp.txt "[ ";
pp::seqx {. pp.txt ", "; }
pprint_option
options
;
pp.txt " ]";
pp.lit ")";
};
}
where
fun pprint_option option
=
case option
#
OS_MICROTHREAD_NAME name => { pp.lit (sprintf "OS_MICROTHREAD_NAME \"%s\"" name); };
OS_ID id => { pp.lit (sprintf "OS_ID %d" (id_to_int id) ); };
OS_SPRITESPACE_CALLBACK _ => { pp.lit "OS_SPRITESPACE_CALLBACK (callback)"; };
esac;
end;
#########################################################################################
### gui-plan code
Guiplan_Apply_Option # The following guiplan_apply() facility allows clients to iterate over nodes in a Guiplan tree without having to write out the whole recursion.
#
= GP_ROW_FN (Gp_Row -> Void) # Call this fn on ROW nodes in Guiplan. Defaults to null fn.
| GP_COL_FN (Gp_Col -> Void)
# Call this fn on COL nodes in Guiplan. Defaults to null fn.
| GP_GRID_FN (Gp_Grid -> Void)
# Call this fn on GRID nodes in Guiplan. Defaults to null fn.
| GP_MARK_FN (Gp_Mark -> Void)
# Call this fn on MARK nodes in Guiplan. Defaults to null fn.
#
| GP_ROW'_FN (Gp_Row' -> Void)
# Call this fn on ROW' nodes in Guiplan. Defaults to null fn.
| GP_COL'_FN (Gp_Col' -> Void)
# Call this fn on COL' nodes in Guiplan. Defaults to null fn.
| GP_GRID'_FN (Gp_Grid' -> Void)
# Call this fn on GRID' nodes in Guiplan. Defaults to null fn.
| GP_MARK'_FN (Gp_Mark' -> Void)
# Call this fn on MARK' nodes in Guiplan. Defaults to null fn.
#
| GP_SCROLLPORT_FN (Gp_Scrollport -> Void)
# Call this fn on SCROLLPORT nodes in Guiplan. Defaults to null fn.
| GP_TABPORT_FN (Gp_Tabport -> Void)
# Call this fn on TABPORT nodes in Guiplan. Defaults to null fn.
| GP_FRAME_FN (Gp_Frame -> Void)
# Call this fn on FRAME nodes in Guiplan. Defaults to null fn.
#
| GP_WIDGET_FN (Gp_Widget -> Void)
# Call this fn on WIDGET nodes in Guiplan. Defaults to null fn.
| GP_SPRITE_FN (Sprite_Start_Fn -> Void)
# Call this fn on SPRITE nodes in Guiplan. Defaults to null fn.
| GP_OBJECT_FN (Object_Start_Fn -> Void)
# Call this fn on OBJECT nodes in Guiplan. Defaults to null fn.
#
| GP_WIDGETSPACE_FN (Gp_Widgetspace -> Void)
# Call this fn on WIDGETSPACE nodes in Guiplan. Defaults to null fn.
| GP_OBJECTSPACE_FN (Gp_Objectspace -> Void)
# Call this fn on OBJECTSPACE nodes in Guiplan. Defaults to null fn.
| GP_SPRITESPACE_FN (Gp_Spritespace -> Void)
# Call this fn on SPRITESPACE nodes in Guiplan. Defaults to null fn.
;
fun guiplan_apply
(
guiplan as ( gp_widget: Gp_Widget_Type
),
options: List( Guiplan_Apply_Option )
)
=
do_gp_widget gp_widget
where
fun process_options (options: List(Guiplan_Apply_Option))
=
{ null_fn = (\\ (x: X) = ());
#
my_row_fn = REF null_fn;
my_col_fn = REF null_fn;
my_grid_fn = REF null_fn;
my_mark_fn = REF null_fn;
#
my_row'_fn = REF null_fn;
my_col'_fn = REF null_fn;
my_grid'_fn = REF null_fn;
my_mark'_fn = REF null_fn;
#
my_scrollport_fn = REF null_fn;
my_tabport_fn = REF null_fn;
my_frame_fn = REF null_fn;
#
my_widget_fn = REF null_fn;
my_object_fn = REF null_fn;
my_sprite_fn = REF null_fn;
#
my_widgetspace_fn = REF null_fn;
my_objectspace_fn = REF null_fn;
my_spritespace_fn = REF null_fn;
apply do_option options
where
fun do_option (GP_ROW_FN fn) => my_row_fn := fn;
do_option (GP_COL_FN fn) => my_col_fn := fn;
do_option (GP_GRID_FN fn) => my_grid_fn := fn;
do_option (GP_MARK_FN fn) => my_mark_fn := fn;
#
do_option (GP_ROW'_FN fn) => my_row'_fn := fn;
do_option (GP_COL'_FN fn) => my_col'_fn := fn;
do_option (GP_GRID'_FN fn) => my_grid'_fn := fn;
do_option (GP_MARK'_FN fn) => my_mark'_fn := fn;
#
do_option (GP_SCROLLPORT_FN fn) => my_scrollport_fn := fn;
do_option (GP_TABPORT_FN fn) => my_tabport_fn := fn;
do_option (GP_FRAME_FN fn) => my_frame_fn := fn;
#
do_option (GP_WIDGET_FN fn) => my_widget_fn := fn;
do_option (GP_OBJECT_FN fn) => my_object_fn := fn;
do_option (GP_SPRITE_FN fn) => my_sprite_fn := fn;
#
do_option (GP_WIDGETSPACE_FN fn) => my_widgetspace_fn := fn;
do_option (GP_OBJECTSPACE_FN fn) => my_objectspace_fn := fn;
do_option (GP_SPRITESPACE_FN fn) => my_spritespace_fn := fn;
end;
end;
{ row_fn => *my_row_fn,
col_fn => *my_col_fn,
grid_fn => *my_grid_fn,
mark_fn => *my_mark_fn,
#
row'_fn => *my_row'_fn,
col'_fn => *my_col'_fn,
grid'_fn => *my_grid'_fn,
mark'_fn => *my_mark'_fn,
#
scrollport_fn => *my_scrollport_fn,
tabport_fn => *my_tabport_fn,
frame_fn => *my_frame_fn,
#
widget_fn => *my_widget_fn,
object_fn => *my_object_fn,
sprite_fn => *my_sprite_fn,
#
widgetspace_fn => *my_widgetspace_fn,
objectspace_fn => *my_objectspace_fn,
spritespace_fn => *my_spritespace_fn
};
};
options = process_options options;
fun do_gp_widget (gp_widget: Gp_Widget_Type)
=
case gp_widget
#
ROW (arg: Gp_Row)
=>
{ arg -> (widgets: List( Gp_Widget_Type ));
#
apply do_gp_widget widgets;
options.row_fn arg;
};
COL (arg: Gp_Col)
=>
{ arg -> (widgets: List( Gp_Widget_Type ));
#
apply do_gp_widget widgets;
options.col_fn arg;
};
ROW' (arg: Gp_Row')
=>
{ arg -> ( id: Id,
widgets: List( Gp_Widget_Type )
);
#
apply do_gp_widget widgets;
options.row'_fn arg;
};
COL' (arg: Gp_Col')
=>
{ arg -> ( id: Id,
widgets: List( Gp_Widget_Type )
);
#
apply do_gp_widget widgets;
options.col'_fn arg;
};
GRID (arg: Gp_Grid)
=>
{ arg -> (widgets: List( List( Gp_Widget_Type ) ));
#
apply do_widgets widgets
where
fun do_widgets (widgets: List(Gp_Widget_Type))
=
apply do_gp_widget widgets;
end;
options.grid_fn arg;
};
GRID' (arg: Gp_Grid')
=>
{ arg -> ( id: Id,
widgets: List( List( Gp_Widget_Type ) )
);
#
apply do_widgets widgets
where
fun do_widgets (widgets: List(Gp_Widget_Type))
=
apply do_gp_widget widgets;
end;
options.grid'_fn arg;
};
MARK (arg: Gp_Mark)
=>
{ arg -> (widget: Gp_Widget_Type);
#
do_gp_widget widget;
options.mark_fn arg;
};
MARK' (arg: Gp_Mark')
=>
{ arg -> ( id: Id,
doc: String,
widget: Gp_Widget_Type
);
#
do_gp_widget widget;
options.mark'_fn arg;
};
SCROLLPORT (arg: Gp_Scrollport)
=>
{ arg -> { scroller_callback: Scroller_Callback,
pixmap_size: g2d::Size, # Size of pixmap visible in scrollport.
widget: Gp_Widget_Type # Widget-tree providing content visible in scrollport -- will be rendered onto pixmap.
};
do_gp_widget widget;
options.scrollport_fn arg;
};
TABPORT (arg: Gp_Tabport)
=>
{ arg -> ( tab_picker_callback: Tab_Picker_Callback,
tab: Gp_Widget_Type,
tabs: List( Gp_Widget_Type ) #
);
apply do_gp_widget (tab ! tabs);
options.tabport_fn arg;
};
FRAME (arg: Gp_Frame)
=>
{ arg -> ( frame_options: List(Frame_Option),
widget: Gp_Widget_Type
);
do_gp_widget widget;
#
options.frame_fn arg;
};
WIDGET (arg: Gp_Widget)
=>
{ arg -> (
widget: Widget_Start_Fn
);
#
options.widget_fn arg;
};
OBJECTSPACE (arg: Gp_Objectspace)
=>
{ arg -> ( objectspace_options: List( Objectspace_Option ),
objects: List( Gp_Object )
);
apply do_gp_object objects;
options.objectspace_fn arg;
};
SPRITESPACE (arg: Gp_Spritespace)
=>
{ arg -> ( spritespace_options: List( Spritespace_Option ),
sprites: List( Gp_Sprite )
);
apply do_gp_sprite sprites;
options.spritespace_fn arg;
};
NULL_WIDGET
=>
{
(); # Move along, nothing to see here.
};
esac
also
fun do_gp_object (gp_object: Gp_Object)
=
case gp_object
#
WIDGETSPACE arg
=>
{ arg -> ( widgetspace_options: List(Widgetspace_Option),
gp_widget: Gp_Widget_Type
);
do_gp_widget gp_widget;
options.widgetspace_fn arg;
};
OBJECT (arg: Object_Start_Fn)
=>
{
options.object_fn arg;
};
esac
also
fun do_gp_sprite (gp_sprite: Gp_Sprite)
=
case gp_sprite
#
SPRITE (arg: Sprite_Start_Fn)
=>
{
options.sprite_fn arg;
};
esac;
end;
Guiplan_Map_Option # The following guiplan_map() facility allows clients to recursively rewrite a Guiplan tree without having to write out the whole recursion.
#
= GP_ROW_MAP_FN (Gp_Row -> Gp_Row) # Call this fn on ROW nodes in Guiplan. Defaults to null fn.
| GP_COL_MAP_FN (Gp_Col -> Gp_Col)
# Call this fn on COL nodes in Guiplan. Defaults to null fn.
| GP_GRID_MAP_FN (Gp_Grid -> Gp_Grid)
# Call this fn on GRID nodes in Guiplan. Defaults to null fn.
| GP_MARK_MAP_FN (Gp_Mark -> Gp_Mark)
# Call this fn on MARK nodes in Guiplan. Defaults to null fn.
#
| GP_ROW'_MAP_FN (Gp_Row' -> Gp_Row')
# Call this fn on ROW' nodes in Guiplan. Defaults to null fn.
| GP_COL'_MAP_FN (Gp_Col' -> Gp_Col')
# Call this fn on COL' nodes in Guiplan. Defaults to null fn.
| GP_GRID'_MAP_FN (Gp_Grid' -> Gp_Grid')
# Call this fn on GRID' nodes in Guiplan. Defaults to null fn.
| GP_MARK'_MAP_FN (Gp_Mark' -> Gp_Mark')
# Call this fn on MARK' nodes in Guiplan. Defaults to null fn.
#
| GP_SCROLLPORT_MAP_FN (Gp_Scrollport -> Gp_Scrollport)
# Call this fn on SCROLLPORT nodes in Guiplan. Defaults to null fn.
| GP_TABPORT_MAP_FN (Gp_Tabport -> Gp_Tabport)
# Call this fn on TABPORT nodes in Guiplan. Defaults to null fn.
| GP_FRAME_MAP_FN (Gp_Frame -> Gp_Frame)
# Call this fn on FRAME nodes in Guiplan. Defaults to null fn.
#
| GP_WIDGET_MAP_FN (Gp_Widget -> Gp_Widget)
# Call this fn on WIDGET nodes in Guiplan. Defaults to null fn.
| GP_SPRITE_MAP_FN (Sprite_Start_Fn -> Sprite_Start_Fn)
# Call this fn on SPRITE nodes in Guiplan. Defaults to null fn.
| GP_OBJECT_MAP_FN (Object_Start_Fn -> Object_Start_Fn)
# Call this fn on OBJECT nodes in Guiplan. Defaults to null fn.
#
| GP_WIDGETSPACE_MAP_FN (Gp_Widgetspace -> Gp_Widgetspace)
# Call this fn on WIDGETSPACE nodes in Guiplan. Defaults to null fn.
| GP_OBJECTSPACE_MAP_FN (Gp_Objectspace -> Gp_Objectspace)
# Call this fn on OBJECTSPACE nodes in Guiplan. Defaults to null fn.
| GP_SPRITESPACE_MAP_FN (Gp_Spritespace -> Gp_Spritespace)
# Call this fn on SPRITESPACE nodes in Guiplan. Defaults to null fn.
;
fun guiplan_map
(
guiplan as ( gp_widget: Gp_Widget_Type
),
options: List( Guiplan_Map_Option )
)
=
do_gp_widget gp_widget
where
fun process_options (options: List(Guiplan_Map_Option))
=
{ null_fn = (\\ (x: X) = x);
#
my_row_fn = REF null_fn;
my_col_fn = REF null_fn;
my_grid_fn = REF null_fn;
my_mark_fn = REF null_fn;
#
my_row'_fn = REF null_fn;
my_col'_fn = REF null_fn;
my_grid'_fn = REF null_fn;
my_mark'_fn = REF null_fn;
#
my_scrollport_fn = REF null_fn;
my_tabport_fn = REF null_fn;
my_frame_fn = REF null_fn;
#
my_widget_fn = REF null_fn;
my_object_fn = REF null_fn;
my_sprite_fn = REF null_fn;
#
my_widgetspace_fn = REF null_fn;
my_objectspace_fn = REF null_fn;
my_spritespace_fn = REF null_fn;
apply do_option options
where
fun do_option (GP_ROW_MAP_FN fn) => my_row_fn := fn;
do_option (GP_COL_MAP_FN fn) => my_col_fn := fn;
do_option (GP_GRID_MAP_FN fn) => my_grid_fn := fn;
do_option (GP_MARK_MAP_FN fn) => my_mark_fn := fn;
#
do_option (GP_ROW'_MAP_FN fn) => my_row'_fn := fn;
do_option (GP_COL'_MAP_FN fn) => my_col'_fn := fn;
do_option (GP_GRID'_MAP_FN fn) => my_grid'_fn := fn;
do_option (GP_MARK'_MAP_FN fn) => my_mark'_fn := fn;
#
do_option (GP_SCROLLPORT_MAP_FN fn) => my_scrollport_fn := fn;
do_option (GP_TABPORT_MAP_FN fn) => my_tabport_fn := fn;
do_option (GP_FRAME_MAP_FN fn) => my_frame_fn := fn;
#
do_option (GP_WIDGET_MAP_FN fn) => my_widget_fn := fn;
do_option (GP_OBJECT_MAP_FN fn) => my_object_fn := fn;
do_option (GP_SPRITE_MAP_FN fn) => my_sprite_fn := fn;
#
do_option (GP_WIDGETSPACE_MAP_FN fn) => my_widgetspace_fn := fn;
do_option (GP_OBJECTSPACE_MAP_FN fn) => my_objectspace_fn := fn;
do_option (GP_SPRITESPACE_MAP_FN fn) => my_spritespace_fn := fn;
end;
end;
{ row_fn => *my_row_fn,
col_fn => *my_col_fn,
grid_fn => *my_grid_fn,
mark_fn => *my_mark_fn,
#
row'_fn => *my_row'_fn,
col'_fn => *my_col'_fn,
grid'_fn => *my_grid'_fn,
mark'_fn => *my_mark'_fn,
#
scrollport_fn => *my_scrollport_fn,
tabport_fn => *my_tabport_fn,
frame_fn => *my_frame_fn,
#
widget_fn => *my_widget_fn,
object_fn => *my_object_fn,
sprite_fn => *my_sprite_fn,
#
widgetspace_fn => *my_widgetspace_fn,
objectspace_fn => *my_objectspace_fn,
spritespace_fn => *my_spritespace_fn
};
};
options = process_options options;
fun do_gp_widget (gp_widget: Gp_Widget_Type)
=
case gp_widget
#
ROW (arg: Gp_Row)
=>
{ arg -> (widgets: List( Gp_Widget_Type ));
#
widgets = map do_gp_widget widgets;
arg = widgets;
ROW (options.row_fn arg);
};
COL (arg: Gp_Col)
=>
{ arg -> (widgets: List( Gp_Widget_Type ));
#
widgets = map do_gp_widget widgets;
arg = widgets;
COL (options.col_fn arg);
};
GRID (arg: Gp_Grid)
=>
{ arg -> (widgets: List( List( Gp_Widget_Type ) ));
#
widgets = map do_widgets widgets
where
fun do_widgets (widgets: List(Gp_Widget_Type))
=
map do_gp_widget widgets;
end;
arg = widgets;
GRID (options.grid_fn arg);
};
MARK (arg: Gp_Mark)
=>
{ arg -> (widget: Gp_Widget_Type);
#
do_gp_widget widget;
arg = widget;
MARK (options.mark_fn arg);
};
ROW' (arg: Gp_Row')
=>
{ arg -> ( id: Id,
widgets: List( Gp_Widget_Type )
);
#
widget = map do_gp_widget widgets;
arg = ( id,
widgets
);
ROW' (options.row'_fn arg);
};
COL' (arg: Gp_Col')
=>
{ arg -> ( id: Id,
widgets: List( Gp_Widget_Type )
);
#
widget = map do_gp_widget widgets;
arg = ( id,
widgets
);
COL' (options.col'_fn arg);
};
GRID' (arg: Gp_Grid')
=>
{ arg -> ( id: Id,
widgets: List( List( Gp_Widget_Type ) )
);
#
widgets = map do_widgets widgets
where
fun do_widgets (widgets: List(Gp_Widget_Type))
=
map do_gp_widget widgets;
end;
arg = (id, widgets);
GRID' (options.grid'_fn arg);
};
MARK' (arg: Gp_Mark')
=>
{ arg -> ( id: Id,
doc: String,
widget: Gp_Widget_Type
);
#
widget = do_gp_widget widget;
arg = (id, doc, widget);
MARK' (options.mark'_fn arg);
};
SCROLLPORT (arg: Gp_Scrollport)
=>
{ arg -> { scroller_callback: Scroller_Callback,
pixmap_size: g2d::Size, # Full size of pixmap partly visible in scrollport.
widget: Gp_Widget_Type # Widget-tree providing content visible in scrollport -- will be rendered onto pixmap.
};
widget = do_gp_widget widget;
arg = { scroller_callback,
pixmap_size,
widget
};
SCROLLPORT (options.scrollport_fn arg);
};
TABPORT (arg: Gp_Tabport)
=>
{ arg -> ( tab_picker_callback: Tab_Picker_Callback,
tab: Gp_Widget_Type,
tabs: List( Gp_Widget_Type ) #
);
tab = do_gp_widget tab;
tabs = map do_gp_widget tabs;
arg = ( tab_picker_callback,
tab,
tabs
);
TABPORT (options.tabport_fn arg);
};
FRAME (arg: Gp_Frame)
=>
{ arg -> ( frame_options: List(Frame_Option),
widget: Gp_Widget_Type
);
widget = do_gp_widget widget;
#
arg = ( frame_options,
widget
);
FRAME (options.frame_fn arg);
};
WIDGET (arg: Gp_Widget)
=>
{ arg -> (
widget: Widget_Start_Fn
);
#
WIDGET (options.widget_fn arg);
};
OBJECTSPACE (arg: Gp_Objectspace)
=>
{ arg -> ( objectspace_options: List( Objectspace_Option ),
objects: List( Gp_Object )
);
objects = map do_gp_object objects;
arg = ( objectspace_options,
objects
);
OBJECTSPACE (options.objectspace_fn arg);
};
SPRITESPACE (arg: Gp_Spritespace)
=>
{ arg -> ( spritespace_options: List( Spritespace_Option ),
sprites: List( Gp_Sprite )
);
sprites = map do_gp_sprite sprites;
arg = ( spritespace_options,
sprites
);
SPRITESPACE (options.spritespace_fn arg);
};
NULL_WIDGET
=>
{
NULL_WIDGET; # Move along, nothing to see here.
};
esac
also
fun do_gp_object (gp_object: Gp_Object)
=
case gp_object
#
WIDGETSPACE arg
=>
{ arg -> ( widgetspace_options: List(Widgetspace_Option),
gp_widget: Gp_Widget_Type
);
gp_widget = do_gp_widget gp_widget;
arg = ( widgetspace_options,
gp_widget
);
WIDGETSPACE (options.widgetspace_fn arg);
};
OBJECT (arg: Object_Start_Fn)
=>
{
OBJECT (options.object_fn arg);
};
esac
also
fun do_gp_sprite (gp_sprite: Gp_Sprite)
=
case gp_sprite
#
SPRITE (arg: Sprite_Start_Fn)
=>
{
SPRITE (options.sprite_fn arg);
};
esac;
end;
fun pprint_guiplan (guiplan: Guiplan) # "pprint" == "prettyprint".
=
pp::with_standard_prettyprinter
#
(err::default_plaint_sink ()) []
#
(\\ pp: pp::Prettyprinter
=
do_guiplan guiplan
where
fun do_guiplan guiplan
=
do_gp_widget guiplan
also
fun do_widgetspace
( widgetspace_arg: Widgetspace_Arg,
gp_widget: Gp_Widget_Type
)
=
{ pp.box {.
do_widgetspace_arg widgetspace_arg;
do_gp_widget gp_widget;
};
pp.newline();
}
also
fun do_spritespace
(
spritespace_arg: Spritespace_Arg,
pg_sprites: List( Gp_Sprite )
)
=
{ pp.box {.
do_spritespace_arg spritespace_arg;
do_pg_sprites pg_sprites;
};
pp.newline();
}
also
fun do_spritespace_arg (spritespace_arg: Spritespace_Arg)
=
{
pprint_spritespace_arg pp spritespace_arg;
pp.newline();
}
also
fun do_pg_sprites (gp_sprites: List( Gp_Sprite ))
=
{
pp.box' 0 -1 {.
pp.lit "[";
pp.ind 2;
pp.txt " ";
fun do_sprite (gp_sprite: Gp_Sprite)
=
pp.box {.
do_gp_sprite gp_sprite;
pp.endlit ",";
pp.txt " ";
};
pp::seqx
{. pp.endlit ","; pp.txt " "; } # Inter-element separator.
do_sprite # Print one list element.
gp_sprites; # List of elements.
pp.ind 0;
pp.txt " ";
pp.lit "]";
};
}
also
fun do_gp_sprite (gp_sprite: Gp_Sprite)
=
case gp_sprite
#
SPRITE _
=>
{
pp.box {.
pp.lit "SPRITE _";
};
pp.newline();
};
esac
also
fun do_objectspace
(
objectspace_arg: Objectspace_Arg,
object_widgets: List( Gp_Object )
)
=
{ pp.box {.
do_objectspace_arg objectspace_arg;
do_object_widgets object_widgets;
};
pp.newline();
}
also
fun do_objectspace_arg (objectspace_arg: Objectspace_Arg)
=
{
pprint_objectspace_arg pp objectspace_arg;
pp.newline();
}
also
fun do_object_widgets (object_widgets: List( Gp_Object ))
=
{
pp.box' 0 -1 {.
pp.lit "[";
pp.ind 2;
pp.txt " ";
fun do_widget (object_widget: Gp_Object)
=
pp.box {.
do_object_widget object_widget;
pp.endlit ",";
pp.txt " ";
};
pp::seqx
{. pp.endlit ","; pp.txt " "; } # Inter-element separator.
do_widget # Print one list element.
object_widgets; # List of elements.
pp.ind 0;
pp.txt " ";
pp.lit "]";
};
}
also
fun do_object_widget (object_widget: Gp_Object)
=
case object_widget
#
OBJECT _
=>
{
pp.box {.
pp.lit "OBJECT _";
};
pp.newline();
};
WIDGETSPACE widgetspace
=>
{
pp.lit "WIDGETSPACE ";
pp.newline();
do_widgetspace widgetspace;
pp.newline();
};
esac
also
fun do_widgetspace_arg (widgetspace_arg: Widgetspace_Arg)
=
{
pprint_widgetspace_arg pp widgetspace_arg;
pp.newline();
}
also
fun do_gp_widget (gp_widget: Gp_Widget_Type)
=
case gp_widget
#
ROW (widgets: List( Gp_Widget_Type ))
=>
{
pp.box' 0 -1 {.
pp.lit "ROW [";
pp.ind 2;
pp.txt " ";
fun do_widget (gp_widget: Gp_Widget_Type)
=
pp.box {.
do_gp_widget gp_widget;
pp.endlit ",";
};
pp::seqx
{. pp.endlit ","; pp.txt " "; } # Inter-element separator.
do_widget # Print one list element.
widgets; # List of elements.
pp.ind 0;
pp.txt " ";
pp.lit "]";
};
};
COL (a: List( Gp_Widget_Type ))
=>
{
pp.lit "COL";
pp.newline();
};
GRID (a: List( List( Gp_Widget_Type )))
=>
{
pp.lit "GRID ... ";
pp.newline();
};
MARK (a: Gp_Widget_Type)
=>
{
pp.lit "MARK ... ";
pp.newline();
};
ROW' (id, a: List( Gp_Widget_Type ))
=>
{
pp.lit "ROW'";
pp.newline();
};
COL' (id, a: List( Gp_Widget_Type ))
=>
{
pp.lit "COL'";
pp.newline();
};
GRID' (id, a: List( List( Gp_Widget_Type )))
=>
{
pp.lit "GRID' ... ";
pp.newline();
};
MARK' (id, doc, a: Gp_Widget_Type)
=>
{
pp.lit (sprintf "MARK' ('%s') " doc);
pp.newline();
};
SCROLLPORT _
=>
{
pp.box {.
pp.lit "SCROLLPORT _";
};
pp.newline();
};
TABPORT _
=>
{
pp.box {.
pp.lit "TABPORT _";
};
pp.newline();
};
FRAME _
=>
{
pp.box {.
pp.lit "FRAME _";
};
pp.newline();
};
WIDGET _
=>
{
pp.box {.
pp.lit "WIDGET _";
};
pp.newline();
};
OBJECTSPACE (objectspace: (Objectspace_Arg, List( Gp_Object)))
=>
{
pp.lit "OBJECTSPACE";
do_objectspace objectspace;
pp.newline();
};
SPRITESPACE (spritespace: (Spritespace_Arg, List( Gp_Sprite )))
=>
{
pp.lit "SPRITESPACE";
do_spritespace spritespace;
pp.newline();
};
NULL_WIDGET
=>
{
pp.lit "NULL_WIDGET";
pp.newline();
};
esac;
end
);
#########################################################################################
### running-gui code
fun rg_widget_site (rg_widget: Rg_Widget_Type)
=
case rg_widget
#
RG_ROW r => *r.site;
RG_COL r => *r.site;
RG_GRID r => *r.site;
RG_MARK r => *r.site;
RG_SCROLLPORT r => *r.site;
RG_TABPORT r => *r.site;
RG_FRAME r => *r.site;
RG_WIDGET r => *r.site;
RG_OBJECTSPACE r => *r.site;
RG_SPRITESPACE r => *r.site;
#
RG_NULL_WIDGET => g2d::box::zero;
esac;
fun rg_widget_id (rg_widget: Rg_Widget_Type) # For debugging. NOTE THAT this fn confutes Id and Id values, so uniqueness is not assured!
=
case rg_widget
#
RG_ROW r => id_to_int r.id;
RG_COL r => id_to_int r.id;
RG_GRID r => id_to_int r.id;
RG_MARK r => id_to_int r.id;
RG_SCROLLPORT r => id_to_int r.id;
RG_TABPORT r => id_to_int r.id;
RG_FRAME r => id_to_int r.id;
RG_WIDGET r => id_to_int r.guiboss_to_widget.id;
RG_OBJECTSPACE r => id_to_int r.guiboss_to_objectspace.id;
RG_SPRITESPACE r => id_to_int r.guiboss_to_spritespace.id;
#
RG_NULL_WIDGET => 0;
esac;
Guipane_Map_Option # The following guipane_map() facility allows clients to rewrite a Guipane tree without having to write out the whole recursion.
#
= RG_ROW_MAP_FN (Rg_Row -> Rg_Row) # Call this fn on RG_ROW nodes in Guipane. Defaults to null fn.
| RG_COL_MAP_FN (Rg_Col -> Rg_Col)
# Call this fn on RG_COL nodes in Guipane. Defaults to null fn.
| RG_GRID_MAP_FN (Rg_Grid -> Rg_Grid)
# Call this fn on RG_GRID nodes in Guipane. Defaults to null fn.
| RG_MARK_MAP_FN (Rg_Mark -> Rg_Mark)
# Call this fn on RG_MARK nodes in Guipane. Defaults to null fn.
| RG_SCROLLPORT_MAP_FN (Rg_Scrollport -> Rg_Scrollport)
# Call this fn on RG_SCROLLPORT nodes in Guipane. Defaults to null fn.
| RG_TABPORT_MAP_FN (Rg_Tabport -> Rg_Tabport)
# Call this fn on RG_TABPORT nodes in Guipane. Defaults to null fn.
| RG_FRAME_MAP_FN (Rg_Frame -> Rg_Frame)
# Call this fn on RG_FRAME nodes in Guipane. Defaults to null fn.
| RG_WIDGET_MAP_FN (Rg_Widget -> Rg_Widget)
# Call this fn on RG_WIDGET nodes in Guipane. Defaults to null fn.
| RG_SPRITE_MAP_FN (Rg_Sprite -> Rg_Sprite)
# Call this fn on RG_SPRITE nodes in Guipane. Defaults to null fn.
| RG_OBJECT_MAP_FN (Rg_Object -> Rg_Object)
# Call this fn on RG_OBJECT nodes in Guipane. Defaults to null fn.
| RG_OBJECTSPACE_MAP_FN (Rg_Objectspace -> Rg_Objectspace)
# Call this fn on RG_OBJECTSPACE nodes in Guipane. Defaults to null fn.
| RG_SPRITESPACE_MAP_FN (Rg_Spritespace -> Rg_Spritespace)
# Call this fn on RG_SPRITESPACE nodes in Guipane. Defaults to null fn.
| RG_WIDGETSPACE_MAP_FN (Rg_Widgetspace -> Rg_Widgetspace)
# Call this fn on RG_WIDGETSPACE nodes in Guipane. Defaults to null fn.
;
fun guipane_map
(
guipane: Guipane,
options: List( Guipane_Map_Option )
)
: Guipane
=
{ guipane -> { id: Id,
rg_widget: Rg_Widget_Type, # The widget (or more commonly, tree of widgets) managed by the gui-tree's toplevel widgetspace-imp.
guiboss_to_widgetspace: Guiboss_To_Widgetspace,
widget_to_guiboss: Widget_To_Guiboss,
space_to_gui: Space_To_Gui,
hostwindow: gtg::Guiboss_To_Hostwindow, # The hostwindow on which to draw our widgets.
subwindow_info: Subwindow_Data, # Holds toplevel SUBWINDOW_DATA for gui.
needs_layout_and_redraw: Ref( Bool )
};
rg_widget = do_rg_widget rg_widget;
guipane = { id,
rg_widget,
guiboss_to_widgetspace,
widget_to_guiboss,
space_to_gui,
hostwindow,
subwindow_info,
needs_layout_and_redraw # Should we allocate a new refcell here? Seems more likely to hurt than help us.
};
guipane;
}
where
fun process_options (options: List(Guipane_Map_Option))
=
{ null_fn = (\\ (x: X) = x);
#
my_row_fn = REF null_fn;
my_col_fn = REF null_fn;
my_grid_fn = REF null_fn;
my_mark_fn = REF null_fn;
#
my_scrollport_fn = REF null_fn;
my_tabport_fn = REF null_fn;
my_frame_fn = REF null_fn;
#
my_widget_fn = REF null_fn;
my_object_fn = REF null_fn;
my_sprite_fn = REF null_fn;
#
my_widgetspace_fn = REF null_fn;
my_objectspace_fn = REF null_fn;
my_spritespace_fn = REF null_fn;
apply do_option options
where
fun do_option (RG_ROW_MAP_FN fn) => my_row_fn := fn;
do_option (RG_COL_MAP_FN fn) => my_col_fn := fn;
do_option (RG_GRID_MAP_FN fn) => my_grid_fn := fn;
do_option (RG_MARK_MAP_FN fn) => my_mark_fn := fn;
#
do_option (RG_SCROLLPORT_MAP_FN fn) => my_scrollport_fn := fn;
do_option (RG_TABPORT_MAP_FN fn) => my_tabport_fn := fn;
do_option (RG_FRAME_MAP_FN fn) => my_frame_fn := fn;
#
do_option (RG_WIDGET_MAP_FN fn) => my_widget_fn := fn;
do_option (RG_OBJECT_MAP_FN fn) => my_object_fn := fn;
do_option (RG_SPRITE_MAP_FN fn) => my_sprite_fn := fn;
#
do_option (RG_WIDGETSPACE_MAP_FN fn) => my_widgetspace_fn := fn;
do_option (RG_OBJECTSPACE_MAP_FN fn) => my_objectspace_fn := fn;
do_option (RG_SPRITESPACE_MAP_FN fn) => my_spritespace_fn := fn;
end;
end;
{ row_fn => *my_row_fn,
col_fn => *my_col_fn,
grid_fn => *my_grid_fn,
mark_fn => *my_mark_fn,
#
scrollport_fn => *my_scrollport_fn,
tabport_fn => *my_tabport_fn,
frame_fn => *my_frame_fn,
#
widget_fn => *my_widget_fn,
object_fn => *my_object_fn,
sprite_fn => *my_sprite_fn,
#
widgetspace_fn => *my_widgetspace_fn,
objectspace_fn => *my_objectspace_fn,
spritespace_fn => *my_spritespace_fn
};
};
options = process_options options;
fun do_rg_widget (rg_widget: Rg_Widget_Type)
=
case rg_widget
#
RG_ROW (arg: Rg_Row)
=>
{ arg -> { id: Id,
widgets: List( Rg_Widget_Type ), # The list of widgets to be laid out and displayed in this row.
widget_layout_hint: Ref( Widget_Layout_Hint ),
site: Ref(g2d::Box), # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg first_cut: Null_Or(Float)
};
widgets = map do_rg_widget widgets;
arg = { id,
widgets,
widget_layout_hint,
site,
first_cut
};
RG_ROW (options.row_fn arg);
};
RG_COL (arg: Rg_Col)
=>
{ arg -> { id: Id,
widgets: List( Rg_Widget_Type ), # The list of widgets to be laid out and displayed in this row.
widget_layout_hint: Ref( Widget_Layout_Hint ),
site: Ref(g2d::Box), # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg first_cut: Null_Or(Float)
};
widgets = map do_rg_widget widgets;
arg = { id,
widgets,
widget_layout_hint,
site,
first_cut
};
RG_COL (options.col_fn arg);
};
RG_GRID (arg: Rg_Grid)
=>
{ arg -> { id: Id,
widgets: List( List( Rg_Widget_Type ) ), # The list lists of widgets to be laid out and displayed in this grid.
widget_layout_hint: Ref( Widget_Layout_Hint ),
site: Ref(g2d::Box) # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg };
widgets = map do_widgets widgets
where
fun do_widgets (widgets: List(Rg_Widget_Type))
=
map do_rg_widget widgets;
end;
arg = { id,
widgets,
widget_layout_hint,
site
};
RG_GRID (options.grid_fn arg);
};
RG_MARK (arg: Rg_Mark)
=>
{ arg -> { id: Id,
doc: String,
widget: Rg_Widget_Type, # The widget to be displayed.
widget_layout_hint: Ref( Widget_Layout_Hint ),
site: Ref(g2d::Box) # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg };
widget = do_rg_widget widget;
arg = { id,
doc,
widget,
widget_layout_hint,
site
};
RG_MARK (options.mark_fn arg);
};
RG_SCROLLPORT (arg: Rg_Scrollport)
=>
{
arg ->
{ id: Id,
upperleft: Ref(g2d::Point), # Upperleft of view's subwindow_or_view in scrollport coordinates, used for scrolling pixmap in scrollport.
scroller: Ref(Scroller), # Client-code interface for controlling view_upperleft.
callback: Scroller_Callback, # This is how we pass our Scroller to app client code, which basically lets it set 'pixmap_upperleft' above.
site: Ref(g2d::Box), # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg rg_widget: Ref( Rg_Widget_Type ), # Widget-tree visible in this viewable, which gets rendered onto 'pixmap' here.
# # rg_widget is a Ref not because we intend to change it, but to work around a technical difficulty in guiboss-imp.pkg:do_pg_widget:PG_SCROLLPORT where viewable_data and rg_widget each want to be created first.
pixmap: g2p::Gadget_To_Rw_Pixmap, #
#
parent_subwindow_or_view: Subwindow_Or_View # This can be a SCROLLABLE_INFO if we have a scrollport located on a scrollport.
};
rg_widget = do_rg_widget *rg_widget;
arg = { id,
upperleft,
scroller,
callback,
site,
rg_widget => REF rg_widget,
pixmap,
parent_subwindow_or_view
};
RG_SCROLLPORT (options.scrollport_fn arg);
};
RG_TABPORT (arg: Rg_Tabport)
=>
{ arg -> { id: Id,
tabs: List( Tabbable_Info ), # This record holds one of the alternate views which may be made visible in the scrollport. *** WE REQUIRE AT LEAST ONE ENTRY IN THE LIST! ***
visible_tab: Ref ( Int ), # Which of 'tabs' is currently visible? This refcell references one element from 'tabs'; it supports switching between the tabbed views.
#
callback: Tab_Picker_Callback, # This is how we pass our Tab_Picker to app client code, which basically lets it set 'visible_tab' above.
site: Ref(g2d::Box) # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg };
site = REF *site; # Establish a new refcell to be shared between tabs and rg_tabport.
tabs = map do_tab tabs
where
fun do_tab (arg: Tabbable_Info)
=
{ arg -> { rg_widget: Rg_Widget_Type,
pixmap: g2p::Gadget_To_Rw_Pixmap,
#
parent_subwindow_or_view: Subwindow_Or_View, # This can be a SCROLLABLE_INFO if we have a tabport located on a scrollport, for example.
site: Ref(g2d::Box), # Size and location of subwindow scrollport in parent Subwindow_Or_View coordinates.
#
is_visible: Ref( Bool )
};
rg_widget = do_rg_widget rg_widget;
arg = { rg_widget,
pixmap,
#
parent_subwindow_or_view,
site, # Maintain the invariant that tab.site == rg_tabport.site for all tabs (i.e., refcell is shared).
#
is_visible => REF *is_visible
};
arg;
};
end;
arg = { id,
tabs,
visible_tab => REF *visible_tab,
#
callback,
site
};
RG_TABPORT (options.tabport_fn arg);
};
RG_FRAME (arg: Rg_Frame)
=>
{ arg -> { id: Id,
frame_widget: Rg_Widget_Type, # Widget which will draw the frame surround.
widget: Rg_Widget_Type, # Widget-tree to draw surrounded by frame.
widget_layout_hint: Ref( Widget_Layout_Hint ),
site: Ref(g2d::Box) # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg };
frame_widget = do_rg_widget frame_widget;
widget = do_rg_widget widget;
arg = { id,
frame_widget,
widget,
widget_layout_hint,
site => REF *site
};
RG_FRAME (options.frame_fn arg);
};
RG_WIDGET (arg: Rg_Widget)
=>
{ arg -> { guiboss_to_widget: Guiboss_To_Widget, # The command end of a port for communication to a widget-imp from a
src/lib/x-kit/widget/gui/guiboss-imp.pkg shutdown_oneshot: Once( Void ), # The widget-imp will fire this one-shot when shutting down due to die(). Used by guiboss-imp.
site: Ref(g2d::Box) # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg };
arg = { guiboss_to_widget,
shutdown_oneshot,
site => REF *site
};
RG_WIDGET (options.widget_fn arg);
};
RG_OBJECTSPACE (arg: Rg_Objectspace)
=>
{ arg -> { guiboss_to_objectspace: Guiboss_To_Objectspace,
object_to_objectspace: o2c::Object_To_Objectspace, #
objects: List( Rg_Object_Type ), # The list of objects to be drawn. These can be placed arbitrarily, including possible overlaps.
site: Ref(g2d::Box) # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg };
objects = map do_rg_object objects;
arg = { guiboss_to_objectspace,
object_to_objectspace,
objects,
site => REF *site
};
RG_OBJECTSPACE (options.objectspace_fn arg);
};
RG_SPRITESPACE (arg: Rg_Spritespace)
=>
{ arg -> { guiboss_to_spritespace: Guiboss_To_Spritespace,
sprite_to_spritespace: s2b::Sprite_To_Spritespace, #
sprites: List( Rg_Sprite_Type ), # The list of widgets to be drawn on the spritespace. These can be placed arbitrarily.
site: Ref(g2d::Box) # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg };
sprites = map do_rg_sprite sprites;
arg = { guiboss_to_spritespace,
sprite_to_spritespace,
sprites,
site => REF *site
};
RG_SPRITESPACE (options.spritespace_fn arg);
};
RG_NULL_WIDGET
=>
{
rg_widget;
};
esac
also
fun do_rg_object (rg_object: Rg_Object_Type)
=
case rg_object
#
RG_WIDGETSPACE (arg: Rg_Widgetspace) # A widget space embedded in a object, to allow all widgetspace widgets to be used also on a object.
=>
{ arg -> { guiboss_to_widgetspace: Guiboss_To_Widgetspace,
rg_widget: Rg_Widget_Type
};
rg_widget = do_rg_widget rg_widget;
arg = { guiboss_to_widgetspace,
rg_widget
};
RG_WIDGETSPACE (options.widgetspace_fn arg);
};
RG_OBJECT (arg: Rg_Object)
=>
{ arg -> {
objectspace_to_object: c2o::Objectspace_To_Object, #
guiboss_to_gadget: Guiboss_To_Gadget, #
shutdown_oneshot: Once( Void ) # The sprite-imp will fire this one-shot when shutting down due to die(). Used by guiboss-imp.
};
arg = { objectspace_to_object,
guiboss_to_gadget,
shutdown_oneshot
};
RG_OBJECT (options.object_fn arg);
};
esac
also
fun do_rg_sprite (rg_sprite: Rg_Sprite_Type)
=
case rg_sprite
#
RG_SPRITE (arg: Rg_Sprite)
=>
{ arg -> { spritespace_to_sprite: b2s::Spritespace_To_Sprite, #
guiboss_to_gadget: Guiboss_To_Gadget, #
shutdown_oneshot: Once( Void ) # The sprite-imp will fire this one-shot when shutting down due to die(). Used by guiboss-imp.
};
arg = { spritespace_to_sprite,
guiboss_to_gadget,
shutdown_oneshot
};
RG_SPRITE (options.sprite_fn arg);
};
esac;
end;
Guipane_Apply_Option # The following guipane_apply() facility allows clients to walk a Guipane tree without having to write out the whole recursion.
#
= RG_ROW_FN (Rg_Row -> Void) # Call this fn on RG_ROW nodes in Guipane. Defaults to null fn.
| RG_COL_FN (Rg_Col -> Void)
# Call this fn on RG_COL nodes in Guipane. Defaults to null fn.
| RG_GRID_FN (Rg_Grid -> Void)
# Call this fn on RG_GRID nodes in Guipane. Defaults to null fn.
| RG_MARK_FN (Rg_Mark -> Void)
# Call this fn on RG_MARK nodes in Guipane. Defaults to null fn.
| RG_SCROLLPORT_FN (Rg_Scrollport -> Void)
# Call this fn on RG_SCROLLPORT nodes in Guipane. Defaults to null fn.
| RG_TABPORT_FN (Rg_Tabport -> Void)
# Call this fn on RG_TABPORT nodes in Guipane. Defaults to null fn.
| RG_FRAME_FN (Rg_Frame -> Void)
# Call this fn on RG_FRAME nodes in Guipane. Defaults to null fn.
| RG_WIDGET_FN (Rg_Widget -> Void)
# Call this fn on RG_WIDGET nodes in Guipane. Defaults to null fn.
| RG_OBJECT_FN (Rg_Object -> Void)
# Call this fn on RG_OBJECT nodes in Guipane. Defaults to null fn.
| RG_SPRITE_FN (Rg_Sprite -> Void)
# Call this fn on RG_OBJECT nodes in Guipane. Defaults to null fn.
| RG_OBJECTSPACE_FN (Rg_Objectspace -> Void)
# Call this fn on RG_OBJECTSPACE nodes in Guipane. Defaults to null fn.
| RG_SPRITESPACE_FN (Rg_Spritespace -> Void)
# Call this fn on RG_SPRITESPACE nodes in Guipane. Defaults to null fn.
| RG_WIDGETSPACE_FN (Rg_Widgetspace -> Void)
# Call this fn on RG_WIDGETSPACE nodes in Guipane. Defaults to null fn.
;
fun guipane_apply
(
guipane: Guipane,
options: List( Guipane_Apply_Option )
)
: Void
=
{ guipane -> { id: Id,
rg_widget: Rg_Widget_Type, # The widget (or more commonly, tree of widgets) to display on the Guipane.
guiboss_to_widgetspace: Guiboss_To_Widgetspace,
widget_to_guiboss: Widget_To_Guiboss,
space_to_gui: Space_To_Gui,
hostwindow: gtg::Guiboss_To_Hostwindow, # The hostwindow on which to draw our widgets.
subwindow_info: Subwindow_Data, # Holds toplevel SUBWINDOW_DATA for gui.
needs_layout_and_redraw: Ref( Bool )
};
do_rg_widget rg_widget;
}
where
fun process_options (options: List(Guipane_Apply_Option))
=
{ null_fn = (\\ (x: X) = ());
#
my_row_fn = REF null_fn;
my_col_fn = REF null_fn;
my_grid_fn = REF null_fn;
my_mark_fn = REF null_fn;
#
my_scrollport_fn = REF null_fn;
my_tabport_fn = REF null_fn;
my_frame_fn = REF null_fn;
my_widget_fn = REF null_fn;
my_object_fn = REF null_fn;
my_sprite_fn = REF null_fn;
#
my_spritespace_fn = REF null_fn;
my_objectspace_fn = REF null_fn;
my_widgetspace_fn = REF null_fn;
apply do_option options
where
fun do_option (RG_ROW_FN fn) => my_row_fn := fn;
do_option (RG_COL_FN fn) => my_col_fn := fn;
do_option (RG_GRID_FN fn) => my_grid_fn := fn;
do_option (RG_MARK_FN fn) => my_mark_fn := fn;
#
do_option (RG_SCROLLPORT_FN fn) => my_scrollport_fn := fn;
do_option (RG_TABPORT_FN fn) => my_tabport_fn := fn;
do_option (RG_FRAME_FN fn) => my_frame_fn := fn;
do_option (RG_WIDGET_FN fn) => my_widget_fn := fn;
do_option (RG_OBJECT_FN fn) => my_object_fn := fn;
do_option (RG_SPRITE_FN fn) => my_sprite_fn := fn;
#
do_option (RG_SPRITESPACE_FN fn) => my_spritespace_fn := fn;
do_option (RG_OBJECTSPACE_FN fn) => my_objectspace_fn := fn;
do_option (RG_WIDGETSPACE_FN fn) => my_widgetspace_fn := fn;
end;
end;
{ row_fn => *my_row_fn,
col_fn => *my_col_fn,
grid_fn => *my_grid_fn,
mark_fn => *my_mark_fn,
#
scrollport_fn => *my_scrollport_fn,
tabport_fn => *my_tabport_fn,
frame_fn => *my_frame_fn,
widget_fn => *my_widget_fn,
object_fn => *my_object_fn,
sprite_fn => *my_sprite_fn,
#
spritespace_fn => *my_spritespace_fn,
objectspace_fn => *my_objectspace_fn,
widgetspace_fn => *my_widgetspace_fn
};
};
options = process_options options;
fun do_rg_widget (rg_widget: Rg_Widget_Type)
=
case rg_widget
#
RG_ROW (arg: Rg_Row)
=>
{ arg -> { id: Id,
widgets: List( Rg_Widget_Type ), # The list of widgets to be laid out and displayed in this row.
widget_layout_hint: Ref( Widget_Layout_Hint ),
site: Ref(g2d::Box), # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg first_cut: Null_Or(Float)
};
apply do_rg_widget widgets;
options.row_fn arg;
};
RG_COL (arg: Rg_Col)
=>
{ arg -> { id: Id,
widgets: List( Rg_Widget_Type ), # The list of widgets to be laid out and displayed in this row.
widget_layout_hint: Ref( Widget_Layout_Hint ),
site: Ref(g2d::Box), # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg first_cut: Null_Or(Float)
};
apply do_rg_widget widgets;
options.col_fn arg;
};
RG_GRID (arg: Rg_Grid)
=>
{ arg -> { id: Id,
widgets: List( List( Rg_Widget_Type ) ), # The list lists of widgets to be laid out and displayed in this grid.
widget_layout_hint: Ref( Widget_Layout_Hint ),
site: Ref(g2d::Box) # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg };
apply do_widgets widgets
where
fun do_widgets (widgets: List(Rg_Widget_Type))
=
apply do_rg_widget widgets;
end;
options.grid_fn arg;
};
RG_MARK (arg: Rg_Mark)
=>
{ arg -> { id: Id,
doc: String,
widget: Rg_Widget_Type, # The widget to display.
widget_layout_hint: Ref( Widget_Layout_Hint ),
site: Ref(g2d::Box) # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg };
do_rg_widget widget;
options.mark_fn arg;
};
RG_SCROLLPORT (arg: Rg_Scrollport)
=>
{
arg -> { id: Id,
upperleft: Ref(g2d::Point), # Upperleft of view's subwindow_or_view in scrollport coordinates, used for scrolling pixmap in scrollport.
scroller: Ref(Scroller), # Client-code interface for controlling view_upperleft.
callback: Scroller_Callback, # This is how we pass our Scroller to app client code, which basically lets it set 'pixmap_upperleft' above.
site: Ref(g2d::Box), # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg rg_widget: Ref( Rg_Widget_Type ), # Widget-tree visible in this viewable, which gets rendered onto 'pixmap' here.
# # rg_widget is a Ref not because we intend to change it, but to work around a technical difficulty in guiboss-imp.pkg:do_pg_widget:PG_SCROLLPORT where viewable_data and rg_widget each want to be created first.
pixmap: g2p::Gadget_To_Rw_Pixmap, #
#
parent_subwindow_or_view: Subwindow_Or_View # This can be a SCROLLABLE_INFO if we have a scrollport located on a scrollport.
};
do_rg_widget *rg_widget;
options.scrollport_fn arg;
};
RG_TABPORT (arg: Rg_Tabport)
=>
{ arg -> { id: Id,
tabs: List( Tabbable_Info ), # This holds the alternate views which may be made visible in the tabport. This list is guaranteed to be non-empty.
visible_tab: Ref ( Int ), # Which of 'tabs' is currently visible? This refcell references one element from 'tabs'; it supports switching between the tabbed views.
#
callback: Tab_Picker_Callback, # This is how we pass our Tab_Picker to app client code, which basically lets it set 'visible_tab' above.
site: Ref(g2d::Box) # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg };
apply do_tab tabs
where
fun do_tab (arg: Tabbable_Info)
=
{ arg -> { rg_widget: Rg_Widget_Type,
pixmap: g2p::Gadget_To_Rw_Pixmap,
parent_subwindow_or_view: Subwindow_Or_View, # This can be a SCROLLABLE_INFO if we have a tabport located on a scrollport, for example.
site: Ref(g2d::Box), # Size and location of subwindow scrollport in parent Subwindow_Or_View coordinates.
is_visible: Ref( Bool )
};
do_rg_widget rg_widget;
};
end;
options.tabport_fn arg;
};
RG_FRAME (arg: Rg_Frame)
=>
{ arg -> { id: Id,
frame_widget: Rg_Widget_Type, # Widget which will draw the frame surround.
widget: Rg_Widget_Type, # Widget-tree to draw surrounded by frame.
widget_layout_hint: Ref( Widget_Layout_Hint ),
site: Ref(g2d::Box) # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg };
do_rg_widget frame_widget;
do_rg_widget widget;
options.frame_fn arg;
};
RG_WIDGET (arg: Rg_Widget)
=>
{ arg -> { guiboss_to_widget: Guiboss_To_Widget, # The command end of a port for communication to a widget-imp from a
src/lib/x-kit/widget/gui/guiboss-imp.pkg shutdown_oneshot: Once( Void ), # The widget-imp will fire this one-shot when shutting down due to die(). Used by guiboss-imp.
site: Ref(g2d::Box) # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg };
options.widget_fn arg;
};
RG_OBJECTSPACE (arg: Rg_Objectspace)
=>
{ arg -> { guiboss_to_objectspace: Guiboss_To_Objectspace,
object_to_objectspace: o2c::Object_To_Objectspace, #
objects: List( Rg_Object_Type ), # The list of objects to be drawn. These can be placed arbitrarily, including possible overlaps.
site: Ref(g2d::Box) # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg };
# Eventually we'll have to do the full subrecursion here but for the moment none of that stuff is really operational.
options.objectspace_fn arg;
};
RG_SPRITESPACE (arg: Rg_Spritespace)
=>
{ arg -> { guiboss_to_spritespace: Guiboss_To_Spritespace,
sprite_to_spritespace: s2b::Sprite_To_Spritespace, #
sprites: List( Rg_Sprite_Type ), # The list of widgets to be drawn on the spritespace. These can be placed arbitrarily.
site: Ref(g2d::Box) # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg };
# Eventually we'll have to do the full subrecursion here but for the moment none of that stuff is really operational.
options.spritespace_fn arg;
};
RG_NULL_WIDGET
=>
{
};
esac
also
fun do_rg_object (rg_object: Rg_Object_Type)
=
case rg_object
#
RG_WIDGETSPACE (arg: Rg_Widgetspace) # A widget space embedded in a object, to allow all widgetspace widgets to be used also on a object.
=>
{ arg -> { guiboss_to_widgetspace: Guiboss_To_Widgetspace,
rg_widget: Rg_Widget_Type
};
do_rg_widget rg_widget;
options.widgetspace_fn arg;
};
RG_OBJECT (arg: Rg_Object)
=>
{ arg -> {
objectspace_to_object: c2o::Objectspace_To_Object, #
guiboss_to_gadget: Guiboss_To_Gadget, #
shutdown_oneshot: Once( Void ) # The sprite-imp will fire this one-shot when shutting down due to die(). Used by guiboss-imp.
};
options.object_fn arg;
};
esac
also
fun do_rg_sprite (rg_sprite: Rg_Sprite_Type)
=
case rg_sprite
#
RG_SPRITE (arg: Rg_Sprite)
=>
{ arg -> { spritespace_to_sprite: b2s::Spritespace_To_Sprite, #
guiboss_to_gadget: Guiboss_To_Gadget, #
shutdown_oneshot: Once( Void ) # The sprite-imp will fire this one-shot when shutting down due to die(). Used by guiboss-imp.
};
options.sprite_fn arg;
};
esac;
end;
fun all_guipanes_on_hostwindow_apply # Apply guipane_fn to all Guipane instances on this hostwindow.
#
(hostwindow_info: Hostwindow_Info)
#
(guipane_fn: Guipane -> Void)
=
case *hostwindow_info.subwindow_info
#
THE subwindow_data
=>
do_subwindow_data subwindow_data;
NULL => ();
esac
where
fun do_subwindow_data (SUBWINDOW_DATA (subwindow_info: Subwindow_Info))
=
{ apply do_subwindow_data *subwindow_info.popups;
#
case *subwindow_info.guipane
#
THE (guipane: Guipane)
=>
guipane_fn guipane;
NULL => ();
esac;
};
end;
fun pprint_guipane' # "pprint" == "prettyprint".
(
me: Guiboss_State,
guipane: Guipane,
pp: pp::Prettyprinter
)
=
do_guipane guipane
where
fun do_guipane (guipane: Guipane)
=
{ guipane -> { id: Id,
rg_widget: Rg_Widget_Type, # The widget (or more commonly, tree of widgets) to display on the Guipane.
guiboss_to_widgetspace: Guiboss_To_Widgetspace,
widget_to_guiboss: Widget_To_Guiboss,
space_to_gui: Space_To_Gui,
hostwindow: gtg::Guiboss_To_Hostwindow, # The hostwindow on which to draw our widgets.
subwindow_info: Subwindow_Data, # Holds toplevel SUBWINDOW_DATA for gui.
needs_layout_and_redraw: Ref( Bool )
};
do_rg_widget rg_widget;
}
also
fun do_rg_widget (rg_widget: Rg_Widget_Type)
=
case rg_widget
#
RG_ROW (arg: Rg_Row)
=>
{
arg -> { id: Id,
widgets: List( Rg_Widget_Type ), # The list of widgets to be laid out and displayed in this row.
widget_layout_hint: Ref( Widget_Layout_Hint ),
site: Ref(g2d::Box), # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg first_cut: Null_Or(Float)
};
pp.box' 0 -1 {.
pp.lit (sprintf "RG_ROW id=%d [" (id_to_int id));
pp.ind 2;
pp.txt " ";
fun do_widget (rg_widget: Rg_Widget_Type)
=
pp.box {.
do_rg_widget rg_widget;
};
pp::seqx
{. pp.endlit ","; pp.txt " "; } # Inter-element separator.
do_widget # Print one list element.
widgets; # List of elements.
pp.ind 0;
pp.txt " ";
pp.lit "]";
};
};
RG_COL (arg: Rg_Col)
=>
{
arg -> { id: Id,
widgets: List( Rg_Widget_Type ), # The list of widgets to be laid out and displayed in this row.
widget_layout_hint: Ref( Widget_Layout_Hint ),
site: Ref(g2d::Box), # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg first_cut: Null_Or(Float)
};
pp.box' 0 -1 {.
pp.lit (sprintf "RG_COL id=%d [" (id_to_int id));
pp.ind 2;
pp.txt " ";
fun do_widget (rg_widget: Rg_Widget_Type)
=
pp.box {.
do_rg_widget rg_widget;
};
pp::seqx
{. pp.endlit ","; pp.txt " "; } # Inter-element separator.
do_widget # Print one list element.
widgets; # List of elements.
pp.ind 0;
pp.txt " ";
pp.lit "]";
};
};
RG_GRID (arg: Rg_Grid)
=>
{
arg -> { id: Id,
widgets => widget_lists: List( List( Rg_Widget_Type ) ), # The list lists of widgets to be laid out and displayed in this grid.
widget_layout_hint: Ref( Widget_Layout_Hint ),
site: Ref(g2d::Box) # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg };
pp.box' 0 -1 {.
pp.lit (sprintf "RG_GRID id=%d [" (id_to_int id));
pp.ind 2;
pp.txt " ";
fun do_widgets (rg_widgets: List(Rg_Widget_Type))
=
pp.box {.
pp.lit " [";
pp.ind 2;
pp.txt " ";
fun do_widget (rg_widget: Rg_Widget_Type)
=
pp.box {.
do_rg_widget rg_widget;
};
pp::seqx
{. pp.endlit ","; pp.txt " "; } # Inter-element separator.
do_widget # Print one widget
rg_widgets; # List of elements.
pp.ind 0;
pp.txt " ";
pp.lit "]";
};
pp::seqx
{. pp.endlit ","; pp.txt " "; } # Inter-element separator.
do_widgets # Print one widget list.
widget_lists; # List of elements.
pp.ind 0;
pp.txt " ";
pp.lit "]";
};
};
RG_MARK (arg: Rg_Mark)
=>
{
arg -> { id: Id,
doc: String,
widget: Rg_Widget_Type, # The widget to display.
widget_layout_hint: Ref( Widget_Layout_Hint ),
site: Ref(g2d::Box) # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg };
pp.box' 0 -1 {.
pp.lit (sprintf "RG_MARK id=%d doc='%s' <" (id_to_int id) doc);
pp.ind 2;
pp.txt " ";
do_rg_widget widget;
pp.ind 0;
pp.txt " ";
pp.lit ">";
};
};
RG_SCROLLPORT (arg: Rg_Scrollport)
=>
{
arg -> { id: Id,
upperleft: Ref(g2d::Point), # Upperleft of view's subwindow_or_view in scrollport coordinates, used for scrolling pixmap in scrollport.
scroller: Ref(Scroller), # Client-code interface for controlling view_upperleft.
callback: Scroller_Callback, # This is how we pass our Scroller to app client code, which basically lets it set 'pixmap_upperleft' above.
site: Ref(g2d::Box), # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg rg_widget: Ref( Rg_Widget_Type ), # Widget-tree visible in this viewable, which gets rendered onto 'pixmap' here.
# # rg_widget is a Ref not because we intend to change it, but to work around a technical difficulty in guiboss-imp.pkg:do_pg_widget:PG_SCROLLPORT where viewable_data and rg_widget each want to be created first.
pixmap: g2p::Gadget_To_Rw_Pixmap, #
#
parent_subwindow_or_view: Subwindow_Or_View # This can be a SCROLLABLE_INFO if we have a scrollport located on a scrollport.
};
pp.box {.
pp.lit (sprintf "SCROLLPORT %d " (id_to_int id));
#
do_rg_widget *rg_widget;
};
pp.newline();
};
RG_TABPORT (arg: Rg_Tabport)
=>
{
arg -> { id: Id,
tabs: List( Tabbable_Info ), # This holds the alternate views which may be made visible in the tabport. This list is guaranteed to be non-empty.
visible_tab: Ref ( Int ), # Which of 'tabs' is currently visible? This refcell references one element from 'tabs'; it supports switching between the tabbed views.
#
callback: Tab_Picker_Callback, # This is how we pass our Tab_Picker to app client code, which basically lets it set 'visible_tab' above.
site: Ref(g2d::Box) # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg };
pp.box' 0 -1 {.
pp.lit (sprintf "RG_TABPORT id=%d [" (id_to_int id));
pp.ind 2;
pp.txt " ";
fun do_tab (tab: Tabbable_Info)
=
{ tab -> { rg_widget: Rg_Widget_Type,
pixmap: g2p::Gadget_To_Rw_Pixmap,
parent_subwindow_or_view: Subwindow_Or_View, # This can be a SCROLLABLE_INFO if we have a tabport located on a scrollport, for example.
site: Ref(g2d::Box), # Size and location of subwindow scrollport in parent Subwindow_Or_View coordinates.
is_visible: Ref( Bool )
};
pp.box {.
do_rg_widget rg_widget;
pp.endlit ",";
};
};
pp::seqx
{. pp.endlit ","; pp.txt " "; } # Inter-element separator.
do_tab # Print one list element.
tabs; # List of elements.
pp.ind 0;
pp.txt " ";
pp.lit "]";
};
};
RG_FRAME (arg: Rg_Frame)
=>
{
arg -> { id: Id,
frame_widget: Rg_Widget_Type, # Widget which will draw the frame surround.
widget: Rg_Widget_Type, # Widget-tree to draw surrounded by frame.
widget_layout_hint: Ref( Widget_Layout_Hint ),
site: Ref(g2d::Box) # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg };
pp.lit (sprintf "RG_FRAME id=%d {" (id_to_int id));
pp.ind 2;
pp.txt " ";
pp.box {.
pp.lit "frame_widget => ";
pp.box {.
do_rg_widget frame_widget;
};
pp.endlit ",";
};
pp.box {.
pp.lit "widget => ";
pp.box {.
do_rg_widget widget;
};
};
pp.ind 0;
pp.txt " ";
pp.lit "}";
};
RG_WIDGET (arg: Rg_Widget)
=>
{
arg -> { guiboss_to_widget: Guiboss_To_Widget, # The command end of a port for communication to a widget-imp from a
src/lib/x-kit/widget/gui/guiboss-imp.pkg shutdown_oneshot: Once( Void ), # The widget-imp will fire this one-shot when shutting down due to die(). Used by guiboss-imp.
site: Ref(g2d::Box) # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg };
key = id_to_int guiboss_to_widget.id;
widget_layout_hint
=
case (idm::get (*me.widget_layout_hints, guiboss_to_widget.id))
#
THE h => widget_layout_hint__to__string h;
NULL => "<unknown>";
esac;
pp.box' 0 -1 {.
pp.lit (sprintf "RG_WIDGET id=%d guiboss_to_widget.doc=\"%s\" {" key guiboss_to_widget.doc);
pp.ind 2;
pp.txt " ";
pp.box {.
pp.lit (sprintf "site => %s" (g2j::box_to_string *site));
pp.endlit ",";
};
pp.txt " ";
pp.box {.
pp.lit (sprintf "widget_layout_hint => %s" widget_layout_hint);
};
pp.ind 0;
pp.txt " ";
pp.lit "}";
};
};
RG_OBJECTSPACE (arg: Rg_Objectspace)
=>
{
arg -> { guiboss_to_objectspace: Guiboss_To_Objectspace,
object_to_objectspace: o2c::Object_To_Objectspace, #
objects: List( Rg_Object_Type ), # The list of objects to be drawn. These can be placed arbitrarily, including possible overlaps.
site: Ref(g2d::Box) # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg };
pp.lit "RG_OBJECTSPACE";
# Eventually we'll have to do the full subrecursion here but for the moment none of that stuff is really operational.
pp.newline();
};
RG_SPRITESPACE (arg: Rg_Spritespace)
=>
{
arg -> { guiboss_to_spritespace: Guiboss_To_Spritespace,
sprite_to_spritespace: s2b::Sprite_To_Spritespace, #
sprites: List( Rg_Sprite_Type ), # The list of widgets to be drawn on the spritespace. These can be placed arbitrarily.
site: Ref(g2d::Box) # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg };
pp.lit "RG_SPRITESPACE";
# Eventually we'll have to do the full subrecursion here but for the moment none of that stuff is really operational.
pp.newline();
};
RG_NULL_WIDGET
=>
{
pp.lit "RG_NULL_WIDGET";
};
esac
also
fun do_rg_object (rg_object: Rg_Object_Type)
=
case rg_object
#
RG_WIDGETSPACE (arg: Rg_Widgetspace) # A widget space embedded in a object, to allow all widgetspace widgets to be used also on a object.
=>
{ arg -> { guiboss_to_widgetspace: Guiboss_To_Widgetspace,
rg_widget: Rg_Widget_Type
};
key = id_to_int guiboss_to_widgetspace.id;
pp.box' 0 -1 {.
pp.lit (sprintf "RG_WIDGETSPACE id=%d <" key);
pp.ind 2;
pp.txt " ";
do_rg_widget rg_widget;
pp.ind 0;
pp.txt " ";
pp.lit ">";
};
};
RG_OBJECT (arg: Rg_Object)
=>
{ arg -> {
objectspace_to_object: c2o::Objectspace_To_Object, #
guiboss_to_gadget: Guiboss_To_Gadget, #
shutdown_oneshot: Once( Void ) # The sprite-imp will fire this one-shot when shutting down due to die(). Used by guiboss-imp.
};
key = id_to_int guiboss_to_gadget.id;
pp.box' 0 -1 {.
pp.lit (sprintf "RG_OBJECT id=%d <" key);
pp.ind 2;
pp.txt " ";
pp.ind 0;
pp.txt " ";
pp.lit ">";
};
};
esac
also
fun do_rg_sprite (rg_sprite: Rg_Sprite_Type)
=
case rg_sprite
#
RG_SPRITE (arg: Rg_Sprite)
=>
{ arg -> { spritespace_to_sprite: b2s::Spritespace_To_Sprite, #
guiboss_to_gadget: Guiboss_To_Gadget, #
shutdown_oneshot: Once( Void ) # The sprite-imp will fire this one-shot when shutting down due to die(). Used by guiboss-imp.
};
key = id_to_int guiboss_to_gadget.id;
pp.box' 0 -1 {.
pp.lit (sprintf "RG_SPRITE id=%d <" key);
pp.ind 2;
pp.txt " ";
pp.ind 0;
pp.txt " ";
pp.lit ">";
};
};
esac;
end;
fun pprint_guipane # "pprint" == "prettyprint".
(
me: Guiboss_State,
guipane: Guipane
)
=
pp::with_standard_prettyprinter
#
(err::default_plaint_sink ()) []
#
(\\ pp: pp::Prettyprinter
=
pprint_guipane' (me, guipane, pp)
);
fun pprint_hostwindows
(
me: Guiboss_State,
hostwindows: idm::Map( Hostwindow_Info )
)
=
pp::with_standard_prettyprinter
#
(err::default_plaint_sink ()) []
#
(\\ pp: pp::Prettyprinter
=
{
pp.box' 0 -1 {.
pp.lit "hostwindows [";
pp.ind 2;
pp.txt " ";
fun do_hostwindow
(
arg: Hostwindow_Info
)
=
{
arg -> { guiboss_to_hostwindow: gtg::Guiboss_To_Hostwindow,
current_frame_number: Ref(Int), # We count frames for convenience of widgets and debugging.
seconds_per_frame: Ref(Float), # Primarily so widgets can do motion blurring if they wish.
done_extra_redraw_request_this_frame: Ref(Bool), # See Note[3].
next_stacking_order: Ref(Int), # Next Subwindow_Or_View.stacking_order value to issue.
subwindow_info: Ref( Null_Or( Subwindow_Data ) )
};
pp.lit (sprintf "hostwindow %d [" (id_to_int guiboss_to_hostwindow.id));
pp.ind 2;
pp.txt " ";
fun do_subwindow_info (subwindow_info: Subwindow_Info)
=
{
subwindow_info
->
{ id: Id,
guipane: Ref( Null_Or( Guipane ) ),
pixmap: Ref( g2p::Gadget_To_Rw_Pixmap ), # Main backing store for this running gui.
popups: Ref(List(Subwindow_Data)), # These will all be SUBWINDOW_INFO, so 'Ref(List(Subwindow_Info))' would be a better type here.
parent: Null_Or( Subwindow_Data ), # For popups this points to the parent; for the original non-popup window it is NULL.
stacking_order: Int, # Assigned in increasing order starting at 1; these determine who overlies who visually on the screen in case of overlaps. (Popups must be entirely within parent, but sibling popups can overlap.)
upperleft: Ref(g2d::Point) # If we have a parent, this gives our location on it. Note that pixmap.size gives our size.
};
pp.box' 0 -1 {.
pp.lit (sprintf "subwindow_info %d {" (id_to_int id));
pp.ind 2;
pp.txt " ";
pp.lit (sprintf "stacking_order => %d," stacking_order);
pp.lit (sprintf "upperleft => %s," (g2j::point_to_string *upperleft));
case *guipane
#
THE guipane
=>
pp.box' 0 -1 {.
pp.lit "guipane => ";
pp.ind 2;
pprint_guipane' (me, guipane, pp);
};
NULL => ();
esac;
case *popups
#
[] => ();
_ => {
pp.box' 0 -1 {.
pp.lit sprintf "popups => [";
pp.ind 2;
pp.txt " ";
fun do_subwindow_data (SUBWINDOW_DATA subwindow_info)
=
do_subwindow_info subwindow_info;
pp::seqx
{. pp.endlit ","; pp.txt " "; } # Inter-element separator.
do_subwindow_data # Print one list element.
*popups; # List of elements.
pp.ind 0;
pp.txt " ";
pp.lit "]";
};
};
esac;
};
};
case *subwindow_info
#
THE (SUBWINDOW_DATA subwindow_info)
=> do_subwindow_info subwindow_info;
NULL => ();
esac;
pp.ind 0;
pp.txt " ";
pp.lit "]";
};
pp::seqx
{. pp.endlit ","; pp.txt " "; } # Inter-element separator.
do_hostwindow # Print one list element.
(idm::vals_list hostwindows); # List of elements.
pp.ind 0;
pp.txt " ";
pp.lit "]";
};
}
);
#########################################################################################
### export-gui code
Guipith_Map_Option # The following guipith_map() facility allows clients to rewrite an Guipith tree without having to write out the whole recursion.
#
= XI_ROW_MAP_FN (Xi_Row -> Xi_Row ) # Call this fn on XI_ROW nodes in Guipith. Defaults to null fn.
| XI_COL_MAP_FN (Xi_Col -> Xi_Col )
# Call this fn on XI_COL nodes in Guipith. Defaults to null fn.
| XI_GRID_MAP_FN (Xi_Grid -> Xi_Grid )
# Call this fn on XI_GRID nodes in Guipith. Defaults to null fn.
| XI_MARK_MAP_FN (Xi_Mark -> Xi_Mark )
# Call this fn on XI_MARK nodes in Guipith. Defaults to null fn.
| XI_SCROLLPORT_MAP_FN (Xi_Scrollport -> Xi_Scrollport )
# Call this fn on XI_SCROLLPORT nodes in Guipith. Defaults to null fn.
| XI_TABPORT_MAP_FN (Xi_Tabport -> Xi_Tabport )
# Call this fn on XI_TABPORT nodes in Guipith. Defaults to null fn.
| XI_FRAME_MAP_FN (Xi_Frame -> Xi_Frame )
# Call this fn on XI_FRAME nodes in Guipith. Defaults to null fn.
| XI_WIDGET_MAP_FN (Xi_Widget -> Xi_Widget )
# Call this fn on XI_WIDGET nodes in Guipith. Defaults to null fn.
| XI_GUIPLAN_MAP_FN (Guiplan -> Guiplan )
# Call this fn on XI_WIDGET nodes in Guipith. Defaults to null fn.
#
| XI_WIDGET_TYPE_MAP_FN (Xi_Widget_Type -> Xi_Widget_Type )
# This was an afterthought. Should do the same thing for the other rewritors. XXX SUCKO FIXME
#
| XI_HOSTWINDOW_INFO_MAP_FN (Xi_Hostwindow_Info -> Xi_Hostwindow_Info )
| XI_SUBWINDOW_INFO_MAP_FN (Xi_Subwindow_Info -> Xi_Subwindow_Info )
| XI_GUIPANE_MAP_FN (Xi_Guipane -> Xi_Guipane )
#
| XI_GP_ROW_MAP_FN (Gp_Row -> Gp_Row )
| XI_GP_COL_MAP_FN (Gp_Col -> Gp_Col )
| XI_GP_GRID_MAP_FN (Gp_Grid -> Gp_Grid )
| XI_GP_MARK_MAP_FN (Gp_Mark -> Gp_Mark )
| XI_GP_ROW'_MAP_FN (Gp_Row' -> Gp_Row' )
| XI_GP_COL'_MAP_FN (Gp_Col' -> Gp_Col' )
| XI_GP_GRID'_MAP_FN (Gp_Grid' -> Gp_Grid' )
| XI_GP_MARK'_MAP_FN (Gp_Mark' -> Gp_Mark' )
| XI_GP_SCROLLPORT_MAP_FN (Gp_Scrollport -> Gp_Scrollport )
| XI_GP_TABPORT_MAP_FN (Gp_Tabport -> Gp_Tabport )
| XI_GP_FRAME_MAP_FN (Gp_Frame -> Gp_Frame )
| XI_GP_WIDGET_MAP_FN (Gp_Widget -> Gp_Widget )
#
| XI_GP_WIDGET_TYPE_MAP_FN (Gp_Widget_Type -> Gp_Widget_Type )
# This was an afterthought. Should do the same thing for the other rewritors. XXX SUCKO FIXME
;
fun guipith_map
(
guipiths: idm::Map( Xi_Hostwindow_Info ),
#
options: List( Guipith_Map_Option )
)
=
{ guipiths = do_hostwindows guipiths;
#
guipiths;
}
where
fun process_options (options: List(Guipith_Map_Option))
=
{ null_fn = (\\ (x: X) = x);
#
my_row_fn = REF null_fn;
my_col_fn = REF null_fn;
my_grid_fn = REF null_fn;
my_mark_fn = REF null_fn;
#
my_scrollport_fn = REF null_fn;
my_tabport_fn = REF null_fn;
my_frame_fn = REF null_fn;
my_widget_fn = REF null_fn;
my_guiplan_fn = REF null_fn;
#
my_hostwindow_info_fn = REF null_fn;
my_subwindow_info_fn = REF null_fn;
my_guipane_fn = REF null_fn;
my_widget_type_fn = REF null_fn;
my_gp_row_fn = REF null_fn;
my_gp_col_fn = REF null_fn;
my_gp_grid_fn = REF null_fn;
my_gp_mark_fn = REF null_fn;
my_gp_row'_fn = REF null_fn;
my_gp_col'_fn = REF null_fn;
my_gp_grid'_fn = REF null_fn;
my_gp_mark'_fn = REF null_fn;
my_gp_scrollport_fn = REF null_fn;
my_gp_tabport_fn = REF null_fn;
my_gp_frame_fn = REF null_fn;
my_gp_widget_fn = REF null_fn;
my_gp_widget_type_fn = REF null_fn;
apply do_option options
where
fun do_option (XI_ROW_MAP_FN fn) => my_row_fn := fn;
do_option (XI_COL_MAP_FN fn) => my_col_fn := fn;
do_option (XI_GRID_MAP_FN fn) => my_grid_fn := fn;
do_option (XI_MARK_MAP_FN fn) => my_mark_fn := fn;
#
do_option (XI_SCROLLPORT_MAP_FN fn) => my_scrollport_fn := fn;
do_option (XI_TABPORT_MAP_FN fn) => my_tabport_fn := fn;
do_option (XI_FRAME_MAP_FN fn) => my_frame_fn := fn;
do_option (XI_WIDGET_MAP_FN fn) => my_widget_fn := fn;
do_option (XI_GUIPLAN_MAP_FN fn) => my_guiplan_fn := fn;
#
#
do_option (XI_HOSTWINDOW_INFO_MAP_FN fn) => my_hostwindow_info_fn := fn;
do_option (XI_SUBWINDOW_INFO_MAP_FN fn) => my_subwindow_info_fn := fn;
do_option (XI_GUIPANE_MAP_FN fn) => my_guipane_fn := fn;
do_option (XI_WIDGET_TYPE_MAP_FN fn) => my_widget_type_fn := fn;
do_option (XI_GP_ROW_MAP_FN fn) => my_gp_row_fn := fn;
do_option (XI_GP_COL_MAP_FN fn) => my_gp_col_fn := fn;
do_option (XI_GP_GRID_MAP_FN fn) => my_gp_grid_fn := fn;
do_option (XI_GP_MARK_MAP_FN fn) => my_gp_mark_fn := fn;
do_option (XI_GP_ROW'_MAP_FN fn) => my_gp_row'_fn := fn;
do_option (XI_GP_COL'_MAP_FN fn) => my_gp_col'_fn := fn;
do_option (XI_GP_GRID'_MAP_FN fn) => my_gp_grid'_fn := fn;
do_option (XI_GP_MARK'_MAP_FN fn) => my_gp_mark'_fn := fn;
do_option (XI_GP_SCROLLPORT_MAP_FN fn) => my_gp_scrollport_fn := fn;
do_option (XI_GP_TABPORT_MAP_FN fn) => my_gp_tabport_fn := fn;
do_option (XI_GP_FRAME_MAP_FN fn) => my_gp_frame_fn := fn;
do_option (XI_GP_WIDGET_MAP_FN fn) => my_gp_widget_fn := fn;
do_option (XI_GP_WIDGET_TYPE_MAP_FN fn) => my_gp_widget_type_fn := fn;
end;
end;
{ row_fn => *my_row_fn,
col_fn => *my_col_fn,
grid_fn => *my_grid_fn,
mark_fn => *my_mark_fn,
#
scrollport_fn => *my_scrollport_fn,
tabport_fn => *my_tabport_fn,
frame_fn => *my_frame_fn,
widget_fn => *my_widget_fn,
guiplan_fn => *my_guiplan_fn,
#
hostwindow_info_fn => *my_hostwindow_info_fn,
subwindow_info_fn => *my_subwindow_info_fn,
guipane_fn => *my_guipane_fn,
widget_type_fn => *my_widget_type_fn,
gp_row_fn => *my_gp_row_fn,
gp_col_fn => *my_gp_col_fn,
gp_grid_fn => *my_gp_grid_fn,
gp_mark_fn => *my_gp_mark_fn,
gp_row'_fn => *my_gp_row'_fn,
gp_col'_fn => *my_gp_col'_fn,
gp_grid'_fn => *my_gp_grid'_fn,
gp_mark'_fn => *my_gp_mark'_fn,
gp_scrollport_fn => *my_gp_scrollport_fn,
gp_tabport_fn => *my_gp_tabport_fn,
gp_frame_fn => *my_gp_frame_fn,
gp_widget_fn => *my_gp_widget_fn,
gp_widget_type_fn => *my_gp_widget_type_fn
};
};
options = process_options options;
fun do_gp_widget (gp_widget: Gp_Widget_Type): Gp_Widget_Type
=
case gp_widget
#
ROW (arg: Gp_Row)
=>
{ arg -> (row: List(Gp_Widget_Type));
#
row = map do_gp_widget row;
val = ROW (options.gp_row_fn row);
options.gp_widget_type_fn val;
};
COL (arg: Gp_Col)
=>
{ arg -> (col: List(Gp_Widget_Type));
#
col = map do_gp_widget col;
#
val = COL (options.gp_col_fn col);
options.gp_widget_type_fn val;
};
GRID (arg: Gp_Grid)
=>
{ arg -> (grid: List(List(Gp_Widget_Type)));
#
grid = map do_gp_widgets grid
where
fun do_gp_widgets (widgets: List(Gp_Widget_Type))
=
map do_gp_widget widgets;
end ;
arg = grid;
val = GRID (options.gp_grid_fn arg);
options.gp_widget_type_fn val;
};
MARK (arg: Gp_Mark)
=>
{ arg -> (widget: Gp_Widget_Type);
#
widget = do_gp_widget widget;
arg = widget;
val = MARK (options.gp_mark_fn arg);
options.gp_widget_type_fn val;
};
ROW' (arg: Gp_Row')
=>
{ arg -> ( id: Id,
widgets: List(Gp_Widget_Type)
);
#
widgets = map do_gp_widget widgets;
arg = (id, widgets);
val = ROW' (options.gp_row'_fn arg);
options.gp_widget_type_fn val;
};
COL' (arg: Gp_Col')
=>
{ arg -> ( id: Id,
widgets: List(Gp_Widget_Type)
);
#
widgets = map do_gp_widget widgets;
arg = (id, widgets);
val = COL' (options.gp_col'_fn arg);
options.gp_widget_type_fn val;
};
GRID' (arg: Gp_Grid')
=>
{ arg -> ( id: Id,
grid: List(List(Gp_Widget_Type))
);
#
grid = map do_gp_widgets grid
where
fun do_gp_widgets (widgets: List(Gp_Widget_Type))
=
map do_gp_widget widgets;
end ;
arg = (id, grid);
val = GRID' (options.gp_grid'_fn arg);
options.gp_widget_type_fn val;
};
MARK' (arg: Gp_Mark')
=>
{ arg -> ( id: Id,
doc: String,
widget: Gp_Widget_Type
);
#
widget = do_gp_widget widget;
arg = (id, doc, widget);
val = MARK' (options.gp_mark'_fn arg);
options.gp_widget_type_fn val;
};
SCROLLPORT (arg: Gp_Scrollport)
=>
{ arg -> { scroller_callback: Scroller_Callback,
pixmap_size: g2d::Size, # Size of pixmap visible in scrollport.
widget: Gp_Widget_Type # Widget-tree providing content visible in scrollport -- will be rendered onto pixmap.
};
# arg = { scroller_callback,
# pixmap_size,
# widget
# };
val = SCROLLPORT (options.gp_scrollport_fn arg);
options.gp_widget_type_fn val;
};
TABPORT (arg: Gp_Tabport)
=>
{ arg -> ( tab_picker_callback: Tab_Picker_Callback,
tab: Gp_Widget_Type,
tabs: List( Gp_Widget_Type ) #
);
tabs = map do_gp_widget (tab ! tabs);
arg = ( tab_picker_callback,
tab,
tabs
);
val = TABPORT (options.gp_tabport_fn arg);
options.gp_widget_type_fn val;
};
FRAME (arg: Gp_Frame)
=>
{ arg -> ( frame_options: List(Frame_Option),
gp_widget: Gp_Widget_Type
);
gp_widget = do_gp_widget gp_widget;
arg -> ( frame_options, gp_widget);
val = FRAME (options.gp_frame_fn arg);
options.gp_widget_type_fn val;
};
WIDGET (arg: Gp_Widget)
=>
{ arg -> (
widget: Widget_Start_Fn
);
#
val = WIDGET (options.gp_widget_fn arg);
options.gp_widget_type_fn val;
};
OBJECTSPACE (arg: Gp_Objectspace)
=>
{ arg -> ( objectspace_options: List( Objectspace_Option ),
objects: List( Gp_Object )
);
arg = ( objectspace_options,
objects
);
val = OBJECTSPACE arg; # Eventually we'll have to do the full subrecursion here but for the moment none of that stuff is really operational.
options.gp_widget_type_fn val;
};
SPRITESPACE (arg: Gp_Spritespace)
=>
{ arg -> ( spritespace_options: List( Spritespace_Option ),
sprites: List( Gp_Sprite )
);
arg = ( spritespace_options,
sprites
);
val = SPRITESPACE arg; # Eventually we'll have to do the full subrecursion here but for the moment none of that stuff is really operational.
options.gp_widget_type_fn val;
};
NULL_WIDGET
=>
{ val = gp_widget;
#
options.gp_widget_type_fn val;
};
esac;
fun do_xi_widget (xi_widget: Xi_Widget_Type)
=
case xi_widget
#
XI_ROW (arg: Xi_Row)
=>
{ arg -> { id, widgets, first_cut };
#
widgets = map do_xi_widget widgets;
arg = { id, widgets, first_cut };
val = XI_ROW (options.row_fn arg);
options.widget_type_fn val;
};
XI_COL (arg: Xi_Col)
=>
{ arg -> { id, widgets, first_cut };
#
widgets = map do_xi_widget widgets;
arg = { id, widgets, first_cut };
val = XI_COL (options.row_fn arg);
options.widget_type_fn val;
};
XI_GRID (arg: Xi_Grid)
=>
{ arg -> { id: Id,
widgets: List( List( Xi_Widget_Type ))
};
#
widgets = map do_widgets widgets
where
fun do_widgets (widgets: List(Xi_Widget_Type))
=
map do_xi_widget widgets;
end;
arg = { id, widgets };
val = XI_GRID (options.grid_fn arg);
options.widget_type_fn val;
};
XI_MARK (arg: Xi_Mark)
=>
{ arg -> { id: Id,
doc: String,
widget: Xi_Widget_Type
};
#
widget = do_xi_widget widget;
arg = { id, doc, widget };
val = XI_MARK (options.mark_fn arg);
options.widget_type_fn val;
};
XI_SCROLLPORT (arg: Xi_Scrollport)
=>
{ arg -> { id: Id,
xi_widget: Xi_Widget_Type # Tree of widgets partially visible in scrollport.
};
xi_widget = do_xi_widget xi_widget;
arg = { id,
xi_widget
};
val = XI_SCROLLPORT (options.scrollport_fn arg);
options.widget_type_fn val;
};
XI_TABPORT (arg: Xi_Tabport)
=>
{ arg -> { id: Id,
widgets: List( Xi_Widget_Type )
};
widgets = map do_xi_widget widgets;
arg = { id, widgets };
val = XI_TABPORT (options.tabport_fn arg);
options.widget_type_fn val;
};
XI_FRAME (arg: Xi_Frame)
=>
{ arg -> { id: Id,
frame_widget: Xi_Widget_Type, # Widget which will draw the frame surround.
widget: Xi_Widget_Type # Widget-tree to draw surrounded by frame.
};
frame_widget = do_xi_widget frame_widget;
widget = do_xi_widget widget;
arg = { id,
frame_widget,
widget
};
val = XI_FRAME (options.frame_fn arg);
options.widget_type_fn val;
};
XI_WIDGET (arg: Xi_Widget)
=>
{ arg -> { widget_id: Id,
widget_layout_hint: Widget_Layout_Hint,
doc: String
};
arg = { widget_id,
widget_layout_hint,
doc
};
val = XI_WIDGET (options.widget_fn arg);
options.widget_type_fn val;
};
XI_OBJECTSPACE (arg: Xi_Objectspace)
=>
{ arg -> { guiboss_to_objectspace_id: Id,
xi_objects: List(Xi_Object)
};
#
arg = { guiboss_to_objectspace_id,
xi_objects
};
val = XI_OBJECTSPACE arg; # Eventually we'll have to do the full subrecursion here but for the moment none of that stuff is really operational.
options.widget_type_fn val;
};
XI_SPRITESPACE (arg: Xi_Spritespace)
=>
{ arg -> { guiboss_to_spritespace_id: Id,
xi_sprites: List(Xi_Sprite)
};
#
arg = { guiboss_to_spritespace_id,
xi_sprites
};
val = XI_SPRITESPACE arg; # Eventually we'll have to do the full subrecursion here but for the moment none of that stuff is really operational.
options.widget_type_fn val;
};
XI_NULL_WIDGET
=>
{ val = xi_widget;
#
options.widget_type_fn val;
};
XI_GUIPLAN (arg: Guiplan)
=>
{ arg -> (gp_widget: Gp_Widget_Type);
#
gp_widget = do_gp_widget gp_widget;
arg = (gp_widget);
val = XI_GUIPLAN (options.guiplan_fn arg);
options.widget_type_fn val;
};
esac;
fun do_xi_guipane (arg: Xi_Guipane)
=
{ arg -> { id: Id,
guiboss_to_widgetspace_id: Id,
xi_widget: Xi_Widget_Type # The widget (or more commonly, tree of widgets) managed by the gui-tree's toplevel widgetspace-imp.
};
xi_widget = do_xi_widget xi_widget;
arg = { id, guiboss_to_widgetspace_id, xi_widget };
options.guipane_fn arg;
};
fun do_xi_subwindow_info (arg: Xi_Subwindow_Info)
=
{ arg -> { id: Id, # From (*Subwindow_Info.pixmap).id
guipane: Null_Or( Xi_Guipane ),
popups: List(Xi_Subwindow_Data) #
};
guipane = case guipane
#
THE guipane => THE (do_xi_guipane guipane);
NULL => NULL;
esac;
popups = map do_info popups
where
fun do_info (XI_SUBWINDOW_DATA xi_subwindow_info)
=
XI_SUBWINDOW_DATA (do_xi_subwindow_info xi_subwindow_info);
end;
arg = { id, guipane, popups };
options.subwindow_info_fn arg;
};
fun do_hostwindows (hostwindows: idm::Map( Xi_Hostwindow_Info ))
=
{ hostwindows = REF hostwindows;
#
fun do_hostwindow
(
id': Id,
arg: Xi_Hostwindow_Info
)
=
{ arg -> { id: Id, # From hostwindow_info.guiboss_to_hostwindow.id
subwindow_info: Null_Or( Xi_Subwindow_Data )
};
subwindow_info
=
case subwindow_info
#
THE (XI_SUBWINDOW_DATA xi_subwindow_info)
=>
THE (XI_SUBWINDOW_DATA (do_xi_subwindow_info xi_subwindow_info));
NULL => NULL;
esac;
arg = { id, subwindow_info };
arg = options.hostwindow_info_fn arg;
hostwindows := idm::set (*hostwindows, id', arg);
};
apply do_hostwindow (idm::keyvals_list *hostwindows);
#
*hostwindows;
};
end;
fun xi_widget_id (w: Xi_Widget_Type): Null_Or( Id )
=
case w
#
XI_ROW x => THE x.id;
XI_COL x => THE x.id;
XI_GRID x => THE x.id;
XI_MARK x => THE x.id;
XI_SCROLLPORT x => THE x.id;
XI_TABPORT x => THE x.id;
XI_FRAME x => THE x.id;
XI_WIDGET x => THE x.widget_id;
XI_OBJECTSPACE x => THE x.guiboss_to_objectspace_id;
XI_SPRITESPACE x => THE x.guiboss_to_spritespace_id;
XI_NULL_WIDGET => NULL;
XI_GUIPLAN _ => NULL;
esac;
Guipith_Apply_Option # The following guipith_apply() facility allows clients to rewrite an Guipith tree without having to write out the whole recursion.
#
= XI_ROW_FN (Xi_Row -> Void) # Call this fn on XI_ROW nodes in Guipith. Defaults to null fn.
| XI_COL_FN (Xi_Col -> Void)
# Call this fn on XI_COL nodes in Guipith. Defaults to null fn.
| XI_GRID_FN (Xi_Grid -> Void)
# Call this fn on XI_GRID nodes in Guipith. Defaults to null fn.
| XI_MARK_FN (Xi_Mark -> Void)
# Call this fn on XI_MARK nodes in Guipith. Defaults to null fn.
| XI_SCROLLPORT_FN (Xi_Scrollport -> Void)
# Call this fn on XI_SCROLLPORT nodes in Guipith. Defaults to null fn.
| XI_TABPORT_FN (Xi_Tabport -> Void)
# Call this fn on XI_TABPORT nodes in Guipith. Defaults to null fn.
| XI_FRAME_FN (Xi_Frame -> Void)
# Call this fn on XI_FRAME nodes in Guipith. Defaults to null fn.
| XI_WIDGET_FN (Xi_Widget -> Void)
# Call this fn on XI_WIDGET nodes in Guipith. Defaults to null fn.
| XI_GUIPLAN_FN (Guiplan -> Void)
# Call this fn on XI_WIDGET nodes in Guipith. Defaults to null fn.
#
| XI_HOSTWINDOW_INFO_FN (Xi_Hostwindow_Info -> Void)
| XI_SUBWINDOW_INFO_FN (Xi_Subwindow_Info -> Void)
| XI_GUIPANE_FN (Xi_Guipane -> Void)
#
| XI_GP_ROW_FN (Gp_Row -> Void)
| XI_GP_COL_FN (Gp_Col -> Void)
| XI_GP_GRID_FN (Gp_Grid -> Void)
| XI_GP_MARK_FN (Gp_Mark -> Void)
| XI_GP_ROW'_FN (Gp_Row' -> Void)
| XI_GP_COL'_FN (Gp_Col' -> Void)
| XI_GP_GRID'_FN (Gp_Grid' -> Void)
| XI_GP_MARK'_FN (Gp_Mark' -> Void)
| XI_GP_SCROLLPORT_FN (Gp_Scrollport -> Void)
| XI_GP_TABPORT_FN (Gp_Tabport -> Void)
| XI_GP_FRAME_FN (Gp_Frame -> Void)
| XI_GP_WIDGET_FN (Gp_Widget -> Void)
;
fun guipith_apply
(
hostwindows: idm::Map( Xi_Hostwindow_Info ),
#
options: List( Guipith_Apply_Option )
)
=
do_hostwindows hostwindows
where
fun process_options (options: List(Guipith_Apply_Option))
=
{ null_fn = (\\ (x: X) = ());
#
my_row_fn = REF null_fn;
my_col_fn = REF null_fn;
my_grid_fn = REF null_fn;
my_mark_fn = REF null_fn;
#
my_scrollport_fn = REF null_fn;
my_tabport_fn = REF null_fn;
my_frame_fn = REF null_fn;
my_widget_fn = REF null_fn;
my_guiplan_fn = REF null_fn;
#
my_hostwindow_info_fn = REF null_fn;
my_subwindow_info_fn = REF null_fn;
my_guipane_fn = REF null_fn;
my_gp_row_fn = REF null_fn;
my_gp_col_fn = REF null_fn;
my_gp_grid_fn = REF null_fn;
my_gp_mark_fn = REF null_fn;
my_gp_row'_fn = REF null_fn;
my_gp_col'_fn = REF null_fn;
my_gp_grid'_fn = REF null_fn;
my_gp_mark'_fn = REF null_fn;
my_gp_scrollport_fn = REF null_fn;
my_gp_tabport_fn = REF null_fn;
my_gp_frame_fn = REF null_fn;
my_gp_widget_fn = REF null_fn;
apply do_option options
where
fun do_option (XI_ROW_FN fn) => my_row_fn := fn;
do_option (XI_COL_FN fn) => my_col_fn := fn;
do_option (XI_GRID_FN fn) => my_grid_fn := fn;
do_option (XI_MARK_FN fn) => my_mark_fn := fn;
#
do_option (XI_SCROLLPORT_FN fn) => my_scrollport_fn := fn;
do_option (XI_TABPORT_FN fn) => my_tabport_fn := fn;
do_option (XI_FRAME_FN fn) => my_frame_fn := fn;
do_option (XI_WIDGET_FN fn) => my_widget_fn := fn;
do_option (XI_GUIPLAN_FN fn) => my_guiplan_fn := fn;
#
do_option (XI_HOSTWINDOW_INFO_FN fn) => my_hostwindow_info_fn := fn;
do_option (XI_SUBWINDOW_INFO_FN fn) => my_subwindow_info_fn := fn;
do_option (XI_GUIPANE_FN fn) => my_guipane_fn := fn;
#
do_option (XI_GP_ROW_FN fn) => my_gp_row_fn := fn;
do_option (XI_GP_COL_FN fn) => my_gp_col_fn := fn;
do_option (XI_GP_GRID_FN fn) => my_gp_grid_fn := fn;
do_option (XI_GP_MARK_FN fn) => my_gp_mark_fn := fn;
do_option (XI_GP_ROW'_FN fn) => my_gp_row'_fn := fn;
do_option (XI_GP_COL'_FN fn) => my_gp_col'_fn := fn;
do_option (XI_GP_GRID'_FN fn) => my_gp_grid'_fn := fn;
do_option (XI_GP_MARK'_FN fn) => my_gp_mark'_fn := fn;
do_option (XI_GP_SCROLLPORT_FN fn) => my_gp_scrollport_fn := fn;
do_option (XI_GP_TABPORT_FN fn) => my_gp_tabport_fn := fn;
do_option (XI_GP_FRAME_FN fn) => my_gp_frame_fn := fn;
do_option (XI_GP_WIDGET_FN fn) => my_gp_widget_fn := fn;
end;
end;
{ row_fn => *my_row_fn,
col_fn => *my_col_fn,
grid_fn => *my_grid_fn,
mark_fn => *my_mark_fn,
#
scrollport_fn => *my_scrollport_fn,
tabport_fn => *my_tabport_fn,
frame_fn => *my_frame_fn,
widget_fn => *my_widget_fn,
guiplan_fn => *my_guiplan_fn,
#
hostwindow_info_fn => *my_hostwindow_info_fn,
subwindow_info_fn => *my_subwindow_info_fn,
guipane_fn => *my_guipane_fn,
#
gp_row_fn => *my_gp_row_fn,
gp_col_fn => *my_gp_col_fn,
gp_grid_fn => *my_gp_grid_fn,
gp_mark_fn => *my_gp_mark_fn,
gp_row'_fn => *my_gp_row'_fn,
gp_col'_fn => *my_gp_col'_fn,
gp_grid'_fn => *my_gp_grid'_fn,
gp_mark'_fn => *my_gp_mark'_fn,
gp_scrollport_fn => *my_gp_scrollport_fn,
gp_tabport_fn => *my_gp_tabport_fn,
gp_frame_fn => *my_gp_frame_fn,
gp_widget_fn => *my_gp_widget_fn
};
};
options = process_options options;
fun do_gp_widget (gp_widget: Gp_Widget_Type): Void
=
case gp_widget
#
ROW (arg: Gp_Row)
=>
{ arg -> (row: List(Gp_Widget_Type));
#
apply do_gp_widget row;
options.gp_row_fn arg;
};
COL (arg: Gp_Col)
=>
{ arg -> (col: List(Gp_Widget_Type));
#
apply do_gp_widget col;
options.gp_col_fn arg;
};
GRID (arg: Gp_Grid)
=>
{ arg -> (grid: List(List(Gp_Widget_Type)));
#
apply do_gp_widgets grid
where
fun do_gp_widgets (widgets: List(Gp_Widget_Type))
=
apply do_gp_widget widgets;
end;
options.gp_grid_fn arg;
};
MARK (arg: Gp_Mark)
=>
{ arg -> (widget: Gp_Widget_Type);
#
do_gp_widget widget;
options.gp_mark_fn arg;
};
ROW' (arg: Gp_Row')
=>
{ arg -> ( id: Id,
widgets: List(Gp_Widget_Type)
);
#
apply do_gp_widget widgets;
options.gp_row'_fn arg;
};
COL' (arg: Gp_Col')
=>
{ arg -> ( id: Id,
widgets: List(Gp_Widget_Type)
);
#
apply do_gp_widget widgets;
options.gp_col'_fn arg;
};
GRID' (arg: Gp_Grid')
=>
{ arg -> ( id: Id,
grid: List(List(Gp_Widget_Type))
);
#
apply do_gp_widgets grid
where
fun do_gp_widgets (widgets: List(Gp_Widget_Type))
=
apply do_gp_widget widgets;
end;
options.gp_grid'_fn arg;
};
MARK' (arg: Gp_Mark')
=>
{ arg -> ( id: Id,
doc: String,
widget: Gp_Widget_Type
);
#
do_gp_widget widget;
options.gp_mark'_fn arg;
};
SCROLLPORT (arg: Gp_Scrollport)
=>
{ arg -> { scroller_callback: Scroller_Callback,
pixmap_size: g2d::Size, # Size of pixmap visible in scrollport.
widget: Gp_Widget_Type # Widget-tree providing content visible in scrollport -- will be rendered onto pixmap.
};
options.gp_scrollport_fn arg;
};
TABPORT (arg: Gp_Tabport)
=>
{ arg -> ( tab_picker_callback: Tab_Picker_Callback,
tab: Gp_Widget_Type,
tabs: List( Gp_Widget_Type ) #
);
apply do_gp_widget (tab ! tabs);
options.gp_tabport_fn arg;
};
FRAME (arg: Gp_Frame)
=>
{ arg -> ( frame_options: List(Frame_Option),
gp_widget: Gp_Widget_Type
);
do_gp_widget gp_widget;
options.gp_frame_fn arg;
};
WIDGET (arg: Gp_Widget)
=>
{ arg -> (
widget: Widget_Start_Fn
);
#
options.gp_widget_fn arg;
};
OBJECTSPACE (arg: Gp_Objectspace)
=>
{ arg -> ( objectspace_options: List( Objectspace_Option ),
objects: List( Gp_Object )
);
# Eventually we'll have to do the full subrecursion here but for the moment none of that stuff is really operational.
};
SPRITESPACE (arg: Gp_Spritespace)
=>
{ arg -> ( spritesapce_options: List( Spritespace_Option ),
sprites: List( Gp_Sprite )
);
# Eventually we'll have to do the full subrecursion here but for the moment none of that stuff is really operational.
};
NULL_WIDGET
=>
{
};
esac;
fun do_xi_widget (xi_widget: Xi_Widget_Type)
=
case xi_widget
#
XI_ROW (arg: Xi_Row)
=>
{ arg -> { id, widgets, first_cut };
#
apply do_xi_widget widgets;
options.row_fn arg;
};
XI_COL (arg: Xi_Col)
=>
{ arg -> { id, widgets, first_cut };
#
apply do_xi_widget widgets;
options.row_fn arg;
};
XI_GRID (arg: Xi_Grid)
=>
{ arg -> { id: Id,
widgets: List( List( Xi_Widget_Type ))
};
#
apply do_widgets widgets
where
fun do_widgets (widgets: List(Xi_Widget_Type))
=
apply do_xi_widget widgets;
end;
options.grid_fn arg;
};
XI_MARK (arg: Xi_Mark)
=>
{ arg -> { id: Id,
doc: String,
widget: Xi_Widget_Type
};
#
do_xi_widget widget;
options.mark_fn arg;
};
XI_SCROLLPORT (arg: Xi_Scrollport)
=>
{ arg -> { id: Id,
xi_widget: Xi_Widget_Type # Tree of widgets partially visible in scrollport.
};
do_xi_widget xi_widget;
options.scrollport_fn arg;
};
XI_TABPORT (arg: Xi_Tabport)
=>
{ arg -> { id: Id,
widgets: List( Xi_Widget_Type )
};
apply do_xi_widget widgets;
options.tabport_fn arg;
};
XI_FRAME (arg: Xi_Frame)
=>
{ arg -> { id: Id,
frame_widget: Xi_Widget_Type, # Widget which will draw the frame surround.
widget: Xi_Widget_Type # Widget-tree to draw surrounded by frame.
};
do_xi_widget frame_widget;
do_xi_widget widget;
options.frame_fn arg;
};
XI_WIDGET (arg: Xi_Widget)
=>
{ arg -> { widget_id: Id,
widget_layout_hint: Widget_Layout_Hint,
doc: String
};
options.widget_fn arg;
};
XI_OBJECTSPACE (arg: Xi_Objectspace)
=>
{ arg -> { guiboss_to_objectspace_id: Id,
xi_objects: List(Xi_Object)
};
#
# Eventually we'll have to do the full subrecursion here but for the moment none of that stuff is really operational.
};
XI_SPRITESPACE (arg: Xi_Spritespace)
=>
{ arg -> { guiboss_to_spritespace_id: Id,
xi_sprites: List(Xi_Sprite)
};
#
# Eventually we'll have to do the full subrecursion here but for the moment none of that stuff is really operational.
};
XI_NULL_WIDGET
=>
{
};
XI_GUIPLAN (arg: Guiplan)
=>
{ arg -> (gp_widget: Gp_Widget_Type);
#
do_gp_widget gp_widget;
options.guiplan_fn arg;
};
esac;
fun do_xi_guipane (arg: Xi_Guipane)
=
{ arg -> { id: Id,
guiboss_to_widgetspace_id: Id,
xi_widget: Xi_Widget_Type # The widget (or more commonly, tree of widgets) managed by the gui-tree's toplevel widgetspace-imp.
};
do_xi_widget xi_widget;
options.guipane_fn arg;
};
fun do_xi_subwindow_info (arg: Xi_Subwindow_Info)
=
{ arg -> { id: Id, # From (*Subwindow_Info.pixmap).id
guipane: Null_Or( Xi_Guipane ),
popups: List(Xi_Subwindow_Data) #
};
case guipane
#
THE guipane => do_xi_guipane guipane;
NULL => ();
esac;
apply do_info popups
where
fun do_info (XI_SUBWINDOW_DATA xi_subwindow_info)
=
do_xi_subwindow_info xi_subwindow_info;
end;
options.subwindow_info_fn arg;
};
fun do_hostwindows (hostwindows: idm::Map( Xi_Hostwindow_Info ))
=
apply do_hostwindow (idm::vals_list hostwindows)
where
fun do_hostwindow (arg: Xi_Hostwindow_Info)
=
{ arg -> { id: Id, # From hostwindow_info.guiboss_to_hostwindow.id
subwindow_info: Null_Or( Xi_Subwindow_Data )
};
case subwindow_info
#
THE (XI_SUBWINDOW_DATA xi_subwindow_info)
=>
do_xi_subwindow_info xi_subwindow_info;
NULL => ();
esac;
options.hostwindow_info_fn arg;
};
end;
end;
fun xi_widget_parent # This fn is not yet used. The interface might not be right yet.
(
given_id: Id, # Search for parent of this widget
hostwindows: idm::Map( Xi_Hostwindow_Info ) # throughout these guipiths.
)
: Null_Or( Id )
=
{ result = REF (NULL: Null_Or(Id));
#
fun check_widget
(
parent_id: Id,
w: Xi_Widget_Type
)
=
case (xi_widget_id(w))
#
THE id => if (same_id( id, given_id)) result := THE parent_id; fi;
NULL => ();
esac;
options
=
[ XI_ROW_FN (\\ (x: Xi_Row) = apply do_widget x.widgets where fun do_widget (w: Xi_Widget_Type) = check_widget(x.id, w); end),
XI_ROW_FN (\\ (x: Xi_Row) = apply do_widget x.widgets where fun do_widget (w: Xi_Widget_Type) = check_widget(x.id, w); end),
XI_GRID_FN (\\ (x: Xi_Grid) = apply do_widget x.widgets where fun do_widget (w: List(Xi_Widget_Type)) = apply do_widget' w where fun do_widget' (w: Xi_Widget_Type) = check_widget (x.id, w); end; end),
XI_MARK_FN (\\ (x: Xi_Mark) = check_widget (x.id, x.widget)),
XI_SCROLLPORT_FN (\\ (x: Xi_Scrollport) = check_widget (x.id, x.xi_widget)),
XI_TABPORT_FN (\\ (x: Xi_Tabport) = apply do_widget x.widgets where fun do_widget (w: Xi_Widget_Type) = check_widget(x.id, w); end),
XI_FRAME_FN (\\ (x: Xi_Frame) = { check_widget (x.id, x.frame_widget); check_widget (x.id, x.widget); })
#
# NB: We omit
# XI_GUIPLAN_FN (Guiplan -> Void) # Call this fn on XI_WIDGET nodes in Guipith. Defaults to null fn.
# XI_GP_ROW_FN (Gp_Row -> Void)
# XI_GP_COL_FN (Gp_Col -> Void)
# XI_GP_GRID_FN (Gp_Grid -> Void)
# XI_GP_MARK_FN (Gp_Mark -> Void)
# XI_GP_ROW'_FN (Gp_Row' -> Void)
# XI_GP_COL'_FN (Gp_Col' -> Void)
# XI_GP_GRID'_FN (Gp_Grid' -> Void)
# XI_GP_MARK'_FN (Gp_Mark' -> Void)
# XI_GP_SCROLLPORT_FN (Gp_Scrollport -> Void)
# XI_GP_TABPORT_FN (Gp_Tabport -> Void)
# XI_GP_FRAME_FN (Gp_Frame -> Void)
# XI_GP_WIDGET_FN (Gp_Widget -> Void)
# because their args lack 'id' fields we can check.
# We omit
# XI_HOSTWINDOW_INFO_FN (Xi_Hostwindow_Info -> Void)
# XI_SUBWINDOW_INFO_FN (Xi_Subwindow_Info -> Void)
# XI_GUIPANE_FN (Xi_Guipane -> Void)
# because they don't seem germane at the moment -- possibly
# we should revisit this at some future time.
];
guipith_apply (hostwindows, options);
*result;
};
fun pprint_subwindow_info (subwindow_info: Subwindow_Data)
=
pp::with_standard_prettyprinter
#
(err::default_plaint_sink ()) []
#
(\\ pp: pp::Prettyprinter
=
do_subwindow_info subwindow_info
where
fun do_guipane
(
{ id: Id,
rg_widget: Rg_Widget_Type, # The widget (or more commonly, tree of widgets) managed by the gui-tree's toplevel widgetspace-imp.
guiboss_to_widgetspace: Guiboss_To_Widgetspace,
widget_to_guiboss: Widget_To_Guiboss,
space_to_gui: Space_To_Gui,
hostwindow: gtg::Guiboss_To_Hostwindow, # The hostwindow on which to draw our widgets.
subwindow_info: Subwindow_Data, # Holds toplevel SUBWINDOW_DATA for gui.
needs_layout_and_redraw: Ref( Bool )
}
: Guipane
)
=
{ pp.box {.
pp.lit "GUIPANE {";
pp.ind 2;
pp.txt " ";
pp.lit (sprintf "id => %d" (id_to_int id));
pp.endlit ",";
pp.lit (sprintf "guiboss_to_widgetspace.id => %d" (id_to_int guiboss_to_widgetspace.id));
pp.endlit ",";
pp.lit (sprintf "hostwindow => { id => %d, subwindow_or_view:Gadget_To_Rw_Pixmap => { id => %d, size => %s... }" (id_to_int hostwindow.id) (id_to_int hostwindow.subwindow_or_view.id) (g2j::size_to_string hostwindow.subwindow_or_view.size));
pp.endlit ",";
pp.box {.
pp.lit "rg_widget => ";
do_rg_widget rg_widget;
};
pp.endlit ",";
pp.lit (sprintf "subwindow_info => %s" (subwindow_info_id subwindow_info));
pp.ind 0;
pp.txt " ";
pp.lit "}";
};
pp.newline();
}
also
fun do_subwindow_info (bp: Subwindow_Data)
=
case bp
#
SUBWINDOW_DATA { id: Id, #
guipane: Ref( Null_Or( Guipane ) ), #
pixmap: Ref( g2p::Gadget_To_Rw_Pixmap ), # Main backing pixmap for this running gui.
popups: Ref( List(Subwindow_Data) ), # These will all be SUBWINDOW_DATA, so 'Ref(List(Subwindow_Data))' would be a better type here.
parent: Null_Or( Subwindow_Data ), # For popups this points to the parent; for the original non-popup window it is NULL.
stacking_order: Int, # Assigned in increasing order starting at 1; these determine who overlies who visually on the screen in case of overlaps. (Popups must be entirely within parent, but sibling popups can overlap.)
upperleft: Ref( g2d::Point ) # If we have a parent, this gives our location on it. Note that pixmap.size gives our size.
}
=>
{
pp.box' 0 -1 {.
pp.lit "SUBWINDOW_INFO {";
pp.ind 2;
pp.txt " ";
pp.lit (sprintf "id => %d" (id_to_int id));
pp.endlit ",";
pp.lit (sprintf "stacking_order => %d" stacking_order);
pp.endlit ",";
pp.lit (sprintf "upperleft => %s" (g2j::point_to_string *upperleft));
pp.endlit ",";
pp.lit (sprintf "pixmap.id => %d" (id_to_int (*pixmap).id));
pp.endlit ",";
case *guipane
#
NULL => pp.lit "running_site => NULL";
THE rg => do_guipane rg;
esac;
pp.endlit ",";
case parent
NULL => pp.lit "parent => NULL";
THE p => pp.lit (sprintf "parent => <<< %s >>>" (subwindow_info_id p));
esac;
pp.endlit ",";
pp.lit (sprintf "#popups => %d" (list::length *popups));
pp.endlit ",";
pp::seqx
{. pp.endlit ","; pp.txt " "; } # Inter-element separator.
do_subwindow_info # Print one list element.
*popups; # List of elements.
pp.ind 0;
pp.txt " ";
pp.lit "}";
};
pp.newline();
};
#
esac
also
fun do_widgetspace_arg (widgetspace_arg: Widgetspace_Arg)
=
{
pprint_widgetspace_arg pp widgetspace_arg;
pp.newline();
}
also
fun do_rg_widget (rg_widget: Rg_Widget_Type)
=
case rg_widget
#
RG_ROW { id: Id,
widgets: List( Rg_Widget_Type ),
widget_layout_hint: Ref( Widget_Layout_Hint ),
site: Ref(g2d::Box), # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg first_cut: Null_Or(Float)
}
=>
{
pp.box' 0 -1 {.
pp.lit "RG_ROW {";
pp.ind 2;
pp.txt " ";
pp.lit (sprintf "site => %s" (g2j::box_to_string *site));
pp.endlit ",";
fun do_widget (rg_widget: Rg_Widget_Type)
=
pp.box {.
do_rg_widget rg_widget;
pp.endlit ",";
pp.txt " ";
};
pp::listx pp
do_widget # Print one list element.
"" # Title.
widgets; # List of elements.
pp.ind 0;
pp.txt " ";
pp.lit "}";
};
};
RG_COL { id: Id,
widgets: List( Rg_Widget_Type ),
widget_layout_hint: Ref( Widget_Layout_Hint ),
site: Ref(g2d::Box), # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg first_cut: Null_Or(Float)
}
=>
{
pp.box' 0 -1 {.
pp.lit "RG_COL {";
pp.ind 2;
pp.txt " ";
pp.lit (sprintf "site => %s" (g2j::box_to_string *site));
pp.endlit ",";
fun do_widget (rg_widget: Rg_Widget_Type)
=
pp.box {.
do_rg_widget rg_widget;
pp.endlit ",";
pp.txt " ";
};
pp::listx pp
do_widget # Print one list element.
"" # Title.
widgets; # List of elements.
pp.ind 0;
pp.txt " ";
pp.lit "}";
};
};
RG_GRID { id: Id,
widgets: List( List( Rg_Widget_Type ) ),
widget_layout_hint: Ref( Widget_Layout_Hint ),
site: Ref(g2d::Box) # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg }
=>
{
pp.box' 0 -1 {.
pp.lit "RG_GRID {";
pp.ind 2;
pp.txt " ";
pp.lit (sprintf "site => %s" (g2j::box_to_string *site));
pp.endlit ",";
pp::listx pp
do_row # Print one list element.
"" # Title.
widgets # List of elements.
where
fun do_row (widgets: List(Rg_Widget_Type))
=
pp::listx pp
do_widget # Print one list element.
"" # Title.
widgets # List of elements.
where
fun do_widget (rg_widget: Rg_Widget_Type)
=
pp.box {.
do_rg_widget rg_widget;
pp.endlit ",";
pp.txt " ";
};
end;
end;
pp.ind 0;
pp.txt " ";
pp.lit "}";
};
};
RG_MARK { id: Id,
doc: String,
widget: Rg_Widget_Type,
widget_layout_hint: Ref( Widget_Layout_Hint ),
site: Ref(g2d::Box) # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg }
=>
{
pp.box' 0 -1 {.
pp.lit (sprintf "RG_MARK id=%d doc='%s' {" (id_to_int id) doc);
pp.ind 2;
pp.txt " ";
pp.lit (sprintf "site => %s" (g2j::box_to_string *site));
pp.endlit ",";
do_rg_widget widget;
pp.ind 0;
pp.txt " ";
pp.lit "}";
};
};
RG_SCROLLPORT
{ id: Id, # Here we provide support for widgets visible through a scrollable scrollport. Actually providing scrollbars happens at a higher level; here we handle pixmap state maintenance and redraw support.
upperleft: Ref(g2d::Point), # Upperleft of view's subwindow_or_view in scrollport coordinates, used for scrolling pixmap in scrollport.
scroller: Ref(Scroller), # Client-code interface for controlling view_upperleft. This is a ref to resolve mutual recursion issues at creation, not because we expect to update it.
callback: Scroller_Callback, # This is how we pass our Scroller to app client code, which basically lets it set 'pixmap_upperleft' above.
site: Ref(g2d::Box), # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg rg_widget: Ref( Rg_Widget_Type ), # Widget-tree visible in this viewable, which gets rendered onto 'pixmap' here.
# # rg_widget is a Ref not because we intend to change it, but to work around a technical difficulty in guiboss-imp.pkg:do_pg_widget:PG_SCROLLPORT where viewable_data and rg_widget each want to be created first.
pixmap: g2p::Gadget_To_Rw_Pixmap, #
#
#
parent_subwindow_or_view: Subwindow_Or_View # This can be a SCROLLABLE_INFO if we have a scrollport located on a scrollport.
}
=>
{
pp.lit "RG_SCROLLPORT { ... }";
pp.newline();
};
RG_TABPORT # Here we provide support for selection between alternate views in scrollport. Actually providing tabs happens at a higher level; here we handle pixmap state maintenance and redraw support.
{ id: Id,
tabs: List( Tabbable_Info ), # Each record holds one of the alternate tabs which may be made visible in the tabport. This list is guaranteed to be non-empty.
visible_tab: Ref ( Int ), # Which of 'tabs' is currently visible? This refcell references one element from 'tabs'; it supports switching between the tabbed views.
callback: Tab_Picker_Callback, # This is how we pass our Tab_Picker to app client code, which basically lets it set 'visible_tab' above.
site: Ref(g2d::Box) # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg }
=>
{
pp.lit "RG_TABPORT { ... }";
pp.newline();
};
RG_FRAME _
=>
{
pp.lit "RG_FRAME { ... }";
pp.newline();
};
RG_WIDGET { # An actual leaf widget like an arrowbutton or label or text-entry box. These are all customizations of
src/lib/x-kit/widget/xkit/theme/widget/default/look/widget-imp.pkg guiboss_to_widget: Guiboss_To_Widget, # The command end of a port for communication to a widget-imp from a
src/lib/x-kit/widget/gui/guiboss-imp.pkg shutdown_oneshot: Once( Void ), # The widget-imp will fire this one-shot when shutting down due to die(). Used by guiboss-imp.
site: Ref(g2d::Box) # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg }
=>
{
pp.box {.
pp.lit (sprintf "RG_WIDGET guiboss_to_widget.doc=\"%s\" {" guiboss_to_widget.doc);
pp.lit (sprintf "guiboss_to_widget.id => %d" (id_to_int guiboss_to_widget.id));
pp.endlit ",";
pp.lit (sprintf "site => %s" (g2j::box_to_string *site));
pp.lit " }";
};
pp.newline();
};
RG_OBJECTSPACE { guiboss_to_objectspace: Guiboss_To_Objectspace,
object_to_objectspace: o2c::Object_To_Objectspace, #
objects: List( Rg_Object_Type ), # The list of objects to be drawn. These can be placed arbitrarily, including possible overlaps.
site: Ref(g2d::Box) # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg }
=>
{
pp.lit "RG_OBJECTSPACE";
# do_objectspace objectspace;
pp.newline();
};
RG_SPRITESPACE { guiboss_to_spritespace: Guiboss_To_Spritespace,
sprite_to_spritespace: s2b::Sprite_To_Spritespace, #
sprites: List( Rg_Sprite_Type ), # The list of widgets to be drawn on the spritespace. These can be placed arbitrarily.
site: Ref(g2d::Box) # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg }
=>
{
pp.lit "RG_SPRITESPACE";
# do_spritespace spritespace;
pp.newline();
};
RG_NULL_WIDGET
=>
{
pp.lit "RG_NULL_WIDGET";
pp.newline();
};
esac;
end
);
fun make_base_subwindow_data # Make the base SUBWINDOW_DATA instance for a GUI. (There will be an additional SUBWINDOW_DATA for each popup's Guipane.)
#
(pixmap: g2p::Gadget_To_Rw_Pixmap)
#
: Subwindow_Data
=
SUBWINDOW_DATA
{ id => issue_unique_id (),
stacking_order => 1,
guipane => REF NULL,
pixmap => REF pixmap, # Main backing pixmap for this running gui.
popups => REF ([]: List( Subwindow_Data)),
parent => NULL: Null_Or( Subwindow_Data ),
upperleft => REF { row => 0, col => 0 }
};
fun pprint_gadget_imp_info (gadget_imp_info: Gadget_Imp_Info)
=
pp::with_standard_prettyprinter
#
(err::default_plaint_sink ()) []
#
(\\ pp: pp::Prettyprinter
=
do_gadget_imp_info gadget_imp_info
where
fun do_gadget_imp_info
(
{
site: Site, # Where to draw this gadget, in hostwindow coordinates.
subwindow_or_view: Ref(Subwindow_Or_View),
#
guiboss_to_gadget: Guiboss_To_Gadget, # We use this to make requests of visible gadgets.
gadget_mode: Ref( Gadget_Mode ),
#
needs_redraw_request: Ref( Bool ), #
sent__initialize_gadget: Ref( Bool ),
#
point_in_gadget: Ref( Null_Or( g2d::Point -> Bool )), # Optional fn to decide if a mouseclick actually hit the gadget itself, or just somewhere near it in the screenspace assigned to it.
#
pixmaps: Ref( im::Map( g2p::Gadget_To_Rw_Pixmap )), # This tracks all X-server pixmaps created by this particular gadget. We need this so that we can reliably recycle them all when killing the gadget -- otherwise we're leaking memory in the X server.
#
at_frame_n: Ref ( Null_Or # Call gadget.wakeup once, during frame N, and pass wakeup_fn in call. NULL means this wakeup is off.
{ at_frame: Int,
wakeup_fn: Wakeup_Arg -> Void
}
),
every_n_frames: Ref ( Null_Or # Call gadget.wakeup every N frames, and pass wakeup_fn in call. NULL means this wakeup is off.
{ n: Int,
next: Ref(Int),
wakeup_fn: Wakeup_Arg -> Void
}
)
}: Gadget_Imp_Info
)
=
{ pp.box {.
pp.lit "Gadget_Imp_Info {";
pp.ind 2;
pp.txt " ";
pp.lit (sprintf "site => %s" (g2j::box_to_string *site));
pp.endlit ",";
pp.lit (sprintf "subwindow_or_view => %s" (subwindow_or_view_id *subwindow_or_view));
pp.endlit ",";
pp.lit (sprintf "id => %d" (id_to_int guiboss_to_gadget.id));
pp.ind 0;
pp.txt " ";
pp.lit "}";
};
pp.newline();
};
end
);
};
end;
##########################################################################
# Note[1]
#
# We need a NULL_WIDGET but not a NULL_SPRITE or NULL_OBJECT
# because Guiplans are required arguments to guiboss-imp and
# Gp_Widget_Type is a required component of a Guiplan, but
# sprite and object spaces are always optional.
##########################################################################
# Note[2]
#
# "Simple things should be simple.
# Complex things should be possible."
# -- Alan Kay
#
# The purpose of the Rg_Widget_Type facilities generally and
# of RG_ROW RG_COL RG_GRID specifically is to make simple GUI
# layout problems simple.
#
# In general, complex widget layout issues should be handled by
# writing custom code which lays out widgets (etc) on a object,
# not by cluttering Rg_Widget_Type with special cases.
#
# Trying to make complex things simple will always fail;
# the result will be instead to make simple things complex.