PreviousUpNext

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

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

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






###                        "We in science are spoiled by the success of mathematics.
###                         Mathematics is the study of problems so simple
###                         that they have good solutions."
###
###                                                   -- Whitfield Diffie 


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

stipulate
    package xg  =  xgeometry;                                           # xgeometry             is from   src/lib/std/2d/xgeometry.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/lib/three-d.pkg
    package wg  =  widget;                                              # widget                is from   src/lib/x-kit/widget/basic/widget.pkg
    package wa  =  widget_attribute;                                    # widget_attribute      is from   src/lib/x-kit/widget/lib/widget-attribute.pkg
    package wt  =  widget_types;                                        # widget_types          is from   src/lib/x-kit/widget/basic/widget-types.pkg
herein

    package textbutton_look: (weak)  Button_Look {              # Button_Look   is from   src/lib/x-kit/widget/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
            =
            {   my  { ascent  => font_ascent,
                      descent => font_descent
                    }
                    =
                    xc::font_high font;

                { font, font_ascent, font_descent };
            };

        Labeldata
            =
            { label:  String,
              lb:     Int,
              rb:     Int
            };

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

                { 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 xg::SIZE { wide, high } )
            =
            drawf
            where 
                d = xc::drawable_of_window  window;

                r = xg::box::make (xg::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 =  xg::POINT { 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 xg::SIZE { wide, high } )
            =
            drawf
            where 

                d =  xc::drawable_of_window  window;

                r = xg::BOX { 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 =  xg::POINT
                             { 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 config (arg as (BUTTON_LOOK { rounded=>TRUE, ... }, window, size))
                =>
                rconfigfn arg;

            config 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