## guiboss-types.pkg
#
# Private and public types for
src/lib/x-kit/widget/gui/guiboss-imp.pkg# Support code may be found in
src/lib/x-kit/widget/gui/guiboss-types-junk.pkg#
# This file contains a great recursive black hole: # Originally this was a flock of separate files, but the natural recursive
# No type or function which enters it can ever escape. # relationships proved just too difficult to avoid, so they all moved into
# # this file where they can recursively refer to each other to their heart's
# We use three representations for a GUI with transition diagram # content. Sometimes it is best to just accept the inevitable...
#
# Guiplan # Public definition of GUI constructed by client and then passed to guiboss_imp via Client_To_Guiboss.start_gui or Gadget_To_Guiboss.make_popup.
#
|
#
# v #
# Guipane # Primary representation of a running gui. This is private to guiboss_imp and its private support packages.
#
| ^
#
# v
|
#
# Guipith # Public summary of a running gui. Its purpose is to allow client code to morph Guipane(s) by generating a Guipith (Gadget_To_Guiboss.get_guipiths), editing it, and submitting it (Gadget_To_Guiboss.install_updated_guipiths).
#
# The application programmers passes guiboss_imp a Guiplan
# to define the GUI, which is then converted to a running
# Guipane which is then abstracted on request into a Guipith
# via Gadget_To_Guiboss.get_guipiths for application massaging and
# via Gadget_To_Guiboss.install_updated_guipiths conversion back
# into running-GUI form: This is the main application tool for
# restructing a running GUI.
#
# In addition to defining the three GUI representations, this
# file defines most (but not all) of the major ports between
# guiboss_imp and other imps: # "gadget" refers to any of "widget", "sprite" or "object". (Most frequently, "widget".)
#
# Guiboss_To_Gadget # The general guiboss_imp -> gadget interface, used for forwarding user mouseclicks etc. Most frequently used guiboss_imp -> widget_imp, but also to sprite_imp and object_imp.
# Gadget_To_Guiboss # The general gadget -> guiboss_imp interface, used for forwarding draw operations etc.
# #
# Guiboss_To_Widgetspace # The guiboss_imp -> widgetspace_imp, used to manage layout of widgets on windows. Not yet of much importance in practice.
# Guiboss_To_Objectspace # The guiboss_imp -> objectspace_imp, used to manage layout of objects on windows. Not yet of much importance in practice.
# Guiboss_To_Spritespace # The guiboss_imp -> spritespace_imp, used to manage layout of sprites on windows. Not yet of much importance in practice.
#
# Support code including iterators over these datastructures may be found in:
#
#
src/lib/x-kit/widget/gui/guiboss-types-junk.pkg#
# See also:
#
#
src/lib/x-kit/widget/edit/millboss-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 sm = string_map; # string_map is from
src/lib/src/string-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 package a2c = app_to_compileimp; # app_to_compileimp is from
src/lib/x-kit/widget/edit/app-to-compileimp.pkg nb = log::note_on_stderr; # log is from
src/lib/std/src/log.pkgherein
package guiboss_types
{
# Some abbreviations because line length was getting out of hand below:
#
Once(X) = Oneshot_Maildrop(X);
Site = Ref( g2d::Box ); # Pixel-rectangle assigned to the widget, in backing-pixmap coordinates.
#########################################################################################
### preliminary types
Scroller # Client controller for scrolling a viewable around in a scrollport.
=
{ get_scrollport_upperleft: Void -> g2d::Point,
set_scrollport_upperleft: g2d::Point -> Void # Shouldn't this be 'pass_scrollport_upperleft'?
};
Scroller_Callback # Used in Gp_Widget_Type.SCROLLPORT in
src/lib/x-kit/widget/gui/guiboss-types.pkg =
Null_Or( Scroller ) -> Void;
Tab_Picker # Client controller for which tab is visible in given tabport.
=
{ get_active_tab: Void -> Int,
set_active_tab: Int -> Void
};
Tab_Picker_Callback # Used in Gp_Widget_Type.TABBED_VIEWS in
src/lib/x-kit/widget/gui/guiboss-types.pkg =
Null_Or( Tab_Picker ) -> Void;
#########################################################################################
### Preliminary running-gui types
# Storing instances of
# guiboss_to_spritespace,
# guiboss_to_objectspace,
# or guiboss_to_widgetspace
# directly in Guipane leads to package circularity,
# so instead we store their integer id here, and
# in guiboss-imp.pkg look them up as needed in
# (respectively):
# spritespaces
# objectspaces
# widgetspaces
#
Spritespace_Id = Id;
Objectspace_Id = Id;
Widgetspace_Id = Id;
#########################################################################################
### gadget-to-guiboss types
Gadget_Mode # We use this mostly to control how a widget draws itself.
= # To avoid a package cycle this def is duplicated in
src/lib/x-kit/widget/theme/widget/widget-theme.pkg { # We probably should find/make another home for this def. XXX SUCKO FIXME
is_active: Bool, # An inactive gadget is passed no user input. Inactive widgets are typically drawn "grayed-out".
has_mouse_focus: Bool, # A widget which has the mouse cursor on it may want to draw itself brigher or such.
has_keyboard_focus: Bool # A widget which has the keyboard focus will often draw a black outline around its text-entry rectangle.
};
Wakeup_Arg
=
{ frame_number: Int # 1,2,3,... Purely for convenience of widget, guiboss-imp makes no use of this.
};
Wake_Me_Option
#
= AT_FRAME_N Null_Or( (Int, Wakeup_Arg -> Void) ) # Call gadget.wakeup once, during frame N, and pass given arg in call. NULL arg turns this wakeup off.
| EVERY_N_FRAMES Null_Or( (Int, Wakeup_Arg -> Void) )
# Call gadget.wakeup every N frames, and pass given arg in call. NULL arg turns this wakeup off.
#
# I'm too lazy to implement these two right
# now but I expect we'll want them eventually: -- CrT 2015-01-05
#
#
| IN_S_SECONDS Null_Or( (Float, Wakeup_Arg -> Void) )
# Call gadget.wakeup once after s seconds, and pass given arg in call. NULL arg turns this wakeup off.
#
| EVERY_S_SECONDS Null_Or( (Float, Wakeup_Arg -> Void) )
# Call gadget.wakeup every s seconds, and pass given arg in call. NULL arg turns this wakeup off.
;
Widget_Layout_Hint
=
{ pixels_high_min: Int, # Minimum vertical pixels to allocate for this widget. Used in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg pixels_wide_min: Int, # Minimum horizontal pixels to allocate for this widget. Used in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg #
pixels_high_cut: Float, # Share of remaining vertical pixels to allocate to this widget. Used in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg pixels_wide_cut: Float # Share of remaining horizontal pixels to allocate to this widget. Used in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg };
default_widget_layout_hint
=
{ pixels_high_min => 0,
pixels_wide_min => 0,
#
pixels_high_cut => 1.0,
pixels_wide_cut => 1.0
};
Frame_Indent_Hint # Used to format RG_FRAME nodes in
src/lib/x-kit/widget/gui/guiboss-widget-layout.pkg = # I expect to use this facility very rarely, so I'm favoring verbose-and-clear here in choice of fieldnames:
{ pixels_for_top_of_frame: Int, # Vertical pixels to allocate for top side of frame.
pixels_for_bottom_of_frame: Int, # Vertical pixels to allocate for bottom side of frame.
#
pixels_for_left_of_frame: Int, # Horizontal pixels to allocate for left side of frame.
pixels_for_right_of_frame: Int # Horizontal pixels to allocate for right side of frame.
};
default_frame_indent_hint
=
{ pixels_for_top_of_frame => 9,
pixels_for_bottom_of_frame => 9,
#
pixels_for_left_of_frame => 9,
pixels_for_right_of_frame => 9
};
#########################################################################################
### Guiplan datatypes
###
### A Guiplan is a public definition of GUI constructed by client and then passed
### to guiboss_imp via Client_To_Guiboss.start_gui or Gadget_To_Guiboss.make_popup.
Gp_Sprite # Nomenclature: "Gp_" and "GP_" are mnemonic for "Gui Plan".
#
= SPRITE Sprite_Start_Fn # Intended to support 2-D animated pinball sprites (Pac-man type stuff) initially, 3-D OpenGL animated avatars eventually. Not yet supported.
also
Gp_Object # Intended to support overlapping non-rectangular non-tiled stuff like multiple x-y curves graphed in 2D with mouse-interaction support. Not yet supported.
#
= WIDGETSPACE Gp_Widgetspace
#
| OBJECT Object_Start_Fn
also
Gp_Widget_Type # "_Type" because for consistency we need "Gp_Widget" for WIDGET.
#
= ROW Gp_Row # Horizontal row of widgets. A ROW of less than two widgets may be optimized away.
| COL Gp_Col
# Vertical col of widgets. A COL of less than two widgets may be optimized away.
| GRID Gp_Grid
# Grid of widgets; outer list goes by rows, inner lists go by columns. A GRID of less than two widgets may be optimized away.
| MARK Gp_Mark
# Single widget whose 'id' field provides a way to identify a point in a guiplan. These are never optimized away.
#
| ROW' Gp_Row'
# Same as ROW except 'id' field is explicitly provided instead of implicitly generated.
| COL' Gp_Col'
# Same as COL except 'id' field is explicitly provided instead of implicitly generated.
| GRID' Gp_Grid'
# Same as GRID except 'id' field is explicitly provided instead of implicitly generated.
| MARK' Gp_Mark'
# Same as MARK except 'id' field is explicitly provided instead of implicitly generated.
#
| SCROLLPORT Gp_Scrollport
# Support for scrollable viewports holding arbitrary widgets.
| TABPORT Gp_Tabport
# Support for tab-selectable ports holding arbitrary widgets on each tab.
| FRAME Gp_Frame
# For drawing a customizable frame around a widget subtree.
| WIDGET Gp_Widget
# Actual leaf widgets like buttons and text-entry fields. These values are created by make_widget_start_fn in
src/lib/x-kit/widget/xkit/theme/widget/default/look/widget-imp.pkg
#
| OBJECTSPACE Gp_Objectspace
# Intended to support free-form (non-tiled) layout of bubble-and-arrow graphs, widgets etc. Also drawing and painting. Not yet supported.
| SPRITESPACE Gp_Spritespace
# Intended to support 2-D pinball animation initially and 3-D OpenGL animation eventually. Not yet supported.
#
| NULL_WIDGET
# Note[1]
also
Frame_Option
#
= FRAME_WIDGET Gp_Widget_Type
#########################################################################################
### running-gui datatypes
###
### A Guipane is the primary representation of a running gui.
### This is private to guiboss_imp and its private support packages.
# Nomenclature: "Rg_" and "RG_" are mnemonic for "Running Gui".
also
Rg_Sprite_Type # "_Type" because for consistency we need "Rg_Sprite" for RG_SPRITE.
# # This datatype has only one alternative, but will presumably eventually have multiple variants just like Rg_Object_Type and Rg_Widget_Type, so converting it to a simple type is probably a bad idea.
= RG_SPRITE Rg_Sprite
also
Rg_Object_Type # "_Type" because for consistency we need "Rg_Object" for RG_OBJECT.
#
= RG_WIDGETSPACE Rg_Widgetspace # A widget space embedded in a object, to allow all widgetspace widgets to be used also on a object.
| RG_OBJECT Rg_Object
also
Rg_Widget_Type # "_Type" because for consistency we need "Rg_Widget" for RG_WIDGET.
#
= RG_ROW Rg_Row # A horizontal row of widgets.
| RG_COL Rg_Col
# A vertical col of widgets.
| RG_GRID Rg_Grid
# A rectangular grid of widgets.
| RG_MARK Rg_Mark
# A single widget. Used to mark a spot in widget-tree for later reference, typically between Gadget_To_Guiboss get_guipiths() and install_updated_guipiths() calls.
#
| RG_CUSTOM_LAYOUT here might be a good idea by and by. Semantics TBD
| RG_SCROLLPORT Rg_Scrollport
# 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.
| RG_TABPORT Rg_Tabport
# Here we provide support for selection between alternate views in tabport. Actually providing tabs happens at a higher level; here we handle pixmap state maintenance and redraw support.
#
| RG_FRAME Rg_Frame
| RG_WIDGET 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 #
| RG_OBJECTSPACE Rg_Objectspace
# This is intended to allow editing of bubble-and-arrow graphs, arbitrary placement of widgets etc. Not yet supported.
| RG_SPRITESPACE Rg_Spritespace
# This is intended to allow 2-D pinball animation (and eventually 3-D OpenGL animation). Not yet supported.
#
| RG_NULL_WIDGET
# We need this because Guipane requires an Rg_Widget_Type value, and sometimes we may not have anything else.
#########################################################################################
### guiboss-to-widgetspace datatypes
#
# Communication from
src/lib/x-kit/widget/gui/guiboss-imp.pkg # to
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg also
Widgetspace_Option
#
= PS_MICROTHREAD_NAME String #
| PS_ID Id
# Unique ID for imp, issued by issue_unique_id::issue_unique_id().
| PS_CALLBACK Guiboss_To_Widgetspace -> Void
#########################################################################################
### guiboss-to-objectpace datatypes
#
# Communication from
src/lib/x-kit/widget/gui/guiboss-imp.pkg # to
src/lib/x-kit/widget/space/object/objectspace-imp.pkg also
Objectspace_Option
#
= CS_MICROTHREAD_NAME String #
| CS_ID Id
# Unique ID for imp, issued by issue_unique_id::issue_unique_id().
| CS_OBJECTSPACE_CALLBACK Guiboss_To_Objectspace -> Void
#########################################################################################
### guiboss-to-spritespace datatypes
#
# Communication from
src/lib/x-kit/widget/gui/guiboss-imp.pkg # to
src/lib/x-kit/widget/space/sprite/spritespace-imp.pkg also
Spritespace_Option
#
= OS_MICROTHREAD_NAME String #
| OS_ID Id
# Unique ID for imp, issued by issue_unique_id::issue_unique_id().
| OS_SPRITESPACE_CALLBACK Guiboss_To_Spritespace -> Void
#########################################################################################
### gadget-to-guiboss datatypes
#########################################################################################
### guiboss-to-gadget datatypes
also
Gadget_Transit # This protocol is intended to support (e.g.) highlighting a gadget while the mouse is over it.
# # The intended semantics here is that:
= CAME # o A widget should always see an CAME before anything else when the mouse cursor enters its space. CAME events are NOT sent during a drag. A MOVE is always sent immediately after an CAME, with the same mouse coordinate.
| MOVE
# o A widget can see any number of MOVE events between a CAME and LEFT; all will be in its space. MOVE events are NOT sent during a drag.
| LEFT
# o A widget should always see a LEFT after everything else when the mouse cursor exits its space. LEFT events are NOT sent during a drag.
# o Thus, a widget is not guaranteed to see an CAME every time the mouse cursor enters it (due to drag exception). But if it sees anything at all, an CAME will be first, and a LEFT will be last.
also
Drag_Phase # This protocol is intended to support dragging a slider or scrollbar thumb.
# # The intended semantics here is that:
= OPEN # o Every drag sequence begins with exactly one OPEN.
| DRAG
# o Every drag sequence has zero or more DRAG phases.
| DONE
# o Every drag sequence ends with exactly one DONE.
#
also
Key_Event # This protocol is intended to support keyboard text entry.
#
= KEY_PRESS
| KEY_RELEASE
also
Mousebutton_Event # This protocol is intended to support mouse button processing. Double-clicks are not supported here. I dislike them because they inherently add latency, and half of GUI framework design is about minimizing latency.
#
= MOUSEBUTTON_PRESS
| MOUSEBUTTON_RELEASE
#########################################################################################
### Sprite_Start_Fn datatype
also
Sprite_Start_Fn # Converting this to a simple type does not work due to mutual recursion between Sprite_Start_Fn and Sprite_Imports.
=
SPRITE_START_FN (Sprite_Imports -> Sprite_Exports)
#########################################################################################
### Object_Start_Fn datatype
also
Object_Start_Fn # Converting this to a simple type does not work due to mutual recursion between Object_Start_Fn and Object_Imports.
=
OBJECT_START_FN (Object_Imports -> Object_Exports)
#########################################################################################
### Widget_Start_Fn datatype
also
Widget_Start_Fn # Converting this to a simple type does not work due to mutual recursion between Widget_Start_Fn and Widget_Imports.
= # This type is the critical interface between the widget world and
src/lib/x-kit/widget/gui/guiboss-imp.pkg WIDGET_START_FN (Widget_Imports -> Widget_Exports) # In particular quiplan__to__guipane() in guiboss_imp calls the widget_start_fn built in
src/lib/x-kit/widget/xkit/theme/widget/default/look/widget-imp.pkg
#########################################################################################
### Subwindow_Or_View datatype # This is used mainly for the home of a gadget, since a gadget may live either directly on a subwindow or else in a scrollport visible ultimately on a subwindow.
#
also #
Subwindow_Or_View #
# #
= SUBWINDOW_INFO Subwindow_Info #
#
| SCROLLABLE_INFO Rg_Scrollport
#
| TABBABLE_INFO Tabbable_Info
#
also #
Subwindow_Data # This is used in Hostwindow_Info and Guipane because they are always located directly on a subwindow, not on a scrollport within a subwindow.
# # Unfortunately we can NOT just replace Subwindow_Data everywhere by Subwindow_Info because then Subwindow_Info contains fields of type Subwindow_Info, which is not allowed by the type system.
= SUBWINDOW_DATA Subwindow_Info #
#########################################################################################
### Guipith datatypes # Nomenclature: "Xi_" and "XI_" are mnemonic for "eXport/Import".
###
### A Guipith is a public summary of a running gui. Its purpose is to
### allow client code to morph Guipane(s) by generating Guipith
### summaries of running Guipanes via Gadget_To_Guiboss.get_guipiths,
### editing them (often via the guiboss_types_junk::guipith_map # guiboss_types_junk is from
src/lib/x-kit/widget/gui/guiboss-types-junk.pkg ### facility), and submitting them back to guiboss_imp via
### Gadget_To_Guiboss.install_updated_guipiths, which which converts
### them back into a full Guipanes using information from the
### pre-existing Guipanes and then installs ttem as the new running
### Guipanes, doing re-sites + re-draws as needed to appropriately
### update the visible screen image of the affected running GUIs.
###
### This facility is motivated by a desire to allow (for example)
### emacs-style editors to add new (sub)windows onto new files without
### having to completely shut down the existing GUI, together with a
### desire to keep the Guipane types private to guiboss_imp for
### implementation hiding / separation of concerns, and also to
### minimize the amount of validation needed in
### Gadget_To_Guiboss.install_updated_guipiths
### by minimizing the amount of superfluous information passed
### to install_updated_guipiths.
#
also
Xi_Sprite # This datatype has only one alternative, but will presumably eventually have multiple variants just like Rg_Object_Type and Rg_Widget_Type, so converting it to a simple type is probably a bad idea.
#
= XI_SPRITE {
sprite_id: Id
}
also
Xi_Object
#
= XI_WIDGETSPACE { widgetspace_id: Id, #
xi_widget: Xi_Widget_Type
}
| XI_OBJECT {
object_id: Id
}
also
Xi_Widget_Type # "_Type" because for consistency we need "Xi_Widget" for XI_WIDGET.
#
= XI_ROW Xi_Row
| XI_COL Xi_Col
| XI_GRID Xi_Grid
# A rectangular grid of widget widgets.
| XI_MARK Xi_Mark
# A single widget.
#
| XI_SCROLLPORT Xi_Scrollport
# 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.
| XI_TABPORT Xi_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.
#
| XI_FRAME Xi_Frame
| XI_WIDGET Xi_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 #
| XI_OBJECTSPACE Xi_Objectspace
| XI_SPRITESPACE Xi_Spritespace
#
| XI_NULL_WIDGET
# We need this because Guipane requires an Rg_Widget_Type value, and sometimes we may not have anything else.
| XI_GUIPLAN Guiplan
# To allow starting up new widgets as part of a running-gui update.
also #
Xi_Subwindow_Or_View #
# #
= XI_SUBWINDOW_INFO Xi_Subwindow_Info #
#
| XI_SCROLLABLE_INFO
#
also
Xi_Subwindow_Data
#
= XI_SUBWINDOW_DATA Xi_Subwindow_Info
withtype
Keystroke_Info
=
{ key_event: Key_Event, # KEY_PRESS or KEY_RELEASE.
keycode: evt::Keycode, # Keyboard key just pressed/released.
keysym: evt::Keysym, # Keysym of the key. This is not present in the X version of Key_Kevtinfo; added for widget-code convenience.
keystring: String, # Ascii for the key. This is not present in the X version of Key_Kevtinfo; added for widget-code convenience.
keychar: Char, # First char of 'string' ('\0' if string-length != 1).
modifier_keys_state: evt::Modifier_Keys_State, # State of the modifier keys (shift, ctrl...).
mousebuttons_state: evt::Mousebuttons_State # State of mouse buttons as a bool record.
}
also
Note_Mouse_Drag_Event_Arg
=
{ phase: Drag_Phase, # We guarantee that the gadget that sees the OPEN (downclick) for a drag also sees all the DRAGs and the DONE for that drag, and that no other gadget sees drag or transit events during that time period.
button: evt::Mousebutton, # Mouse button lack clicked down. Range is 1-13 or more. Typically 1=left, 2=middle, 3=right, 4=mousewheel-forward, 5=mousewheel-back.
modifier_keys_state: evt::Modifier_Keys_State, # State of the modifier keys (shift, ctrl...).
mousebuttons_state: evt::Mousebuttons_State, # State of mouse buttons as a bool record.
event_point: g2d::Point, # 'event_point' is the current point the window's coordinate system.
start_point: g2d::Point, # 'start_point' is the downclick point the window's coordinate system.
last_point: g2d::Point, # 'last_point' is the event_point from the preceding ntoe_mouse_drag_event call.
site: g2d::Box, # Gadget's assigned area in window coordinates.
theme: wt::Widget_Theme #
} # DONE is sent when last mousebutton is released, no matter where that happnes.
also
Note_Mouse_Transit_Arg
=
{ transit: Gadget_Transit,
modifier_keys_state: evt::Modifier_Keys_State, # State of the modifier keys (shift, ctrl...).
event_point: g2d::Point, # 'event_point' is the click point the window's coordinate system.
site: g2d::Box, # Gadget's assigned area in window coordinates.
theme: wt::Widget_Theme #
} # CAME/MOVE/LEFT are never sent during drag operations.
also
Note_Key_Event_Arg
=
{ keystroke: Keystroke_Info,
site: g2d::Box, # Gadget's assigned area in window coordinates.
theme: wt::Widget_Theme
}
also
Note_Mousebutton_Event_Arg
=
{ mousebutton_event: Mousebutton_Event, # MOUSEBUTTON_PRESS or MOUSEBUTTON_RELEASE. These go to the gadget under the mouse pointer, hence a gadget may not see both if the pointer moves between them. Use note_mouse_drag_event if this is a problem.
mouse_button: evt::Mousebutton, # Mouse button just clicked down. Range is 1-13 or more. Typically 1=left, 2=middle, 3=right, 4=mousewheel-forward, 5=mousewheel-back.
modifier_keys_state: evt::Modifier_Keys_State, # State of the modifier keys (shift, ctrl...).
mousebuttons_state: evt::Mousebuttons_State, # State of mouse buttons as a bool record, BEFORE THE EVENT -- so a MOUSEBUTTON_RLEASE will always show at least one button down.
event_point: g2d::Point, # 'point' is the click point the window's coordinate system.
site: g2d::Box, # Gadget's assigned area in window coordinates.
theme: wt::Widget_Theme #
} # Normally MOUSEBUTTON_PRESS or MOUSEBUTTON_RELEASE are sent if they occur within the gadget's assigned site.
also
Xi_Row # Used in XI_ROW
=
{ # A horizontal row of widget widgets.
id: Id,
widgets: List( Xi_Widget_Type ), # The list of widgets to be laid out and displayed in this row.
first_cut: Null_Or( Float ) # Normally NULL; if non-NULL (and at least two widgets in row/col), gives fraction of row/col space to allocate to first widget, overriding the regular bottom-up sizing mechanism.
}
also
Xi_Col = Xi_Row
also
Xi_Grid # Used in XI_GRID
=
{ id: Id, # A grid of widgets.
widgets: List( List( Xi_Widget_Type ) )
}
also
Xi_Mark # Used inX I_GRID
=
{ id: Id, # A widget.
doc: String,
widget: Xi_Widget_Type
}
also
Xi_Scrollport #
=
{ id: Id, #
xi_widget: Xi_Widget_Type # Tree of widgets partially visible in scrollport.
}
also
Xi_Tabport #
=
{ id: Id, #
widgets: List( Xi_Widget_Type )
}
also
Xi_Frame
=
{ 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.
}
also
Xi_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 = # Used in XI_WIDGET
{ widget_id: Id,
widget_layout_hint: Widget_Layout_Hint,
doc: String # Debugging support: Allow XI_WIDGETs to be distinguishable for debug-display purposes.
}
also
Xi_Guipane
=
{ 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.
}
also
Xi_Subwindow_Info # Used in SUBWINDOW_INFO.
=
{ id: Id, # From (*Subwindow_Info.pixmap).id
guipane: Null_Or( Xi_Guipane ),
popups: List(Xi_Subwindow_Data) #
}
also
Xi_Hostwindow_Info
=
{ id: Id, # From hostwindow_info.guiboss_to_hostwindow.id
subwindow_info: Null_Or( Xi_Subwindow_Data )
}
also
Xi_Objectspace
=
{ guiboss_to_objectspace_id: Id,
xi_objects: List(Xi_Object)
}
also
Xi_Spritespace
=
{ guiboss_to_spritespace_id: Id,
xi_sprites: List(Xi_Sprite)
}
#########################################################################################
### More Subwindow_Or_View types
also Spritespace_Arg = List(Spritespace_Option) # Currently no required component.
also Objectspace_Arg = List(Objectspace_Option) # Currently no required component.
also Widgetspace_Arg = List(Widgetspace_Option) # Currently no required component.
also
Space_To_Gui # This may eventually need to move to
src/lib/x-kit/widget/gui/guiboss-types.pkg = # so it can be mutually recursive with everything else there, but for the moment it is working as a standalone definition.
{ id: Id, # Unique id to facilitate storing space_to_gui ports in indexed datastructures like red-black trees.
#
note_widget_site: { id: Id,
site: g2d::Box,
subwindow_or_view: Subwindow_Or_View
}
-> Void
}
also
Client_To_Guiwindow
=
{ id: Id, # Unique id to facilitate storing guiboss instances in indexed datastructures like red-black trees.
kill_gui: Void -> Void # Stop gui and recycle its state and Xserver-side resources. This invokes exactly the same code as Gadget_To_Guiboss.kill_popup.
}
also Guiplan = Gp_Widget_Type # Synonym for improved readability.
# also Guipith = Xi_Widget_Type # Synonym for improved readability.
also
Make_Popup_Fn # Create popup pane on given window in given site. Given site is adjusted to lie entirely within parent (if necessary) and returned.
=
(
g2d::Box, # Requested site for popup, in basewindow coordinates.
Guiplan #
)
->
(
g2d::Box, # Actual site for popup, in basewindow coordinates. It differs from requested site only if requested site does not lie entirely within basewindow site.
Client_To_Guiwindow
)
also
Guiboss_To_Objectspace #
=
{ id: Id, # Unique id to facilitate storing guiboss_to_objectspace instances in indexed datastructures like red-black trees.
#
pass_something: Replyqueue -> (Int -> Void) -> Void,
do_something: Int -> Void,
die: Void -> Void # Equivalent to firing end_gun', but affects only one objectspace imp.
}
also
Guiboss_To_Spritespace #
=
{ id: Id, # Unique id to facilitate storing guiboss_to_spritespace instances in indexed datastructures like red-black trees.
#
pass_something: Replyqueue -> (Int -> Void) -> Void,
do_something: Int -> Void,
die: Void -> Void # Equivalent to firing end_gun', but affects only one spritespace imp.
}
also
Guiboss_To_Widgetspace #
=
{ id: Id, # Unique id to facilitate storing guiboss_to_widgetspace instances in indexed datastructures like red-black trees.
#
pass_something: Replyqueue -> (Int -> Void) -> Void,
do_something: Int -> Void,
die: Void -> Void # Equivalent to firing end_gun', but affects only one widgetspace imp.
}
also
Gadget_To_Guiboss #
=
{ id: Id, # Unique id to facilitate storing Gadget_To_Guiboss ports in indexed datastructures like red-black trees.
#
needs_redraw_gadget_request: Id -> Void, # Inform guiboss_imp that the gadget's appearance needs refreshing. Without this, it may not get a redraw_gadget_request call.
# This should be called any time the gadget's state changes in a way that would visibly affect its appearance. See Note[3] in
src/lib/x-kit/widget/gui/guiboss-imp.pkg #
redraw_gadget # Update gadget appearance in response to a guiboss_to_gadget.redraw_gadget_request {...} call.
: # This can also be called spontaneously in the absence of a redraw_gadget_request call,
{ id: Id, # but if the gadget state gets updated frequently (say, 10,000 times/sec) this may overwhelm the display subsystem.
site: g2d::Box, # This should be the 'site' value handed to Guiboss_To_Gadget.redraw_gadget_request: guiboss_imp uses this value to detect (and discard) stale redraw_gadget messages.
displaylist: gd::Gui_Displaylist,
point_in_gadget: 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.
}
->
Void,
request_keyboard_focus: Id -> Void, # This should result in us getting Guiboss_To_Gadget.note_keyboard_focus(TRUE) from
src/lib/x-kit/widget/gui/guiboss-imp.pkg release_keyboard_focus: Id -> Void, # This should result in us getting Guiboss_To_Gadget.note_keyboard_focus(FALSE) from
src/lib/x-kit/widget/gui/guiboss-imp.pkg note_changed_gadget_activity: { id: Id, is_active: Bool } -> Void, # is_active is FALSE if gadget should be insensitive to input and perhaps drawn grayed-out. Controlled by application logic.
wake_me: { id: Id, options: List(Wake_Me_Option) } -> Void, # Used to schedule guiboss_to_gadget.wakeup calls.
make_popup: Make_Popup_Fn, # Create popup pane at given site. Given site is adjusted to lie entirely within parent (if necessary) and returned.
kill_popup: Void -> Void, # Stop guipane containing this gadget (and all its descendent popups) and recycle its state and Xserver-side resources. This invokes exactly the same code as Client_To_Guiwindow.kill_gui.
note_global: Crypt -> Void, # These three implement a general registry which gadget and app code can use as a blackboard for communication and coordination.
find_global: String -> Null_Or(Crypt), # 'String' should be the Crypt.type field for the desired Crypt.
drop_global: String -> Void, # 'String' should be the Crypt.type field for the desired Crypt. This is a no-op if no such Crypt is registered.
set_guipane_upperleft: (Id, g2d::Point) -> Void, # Ask guiboss-imp to change value of Subwindow_Info.upperleft for guipane containing gadget.
pass_guipane_upperleft: Id # Ask guiboss-imp to pass value of Subwindow_Info.upperleft for guipane containing gadget to given handler.
-> Replyqueue #
-> (g2d::Point -> Void) #
-> Void, #
set_guipane_size: (Id, g2d::Size) -> Void, # Ask guiboss-imp to change value of Subwindow_Info.size for guipane containing gadget.
pass_guipane_size: Id # Ask guiboss-imp to pass value of Subwindow_Info.size for guipane containing gadget to given handler.
-> Replyqueue #
-> (g2d::Size -> Void) #
-> Void, #
shut_down_guiboss: Void -> Void, # Set Client_To_Guiboss.guiboss_done' and then terminate guiboss_imp microthread. Nothing else.
app_to_compileimp: a2c::App_To_Compileimp,
get_guipiths: Void -> (Int, idm::Map( Xi_Hostwindow_Info )), # Export abstract version of guiboss_imp's current set of running guis (Guipane instances). 'Int' is gui version, needed to trap bad concurrent updates.
install_updated_guipiths: (Int, idm::Map( Xi_Hostwindow_Info )) -> Bool # Update guiboss_imp's running gui per supplied Guipith instances, which should be a suitably edited version of return value from get_guipiths. See Note[1] in
src/lib/x-kit/widget/gui/translate-guipane-to-guipith.pkg #
# The Int values are Guiboss_State.gui_update_count: If the value supplied with install_updated_guipiths does not match, guiboss returns FALSE and does nothing, and client must
# start the get_guipiths -> mutate -> install_updated_guipiths. This is insurance against two concurrent clients attempting overlapping updates to the GUI topology.
#
# The idiom to use here is:
#
# do_while_not {.
# (get_guipiths ()) -> (gui_version, guipiths); # Get current GUI layout.
# guipiths = gtj::guipith_map (guipiths, options); # Modify it to produce new GUI layout.
# install_updated_guipiths (gui_version, guipiths); # Install new GUI layout.
# }; # If someone else modified the current GUI layout out from under us, retry.
#
# Worked examples of doing this may be found in (e.g.)
#
src/lib/x-kit/widget/edit/fundamental-mode.pkg #
# Limitations of install_updated_guipiths:
# o Revised guipane may move widgets around but no individual widget may be present more than once. (Ditto for all other guipith entities.) This restruction is fundamental to the design.
# o Popup hierarchy may not be modified. Use make_popup()/kill_popup() for that. This restriction is pure implementation laziness: we'll presumbly lift it eventually.
# o Tabports and Scrollports may not be modified beyond substituting widgets. This restriction is pure implementation laziness: we'll presumbly lift it eventually.
# As a convenience, XI_ROW, XI_COL and XI_GRID instances may be freely created and inserted. (In general guipith values may be only re-arranged or dropped, outside of XI_GUIPLAN.)
# XXX QUERO FIXME I think maybe we should have call(s) here to subscribe to events like garbage collection, disk-full, low-on-ram etc.
# Having method(s) here to register a fn to be called for a given event is a simple, effective way to implement that functionality.
# One could argue that such events have little to do with GUIs and hence should not be the purvue of guiboss-imp, but guiboss-imp
# is the established architecture apps will be using to process the dominant event streams (mouseclicks + keypresses), so piggybacking
# on that takes advantage of established app architecture as well as established internal guiboss_imp architecture. We need at least
# DISK_FULL and RAM_FULL in order to write robust apps that deal gracefully with resource exhaustion. CPU_FULL would be a logical
# correlate, so apps can cut back on background processing when CPU cycles are in short supply. It might be worth just running through
# the list of standard Unix signals and thinking about which of them might also be best coupled to the Mythryl GUI-app world by turning
# them into events delivered through this mechanism. SIGPWR and SIGHUP might make sense...?
# Gadget_To_Guiboss should maybe export the log.pkg fns, as futureproofing
# against distributed-computation situations where the GUI runs remote from
# the application and we want logging to be centralized in the application.
}
also
Widget_To_Guiboss
=
{ id: Id, # Unique id to facilitate storing guiboss instances in indexed datastructures like red-black trees.
#
g: Gadget_To_Guiboss,
note_widget_layout_hint: { id: Id,
widget_layout_hint: Widget_Layout_Hint
}
-> Void #
}
also
Guiboss_To_Gadget #
=
{ id: Id, # Unique id to facilitate storing Guiboss_To_Gadget ports in indexed datastructures like red-black trees.
doc: String,
#
# These two may be a mistake,
# I'm not sure they are used
# or even potentially useful:
wants_keystrokes: Bool, # TRUE iff guiboss_imp should send keyboard events to this gadget. This might need to become a Ref(Bool)...?
wants_mouseclicks: Bool, # TRUE iff guiboss_imp should send mouse events to this gadget. This is about correctness not efficiency: We might have two nested candidate gadgets where this flag decides which one gets the event.
#
initialize_gadget: { # Before the first redraw_gadget_request call every widget-imp/sprite-imp/object-imp gets this call from
src/lib/x-kit/widget/gui/guiboss-imp.pkg # # If its appearance has changed it should call needs_redraw_gadget_request().
site: g2d::Box, # Window rectangle in which to draw.
theme: wt::Widget_Theme,
#
get_font: List(String) -> evt::Font, # Accepts a list of font names which are tried in order; returns font 'ascent' and 'descent' in pixels -- sum them to get font height.
pass_font: List(String) -> Replyqueue #
-> ( evt::Font -> Void ) #
-> Void, # Nonblocking version of previous, for use in imps.
make_rw_pixmap: g2d::Size -> g2p::Gadget_To_Rw_Pixmap
}
->
Void,
redraw_gadget_request: { # This is a request to the gadget to redraw itself, made by
src/lib/x-kit/widget/gui/guiboss-imp.pkg # # Gadget should always respond by calling gadget_to_guiboss.redraw_gadget(), even if appearance is unchanged. (guiboss might be refreshing screen after an EXPOSE event, say.)
frame_number: Int, # 1,2,3,... Purely for convenience of gadget -- guiboss-imp makes no use of this.
site: g2d::Box, # Window rectangle in which to draw.
duration_in_seconds: Float, # If state has changed look-imp should call redraw_gadget() before this time is up. Also useful for motionblur.
gadget_mode: Gadget_Mode,
theme: wt::Widget_Theme,
popup_nesting_depth: Int # 0 for gadgets on basewindow, 1 for gadgets on popup on basewindow, 2 for gadgets on popup on popup, etc.
}
->
Void,
wakeup: { # These calls are set up by calling gadget_to_guiboss.wake_me[].
wakeup_arg: Wakeup_Arg, #
wakeup_fn: Wakeup_Arg -> Void # Gadget thunk registered via gadget_to_guiboss.wake_me[].
}
->
Void,
note_keyboard_focus: (Bool, wt::Widget_Theme) -> Void, # TRUE means we now have keyboard focus, FALSE means we no longer have it. Allows gadget to visually display focus locus, typically via a black outline and/or dis/abling cursor. See also Gadget_To_Guiboss.request_keyboard_focus
note_mouse_drag_event: Note_Mouse_Drag_Event_Arg -> Void, # Intended to support dragging sliders and scrollbar thumbs etc. Not intended for drag-and-drop.
note_mouse_transit: Note_Mouse_Transit_Arg -> Void, # Mouse entering or leaving window site assigned to gadget. Intended to support tooltips, active-widget highlighting etc. Note that buttons are always all up in a mouse transit -- otherwise it is a mouse-drag event.
note_key_event: Note_Key_Event_Arg -> Void, # Note keyboard KEY_PRESS or KEY_RELEASE at 'point'. Intended for textfield text entry etc.
note_mousebutton_event: Note_Mousebutton_Event_Arg -> Void, # Note mousebutton click at 'point'. Intended for pushbuttons etc.
die: Void -> Void # Equivalent to firing end_gun', but affects only one gadget.
}
also
Guiboss_To_Widget
=
{ id: Id, # Unique id to facilitate storing guiboss_to_widget instances in indexed datastructures like red-black trees.
doc: String,
g: Guiboss_To_Gadget, # We're extending this generic widget/sprite/object interface with widget-specific functionality.
#
get_widget_layout_hint: Void -> Widget_Layout_Hint, # We require this call to be O(1) and nonblocking.
get_frame_indent_hint: Void -> Frame_Indent_Hint, # We require this call to be O(1) and nonblocking.
#
pass_something: Replyqueue -> (Int -> Void) -> Void,
do_something: Int -> Void
}
also
Spritespace_Imp_Info
=
# Looks like we don't need this record at all any more...?
# All this info is now in Rg_Spritespace, excepting
# the oneshot which is about to die. So Spritespace_Imps
# can be just an index of Rg_Spritespace records.
{ sprite_to_spritespace: s2b::Sprite_To_Spritespace, #
guiboss_to_spritespace: Guiboss_To_Spritespace,
shutdown_oneshot: Oneshot_Maildrop( Void )
}
also
Objectspace_Imp_Info
=
# Looks like we don't need this record at all any more...?
# All this info is now in Rg_Objectspace, excepting
# the oneshot which is about to die. So Objectspace_Imps
# can be just an index of Rg_Objectspace records.
{ object_to_objectspace: o2c::Object_To_Objectspace, #
guiboss_to_objectspace: Guiboss_To_Objectspace,
shutdown_oneshot: Oneshot_Maildrop( Void )
}
also
Widgetspace_Imp_Info
=
# Looks like we don't need this record at all any more...?
# All this info is now in Rg_Widgetspace, excepting
# the oneshot which is about to die. So Widgetspace_Imps
# can be just an index of Rg_Widgetspace records.
{
guiboss_to_widgetspace: Guiboss_To_Widgetspace,
shutdown_oneshot: Oneshot_Maildrop( Void )
}
also
Gadget_Imp_Info # The per-gadget information we track. (This is private to guiboss-imp.)
= # Here 'gadget' refers indifferently to widget-imps, sprite-imps and object-imps.
{ site: Ref( g2d::Box ), # 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 gadgets.
gadget_mode: Ref( Gadget_Mode ), # Tracks whether this gadget currently has the mouse focus (etc).
#
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
}
)
}
also Spritespace_Imps = Ref( idm::Map( Spritespace_Imp_Info ) ) #
also Objectspace_Imps = Ref( idm::Map( Objectspace_Imp_Info ) ) #
also Widgetspace_Imps = Ref( idm::Map( Widgetspace_Imp_Info ) ) #
also Gadget_Imps = Ref( idm::Map( Gadget_Imp_Info ) ) # Index is guiboss_to_gadget.id.
also Widget_Layout_Hints = Ref( idm::Map( Widget_Layout_Hint ) ) # Index is guiboss_to_gadget.id.
also
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. This represents the X-server window holding our tree of running guis.
subwindow_info: Subwindow_Data, # The subwindow on which this running gui is drawn. This will be a sub-rectangle of the hostwindow, except for the root running gui of the popups tree. It hosts the actual backing pixmap on which rg_widget will be drawn first.
needs_layout_and_redraw: Ref( Bool )
}
also
Subwindow_Info # Used in 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.
}
also
Tabbable_Info #
= #
{
rg_widget: Rg_Widget_Type, # Widget-tree visible in this tabport, which gets rendered onto 'pixmap' here.
# #
pixmap: g2p::Gadget_To_Rw_Pixmap, # Tabbable_Info values appear only in RG_SCROLLPORT.scrollable_info,
# RG_TABPORT.tabs
#
parent_subwindow_or_view: Subwindow_Or_View, # This can be a SCROLLABLE_INFO if we have a tabportport 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 ) #
# This value is implied by *Rg_Tabport.visible_tab but as a convenience we maintain this redundant explicit version.
# We need this so that update_offscreen_parent_pixmaps_and_then_hostwindow() in
src/lib/x-kit/widget/gui/guiboss-imp.pkg # can know when to stop propagating widget updates up the tabport tree.
}
also Gp_Row = List( Gp_Widget_Type )
also Gp_Col = List( Gp_Widget_Type )
also Gp_Grid = List( List( Gp_Widget_Type ))
also Gp_Mark = Gp_Widget_Type
also Gp_Row' = (Id, List( Gp_Widget_Type ))
also Gp_Col' = (Id, List( Gp_Widget_Type ))
also Gp_Grid' = (Id, List( List( Gp_Widget_Type )))
also Gp_Mark' = (Id, String, Gp_Widget_Type )
#
also Gp_Scrollport = { scroller_callback: Scroller_Callback, pixmap_size: g2d::Size, widget: Gp_Widget_Type }
also Gp_Tabport = (Tab_Picker_Callback, Gp_Widget_Type, List( Gp_Widget_Type )) # "Gp_Widget_Type, List(Gp_Widget_Type)" is a technical trick to specify via the type system that the list must be at least one entry long. (We subsequently just use Gp_Widget_Type ! List(Gp_Widget_Type).)
also Gp_Frame = (List(Frame_Option), Gp_Widget_Type )
also Gp_Widget = Widget_Start_Fn
also Gp_Objectspace = (List(Objectspace_Option), List(Gp_Object))
also Gp_Spritespace = (List(Spritespace_Option), List(Gp_Sprite))
also Gp_Widgetspace = (List(Widgetspace_Option), Gp_Widget_Type)
#########################################################################################
### More guiboss-to-widgetspace types
#########################################################################################
### More guiboss-to-objectspace types
#########################################################################################
### More guiboss-to-spritespace types
#########################################################################################
### More gui-plan types
#########################################################################################
### Recursive running-gui types
also
Rg_Row # Used in RG_ROW
= # A horizontal row of widget widgets.
{ 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 ), # Derived ultimately from Rg_Widget layout hints. This gets computed and set in
src/lib/x-kit/widget/gui/guiboss-widget-layout.pkg 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 ) # Normally NULL; if non-NULL (and at least two widgets in row/col), gives fraction of row/col space to allocate to first widget, overriding the regular bottom-up sizing mechanism.
}
also
Rg_Col = Rg_Row # Used in RG_COL. Synonym to allow better code readability.
also
Rg_Grid # Used in RG_GRID
= # A grid widget widgets.
{ 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 ), # Derived ultimately from Rg_Widget layout hints. This gets computed and set in
src/lib/x-kit/widget/gui/guiboss-widget-layout.pkg 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 }
also
Rg_Mark # Used in RG_MARK
= # A single widget.
{ id: Id,
doc: String,
widget: Rg_Widget_Type, # The widget to be displayed.
widget_layout_hint: Ref( Widget_Layout_Hint ), # Derived ultimately from Rg_Widget layout hints. This gets computed and set in
src/lib/x-kit/widget/gui/guiboss-widget-layout.pkg 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 }
also
Rg_Scrollport # Used in RG_SCROLLPORT
= #
{ id: Id,
upperleft: Ref(g2d::Point), # Upperleft of scrollport's contents in scrollport coordinates, used for scrolling pixmap in scrollport.
scroller: Ref(Scroller), # Client-code interface for controlling 'upperleft' and thus scrolling scrollport contents. 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 'upperleft' above.
site: Ref(g2d::Box), # Our scrollport's current assigned site on parent pixmap (NOT '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 rg_scrollport and rg_widget each want to be created first.
pixmap: g2p::Gadget_To_Rw_Pixmap, #
#
parent_subwindow_or_view: Subwindow_Or_View # Used when propagating redraws up the pixmap hierachy. This can be a SCROLLABLE_INFO if we have a scrollport located on a scrollport.
}
also
Rg_Tabport # Used in 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,
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.
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! ***
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 # NOTE: We specifically depend on tab.site == rg_tabport.site for all tabs (i.e., all point to the same refcell).
}
also
Rg_Frame
=
{ 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 }
also
Rg_Widget # Used in 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 =
{ # We don't need an 'id' field here because guiboss_to_widget.id serves the purpose.
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 when shutting down due to die() call. 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# doc: String # Debugging support: Allow RG_WIDGETs to be distinguishable for debug-display purposes.
}
also
Rg_Widgetspace
=
{ # We don't need an 'id' field here because guiboss_to_widgetspace.id serves the purpose.
guiboss_to_widgetspace: Guiboss_To_Widgetspace, # Layout imp for this widgetspace.
rg_widget: Rg_Widget_Type # Widgettree displayed in this widgetspace.
}
also
Rg_Objectspace # Used in RG_OBJECTSPACE
=
{ # We don't need an 'id' field here because guiboss_to_objectspace.id serves the purpose.
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 }
also
Rg_Object
=
{ # We don't need an 'id' field here because guiboss_to_gadget.id serves the purpose.
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.
}
also
Rg_Sprite
=
{ # We don't need an 'id' field here because guiboss_to_gadget.id serves the purpose.
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.
}
also
Rg_Spritespace # Used in RG_SPRITESPACE
=
{ # We don't need an 'id' field here because guiboss_to_spritespace.id serves the purpose.
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 }
#########################################################################################
### Recursive Widget_Start_Fn types
also
Widget_Imports
=
{
widget_to_guiboss: Widget_To_Guiboss, #
run_gun': Run_Gun, #
shutdown_oneshot: Oneshot_Maildrop( Void )
}
also
Widget_Exports
=
{ guiboss_to_widget: Guiboss_To_Widget #
}
#########################################################################################
### Recursive Object_Start_Fn types
also
Object_Imports
=
{ gadget_to_guiboss: Gadget_To_Guiboss, #
object_to_objectspace: o2c::Object_To_Objectspace, #
run_gun': Run_Gun, #
shutdown_oneshot: Oneshot_Maildrop( Void )
}
also
Object_Exports
=
{ guiboss_to_gadget: Guiboss_To_Gadget, #
objectspace_to_object: c2o::Objectspace_To_Object #
}
#########################################################################################
### Recursive Sprite_Start_Fn types
also
Sprite_Imports
=
{ gadget_to_guiboss: Gadget_To_Guiboss, #
sprite_to_spritespace: s2b::Sprite_To_Spritespace, #
run_gun': Run_Gun, #
shutdown_oneshot: Oneshot_Maildrop( Void ) #
}
also
Sprite_Exports
=
{ guiboss_to_gadget: Guiboss_To_Gadget, #
spritespace_to_sprite: b2s::Spritespace_To_Sprite #
};
Mouse_Is # Support for mouse drag operations.
#
= CROSSING_NONGADGET # Mouse is not currently to be on any gadget.
#
| CROSSING_GADGET
# Mouse is currently on a gadget. Eventually we should issue ENTER and LEAVE events based on this.
{ gadget_imp_info: Gadget_Imp_Info # This is the gadget on which the mouse is currently located. We send a LEAVE event when the mouse leaves it.
}
#
| DRAGGING
# Mouse is being dragged on this gadget.
{ gadget_imp_info: Gadget_Imp_Info, # This is the gadget on which the drag started. It gets all the motion events until drag terminates, even if mouse leaves the window area owned by the gadget.
start_point: g2d::Point, # This is the window coordinate of the downclick which started this drag.
last_point: g2d::Point, # This is the window coordinate of the last motion event for this drag.
guipane_offset: g2d::Point # Add this to points in basewindow coordinate system to convert them to guipane coordinate system that the gadget expects.
}
;
Hostwindow_Info
=
{ 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.
# The remainder are valid only while a gui is running,
# which is to say, between start_gui' and kill_gui'.
subwindow_info: Ref( Null_Or( Subwindow_Data ) )
};
Guiboss_State #
=
{
gui_update_count: Ref( Int ), # Counts the number of times that install_updated_guipiths() has been called (or gui topology otherwise modified).
hostwindows: Ref( idm::Map( Hostwindow_Info ) ), # Each call to client_to_guiboss.make_hostwindow() adds one entry to this. Indexed by guiboss_to_hostwindow.id.
mouse_is: Ref( Mouse_Is ), # Support for mouse drag operations.
last_button_changed: Ref( evt::Mousebutton ), # So we can tell drag_fn clients which button is dragging. (evt::Motion_Xevtinfo values do not include a 'button' arg, unlike evt::Button_Xevtinfo values.)
keyboard_focus: Ref( Null_Or( Gadget_Imp_Info ) ), # Gadget currently holding keyboard focus, if any.
#
gadget_imps: Gadget_Imps, # Holds info on our Gadget_Imp_Info instances -- basically, all running widgets, sprites and objects in hostwindow.
widget_layout_hints: Widget_Layout_Hints, # Holds our Widget_Layout_Hint instances for all widget-imp.pkg instances for this hostwindow.
spritespace_imps: Spritespace_Imps, # Holds info on our Guiboss_To_Spritespace instances -- all spritespace-imp.pkg instances for this hostwindow.
objectspace_imps: Objectspace_Imps, # Holds info on our Guiboss_To_Objectspace instances -- all objectspace-imp.pkg instances for this hostwindow.
widgetspace_imps: Widgetspace_Imps # Holds info on our Guiboss_To_Widgetspace instances -- all widgetspace-imp.pkg instances for this hostwindow.
};
};
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.