diff options
Diffstat (limited to 'src/ui/scrollwidget.c')
-rw-r--r-- | src/ui/scrollwidget.c | 57 |
1 files changed, 52 insertions, 5 deletions
diff --git a/src/ui/scrollwidget.c b/src/ui/scrollwidget.c index cbfd2e70..1be62bb8 100644 --- a/src/ui/scrollwidget.c +++ b/src/ui/scrollwidget.c | |||
@@ -1,5 +1,6 @@ | |||
1 | #include "scrollwidget.h" | 1 | #include "scrollwidget.h" |
2 | #include "paint.h" | 2 | #include "paint.h" |
3 | #include "util.h" | ||
3 | 4 | ||
4 | iDefineObjectConstruction(ScrollWidget) | 5 | iDefineObjectConstruction(ScrollWidget) |
5 | 6 | ||
@@ -8,6 +9,8 @@ struct Impl_ScrollWidget { | |||
8 | iRangei range; | 9 | iRangei range; |
9 | int thumb; | 10 | int thumb; |
10 | int thumbSize; | 11 | int thumbSize; |
12 | iClick click; | ||
13 | int startThumb; | ||
11 | }; | 14 | }; |
12 | 15 | ||
13 | void init_ScrollWidget(iScrollWidget *d) { | 16 | void init_ScrollWidget(iScrollWidget *d) { |
@@ -19,19 +22,23 @@ void init_ScrollWidget(iScrollWidget *d) { | |||
19 | moveToParentRightEdge_WidgetFlag, | 22 | moveToParentRightEdge_WidgetFlag, |
20 | iTrue); | 23 | iTrue); |
21 | w->rect.size.x = gap_UI * 3; | 24 | w->rect.size.x = gap_UI * 3; |
25 | init_Click(&d->click, d, SDL_BUTTON_LEFT); | ||
22 | } | 26 | } |
23 | 27 | ||
24 | void deinit_ScrollWidget(iScrollWidget *d) { | 28 | void deinit_ScrollWidget(iScrollWidget *d) { |
25 | iUnused(d); | 29 | iUnused(d); |
26 | } | 30 | } |
27 | 31 | ||
32 | static int thumbSize_ScrollWidget_(const iScrollWidget *d) { | ||
33 | return iMax(gap_UI * 6, d->thumbSize); | ||
34 | } | ||
35 | |||
28 | static iRect thumbRect_ScrollWidget_(const iScrollWidget *d) { | 36 | static iRect thumbRect_ScrollWidget_(const iScrollWidget *d) { |
29 | const iRect bounds = bounds_Widget(constAs_Widget(d)); | 37 | const iRect bounds = bounds_Widget(constAs_Widget(d)); |
30 | iRect rect = init_Rect(bounds.pos.x, bounds.pos.y, bounds.size.x, 0); | 38 | iRect rect = init_Rect(bounds.pos.x, bounds.pos.y, bounds.size.x, 0); |
31 | const int total = size_Range(&d->range); | 39 | const int total = size_Range(&d->range); |
32 | // printf("total: %d thumb: %d thsize: %d\n", total, d->thumb, d->thumbSize); fflush(stdout); | ||
33 | if (total > 0) { | 40 | if (total > 0) { |
34 | const int tsize = iMax(gap_UI * 6, d->thumbSize); | 41 | const int tsize = thumbSize_ScrollWidget_(d); |
35 | const int tpos = | 42 | const int tpos = |
36 | iClamp((float) d->thumb / (float) total, 0, 1) * (height_Rect(bounds) - tsize); | 43 | iClamp((float) d->thumb / (float) total, 0, 1) * (height_Rect(bounds) - tsize); |
37 | rect.pos.y = tpos; | 44 | rect.pos.y = tpos; |
@@ -46,7 +53,7 @@ static void checkVisible_ScrollWidget_(iScrollWidget *d) { | |||
46 | 53 | ||
47 | void setRange_ScrollWidget(iScrollWidget *d, iRangei range) { | 54 | void setRange_ScrollWidget(iScrollWidget *d, iRangei range) { |
48 | range.end = iMax(range.start, range.end); | 55 | range.end = iMax(range.start, range.end); |
49 | d->range = range; | 56 | d->range = range; |
50 | checkVisible_ScrollWidget_(d); | 57 | checkVisible_ScrollWidget_(d); |
51 | } | 58 | } |
52 | 59 | ||
@@ -58,18 +65,58 @@ void setThumb_ScrollWidget(iScrollWidget *d, int thumb, int thumbSize) { | |||
58 | 65 | ||
59 | static iBool processEvent_ScrollWidget_(iScrollWidget *d, const SDL_Event *ev) { | 66 | static iBool processEvent_ScrollWidget_(iScrollWidget *d, const SDL_Event *ev) { |
60 | iWidget *w = as_Widget(d); | 67 | iWidget *w = as_Widget(d); |
68 | switch (processEvent_Click(&d->click, ev)) { | ||
69 | case started_ClickResult: | ||
70 | setFlags_Widget(w, pressed_WidgetFlag, iTrue); | ||
71 | d->startThumb = d->thumb; | ||
72 | refresh_Widget(w); | ||
73 | return iTrue; | ||
74 | case drag_ClickResult: { | ||
75 | const iRect bounds = bounds_Widget(w); | ||
76 | const int offset = delta_Click(&d->click).y; | ||
77 | const int total = size_Range(&d->range); | ||
78 | int dpos = (float) offset / (float) (height_Rect(bounds) - thumbSize_ScrollWidget_(d)) * total; | ||
79 | d->thumb = iClamp(d->startThumb + dpos, d->range.start, d->range.end); | ||
80 | postCommand_Widget(w, "scroll.moved arg:%d", d->thumb); | ||
81 | refresh_Widget(w); | ||
82 | return iTrue; | ||
83 | } | ||
84 | case finished_ClickResult: | ||
85 | case aborted_ClickResult: | ||
86 | if (!isMoved_Click(&d->click)) { | ||
87 | /* Page up/down. */ | ||
88 | const iRect tr = thumbRect_ScrollWidget_(d); | ||
89 | const int y = pos_Click(&d->click).y; | ||
90 | int pgDir = 0; | ||
91 | if (y < top_Rect(tr)) { | ||
92 | pgDir = -1; | ||
93 | } | ||
94 | else if (y > bottom_Rect(tr)) { | ||
95 | pgDir = +1; | ||
96 | } | ||
97 | if (pgDir) { | ||
98 | postCommand_Widget(w, "scroll.page arg:%d", pgDir); | ||
99 | } | ||
100 | } | ||
101 | setFlags_Widget(w, pressed_WidgetFlag, iFalse); | ||
102 | refresh_Widget(w); | ||
103 | return iTrue; | ||
104 | default: | ||
105 | break; | ||
106 | } | ||
61 | return processEvent_Widget(w, ev); | 107 | return processEvent_Widget(w, ev); |
62 | } | 108 | } |
63 | 109 | ||
64 | static void draw_ScrollWidget_(const iScrollWidget *d) { | 110 | static void draw_ScrollWidget_(const iScrollWidget *d) { |
65 | const iWidget *w = constAs_Widget(d); | 111 | const iWidget *w = constAs_Widget(d); |
66 | const iRect bounds = bounds_Widget(w); | 112 | const iRect bounds = bounds_Widget(w); |
113 | const iBool isPressed = (flags_Widget(w) & pressed_WidgetFlag) != 0; | ||
67 | if (bounds.size.x > 0) { | 114 | if (bounds.size.x > 0) { |
68 | iPaint p; | 115 | iPaint p; |
69 | init_Paint(&p); | 116 | init_Paint(&p); |
70 | drawRect_Paint(&p, bounds, black_ColorId); | 117 | drawRect_Paint(&p, bounds, black_ColorId); |
71 | iRect tr = thumbRect_ScrollWidget_(d); | 118 | fillRect_Paint(&p, shrunk_Rect(thumbRect_ScrollWidget_(d), one_I2()), |
72 | fillRect_Paint(&p, thumbRect_ScrollWidget_(d), gray50_ColorId); | 119 | isPressed ? orange_ColorId : gray50_ColorId); |
73 | } | 120 | } |
74 | } | 121 | } |
75 | 122 | ||