| 717 | |
| 718 | |
| 719 | void draw_scrollbar_on(LfDiv* div) { |
| 720 | lf_next_line(); |
| 721 | if (state.current_div.id == div->id) { |
| 722 | state.scrollbar_div = *div; |
| 723 | LfDiv* selected = div; |
| 724 | float scroll = *state.scroll_ptr; |
| 725 | LfUIElementProps props = get_props_for(state.theme.scrollbar_props); |
| 726 | |
| 727 | selected->total_area.x = state.pos_ptr.x; |
| 728 | selected->total_area.y = state.pos_ptr.y + state.div_props.corner_radius; |
| 729 | |
| 730 | if (*state.scroll_ptr < -((div->total_area.y - *state.scroll_ptr) - div->aabb.pos.y - div->aabb.size.y) && *state.scroll_velocity_ptr < 0 && state.theme.div_smooth_scroll) { |
| 731 | *state.scroll_velocity_ptr = 0; |
| 732 | *state.scroll_ptr = -((div->total_area.y - *state.scroll_ptr) - div->aabb.pos.y - div->aabb.size.y); |
| 733 | } |
| 734 | |
| 735 | float total_area = selected->total_area.y - scroll; |
| 736 | float visible_area = selected->aabb.size.y + selected->aabb.pos.y; |
| 737 | if (total_area > visible_area) { |
| 738 | const float min_scrollbar_height = 20; |
| 739 | |
| 740 | float area_mapped = visible_area / total_area; |
| 741 | float scroll_mapped = (-1 * scroll) / total_area; |
| 742 | float scrollbar_height = MAX((selected->aabb.size.y * area_mapped - props.margin_top * 2), min_scrollbar_height); |
| 743 | |
| 744 | LfAABB scrollbar_area = (LfAABB){ |
| 745 | .pos = (vec2s){ |
| 746 | selected->aabb.pos.x + selected->aabb.size.x - state.theme.scrollbar_width - props.margin_right - state.div_props.padding - state.div_props.border_width, |
| 747 | MIN((selected->aabb.pos.y + selected->aabb.size.y * scroll_mapped + props.margin_top + state.div_props.padding + state.div_props.border_width + state.div_props.corner_radius), |
| 748 | visible_area - scrollbar_height)}, |
| 749 | .size = (vec2s){ |
| 750 | state.theme.scrollbar_width, |
| 751 | scrollbar_height - state.div_props.border_width * 2 - state.div_props.corner_radius * 2}, |
| 752 | }; |
| 753 | |
| 754 | vec2s cursorpos = (vec2s){lf_get_mouse_x(), lf_get_mouse_y()}; |
| 755 | if (lf_mouse_button_went_down(GLFW_MOUSE_BUTTON_LEFT) && lf_hovered(scrollbar_area.pos, scrollbar_area.size)) { |
| 756 | state.drag_state.is_dragging = true; |
| 757 | state.drag_state.start_cursor_pos = cursorpos; |
| 758 | state.drag_state.start_scroll = *state.scroll_ptr; |
| 759 | } |
| 760 | if(state.drag_state.is_dragging) { |
| 761 | float cursor_delta = (cursorpos.y - state.drag_state.start_cursor_pos.y); |
| 762 | float new_scroll = state.drag_state.start_scroll - cursor_delta * (total_area / visible_area); |
| 763 | *state.scroll_ptr = new_scroll; |
| 764 | |
| 765 | if (*state.scroll_ptr > 0) { |
| 766 | *state.scroll_ptr = 0; |
| 767 | } else if (*state.scroll_ptr < -(total_area - visible_area)) { |
| 768 | *state.scroll_ptr = -(total_area - visible_area); |
| 769 | } |
| 770 | } |
| 771 | if (lf_mouse_button_is_released(GLFW_MOUSE_BUTTON_LEFT)) { |
| 772 | state.drag_state.is_dragging = false; |
| 773 | } |
| 774 | |
| 775 | lf_rect_render(scrollbar_area.pos, scrollbar_area.size, |
| 776 | props.color, props.border_color, props.border_width, props.corner_radius); |
no test coverage detected