summaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/listwidget.c10
-rw-r--r--src/ui/scrollwidget.c85
-rw-r--r--src/ui/sidebarwidget.c11
-rw-r--r--src/ui/util.c3
-rw-r--r--src/ui/util.h1
-rw-r--r--src/ui/widget.c19
-rw-r--r--src/ui/widget.h31
-rw-r--r--src/ui/window.c2
8 files changed, 128 insertions, 34 deletions
diff --git a/src/ui/listwidget.c b/src/ui/listwidget.c
index 237562ca..f351c3b3 100644
--- a/src/ui/listwidget.c
+++ b/src/ui/listwidget.c
@@ -379,9 +379,13 @@ static void draw_ListWidget_(const iListWidget *d) {
379 beginTarget_Paint(&p, buf->texture); 379 beginTarget_Paint(&p, buf->texture);
380 fillRect_Paint(&p, (iRect){ zero_I2(), d->visBuf->texSize }, bg[i]); 380 fillRect_Paint(&p, (iRect){ zero_I2(), d->visBuf->texSize }, bg[i]);
381 } 381 }
382 const iRect sbBlankRect = 382#if defined (iPlatformApple)
383 { init_I2(d->visBuf->texSize.x - scrollBarWidth_ListWidget(d), 0), 383 const int blankWidth = 0; /* scrollbars fade away */
384 init_I2(scrollBarWidth_ListWidget(d), d->itemHeight) }; 384#else
385 const int blankWidth = scrollBarWidth_ListWidget(d);
386#endif
387 const iRect sbBlankRect = { init_I2(d->visBuf->texSize.x - blankWidth, 0),
388 init_I2(blankWidth, d->itemHeight) };
385 iConstForEach(IntSet, v, &d->invalidItems) { 389 iConstForEach(IntSet, v, &d->invalidItems) {
386 const size_t index = *v.value; 390 const size_t index = *v.value;
387 if (contains_Range(&drawItems, index)) { 391 if (contains_Range(&drawItems, index)) {
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
27iDefineObjectConstruction(ScrollWidget) 31iDefineObjectConstruction(ScrollWidget)
28 32
33static 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
29struct Impl_ScrollWidget { 43struct 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
38static void updateMetrics_ScrollWidget_(iScrollWidget *d) { 55static 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
59static 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
42void init_ScrollWidget(iScrollWidget *d) { 67void 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
54void deinit_ScrollWidget(iScrollWidget *d) { 81void deinit_ScrollWidget(iScrollWidget *d) {
55 iUnused(d); 82 remove_Periodic(periodic_App(), d);
83 removeTicker_App(animateOpacity_ScrollWidget_, d);
56} 84}
57 85
58static int thumbSize_ScrollWidget_(const iScrollWidget *d) { 86static 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
105static 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
77static void checkVisible_ScrollWidget_(iScrollWidget *d) { 118static 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
83void setRange_ScrollWidget(iScrollWidget *d, iRangei range) { 127void setRange_ScrollWidget(iScrollWidget *d, iRangei range) {
@@ -87,9 +131,13 @@ void setRange_ScrollWidget(iScrollWidget *d, iRangei range) {
87} 131}
88 132
89void setThumb_ScrollWidget(iScrollWidget *d, int thumb, int thumbSize) { 133void 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
95static iBool processEvent_ScrollWidget_(iScrollWidget *d, const SDL_Event *ev) { 143static 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
diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c
index 802669c7..ac119575 100644
--- a/src/ui/sidebarwidget.c
+++ b/src/ui/sidebarwidget.c
@@ -143,7 +143,7 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) {
143 iDate on; 143 iDate on;
144 initCurrent_Time(&now); 144 initCurrent_Time(&now);
145 init_Date(&on, &now); 145 init_Date(&on, &now);
146 const int thisYear = on.year; 146 const iDate today = on;
147 iZap(on); 147 iZap(on);
148 size_t numItems = 0; 148 size_t numItems = 0;
149 iConstForEach(PtrArray, i, listEntries_Feeds()) { 149 iConstForEach(PtrArray, i, listEntries_Feeds()) {
@@ -1306,6 +1306,11 @@ static void draw_SidebarItem_(const iSidebarItem *d, iPaint *p, iRect itemRect,
1306 const iBool isHover = isHover_Widget(constAs_Widget(list)) && 1306 const iBool isHover = isHover_Widget(constAs_Widget(list)) &&
1307 constHoverItem_ListWidget(list) == d; 1307 constHoverItem_ListWidget(list) == d;
1308 const int scrollBarWidth = scrollBarWidth_ListWidget(list); 1308 const int scrollBarWidth = scrollBarWidth_ListWidget(list);
1309#if defined (iPlatformApple)
1310 const int blankWidth = 0;
1311#else
1312 const int blankWidth = scrollBarWidth;
1313#endif
1309 const int itemHeight = height_Rect(itemRect); 1314 const int itemHeight = height_Rect(itemRect);
1310 const int iconColor = isHover ? (isPressing ? uiTextPressed_ColorId : uiIconHover_ColorId) 1315 const int iconColor = isHover ? (isPressing ? uiTextPressed_ColorId : uiIconHover_ColorId)
1311 : uiIcon_ColorId; 1316 : uiIcon_ColorId;
@@ -1345,7 +1350,7 @@ static void draw_SidebarItem_(const iSidebarItem *d, iPaint *p, iRect itemRect,
1345 if (d != constItem_ListWidget(list, 0)) { 1350 if (d != constItem_ListWidget(list, 0)) {
1346 drawHLine_Paint(p, 1351 drawHLine_Paint(p,
1347 addY_I2(pos, 2 * gap_UI), 1352 addY_I2(pos, 2 * gap_UI),
1348 width_Rect(itemRect) - scrollBarWidth, 1353 width_Rect(itemRect) - blankWidth,
1349 uiSeparator_ColorId); 1354 uiSeparator_ColorId);
1350 } 1355 }
1351 drawRange_Text( 1356 drawRange_Text(
@@ -1463,7 +1468,7 @@ static void draw_SidebarItem_(const iSidebarItem *d, iPaint *p, iRect itemRect,
1463 iInt2 drawPos = addY_I2(topLeft_Rect(itemRect), d->id); 1468 iInt2 drawPos = addY_I2(topLeft_Rect(itemRect), d->id);
1464 drawHLine_Paint(p, 1469 drawHLine_Paint(p,
1465 addY_I2(drawPos, -gap_UI), 1470 addY_I2(drawPos, -gap_UI),
1466 width_Rect(itemRect) - scrollBarWidth, 1471 width_Rect(itemRect) - blankWidth,
1467 uiSeparator_ColorId); 1472 uiSeparator_ColorId);
1468 drawRange_Text( 1473 drawRange_Text(
1469 uiLabelLargeBold_FontId, 1474 uiLabelLargeBold_FontId,
diff --git a/src/ui/util.c b/src/ui/util.c
index e07e036a..13d1bf78 100644
--- a/src/ui/util.c
+++ b/src/ui/util.c
@@ -401,6 +401,7 @@ static iBool isCommandIgnoredByMenus_(const char *cmd) {
401 equal_Command(cmd, "document.request.updated") || 401 equal_Command(cmd, "document.request.updated") ||
402 equal_Command(cmd, "document.request.finished") || 402 equal_Command(cmd, "document.request.finished") ||
403 equal_Command(cmd, "document.changed") || 403 equal_Command(cmd, "document.changed") ||
404 equal_Command(cmd, "scrollbar.fade") ||
404 equal_Command(cmd, "visited.changed") || 405 equal_Command(cmd, "visited.changed") ||
405 (deviceType_App() == desktop_AppDeviceType && equal_Command(cmd, "window.resized")) || 406 (deviceType_App() == desktop_AppDeviceType && equal_Command(cmd, "window.resized")) ||
406 equal_Command(cmd, "widget.overflow") || 407 equal_Command(cmd, "widget.overflow") ||
@@ -1634,12 +1635,14 @@ void updateValueInput_Widget(iWidget *d, const char *title, const char *prompt)
1634 1635
1635static iBool messageHandler_(iWidget *msg, const char *cmd) { 1636static iBool messageHandler_(iWidget *msg, const char *cmd) {
1636 /* Almost any command dismisses the sheet. */ 1637 /* Almost any command dismisses the sheet. */
1638 /* TODO: Use a "notification" prefix (like `) to ignore all types of commands line this? */
1637 if (!(equal_Command(cmd, "media.updated") || 1639 if (!(equal_Command(cmd, "media.updated") ||
1638 equal_Command(cmd, "media.player.update") || 1640 equal_Command(cmd, "media.player.update") ||
1639 equal_Command(cmd, "bookmarks.request.finished") || 1641 equal_Command(cmd, "bookmarks.request.finished") ||
1640 equal_Command(cmd, "document.autoreload") || 1642 equal_Command(cmd, "document.autoreload") ||
1641 equal_Command(cmd, "document.reload") || 1643 equal_Command(cmd, "document.reload") ||
1642 equal_Command(cmd, "document.request.updated") || 1644 equal_Command(cmd, "document.request.updated") ||
1645 equal_Command(cmd, "scrollbar.fade") ||
1643 equal_Command(cmd, "widget.overflow") || 1646 equal_Command(cmd, "widget.overflow") ||
1644 startsWith_CStr(cmd, "window."))) { 1647 startsWith_CStr(cmd, "window."))) {
1645 destroy_Widget(msg); 1648 destroy_Widget(msg);
diff --git a/src/ui/util.h b/src/ui/util.h
index 35e10c6f..09e52a4d 100644
--- a/src/ui/util.h
+++ b/src/ui/util.h
@@ -102,7 +102,6 @@ struct Impl_Anim {
102 102
103void init_Anim (iAnim *, float value); 103void init_Anim (iAnim *, float value);
104void setValue_Anim (iAnim *, float to, uint32_t span); 104void setValue_Anim (iAnim *, float to, uint32_t span);
105void setValueLinear_Anim (iAnim *, float to, uint32_t span);
106void setValueEased_Anim (iAnim *, float to, uint32_t span); 105void setValueEased_Anim (iAnim *, float to, uint32_t span);
107void setFlags_Anim (iAnim *, int flags, iBool set); 106void setFlags_Anim (iAnim *, int flags, iBool set);
108void stop_Anim (iAnim *); 107void stop_Anim (iAnim *);
diff --git a/src/ui/widget.c b/src/ui/widget.c
index d5e639fd..4f5d174c 100644
--- a/src/ui/widget.c
+++ b/src/ui/widget.c
@@ -582,10 +582,17 @@ iInt2 localCoord_Widget(const iWidget *d, iInt2 coord) {
582} 582}
583 583
584iBool contains_Widget(const iWidget *d, iInt2 coord) { 584iBool contains_Widget(const iWidget *d, iInt2 coord) {
585 const iRect bounds = { zero_I2(), addY_I2(d->rect.size, 585 return containsExpanded_Widget(d, coord, 0);
586 d->flags & drawBackgroundToBottom_WidgetFlag ? 586}
587 rootSize_Window(get_Window()).y : 0) }; 587
588 return contains_Rect(bounds, localCoord_Widget(d, coord)); 588iBool containsExpanded_Widget(const iWidget *d, iInt2 coord, int expand) {
589 const iRect bounds = {
590 zero_I2(),
591 addY_I2(d->rect.size,
592 d->flags & drawBackgroundToBottom_WidgetFlag ? rootSize_Window(get_Window()).y : 0)
593 };
594 return contains_Rect(expand ? expanded_Rect(bounds, init1_I2(expand)) : bounds,
595 localCoord_Widget(d, coord));
589} 596}
590 597
591iLocalDef iBool isKeyboardEvent_(const SDL_Event *ev) { 598iLocalDef iBool isKeyboardEvent_(const SDL_Event *ev) {
@@ -854,8 +861,8 @@ void drawBackground_Widget(const iWidget *d) {
854 const iBool isLight = isLight_ColorTheme(colorTheme_App()); 861 const iBool isLight = isLight_ColorTheme(colorTheme_App());
855 p.alpha = isLight ? 0xc : 0x20; 862 p.alpha = isLight ? 0xc : 0x20;
856 SDL_SetRenderDrawBlendMode(renderer_Window(get_Window()), SDL_BLENDMODE_BLEND); 863 SDL_SetRenderDrawBlendMode(renderer_Window(get_Window()), SDL_BLENDMODE_BLEND);
857 iRect shadowRect = expanded_Rect(bounds_Widget(d), mulf_I2(gap2_UI, 1)); 864 iRect shadowRect = expanded_Rect(bounds_Widget(d), mulf_I2(gap2_UI, 8));
858 shadowRect.pos.y += gap_UI / 4; 865// shadowRect.pos.y += gap_UI * 4;
859 fillRect_Paint(&p, shadowRect, /*isLight ? white_ColorId :*/ black_ColorId); 866 fillRect_Paint(&p, shadowRect, /*isLight ? white_ColorId :*/ black_ColorId);
860 SDL_SetRenderDrawBlendMode(renderer_Window(get_Window()), SDL_BLENDMODE_NONE); 867 SDL_SetRenderDrawBlendMode(renderer_Window(get_Window()), SDL_BLENDMODE_NONE);
861 } 868 }
diff --git a/src/ui/widget.h b/src/ui/widget.h
index 88d75b62..90ccac8e 100644
--- a/src/ui/widget.h
+++ b/src/ui/widget.h
@@ -161,21 +161,22 @@ void destroy_Widget (iWidget *); /* widget removed and deleted later
161void destroyPending_Widget (void); 161void destroyPending_Widget (void);
162void releaseChildren_Widget (iWidget *); 162void releaseChildren_Widget (iWidget *);
163 163
164const iString *id_Widget (const iWidget *); 164const iString *id_Widget (const iWidget *);
165int64_t flags_Widget (const iWidget *); 165int64_t flags_Widget (const iWidget *);
166iRect bounds_Widget (const iWidget *); /* outer bounds */ 166iRect bounds_Widget (const iWidget *); /* outer bounds */
167iRect innerBounds_Widget (const iWidget *); 167iRect innerBounds_Widget (const iWidget *);
168iInt2 localCoord_Widget (const iWidget *, iInt2 coord); 168iInt2 localCoord_Widget (const iWidget *, iInt2 coord);
169iBool contains_Widget (const iWidget *, iInt2 coord); 169iBool contains_Widget (const iWidget *, iInt2 coord);
170iAny * hitChild_Widget (const iWidget *, iInt2 coord); 170iBool containsExpanded_Widget (const iWidget *, iInt2 coord, int expand);
171iAny * findChild_Widget (const iWidget *, const char *id); 171iAny * hitChild_Widget (const iWidget *, iInt2 coord);
172const iPtrArray *findChildren_Widget (const iWidget *, const char *id); 172iAny * findChild_Widget (const iWidget *, const char *id);
173iAny * findParentClass_Widget(const iWidget *, const iAnyClass *class); 173const iPtrArray *findChildren_Widget (const iWidget *, const char *id);
174iAny * findFocusable_Widget(const iWidget *startFrom, enum iWidgetFocusDir focusDir); 174iAny * findParentClass_Widget (const iWidget *, const iAnyClass *class);
175size_t childCount_Widget (const iWidget *); 175iAny * findFocusable_Widget (const iWidget *startFrom, enum iWidgetFocusDir focusDir);
176void draw_Widget (const iWidget *); 176size_t childCount_Widget (const iWidget *);
177void drawBackground_Widget(const iWidget *); 177void draw_Widget (const iWidget *);
178void drawChildren_Widget (const iWidget *); 178void drawBackground_Widget (const iWidget *);
179void drawChildren_Widget (const iWidget *);
179 180
180iLocalDef int width_Widget(const iAnyObject *d) { 181iLocalDef int width_Widget(const iAnyObject *d) {
181 if (d) { 182 if (d) {
diff --git a/src/ui/window.c b/src/ui/window.c
index 1c0c0394..e7945c62 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -1827,7 +1827,7 @@ void draw_Window(iWindow *d) {
1827 } 1827 }
1828 } 1828 }
1829#endif 1829#endif
1830 const int winFlags = SDL_GetWindowFlags(d->win); 1830 const int winFlags = SDL_GetWindowFlags(d->win);
1831 const iBool gotFocus = (winFlags & SDL_WINDOW_INPUT_FOCUS) != 0; 1831 const iBool gotFocus = (winFlags & SDL_WINDOW_INPUT_FOCUS) != 0;
1832 /* Clear the window. The clear color is visible as a border around the window 1832 /* Clear the window. The clear color is visible as a border around the window
1833 when the custom frame is being used. */ { 1833 when the custom frame is being used. */ {