C++ apps: templated scene controller (#517)

* C++ apps: templated scene controller
* templated app: fix type names
* templated app: text store component
* Applications: add "Templated Scene" application
* templated app: refractoring
* Gui module byte input: fix docs
* templated app: new byte input scene
* templated app: dialog ex view module
* templated app: popup view module
* templated app: dialog-ex view module, fix docs
* templated app: text input view module
* Gui module text input: fix docs
* Furi: duplicated include
* templated app: record holder (controller) class
* templated app: view modules can now be accessed via cast
* templated app: remove unused includes
* templated app: fix return code
This commit is contained in:
SG
2021-06-15 21:01:56 +10:00
committed by GitHub
parent 3a2121bbb8
commit 0b14db4fb3
30 changed files with 1242 additions and 9 deletions

View File

@@ -39,6 +39,7 @@ int32_t app_accessor(void* p);
int32_t internal_storage_task(void* p);
int32_t app_archive(void* p);
int32_t notification_app(void* p);
int32_t scened_app(void* p);
// On system start hooks declaration
void irda_cli_init();
@@ -293,6 +294,10 @@ const FlipperApplication FLIPPER_DEBUG_APPS[] = {
.stack_size = 1024,
.icon = A_Plugins_14},
#endif
#ifdef APP_SCENED
{.app = scened_app, .name = "Templated Scene", .stack_size = 1024, .icon = A_Plugins_14},
#endif
};
const size_t FLIPPER_DEBUG_APPS_COUNT = sizeof(FLIPPER_DEBUG_APPS) / sizeof(FlipperApplication);

View File

@@ -46,7 +46,7 @@ void byte_input_free(ByteInput* byte_input);
View* byte_input_get_view(ByteInput* byte_input);
/**
* @brief Deinitialize and free byte input
* @brief Set byte input result callback
*
* @param byte_input byte input instance
* @param input_callback input callback fn

View File

@@ -9,23 +9,31 @@ extern "C" {
typedef struct TextInput TextInput;
typedef void (*TextInputCallback)(void* context, char* text);
/* Allocate and initialize text input
* This text input is used to enter string
/**
* @brief Allocate and initialize text input
* This text input is used to enter string
*
*/
TextInput* text_input_alloc();
/* Deinitialize and free text input
/**
* @brief Deinitialize and free text input
*
* @param text_input - Text input instance
*/
void text_input_free(TextInput* text_input);
/* Get text input view
/**
* @brief Get text input view
*
* @param text_input - Text input instance
* @return View instance that can be used for embedding
*/
View* text_input_get_view(TextInput* text_input);
/* Deinitialize and free text input
/**
* @brief Set text input result callback
*
* @param text_input - Text input instance
* @param callback - callback fn
* @param callback_context - callback context
@@ -39,7 +47,9 @@ void text_input_set_result_callback(
char* text,
uint8_t max_text_length);
/* Set text input header text
/**
* @brief Set text input header text
*
* @param text input - Text input instance
* @param text - text to be shown
*/

View File

@@ -0,0 +1,35 @@
#include "scened-app-scene-byte-input.h"
void ScenedAppSceneByteInput::on_enter(ScenedApp* app, bool need_restore) {
ByteInputVM* byte_input = app->view_controller;
auto callback = cbc::obtain_connector(this, &ScenedAppSceneByteInput::result_callback);
byte_input->set_result_callback(callback, NULL, app, data, 4);
byte_input->set_header_text("Enter the key");
app->view_controller.switch_to<ByteInputVM>();
}
bool ScenedAppSceneByteInput::on_event(ScenedApp* app, ScenedApp::Event* event) {
bool consumed = false;
if(event->type == ScenedApp::EventType::ByteEditResult) {
app->scene_controller.switch_to_previous_scene();
consumed = true;
}
return consumed;
}
void ScenedAppSceneByteInput::on_exit(ScenedApp* app) {
app->view_controller.get<ByteInputVM>()->clean();
}
void ScenedAppSceneByteInput::result_callback(void* context, uint8_t* bytes, uint8_t bytes_count) {
ScenedApp* app = static_cast<ScenedApp*>(context);
ScenedApp::Event event;
event.type = ScenedApp::EventType::ByteEditResult;
app->view_controller.send_event(&event);
}

View File

@@ -0,0 +1,19 @@
#pragma once
#include "../scened-app.h"
class ScenedAppSceneByteInput : public GenericScene<ScenedApp> {
public:
void on_enter(ScenedApp* app, bool need_restore) final;
bool on_event(ScenedApp* app, ScenedApp::Event* event) final;
void on_exit(ScenedApp* app) final;
private:
void result_callback(void* context, uint8_t* bytes, uint8_t bytes_count);
uint8_t data[4] = {
0x01,
0xA2,
0xF4,
0xD3,
};
};

View File

@@ -0,0 +1,47 @@
#include "scened-app-scene-start.h"
typedef enum {
SubmenuByteInput,
} SubmenuIndex;
void ScenedAppSceneStart::on_enter(ScenedApp* app, bool need_restore) {
auto submenu = app->view_controller.get<SubmenuVM>();
auto callback = cbc::obtain_connector(this, &ScenedAppSceneStart::submenu_callback);
submenu->add_item("Byte Input", SubmenuByteInput, callback, app);
if(need_restore) {
submenu->set_selected_item(submenu_item_selected);
}
app->view_controller.switch_to<SubmenuVM>();
}
bool ScenedAppSceneStart::on_event(ScenedApp* app, ScenedApp::Event* event) {
bool consumed = false;
if(event->type == ScenedApp::EventType::MenuSelected) {
submenu_item_selected = event->payload.menu_index;
switch(event->payload.menu_index) {
case SubmenuByteInput:
app->scene_controller.switch_to_next_scene(ScenedApp::SceneType::ByteInputScene);
break;
}
consumed = true;
}
return consumed;
}
void ScenedAppSceneStart::on_exit(ScenedApp* app) {
app->view_controller.get<SubmenuVM>()->clean();
}
void ScenedAppSceneStart::submenu_callback(void* context, uint32_t index) {
ScenedApp* app = static_cast<ScenedApp*>(context);
ScenedApp::Event event;
event.type = ScenedApp::EventType::MenuSelected;
event.payload.menu_index = index;
app->view_controller.send_event(&event);
}

View File

@@ -0,0 +1,13 @@
#pragma once
#include "../scened-app.h"
class ScenedAppSceneStart : public GenericScene<ScenedApp> {
public:
void on_enter(ScenedApp* app, bool need_restore) final;
bool on_event(ScenedApp* app, ScenedApp::Event* event) final;
void on_exit(ScenedApp* app) final;
private:
void submenu_callback(void* context, uint32_t index);
uint32_t submenu_item_selected = 0;
};

View File

@@ -0,0 +1,10 @@
#include "scened-app.h"
// app enter function
extern "C" int32_t scened_app(void* p) {
ScenedApp* app = new ScenedApp();
app->run();
delete app;
return 0;
}

View File

@@ -0,0 +1,20 @@
#include "scened-app.h"
#include "scene/scened-app-scene-start.h"
#include "scene/scened-app-scene-byte-input.h"
ScenedApp::ScenedApp()
: scene_controller{this}
, text_store{128}
, notification{"notification"} {
}
ScenedApp::~ScenedApp() {
}
void ScenedApp::run() {
scene_controller.add_scene(SceneType::Start, new ScenedAppSceneStart());
scene_controller.add_scene(SceneType::ByteInputScene, new ScenedAppSceneByteInput());
notification_message(notification, &sequence_blink_green_10);
scene_controller.process(100);
}

View File

@@ -0,0 +1,47 @@
#pragma once
#include <furi.h>
#include <api-hal.h>
#include <generic-scene.hpp>
#include <scene-controller.hpp>
#include <view-controller.hpp>
#include <record-controller.hpp>
#include <text-store.h>
#include <view-modules/submenu-vm.h>
#include <view-modules/byte-input-vm.h>
#include <notification/notification-messages.h>
class ScenedApp {
public:
enum class EventType : uint8_t {
GENERIC_EVENT_ENUM_VALUES,
MenuSelected,
ByteEditResult,
};
enum class SceneType : uint8_t {
GENERIC_SCENE_ENUM_VALUES,
ByteInputScene,
};
class Event {
public:
union {
int32_t menu_index;
} payload;
EventType type;
};
SceneController<GenericScene<ScenedApp>, ScenedApp> scene_controller;
TextStore text_store;
ViewController<ScenedApp, SubmenuVM, ByteInputVM> view_controller;
RecordController<NotificationApp> notification;
~ScenedApp();
ScenedApp();
void run();
};