PreviousUpNext

15.4.1451  src/lib/x-kit/widget/leaf/blank.pkg

## blank.pkg
#
# See also:
#     src/lib/x-kit/widget/leaf/blank.pkg
#     src/lib/x-kit/widget/leaf/diamondbutton.pkg
#     src/lib/x-kit/widget/leaf/roundbutton.pkg

# Compiled by:
#     src/lib/x-kit/widget/xkit-widget.sublib





###                "The problem is to compress a room full
###                 of digital computation equipment into
###                 the size of a suitcase, then a shoe box,
###                 and finally small enough to hold in the
###                 palm of the hand."
###                                    -- Jack Staller, 1959

# This package gets used in:
#
#     

stipulate
    include package   threadkit;                                                # threadkit                     is from   src/lib/src/lib/thread-kit/src/core-thread-kit/threadkit.pkg
    include package   geometry2d;                                               # geometry2d                    is from   src/lib/std/2d/geometry2d.pkg
    #
    package evt =  gui_event_types;                                             # gui_event_types               is from   src/lib/x-kit/widget/gui/gui-event-types.pkg
    package g2p =  gadget_to_pixmap;                                            # gadget_to_pixmap              is from   src/lib/x-kit/widget/theme/gadget-to-pixmap.pkg
    package gd  =  gui_displaylist;                                             # gui_displaylist               is from   src/lib/x-kit/widget/theme/gui-displaylist.pkg
    package gt  =  guiboss_types;                                               # guiboss_types                 is from   src/lib/x-kit/widget/gui/guiboss-types.pkg
    package wt  =  widget_theme;                                                # widget_theme                  is from   src/lib/x-kit/widget/theme/widget/widget-theme.pkg
    package r8  =  rgb8;                                                        # rgb8                          is from   src/lib/x-kit/xclient/src/color/rgb8.pkg
    package r64 =  rgb;                                                         # rgb                           is from   src/lib/x-kit/xclient/src/color/rgb.pkg
    package wi  =  widget_imp;                                                  # widget_imp                    is from   src/lib/x-kit/widget/xkit/theme/widget/default/look/widget-imp.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 mtx =  rw_matrix;                                                   # rw_matrix                     is from   src/lib/std/src/rw-matrix.pkg
    package pp  =  standard_prettyprinter;                                      # standard_prettyprinter        is from   src/lib/prettyprint/big/src/standard-prettyprinter.pkg
    package gtg =  guiboss_to_guishim;                                          # guiboss_to_guishim            is from   src/lib/x-kit/widget/theme/guiboss-to-guishim.pkg

    nb =  log::note_on_stderr;                                                  # log                           is from   src/lib/std/src/log.pkg
herein

    package blank
    :       Blank                                                               # Blank                 is from   src/lib/x-kit/widget/leaf/blank.api
    {
        App_To_Blank
          =
          { id:                                 Id
          };


        Redraw_Fn_Arg
            =
            REDRAW_FN_ARG
              {
                id:                             Id,                             # Unique Id for widget.
                doc:                            String,                         # Human-readable description of this widget, for debug and inspection.
                frame_number:                   Int,                            # 1,2,3,... Purely for convenience of widget, guiboss-imp makes no use of this.
                frame_indent_hint:              gt::Frame_Indent_Hint,
                site:                           g2d::Box,                       # Window rectangle in which to draw.
                popup_nesting_depth:            Int,                            # 0 for gadgets on basewindow, 1 for gadgets on popup on basewindow, 2 for gadgets on popup on popup, etc.
                #
                duration_in_seconds:            Float,                          # If state has changed look-imp should call note_changed_gadget_foreground() before this time is up. Also useful for motionblur.
                widget_to_guiboss:              gt::Widget_To_Guiboss,
                gadget_mode:                    gt::Gadget_Mode,
                #
                theme:                          wt::Widget_Theme,
                do:                             (Void -> Void) -> Void,         # Used by widget subthreads to execute code in main widget microthread.
                to:                             Replyqueue,                                             # Used to call 'pass_*' methods in other imps.
                palette:                        wt::Gadget_Palette,
                #
                default_redraw_fn:              Redraw_Fn
              }
        withtype
        Redraw_Fn
          =
          Redraw_Fn_Arg
          ->
          { displaylist:                        gd::Gui_Displaylist,
            point_in_gadget:                    Null_Or(g2d::Point -> Bool)     # 
          }
          ;



        Mouse_Click_Fn_Arg
            =
            MOUSE_CLICK_FN_ARG                                                  # Needs to be a sumtype because of recursive reference in default_mouse_click_fn.
              { id:                             Id,                             # Unique Id for widget.
                doc:                            String,                         # Human-readable description of this widget, for debug and inspection.
                event:                          gt::Mousebutton_Event,          # MOUSEBUTTON_PRESS or MOUSEBUTTON_RELEASE.
                button:                         evt::Mousebutton,               # Which mousebutton was pressed/released.
                point:                          g2d::Point,                     # Where the mouse was.
                widget_layout_hint:             gt::Widget_Layout_Hint,
                frame_indent_hint:              gt::Frame_Indent_Hint,
                site:                           g2d::Box,                       # Widget's assigned area in window coordinates.
                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.
                widget_to_guiboss:              gt::Widget_To_Guiboss,
                theme:                          wt::Widget_Theme,
                do:                             (Void -> Void) -> Void,         # Used by widget subthreads to execute code in main widget microthread.
                to:                             Replyqueue,                     # Used to call 'pass_*' methods in other imps.
                #
                default_mouse_click_fn:         Mouse_Click_Fn,
                #
                needs_redraw_gadget_request:    Void -> Void                    # Notify guiboss-imp that this button needs to be redrawn (i.e., sent a redraw_gadget_request()).
              }
        withtype
        Mouse_Click_Fn = Mouse_Click_Fn_Arg -> Void;



        Mouse_Drag_Fn_Arg
            =
            MOUSE_DRAG_FN_ARG
              {
                id:                             Id,                             # Unique Id for widget.
                doc:                            String,                         # Human-readable description of this widget, for debug and inspection.
                event_point:                    g2d::Point,
                start_point:                    g2d::Point,
                last_point:                     g2d::Point,
                widget_layout_hint:             gt::Widget_Layout_Hint,
                frame_indent_hint:              gt::Frame_Indent_Hint,
                site:                           g2d::Box,                       # Widget's assigned area in window coordinates.
                phase:                          gt::Drag_Phase, 
                button:                         evt::Mousebutton,
                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.
                widget_to_guiboss:              gt::Widget_To_Guiboss,
                theme:                          wt::Widget_Theme,
                do:                             (Void -> Void) -> Void,         # Used by widget subthreads to execute code in main widget microthread.
                to:                             Replyqueue,                     # Used to call 'pass_*' methods in other imps.
                #
                default_mouse_drag_fn:          Mouse_Drag_Fn,
                #
                needs_redraw_gadget_request:    Void -> Void                    # Notify guiboss-imp that this button needs to be redrawn (i.e., sent a redraw_gadget_request()).
              }
        withtype
        Mouse_Drag_Fn =  Mouse_Drag_Fn_Arg -> Void;



        Mouse_Transit_Fn_Arg                                                    # Note that buttons are always all up in a mouse-transit event -- otherwise it is a mouse-drag event.
            =
            MOUSE_TRANSIT_FN_ARG
              {
                id:                             Id,                             # Unique Id for widget.
                doc:                            String,                         # Human-readable description of this widget, for debug and inspection.
                event_point:                    g2d::Point,
                widget_layout_hint:             gt::Widget_Layout_Hint,
                frame_indent_hint:              gt::Frame_Indent_Hint,
                site:                           g2d::Box,                       # Widget's assigned area in window coordinates.
                transit:                        gt::Gadget_Transit,             # Mouse is entering (CAME) or leaving (LEFT) widget, or moving (MOVE) across it.
                modifier_keys_state:            evt::Modifier_Keys_State,       # State of the modifier keys (shift, ctrl...).
                widget_to_guiboss:              gt::Widget_To_Guiboss,
                theme:                          wt::Widget_Theme,
                do:                             (Void -> Void) -> Void,         # Used by widget subthreads to execute code in main widget microthread.
                to:                             Replyqueue,                     # Used to call 'pass_*' methods in other imps.
                #
                default_mouse_transit_fn:       Mouse_Transit_Fn,
                #
                needs_redraw_gadget_request:    Void -> Void                    # Notify guiboss-imp that this button needs to be redrawn (i.e., sent a redraw_gadget_request()).
              }
        withtype
        Mouse_Transit_Fn =  Mouse_Transit_Fn_Arg -> Void;



        Key_Event_Fn_Arg
            =
            KEY_EVENT_FN_ARG
              {
                id:                             Id,                             # Unique Id for widget.
                doc:                            String,                         # Human-readable description of this widget, for debug and inspection.
                keystroke:                      gt::Keystroke_Info,             # Keystring etc for event.
                widget_layout_hint:             gt::Widget_Layout_Hint,
                frame_indent_hint:              gt::Frame_Indent_Hint,
                site:                           g2d::Box,                       # Widget's assigned area in window coordinates.
                widget_to_guiboss:              gt::Widget_To_Guiboss,
                guiboss_to_widget:              gt::Guiboss_To_Widget,          # Used by textpane.pkg keystroke-macro stuff to synthesize fake keystroke events to widget.
                theme:                          wt::Widget_Theme,
                do:                             (Void -> Void) -> Void,         # Used by widget subthreads to execute code in main widget microthread.
                to:                             Replyqueue,                     # Used to call 'pass_*' methods in other imps.
                #
                default_key_event_fn:           Key_Event_Fn,
                #
                needs_redraw_gadget_request:    Void -> Void                    # Notify guiboss-imp that this button needs to be redrawn (i.e., sent a redraw_gadget_request()).
              }
        withtype
        Key_Event_Fn =  Key_Event_Fn_Arg -> Void;



        Option  = PIXELS_SQUARE         Int
                #
                | PIXELS_HIGH_MIN       Int
                | PIXELS_WIDE_MIN       Int
                #
                | PIXELS_HIGH_CUT       Float
                | PIXELS_WIDE_CUT       Float
                #
                | ID                    Id
                | DOC                   String
                #
                | REDRAW_FN             Redraw_Fn                               # Application-specific handler for widget redraw.
                | MOUSE_CLICK_FN        Mouse_Click_Fn                          # Application-specific handler for mousebutton clicks.
                | MOUSE_DRAG_FN         Mouse_Drag_Fn                           # Application-specific handler for mouse drags.
                | MOUSE_TRANSIT_FN      Mouse_Transit_Fn                        # Application-specific handler for mouse crossings.
                | KEY_EVENT_FN          Key_Event_Fn                            # Application-specific handler for keyboard input.
                #
                | PORTWATCHER           (Null_Or(App_To_Blank) -> Void)         # Widget's app port                   will be sent to these fns at widget startup.
                | SITEWATCHER           (Null_Or((Id,g2d::Box)) -> Void)        # Widget's site in window coordinates will be sent to these fns each time it changes.
                ;                                                               # To help prevent deadlock, watcher fns should be fast and nonblocking, typically just setting a var or entering something into a mailqueue.
                
        fun process_options
            ( options: List(Option),
              #
              { widget_id,
                widget_doc,
                #
                redraw_fn,
                mouse_click_fn,
                mouse_drag_fn,
                mouse_transit_fn,
                key_event_fn,
                #
                widget_options,
                #
                portwatchers,
                sitewatchers
              }
            )
            =
            {   my_widget_id            =  REF  widget_id;
                my_widget_doc           =  REF  widget_doc;
                #
                my_redraw_fn            =  REF  redraw_fn;
                my_mouse_click_fn       =  REF  mouse_click_fn;
                my_mouse_drag_fn        =  REF  mouse_drag_fn;
                my_mouse_transit_fn     =  REF  mouse_transit_fn;
                my_key_event_fn         =  REF  key_event_fn;
                #
                my_widget_options       =  REF  widget_options;
                #
                my_portwatchers         =  REF  portwatchers;
                my_sitewatchers         =  REF  sitewatchers;
                #

                apply  do_option  options
                where
                    fun do_option (ID                           i) =>   my_widget_id            :=  THE i;
                        do_option (DOC                          d) =>   my_widget_doc           :=      d;
                        #
                        do_option (REDRAW_FN                    f) =>   my_redraw_fn            :=  f;
                        do_option (MOUSE_CLICK_FN               f) =>   my_mouse_click_fn       :=  f;
                        do_option (MOUSE_DRAG_FN                f) =>   my_mouse_drag_fn        :=  THE f;
                        do_option (MOUSE_TRANSIT_FN             f) =>   my_mouse_transit_fn     :=  THE f;
                        do_option (KEY_EVENT_FN                 f) =>   my_key_event_fn         :=  THE f;
                        #
                        do_option (PORTWATCHER                  c) =>   my_portwatchers         :=  c ! *my_portwatchers;
                        do_option (SITEWATCHER                  c) =>   my_sitewatchers         :=  c ! *my_sitewatchers;
                        #
                        #
                        do_option (PIXELS_HIGH_MIN              i) =>   my_widget_options       :=  (wi::PIXELS_HIGH_MIN i) ! *my_widget_options;
                        do_option (PIXELS_WIDE_MIN              i) =>   my_widget_options       :=  (wi::PIXELS_WIDE_MIN i) ! *my_widget_options;
                        #
                        do_option (PIXELS_HIGH_CUT              f) =>   my_widget_options       :=  (wi::PIXELS_HIGH_CUT f) ! *my_widget_options;
                        do_option (PIXELS_WIDE_CUT              f) =>   my_widget_options       :=  (wi::PIXELS_WIDE_CUT f) ! *my_widget_options;
                        #
                        do_option (PIXELS_SQUARE                i) =>   my_widget_options       :=  (wi::PIXELS_HIGH_MIN   i)
                                                                                                !   (wi::PIXELS_WIDE_MIN   i)
                                                                                                !   (wi::PIXELS_HIGH_CUT 0.0)
                                                                                                !   (wi::PIXELS_WIDE_CUT 0.0)
                                                                                                !   *my_widget_options;
                    end;
                end;

                { widget_id             =>  *my_widget_id,
                  widget_doc            =>  *my_widget_doc,
                  #
                  redraw_fn             =>  *my_redraw_fn,
                  mouse_click_fn        =>  *my_mouse_click_fn,
                  mouse_drag_fn         =>  *my_mouse_drag_fn,
                  mouse_transit_fn      =>  *my_mouse_transit_fn,
                  key_event_fn          =>  *my_key_event_fn,
                  #
                  widget_options        =>  *my_widget_options,
                  #
                  portwatchers          =>  *my_portwatchers,
                  sitewatchers          =>  *my_sitewatchers
                };
            };


        offset = 1;

        fun with (options: List(Option))                                                                        # PUBLIC.  The point of the 'with' name is that GUI coders can write 'blank::with { this => that, foo => bar, ... }.'
            =
            {
                fun default_redraw_fn (REDRAW_FN_ARG a)
                    =
                    {   palette         =  a.palette;
                        site            =  a.site;

                        point_in_gadget = NULL;
                        #
                        background_box =  site;

                        background = [ gd::COLOR (palette.surround_color,  [ gd::FILLED_BOXES [ background_box ]]) ];

                        { displaylist => background, point_in_gadget };
                    };

                fun default_mouse_click_fn (MOUSE_CLICK_FN_ARG a)
                    =
                    {
                        ();
                    };

                (process_options
                  (
                    options,
                    #
                    { widget_id         =>  NULL,
                      widget_doc        =>  "<blank>",
                      # 
                      redraw_fn         =>  default_redraw_fn,
                      mouse_click_fn    =>  default_mouse_click_fn,
                      mouse_drag_fn     =>  NULL,
                      mouse_transit_fn  =>  NULL,
                      key_event_fn      =>  NULL,
                      #
                      widget_options    =>  [],
                      #
                      portwatchers      =>  [],
                      sitewatchers      =>  []
                    }
                ) )
                    ->
                    {                                                                                           # These values are globally visible to the subsequenc fns, which can lock them in as needed.
                      widget_id,
                      widget_doc,
                      # 
                      redraw_fn,
                      mouse_click_fn,
                      mouse_drag_fn,
                      mouse_transit_fn,
                      key_event_fn,
                      #
                      widget_options,
                      #
                      portwatchers,
                      sitewatchers
                    };


                #######################################
                # Top of per-imp state variable section
                #

                widget_to_guiboss__global
                    =
                    REF (NULL:  Null_Or((gt::Widget_To_Guiboss, Id)));

                fun needs_redraw_gadget_request ()
                    =
                    case (*widget_to_guiboss__global)
                        #
                        THE (widget_to_guiboss, id)     =>  widget_to_guiboss.g.needs_redraw_gadget_request(id);
                        NULL                            =>  ();
                    esac;


                last_known_site
                    =
                    REF ( { col => -1,  wide => -1,
                            row => -1,  high => -1
                          }:                            g2d::Box
                        );



                exception SAVED_STATE { last_known_site:        g2d::Box                                        # Here we're doing the usual hack of using Exception as an extensible datatype -- nothing to do with actually raising or trapping exceptions.
                                      };        


                fun note_site  (id: Id,  site: g2d::Box)
                    =
                    if(*last_known_site != site)
                        last_known_site := site;
                        #
                        apply tell_watcher sitewatchers
                            where
                                fun tell_watcher sitewatcher
                                    =
                                    sitewatcher (THE (id,site));
                            end;
                    fi;

                #
                # End of state variable section
                ###############################


                #####################
                # Top of port section
                #
                # Here we implement our App_To_Blank port:

                #
                # End of port section
                #####################


                ###############################
                # Top of widget hook fn section
                #
                # These fns get called by widget_imp logic, ultimately                                          # widget_imp            is from   src/lib/x-kit/widget/xkit/theme/widget/default/look/widget-imp.pkg
                # in response to user mouseclicks and keypresses etc:

                fun startup_fn
                    { 
                      id:                               Id,                                                     # Unique Id for widget.
                      doc:                              String,                                                 # Human-readable description of this widget, for debug and inspection.
                      widget_to_guiboss:                gt::Widget_To_Guiboss,
                      do:                               (Void -> Void) -> Void,                                 # Used by widget subthreads to execute code in main widget microthread.
                      to:                               Replyqueue
                    }
                    =
                    {   widget_to_guiboss__global
                            :=  
                            THE (widget_to_guiboss, id);

                        app_to_blank
                          =
                          { id 
                          }
                          : App_To_Blank
                          ;

                        apply   tell_watcher  portwatchers                                                      # We do this here rather than (say) above this fn because we don't want the port in circulation until we're running.
                                where
                                    fun tell_watcher  portwatcher
                                        =
                                        portwatcher  (THE app_to_blank);
                                end;
                        ();
                    };

                fun shutdown_fn ()                                                                              # Return to widget_imp an exception packaging up our state; this will be returned to guiboss_imp, saved in the
                    =                                                                                           # Paused_Gui tree, and passed to our startup_fn when/if gui is restarted. This exception will never be raised;
                    {   apply   tell_watcher  portwatchers                                                      # 
                                where
                                    fun tell_watcher  portwatcher
                                        =
                                        portwatcher  NULL;
                                end;

                        apply tell_watcher sitewatchers
                            where
                                fun tell_watcher sitewatcher
                                    =
                                    sitewatcher NULL;
                            end;
                    };

                fun initialize_gadget_fn
                    {
                      id:                               Id,                                                     # Unique Id for widget.
                      doc:                              String,                                                 # Human-readable description of this widget, for debug and inspection.
                      site:                             g2d::Box,                                               # Window rectangle in which to draw.
                      widget_to_guiboss:                gt::Widget_To_Guiboss,
                      theme:                            wt::Widget_Theme,
                      pass_font:                        List(String) -> Replyqueue
                                                                     -> (evt::Font -> Void) -> Void,            # Nonblocking version of next, for use in imps.
                       get_font:                        List(String) ->  evt::Font,                             # Accepts a list of font names which are tried in order.
                      make_rw_pixmap:                   g2d::Size -> g2p::Gadget_To_Rw_Pixmap,
                      #
                      do:                               (Void -> Void) -> Void,                                 # Used by widget subthreads to execute code in main widget microthread.
                      to:                               Replyqueue                                              # Used to call 'pass_*' methods in other imps.
                    }
                    =
                    {   note_site (id,site);
                        #
                        ();
                    };

                fun redraw_request_fn_wrapper
                    {
                      id:                               Id,                             # Unique Id for widget.
                      doc:                              String,                         # Human-readable description of this widget, for debug and inspection.
                      frame_number:                     Int,                            # 1,2,3,... Purely for convenience of widget-imp, guiboss-imp makes no use of this.
                      frame_indent_hint:                gt::Frame_Indent_Hint,
                      site:                             g2d::Box,                       # Window rectangle in which to draw.
                      popup_nesting_depth:              Int,                            # 0 for gadgets on basewindow, 1 for gadgets on popup on basewindow, 2 for gadgets on popup on popup, etc.
                      #
                      duration_in_seconds:              Float,                          # If state has changed widget-imp should call redraw_gadget() before this time is up. Also useful for motionblur.
                      widget_to_guiboss:                gt::Widget_To_Guiboss,
                      #
                      gadget_mode:                      gt::Gadget_Mode,
                      theme:                            wt::Widget_Theme,
                      do:                               (Void -> Void) -> Void,
                      to:                               Replyqueue                      # Used to call 'pass_*' methods in other imps.
                    }
                    =
                    {   note_site (id,site);
                        #
                        (*theme.current_gadget_colors { gadget_is_on => FALSE,
                                                        gadget_mode,
                                                        popup_nesting_depth,
                                                        #
                                                        body_color                          => NULL,
                                                        body_color_when_on                  => NULL,
                                                        body_color_with_mousefocus          => NULL,
                                                        body_color_when_on_with_mousefocus  => NULL
                                                      }
                        )
                            ->
                            (palette: wt::Gadget_Palette);

                        redraw_fn_arg
                            =
                            REDRAW_FN_ARG
                              { id,
                                doc,
                                frame_number,
                                frame_indent_hint,
                                site,
                                popup_nesting_depth,
                                duration_in_seconds,
                                widget_to_guiboss,
                                gadget_mode,
                                theme,
                                do,
                                to,
                                palette,
                                #
                                default_redraw_fn
                              };

                        (redraw_fn  redraw_fn_arg)
                            ->
                            { displaylist, point_in_gadget };

                        widget_to_guiboss.g.redraw_gadget { id, site, displaylist, point_in_gadget };
                    };


                fun mouse_click_fn_wrapper                                                                      # This a callback we hand to   src/lib/x-kit/widget/xkit/theme/widget/default/look/widget-imp.pkg
                      {
                        id:                             Id,                                                     # Unique Id for widget.
                        doc:                            String,                                                 # Human-readable description of this widget, for debug and inspection.
                        event:                          gt::Mousebutton_Event,                                  # MOUSEBUTTON_PRESS or MOUSEBUTTON_RELEASE.
                        button:                         evt::Mousebutton,
                        point:                          g2d::Point,
                        widget_layout_hint:             gt::Widget_Layout_Hint,
                        frame_indent_hint:              gt::Frame_Indent_Hint,
                        site:                           g2d::Box,                                               # Widget's assigned area in window coordinates.
                        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.
                        widget_to_guiboss:              gt::Widget_To_Guiboss,
                        theme:                          wt::Widget_Theme,
                        do:                             (Void -> Void) -> Void,                                 # Used by widget subthreads to execute code in main widget microthread.
                        to:                             Replyqueue                                              # Used to call 'pass_*' methods in other imps.
                      }
                    = 
                    {   note_site  (id,site);
                        #
                        mouse_click_fn_arg
                            =
                            MOUSE_CLICK_FN_ARG
                              {
                                id,
                                doc,
                                event,
                                button,
                                point,
                                widget_layout_hint,
                                frame_indent_hint,
                                site,
                                modifier_keys_state,
                                mousebuttons_state,
                                widget_to_guiboss,
                                theme,
                                do,
                                to,
                                #
                                default_mouse_click_fn,
                                #
                                needs_redraw_gadget_request
                              };

                        mouse_click_fn  mouse_click_fn_arg;
                    };

                fun mouse_drag_fn_wrapper                                                                       # This a callback we hand to   src/lib/x-kit/widget/xkit/theme/widget/default/look/widget-imp.pkg
                    (
                      { id:                             Id,                                                     # Unique Id for widget.
                        doc:                            String,                                                 # Human-readable description of this widget, for debug and inspection.
                        event_point:                    g2d::Point,
                        start_point:                    g2d::Point,
                        last_point:                     g2d::Point,
                        widget_layout_hint:             gt::Widget_Layout_Hint,
                        frame_indent_hint:              gt::Frame_Indent_Hint,
                        site:                           g2d::Box,                                               # Widget's assigned area in window coordinates.
                        phase:                          gt::Drag_Phase, 
                        button:                         evt::Mousebutton,
                        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.
                        widget_to_guiboss:              gt::Widget_To_Guiboss,
                        theme:                          wt::Widget_Theme,
                        do:                             (Void -> Void) -> Void,                                 # Used by widget subthreads to execute code in main widget microthread.
                        to:                             Replyqueue                                              # Used to call 'pass_*' methods in other imps.
                      }
                    )
                    = 
                    {   note_site  (id,site);
                        #
                        mouse_drag_fn_arg
                            =
                            MOUSE_DRAG_FN_ARG
                              {
                                id,
                                doc,
                                event_point,
                                start_point,
                                last_point,
                                widget_layout_hint,
                                frame_indent_hint,
                                site,
                                phase,
                                button,
                                modifier_keys_state,
                                mousebuttons_state,
                                widget_to_guiboss,
                                theme,
                                do,
                                to,
                                #
                                default_mouse_drag_fn =>  \\ _ = (),                                            # Default drag behavior is to do absolutely nothing.
                                #
                                needs_redraw_gadget_request
                              };

                        case mouse_drag_fn
                            #
                            THE mouse_drag_fn =>   mouse_drag_fn  mouse_drag_fn_arg;
                            NULL              =>   ();                                                          # We do not expect this case to happen: If mouse_drag_fn is NULL mouse_drag_fn_wrapper should not have been registered with widget-imp so we should never get called.
                        esac;
                    };

                fun mouse_transit_fn_wrapper
                      #
                      ( arg as
                        {
                          id:                           Id,                                                     # Unique Id for widget.
                          doc:                          String,                                                 # Human-readable description of this widget, for debug and inspection.
                          event_point:                  g2d::Point,
                          widget_layout_hint:           gt::Widget_Layout_Hint,
                          frame_indent_hint:            gt::Frame_Indent_Hint,
                          site:                         g2d::Box,                                               # Widget's assigned area in window coordinates.
                          transit:                      gt::Gadget_Transit,                                     # Mouse is entering (CAME) or leaving (LEFT) widget, or moving (MOVE) across it.
                          modifier_keys_state:          evt::Modifier_Keys_State,                               # State of the modifier keys (shift, ctrl...).
                          widget_to_guiboss:            gt::Widget_To_Guiboss,
                          theme:                        wt::Widget_Theme,
                          do:                           (Void -> Void) -> Void,                                 # Used by widget subthreads to execute code in main widget microthread.
                          to:                           Replyqueue                                              # Used to call 'pass_*' methods in other imps.
                        }
                      ) 
                    = 
                    {   note_site (id,site);
                        #
                        mouse_transit_fn_arg
                            =
                            MOUSE_TRANSIT_FN_ARG
                              {
                                id,
                                doc,
                                event_point,
                                widget_layout_hint,
                                frame_indent_hint,
                                site,
                                transit,
                                modifier_keys_state,
                                widget_to_guiboss,
                                theme,
                                do,
                                to,
                                #
                                default_mouse_transit_fn =>  \\ _ = (),                                         # Default transit behavior is to do absolutely nothing.
                                #
                                needs_redraw_gadget_request
                              };

                        case mouse_transit_fn
                            #
                            THE mouse_transit_fn =>   mouse_transit_fn  mouse_transit_fn_arg;
                            NULL                 =>   ();                                                       # We do not expect this case to happen: If mouse_transit_fn is NULL mouse_transit_fn_wrapper should not have been registered with widget-imp so we should never get called.
                        esac;

                        ();
                    };

                fun key_event_fn_wrapper
                      {
                        id:                             Id,                                                     # Unique Id for widget.
                        doc:                            String,                                                 # Human-readable description of this widget, for debug and inspection.
                        keystroke:                      gt::Keystroke_Info,                                     # Keystring etc for event.
                        widget_layout_hint:             gt::Widget_Layout_Hint,
                        frame_indent_hint:              gt::Frame_Indent_Hint,
                        site:                           g2d::Box,                                               # Widget's assigned area in window coordinates.
                        widget_to_guiboss:              gt::Widget_To_Guiboss,
                        guiboss_to_widget:              gt::Guiboss_To_Widget,                                  # Used by textpane.pkg keystroke-macro stuff to synthesize fake keystroke events to widget.
                        theme:                          wt::Widget_Theme,
                        do:                             (Void -> Void) -> Void,                                 # Used by widget subthreads to execute code in main widget microthread.
                        to:                             Replyqueue                                              # Used to call 'pass_*' methods in other imps.
                      }
                    = 
                    {   note_site (id,site);
                        #
                        key_event_fn_arg
                            =
                            KEY_EVENT_FN_ARG
                              {
                                id,
                                doc,
                                keystroke,
                                widget_layout_hint,
                                frame_indent_hint,
                                site,
                                widget_to_guiboss,
                                guiboss_to_widget,
                                theme,
                                do,
                                to,
                                #
                                default_key_event_fn =>  \\ _ = (),                                             # Default key event behavior is to do absolutely nothing.
                                #
                                needs_redraw_gadget_request
                              };

                        case key_event_fn
                            #
                            THE key_event_fn =>   key_event_fn  key_event_fn_arg;
                            NULL             =>   ();                                                           # We do not expect this case to happen: If key_event_fn is NULL key_event_fn_wrapper should not have been registered with widget-imp so we should never get called.
                        esac;

                       ();
                    };


                #
                # End of widget hook fn section
                ###############################

                widget_options
                    =
                    case mouse_drag_fn
                        #
                        THE _ =>  (wi::MOUSE_DRAG_FN mouse_drag_fn_wrapper)       ! widget_options;             # Register for drag events only if we are going to use them.
                        NULL  =>                                                    widget_options;
                    esac;

                widget_options
                    =
                    case mouse_transit_fn
                        #
                        THE _ =>  (wi::MOUSE_TRANSIT_FN mouse_transit_fn_wrapper) ! widget_options;             # Register for transit events only if we are going to use them.
                        NULL  =>                                                    widget_options;
                    esac;

                widget_options
                    =
                    case key_event_fn
                        #
                        THE _ =>  (wi::KEY_EVENT_FN key_event_fn_wrapper)         ! widget_options;             # Register for key events only if we are going to use them.
                        NULL  =>                                                    widget_options;
                    esac;

                widget_options
                    =
                    case widget_id
                        #
                        THE id =>  (wi::ID id)                                    ! widget_options;             # 
                        NULL   =>                                                   widget_options;
                    esac;

                widget_options
                  =
                  [ wi::STARTUP_FN                      startup_fn,                                             # We always register for these five because our base behavior depends on them.
                    wi::SHUTDOWN_FN                     shutdown_fn,
                    wi::INITIALIZE_GADGET_FN            initialize_gadget_fn,
                    wi::REDRAW_REQUEST_FN               redraw_request_fn_wrapper,
                    wi::MOUSE_CLICK_FN                  mouse_click_fn_wrapper,
                    wi::DOC                             widget_doc
                  ]
                  @
                  widget_options
                  ;

                make_widget_fn =  wi::make_widget_start_fn  widget_options;

                gt::WIDGET  make_widget_fn;                                                                     # So caller can write   guiplan = gt::ROW [ blank::with [...], blank::with [...], ... ];
            };                                                                                                  # PUBLIC
    };
end;




Comments and suggestions to: bugs@mythryl.org

PreviousUpNext