Gui: scrollable long file names in FileBrowser and Archive Browser (#2159)
* Gui: scrollable long file names in FileBrowser * Archive: scroll long file names * Gui: elements code cleanup
This commit is contained in:
		
							parent
							
								
									0286636183
								
							
						
					
					
						commit
						e7107e39f7
					
				@ -5,6 +5,9 @@
 | 
				
			|||||||
#include "archive_browser_view.h"
 | 
					#include "archive_browser_view.h"
 | 
				
			||||||
#include "../helpers/archive_browser.h"
 | 
					#include "../helpers/archive_browser.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SCROLL_INTERVAL (333)
 | 
				
			||||||
 | 
					#define SCROLL_DELAY (2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char* ArchiveTabNames[] = {
 | 
					static const char* ArchiveTabNames[] = {
 | 
				
			||||||
    [ArchiveTabFavorites] = "Favorites",
 | 
					    [ArchiveTabFavorites] = "Favorites",
 | 
				
			||||||
    [ArchiveTabIButton] = "iButton",
 | 
					    [ArchiveTabIButton] = "iButton",
 | 
				
			||||||
@ -146,13 +149,18 @@ static void draw_list(Canvas* canvas, ArchiveBrowserViewModel* model) {
 | 
				
			|||||||
            furi_string_set(str_buf, "---");
 | 
					            furi_string_set(str_buf, "---");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        elements_string_fit_width(
 | 
					        size_t scroll_counter = model->scroll_counter;
 | 
				
			||||||
            canvas, str_buf, (scrollbar ? MAX_LEN_PX - 6 : MAX_LEN_PX) - x_offset);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(model->item_idx == idx) {
 | 
					        if(model->item_idx == idx) {
 | 
				
			||||||
            archive_draw_frame(canvas, i, scrollbar, model->move_fav);
 | 
					            archive_draw_frame(canvas, i, scrollbar, model->move_fav);
 | 
				
			||||||
 | 
					            if(scroll_counter < SCROLL_DELAY) {
 | 
				
			||||||
 | 
					                scroll_counter = 0;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                scroll_counter -= SCROLL_DELAY;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            canvas_set_color(canvas, ColorBlack);
 | 
					            canvas_set_color(canvas, ColorBlack);
 | 
				
			||||||
 | 
					            scroll_counter = 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(custom_icon_data) {
 | 
					        if(custom_icon_data) {
 | 
				
			||||||
@ -162,8 +170,15 @@ static void draw_list(Canvas* canvas, ArchiveBrowserViewModel* model) {
 | 
				
			|||||||
            canvas_draw_icon(
 | 
					            canvas_draw_icon(
 | 
				
			||||||
                canvas, 2 + x_offset, 16 + i * FRAME_HEIGHT, ArchiveItemIcons[file_type]);
 | 
					                canvas, 2 + x_offset, 16 + i * FRAME_HEIGHT, ArchiveItemIcons[file_type]);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        canvas_draw_str(
 | 
					
 | 
				
			||||||
            canvas, 15 + x_offset, 24 + i * FRAME_HEIGHT, furi_string_get_cstr(str_buf));
 | 
					        elements_scrollable_text_line(
 | 
				
			||||||
 | 
					            canvas,
 | 
				
			||||||
 | 
					            15 + x_offset,
 | 
				
			||||||
 | 
					            24 + i * FRAME_HEIGHT,
 | 
				
			||||||
 | 
					            ((scrollbar ? MAX_LEN_PX - 6 : MAX_LEN_PX) - x_offset),
 | 
				
			||||||
 | 
					            str_buf,
 | 
				
			||||||
 | 
					            scroll_counter,
 | 
				
			||||||
 | 
					            (model->item_idx != idx));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        furi_string_free(str_buf);
 | 
					        furi_string_free(str_buf);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -329,6 +344,7 @@ static bool archive_view_input(InputEvent* event, void* context) {
 | 
				
			|||||||
                        if(move_fav_mode) {
 | 
					                        if(move_fav_mode) {
 | 
				
			||||||
                            browser->callback(ArchiveBrowserEventFavMoveUp, browser->context);
 | 
					                            browser->callback(ArchiveBrowserEventFavMoveUp, browser->context);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
					                        model->scroll_counter = 0;
 | 
				
			||||||
                    } else if(event->key == InputKeyDown) {
 | 
					                    } else if(event->key == InputKeyDown) {
 | 
				
			||||||
                        model->item_idx = (model->item_idx + 1) % model->item_cnt;
 | 
					                        model->item_idx = (model->item_idx + 1) % model->item_cnt;
 | 
				
			||||||
                        if(is_file_list_load_required(model)) {
 | 
					                        if(is_file_list_load_required(model)) {
 | 
				
			||||||
@ -338,6 +354,7 @@ static bool archive_view_input(InputEvent* event, void* context) {
 | 
				
			|||||||
                        if(move_fav_mode) {
 | 
					                        if(move_fav_mode) {
 | 
				
			||||||
                            browser->callback(ArchiveBrowserEventFavMoveDown, browser->context);
 | 
					                            browser->callback(ArchiveBrowserEventFavMoveDown, browser->context);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
					                        model->scroll_counter = 0;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
                true);
 | 
					                true);
 | 
				
			||||||
@ -377,6 +394,27 @@ static bool archive_view_input(InputEvent* event, void* context) {
 | 
				
			|||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void browser_scroll_timer(void* context) {
 | 
				
			||||||
 | 
					    furi_assert(context);
 | 
				
			||||||
 | 
					    ArchiveBrowserView* browser = context;
 | 
				
			||||||
 | 
					    with_view_model(
 | 
				
			||||||
 | 
					        browser->view, ArchiveBrowserViewModel * model, { model->scroll_counter++; }, true);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void browser_view_enter(void* context) {
 | 
				
			||||||
 | 
					    furi_assert(context);
 | 
				
			||||||
 | 
					    ArchiveBrowserView* browser = context;
 | 
				
			||||||
 | 
					    with_view_model(
 | 
				
			||||||
 | 
					        browser->view, ArchiveBrowserViewModel * model, { model->scroll_counter = 0; }, true);
 | 
				
			||||||
 | 
					    furi_timer_start(browser->scroll_timer, SCROLL_INTERVAL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void browser_view_exit(void* context) {
 | 
				
			||||||
 | 
					    furi_assert(context);
 | 
				
			||||||
 | 
					    ArchiveBrowserView* browser = context;
 | 
				
			||||||
 | 
					    furi_timer_stop(browser->scroll_timer);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ArchiveBrowserView* browser_alloc() {
 | 
					ArchiveBrowserView* browser_alloc() {
 | 
				
			||||||
    ArchiveBrowserView* browser = malloc(sizeof(ArchiveBrowserView));
 | 
					    ArchiveBrowserView* browser = malloc(sizeof(ArchiveBrowserView));
 | 
				
			||||||
    browser->view = view_alloc();
 | 
					    browser->view = view_alloc();
 | 
				
			||||||
@ -384,6 +422,10 @@ ArchiveBrowserView* browser_alloc() {
 | 
				
			|||||||
    view_set_context(browser->view, browser);
 | 
					    view_set_context(browser->view, browser);
 | 
				
			||||||
    view_set_draw_callback(browser->view, archive_view_render);
 | 
					    view_set_draw_callback(browser->view, archive_view_render);
 | 
				
			||||||
    view_set_input_callback(browser->view, archive_view_input);
 | 
					    view_set_input_callback(browser->view, archive_view_input);
 | 
				
			||||||
 | 
					    view_set_enter_callback(browser->view, browser_view_enter);
 | 
				
			||||||
 | 
					    view_set_exit_callback(browser->view, browser_view_exit);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    browser->scroll_timer = furi_timer_alloc(browser_scroll_timer, FuriTimerTypePeriodic, browser);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    browser->path = furi_string_alloc_set(archive_get_default_path(TAB_DEFAULT));
 | 
					    browser->path = furi_string_alloc_set(archive_get_default_path(TAB_DEFAULT));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -402,6 +444,8 @@ ArchiveBrowserView* browser_alloc() {
 | 
				
			|||||||
void browser_free(ArchiveBrowserView* browser) {
 | 
					void browser_free(ArchiveBrowserView* browser) {
 | 
				
			||||||
    furi_assert(browser);
 | 
					    furi_assert(browser);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    furi_timer_free(browser->scroll_timer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(browser->worker_running) {
 | 
					    if(browser->worker_running) {
 | 
				
			||||||
        file_browser_worker_free(browser->worker);
 | 
					        file_browser_worker_free(browser->worker);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -81,6 +81,7 @@ struct ArchiveBrowserView {
 | 
				
			|||||||
    FuriString* path;
 | 
					    FuriString* path;
 | 
				
			||||||
    InputKey last_tab_switch_dir;
 | 
					    InputKey last_tab_switch_dir;
 | 
				
			||||||
    bool is_root;
 | 
					    bool is_root;
 | 
				
			||||||
 | 
					    FuriTimer* scroll_timer;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
@ -97,6 +98,7 @@ typedef struct {
 | 
				
			|||||||
    int32_t item_idx;
 | 
					    int32_t item_idx;
 | 
				
			||||||
    int32_t array_offset;
 | 
					    int32_t array_offset;
 | 
				
			||||||
    int32_t list_offset;
 | 
					    int32_t list_offset;
 | 
				
			||||||
 | 
					    size_t scroll_counter;
 | 
				
			||||||
} ArchiveBrowserViewModel;
 | 
					} ArchiveBrowserViewModel;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void archive_browser_set_callback(
 | 
					void archive_browser_set_callback(
 | 
				
			||||||
 | 
				
			|||||||
@ -50,6 +50,10 @@ void view_holder_free(ViewHolder* view_holder) {
 | 
				
			|||||||
void view_holder_set_view(ViewHolder* view_holder, View* view) {
 | 
					void view_holder_set_view(ViewHolder* view_holder, View* view) {
 | 
				
			||||||
    furi_assert(view_holder);
 | 
					    furi_assert(view_holder);
 | 
				
			||||||
    if(view_holder->view) {
 | 
					    if(view_holder->view) {
 | 
				
			||||||
 | 
					        if(view_holder->view->exit_callback) {
 | 
				
			||||||
 | 
					            view_holder->view->exit_callback(view_holder->view->context);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        view_set_update_callback(view_holder->view, NULL);
 | 
					        view_set_update_callback(view_holder->view, NULL);
 | 
				
			||||||
        view_set_update_callback_context(view_holder->view, NULL);
 | 
					        view_set_update_callback_context(view_holder->view, NULL);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -59,6 +63,10 @@ void view_holder_set_view(ViewHolder* view_holder, View* view) {
 | 
				
			|||||||
    if(view_holder->view) {
 | 
					    if(view_holder->view) {
 | 
				
			||||||
        view_set_update_callback(view_holder->view, view_holder_update);
 | 
					        view_set_update_callback(view_holder->view, view_holder_update);
 | 
				
			||||||
        view_set_update_callback_context(view_holder->view, view_holder);
 | 
					        view_set_update_callback_context(view_holder->view, view_holder);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(view_holder->view->enter_callback) {
 | 
				
			||||||
 | 
					            view_holder->view->enter_callback(view_holder->view->context);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -547,6 +547,52 @@ void elements_string_fit_width(Canvas* canvas, FuriString* string, uint8_t width
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void elements_scrollable_text_line(
 | 
				
			||||||
 | 
					    Canvas* canvas,
 | 
				
			||||||
 | 
					    uint8_t x,
 | 
				
			||||||
 | 
					    uint8_t y,
 | 
				
			||||||
 | 
					    uint8_t width,
 | 
				
			||||||
 | 
					    FuriString* string,
 | 
				
			||||||
 | 
					    size_t scroll,
 | 
				
			||||||
 | 
					    bool ellipsis) {
 | 
				
			||||||
 | 
					    FuriString* line = furi_string_alloc_set(string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    size_t len_px = canvas_string_width(canvas, furi_string_get_cstr(line));
 | 
				
			||||||
 | 
					    if(len_px > width) {
 | 
				
			||||||
 | 
					        if(ellipsis) {
 | 
				
			||||||
 | 
					            width -= canvas_string_width(canvas, "...");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Calculate scroll size
 | 
				
			||||||
 | 
					        size_t scroll_size = furi_string_size(string);
 | 
				
			||||||
 | 
					        size_t right_width = 0;
 | 
				
			||||||
 | 
					        for(size_t i = scroll_size; i > 0; i--) {
 | 
				
			||||||
 | 
					            right_width += canvas_glyph_width(canvas, furi_string_get_char(line, i));
 | 
				
			||||||
 | 
					            if(right_width > width) break;
 | 
				
			||||||
 | 
					            scroll_size--;
 | 
				
			||||||
 | 
					            if(!scroll_size) break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        // Ensure that we have something to scroll
 | 
				
			||||||
 | 
					        if(scroll_size) {
 | 
				
			||||||
 | 
					            scroll_size += 3;
 | 
				
			||||||
 | 
					            scroll = scroll % scroll_size;
 | 
				
			||||||
 | 
					            furi_string_right(line, scroll);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        do {
 | 
				
			||||||
 | 
					            furi_string_left(line, furi_string_size(line) - 1);
 | 
				
			||||||
 | 
					            len_px = canvas_string_width(canvas, furi_string_get_cstr(line));
 | 
				
			||||||
 | 
					        } while(len_px > width);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(ellipsis) {
 | 
				
			||||||
 | 
					            furi_string_cat(line, "...");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    canvas_draw_str(canvas, x, y, furi_string_get_cstr(line));
 | 
				
			||||||
 | 
					    furi_string_free(line);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void elements_text_box(
 | 
					void elements_text_box(
 | 
				
			||||||
    Canvas* canvas,
 | 
					    Canvas* canvas,
 | 
				
			||||||
    uint8_t x,
 | 
					    uint8_t x,
 | 
				
			||||||
 | 
				
			|||||||
@ -192,6 +192,25 @@ void elements_bubble_str(
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
void elements_string_fit_width(Canvas* canvas, FuriString* string, uint8_t width);
 | 
					void elements_string_fit_width(Canvas* canvas, FuriString* string, uint8_t width);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Draw scrollable text line
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param      canvas    The canvas
 | 
				
			||||||
 | 
					 * @param[in]  x         X coordinate
 | 
				
			||||||
 | 
					 * @param[in]  y         Y coordinate
 | 
				
			||||||
 | 
					 * @param[in]  width     The width
 | 
				
			||||||
 | 
					 * @param      string    The string
 | 
				
			||||||
 | 
					 * @param[in]  scroll    The scroll counter: 0 - no scroll, any other number - scroll. Just count up, everything else will be calculated on the inside.
 | 
				
			||||||
 | 
					 * @param[in]  ellipsis  The ellipsis flag: true to add ellipse
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void elements_scrollable_text_line(
 | 
				
			||||||
 | 
					    Canvas* canvas,
 | 
				
			||||||
 | 
					    uint8_t x,
 | 
				
			||||||
 | 
					    uint8_t y,
 | 
				
			||||||
 | 
					    uint8_t width,
 | 
				
			||||||
 | 
					    FuriString* string,
 | 
				
			||||||
 | 
					    size_t scroll,
 | 
				
			||||||
 | 
					    bool ellipsis);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Draw text box element
 | 
					/** Draw text box element
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param       canvas          Canvas instance
 | 
					 * @param       canvas          Canvas instance
 | 
				
			||||||
 | 
				
			|||||||
@ -19,6 +19,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#define CUSTOM_ICON_MAX_SIZE 32
 | 
					#define CUSTOM_ICON_MAX_SIZE 32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SCROLL_INTERVAL (333)
 | 
				
			||||||
 | 
					#define SCROLL_DELAY (2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef enum {
 | 
					typedef enum {
 | 
				
			||||||
    BrowserItemTypeLoading,
 | 
					    BrowserItemTypeLoading,
 | 
				
			||||||
    BrowserItemTypeBack,
 | 
					    BrowserItemTypeBack,
 | 
				
			||||||
@ -95,6 +98,7 @@ struct FileBrowser {
 | 
				
			|||||||
    void* item_context;
 | 
					    void* item_context;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    FuriString* result_path;
 | 
					    FuriString* result_path;
 | 
				
			||||||
 | 
					    FuriTimer* scroll_timer;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
@ -110,6 +114,7 @@ typedef struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    const Icon* file_icon;
 | 
					    const Icon* file_icon;
 | 
				
			||||||
    bool hide_ext;
 | 
					    bool hide_ext;
 | 
				
			||||||
 | 
					    size_t scroll_counter;
 | 
				
			||||||
} FileBrowserModel;
 | 
					} FileBrowserModel;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const Icon* BrowserItemIcons[] = {
 | 
					static const Icon* BrowserItemIcons[] = {
 | 
				
			||||||
@ -129,6 +134,27 @@ static void
 | 
				
			|||||||
    browser_list_item_cb(void* context, FuriString* item_path, bool is_folder, bool is_last);
 | 
					    browser_list_item_cb(void* context, FuriString* item_path, bool is_folder, bool is_last);
 | 
				
			||||||
static void browser_long_load_cb(void* context);
 | 
					static void browser_long_load_cb(void* context);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void file_browser_scroll_timer_callback(void* context) {
 | 
				
			||||||
 | 
					    furi_assert(context);
 | 
				
			||||||
 | 
					    FileBrowser* browser = context;
 | 
				
			||||||
 | 
					    with_view_model(
 | 
				
			||||||
 | 
					        browser->view, FileBrowserModel * model, { model->scroll_counter++; }, true);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void file_browser_view_enter_callback(void* context) {
 | 
				
			||||||
 | 
					    furi_assert(context);
 | 
				
			||||||
 | 
					    FileBrowser* browser = context;
 | 
				
			||||||
 | 
					    with_view_model(
 | 
				
			||||||
 | 
					        browser->view, FileBrowserModel * model, { model->scroll_counter = 0; }, true);
 | 
				
			||||||
 | 
					    furi_timer_start(browser->scroll_timer, SCROLL_INTERVAL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void file_browser_view_exit_callback(void* context) {
 | 
				
			||||||
 | 
					    furi_assert(context);
 | 
				
			||||||
 | 
					    FileBrowser* browser = context;
 | 
				
			||||||
 | 
					    furi_timer_stop(browser->scroll_timer);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
FileBrowser* file_browser_alloc(FuriString* result_path) {
 | 
					FileBrowser* file_browser_alloc(FuriString* result_path) {
 | 
				
			||||||
    furi_assert(result_path);
 | 
					    furi_assert(result_path);
 | 
				
			||||||
    FileBrowser* browser = malloc(sizeof(FileBrowser));
 | 
					    FileBrowser* browser = malloc(sizeof(FileBrowser));
 | 
				
			||||||
@ -137,6 +163,11 @@ FileBrowser* file_browser_alloc(FuriString* result_path) {
 | 
				
			|||||||
    view_set_context(browser->view, browser);
 | 
					    view_set_context(browser->view, browser);
 | 
				
			||||||
    view_set_draw_callback(browser->view, file_browser_view_draw_callback);
 | 
					    view_set_draw_callback(browser->view, file_browser_view_draw_callback);
 | 
				
			||||||
    view_set_input_callback(browser->view, file_browser_view_input_callback);
 | 
					    view_set_input_callback(browser->view, file_browser_view_input_callback);
 | 
				
			||||||
 | 
					    view_set_enter_callback(browser->view, file_browser_view_enter_callback);
 | 
				
			||||||
 | 
					    view_set_exit_callback(browser->view, file_browser_view_exit_callback);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    browser->scroll_timer =
 | 
				
			||||||
 | 
					        furi_timer_alloc(file_browser_scroll_timer_callback, FuriTimerTypePeriodic, browser);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    browser->result_path = result_path;
 | 
					    browser->result_path = result_path;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -149,6 +180,8 @@ FileBrowser* file_browser_alloc(FuriString* result_path) {
 | 
				
			|||||||
void file_browser_free(FileBrowser* browser) {
 | 
					void file_browser_free(FileBrowser* browser) {
 | 
				
			||||||
    furi_assert(browser);
 | 
					    furi_assert(browser);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    furi_timer_free(browser->scroll_timer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with_view_model(
 | 
					    with_view_model(
 | 
				
			||||||
        browser->view, FileBrowserModel * model, { items_array_clear(model->items); }, false);
 | 
					        browser->view, FileBrowserModel * model, { items_array_clear(model->items); }, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -468,13 +501,17 @@ static void browser_draw_list(Canvas* canvas, FileBrowserModel* model) {
 | 
				
			|||||||
            furi_string_set(filename, ". .");
 | 
					            furi_string_set(filename, ". .");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        elements_string_fit_width(
 | 
					        size_t scroll_counter = model->scroll_counter;
 | 
				
			||||||
            canvas, filename, (show_scrollbar ? MAX_LEN_PX - 6 : MAX_LEN_PX));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if(model->item_idx == idx) {
 | 
					        if(model->item_idx == idx) {
 | 
				
			||||||
            browser_draw_frame(canvas, i, show_scrollbar);
 | 
					            browser_draw_frame(canvas, i, show_scrollbar);
 | 
				
			||||||
 | 
					            if(scroll_counter < SCROLL_DELAY) {
 | 
				
			||||||
 | 
					                scroll_counter = 0;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                scroll_counter -= SCROLL_DELAY;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            canvas_set_color(canvas, ColorBlack);
 | 
					            canvas_set_color(canvas, ColorBlack);
 | 
				
			||||||
 | 
					            scroll_counter = 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(custom_icon_data) {
 | 
					        if(custom_icon_data) {
 | 
				
			||||||
@ -487,8 +524,14 @@ static void browser_draw_list(Canvas* canvas, FileBrowserModel* model) {
 | 
				
			|||||||
            canvas_draw_icon(
 | 
					            canvas_draw_icon(
 | 
				
			||||||
                canvas, 2, Y_OFFSET + 1 + i * FRAME_HEIGHT, BrowserItemIcons[item_type]);
 | 
					                canvas, 2, Y_OFFSET + 1 + i * FRAME_HEIGHT, BrowserItemIcons[item_type]);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        canvas_draw_str(
 | 
					        elements_scrollable_text_line(
 | 
				
			||||||
            canvas, 15, Y_OFFSET + 9 + i * FRAME_HEIGHT, furi_string_get_cstr(filename));
 | 
					            canvas,
 | 
				
			||||||
 | 
					            15,
 | 
				
			||||||
 | 
					            Y_OFFSET + 9 + i * FRAME_HEIGHT,
 | 
				
			||||||
 | 
					            (show_scrollbar ? MAX_LEN_PX - 6 : MAX_LEN_PX),
 | 
				
			||||||
 | 
					            filename,
 | 
				
			||||||
 | 
					            scroll_counter,
 | 
				
			||||||
 | 
					            (model->item_idx != idx));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(show_scrollbar) {
 | 
					    if(show_scrollbar) {
 | 
				
			||||||
@ -543,6 +586,7 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context) {
 | 
				
			|||||||
                            file_browser_worker_load(
 | 
					                            file_browser_worker_load(
 | 
				
			||||||
                                browser->worker, load_offset, ITEM_LIST_LEN_MAX);
 | 
					                                browser->worker, load_offset, ITEM_LIST_LEN_MAX);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
					                        model->scroll_counter = 0;
 | 
				
			||||||
                    } else if(event->key == InputKeyDown) {
 | 
					                    } else if(event->key == InputKeyDown) {
 | 
				
			||||||
                        model->item_idx = (model->item_idx + 1) % model->item_cnt;
 | 
					                        model->item_idx = (model->item_idx + 1) % model->item_cnt;
 | 
				
			||||||
                        if(browser_is_list_load_required(model)) {
 | 
					                        if(browser_is_list_load_required(model)) {
 | 
				
			||||||
@ -554,6 +598,7 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context) {
 | 
				
			|||||||
                            file_browser_worker_load(
 | 
					                            file_browser_worker_load(
 | 
				
			||||||
                                browser->worker, load_offset, ITEM_LIST_LEN_MAX);
 | 
					                                browser->worker, load_offset, ITEM_LIST_LEN_MAX);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
					                        model->scroll_counter = 0;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
                true);
 | 
					                true);
 | 
				
			||||||
 | 
				
			|||||||
@ -752,6 +752,7 @@ Function,+,elements_multiline_text,void,"Canvas*, uint8_t, uint8_t, const char*"
 | 
				
			|||||||
Function,+,elements_multiline_text_aligned,void,"Canvas*, uint8_t, uint8_t, Align, Align, const char*"
 | 
					Function,+,elements_multiline_text_aligned,void,"Canvas*, uint8_t, uint8_t, Align, Align, const char*"
 | 
				
			||||||
Function,+,elements_multiline_text_framed,void,"Canvas*, uint8_t, uint8_t, const char*"
 | 
					Function,+,elements_multiline_text_framed,void,"Canvas*, uint8_t, uint8_t, const char*"
 | 
				
			||||||
Function,+,elements_progress_bar,void,"Canvas*, uint8_t, uint8_t, uint8_t, float"
 | 
					Function,+,elements_progress_bar,void,"Canvas*, uint8_t, uint8_t, uint8_t, float"
 | 
				
			||||||
 | 
					Function,+,elements_scrollable_text_line,void,"Canvas*, uint8_t, uint8_t, uint8_t, FuriString*, size_t, _Bool"
 | 
				
			||||||
Function,+,elements_scrollbar,void,"Canvas*, uint16_t, uint16_t"
 | 
					Function,+,elements_scrollbar,void,"Canvas*, uint16_t, uint16_t"
 | 
				
			||||||
Function,+,elements_scrollbar_pos,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint16_t, uint16_t"
 | 
					Function,+,elements_scrollbar_pos,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint16_t, uint16_t"
 | 
				
			||||||
Function,+,elements_slightly_rounded_box,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t"
 | 
					Function,+,elements_slightly_rounded_box,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t"
 | 
				
			||||||
 | 
				
			|||||||
		
		
			
  | 
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user