Skip to content

Commit 2b4ac9a

Browse files
committed
feat: implement scene manager based implementation
1 parent b3b8e15 commit 2b4ac9a

File tree

18 files changed

+449
-119
lines changed

18 files changed

+449
-119
lines changed

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,19 @@ Here are the resources for developing applications for Flipper Zero:
5050
- [Flipper Zero Firmware Docs](https://developer.flipper.net/flipperzero/doxygen/)
5151
- [`struct` list](https://developer.flipper.net/flipperzero/doxygen/annotated.html) ([index](https://developer.flipper.net/flipperzero/doxygen/classes.html))
5252
- [Flipper Zero code examples](https://github.com/m1ch3al/flipper-zero-dev-tutorial)
53+
- [Lopaka, Graphics Editor for Embedded Devices](https://lopaka.app/)
54+
Note that Flipper Zero has screen dimension of `128x64`.
55+
56+
57+
### How to use `SceneManager` with this project?
58+
This template implements `SceneManager`, A "Scene" based framework for programming flipper zero GUIs.
59+
60+
Here is how you can add/modify scenes in this repository:
61+
1. Goto [`./src/scenes/list.h`](/src/scenes/list.h).
62+
2. Add your own scene by using macro: `SCENE_ACTION`.
63+
(e.g. If you want to make new scene called `Store`, You should type `SCENE_ACTION(Store)`)
64+
3. Implement `_on_enter`, `_on_event`, `_on_exit`, `_get_view`, `_alloc`, `_free` accordingly. Refer to [`./src/scenes/home/main.c`](/src/scenes/home/main.c) for more info.
65+
(F0 doesn't make sure the precendence of `_on_exit` and `_free`. Please make sure those two are independent by checking each other's free'd state)
66+
4. Add headers to export those functions.
67+
5. Include your header in [`./src/scenes/import.h`](/src/scenes/import.h).
68+

application.fam

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@ App(
55
appid="demo_app", # Must be unique
66
name="Demo Application", # Displayed in UI
77
apptype=FlipperAppType.EXTERNAL,
8-
entry_point="main_entrypoint",
8+
entry_point="entrypoint",
99
stack_size=2 * 1024, # size of memory stack it will allocate
1010

1111
# source code settings
12-
sources=["src/*.c*", "src/*/*.c*"], # Due to limitation of the fbt,
13-
# you need to specify nested directories
14-
# manually since it doesn't support
15-
# recurse globbing such as "src/**/*.c*"
12+
sources=[ # Due to limitation of the fbt,
13+
"src/*.c*", # you need to specify nested directories
14+
"src/*/*.c*", # manually since it doesn't support
15+
"src/*/*/*.c*" # recurse globbing such as "src/**/*.c*"
16+
],
1617

1718
# Dependencies
1819
requires=[

src/entrypoint.c

Lines changed: 0 additions & 8 deletions
This file was deleted.

src/events.c

Lines changed: 0 additions & 29 deletions
This file was deleted.

src/events.h

Lines changed: 0 additions & 7 deletions
This file was deleted.

src/handler.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#include "main.h"
2+
3+
bool scene_handler_event_forwarder(void* context, uint32_t event_id) {
4+
App* app = (App*)context;
5+
if(app == NULL || app->scene_manager == NULL) {
6+
return false;
7+
}
8+
9+
return scene_manager_handle_custom_event(app->scene_manager, event_id);
10+
}
11+
12+
bool scene_handler_navigation_forwarder(void* context) {
13+
App* app = (App*)context;
14+
if(app == NULL || app->scene_manager == NULL) {
15+
return false;
16+
}
17+
18+
return scene_manager_handle_back_event(app->scene_manager);
19+
}

src/main.c

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,36 @@
11
#include <stdio.h>
22
#include <furi.h>
33
#include <gui/gui.h>
4-
#include "events.h"
5-
#include "utils/gui.h"
4+
#include "main.h"
5+
#include "scenes/register.h"
66

77
int main() {
8-
// 1. Provision the InputHandlers
9-
// Handle input event
10-
InputEvent event;
11-
GUISetupData* gui_setup = setup_gui(on_draw, on_input);
12-
13-
// 2. Main EventLoop
14-
while(true) {
15-
// 4.1. Read input event from the message queue
16-
furi_check(
17-
furi_message_queue_get(gui_setup->msg_queue, &event, FuriWaitForever) == FuriStatusOk);
18-
19-
// 4.2. check if the event is a quit event
20-
if(event.key == InputKeyBack) {
21-
break;
22-
}
23-
}
24-
25-
// 3. Free the resources
26-
free_gui(gui_setup);
8+
App* app = malloc(sizeof(App));
9+
furi_assert(app != NULL, "Failed to allocate memory for the app");
10+
11+
Gui* gui = furi_record_open(RECORD_GUI);
12+
furi_assert(gui != NULL, "Failed to open the GUI record");
13+
14+
register_scenes(app);
15+
view_dispatcher_attach_to_gui(app->view_dispatcher, gui, ViewDispatcherTypeFullscreen);
16+
17+
// The default scene is always the first one!
18+
scene_manager_next_scene(app->scene_manager, 0);
19+
view_dispatcher_switch_to_view(app->view_dispatcher, 0);
20+
21+
view_dispatcher_run(app->view_dispatcher);
22+
23+
FURI_LOG_I("DemoApp", "Exiting application.");
24+
free_scenes(app);
25+
26+
FURI_LOG_I("DemoApp", "Freed app.");
27+
28+
return 0;
29+
}
30+
31+
// Stub entrypoint due to gcc complaining about
32+
// mismatching main function signature.
33+
int32_t entrypoint(void* p) {
34+
UNUSED(p);
35+
return main();
2736
}

src/main.h

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,29 @@
11
#pragma once
22

3-
int main();
3+
#include <gui/scene_manager.h>
4+
#include <gui/view_dispatcher.h>
5+
#include "scenes/import.h"
6+
7+
typedef struct App {
8+
SceneManager* scene_manager;
9+
ViewDispatcher* view_dispatcher;
10+
11+
void** allocated_scenes;
12+
} App;
13+
14+
/**
15+
* Enum for scenes.
16+
*/
17+
typedef enum {
18+
#define SCENE_ACTION(scene) scene,
19+
#include "scenes/list.h"
20+
#undef SCENE_ACTION
21+
22+
AppSceneNum, // This should be the last element in the enumeration.
23+
} AppViews;
24+
25+
/**
26+
* Header definition for handler.c
27+
*/
28+
bool scene_handler_event_forwarder(void* context, uint32_t event_id);
29+
bool scene_handler_navigation_forwarder(void* context);

src/scenes/about/main.c

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#include <gui/view.h>
2+
#include <gui/modules/submenu.h>
3+
#include "../../main.h"
4+
#include "main.h"
5+
6+
#define THIS_SCENE About
7+
8+
void About_on_draw(Canvas* canvas, void* context);
9+
AppAbout* About_alloc() {
10+
AppAbout* about = (AppAbout*)malloc(sizeof(AppAbout));
11+
about->view = view_alloc();
12+
view_set_draw_callback(about->view, About_on_draw);
13+
14+
return about;
15+
}
16+
17+
void About_on_draw(Canvas* canvas, void* context) {
18+
UNUSED(context);
19+
20+
canvas_clear(canvas);
21+
22+
canvas_set_bitmap_mode(canvas, true);
23+
canvas_set_font(canvas, FontPrimary);
24+
canvas_draw_str(canvas, 67, 11, "f0-template");
25+
canvas_set_font(canvas, FontSecondary);
26+
canvas_draw_str(canvas, 72, 20, "by Alex4386");
27+
canvas_draw_line(canvas, 54, 25, 124, 25);
28+
canvas_draw_str(canvas, 71, 39, "Protected by");
29+
canvas_set_font(canvas, FontPrimary);
30+
canvas_draw_str(canvas, 61, 51, "Fantasy Seal");
31+
canvas_draw_str(canvas, 69, 61, "Technology");
32+
}
33+
34+
void About_free(void* ptr) {
35+
AppAbout* home = (AppAbout*)ptr;
36+
FURI_LOG_I("DemoApp", "Triggering Free for view");
37+
38+
view_free(home->view);
39+
home->view = NULL;
40+
41+
free(home);
42+
}
43+
44+
View* About_get_view(void* ptr) {
45+
AppAbout* home = (AppAbout*)ptr;
46+
return home->view;
47+
}
48+
49+
void About_on_enter(void* context) {
50+
UNUSED(context);
51+
}
52+
53+
bool About_on_event(void* context, SceneManagerEvent event) {
54+
UNUSED(context);
55+
UNUSED(event);
56+
57+
if(event.type == SceneManagerEventTypeBack) {
58+
return false;
59+
}
60+
61+
return true;
62+
}
63+
64+
void About_on_exit(void* context) {
65+
App* app = (App*)context;
66+
if(app == NULL) {
67+
return;
68+
}
69+
70+
if(app->view_dispatcher) view_dispatcher_switch_to_view(app->view_dispatcher, Home);
71+
if(app->scene_manager) scene_manager_previous_scene(app->scene_manager);
72+
}

src/scenes/about/main.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#pragma once
2+
#include <gui/view.h>
3+
#include <gui/modules/submenu.h>
4+
5+
typedef struct AppAbout {
6+
View* view;
7+
Canvas* canvas;
8+
} AppAbout;
9+
10+
AppAbout* About_alloc();
11+
void About_free(void* ptr);
12+
View* About_get_view(void* ptr);
13+
void About_on_enter(void* context);
14+
bool About_on_event(void* context, SceneManagerEvent event);
15+
void About_on_exit(void* context);

0 commit comments

Comments
 (0)