diff options
Diffstat (limited to 'src/ui/scrollwidget.c')
-rw-r--r-- | src/ui/scrollwidget.c | 85 |
1 files changed, 80 insertions, 5 deletions
diff --git a/src/ui/scrollwidget.c b/src/ui/scrollwidget.c index e887ddbf..a08b58d7 100644 --- a/src/ui/scrollwidget.c +++ b/src/ui/scrollwidget.c | |||
@@ -23,9 +23,23 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
23 | #include "scrollwidget.h" | 23 | #include "scrollwidget.h" |
24 | #include "paint.h" | 24 | #include "paint.h" |
25 | #include "util.h" | 25 | #include "util.h" |
26 | #include "periodic.h" | ||
27 | #include "app.h" | ||
28 | |||
29 | #include <SDL_timer.h> | ||
26 | 30 | ||
27 | iDefineObjectConstruction(ScrollWidget) | 31 | iDefineObjectConstruction(ScrollWidget) |
28 | 32 | ||
33 | static float minOpacity_(void) { | ||
34 | #if !defined (iPlatformApple) | ||
35 | if (deviceType_App() == desktop_AppDeviceType) { | ||
36 | /* Don't fade the scrollbars completely. */ | ||
37 | return 0.333f; | ||
38 | } | ||
39 | #endif | ||
40 | return 0.0f; | ||
41 | } | ||
42 | |||
29 | struct Impl_ScrollWidget { | 43 | struct Impl_ScrollWidget { |
30 | iWidget widget; | 44 | iWidget widget; |
31 | iRangei range; | 45 | iRangei range; |
@@ -33,12 +47,23 @@ struct Impl_ScrollWidget { | |||
33 | int thumbSize; | 47 | int thumbSize; |
34 | iClick click; | 48 | iClick click; |
35 | int startThumb; | 49 | int startThumb; |
50 | iAnim opacity; | ||
51 | uint32_t fadeStart; | ||
52 | iBool willCheckFade; | ||
36 | }; | 53 | }; |
37 | 54 | ||
38 | static void updateMetrics_ScrollWidget_(iScrollWidget *d) { | 55 | static void updateMetrics_ScrollWidget_(iScrollWidget *d) { |
39 | as_Widget(d)->rect.size.x = gap_UI * 3; | 56 | as_Widget(d)->rect.size.x = gap_UI * 3; |
40 | } | 57 | } |
41 | 58 | ||
59 | static void animateOpacity_ScrollWidget_(void *ptr) { | ||
60 | iScrollWidget *d = ptr; | ||
61 | if (!isFinished_Anim(&d->opacity)) { | ||
62 | addTicker_App(animateOpacity_ScrollWidget_, ptr); | ||
63 | } | ||
64 | refresh_Widget(ptr); | ||
65 | } | ||
66 | |||
42 | void init_ScrollWidget(iScrollWidget *d) { | 67 | void init_ScrollWidget(iScrollWidget *d) { |
43 | iWidget *w = as_Widget(d); | 68 | iWidget *w = as_Widget(d); |
44 | init_Widget(w); | 69 | init_Widget(w); |
@@ -49,10 +74,13 @@ void init_ScrollWidget(iScrollWidget *d) { | |||
49 | iTrue); | 74 | iTrue); |
50 | updateMetrics_ScrollWidget_(d); | 75 | updateMetrics_ScrollWidget_(d); |
51 | init_Click(&d->click, d, SDL_BUTTON_LEFT); | 76 | init_Click(&d->click, d, SDL_BUTTON_LEFT); |
77 | init_Anim(&d->opacity, minOpacity_()); | ||
78 | d->willCheckFade = iFalse; | ||
52 | } | 79 | } |
53 | 80 | ||
54 | void deinit_ScrollWidget(iScrollWidget *d) { | 81 | void deinit_ScrollWidget(iScrollWidget *d) { |
55 | iUnused(d); | 82 | remove_Periodic(periodic_App(), d); |
83 | removeTicker_App(animateOpacity_ScrollWidget_, d); | ||
56 | } | 84 | } |
57 | 85 | ||
58 | static int thumbSize_ScrollWidget_(const iScrollWidget *d) { | 86 | static int thumbSize_ScrollWidget_(const iScrollWidget *d) { |
@@ -74,10 +102,26 @@ static iRect thumbRect_ScrollWidget_(const iScrollWidget *d) { | |||
74 | return rect; | 102 | return rect; |
75 | } | 103 | } |
76 | 104 | ||
105 | static void unfade_ScrollWidget_(iScrollWidget *d, float opacity) { | ||
106 | d->fadeStart = SDL_GetTicks() + 1000; | ||
107 | if (targetValue_Anim(&d->opacity) < opacity) { | ||
108 | setValue_Anim(&d->opacity, opacity, 66); | ||
109 | addTicker_App(animateOpacity_ScrollWidget_, d); | ||
110 | } | ||
111 | if (!d->willCheckFade) { | ||
112 | d->willCheckFade = iTrue; | ||
113 | add_Periodic(periodic_App(), d, "scrollbar.fade"); | ||
114 | } | ||
115 | refresh_Widget(d); | ||
116 | } | ||
117 | |||
77 | static void checkVisible_ScrollWidget_(iScrollWidget *d) { | 118 | static void checkVisible_ScrollWidget_(iScrollWidget *d) { |
78 | setFlags_Widget(as_Widget(d), | 119 | const iBool wasHidden = isVisible_Widget(d); |
79 | hidden_WidgetFlag, | 120 | const iBool isHidden = d->thumbSize != 0 ? height_Rect(thumbRect_ScrollWidget_(d)) == 0 : iTrue; |
80 | d->thumbSize != 0 ? height_Rect(thumbRect_ScrollWidget_(d)) == 0 : iTrue); | 121 | setFlags_Widget(as_Widget(d), hidden_WidgetFlag, isHidden); |
122 | if (wasHidden && !isHidden) { | ||
123 | unfade_ScrollWidget_(d, 1.0f); | ||
124 | } | ||
81 | } | 125 | } |
82 | 126 | ||
83 | void setRange_ScrollWidget(iScrollWidget *d, iRangei range) { | 127 | void setRange_ScrollWidget(iScrollWidget *d, iRangei range) { |
@@ -87,9 +131,13 @@ void setRange_ScrollWidget(iScrollWidget *d, iRangei range) { | |||
87 | } | 131 | } |
88 | 132 | ||
89 | void setThumb_ScrollWidget(iScrollWidget *d, int thumb, int thumbSize) { | 133 | void setThumb_ScrollWidget(iScrollWidget *d, int thumb, int thumbSize) { |
134 | const int oldThumb = d->thumb; | ||
90 | d->thumb = thumb; | 135 | d->thumb = thumb; |
91 | d->thumbSize = thumbSize; | 136 | d->thumbSize = thumbSize; |
92 | checkVisible_ScrollWidget_(d); | 137 | checkVisible_ScrollWidget_(d); |
138 | if (oldThumb != d->thumb && thumbSize) { | ||
139 | unfade_ScrollWidget_(d, 1.0f); | ||
140 | } | ||
93 | } | 141 | } |
94 | 142 | ||
95 | static iBool processEvent_ScrollWidget_(iScrollWidget *d, const SDL_Event *ev) { | 143 | static iBool processEvent_ScrollWidget_(iScrollWidget *d, const SDL_Event *ev) { |
@@ -97,6 +145,25 @@ static iBool processEvent_ScrollWidget_(iScrollWidget *d, const SDL_Event *ev) { | |||
97 | if (isMetricsChange_UserEvent(ev)) { | 145 | if (isMetricsChange_UserEvent(ev)) { |
98 | updateMetrics_ScrollWidget_(d); | 146 | updateMetrics_ScrollWidget_(d); |
99 | } | 147 | } |
148 | if (ev->type == SDL_MOUSEMOTION) { | ||
149 | const iInt2 mouse = init_I2(ev->motion.x, ev->motion.y); | ||
150 | const iBool isNearby = containsExpanded_Widget(&d->widget, mouse, 4 * gap_UI); | ||
151 | const iBool isOver = isNearby && contains_Rect(thumbRect_ScrollWidget_(d), mouse); | ||
152 | if (isNearby) { | ||
153 | unfade_ScrollWidget_(d, isOver ? 1.0f : 0.4f); | ||
154 | } | ||
155 | } | ||
156 | if (isCommand_UserEvent(ev, "scrollbar.fade")) { | ||
157 | if (d->willCheckFade && SDL_GetTicks() > d->fadeStart) { | ||
158 | setValue_Anim(&d->opacity, minOpacity_(), 200); | ||
159 | remove_Periodic(periodic_App(), d); | ||
160 | d->willCheckFade = iFalse; | ||
161 | if (!isFinished_Anim(&d->opacity)) { | ||
162 | addTicker_App(animateOpacity_ScrollWidget_, d); | ||
163 | } | ||
164 | } | ||
165 | return iFalse; | ||
166 | } | ||
100 | switch (processEvent_Click(&d->click, ev)) { | 167 | switch (processEvent_Click(&d->click, ev)) { |
101 | case started_ClickResult: | 168 | case started_ClickResult: |
102 | setFlags_Widget(w, pressed_WidgetFlag, iTrue); | 169 | setFlags_Widget(w, pressed_WidgetFlag, iTrue); |
@@ -146,10 +213,18 @@ static void draw_ScrollWidget_(const iScrollWidget *d) { | |||
146 | if (bounds.size.x > 0) { | 213 | if (bounds.size.x > 0) { |
147 | iPaint p; | 214 | iPaint p; |
148 | init_Paint(&p); | 215 | init_Paint(&p); |
149 | //drawVLine_Paint(&p, topLeft_Rect(bounds), height_Rect(bounds), uiSeparator_ColorId); | 216 | /* Blend if opacity is not at maximum. */ |
217 | p.alpha = 255 * value_Anim(&d->opacity); | ||
218 | SDL_Renderer *render = renderer_Window(get_Window()); | ||
219 | if (p.alpha < 255) { | ||
220 | SDL_SetRenderDrawBlendMode(render, SDL_BLENDMODE_BLEND); | ||
221 | } | ||
150 | const iRect thumbRect = shrunk_Rect( | 222 | const iRect thumbRect = shrunk_Rect( |
151 | thumbRect_ScrollWidget_(d), init_I2(isPressed ? gap_UI : (gap_UI * 4 / 3), gap_UI / 2)); | 223 | thumbRect_ScrollWidget_(d), init_I2(isPressed ? gap_UI : (gap_UI * 4 / 3), gap_UI / 2)); |
152 | fillRect_Paint(&p, thumbRect, isPressed ? uiBackgroundPressed_ColorId : tmQuote_ColorId); | 224 | fillRect_Paint(&p, thumbRect, isPressed ? uiBackgroundPressed_ColorId : tmQuote_ColorId); |
225 | if (p.alpha < 255) { | ||
226 | SDL_SetRenderDrawBlendMode(render, SDL_BLENDMODE_NONE); | ||
227 | } | ||
153 | } | 228 | } |
154 | } | 229 | } |
155 | 230 | ||