[FL-3373] Scroll acceleration (#2784)
* Support for scroll acceleration * Revert keyboard acceleration * Add scroll acceleration to the text box * Remove redundant code from the file manager input handler * Archive: slightly better scrolling * Gui,Archive: final version of accelerated scrolling Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
parent
761a14e6e2
commit
168fa72d53
@ -334,9 +334,22 @@ static bool archive_view_input(InputEvent* event, void* context) {
|
|||||||
browser->view,
|
browser->view,
|
||||||
ArchiveBrowserViewModel * model,
|
ArchiveBrowserViewModel * model,
|
||||||
{
|
{
|
||||||
|
int32_t scroll_speed = 1;
|
||||||
|
if(model->button_held_for_ticks > 5) {
|
||||||
|
if(model->button_held_for_ticks % 2) {
|
||||||
|
scroll_speed = 0;
|
||||||
|
} else {
|
||||||
|
scroll_speed = model->button_held_for_ticks > 9 ? 4 : 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(event->key == InputKeyUp) {
|
if(event->key == InputKeyUp) {
|
||||||
|
if(model->item_idx < scroll_speed) {
|
||||||
|
scroll_speed = model->item_idx;
|
||||||
|
}
|
||||||
|
|
||||||
model->item_idx =
|
model->item_idx =
|
||||||
((model->item_idx - 1) + model->item_cnt) % model->item_cnt;
|
((model->item_idx - scroll_speed) + model->item_cnt) % model->item_cnt;
|
||||||
if(is_file_list_load_required(model)) {
|
if(is_file_list_load_required(model)) {
|
||||||
model->list_loading = true;
|
model->list_loading = true;
|
||||||
browser->callback(ArchiveBrowserEventLoadPrevItems, browser->context);
|
browser->callback(ArchiveBrowserEventLoadPrevItems, browser->context);
|
||||||
@ -345,8 +358,14 @@ static bool archive_view_input(InputEvent* event, void* context) {
|
|||||||
browser->callback(ArchiveBrowserEventFavMoveUp, browser->context);
|
browser->callback(ArchiveBrowserEventFavMoveUp, browser->context);
|
||||||
}
|
}
|
||||||
model->scroll_counter = 0;
|
model->scroll_counter = 0;
|
||||||
|
model->button_held_for_ticks += 1;
|
||||||
} else if(event->key == InputKeyDown) {
|
} else if(event->key == InputKeyDown) {
|
||||||
model->item_idx = (model->item_idx + 1) % model->item_cnt;
|
int32_t count = model->item_cnt;
|
||||||
|
if(model->item_idx >= (count - scroll_speed)) {
|
||||||
|
scroll_speed = model->item_cnt - model->item_idx - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
model->item_idx = (model->item_idx + scroll_speed) % model->item_cnt;
|
||||||
if(is_file_list_load_required(model)) {
|
if(is_file_list_load_required(model)) {
|
||||||
model->list_loading = true;
|
model->list_loading = true;
|
||||||
browser->callback(ArchiveBrowserEventLoadNextItems, browser->context);
|
browser->callback(ArchiveBrowserEventLoadNextItems, browser->context);
|
||||||
@ -355,6 +374,7 @@ static bool archive_view_input(InputEvent* event, void* context) {
|
|||||||
browser->callback(ArchiveBrowserEventFavMoveDown, browser->context);
|
browser->callback(ArchiveBrowserEventFavMoveDown, browser->context);
|
||||||
}
|
}
|
||||||
model->scroll_counter = 0;
|
model->scroll_counter = 0;
|
||||||
|
model->button_held_for_ticks += 1;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
true);
|
true);
|
||||||
@ -391,6 +411,14 @@ static bool archive_view_input(InputEvent* event, void* context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(event->type == InputTypeRelease) {
|
||||||
|
with_view_model(
|
||||||
|
browser->view,
|
||||||
|
ArchiveBrowserViewModel * model,
|
||||||
|
{ model->button_held_for_ticks = 0; },
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -100,6 +100,8 @@ typedef struct {
|
|||||||
int32_t array_offset;
|
int32_t array_offset;
|
||||||
int32_t list_offset;
|
int32_t list_offset;
|
||||||
size_t scroll_counter;
|
size_t scroll_counter;
|
||||||
|
|
||||||
|
uint32_t button_held_for_ticks;
|
||||||
} ArchiveBrowserViewModel;
|
} ArchiveBrowserViewModel;
|
||||||
|
|
||||||
void archive_browser_set_callback(
|
void archive_browser_set_callback(
|
||||||
|
|||||||
@ -118,6 +118,8 @@ typedef struct {
|
|||||||
const Icon* file_icon;
|
const Icon* file_icon;
|
||||||
bool hide_ext;
|
bool hide_ext;
|
||||||
size_t scroll_counter;
|
size_t scroll_counter;
|
||||||
|
|
||||||
|
uint32_t button_held_for_ticks;
|
||||||
} FileBrowserModel;
|
} FileBrowserModel;
|
||||||
|
|
||||||
static const Icon* BrowserItemIcons[] = {
|
static const Icon* BrowserItemIcons[] = {
|
||||||
@ -589,9 +591,22 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context) {
|
|||||||
browser->view,
|
browser->view,
|
||||||
FileBrowserModel * model,
|
FileBrowserModel * model,
|
||||||
{
|
{
|
||||||
|
int32_t scroll_speed = 1;
|
||||||
|
if(model->button_held_for_ticks > 5) {
|
||||||
|
if(model->button_held_for_ticks % 2) {
|
||||||
|
scroll_speed = 0;
|
||||||
|
} else {
|
||||||
|
scroll_speed = model->button_held_for_ticks > 9 ? 5 : 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(event->key == InputKeyUp) {
|
if(event->key == InputKeyUp) {
|
||||||
|
if(model->item_idx < scroll_speed) {
|
||||||
|
scroll_speed = model->item_idx;
|
||||||
|
}
|
||||||
|
|
||||||
model->item_idx =
|
model->item_idx =
|
||||||
((model->item_idx - 1) + model->item_cnt) % model->item_cnt;
|
((model->item_idx - scroll_speed) + model->item_cnt) % model->item_cnt;
|
||||||
if(browser_is_list_load_required(model)) {
|
if(browser_is_list_load_required(model)) {
|
||||||
model->list_loading = true;
|
model->list_loading = true;
|
||||||
int32_t load_offset = CLAMP(
|
int32_t load_offset = CLAMP(
|
||||||
@ -602,8 +617,15 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context) {
|
|||||||
browser->worker, load_offset, ITEM_LIST_LEN_MAX);
|
browser->worker, load_offset, ITEM_LIST_LEN_MAX);
|
||||||
}
|
}
|
||||||
model->scroll_counter = 0;
|
model->scroll_counter = 0;
|
||||||
|
|
||||||
|
model->button_held_for_ticks += 1;
|
||||||
} else if(event->key == InputKeyDown) {
|
} else if(event->key == InputKeyDown) {
|
||||||
model->item_idx = (model->item_idx + 1) % model->item_cnt;
|
int32_t count = model->item_cnt;
|
||||||
|
if(model->item_idx + scroll_speed >= count) {
|
||||||
|
scroll_speed = count - model->item_idx - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
model->item_idx = (model->item_idx + scroll_speed) % model->item_cnt;
|
||||||
if(browser_is_list_load_required(model)) {
|
if(browser_is_list_load_required(model)) {
|
||||||
model->list_loading = true;
|
model->list_loading = true;
|
||||||
int32_t load_offset = CLAMP(
|
int32_t load_offset = CLAMP(
|
||||||
@ -614,11 +636,19 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context) {
|
|||||||
browser->worker, load_offset, ITEM_LIST_LEN_MAX);
|
browser->worker, load_offset, ITEM_LIST_LEN_MAX);
|
||||||
}
|
}
|
||||||
model->scroll_counter = 0;
|
model->scroll_counter = 0;
|
||||||
|
|
||||||
|
model->button_held_for_ticks += 1;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
true);
|
true);
|
||||||
browser_update_offset(browser);
|
browser_update_offset(browser);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
|
} else if(event->type == InputTypeRelease) {
|
||||||
|
with_view_model(
|
||||||
|
browser->view,
|
||||||
|
FileBrowserModel * model,
|
||||||
|
{ model->button_held_for_ticks = 0; },
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
} else if(event->key == InputKeyOk) {
|
} else if(event->key == InputKeyOk) {
|
||||||
if(event->type == InputTypeShort) {
|
if(event->type == InputTypeShort) {
|
||||||
|
|||||||
@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
struct TextBox {
|
struct TextBox {
|
||||||
View* view;
|
View* view;
|
||||||
|
|
||||||
|
uint16_t button_held_for_ticks;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -19,28 +21,39 @@ typedef struct {
|
|||||||
bool formatted;
|
bool formatted;
|
||||||
} TextBoxModel;
|
} TextBoxModel;
|
||||||
|
|
||||||
static void text_box_process_down(TextBox* text_box) {
|
static void text_box_process_down(TextBox* text_box, uint8_t lines) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
text_box->view,
|
text_box->view,
|
||||||
TextBoxModel * model,
|
TextBoxModel * model,
|
||||||
{
|
{
|
||||||
if(model->scroll_pos < model->scroll_num - 1) {
|
if(model->scroll_pos < model->scroll_num - lines) {
|
||||||
model->scroll_pos++;
|
model->scroll_pos += lines;
|
||||||
|
for(uint8_t i = 0; i < lines; i++) {
|
||||||
// Search next line start
|
// Search next line start
|
||||||
while(*model->text_pos++ != '\n')
|
while(*model->text_pos++ != '\n')
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
} else if(lines > 1) {
|
||||||
|
lines = model->scroll_num - model->scroll_pos - 1;
|
||||||
|
model->scroll_pos = model->scroll_num - 1;
|
||||||
|
for(uint8_t i = 0; i < lines; i++) {
|
||||||
|
// Search next line start
|
||||||
|
while(*model->text_pos++ != '\n')
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void text_box_process_up(TextBox* text_box) {
|
static void text_box_process_up(TextBox* text_box, uint8_t lines) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
text_box->view,
|
text_box->view,
|
||||||
TextBoxModel * model,
|
TextBoxModel * model,
|
||||||
{
|
{
|
||||||
if(model->scroll_pos > 0) {
|
if(model->scroll_pos > lines - 1) {
|
||||||
model->scroll_pos--;
|
model->scroll_pos -= lines;
|
||||||
|
for(uint8_t i = 0; i < lines; i++) {
|
||||||
// Reach last symbol of previous line
|
// Reach last symbol of previous line
|
||||||
model->text_pos--;
|
model->text_pos--;
|
||||||
// Search previous line start
|
// Search previous line start
|
||||||
@ -50,6 +63,11 @@ static void text_box_process_up(TextBox* text_box) {
|
|||||||
model->text_pos++;
|
model->text_pos++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if(lines > 1) {
|
||||||
|
lines = model->scroll_pos;
|
||||||
|
model->scroll_pos = 0;
|
||||||
|
model->text_pos = (char*)model->text;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
@ -120,14 +138,28 @@ static bool text_box_view_input_callback(InputEvent* event, void* context) {
|
|||||||
|
|
||||||
TextBox* text_box = context;
|
TextBox* text_box = context;
|
||||||
bool consumed = false;
|
bool consumed = false;
|
||||||
if(event->type == InputTypeShort) {
|
if(event->type == InputTypeShort || event->type == InputTypeRepeat) {
|
||||||
|
int32_t scroll_speed = 1;
|
||||||
|
if(text_box->button_held_for_ticks > 5) {
|
||||||
|
if(text_box->button_held_for_ticks % 2) {
|
||||||
|
scroll_speed = 0;
|
||||||
|
} else {
|
||||||
|
scroll_speed = text_box->button_held_for_ticks > 9 ? 5 : 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(event->key == InputKeyDown) {
|
if(event->key == InputKeyDown) {
|
||||||
text_box_process_down(text_box);
|
text_box_process_down(text_box, scroll_speed);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(event->key == InputKeyUp) {
|
} else if(event->key == InputKeyUp) {
|
||||||
text_box_process_up(text_box);
|
text_box_process_up(text_box, scroll_speed);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
text_box->button_held_for_ticks++;
|
||||||
|
} else if(event->type == InputTypeRelease) {
|
||||||
|
text_box->button_held_for_ticks = 0;
|
||||||
|
consumed = true;
|
||||||
}
|
}
|
||||||
return consumed;
|
return consumed;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user