Ignore:
File:
1 edited

Legend:

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

    ra106037 rd0dfbba  
    11/*
    2  * Copyright (c) 2021 Jiri Svoboda
     2 * Copyright (c) 2026 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    3737 */
    3838
     39#include <assert.h>
    3940#include <clipboard.h>
    4041#include <errno.h>
     
    4445#include <gfx/text.h>
    4546#include <macros.h>
     47#include <stdio.h>
    4648#include <stdlib.h>
    4749#include <str.h>
     
    6769        ui_entry_cursor_width = 2,
    6870        ui_entry_sel_hpad = 0,
    69         ui_entry_sel_vpad = 2
     71        ui_entry_sel_vpad = 2,
     72        /** Additional amount to scroll to the left after revealing cursor */
     73        ui_entry_left_scroll_margin = 30
    7074};
    7175
     
    156160{
    157161        entry->halign = halign;
     162        ui_entry_scroll_update(entry, true);
     163        ui_entry_paint(entry);
    158164}
    159165
     
    187193        entry->sel_start = entry->pos;
    188194
     195        ui_entry_scroll_update(entry, false);
     196        ui_entry_paint(entry);
     197
    189198        return EOK;
     199}
     200
     201/** Get entry text.
     202 *
     203 * @return Pointer to entry text.
     204 */
     205const char *ui_entry_get_text(ui_entry_t *entry)
     206{
     207        return entry->text;
    190208}
    191209
     
    298316
    299317        gfx_text_fmt_init(&fmt);
     318        fmt.font = res->font;
    300319        fmt.color = res->entry_fg_color;
    301320        fmt.halign = gfx_halign_left;
     
    313332        entry->text[off1] = '\0';
    314333
    315         rc = gfx_puttext(res->font, &pos, &fmt, entry->text);
     334        rc = gfx_puttext(&pos, &fmt, entry->text);
    316335        if (rc != EOK) {
    317336                (void) gfx_set_clip_rect(res->gc, NULL);
     
    319338        }
    320339
    321         gfx_text_cont(res->font, &pos, &fmt, entry->text, &cpos, &cfmt);
     340        gfx_text_cont(&pos, &fmt, entry->text, &cpos, &cfmt);
    322341        entry->text[off1] = c;
    323342
     
    327346                c = entry->text[off2];
    328347                entry->text[off2] = '\0';
    329                 cfmt.color = res->entry_bg_color;
    330 
    331                 gfx_text_rect(res->font, &cpos, &cfmt, entry->text + off1, &sel);
     348                cfmt.color = res->entry_sel_text_fg_color;
     349
     350                gfx_text_rect(&cpos, &cfmt, entry->text + off1, &sel);
    332351                sel.p0.x -= ui_entry_sel_hpad;
    333352                sel.p0.y -= ui_entry_sel_vpad;
     
    335354                sel.p1.y += ui_entry_sel_vpad;
    336355
    337                 rc = gfx_set_color(res->gc, res->entry_fg_color);
     356                rc = gfx_set_color(res->gc, res->entry_sel_text_bg_color);
    338357                if (rc != EOK)
    339358                        goto error;
     
    343362                        goto error;
    344363
    345                 rc = gfx_puttext(res->font, &cpos, &cfmt, entry->text + off1);
     364                rc = gfx_puttext(&cpos, &cfmt, entry->text + off1);
    346365                if (rc != EOK) {
    347366                        (void) gfx_set_clip_rect(res->gc, NULL);
     
    349368                }
    350369
    351                 gfx_text_cont(res->font, &cpos, &cfmt, entry->text + off1,
    352                     &cpos, &cfmt);
     370                gfx_text_cont(&cpos, &cfmt, entry->text + off1, &cpos, &cfmt);
    353371
    354372                entry->text[off2] = c;
     
    358376        cfmt.color = res->entry_fg_color;
    359377
    360         rc = gfx_puttext(res->font, &cpos, &cfmt, entry->text + off2);
     378        rc = gfx_puttext(&cpos, &cfmt, entry->text + off2);
    361379        if (rc != EOK) {
    362380                (void) gfx_set_clip_rect(res->gc, NULL);
     
    405423
    406424        gfx_text_fmt_init(&fmt);
     425        fmt.font = res->font;
    407426        fmt.halign = gfx_halign_left;
    408427        fmt.valign = gfx_valign_top;
    409428
    410         return gfx_text_find_pos(res->font, &geom.text_pos, &fmt,
    411             entry->text, fpos);
     429        return gfx_text_find_pos(&geom.text_pos, &fmt, entry->text, fpos);
    412430}
    413431
     
    452470        entry->pos = off1;
    453471        entry->sel_start = off1;
     472        ui_entry_scroll_update(entry, false);
    454473        ui_entry_paint(entry);
    455474}
     
    494513
    495514        entry->sel_start = entry->pos;
     515        ui_entry_scroll_update(entry, false);
    496516        ui_entry_paint(entry);
    497517
     
    526546        entry->sel_start = off;
    527547
     548        ui_entry_scroll_update(entry, false);
    528549        ui_entry_paint(entry);
    529550}
     
    551572            str_size(entry->text + off) + 1);
    552573
     574        ui_entry_scroll_update(entry, false);
    553575        ui_entry_paint(entry);
    554576}
     
    644666                break;
    645667        }
    646 
    647668        return ui_claimed;
    648669}
     
    723744        if (!entry->active)
    724745                return ui_unclaimed;
    725 
    726         if (event->type == KEY_PRESS && event->c >= ' ') {
    727                 off = 0;
    728                 rc = chr_encode(event->c, buf, &off, sizeof(buf));
    729                 if (rc == EOK) {
    730                         buf[off] = '\0';
    731                         (void) ui_entry_insert_str(entry, buf);
    732                 }
    733         }
    734746
    735747        /*
     
    748760        if (event->type == KEY_RELEASE && event->key == KC_RSHIFT)
    749761                entry->rshift_held = false;
     762
     763        if (event->type == KEY_PRESS &&
     764            (event->mods & (KM_CTRL | KM_ALT)) == 0 && event->c >= ' ') {
     765                off = 0;
     766                rc = chr_encode(event->c, buf, &off, sizeof(buf));
     767                if (rc == EOK) {
     768                        buf[off] = '\0';
     769                        (void) ui_entry_insert_str(entry, buf);
     770                }
     771        }
    750772
    751773        if (event->type == KEY_PRESS &&
     
    875897        gfx_coord_t hpad;
    876898        gfx_coord_t vpad;
    877         gfx_coord_t width;
    878899        ui_resource_t *res;
    879900
     
    895916        }
    896917
    897         width = gfx_text_width(res->font, entry->text);
     918        geom->text_rect.p0.x = geom->interior_rect.p0.x + hpad;
     919        geom->text_rect.p0.y = geom->interior_rect.p0.y + vpad;
     920        geom->text_rect.p1.x = geom->interior_rect.p1.x - hpad;
     921        geom->text_rect.p1.y = geom->interior_rect.p1.y - vpad;
     922
     923        geom->text_pos.x = geom->interior_rect.p0.x + hpad +
     924            entry->scroll_pos;
     925        geom->text_pos.y = geom->interior_rect.p0.y + vpad;
    898926
    899927        switch (entry->halign) {
    900928        case gfx_halign_left:
    901929        case gfx_halign_justify:
    902                 geom->text_pos.x = geom->interior_rect.p0.x + hpad;
     930                geom->anchor_x = geom->text_rect.p0.x;
    903931                break;
    904932        case gfx_halign_center:
    905                 geom->text_pos.x = (geom->interior_rect.p0.x +
    906                     geom->interior_rect.p1.x) / 2 - width / 2;
     933                geom->anchor_x = (geom->text_rect.p0.x +
     934                    geom->text_rect.p1.x) / 2;
    907935                break;
    908936        case gfx_halign_right:
    909                 geom->text_pos.x = geom->interior_rect.p1.x - hpad - 1 - width;
    910                 break;
    911         }
    912 
    913         geom->text_pos.y = geom->interior_rect.p0.y + vpad;
     937                geom->anchor_x = geom->text_rect.p1.x;
     938                break;
     939        }
    914940}
    915941
     
    945971        if (!shift)
    946972                entry->sel_start = entry->pos;
     973
     974        ui_entry_scroll_update(entry, false);
    947975        (void) ui_entry_paint(entry);
    948976}
     
    959987        if (!shift)
    960988                entry->sel_start = entry->pos;
     989
     990        ui_entry_scroll_update(entry, false);
    961991        (void) ui_entry_paint(entry);
    962992}
     
    9781008        if (!shift)
    9791009                entry->sel_start = entry->pos;
     1010
     1011        ui_entry_scroll_update(entry, false);
    9801012        (void) ui_entry_paint(entry);
    9811013}
     
    9971029        if (!shift)
    9981030                entry->sel_start = entry->pos;
     1031
     1032        ui_entry_scroll_update(entry, false);
    9991033        (void) ui_entry_paint(entry);
    10001034}
     
    10211055}
    10221056
     1057/** Update text entry scroll position.
     1058 *
     1059 * @param entry Text entry
     1060 * @param realign @c true iff we should left-align short text.
     1061 *                This should be only used when changing text alignment,
     1062 *                because left-aligned text entries should not realign
     1063 *                the text to the left side under normal circumstances.
     1064 */
     1065void ui_entry_scroll_update(ui_entry_t *entry, bool realign)
     1066{
     1067        ui_entry_geom_t geom;
     1068        gfx_coord_t x;
     1069        gfx_coord_t width;
     1070        gfx_coord2_t tpos;
     1071        gfx_coord2_t anchor;
     1072        gfx_text_fmt_t fmt;
     1073        ui_resource_t *res;
     1074
     1075        res = ui_window_get_res(entry->window);
     1076
     1077        ui_entry_get_geom(entry, &geom);
     1078
     1079        /* Compute position where cursor is currently displayed at */
     1080        x = geom.text_pos.x + ui_entry_lwidth(entry);
     1081
     1082        /* Is cursor off to the left? */
     1083        if (x < geom.text_rect.p0.x) {
     1084                /*
     1085                 * Scroll to make cursor visible and put some space between it
     1086                 * and the left edge of the text rectangle.
     1087                 */
     1088                entry->scroll_pos += geom.text_rect.p0.x - x +
     1089                    ui_entry_left_scroll_margin;
     1090
     1091                /*
     1092                 * We don't want to scroll further than what's needed
     1093                 * to reveal the beginning of the text.
     1094                 */
     1095                if (entry->scroll_pos > 0)
     1096                        entry->scroll_pos = 0;
     1097        }
     1098
     1099        /*
     1100         * Is cursor off to the right? Note that the width of the cursor
     1101         * is deliberately not taken into account (i.e. we only care
     1102         * about the left edge of the cursor).
     1103         */
     1104        if (x > geom.text_rect.p1.x)
     1105                entry->scroll_pos -= x - geom.text_rect.p1.x;
     1106
     1107        width = gfx_text_width(res->font, entry->text);
     1108
     1109        if (width < geom.text_rect.p1.x - geom.text_rect.p0.x &&
     1110            (realign || entry->halign != gfx_halign_left)) {
     1111                /* Text fits inside entry, so we need to align it */
     1112                anchor.x = geom.anchor_x;
     1113                anchor.y = 0;
     1114                gfx_text_fmt_init(&fmt);
     1115                fmt.font = res->font;
     1116                fmt.halign = entry->halign;
     1117                gfx_text_start_pos(&anchor, &fmt, entry->text, &tpos);
     1118                entry->scroll_pos = tpos.x - geom.text_rect.p0.x;
     1119        } else if (geom.text_pos.x + width < geom.text_rect.p1.x &&
     1120            entry->halign != gfx_halign_left) {
     1121                /* Text is long, unused space on the right */
     1122                entry->scroll_pos += geom.text_rect.p1.x -
     1123                    geom.text_pos.x - width;
     1124        }
     1125}
     1126
    10231127/** @}
    10241128 */
Note: See TracChangeset for help on using the changeset viewer.