1 #include "scrollbar.h"
2
3 #include "core/calc.h"
4 #include "core/image.h"
5 #include "core/image_group.h"
6 #include "graphics/image.h"
7 #include "graphics/image_button.h"
8
9 #define SCROLL_BUTTON_HEIGHT 26
10 #define SCROLL_BUTTON_WIDTH 39
11 #define SCROLL_DOT_SIZE 25
12 #define TOTAL_BUTTON_HEIGHT (2 * SCROLL_BUTTON_HEIGHT + SCROLL_DOT_SIZE)
13
14 static void text_scroll(int is_down, int num_lines);
15
16 static image_button image_button_scroll_up = {
17 0, 0, SCROLL_BUTTON_WIDTH, SCROLL_BUTTON_HEIGHT, IB_SCROLL,
18 GROUP_OK_CANCEL_SCROLL_BUTTONS, 8, text_scroll, button_none, 0, 1, 1
19 };
20 static image_button image_button_scroll_down = {
21 0, 0, SCROLL_BUTTON_WIDTH, SCROLL_BUTTON_HEIGHT, IB_SCROLL,
22 GROUP_OK_CANCEL_SCROLL_BUTTONS, 12, text_scroll, button_none, 1, 1, 1
23 };
24
25 static scrollbar_type *current;
26
scrollbar_init(scrollbar_type * scrollbar,int scroll_position,int max_scroll_position)27 void scrollbar_init(scrollbar_type *scrollbar, int scroll_position, int max_scroll_position)
28 {
29 if (max_scroll_position < 0) {
30 max_scroll_position = 0;
31 }
32 scrollbar->scroll_position = calc_bound(scroll_position, 0, max_scroll_position);
33 scrollbar->max_scroll_position = max_scroll_position;
34 scrollbar->is_dragging_scroll = 0;
35 }
36
scrollbar_reset(scrollbar_type * scrollbar,int scroll_position)37 void scrollbar_reset(scrollbar_type *scrollbar, int scroll_position)
38 {
39 scrollbar->scroll_position = scroll_position;
40 scrollbar->is_dragging_scroll = 0;
41 }
42
scrollbar_update_max(scrollbar_type * scrollbar,int max_scroll_position)43 void scrollbar_update_max(scrollbar_type *scrollbar, int max_scroll_position)
44 {
45 if (max_scroll_position < 0) {
46 max_scroll_position = 0;
47 }
48 scrollbar->max_scroll_position = max_scroll_position;
49 if (scrollbar->scroll_position > max_scroll_position) {
50 scrollbar->scroll_position = max_scroll_position;
51 }
52 }
53
scrollbar_draw(scrollbar_type * scrollbar)54 void scrollbar_draw(scrollbar_type *scrollbar)
55 {
56 if (scrollbar->max_scroll_position > 0 || scrollbar->always_visible) {
57 image_buttons_draw(scrollbar->x, scrollbar->y, &image_button_scroll_up, 1);
58 image_buttons_draw(scrollbar->x, scrollbar->y + scrollbar->height - SCROLL_BUTTON_HEIGHT,
59 &image_button_scroll_down, 1);
60
61 int pct;
62 if (scrollbar->scroll_position <= 0) {
63 pct = 0;
64 } else if (scrollbar->scroll_position >= scrollbar->max_scroll_position) {
65 pct = 100;
66 } else {
67 pct = calc_percentage(scrollbar->scroll_position, scrollbar->max_scroll_position);
68 }
69 int offset = calc_adjust_with_percentage(
70 scrollbar->height - TOTAL_BUTTON_HEIGHT - 2 * scrollbar->dot_padding, pct);
71 if (scrollbar->is_dragging_scroll) {
72 offset = scrollbar->scroll_position_drag;
73 }
74 image_draw(image_group(GROUP_PANEL_BUTTON) + 39,
75 scrollbar->x + (SCROLL_BUTTON_WIDTH - SCROLL_DOT_SIZE) / 2,
76 scrollbar->y + offset + SCROLL_BUTTON_HEIGHT + scrollbar->dot_padding);
77 }
78 }
79
handle_scrollbar_dot(scrollbar_type * scrollbar,const mouse * m)80 static int handle_scrollbar_dot(scrollbar_type *scrollbar, const mouse *m)
81 {
82 if (scrollbar->max_scroll_position <= 0 || !m->left.is_down) {
83 return 0;
84 }
85 int track_height = scrollbar->height - TOTAL_BUTTON_HEIGHT - 2 * scrollbar->dot_padding;
86 if (m->x < scrollbar->x || m->x >= scrollbar->x + SCROLL_BUTTON_WIDTH) {
87 return 0;
88 }
89 if (m->y < scrollbar->y + SCROLL_BUTTON_HEIGHT + scrollbar->dot_padding ||
90 m->y > scrollbar->y + scrollbar->height - SCROLL_BUTTON_HEIGHT - scrollbar->dot_padding) {
91 return 0;
92 }
93 int dot_offset = m->y - scrollbar->y - SCROLL_DOT_SIZE/2 - SCROLL_BUTTON_HEIGHT;
94 if (dot_offset < 0) {
95 dot_offset = 0;
96 }
97 if (dot_offset > track_height) {
98 dot_offset = track_height;
99 }
100 int pct_scrolled = calc_percentage(dot_offset, track_height);
101 scrollbar->scroll_position = calc_adjust_with_percentage(
102 scrollbar->max_scroll_position, pct_scrolled);
103 scrollbar->is_dragging_scroll = 1;
104 scrollbar->scroll_position_drag = dot_offset;
105 if (scrollbar->scroll_position_drag < 0) {
106 scrollbar->scroll_position_drag = 0;
107 }
108 if (scrollbar->on_scroll_callback) {
109 scrollbar->on_scroll_callback();
110 }
111 return 1;
112 }
113
scrollbar_handle_mouse(scrollbar_type * scrollbar,const mouse * m)114 int scrollbar_handle_mouse(scrollbar_type *scrollbar, const mouse *m)
115 {
116 if (scrollbar->max_scroll_position <= 0) {
117 return 0;
118 }
119 current = scrollbar;
120 if (m->scrolled == SCROLL_DOWN) {
121 text_scroll(1, 3);
122 } else if (m->scrolled == SCROLL_UP) {
123 text_scroll(0, 3);
124 }
125
126 if (image_buttons_handle_mouse(m,
127 scrollbar->x, scrollbar->y, &image_button_scroll_up, 1, 0)) {
128 return 1;
129 }
130 if (image_buttons_handle_mouse(m,
131 scrollbar->x, scrollbar->y + scrollbar->height - SCROLL_BUTTON_HEIGHT,
132 &image_button_scroll_down, 1, 0)) {
133 return 1;
134 }
135 return handle_scrollbar_dot(scrollbar, m);
136 }
137
text_scroll(int is_down,int num_lines)138 static void text_scroll(int is_down, int num_lines)
139 {
140 scrollbar_type *scrollbar = current;
141 if (is_down) {
142 scrollbar->scroll_position += num_lines;
143 if (scrollbar->scroll_position > scrollbar->max_scroll_position) {
144 scrollbar->scroll_position = scrollbar->max_scroll_position;
145 }
146 } else {
147 scrollbar->scroll_position -= num_lines;
148 if (scrollbar->scroll_position < 0) {
149 scrollbar->scroll_position = 0;
150 }
151 }
152 scrollbar->is_dragging_scroll = 0;
153 if (scrollbar->on_scroll_callback) {
154 scrollbar->on_scroll_callback();
155 }
156 }
157