diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-09-03 19:15:43 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-09-03 19:15:43 +0300 |
commit | 814c513984965d2732ef36215ba3fad97875af51 (patch) | |
tree | 115a3f56c18300693f6700ee5f788939b0a4e55f /src | |
parent | 4d39c1b06742d73efcdb9a64a213c927580dcf48 (diff) |
SidebarWidget: Faster hover change redraw
Don't redraw all the items, only the affected ones.
Diffstat (limited to 'src')
-rw-r--r-- | src/ui/sidebarwidget.c | 32 |
1 files changed, 26 insertions, 6 deletions
diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c index 40c3f55e..a919fca6 100644 --- a/src/ui/sidebarwidget.c +++ b/src/ui/sidebarwidget.c | |||
@@ -35,6 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
35 | #include "util.h" | 35 | #include "util.h" |
36 | #include "visited.h" | 36 | #include "visited.h" |
37 | 37 | ||
38 | #include <the_Foundation/intset.h> | ||
38 | #include <the_Foundation/stringarray.h> | 39 | #include <the_Foundation/stringarray.h> |
39 | #include <SDL_clipboard.h> | 40 | #include <SDL_clipboard.h> |
40 | #include <SDL_mouse.h> | 41 | #include <SDL_mouse.h> |
@@ -89,6 +90,7 @@ struct Impl_SidebarWidget { | |||
89 | iWidget *resizer; | 90 | iWidget *resizer; |
90 | SDL_Cursor *resizeCursor; | 91 | SDL_Cursor *resizeCursor; |
91 | iWidget *menu; | 92 | iWidget *menu; |
93 | iIntSet invalidItems; | ||
92 | SDL_Texture *visBuffer; | 94 | SDL_Texture *visBuffer; |
93 | iBool visBufferValid; | 95 | iBool visBufferValid; |
94 | }; | 96 | }; |
@@ -98,6 +100,7 @@ iDefineObjectConstruction(SidebarWidget) | |||
98 | static void invalidate_SidebarWidget_(iSidebarWidget *d) { | 100 | static void invalidate_SidebarWidget_(iSidebarWidget *d) { |
99 | d->visBufferValid = iFalse; | 101 | d->visBufferValid = iFalse; |
100 | refresh_Widget(as_Widget(d)); | 102 | refresh_Widget(as_Widget(d)); |
103 | clear_IntSet(&d->invalidItems); /* all will be drawn */ | ||
101 | } | 104 | } |
102 | 105 | ||
103 | static iBool isResizing_SidebarWidget_(const iSidebarWidget *d) { | 106 | static iBool isResizing_SidebarWidget_(const iSidebarWidget *d) { |
@@ -375,6 +378,7 @@ void init_SidebarWidget(iSidebarWidget *d) { | |||
375 | setBackgroundColor_Widget(d->resizer, none_ColorId); | 378 | setBackgroundColor_Widget(d->resizer, none_ColorId); |
376 | d->resizeCursor = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE); | 379 | d->resizeCursor = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE); |
377 | d->menu = NULL; | 380 | d->menu = NULL; |
381 | init_IntSet(&d->invalidItems); | ||
378 | d->visBuffer = NULL; | 382 | d->visBuffer = NULL; |
379 | d->visBufferValid = iFalse; | 383 | d->visBufferValid = iFalse; |
380 | } | 384 | } |
@@ -441,8 +445,10 @@ static void setHoverItem_SidebarWidget_(iSidebarWidget *d, size_t index) { | |||
441 | } | 445 | } |
442 | } | 446 | } |
443 | if (d->hoverItem != index) { | 447 | if (d->hoverItem != index) { |
448 | insert_IntSet(&d->invalidItems, d->hoverItem); | ||
449 | insert_IntSet(&d->invalidItems, index); | ||
444 | d->hoverItem = index; | 450 | d->hoverItem = index; |
445 | invalidate_SidebarWidget_(d); | 451 | refresh_Widget(as_Widget(d)); |
446 | } | 452 | } |
447 | } | 453 | } |
448 | 454 | ||
@@ -841,14 +847,14 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev) | |||
841 | processContextMenuEvent_Widget(d->menu, ev, {}); | 847 | processContextMenuEvent_Widget(d->menu, ev, {}); |
842 | switch (processEvent_Click(&d->click, ev)) { | 848 | switch (processEvent_Click(&d->click, ev)) { |
843 | case started_ClickResult: | 849 | case started_ClickResult: |
844 | invalidate_SidebarWidget_(d); | 850 | //invalidate_SidebarWidget_(d); |
845 | break; | 851 | break; |
846 | case finished_ClickResult: | 852 | case finished_ClickResult: |
847 | if (contains_Rect(contentBounds_SidebarWidget_(d), pos_Click(&d->click)) && | 853 | if (contains_Rect(contentBounds_SidebarWidget_(d), pos_Click(&d->click)) && |
848 | d->hoverItem != iInvalidSize) { | 854 | d->hoverItem != iInvalidSize) { |
849 | itemClicked_SidebarWidget_(d, d->hoverItem); | 855 | itemClicked_SidebarWidget_(d, d->hoverItem); |
850 | } | 856 | } |
851 | invalidate_SidebarWidget_(d); | 857 | // invalidate_SidebarWidget_(d); |
852 | break; | 858 | break; |
853 | default: | 859 | default: |
854 | break; | 860 | break; |
@@ -881,17 +887,24 @@ static void draw_SidebarWidget_(const iSidebarWidget *d) { | |||
881 | const int bg = | 887 | const int bg = |
882 | d->mode == documentOutline_SidebarMode ? tmBackground_ColorId : uiBackground_ColorId; | 888 | d->mode == documentOutline_SidebarMode ? tmBackground_ColorId : uiBackground_ColorId; |
883 | fillRect_Paint(&p, bounds_Widget(w), bg); /* TODO: should do only the mode buttons area */ | 889 | fillRect_Paint(&p, bounds_Widget(w), bg); /* TODO: should do only the mode buttons area */ |
884 | if (!d->visBufferValid) { | 890 | if (!d->visBufferValid || !isEmpty_IntSet(&d->invalidItems)) { |
885 | allocVisBuffer_SidebarWidget_(iConstCast(iSidebarWidget *, d)); | 891 | allocVisBuffer_SidebarWidget_(iConstCast(iSidebarWidget *, d)); |
886 | iRect bufBounds = bounds; | 892 | iRect bufBounds = bounds; |
887 | bufBounds.pos = zero_I2(); | 893 | bufBounds.pos = zero_I2(); |
888 | beginTarget_Paint(&p, d->visBuffer); | 894 | beginTarget_Paint(&p, d->visBuffer); |
889 | fillRect_Paint(&p, bufBounds, bg); | 895 | if (!d->visBufferValid) { |
896 | fillRect_Paint(&p, bufBounds, bg); | ||
897 | } | ||
890 | /* Draw the items. */ { | 898 | /* Draw the items. */ { |
891 | const int font = uiContent_FontId; | 899 | const int font = uiContent_FontId; |
892 | const iRanges visRange = visRange_SidebarWidget_(d); | 900 | const iRanges visRange = visRange_SidebarWidget_(d); |
893 | iInt2 pos = addY_I2(topLeft_Rect(bufBounds), -(d->scrollY % d->itemHeight)); | 901 | iInt2 pos = addY_I2(topLeft_Rect(bufBounds), -(d->scrollY % d->itemHeight)); |
894 | for (size_t i = visRange.start; i < visRange.end; i++) { | 902 | for (size_t i = visRange.start; i < visRange.end; i++) { |
903 | if (d->visBufferValid && !contains_IntSet(&d->invalidItems, i)) { | ||
904 | /* TODO: Refactor to loop through invalidItems only. */ | ||
905 | pos.y += d->itemHeight; | ||
906 | continue; | ||
907 | } | ||
895 | const iSidebarItem *item = constAt_Array(&d->items, i); | 908 | const iSidebarItem *item = constAt_Array(&d->items, i); |
896 | const iRect itemRect = { pos, init_I2(width_Rect(bufBounds), d->itemHeight) }; | 909 | const iRect itemRect = { pos, init_I2(width_Rect(bufBounds), d->itemHeight) }; |
897 | const iBool isHover = isHover_Widget(w) && (d->hoverItem == i); | 910 | const iBool isHover = isHover_Widget(w) && (d->hoverItem == i); |
@@ -905,6 +918,9 @@ static void draw_SidebarWidget_(const iSidebarWidget *d) { | |||
905 | isPressing ? uiBackgroundPressed_ColorId | 918 | isPressing ? uiBackgroundPressed_ColorId |
906 | : uiBackgroundFramelessHover_ColorId); | 919 | : uiBackgroundFramelessHover_ColorId); |
907 | } | 920 | } |
921 | else if (d->visBufferValid) { | ||
922 | fillRect_Paint(&p, itemRect, bg); | ||
923 | } | ||
908 | if (d->mode == documentOutline_SidebarMode) { | 924 | if (d->mode == documentOutline_SidebarMode) { |
909 | const int fg = isHover ? (isPressing ? uiTextPressed_ColorId | 925 | const int fg = isHover ? (isPressing ? uiTextPressed_ColorId |
910 | : uiTextFramelessHover_ColorId) | 926 | : uiTextFramelessHover_ColorId) |
@@ -1016,7 +1032,11 @@ static void draw_SidebarWidget_(const iSidebarWidget *d) { | |||
1016 | } | 1032 | } |
1017 | } | 1033 | } |
1018 | endTarget_Paint(&p); | 1034 | endTarget_Paint(&p); |
1019 | iConstCast(iSidebarWidget *, d)->visBufferValid = iTrue; | 1035 | /* Update state. */ { |
1036 | iSidebarWidget *m = iConstCast(iSidebarWidget *, d); | ||
1037 | m->visBufferValid = iTrue; | ||
1038 | clear_IntSet(&m->invalidItems); | ||
1039 | } | ||
1020 | } | 1040 | } |
1021 | SDL_RenderCopy( | 1041 | SDL_RenderCopy( |
1022 | renderer_Window(get_Window()), d->visBuffer, NULL, (const SDL_Rect *) &bounds); | 1042 | renderer_Window(get_Window()), d->visBuffer, NULL, (const SDL_Rect *) &bounds); |