FlipperZero 앱 개발 - GUI 기본코드

biluv·2023년 12월 30일
0

FlipperZeroAppDev

목록 보기
3/6

서론

플리퍼 제로에는 BT, CLI, DESKTOP, DIALOGS, GUI 등 여러 서비스가 있습니다.

GUI 애플리케이션을 개발하기 위해서는 GUI 서비스를 가져와서 이용을 해야 합니다. GUI 서비스 자체는 로우레벨이라 그냥 사용하기에는 너무 불편하여 GUI 라이브러리를 같이 이용해야 합니다.

GUI 라이브러리을 이용하면 이전 글에서 설명했던 Scene, View 개념을 이용하여 쉽게 GUI 애플리케이션을 개발할 수 있습니다.

기본 코드

  1. GUI 관련 헤더를 include 해줍시다.
#include <gui/gui.h>
#include <gui/scene_manager.h>
#include <gui/view_dispatcher.h>
  1. App struct를 만들어야 합니다. callback 등으로 이벤트를 받았을 때 다른 요소에 접근할 수 있도록 합니다.
typedef struct {
    ViewDispatcher* view_dispatcher;
    SceneManager* scene_manager;
} App;
  1. Scene의 핸들러가 들어갈 변수를 만들어줍니다. Scene 추가는 다음 장에서 합니다
void (*const app_scene_on_enter_handlers[])(void*) = {
};

void (*const app_scene_on_exit_handlers[])(void*) = {
};

bool (*const app_scene_on_event_handlers[])(void*, SceneManagerEvent) = {
};

const SceneManagerHandlers app_scene_event_handlers = {
    .on_enter_handlers = app_scene_on_enter_handlers,
    .on_exit_handlers = app_scene_on_exit_handlers,
    .on_event_handlers = app_scene_on_event_handlers,
    .scene_num = 0,
};
  1. 이벤트를 scene_manager로 넘겨주는 함수를 만들어줍니다.
bool app_custom_callback(void* context, uint32_t custom_event) {
    App* app = context;
    return scene_manager_handle_custom_event(app->scene_manager, custom_event);
}

bool app_back_event_callback(void* context) {
    App* app = context;
    return scene_manager_handle_back_event(app->scene_manager);
}
  1. App struct를 생성해주는 함수를 만들어 줍니다. 그냥 코드에 바로 적어도 상관은 없지만 가독성, 유지보수를 위해서는 분리하여 적는 것이 좋습니다.
App* app_alloc() {
    App* app = malloc(sizeof(App));

    app->view_dispatcher = view_dispatcher_alloc();
    app->scene_manager = scene_manager_alloc(&app_scene_event_handlers, app);

    view_dispatcher_enable_queue(app->view_dispatcher);
    view_dispatcher_set_event_callback_context(app->view_dispatcher, app);
    view_dispatcher_set_custom_event_callback(app->view_dispatcher, app_custom_callback);
    view_dispatcher_set_navigation_event_callback(app->view_dispatcher, app_back_event_callback);

    return app;
}
  1. App struct를 지워주는 함수도 만들어 줍니다. 작은 단위부터 지우는 것을 추천합니다(alloc의 역순).
void app_free(App* app) {
    scene_manager_free(app->scene_manager);
    view_dispatcher_free(app->view_dispatcher);
    free(app);
}
  1. GUI에 view_dispatcher 붙이기
int32_t my_first_app_app(void* p) {
    UNUSED(p);

    Gui* gui = furi_record_open(RECORD_GUI);
    App* app = app_alloc();

    view_dispatcher_attach_to_gui(app->view_dispatcher, gui, ViewDispatcherTypeFullscreen);
    // scene_manager_next_scene(scene_manager, AppSceneMain); 추후 사용
    view_dispatcher_run(app->view_dispatcher);

    app_free(app);
    furi_record_close(RECORD_GUI);

    return 0;
}

https://gist.github.com/blluv/db1fc66360f63f2c6dd28e80beb056bf

기본코드 함수 설명

  • furi_record_open GUI 서비스를 가져옵니다

  • view_dispatcher_enable_queue view_dispatcher의 이벤트 큐를 생성합니다 view_dispatcher_run을 쓰기 위해서는 필수적으로 들어가야 합니다. (왜 view_dispatcher_alloc할 때 안하는지는 의문..)

  • view_dispatcher_set_event_callback_context view_dispatcher 이벤트 콜백의 context를 설정합니다. 아무 값이나 들어가도 상관은 없지만 일반적으로 앱의 모든(?) 요소가 있는 App struct를 넣습니다. (이 context는 scene 콜백의 context도 설정해줍니다.)

  • view_dispatcher_set_custom_event_callback view_dispatcher가 custom event를 받았을 때 실행할 callback 함수를 설정합니다.

  • scene_manager_handle_custom_event 커스텀 이벤트를 scene의 on_event에서 받을 수 있게 해줍니다.

  • view_dispatcher_set_navigation_event_callback view_dispatcher가 백 버튼 이벤트를 받았을 때 실행할 callback 함수를 설정합니다. (콜백 함수가 false를 리턴했을 경우 view_dispatcher 종료)

  • scene_manager_handle_back_event

    • 백 버튼 이벤트를 현재 scene의 on_event로 넘기고 사용자가 처리를 안했을 때 scene_manager 기본 동작(이전 scene으로 가기)을 처리하게 합니다.
    • scene_manager가 이벤트를 처리할 수 없을 때(개발자가 처리 안함 && 돌아갈 scene이 없음) false를 반환합니다.

위의 설명을 지금은 이해 못하셔도 상관 없습니다..!

GUI1 최종코드
https://gist.github.com/blluv/db1fc66360f63f2c6dd28e80beb056bf

0개의 댓글