PreviousUpNext

15.4.1365  src/lib/x-kit/widget/fancy/graphviz/scrollable-graphviz-widget.pkg

## scrollable-graphviz-widget.pkg
#
# A little wrapper widget which attaches two scrollbars
# to the basic graphviz widget.

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


stipulate
    include threadkit;                          # threadkit                     is from   src/lib/src/lib/thread-kit/src/core-thread-kit/threadkit.pkg
    include xgeometry;                          # xgeometry                     is from   src/lib/std/2d/xgeometry.pkg
    #
    package f8b =  eight_byte_float;            # eight_byte_float              is from   src/lib/std/eight-byte-float.pkg
    package xtr =  xlogger;                     # xlogger                       is from   src/lib/x-kit/xclient/src/stuff/xlogger.pkg
    #
    package gv  =  graphviz_widget;             # graphviz_widget               is from   src/lib/x-kit/widget/fancy/graphviz/graphviz-widget.pkg
    package b   =  border;                      # border                        is from   src/lib/x-kit/widget/wrapper/border.pkg
    package sb  =  scrollbar;                   # scrollbar                     is from   src/lib/x-kit/widget/leaf/scrollbar.pkg
    package sbl =  widget_with_scrollbars;      # widget_with_scrollbars        is from   src/lib/x-kit/widget/layout/widget-with-scrollbars.pkg
    package wg  =  widget;                      # widget                        is from   src/lib/x-kit/widget/basic/widget.pkg
    package ffc =  font_family_cache;           # font_family_cache             is from   src/lib/x-kit/widget/fancy/graphviz/font-family-cache.pkg
    package lw  =  line_of_widgets;             # line_of_widgets               is from   src/lib/x-kit/widget/layout/line-of-widgets.pkg
    package xc  =  xclient;                     # xclient                       is from   src/lib/x-kit/xclient/xclient.pkg
herein


    # This package gets used in:
    #
    #     src/lib/x-kit/tut/show-graph/show-graph-app.pkg
    #
    package  scrollable_graphviz_widget
    :        Scrollable_Graphviz_Widget         # Scrollable_Graphviz_Widget    is from   src/lib/x-kit/widget/fancy/graphviz/scrollable-graphviz-widget.api
    {

        Scrollable_Graphviz_Widget
            =
            SCROLLABLE_GRAPHVIZ_WIDGET
              { widget:           wg::Widget,
                graphviz_widget:  gv::Graphviz_Widget
              };

        Vport = { min:    Int,
                  size:   Int,
                  total:  Int
                };

        State = (Vport, Vport);

        scroll_bar_size = 10;

        fun make_scrollable_graphviz_widget (font_family_cache, root_window) graph
            =
            {
                graphviz_widget    = gv::make_graphviz_widget (font_family_cache, root_window) graph ;

                move_scrollbar_thumbs_mailop = gv::to_scrollbars_mailop_of  graphviz_widget;

                horizontal_scrollbar = sb::make_horizontal_scrollbar root_window { color=>NULL, size=>scroll_bar_size };            horizontal_scrollbar_change' = sb::scrollbar_change'_of  horizontal_scrollbar;
                vertical_scrollbar   = sb::make_vertical_scrollbar   root_window { color=>NULL, size=>scroll_bar_size };            vertical_scrollbar_change'   = sb::scrollbar_change'_of  vertical_scrollbar;

                black  = xc::black;

                widget
                    =
                    sbl::make_widget_with_scrollbars   root_window
                      {
                        scrolled_widget => gv::as_widget graphviz_widget,

                        horizontal_scrollbar
                            =>
                            THE { pad => 1, 
                                  top => FALSE,
                                  scrollbar
                                      =>
                                      b::as_widget
                                          (b::make_border
                                            {
                                              color => THE black,
                                              width => 1,
                                              child => lw::as_widget
                                                           (lw::make_line_of_widgets  root_window
                                                               (lw::VT_CENTER
                                                                 [
                                                                   lw::SPACER { min_size=>1, ideal_size=>1, max_size=>THE 1 },
                                                                   lw::WIDGET (sb::as_widget horizontal_scrollbar),
                                                                   lw::SPACER { min_size=>1, ideal_size=>1, max_size=>THE 1 }
                                                                 ]
                                                               )
                                                           )
                                            }
                                          )

                                },

                        vertical_scrollbar
                            =>
                            THE { pad  => 1, 
                                  left => FALSE,

                                  scrollbar
                                      =>
                                       b::as_widget
                                           (b::make_border
                                             {
                                               color =>  THE black,
                                               width =>  1,
                                               child =>  lw::as_widget
                                                             (lw::make_line_of_widgets  root_window
                                                                 (lw::HZ_CENTER
                                                                   [
                                                                     lw::SPACER { min_size=>1,  ideal_size=>1, max_size=>THE 1 },
                                                                     lw::WIDGET (sb::as_widget vertical_scrollbar),
                                                                     lw::SPACER { min_size=>1,  ideal_size=>1, max_size=>THE 1 }
                                                                   ]
                                                                 )
                                                             )
                                             }
                                           )


                                }
                      };

                initstate
                    =
                    ( { min=>0, size=>0, total=>0 },
                      { min=>0, size=>0, total=>0 }
                    );


                # Handle user drag of horizontal scrollbar:
                #
                fun do_horizontal_scrollbar_change (sb::SCROLL_UP   r, state:  State) =>  state;
                    do_horizontal_scrollbar_change (sb::SCROLL_DOWN r, state:  State) =>  state;

                    do_horizontal_scrollbar_change (sb::SCROLL_END  r, state as ( { min, size, total }, v))
                        =>
                        {   min' = floor (r * (real total));

                            if (min' != min)
                                #
                                gv::set_horizontal_view graphviz_widget min';

                                ( { min=>min', size, total }, v);
                            else
                                state;
                            fi;
                        };

                    do_horizontal_scrollbar_change (_, state)
                        =>
                        state;
                end;


                # Handle user drag of vertical scrollbar:
                #
                fun do_vertical_scrollbar_change (sb::SCROLL_UP   r, state: State) =>  state;
                    do_vertical_scrollbar_change (sb::SCROLL_DOWN r, state: State) =>  state;

                    do_vertical_scrollbar_change (sb::SCROLL_END  r, state as (h, { min, size, total } ))
                        =>
                        {   min' = floor (r * (real total));

                            if (min' != min)
                                #
                                gv::set_vertical_view graphviz_widget min';

                                (h, { min=>min', size, total } );
                            else
                                state;
                            fi;
                        };

                    do_vertical_scrollbar_change (_, state)
                        =>
                        state;
                end;



                # Adjust scrollbars in response to non-scrollbar
                # changes such as window resizing:
                #
                fun move_scrollbar_thumbs ( { horizontal=>gv::VIEWDIM hz, vertical=>gv::VIEWDIM vt }, (h, v))
                    =
                    {
                        fun change (scrollbar, { min, size, total }:  Vport)
                            =
                            {   total = real total;

                                sb::set_scrollbar_thumb
                                    #
                                    scrollbar
                                    #
                                    { size =>  THE ((f8b::from_int size) // total),
                                      top  =>  THE ((f8b::from_int min ) // total)
                                    };
                            };

                        if (hz != h)   change (horizontal_scrollbar, hz);  fi; 
                        if (vt != v)   change (vertical_scrollbar,   vt);  fi; 

                        (hz, vt);
                    };


                fun loop state
                    =
                    loop (
                        #
                        do_one_mailop [
                            #
                            move_scrollbar_thumbs_mailop
                                ==>
                                (fn e = move_scrollbar_thumbs  (e, state)),             # Update scrollbars to reflect (e.g.) window resizing.

                            horizontal_scrollbar_change'
                                ==>
                                (fn e = do_horizontal_scrollbar_change (e, state)),     # User drag of scrollbar thumb.

                            vertical_scrollbar_change'
                                ==>
                                (fn e = do_vertical_scrollbar_change (e, state))        # User drag of scrollbar thumb.
                        ]
                    );

                xtr::make_thread  "scrollable_graphviz_widget"  .{
                    #
                    loop initstate;
                };

                SCROLLABLE_GRAPHVIZ_WIDGET {
                    graphviz_widget,
                    widget => lw::as_widget widget
                };
            };

        fun as_widget (SCROLLABLE_GRAPHVIZ_WIDGET { widget, ... } )
            =
            widget;

    };                                                  # package scrollable_graphviz_widget 
end;


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext