1 #include "scrollable.h"
2 
3 #include "draw.h"
4 #include "svg.h"
5 
6 #include "../macros.h"
7 #include "../ui.h"
8 
scroll_draw(SCROLLABLE * s,int x,int y,int width,int height)9 void scroll_draw(SCROLLABLE *s, int x, int y, int width, int height) {
10     uint32_t c            = s->content_height;
11     uint32_t h            = height, m, dy;
12     uint32_t scroll_width = 0;
13     if (s->small) {
14         scroll_width = SCROLL_WIDTH / 2;
15     } else {
16         scroll_width = SCROLL_WIDTH;
17     }
18 
19     if (h >= c) {
20         // If h(eight) > c(ontent height), don't draw anything.
21         return;
22     } else {
23         m        = (h * h) / c;
24         double d = (h - m);
25         dy       = (s->d * d) + 0.5;
26     }
27 
28     y += dy;
29     x += s->x;
30 
31     if (!s->left) {
32         x += width - scroll_width;
33     }
34 
35     drawalpha(s->small ? BM_SCROLLHALFTOP_SMALL : BM_SCROLLHALFTOP, x, y, scroll_width, scroll_width / 2, s->color);
36 
37     y += scroll_width / 2;
38     int y2 = y + m - scroll_width;
39     if (scroll_width > m) {
40         y2 = y;
41     }
42     drawrect(x, y, x + scroll_width, y2, s->color);
43 
44     drawalpha(s->small ? BM_SCROLLHALFBOT_SMALL : BM_SCROLLHALFBOT, x, y2, scroll_width, scroll_width / 2, s->color);
45 }
46 
scroll_gety(SCROLLABLE * s,int height)47 int scroll_gety(SCROLLABLE *s, int height) {
48     int c = s->content_height;
49 
50     if (c > height) {
51         return (s->d * (double)(c - height)) + 0.5;
52     }
53 
54     return 0;
55 }
56 
scroll_mmove(SCROLLABLE * s,int UNUSED (px),int UNUSED (py),int width,int height,int x,int y,int UNUSED (dx),int dy)57 bool scroll_mmove(SCROLLABLE *s, int UNUSED(px), int UNUSED(py), int width, int height, int x, int y, int UNUSED(dx),
58                   int dy) {
59     bool draw = false;
60 
61     bool hit = inrect(x, y, s->left ? 0 : (width - SCROLL_WIDTH), 0, SCROLL_WIDTH, height);
62     if (s->mouseover != hit) {
63         s->mouseover = hit;
64         draw         = true;
65     }
66 
67     s->mouseover2 = inrect(x, y, 0, 0, width, height);
68 
69     if (s->mousedown) {
70         uint32_t c = s->content_height;
71         uint32_t h = height;
72 
73         if (c > h) {
74             uint32_t m = (h * h) / c;
75             double   d = (h - m);
76 
77             s->d = ((s->d * d) + (double)dy) / d;
78 
79             if (s->d < 0.0) {
80                 s->d = 0.0;
81             } else if (s->d >= 1.0) {
82                 s->d = 1.0;
83             }
84 
85             draw = true;
86         }
87     }
88 
89     return draw;
90 }
91 
scroll_mdown(SCROLLABLE * s)92 bool scroll_mdown(SCROLLABLE *s) {
93     if (s->mouseover) {
94         s->mousedown = 1;
95         return true;
96     }
97 
98     return false;
99 }
100 
scroll_mright(SCROLLABLE * UNUSED (s))101 bool scroll_mright(SCROLLABLE *UNUSED(s)) { return false; }
102 
scroll_mwheel(SCROLLABLE * s,int height,double delta,bool smooth)103 bool scroll_mwheel(SCROLLABLE *s, int height, double delta, bool smooth) {
104 
105     /* Variable which controls scroll speed. How much one scroll step
106      * moves viewport */
107     double scroll_speed_multip = 5.0;
108 
109     if (s->mouseover2) {
110         uint32_t content_height = s->content_height;
111         uint32_t port_height    = height;
112 
113         if (content_height > port_height) {
114             /* Scrolling is relative to amount of total content in component */
115             if (smooth) {
116                 // this seems to be the magic equation that makes it scroll at the same speed
117                 // regardless of how big the port is compared to the content.
118                 s->d -= (delta * (32.0 * port_height / content_height) / content_height) * scroll_speed_multip;
119             } else {
120                 uint32_t magic = (port_height * port_height) / content_height;
121                 double   fred  = (port_height - magic);
122                 s->d -= 16.0 * delta / fred;
123             }
124 
125             if (s->d < 0.0) {
126                 s->d = 0.0;
127             } else if (s->d >= 1.0) {
128                 s->d = 1.0;
129             }
130 
131             return true;
132         }
133     }
134 
135     return false;
136 }
137 
scroll_mup(SCROLLABLE * s)138 bool scroll_mup(SCROLLABLE *s) {
139     if (s->mousedown) {
140         s->mousedown = 0;
141         return true;
142     }
143 
144     return false;
145 }
146 
scroll_mleave(SCROLLABLE * s)147 bool scroll_mleave(SCROLLABLE *s) {
148     if (s->mouseover) {
149         s->mouseover = 0;
150         return true;
151     }
152 
153     s->mouseover2 = 0;
154 
155     return false;
156 }
157