PreviousUpNext

15.4.1517  src/lib/x-kit/widget/old/leaf/labelbutton-look.pkg

## labelbutton-look.pkg
#
# Basic labeled button view.

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




# This package gets used in:
#
#     src/lib/x-kit/widget/old/leaf/pushbuttons.pkg
#     src/lib/x-kit/widget/old/leaf/toggleswitches.pkg

stipulate
    include package   threadkit;                                        # threadkit                     is from   src/lib/src/lib/thread-kit/src/core-thread-kit/threadkit.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
    package wt =  widget_types;                                         # widget_types                  is from   src/lib/x-kit/widget/old/basic/widget-types.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
herein

    package labelbutton_look
    : (weak)     Button_Look                                            # Button_Look                   is from   src/lib/x-kit/widget/old/leaf/button-look.api
    {
        Label_Type =  TEXT  String
                   |  ICON  xc::Ro_Pixmap
                   ;

    # 2010-01-09 CrT: Commented out because unused.
    #    Plea_Mail
    #      = SET_LABEL  Label_Type
    #      #
    #      | SET_BC     xc::Color
    #      | SET_FC     xc::Color
    #      #
    #      | GET_SIZE_CONSTRAINT  Oneshot_Maildrop( wg::Bounds )
    #      #
    #      | DO_REALIZE  {
    #          kidplug:  xinputt::Kidplug,
    #          window:   xc::Window,
    #          size:     g2d::Size
    #        };

        Label_Data
          =  TXT  { s:  String, rb:  Int, lb:  Int }
          | ICON  xc::Ro_Pixmap
          ;

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

               (font, font_ascent, font_descent);
            };

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

                TXT { s, lb, rb };
            };

        fun size_of_label (ICON ro_pixmap, _)
                =>
                xc::size_of_ro_pixmap ro_pixmap;

            size_of_label (TXT { lb, rb, ... }, (_, fa, fd))
                =>
                { wide => rb - lb + 2, high => fa + fd + 2 };
        end;

        Light_Type = RADIO_LIGHT | CHECK_LIGHT;


        fun cvt_light "radio" => THE RADIO_LIGHT;
            cvt_light "check" => THE CHECK_LIGHT;
            cvt_light _       => NULL;
        end;


        Light = { space:  Int, 
                  size:   Int, 
                  #
                  ltype:  Light_Type, 
                  color:  xc::Rgb
                };


        fun make_light (NULL, _, _, _, _)
                =>
                NULL;

            make_light (THE lt, ICON ro_pixmap, height, _, color)
                =>
                {   (xc::size_of_ro_pixmap  ro_pixmap)
                        ->
                        { wide, high };

                    high = if (height > 0)  height;
                           else             high;
                           fi;

                    size =   case lt
                                 #
                                 CHECK_LIGHT => (65*high) / 100;
                                 RADIO_LIGHT => (75*high) / 100;
                             esac;

                    THE { ltype=>lt, space=>high, size, color };
                };

            make_light (THE lt, _, _, (font, font_ascent, font_descent), color)
                =>
                {   size =  case lt
                                 CHECK_LIGHT => (80*(font_ascent + font_descent)) / 100;
                                 RADIO_LIGHT =>      font_ascent + font_descent;
                            esac;

                    high = size + (xc::text_width font "0");

                    THE { ltype=>lt, space=>high, size, color };
                };
        end;

        Button_Look
            =
            BUTTON_LOOK
              { light:  Null_Or( Light ), 
                label:  Label_Data, 
                relief:  wg::Relief,
                #
                fg:      xc::Rgb, 
                bg:      xc::Rgb, 
                readyc:  xc::Rgb, 
                #
                shades:  wg::Shades,
                stipple:  xc::Ro_Pixmap,
                border_thickness:  Int,
                #
                font:  (xc::Font, Int, Int),
                align:  wt::Horizontal_Alignment,
                #
                width:  Int,
                height: Int,
                padx:   Int,
                pady:   Int
              };

        default_font = "-Adobe-Helvetica-Bold-R-Normal--*-120-*";


        attributes
            =
            [ (wa::halign,         wa::HALIGN,     wa::HALIGN_VAL  wt::HCENTER),
              (wa::tile,           wa::TILE,       wa::NO_VAL),
              (wa::label,          wa::STRING,     wa::STRING_VAL ""),
              (wa::type,           wa::STRING,     wa::STRING_VAL "NoLight"),
              (wa::border_thickness,   wa::INT,        wa::INT_VAL 2),
              (wa::height,         wa::INT,        wa::INT_VAL 0),
              (wa::width,          wa::INT,        wa::INT_VAL 0),
              (wa::padx,           wa::INT,        wa::INT_VAL 1),
              (wa::pady,           wa::INT,        wa::INT_VAL 1),
              (wa::font,           wa::FONT,       wa::STRING_VAL default_font),
              (wa::relief,         wa::RELIEF,     wa::RELIEF_VAL wg::RAISED),
              (wa::foreground,     wa::COLOR,      wa::STRING_VAL "black"),
              (wa::color,          wa::COLOR,      wa::NO_VAL),
              (wa::ready_color,    wa::COLOR,      wa::NO_VAL),
              (wa::background,     wa::COLOR,      wa::STRING_VAL "white")
            ];


        fun make_button_look (root, view, args)
            =
            {   attributes = wg::find_attribute (wg::attributes (view, attributes, args));
                #
                ltype  = wa::get_string (attributes wa::type);
                align  = wa::get_halign (attributes wa::halign);

                bw     = wa::get_int (attributes wa::border_thickness);

                height = wa::get_int (attributes wa::height);
                width  = wa::get_int (attributes wa::width);

                padx   = wa::get_int (attributes wa::padx);
                pady   = wa::get_int (attributes wa::pady);

                (make_font_info (wa::get_font (attributes wa::font)))
                    ->
                    font as (f, _, _);

                label = ICON (wa::get_tile (attributes wa::tile))
                              except _ = make_text_label (wa::get_string (attributes wa::label), f);

                relief = wa::get_relief (attributes wa::relief);
                lab    = wa::get_string (attributes wa::label);

                fg     = wa::get_color (attributes wa::foreground);
                bg     = wa::get_color (attributes wa::background);

                readyc = case (wa::get_color_opt (attributes wa::ready_color))   
                             NULL => bg;
                             THE c => c;
                         esac;

                set_color = case (wa::get_color_opt (attributes wa::color))   
                                #
                                NULL => fg;
                                THE c => c;
                            esac;

                light = make_light (cvt_light ltype, label, height, font, set_color);

                BUTTON_LOOK {
                  light,
                  label,
                  relief,
                  stipple => wg::ro_pixmap root "gray",
                  fg,
                  bg,
                  shades => wg::shades root bg,
                  readyc,
                  border_thickness => int::max (0, bw),
                  font,
                  align,

                  width  => int::max (0, width),
                  height => int::max (0, height),

                  padx   => int::max (0, padx),
                  pady   => int::max (0, pady)
                };
              };

        fun bounds (BUTTON_LOOK v)
            =
            {   v ->  { label, border_thickness, width, height, padx, pady, font, ... };
                #
                light_space = case v.light
                                  #
                                  NULL => 0;
                                  THE { space, ... } => space;
                              esac;

                (size_of_label (label, font))
                    ->
                    { wide, high };

                wide = if (width > 0)   width;
                       else             (2*border_thickness + 2*padx + light_space + wide);
                       fi;

                high = if (height > 0)  height;
                       else             (2*border_thickness + 2*pady + high);
                       fi;

                col_preference =  wg::loose_preference  wide;
                row_preference =  wg::loose_preference  high;

                { col_preference,
                  row_preference
                };
            };

        fun make_button_drawfn (BUTTON_LOOK v, window, { wide, high } )
            =
            {   dr =  xc::drawable_of_window  window;
                #
                v ->  { light, shades, label, border_thickness=>bw, fg, bg, readyc, ... };

                box  = { col=>0, row=>0, wide, high };

                xoff = bw + v.padx;

                back_pen     =  xc::make_pen [xc::p::FOREGROUND (xc::rgb8_from_rgb bg)];
                ready_pen    =  xc::make_pen [xc::p::FOREGROUND (xc::rgb8_from_rgb readyc)];
                normal_pen   =  xc::make_pen [xc::p::FOREGROUND (xc::rgb8_from_rgb fg), xc::p::BACKGROUND (xc::rgb8_from_rgb  bg)];
                inactive_pen =  xc::make_pen [xc::p::FOREGROUND (xc::rgb8_from_rgb fg)];

                inactive_pen =  xc::make_pen
                                  [ xc::p::FOREGROUND (xc::rgb8_from_rgb fg),
                                    xc::p::BACKGROUND (xc::rgb8_from_rgb bg),
                                    xc::p::FILL_STYLE_STIPPLED,
                                    xc::p::STIPPLE v.stipple
                                  ];

                lightspace
                    =
                    case light
                        #
                        NULL => 0;
                        THE { space, ... } => space;
                    esac;


                fun draw_radio (pen, size) is_on
                    =
                    {   ystart = high / 2;
                        half = size / 2;

                        ps = [ { col=>xoff,      row=>ystart },
                               { col=>xoff+half, row=>ystart+half },
                               { col=>xoff+size, row=>ystart },
                               { col=>xoff+half, row=>ystart-half }
                             ];

                        if is_on   xc::fill_polygon dr pen { verts=>ps, shape=>xc::CONVEX_SHAPE };   fi;

                        d3::draw_poly dr { pts=>ps, width=>bw, relief=>wg::RAISED } shades;
                    };


                fun draw_check (pen, size) is_on
                    =
                    {   r = { col=>xoff, row=> (high - size) / 2, wide => size, high => size };

                        if is_on   xc::fill_box dr pen r;   fi;

                        d3::draw_box dr { box=>r, width=>bw, relief=>wg::SUNKEN } shades;
                    };

                draw_label
                    =
                    case label
                        #
                        ICON ro_pixmap
                            =>
                            {   (xc::size_of_ro_pixmap ro_pixmap)
                                    ->
                                    { wide=>twid, high=>tht };

                                sr = { col=>0, row=>0, wide=>twid, high=>tht };

                                x = case v.align
                                        #
                                        wt::HLEFT   =>  xoff + lightspace;
                                        wt::HRIGHT  =>  wide - xoff - twid;
                                        wt::HCENTER => (wide + lightspace - twid) / 2;
                                    esac;

                                y = (high - tht) / 2;

                                arg = { from=> xc::FROM_RO_PIXMAP ro_pixmap, from_box=>sr, to_pos=>{ col=>x, row=>y }};

                                \\ pen =    {   xc::bitblt dr pen arg;
                                                #
                                                ();
                                            };
                            };

                        TXT { s, lb, rb }
                            =>
                            {   v.font ->  (font, font_ascent, font_descent);
                                #
                                pen =  xc::make_pen [xc::p::FOREGROUND (xc::rgb8_from_rgb fg)];

                                col = case v.align   
                                          #
                                          wt::HLEFT   =>   xoff + lightspace - lb + 1;
                                          wt::HRIGHT  =>   wide - xoff - rb - 1;
                                          wt::HCENTER =>  (wide + lightspace - lb - rb) / 2;
                                      esac;

                                row = (high + font_ascent - font_descent) / 2;

                                \\ pen =    xc::draw_transparent_string
                                                dr
                                                pen
                                                font
                                                ({ col, row },  s);
                            };
                    esac;

                fun setf { button_state => wt::INACTIVE s, ... }
                        =>
                        {   rel =   s  ??  wg::SUNKEN
                                       ::  v.relief;

                            xc::fill_box dr back_pen box;

                            draw_label inactive_pen;

                            d3::draw_box dr { box, relief=>rel, width=>bw } shades;
                         };

                    setf { button_state => wt::ACTIVE s, has_mouse_focus, mousebutton_is_down }
                        =>
                        {   backpen = if has_mouse_focus  ready_pen;
                                      else                back_pen;
                                      fi;

                            relief =  (s == mousebutton_is_down)  ??   v.relief
                                                                  ::   wg::SUNKEN;

                            xc::fill_box dr backpen box;

                            draw_label normal_pen;

                            d3::draw_box dr { box, relief, width=>bw } shades;
                        };
                end;

                fun lsetf draw_light { button_state => wt::INACTIVE s, ... }
                        =>
                        {   rel = v.relief;
                            #
                            xc::fill_box dr back_pen box;

                            draw_label inactive_pen;
                            draw_light s;

                            d3::draw_box dr { box, relief=>rel, width=>bw } shades;
                        };

                    lsetf draw_light { button_state => wt::ACTIVE s, has_mouse_focus, mousebutton_is_down }
                        =>
                        {   backpen = if has_mouse_focus  ready_pen;
                                      else                back_pen;
                                      fi;

                            relief =    mousebutton_is_down  ??  wg::SUNKEN
                                                             ::  v.relief;

                            xc::fill_box dr backpen box;
                            draw_label normal_pen;
                            draw_light s;
                            d3::draw_box dr { box, relief, width=>bw } shades;
                        };
                end;


                case light 
                    #
                    NULL => setf;
                    #
                    THE { ltype => CHECK_LIGHT, size, color, ... }
                        => 
                        lsetf (draw_check (xc::make_pen [xc::p::FOREGROUND (xc::rgb8_from_rgb color)], size));

                    THE { ltype => RADIO_LIGHT, size, color, ... }
                        => 
                        lsetf (draw_radio (xc::make_pen [xc::p::FOREGROUND (xc::rgb8_from_rgb color)], size));
                esac;
            };

        fun window_args (BUTTON_LOOK { bg, ... } )
            =
            { background => THE bg };

    };                                                                                  # package labelbutton_look 

end;


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext