PreviousUpNext

15.4.1526  src/lib/x-kit/widget/old/leaf/slider-look.pkg

## slider-look.pkg
#
# Slider views.

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






stipulate#
#    include package   geometry2d;                              # geometry2d            is from   src/lib/std/2d/geometry2d.pkg

    package f8b =  eight_byte_float;                            # eight_byte_float      is from   src/lib/std/eight-byte-float.pkg
    package xc  =  xclient;                                     # xclient               is from   src/lib/x-kit/xclient/xclient.pkg
    package g2d =  geometry2d;                                  # geometry2d            is from   src/lib/std/2d/geometry2d.pkg
    #
    package d3  =  three_d;                                     # three_d               is from   src/lib/x-kit/widget/old/lib/three-d.pkg
    package wg  =  widget;                                      # widget                is from   src/lib/x-kit/widget/old/basic/widget.pkg
    package wa  =  widget_attribute_old;                        # widget_attribute_old  is from   src/lib/x-kit/widget/old/lib/widget-attribute-old.pkg
herein

    package   slider_look
    : (weak)  Slider_Look                                       # Slider_Look           is from   src/lib/x-kit/widget/old/leaf/slider-look.api
    {
        min = int::min;
        max = int::max;

        fun make_font_info font
            =
            {   (xc::font_high font)
                    ->
                    { ascent  => font_ascent,
                      descent => font_descent
                    };
                    

                (font, font_ascent, font_descent);
            };

        fun make_label (NULL, _)
                =>
                NULL;

            make_label (THE s, font)
                =>
                {   ((xc::text_extents font s).overall_info)
                        ->
                        xc::CHAR_INFO { left_bearing=>lb, right_bearing=>rb, ... };

                    THE (s, lb, rb);
                };
        end;

        fun int_to_string i
            =
            if (i >= 0)                int::to_string   i;
            else                "-" + (int::to_string (-i));
            fi;

        fun get_tick_width (from_v, to_v, font, font_ascent)
            =
            {   fun size (i:  Int)
                    =
                    {   s = int_to_string i;
                        #
                        ((xc::text_extents font s).overall_info)
                            ->
                            xc::CHAR_INFO { left_bearing=>lb, right_bearing=>rb, ... };

                        rb-lb;
                    };

                (font_ascent / 2) + max (size from_v, size to_v);
            };

         State = (Int, Bool, Bool, Bool);

         Slider_Look
            =
            { background_color:            xc::Rgb,
              foreground_color:            xc::Rgb,
              #
              is_vertical:   Bool,
              show_value:    Bool,                              # Show current value of slider as text?
              #
              fontinfo:     (xc::Font, Int, Int),
              relief:        wg::Relief,
              #
              border_thickness:  Int,
              from_v:        Int,                               # Leftmost slider value.
              length:        Int,
              #
              label:         Null_Or( (String, Int, Int) ),     # String label for slider. The two int values x size of string as lb,rb == leftbearing,rightbearing from xc::text_extents -- see make_label.
              #
              shades:        wg::Shades,                        # Default shades for slider.
              ready_shades:  wg::Shades,
              slide_shades:  wg::Shades,
              #
              thumb:         Int,                               # thumb length in pixels.
              tick:          Int,                               # I think this is pixels-between-tick-marks.
              to_v:          Int,                               # Rightmost slider value.
              offset:        Int,
              tick_width:    Int,
              width:         Int
            };

        fun num_ticks ( { tick=>0, ... } : Slider_Look)
                =>
                0;

            num_ticks ( { tick, from_v, to_v, ... } : Slider_Look)
                =>
                loop (from_v, 0)
                where
                    stop = if (from_v <= to_v)  \\ v = to_v < v;
                           else                 \\ v = to_v > v;
                           fi;

                    fun loop (v, count)
                        =
                        if (stop v)   count;
                        else          loop (v+tick, count+1);
                        fi;

                end;
         end;



        widget_attributes
            =
            [ (wa::ready_color,         wa::COLOR,      wa::NO_VAL              ),
              (wa::background,          wa::COLOR,      wa::STRING_VAL "white"  ),
              (wa::border_thickness,    wa::INT,        wa::INT_VAL 2           ),
              (wa::font,                wa::FONT,       wa::STRING_VAL "8x13"   ),
              (wa::foreground,          wa::COLOR,      wa::STRING_VAL "black"  ),
              (wa::is_vertical,         wa::BOOL,       wa::BOOL_VAL TRUE       ),
              (wa::relief,              wa::RELIEF,     wa::RELIEF_VAL wg::FLAT ),
              (wa::from_value,          wa::INT,        wa::INT_VAL 0           ),
              (wa::label,               wa::STRING,     wa::NO_VAL              ),
              (wa::length,              wa::INT,        wa::INT_VAL 100         ),      # Gutter length in pixels.
              (wa::show_value,          wa::BOOL,       wa::BOOL_VAL FALSE      ),
              (wa::color,               wa::COLOR,      wa::NO_VAL              ),
              (wa::thumb_length,        wa::INT,        wa::INT_VAL 30          ),      # Thumb length in pixels.
              (wa::tick_interval,       wa::INT,        wa::INT_VAL 0           ),
              (wa::to_value,            wa::INT,        wa::INT_VAL 100         ),
              (wa::width,               wa::INT,        wa::INT_VAL 15          )
            ];


        spacing = 2;

        fun make_slider_look (root, attributes)
            =
            {   foreground_color = wa::get_color (attributes wa::foreground);
                background_color = wa::get_color (attributes wa::background);

                shades = wg::shades root background_color;

                slide_shades = case (wa::get_color_opt (attributes wa::color))   
                                   #    
                                   THE c => wg::shades root c;
                                   NULL => shades;
                               esac;

                ready_shades = case (wa::get_color_opt (attributes wa::ready_color))   
                                   #
                                   THE c => wg::shades root c;
                                   NULL => slide_shades;
                               esac;

                to_v   = wa::get_int (attributes wa::to_value);
                from_v = wa::get_int (attributes wa::from_value);

                border_thickness = wa::get_int  (attributes wa::border_thickness);
                font             = wa::get_font (attributes wa::font);

                (make_font_info  font)
                    ->
                    fontinfo as  (font, font_ascent, _);

                thumb = max (6, max (3*border_thickness, wa::get_int (attributes wa::thumb_length)));

                relief = wa::get_relief (attributes wa::relief);

                fun check_tick t
                    =
                    if   (from_v <= to_v)   (t < 0) ?? -t :: t;
                    else                    (t > 0) ?? -t :: t;
                    fi;


                { background_color,
                  foreground_color,
                  border_thickness,
                  fontinfo,
                  is_vertical => wa::get_bool (attributes wa::is_vertical),
                  relief,
                  from_v,
                  label => make_label (wa::get_string_opt (attributes wa::label), font),
                  length => max (wa::get_int (attributes wa::length), thumb),
                  show_value => wa::get_bool (attributes wa::show_value),
                  shades,
                  slide_shades,
                  ready_shades,
                  thumb,
                  tick       => check_tick (wa::get_int (attributes wa::tick_interval)),
                  tick_width => get_tick_width (from_v, to_v, font, font_ascent),
                  offset     => case relief    wg::FLAT => 0;  _ => border_thickness; esac,
                  to_v,
                  width => max (3*border_thickness, wa::get_int (attributes wa::width))
                };
            };

        fun hbounds_of (slider_look:  Slider_Look)
            =
            {   slider_look.fontinfo ->  (_, font_ascent, font_descent);
                #
                line_high = font_ascent + font_descent;

                offset2 =  2*slider_look.offset;
                bw2     =  2*slider_look.border_thickness;

                x = max (slider_look.length + offset2, (num_ticks slider_look)*slider_look.tick_width);

                y = slider_look.width
                  + offset2
                  + bw2
                  + (slider_look.tick != 0      ??  line_high           ::  0)
                  + (slider_look.show_value     ??  line_high + spacing ::  0)
                  + (slider_look.label != NULL  ??  line_high           ::  0)
                  ;

                size_preferences
                    =
                    { col_preference =>  wg::loose_preference (x+bw2),
                      row_preference =>  wg::tight_preference  y
                    };

                \\ () =  size_preferences;
            };

        fun vbounds_of (slider_look:  Slider_Look)
            =
            {   slider_look.fontinfo ->  (font, font_ascent, font_descent);
                #
                label_width = case slider_look.label   
                                  THE(_, lb, rb) => rb - lb + font_ascent;
                                  NULL => 0;
                              esac;

                tick_width  =  slider_look.tick_width;
                tick_width  =  slider_look.tick != 0   ??  tick_width  ::  0;
                value_width =  slider_look.show_value  ??  tick_width  ::  0;

                offset2 = 2*slider_look.offset;
                bw2     = 2*slider_look.border_thickness;

                y = slider_look.length + offset2 + bw2;
                x = slider_look.width  + offset2 + bw2 + label_width + spacing + tick_width + value_width;

                size_preferences
                    =
                    { col_preference =>  wg::tight_preference  x,
                      row_preference =>  wg::loose_preference  y
                    };

                \\ () =  size_preferences;
            };

        fun val_to_pt (size, slider_look:  Slider_Look)                         # Return fn mapping value to pixel position for thumb.
            =
            {   slider_look ->   { is_vertical, thumb, border_thickness, offset, from_v, to_v, ... };
                #
                size   ->  { wide, high };

                range = float (to_v - from_v);

                prange = (is_vertical ?? high :: wide)                          # "prange" == "pixel_range" -- number of pixels slider can move through...?
                                - thumb - 2*(offset + border_thickness);

                rprange = float prange;

                off =  thumb/2 + offset + border_thickness;                     # Left/bottom limit of thumb motion, as pixel coordinate.

                if (range == 0.0)
                    #
                    \\ _ =  off;
                else
                    \\ value
                        =
                        {   y = trunc((float (value - from_v) * rprange)/range + 0.5);
                            #
                            y = if   (y < 0     )   0;
                                elif (y > prange)   prange;
                                else                y;
                                fi;

                            y + off;
                        };
                fi;
              };


        fun draw_border (0, _, _, _, _)                                         # This appears to actually draw the gutter in which the slider moves.
                =>
                ();

            draw_border (bw, d, wide, high, slider_look:  Slider_Look)
                =>
                {   r = { row=>0, col=>0, wide, high };
                    rel = slider_look.relief;
                    shades = slider_look.shades;

                    d3::draw_box d { box=>r, relief=> rel, width=>bw } shades;
                };
        end;

                                                                                # Draw one tickmark on a vertical slider, labelled by its numeric value -- called by draw_ticks().
                                                                                # Also used to draw current value of slider, at upperright of vertical slider.
        fun draw_vvalue                                                         # Convert int 'value' to string and draw it right-justified (i.e., ending at column 'right').
                (val_to_pt, high, dr, pen, slider_look:  Slider_Look)
                (value, right)
            =
            {   slider_look.fontinfo ->  (font, font_ascent, font_descent);
                #
                offset = slider_look.offset;
                string = int_to_string value;

                ((xc::text_extents font string).overall_info)
                    ->
                    xc::CHAR_INFO { right_bearing, ascent, descent, ... };

                y = max((val_to_pt value) + (font_ascent / 2), offset+ascent);
                y = min (y, high - offset - descent);

                x = right - right_bearing;

                xc::draw_transparent_string dr pen font ({ col=>x, row=>y }, string);
            };

                                                                                # Draw one tickmark on a horizontal slider, labelled by its numeric value -- called by draw_ticks().
        fun draw_hvalue                                                         # Convert int 'value' to string and draw it right-justified
                (val_to_pt, wide, dr, pen, slider_look:  Slider_Look)
                (value, bottom)
            =
            {   slider_look.fontinfo ->  (font, _, font_descent);
                #
                string = int_to_string value;

                ((xc::text_extents font string).overall_info)
                    ->
                    xc::CHAR_INFO { left_bearing=>lb, right_bearing=>rb, ... };

                y = bottom - font_descent;
                offset = slider_look.offset;

                x = max((val_to_pt value) - (lb + rb) / 2, lb + offset);
                x = min (x, wide - offset - rb);

                xc::draw_transparent_string dr pen font ({ col=>x, row=>y }, string);
            };

        fun vdrawf (window, size as { wide, high }, slider_look:  Slider_Look)
            =
            draw
            where 

#               include package   xdraw;                                        # xdraw         is from   src/lib/x-kit/xclient/xclient.pkg

                drawable =  xc::drawable_of_window  window;
                fd       =  xc::make_unbuffered_drawable  drawable;             # "fd" might be "fast drawable" or some such...?
                offset   =  slider_look.offset;

                border_thickness =  slider_look.border_thickness;

                val_to_pt =  val_to_pt (size, slider_look);
                text_pen  =  xc::make_pen [xc::p::FOREGROUND (xc::rgb8_from_rgb  slider_look.foreground_color)];

                draw_vvalue = draw_vvalue (val_to_pt, high, drawable, text_pen, slider_look);

                slider_look.fontinfo ->  (font, font_ascent, font_descent);

                label_wide = case slider_look.label                             # Figure horizontal pixels taken by slider title.
                                THE(_, lb, rb) => rb - lb + font_ascent;        # " + font_ascent" ???
                                NULL => 0;
                            esac;

                tick_width =  slider_look.tick_width;                           # Horizontal pixels taken by a tickmark.

                tick_wide  =  slider_look.tick != 0   ??  tick_width  ::  0;
                value_wide =  slider_look.show_value  ??  tick_width  ::  0;    # Are we assuming values have same horizontal pixels as a tickmark...??

                # Layout consists of four columns. Left-to-right:
                #  1: Tickmarks with numeric labels above them.
                #  2: Current value of slider, written to left of slider.
                #  3: Gutter with thumb sliding up and down in it.
                #  4: Title ("label") for widget.

                # Compute total width of all the stuff
                # we're committed to drawing:
                #
                total = tick_wide                                               # Leftmost is tickmark.
                      + value_wide                                              # Next numeric value for thumb written to left of thumb.
                      + 2 * (border_thickness+spacing)                          # Next come the two sides of the gutter and between them
                      + slider_look.width                                       # the thumb.
                      + label_wide                                              # Rightmost is title ("label") for the slider widget.
                      ;

                # We'll center our stuff in the available space:
                #
                tick_right  = (wide - total) / 2 + tick_wide;                   # Figure column in which ticks end. Total left-over pixels for margin are (wide-total); we'll put half on the left and half on the right.
                value_right = tick_right + value_wide;                          # Figure column in which numeric label for thumb ends.

                scale_left = value_right + spacing;                             # We'll draw the gutter 'spacing' pixels to the right of the thumb-value column.
                label_left = scale_left + 2*border_thickness                    # The thumb is slider_look.width pixels wide, with on each side of it border_thickness pixels of gutter box.
                                  + slider_look.width + (font_ascent / 2);      # We'll draw the slider title/label font_ascent/2 pixels to right of gutter.

                fun draw_ticks 0                                                # Draw referece tickmarks along the slider, labelled with their values right above them.
                        =>
                        ();

                    draw_ticks delta
                        =>
                        loop from_v
                        where
                            to_v   = slider_look.to_v;
                            from_v = slider_look.from_v;

                            stop = if (from_v <= to_v)  \\ v = to_v < v;
                                   else                 \\ v = to_v > v;
                                   fi;

                            fun loop v
                                =
                                if (not (stop v))
                                    draw_vvalue (v, tick_right);
                                    loop (v+delta);
                                fi;
                        end;
                end;

                fun draw_label NULL                                             # Draw the text title for the slider at upper-right.
                        =>
                        ();

                    draw_label (THE (string, _, _))
                        =>
                        {   col = label_left;
                            row = offset + (3*font_ascent) / 2;

                            xc::draw_transparent_string drawable text_pen font ({ col, row }, string);
                        };
                end;

                fun draw_value (value, dont_erase)                              # Draw current numeric value of slider to left of slider.
                    =
                    {   if (not dont_erase)
                            #
                            box = { col=>  value_right - value_wide,   wide=> value_wide,
                                    row=>  offset,                     high=> high - 2*offset
                                  };

                            xc::clear_box drawable box; 
                        fi;

                        draw_vvalue (value, value_right);
                    };

                fun init_window ()
                    =
                    {   xc::clear_drawable  drawable;
                        #
                        draw_ticks slider_look.tick;                            # Draw ticks and title -- they never change.
                        draw_label slider_look.label;
                    };

                fun draw_slider (value, ready, down, do_all)
                    =
                    {   include package   three_d;
                        #
                        width = slider_look.width;                              # Width-in-pixels of thumb.
                        border_thickness = slider_look.border_thickness;        # Width-in-pixels of gutter wall.

                        shades = slider_look.shades;

                        slide_shades =  if ready  slider_look.ready_shades;
                                        else      slider_look.slide_shades;
                                        fi;

                        fun draw_inset (x, y, w, h, sw, rel)                                                    # Draw two smaller islands inside the thumb to give it some texture.
                            =
                            {   x = x +   sw;
                                y = y +   sw;

                                h = h -   sw;
                                w = w - 2*sw;

                                box  = { col=>x, row=>y,   wide=>w, high=>h };
                                box' = { col=>x, row=>y+h, wide=>w, high=>h };

                                draw_filled_box drawable  { box=>box , width=>sw, relief=>rel } slide_shades;
                                draw_filled_box fd        { box=>box', width=>sw, relief=>rel } slide_shades;
                            };

                        fun draw_slide ()                                                                       # Draw the main thumb outline at appropriate spot.
                            =
                            {   sht2 = slider_look.thumb / 2;                                                   # "sht2" == "1/2 slider height".
                                swid = width;                                                                   # "swid" == "slider_width".

                                col = scale_left + border_thickness;                                            # Start col for thumb.
                                row = (val_to_pt value) - sht2;                                                 # Start row for thumb. Subtracting  sht2 puts midpoint of thumb squarely on 'value'-derived pixel.

                                shadow_width = max (1, border_thickness / 2);

                                relief = if down  wg::SUNKEN; else wg::RAISED;fi;                               # <============

                                box = { col, row, wide=>swid, high=>2*sht2 };                                   # Thumb outline.

                                draw_box  drawable  { box, width=>border_thickness, relief }  slide_shades;     # Draw thumb proper within gutter.

                                draw_inset (col, row, swid, sht2, shadow_width, relief);
                            };

                          if do_all
                              # 
                              box =     { col=>scale_left,
                                          row=>offset,
                                          high=>high - 2*offset,
                                          wide=> width + 2*border_thickness
                                        };

                              draw_box drawable { box, width=>border_thickness, relief=>wg::SUNKEN } shades;
                          else
                              box =   { col  => scale_left+border_thickness,
                                        row  => offset+border_thickness,
                                        #       
                                        high => high - 2*(border_thickness+offset),
                                        wide => width
                                      };

                             xc::clear_box  drawable  box; 
                          fi;

                          draw_slide ();
                      };

                fun draw ((value, active, ready, down), do_all)
                    =
                    {   if do_all  init_window(); fi;                                                   # Draw ticks and label -- these never change.
                        #
                        if slider_look.show_value  draw_value (value, do_all); fi;                      # Draw value of slider as numeric text.

                        draw_slider (value, ready, down, do_all);

                        if do_all  draw_border (offset, drawable, wide, high, slider_look); fi;
                    };
            end;

        fun hdrawf (window, size as { wide, high }, slider_look:  Slider_Look)
            =
            {   drawable  =  xc::drawable_of_window window;
                fd        =  xc::make_unbuffered_drawable drawable;                     # "fd" may be "fast drawable"

                offset    =  slider_look.offset;
                val_to_pt =  val_to_pt (size, slider_look);

                text_pen    =  xc::make_pen [xc::p::FOREGROUND (xc::rgb8_from_rgb  slider_look.foreground_color)];
                draw_hvalue =  draw_hvalue (val_to_pt, wide, drawable, text_pen, slider_look);

                slider_look.fontinfo ->   (font, font_ascent, font_descent);

                line_high = font_ascent + font_descent;
                tick_height  = if (slider_look.tick != 0) line_high; else 0;fi;
                value_height = if slider_look.show_value  line_high + spacing; else 0;fi;

                label_height
                    =
                    case slider_look.label
                        #       
                        NULL =>  0;
                        _    =>  line_high;
                    esac;

                border_thickness = slider_look.border_thickness;

                # Layout here is four rows.  Top-to-bottom:
                #  1. Title ("label") for slider widget.
                #  2. Gutter with thumb sliding in it.
                #  3. Value of slider.
                #  4. Ticks, with numeric labels.


                total = tick_height + value_height + 2*border_thickness + slider_look.width
                              + label_height;

                ticky = (high + total) / 2 - 1;

                valuey = ticky  -  tick_height;
                scaley = valuey - value_height;

                labely = scaley - 2*border_thickness - slider_look.width;

                fun draw_ticks 0
                        =>
                        ();

                    draw_ticks delta
                        =>
                        loop from_v
                        where
                            to_v   =  slider_look.to_v;
                            from_v =  slider_look.from_v;

                            stop = if (from_v <= to_v)  \\ v =  to_v < v; 
                                   else                 \\ v =  to_v > v;
                                   fi;

                            fun loop v
                                =
                                if (not (stop v))
                                    #
                                    draw_hvalue (v, ticky);
                                    loop (v+delta);
                                fi;
                        end;
                end;

                fun draw_label NULL
                        =>
                        ();

                    draw_label (THE (string, lb, rb))
                        =>
                        {   col = offset + font_ascent / 2;
                            row = labely - font_descent;

                            xc::draw_transparent_string drawable text_pen font ({ col, row }, string);
                        };
                end;

                fun init_window ()
                    =
                    {   xc::clear_drawable drawable;
                        #
                        draw_ticks slider_look.tick;
                        draw_label slider_look.label;
                    };

                fun draw_value (value, do_not_erase)
                    =
                    {
                        if (not do_not_erase)
                            #
                            box =   { col=> offset,
                                      row=> scaley + 1,

                                      wide=> wide - 2*offset, 
                                      high=> valuey - scaley
                                    };

                            xc::clear_box  drawable  box; 
                        fi;

                        draw_hvalue (value, valuey);
                    };

                fun draw_slider (value, ready, down, do_all)
                    =
                    {   include package   three_d;
                        #
                        width = slider_look.width;
                        border_thickness = slider_look.border_thickness;

                        y = scaley - 2*border_thickness - width + 1;

                        shades = slider_look.shades;

                        slide_shades = if ready  slider_look.ready_shades;
                                       else      slider_look.slide_shades;
                                       fi;

                        fun draw_inset (x, y, w, h, sw, rel)                                                                    # Draw two smaller islands inside the thumb to give it some texture.
                            =
                            {   x = x+sw;
                                y = y+sw;

                                w = w -   sw;
                                h = h - 2*sw;

                                r  = { col=>x,   row=>y, wide=>w, high=>h };
                                r' = { col=>x+w, row=>y, wide=>w, high=>h };

                                draw_filled_box  drawable  { box=>r , width=>sw, relief=>rel }  slide_shades;
                                draw_filled_box  fd        { box=>r', width=>sw, relief=>rel }  slide_shades;
                            };

                        fun draw_slide ()                                                                                       # Draw the main thumb outline at appropriate spot.
                            =
                            {   slider_wide2 =  slider_look.thumb / 2;                                                          # Half of the full thumb length. Useful for putting the middle of thumb exactly on value-appropriate pixel.
                                slider_high =  width;

                                x = (val_to_pt value) - slider_wide2;                                                           # Where to put middle of thumb.

                                shadow_width = max (1, border_thickness / 2);

                                y = y + border_thickness;

                                relief =  down  ??  wg::SUNKEN
                                                ::  wg::RAISED;

                                r = { col=>x, row=>y, wide=> 2*slider_wide2, high=>slider_high };

                                draw_box  drawable  { box=>r, width=>border_thickness, relief }  slide_shades;                  # Draw main outline of thumb.

                                draw_inset (x, y, slider_wide2, slider_high, shadow_width, relief);                             # Draw two islands within thumb to provide texture.
                            };

                          if do_all
                              #
                              box =   { col=>offset,
                                        row=>y,
                                        wide=>wide - 2*offset,
                                        high=> width + 2*border_thickness
                                      };

                              draw_box  drawable  { box, width=>border_thickness, relief=>wg::SUNKEN }  shades;
                          else
                              box = { col=>offset+border_thickness,
                                      row=>y+border_thickness,
                                      wide=>wide - 2*(border_thickness+offset),
                                      high=> width
                                    };

                              xc::clear_box  drawable  box; 
                          fi;

                          draw_slide ();
                      };

                fun draw ((value, active, ready, down), do_all)
                    =
                    {   if do_all   init_window ();   fi;
                        #
                        if slider_look.show_value   draw_value (value, do_all);   fi;

                        draw_slider (value, ready, down, do_all);

                        if do_all  draw_border (offset, drawable, wide, high, slider_look);     fi;
                    };

                draw;
            };

        exception BAD_RANGE;

        fun pt_to_val (size, slider_look:  Slider_Look)
            =
            {   slider_look ->  { is_vertical, thumb, border_thickness, offset, from_v, to_v, ... };
                #
                size ->  { wide, high };

                l =    is_vertical  ??  high  ::  wide;

                range = l - thumb - 2*(offset + border_thickness);
                prange = float range;

                inset = thumb / 2 + offset + border_thickness;
                rrange = float (to_v-from_v);

                fun make_var v
                    =
                    {   value = min (max (0, v - inset), range);
                        tmp = ((float value)*rrange)/prange + (float from_v);
                        trunc (if (tmp < 0.0 ) tmp - 0.5; else tmp + 0.5;fi);
                    };

                if   (range <= 0) \\ _                          =  raise exception BAD_RANGE;
                elif is_vertical  \\ ({ row, ... }: g2d::Point) =  make_var row;
                else              \\ ({ col, ... }: g2d::Point) =  make_var col;
                fi;
            };


        fun size_preference_thunk_of (slider_look:  Slider_Look)
            =
            if slider_look.is_vertical  vbounds_of  slider_look;
            else                        hbounds_of  slider_look;
            fi;


        fun make_slider_drawfn (arg as (_, _, slider_look:  Slider_Look))
            =
            if slider_look.is_vertical  vdrawf arg;
            else                        hdrawf arg;
            fi;

    };                  # package slider_look 

end;


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext