summaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2020-10-30 09:08:09 +0200
committerJaakko Keränen <jaakko.keranen@iki.fi>2020-10-30 09:08:09 +0200
commitb1e9b313f6810afbadde0f8079326ecf04c89817 (patch)
tree93299da98c3f3fdffadb1e09a51ccd56df71b8f1 /src/ui
parent653c055d145d940a318025ca74762f6b8024bf5a (diff)
Added a key binding mechanism
The document scrolling keys are now handled via bindings.
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/documentwidget.c75
-rw-r--r--src/ui/keys.c154
-rw-r--r--src/ui/keys.h17
3 files changed, 205 insertions, 41 deletions
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index 5c6780d1..a2bea17b 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -1536,7 +1536,7 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)
1536 updateVisible_DocumentWidget_(d); 1536 updateVisible_DocumentWidget_(d);
1537 return iTrue; 1537 return iTrue;
1538 } 1538 }
1539 else if (equalWidget_Command(cmd, w, "scroll.page")) { 1539 else if (equal_Command(cmd, "scroll.page") && document_App() == d) {
1540 if (argLabel_Command(cmd, "repeat")) { 1540 if (argLabel_Command(cmd, "repeat")) {
1541 /* TODO: Adjust scroll animation to be linear during repeated scroll? */ 1541 /* TODO: Adjust scroll animation to be linear during repeated scroll? */
1542 } 1542 }
@@ -1547,6 +1547,40 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)
1547 smoothDuration_DocumentWidget_); 1547 smoothDuration_DocumentWidget_);
1548 return iTrue; 1548 return iTrue;
1549 } 1549 }
1550 else if (equal_Command(cmd, "scroll.top") && document_App() == d) {
1551 init_Anim(&d->scrollY, 0);
1552 invalidate_VisBuf(d->visBuf);
1553 scroll_DocumentWidget_(d, 0);
1554 updateVisible_DocumentWidget_(d);
1555 refresh_Widget(w);
1556 return iTrue;
1557 }
1558 else if (equal_Command(cmd, "scroll.bottom") && document_App() == d) {
1559 init_Anim(&d->scrollY, scrollMax_DocumentWidget_(d));
1560 invalidate_VisBuf(d->visBuf);
1561 scroll_DocumentWidget_(d, 0);
1562 updateVisible_DocumentWidget_(d);
1563 refresh_Widget(w);
1564 return iTrue;
1565 }
1566 else if (equal_Command(cmd, "scroll.step") && document_App() == d) {
1567 smoothScroll_DocumentWidget_(d,
1568 3 * lineHeight_Text(paragraph_FontId) * arg_Command(cmd),
1569 smoothDuration_DocumentWidget_);
1570 return iTrue;
1571 }
1572#if 0
1573 case SDLK_PAGEUP:
1574 case SDLK_PAGEDOWN:
1575 case SDLK_SPACE:
1576 postCommand_Widget(
1577 w,
1578 "scroll.page arg:%d repeat:%d",
1579 (key == SDLK_SPACE && mods & KMOD_SHIFT) || key == SDLK_PAGEUP ? -1 : +1,
1580 ev->key.repeat != 0);
1581 return iTrue;
1582 }
1583#endif
1550 else if (equal_Command(cmd, "document.goto") && document_App() == d) { 1584 else if (equal_Command(cmd, "document.goto") && document_App() == d) {
1551 const iRangecc heading = range_Command(cmd, "heading"); 1585 const iRangecc heading = range_Command(cmd, "heading");
1552 if (heading.start) { 1586 if (heading.start) {
@@ -1790,45 +1824,6 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e
1790 refresh_Widget(w); 1824 refresh_Widget(w);
1791 } 1825 }
1792 break; 1826 break;
1793 case SDLK_HOME:
1794 init_Anim(&d->scrollY, 0);
1795 invalidate_VisBuf(d->visBuf);
1796 scroll_DocumentWidget_(d, 0);
1797 updateVisible_DocumentWidget_(d);
1798 refresh_Widget(w);
1799 return iTrue;
1800 case SDLK_END:
1801 init_Anim(&d->scrollY, scrollMax_DocumentWidget_(d));
1802 invalidate_VisBuf(d->visBuf);
1803 scroll_DocumentWidget_(d, 0);
1804 updateVisible_DocumentWidget_(d);
1805 refresh_Widget(w);
1806 return iTrue;
1807 case SDLK_UP:
1808 case SDLK_DOWN:
1809 if (mods == 0) {
1810 if (ev->key.repeat) {
1811// if (!d->smoothContinue) {
1812// d->smoothContinue = iTrue;
1813// }
1814// else return iTrue;
1815 }
1816 smoothScroll_DocumentWidget_(d,
1817 3 * lineHeight_Text(paragraph_FontId) *
1818 (key == SDLK_UP ? -1 : 1),
1819 /*gap_Text * */smoothDuration_DocumentWidget_);
1820 return iTrue;
1821 }
1822 break;
1823 case SDLK_PAGEUP:
1824 case SDLK_PAGEDOWN:
1825 case SDLK_SPACE:
1826 postCommand_Widget(
1827 w,
1828 "scroll.page arg:%d repeat:%d",
1829 (key == SDLK_SPACE && mods & KMOD_SHIFT) || key == SDLK_PAGEUP ? -1 : +1,
1830 ev->key.repeat != 0);
1831 return iTrue;
1832#if 1 1827#if 1
1833 case SDLK_KP_1: 1828 case SDLK_KP_1:
1834 case '`': { 1829 case '`': {
diff --git a/src/ui/keys.c b/src/ui/keys.c
new file mode 100644
index 00000000..d46d20bf
--- /dev/null
+++ b/src/ui/keys.c
@@ -0,0 +1,154 @@
1/* Copyright 2020 Jaakko Keränen <jaakko.keranen@iki.fi>
2
3Redistribution and use in source and binary forms, with or without
4modification, are permitted provided that the following conditions are met:
5
61. Redistributions of source code must retain the above copyright notice, this
7 list of conditions and the following disclaimer.
82. Redistributions in binary form must reproduce the above copyright notice,
9 this list of conditions and the following disclaimer in the documentation
10 and/or other materials provided with the distribution.
11
12THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
13ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
16ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
18LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
19ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
22
23#include "keys.h"
24#include "util.h"
25#include "app.h"
26
27#include <the_Foundation/sortedarray.h>
28
29iDeclareType(Keys)
30iDeclareType(Binding)
31
32struct Impl_Binding {
33 int key;
34 int mods;
35 iString command;
36 iString label;
37};
38
39static int cmp_Binding_(const void *a, const void *b) {
40 const iBinding *d = a, *other = b;
41 const int cmp = iCmp(d->key, other->key);
42 if (cmp == 0) {
43 return iCmp(d->mods, other->mods);
44 }
45 return cmp;
46}
47
48struct Impl_Keys {
49 iSortedArray bindings;
50};
51
52static iKeys keys_;
53
54static void clear_Keys_(iKeys *d) {
55 iForEach(Array, i, &d->bindings.values) {
56 iBinding *bind = i.value;
57 deinit_String(&bind->command);
58 deinit_String(&bind->label);
59 }
60}
61
62static void bindDefaults_(void) {
63 bind_Keys("scroll.top", SDLK_HOME, 0);
64 bind_Keys("scroll.bottom", SDLK_END, 0);
65 bind_Keys("scroll.step arg:-1", SDLK_UP, 0);
66 bind_Keys("scroll.step arg:1", SDLK_DOWN, 0);
67 bind_Keys("scroll.page arg:-1", SDLK_PAGEUP, 0);
68 bind_Keys("scroll.page arg:-1", SDLK_SPACE, KMOD_SHIFT);
69 bind_Keys("scroll.page arg:1", SDLK_PAGEDOWN, 0);
70 bind_Keys("scroll.page arg:1", SDLK_SPACE, 0);
71}
72
73static iBinding *find_Keys_(iKeys *d, int key, int mods) {
74 const iBinding bind = { .key = key, .mods = mods };
75 size_t pos;
76 if (locate_SortedArray(&d->bindings, &bind, &pos)) {
77 return at_SortedArray(&d->bindings, pos);
78 }
79 return NULL;
80}
81
82static iBinding *findCommand_Keys_(iKeys *d, const char *command) {
83 /* Note: O(n) */
84 iForEach(Array, i, &d->bindings.values) {
85 iBinding *bind = i.value;
86 if (!cmp_String(&bind->command, command)) {
87 return bind;
88 }
89 }
90 return NULL;
91}
92
93/*----------------------------------------------------------------------------------------------*/
94
95void init_Keys(void) {
96 iKeys *d = &keys_;
97 init_SortedArray(&d->bindings, sizeof(iBinding), cmp_Binding_);
98 bindDefaults_();
99}
100
101void deinit_Keys(void) {
102 iKeys *d = &keys_;
103 clear_Keys_(d);
104 deinit_SortedArray(&d->bindings);
105}
106
107void load_Keys(const char *saveDir) {
108
109}
110
111void save_Keys(const char *saveDir) {
112
113}
114
115void bind_Keys(const char *command, int key, int mods) {
116 iKeys *d = &keys_;
117 iBinding *bind = find_Keys_(d, key, mods);
118 if (bind) {
119 setCStr_String(&bind->command, command);
120 }
121 else {
122 iBinding bind;
123 bind.key = key;
124 bind.mods = mods;
125 initCStr_String(&bind.command, command);
126 init_String(&bind.label);
127 insert_SortedArray(&d->bindings, &bind);
128 }
129}
130
131void setLabel_Keys(const char *command, const char *label) {
132 iBinding *bind = findCommand_Keys_(&keys_, command);
133 if (bind) {
134 setCStr_String(&bind->label, label);
135 }
136}
137
138//const iString *label_Keys(const char *command) {
139
140//}
141
142//const char *shortcutLabel_Keys(const char *command) {}
143
144iBool processEvent_Keys(const SDL_Event *ev) {
145 iKeys *d = &keys_;
146 if (ev->type == SDL_KEYDOWN) {
147 const iBinding *bind = find_Keys_(d, ev->key.keysym.sym, keyMods_Sym(ev->key.keysym.mod));
148 if (bind) {
149 postCommandString_App(&bind->command);
150 return iTrue;
151 }
152 }
153 return iFalse;
154}
diff --git a/src/ui/keys.h b/src/ui/keys.h
index a9b13df3..157ddea5 100644
--- a/src/ui/keys.h
+++ b/src/ui/keys.h
@@ -22,7 +22,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
22 22
23#pragma once 23#pragma once
24 24
25#include <the_Foundation/defs.h> 25#include <the_Foundation/string.h>
26#include <SDL_events.h>
26 27
27#if defined (iPlatformApple) 28#if defined (iPlatformApple)
28# define reload_KeyShortcut SDLK_r, KMOD_PRIMARY 29# define reload_KeyShortcut SDLK_r, KMOD_PRIMARY
@@ -41,3 +42,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
41# define byWord_KeyModifier KMOD_CTRL 42# define byWord_KeyModifier KMOD_CTRL
42# define byLine_KeyModifier 0 43# define byLine_KeyModifier 0
43#endif 44#endif
45
46void init_Keys (void);
47void deinit_Keys (void);
48
49void load_Keys (const char *saveDir);
50void save_Keys (const char *saveDir);
51
52void bind_Keys (const char *command, int key, int mods);
53void setLabel_Keys (const char *command, const char *label);
54
55//const iString * label_Keys (const char *command);
56//const char * shortcutLabel_Keys (const char *command);
57
58iBool processEvent_Keys (const SDL_Event *);