PreviousUpNext

15.4.1528  src/lib/x-kit/widget/old/leaf/textbutton-look.pkg

## textbutton-look.pkg
#
# View for text buttons.

# 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
    package g2d =  geometry2d;                                          # geometry2d            is from   src/lib/std/2d/geometry2d.pkg
    #
    package xc  =  xclient;                                             # xclient               is from   src/lib/x-kit/xclient/xclient.pkg
    #
    package car =  cartouche;                                           # cartouche             is from   src/lib/x-kit/draw/cartouche.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
herein

    package textbutton_look
    : (weak)    Button_Look                                             # Button_Look           is from   src/lib/x-kit/widget/old/leaf/button-look.api
    {
        default_font_name = "8x13";
        #
        attributes
            =
            [ (wa::halign,       wa::HALIGN,  wa::HALIGN_VAL wt::HCENTER),
              (wa::rounded,      wa::BOOL,    wa::BOOL_VAL FALSE),
              (wa::width,        wa::INT,     wa::NO_VAL),
              (wa::height,       wa::INT,     wa::NO_VAL),
              (wa::border_thickness, wa::INT,     wa::INT_VAL 2),
              (wa::label,        wa::STRING,  wa::STRING_VAL ""),
              (wa::font,         wa::FONT,    wa::STRING_VAL default_font_name),
              (wa::color,        wa::COLOR,   wa::NO_VAL),
              (wa::background,   wa::COLOR,   wa::STRING_VAL "white"),
              (wa::foreground,   wa::COLOR,   wa::STRING_VAL "black")
            ];

        Fontdata
            =
            { font:          xc::Font,
              font_ascent:   Int,
              font_descent:  Int
            };

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

                { font, font_ascent, font_descent };
            };

        Labeldata
            =
            { label:  String,
              lb:     Int,                                              # 'lb' is apparently 'left bound'.
              rb:     Int                                               # 'rb' is apparently 'right bound'.  width == lb - rb.
            };

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

                { label=>s, lb, rb };
            };

         Button_Look
             =
             BUTTON_LOOK
               {
                 align:        wt::Horizontal_Alignment,
                 rounded:      Bool,
                 #
                 width:        Null_Or( Int ),
                 height:       Null_Or( Int ),
                 #
                 border_thickness: Int,
                 labeldata:    Labeldata,
                 fontdata:     Fontdata,
                 #
                 stipple:      xc::Ro_Pixmap,
                 shades:       wg::Shades,
                 #
                 forec:        xc::Rgb,
                 color:        xc::Rgb,
                 backc:        xc::Rgb
               };

        fun make_button_look (root, view, args)
            =
            {   attributes = wg::find_attribute (wg::attributes (view, attributes, args));
                #
                font  = wa::get_font (attributes wa::font);

                backc = wa::get_color (attributes wa::background);

                color = case (wa::get_color_opt (attributes wa::color))   
                            #
                            THE c =>  c;
                            _     =>  backc;
                        esac;

                BUTTON_LOOK
                  {
                    align   => wa::get_halign (attributes wa::halign),
                    rounded => wa::get_bool (attributes wa::rounded),

                    width   => wa::get_int_opt (attributes wa::width),
                    height  => wa::get_int_opt (attributes wa::height),

                    border_thickness =>  wa::get_int (attributes wa::border_thickness),
                    labeldata    =>  make_label (wa::get_string (attributes wa::label), font),

                    stipple =>  wg::ro_pixmap root "gray",
                    shades  =>  wg::shades root color,

                    fontdata => make_font font,
                    forec => wa::get_color (attributes wa::foreground),

                    color,
                    backc
                  };
              };

        pad  = 1;
        rpad = 4;

        fun configfn (BUTTON_LOOK v, window, size as { wide, high } )
            =
            drawf
            where 
                d = xc::drawable_of_window  window;
                #
                r = g2d::box::make (g2d::point::zero, size);

                v ->  { border_thickness, labeldata, fontdata, ... };

                text_pen = xc::make_pen [xc::p::FOREGROUND (xc::rgb8_from_rgb v.forec) ];

                inactive_text_pen
                    =
                    xc::clone_pen
                      ( text_pen,
                        [ xc::p::FILL_STYLE_STIPPLED,
                          xc::p::STIPPLE v.stipple
                        ]
                      );

                v.shades ->  { base, light, dark };

                xoff = border_thickness + pad;

                labeldata ->  { lb, rb, label };
                fontdata  ->  { font, font_ascent, font_descent };

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

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

                text_pt =  { col, row };
                border  =  d3::draw3drect d (r, border_thickness);

                fun draw (text_pen, back_pen, top_pen, bot_pen)
                    =
                    {   xc::fill_box d back_pen r;
                        xc::draw_transparent_string d text_pen font (text_pt, label);
                        border { top=>top_pen, bottom=>bot_pen };
                    };

                fun drawf { button_state => wt::ACTIVE   TRUE , mousebutton_is_down => FALSE, has_mouse_focus } =>  draw (         text_pen, base, dark,  light);
                    drawf { button_state => wt::ACTIVE   FALSE, mousebutton_is_down => FALSE, ...             } =>  draw (         text_pen, base, light, dark );
                    drawf { button_state => wt::ACTIVE   TRUE , mousebutton_is_down => TRUE , ...             } =>  draw (         text_pen, base, light, dark );
                    drawf { button_state => wt::ACTIVE   FALSE, mousebutton_is_down => TRUE , ...             } =>  draw (         text_pen, base, dark,  light);
                    drawf { button_state => wt::INACTIVE TRUE , ...                                           } =>  draw (inactive_text_pen, base, dark,  light);
                    drawf { button_state => wt::INACTIVE FALSE, ...                                           } =>  draw (inactive_text_pen, base, light, dark );
                end;
            end;

        fun rconfigfn (BUTTON_LOOK v, window, size as { wide, high } )                                  # The "r" may be for "rounded" -- notice use of 'cartouche' and 'draw3dround_box'
            =
            drawf
            where 

                d =  xc::drawable_of_window  window;

                r = { col  => 0,
                      row  => 0,
                      wide => wide - 1,
                      high => high - 1
                    };

                corner_radius = int::min (10, int::min (wide, high) / 6);

                v ->  { backc, color, border_thickness, labeldata, fontdata, ... };

                text_pen =  xc::make_pen [xc::p::FOREGROUND (xc::rgb8_from_rgb v.forec) ];

                inactive_text_pen
                    =
                    xc::clone_pen
                      ( text_pen,
                        [ xc::p::FILL_STYLE_STIPPLED,
                          xc::p::STIPPLE v.stipple
                        ]
                      );

                v.shades  ->  { base, light, dark };
                labeldata ->  { lb, rb, label };
                fontdata  ->  { font_ascent, font_descent, font };

                text_pt =    { col=> (wide - lb - rb)                    / 2,
                               row=> (high + font_ascent - font_descent) / 2
                             };

                fun draw (text_pen, back_pen, top_pen, bot_pen)
                    =
                    {   xc::clear_drawable d;
                        #
                        if (not (xc::same_rgb (backc, color)))
                            #
                            car::fill_cartouche d base { box=>r, corner_radius };
                        fi;

                        xc::draw_transparent_string d text_pen font (text_pt, label);

                        d3::draw3dround_box d 
                            { box=>r, c_wid=>corner_radius, c_ht=>corner_radius, width=>border_thickness }
                            { top=>top_pen, bottom=>bot_pen };
                    };

                fun drawf { button_state => wt::ACTIVE   TRUE,  mousebutton_is_down => FALSE, has_mouse_focus } =>  draw (         text_pen, base, dark, light);
                    drawf { button_state => wt::ACTIVE   FALSE, mousebutton_is_down => FALSE, ...             } =>  draw (         text_pen, base, light, dark);
                    drawf { button_state => wt::ACTIVE   TRUE,  mousebutton_is_down => TRUE,  ...             } =>  draw (         text_pen, base, light, dark);
                    drawf { button_state => wt::ACTIVE   FALSE, mousebutton_is_down => TRUE,  ...             } =>  draw (         text_pen, base, dark, light);
                    drawf { button_state => wt::INACTIVE TRUE,  ...                                           } =>  draw (inactive_text_pen, base, dark, light);
                    drawf { button_state => wt::INACTIVE FALSE, ...                                           } =>  draw (inactive_text_pen, base, light, dark);
                end;
            end;

        fun bounds (BUTTON_LOOK v)
            =
            {   v ->  { rounded, border_thickness, labeldata, fontdata, ... };
                #
                inset = border_thickness + (if rounded  rpad; else pad;fi);

                labeldata ->  { lb, rb, ... };
                fontdata  ->  { font_ascent, font_descent, ... };

                lwid = rb - lb;
                lht = font_ascent + font_descent;

                col = case v.width   
                          THE w => w;
                          NULL  => lwid + 2*inset;
                      esac;

                row = case v.height   
                          THE h => h;
                          NULL  => lht + 2*inset;
                      esac;

                { col_preference =>  wg::loose_preference  col,
                  row_preference =>  wg::loose_preference  row
                };
            };

        fun make_button_drawfn (arg as (BUTTON_LOOK { rounded=>TRUE, ... }, window, size))
                =>
                rconfigfn arg;

            make_button_drawfn arg
                =>
                configfn arg;
        end;


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

    };                                          # package textbutton_look

end;


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext