Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/ui/src/pbutton.c

    r3583ffb rb769ca0  
    11/*
    2  * Copyright (c) 2020 Jiri Svoboda
     2 * Copyright (c) 2026 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    3232/**
    3333 * @file Push button
     34 *
     35 * Push button either uses text as decoration, or it can use a caller-provided
     36 * function to paint the decoration.
    3437 */
    3538
     
    5154enum {
    5255        ui_pb_press_dx = 1,
    53         ui_pb_press_dy = 1
     56        ui_pb_press_dy = 1,
     57        ui_pb_pad_x = 2,
     58        ui_pb_pad_x_text = 1
    5459};
    5560
     
    111116
    112117        ui_control_delete(pbutton->control);
     118        free(pbutton->caption);
    113119        free(pbutton);
    114120}
     
    136142}
    137143
     144/** Set push button ops.
     145 *
     146 * These allow overriding the function for painting the button or
     147 * painting the button decoration.
     148 *
     149 * @param pbutton Push button
     150 * @param ops Push button ops
     151 * @param arg Decoration ops argument
     152 */
     153void ui_pbutton_set_ops(ui_pbutton_t *pbutton, ui_pbutton_ops_t *ops, void *arg)
     154{
     155        pbutton->ops = ops;
     156        pbutton->ops_arg = arg;
     157}
     158
     159/** Set push button flag.s
     160 *
     161 * @param pbutton Push button
     162 * @param flags Flags
     163 */
     164void ui_pbutton_set_flags(ui_pbutton_t *pbutton, ui_pbutton_flags_t flags)
     165{
     166        pbutton->flags = flags;
     167}
     168
    138169/** Set button rectangle.
    139170 *
     
    157188{
    158189        pbutton->isdefault = isdefault;
     190}
     191
     192/** Get button light status.
     193 *
     194 * @param pbutton Button
     195 * @return @c true iff light is on
     196 */
     197bool ui_pbutton_get_light(ui_pbutton_t *pbutton)
     198{
     199        return pbutton->light;
     200}
     201
     202/** Turn button light on or off.
     203 *
     204 * @param pbutton Button
     205 * @param light @c true iff button should be lit
     206 */
     207void ui_pbutton_set_light(ui_pbutton_t *pbutton, bool light)
     208{
     209        pbutton->light = light;
     210}
     211
     212/** Set push button caption.
     213 *
     214 * @param pbutton Button
     215 * @param caption New caption
     216 * @return EOK on success, ENOMEM if out of memory
     217 */
     218errno_t ui_pbutton_set_caption(ui_pbutton_t *pbutton, const char *caption)
     219{
     220        char *dcaption;
     221
     222        dcaption = str_dup(caption);
     223        if (dcaption == NULL)
     224                return ENOMEM;
     225
     226        free(pbutton->caption);
     227        pbutton->caption = dcaption;
     228        return EOK;
    159229}
    160230
     
    239309}
    240310
    241 /** Paint push button.
    242  *
    243  * @param pbutton Push button
    244  * @return EOK on success or an error code
    245  */
    246 errno_t ui_pbutton_paint(ui_pbutton_t *pbutton)
     311/** Paint button text shadow.
     312 *
     313 * @param pbutton Push button
     314 * @return EOK on success or an error code
     315 */
     316static errno_t ui_pbutton_paint_text_shadow(ui_pbutton_t *pbutton)
     317{
     318        gfx_rect_t rect;
     319        errno_t rc;
     320
     321        rect.p0.x = pbutton->rect.p0.x + 1;
     322        rect.p0.y = pbutton->rect.p0.y + 1;
     323        rect.p1.x = pbutton->rect.p1.x;
     324        rect.p1.y = pbutton->rect.p1.y;
     325
     326        rc = gfx_set_color(pbutton->res->gc, pbutton->res->btn_shadow_color);
     327        if (rc != EOK)
     328                goto error;
     329
     330        rc = gfx_fill_rect(pbutton->res->gc, &rect);
     331        if (rc != EOK)
     332                goto error;
     333
     334        return EOK;
     335error:
     336        return rc;
     337}
     338
     339/** Paint push button in graphic mode.
     340 *
     341 * @param pbutton Push button
     342 * @return EOK on success or an error code
     343 */
     344static errno_t ui_pbutton_paint_gfx(ui_pbutton_t *pbutton)
    247345{
    248346        gfx_coord2_t pos;
    249347        gfx_text_fmt_t fmt;
    250348        gfx_rect_t rect;
     349        gfx_rect_t irect;
    251350        gfx_coord_t thickness;
     351        gfx_color_t *color;
    252352        bool depressed;
    253353        errno_t rc;
     
    261361        rect.p1.y = pbutton->rect.p1.y - thickness;
    262362
    263         rc = gfx_set_color(pbutton->res->gc, pbutton->res->btn_face_color);
     363        color = pbutton->light ? pbutton->res->btn_face_lit_color :
     364            pbutton->res->btn_face_color;
     365
     366        rc = gfx_set_color(pbutton->res->gc, color);
    264367        if (rc != EOK)
    265368                goto error;
    266369
    267370        rc = gfx_fill_rect(pbutton->res->gc, &rect);
    268         if (rc != EOK)
    269                 goto error;
    270 
    271         rc = gfx_set_color(pbutton->res->gc, pbutton->res->btn_text_color);
    272371        if (rc != EOK)
    273372                goto error;
     
    282381        }
    283382
    284         gfx_text_fmt_init(&fmt);
    285         fmt.halign = gfx_halign_center;
    286         fmt.valign = gfx_valign_center;
    287 
    288         rc = gfx_puttext(pbutton->res->font, &pos, &fmt, pbutton->caption);
    289         if (rc != EOK)
    290                 goto error;
     383        if (pbutton->ops != NULL && pbutton->ops->decor_paint != NULL) {
     384                /* Custom decoration */
     385                rc = pbutton->ops->decor_paint(pbutton, pbutton->ops_arg,
     386                    &pos);
     387                if (rc != EOK)
     388                        goto error;
     389        } else {
     390                /* Text decoration */
     391                ui_paint_get_inset_frame_inside(pbutton->res, &rect, &irect);
     392                gfx_text_fmt_init(&fmt);
     393                fmt.font = pbutton->res->font;
     394                fmt.color = pbutton->res->btn_text_color;
     395                fmt.halign = gfx_halign_center;
     396                fmt.valign = gfx_valign_center;
     397                fmt.abbreviate = true;
     398                fmt.width = irect.p1.x - irect.p0.x - 2 * ui_pb_pad_x;
     399
     400                rc = gfx_puttext(&pos, &fmt, pbutton->caption);
     401                if (rc != EOK)
     402                        goto error;
     403        }
    291404
    292405        rc = ui_pbutton_paint_frame(pbutton);
     
    304417        }
    305418
     419        rc = gfx_update(pbutton->res->gc);
     420        if (rc != EOK)
     421                goto error;
     422
    306423        return EOK;
    307424error:
     
    309426}
    310427
     428/** Paint push button in text mode.
     429 *
     430 * @param pbutton Push button
     431 * @return EOK on success or an error code
     432 */
     433static errno_t ui_pbutton_paint_text(ui_pbutton_t *pbutton)
     434{
     435        gfx_coord2_t pos;
     436        gfx_text_fmt_t fmt;
     437        gfx_rect_t rect;
     438        bool depressed;
     439        errno_t rc;
     440
     441        if ((pbutton->flags & ui_pbf_no_text_depress) == 0)
     442                depressed = pbutton->held && pbutton->inside;
     443        else
     444                depressed = false;
     445
     446        rc = gfx_set_color(pbutton->res->gc, pbutton->res->wnd_face_color);
     447        if (rc != EOK)
     448                goto error;
     449
     450        rc = gfx_fill_rect(pbutton->res->gc, &pbutton->rect);
     451        if (rc != EOK)
     452                goto error;
     453
     454        rect.p0.x = pbutton->rect.p0.x + (depressed ? 1 : 0);
     455        rect.p0.y = pbutton->rect.p0.y;
     456        rect.p1.x = pbutton->rect.p1.x - 1 + (depressed ? 1 : 0);
     457        rect.p1.y = pbutton->rect.p0.y + 1;
     458
     459        rc = gfx_set_color(pbutton->res->gc, pbutton->res->btn_face_color);
     460        if (rc != EOK)
     461                goto error;
     462
     463        rc = gfx_fill_rect(pbutton->res->gc, &rect);
     464        if (rc != EOK)
     465                goto error;
     466
     467        /* Center of button rectangle */
     468        pos.x = (rect.p0.x + rect.p1.x) / 2;
     469        pos.y = (rect.p0.y + rect.p1.y) / 2;
     470
     471        gfx_text_fmt_init(&fmt);
     472        fmt.font = pbutton->res->font;
     473        fmt.color = pbutton->res->btn_text_color;
     474        fmt.halign = gfx_halign_center;
     475        fmt.valign = gfx_valign_center;
     476        fmt.abbreviate = true;
     477        fmt.width = rect.p1.x - rect.p0.x - 2 * ui_pb_pad_x_text;
     478        if (fmt.width < 1)
     479                fmt.width = 1;
     480
     481        rc = gfx_puttext(&pos, &fmt, pbutton->caption);
     482        if (rc != EOK)
     483                goto error;
     484
     485        if (!depressed) {
     486                rc = ui_pbutton_paint_text_shadow(pbutton);
     487                if (rc != EOK)
     488                        goto error;
     489        }
     490
     491        rc = gfx_update(pbutton->res->gc);
     492        if (rc != EOK)
     493                goto error;
     494
     495        return EOK;
     496error:
     497        return rc;
     498}
     499
     500/** Paint push button.
     501 *
     502 * @param pbutton Push button
     503 * @return EOK on success or an error code
     504 */
     505errno_t ui_pbutton_paint(ui_pbutton_t *pbutton)
     506{
     507        if (pbutton->ops != NULL && pbutton->ops->paint != NULL) {
     508                /* Custom paint routine */
     509                return pbutton->ops->paint(pbutton, pbutton->ops_arg);
     510        } else if (pbutton->res->textmode) {
     511                return ui_pbutton_paint_text(pbutton);
     512        } else {
     513                return ui_pbutton_paint_gfx(pbutton);
     514        }
     515}
     516
    311517/** Press down button.
    312518 *
     
    321527        pbutton->held = true;
    322528        (void) ui_pbutton_paint(pbutton);
     529        ui_pbutton_down(pbutton);
    323530}
    324531
     
    333540
    334541        pbutton->held = false;
     542        ui_pbutton_up(pbutton);
    335543
    336544        if (pbutton->inside) {
     
    368576}
    369577
    370 /** Button was clicked.
     578/** Send button clicked event.
    371579 *
    372580 * @param pbutton Push button
     
    376584        if (pbutton->cb != NULL && pbutton->cb->clicked != NULL)
    377585                pbutton->cb->clicked(pbutton, pbutton->arg);
     586}
     587
     588/** Send button down event.
     589 *
     590 * @param pbutton Push button
     591 */
     592void ui_pbutton_down(ui_pbutton_t *pbutton)
     593{
     594        if (pbutton->cb != NULL && pbutton->cb->down != NULL)
     595                pbutton->cb->down(pbutton, pbutton->arg);
     596}
     597
     598/** Send button up event.
     599 *
     600 * @param pbutton Push button
     601 */
     602void ui_pbutton_up(ui_pbutton_t *pbutton)
     603{
     604        if (pbutton->cb != NULL && pbutton->cb->up != NULL)
     605                pbutton->cb->up(pbutton, pbutton->arg);
    378606}
    379607
     
    415643                }
    416644                break;
     645        case POS_DCLICK:
     646                break;
    417647        }
    418648
Note: See TracChangeset for help on using the changeset viewer.