diff --git a/include/tim.h b/include/tim.h index ff1f9ce..2b71920 100644 --- a/include/tim.h +++ b/include/tim.h @@ -181,6 +181,8 @@ typedef struct TimScrollState { TimScrollItem* items; u32 len; u32 cur; + bool draw_border; + bool show_scroll_bar_horizontal; bool use_mouse_wheel; } TimScrollState; diff --git a/src/scroll.c b/src/scroll.c index b237093..1445a1c 100755 --- a/src/scroll.c +++ b/src/scroll.c @@ -1,4 +1,5 @@ #include "tim.h" +#include void TimScrollState_selectNext(TimScrollState* l){ l->cur = (l->cur + 1) % l->len; @@ -9,7 +10,7 @@ void TimScrollState_selectPrev(TimScrollState* l){ } TimScrollItem* tim_scroll(TimScrollState* l, i32 x, i32 y, i32 w, i32 h, TimStyle style){ - // select with buttons and mouse wheel + // select row with keyboard and mouse wheel if(tim_is_key_press(TimKey_Down) || (l->use_mouse_wheel && tim_is_mouse_scroll_down())) { @@ -23,22 +24,55 @@ TimScrollItem* tim_scroll(TimScrollState* l, i32 x, i32 y, i32 w, i32 h, TimStyl tim->focus = l->items[l->cur].focus_target; - tim_frame(x, y, w, h, style); - - TimRect absolute = tim_scope_rect_to_absolute(x, y, w, h); - TimRect place = { .x = x + 1, .y = y + 1, .w = absolute.w - 2, .h = absolute.h - 2 }; - for(u32 i = 0; i < l->len; i++){ - TimScrollItem* item = &l->items[i]; - place.h = item->h; + tim_scope(x, y, w, h) + { + TimRect items_scope = tim->scopes[tim->scope]; - // select with mouse click - if(tim_is_mouse_click_over(tim_scope_rect_to_absolute(place.x, place.y, place.w, place.h))){ - l->cur = i; - tim->focus = item->focus_target; + // draw border and shrink items_scope + if(l->draw_border){ + tim_frame(0, 0, ~0, ~0, style); + items_scope.x += 1; + items_scope.y += 1; + items_scope.w -= 2; + items_scope.h -= 2; + } + + // draw scroll bar and shrink items_scope + if(l->show_scroll_bar_horizontal){ + items_scope.w -= 1; + i32 scrollbar_x = items_scope.x + items_scope.w; + i32 scrollbar_y = items_scope.y; + i32 scrollbar_h = items_scope.h - 2; + f32 slider_y_normalized = 0; + i32 slider_h = 0; + if(l->len != 0){ + slider_y_normalized = (f32)l->cur / l->len + 0.001f; + slider_h = ceilf((f32)scrollbar_h / l->len); + } + i32 slider_y = scrollbar_y + 1 + scrollbar_h * slider_y_normalized; + tim_draw_chr(tim_cell("▲", style.brd, style.bg), scrollbar_x, scrollbar_y); + tim_draw_col(tim_cell("░", style.brd, style.bg), scrollbar_x, scrollbar_y + 1, scrollbar_h); + tim_draw_col(tim_cell("█", style.brd, style.bg), scrollbar_x, slider_y, slider_h); + tim_draw_chr(tim_cell("▼", style.brd, style.bg), scrollbar_x, scrollbar_y + scrollbar_h + 1); } - item->draw(i == l->cur, place, item->data); - place.y += place.h; + tim->scopes[tim->scope] = items_scope; // fit current scope inside frame and scrollbar + + // draw items + TimRect item_place = { .x = 0, .y = 0, .w = items_scope.w, .h = 0 }; + for(u32 i = 0; i < l->len; i++){ + TimScrollItem* item = &l->items[i]; + item_place.h = item->h; + + // select row with mouse click + if(tim_is_mouse_click_over(tim_scope_rect_to_absolute(item_place.x, item_place.y, item_place.w, item_place.h))){ + l->cur = i; + tim->focus = item->focus_target; + } + + item->draw(i == l->cur, item_place, item->data); + item_place.y += item_place.h; + } } return &l->items[l->cur];