Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset dbb42c9 in mainline


Ignore:
Timestamp:
2021-08-01T14:47:33Z (3 months ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
master
Children:
1e242121
Parents:
5de71df
Message:

Scroll entry text when it is long

Whew! This is so much harder than it looks!

Location:
uspace
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/uidemo/uidemo.c

    r5de71df rdbb42c9  
    129129                if (rc != EOK)
    130130                        printf("Error changing entry text.\n");
    131                 (void) ui_entry_paint(demo->entry);
    132131        } else {
    133132                rc = ui_entry_set_text(demo->entry, "Cancel pressed");
    134133                if (rc != EOK)
    135134                        printf("Error changing entry text.\n");
    136                 (void) ui_entry_paint(demo->entry);
    137135        }
    138136}
  • uspace/lib/ui/private/entry.h

    r5de71df rdbb42c9  
    4040#include <gfx/coord.h>
    4141#include <gfx/text.h>
     42#include <stdbool.h>
    4243
    4344/** Actual structure of text entry.
     
    5859        /** Text */
    5960        char *text;
     61        /** Current scroll position (in pixels) */
     62        gfx_coord_t scroll_pos;
    6063        /** Cursor position in the text (offset in bytes) */
    6164        unsigned pos;
     
    8184        /** Interior rectangle */
    8285        gfx_rect_t interior_rect;
     86        /** Text rectangle */
     87        gfx_rect_t text_rect;
    8388        /** Text anchor position */
    8489        gfx_coord2_t text_pos;
     90        /** Text anchor X coordinate */
     91        gfx_coord_t anchor_x;
    8592} ui_entry_geom_t;
    8693
     
    94101extern void ui_entry_activate(ui_entry_t *);
    95102extern void ui_entry_deactivate(ui_entry_t *);
     103extern void ui_entry_scroll_update(ui_entry_t *, bool);
    96104
    97105#endif
  • uspace/lib/ui/src/entry.c

    r5de71df rdbb42c9  
    6767        ui_entry_cursor_width = 2,
    6868        ui_entry_sel_hpad = 0,
    69         ui_entry_sel_vpad = 2
     69        ui_entry_sel_vpad = 2,
     70        /** Additional amount to scroll to the left after revealing cursor */
     71        ui_entry_left_scroll_margin = 30
    7072};
    7173
     
    156158{
    157159        entry->halign = halign;
     160        ui_entry_scroll_update(entry, true);
     161        ui_entry_paint(entry);
    158162}
    159163
     
    186190        entry->pos = str_size(text);
    187191        entry->sel_start = entry->pos;
     192        ui_entry_scroll_update(entry, false);
     193        ui_entry_paint(entry);
    188194
    189195        return EOK;
     
    452458        entry->pos = off1;
    453459        entry->sel_start = off1;
     460        ui_entry_scroll_update(entry, false);
    454461        ui_entry_paint(entry);
    455462}
     
    494501
    495502        entry->sel_start = entry->pos;
     503        ui_entry_scroll_update(entry, false);
    496504        ui_entry_paint(entry);
    497505
     
    526534        entry->sel_start = off;
    527535
     536        ui_entry_scroll_update(entry, false);
    528537        ui_entry_paint(entry);
    529538}
     
    551560            str_size(entry->text + off) + 1);
    552561
     562        ui_entry_scroll_update(entry, false);
    553563        ui_entry_paint(entry);
    554564}
     
    875885        gfx_coord_t hpad;
    876886        gfx_coord_t vpad;
    877         gfx_coord_t width;
    878887        ui_resource_t *res;
    879888
     
    895904        }
    896905
    897         width = gfx_text_width(res->font, entry->text);
     906        geom->text_rect.p0.x = geom->interior_rect.p0.x + hpad;
     907        geom->text_rect.p0.y = geom->interior_rect.p0.y + vpad;
     908        geom->text_rect.p1.x = geom->interior_rect.p1.x - hpad;
     909        geom->text_rect.p1.y = geom->interior_rect.p1.y - vpad;
     910
     911        geom->text_pos.x = geom->interior_rect.p0.x + hpad +
     912            entry->scroll_pos;
     913        geom->text_pos.y = geom->interior_rect.p0.y + vpad;
    898914
    899915        switch (entry->halign) {
    900916        case gfx_halign_left:
    901917        case gfx_halign_justify:
    902                 geom->text_pos.x = geom->interior_rect.p0.x + hpad;
     918                geom->anchor_x = geom->text_rect.p0.x;
    903919                break;
    904920        case gfx_halign_center:
    905                 geom->text_pos.x = (geom->interior_rect.p0.x +
    906                     geom->interior_rect.p1.x) / 2 - width / 2;
     921                geom->anchor_x = (geom->text_rect.p0.x +
     922                    geom->text_rect.p1.x) / 2;
    907923                break;
    908924        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;
     925                geom->anchor_x = geom->text_rect.p1.x;
     926                break;
     927        }
    914928}
    915929
     
    945959        if (!shift)
    946960                entry->sel_start = entry->pos;
     961
     962        ui_entry_scroll_update(entry, false);
    947963        (void) ui_entry_paint(entry);
    948964}
     
    959975        if (!shift)
    960976                entry->sel_start = entry->pos;
     977
     978        ui_entry_scroll_update(entry, false);
    961979        (void) ui_entry_paint(entry);
    962980}
     
    978996        if (!shift)
    979997                entry->sel_start = entry->pos;
     998
     999        ui_entry_scroll_update(entry, false);
    9801000        (void) ui_entry_paint(entry);
    9811001}
     
    9971017        if (!shift)
    9981018                entry->sel_start = entry->pos;
     1019
     1020        ui_entry_scroll_update(entry, false);
    9991021        (void) ui_entry_paint(entry);
    10001022}
     
    10211043}
    10221044
     1045/** Update text entry scroll position.
     1046 *
     1047 * @param entry Text entry
     1048 * @param realign @c true iff we should left-align short text.
     1049 *                This should be only used when changing text alignment,
     1050 *                because left-aligned text entries should not realign
     1051 *                the text to the left side under normal circumstances.
     1052 */
     1053void ui_entry_scroll_update(ui_entry_t *entry, bool realign)
     1054{
     1055        ui_entry_geom_t geom;
     1056        gfx_coord_t x;
     1057        gfx_coord_t width;
     1058        gfx_coord2_t tpos;
     1059        gfx_coord2_t anchor;
     1060        gfx_text_fmt_t fmt;
     1061        ui_resource_t *res;
     1062
     1063        res = ui_window_get_res(entry->window);
     1064
     1065        ui_entry_get_geom(entry, &geom);
     1066
     1067        /* Compute position where cursor is currently displayed at */
     1068        x = geom.text_pos.x + ui_entry_lwidth(entry);
     1069
     1070        /* Is cursor off to the left? */
     1071        if (x < geom.text_rect.p0.x) {
     1072                /*
     1073                 * Scroll to make cursor visible and put some space between it
     1074                 * and the left edge of the text rectangle.
     1075                 */
     1076                entry->scroll_pos += geom.text_rect.p0.x - x +
     1077                    ui_entry_left_scroll_margin;
     1078
     1079                /*
     1080                 * We don't want to scroll further than what's needed
     1081                 * to reveal the beginning of the text.
     1082                 */
     1083                if (entry->scroll_pos > 0)
     1084                        entry->scroll_pos = 0;
     1085        }
     1086
     1087        /*
     1088         * Is cursor off to the right? Note that the width of the cursor
     1089         * is deliberately not taken into account (i.e. we only care
     1090         * about the left edge of the cursor).
     1091         */
     1092        if (x > geom.text_rect.p1.x)
     1093                entry->scroll_pos -= x + 2 - geom.text_rect.p1.x;
     1094
     1095        width = gfx_text_width(res->font, entry->text);
     1096
     1097        if (width < geom.text_rect.p1.x - geom.text_rect.p0.x &&
     1098            (realign || entry->halign != gfx_halign_left)) {
     1099                /* Text fits inside entry, so we need to align it */
     1100                anchor.x = geom.anchor_x;
     1101                anchor.y = 0;
     1102                gfx_text_fmt_init(&fmt);
     1103                fmt.halign = entry->halign;
     1104                gfx_text_start_pos(res->font, &anchor, &fmt, entry->text,
     1105                    &tpos);
     1106                entry->scroll_pos = tpos.x - geom.text_rect.p0.x;
     1107        } else if (geom.text_pos.x + width < geom.text_rect.p1.x &&
     1108            entry->halign != gfx_halign_left) {
     1109                /* Text is long, unused space on the right */
     1110                entry->scroll_pos += geom.text_rect.p1.x -
     1111                    geom.text_pos.x - width;
     1112        }
     1113}
     1114
    10231115/** @}
    10241116 */
Note: See TracChangeset for help on using the changeset viewer.