feat(msg): add publisher-subscriber messaging
This commit is contained in:
20
examples/others/msg/index.rst
Normal file
20
examples/others/msg/index.rst
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
Slider to label messaging
|
||||
"""""""""""""""""""""""""
|
||||
|
||||
.. lv_example:: others/msg/lv_example_msg_1
|
||||
:language: c
|
||||
|
||||
Handling login and its states
|
||||
"""""""""""""""""""""""""""""
|
||||
|
||||
.. lv_example:: others/msg/lv_example_msg_2
|
||||
:language: c
|
||||
|
||||
Setting the same value from many sources
|
||||
""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
.. lv_example:: others/msg/lv_example_msg_3
|
||||
:language: c
|
||||
|
||||
|
||||
40
examples/others/msg/lv_example_msg.h
Normal file
40
examples/others/msg/lv_example_msg.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* @file lv_example_msg.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_EXAMPLE_MSG_H
|
||||
#define LV_EXAMPLE_MSG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
void lv_example_msg_1(void);
|
||||
void lv_example_msg_2(void);
|
||||
void lv_example_msg_3(void);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_EXAMPLE_MSG_H*/
|
||||
49
examples/others/msg/lv_example_msg_1.c
Normal file
49
examples/others/msg/lv_example_msg_1.c
Normal file
@@ -0,0 +1,49 @@
|
||||
#include "../../lv_examples.h"
|
||||
#if LV_USE_MSG && LV_USE_SLIDER && LV_USE_LABEL && LV_BUILD_EXAMPLES
|
||||
|
||||
/*Define a message ID*/
|
||||
#define MSG_NEW_TEMPERATURE 1
|
||||
|
||||
static void slider_event_cb(lv_event_t * e);
|
||||
static void label_event_cb(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* A slider sends a message on value change and a label display's that value
|
||||
*/
|
||||
void lv_example_msg_1(void)
|
||||
{
|
||||
/*Create a slider in the center of the display*/
|
||||
lv_obj_t * slider = lv_slider_create(lv_scr_act());
|
||||
lv_obj_center(slider);
|
||||
lv_obj_add_event_cb(slider, slider_event_cb, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
|
||||
/*Create a label below the slider*/
|
||||
lv_obj_t * label = lv_label_create(lv_scr_act());
|
||||
lv_obj_add_event_cb(label, label_event_cb, LV_EVENT_MSG_RECEIVED, NULL);
|
||||
lv_label_set_text(label, "0%");
|
||||
lv_obj_align(label, LV_ALIGN_CENTER, 0, 30);
|
||||
|
||||
/*Subscribe the label to a message. Also use the user_data to set a format string here.*/
|
||||
lv_msg_subsribe_obj(MSG_NEW_TEMPERATURE, label, "%d °C");
|
||||
}
|
||||
|
||||
static void slider_event_cb(lv_event_t * e)
|
||||
{
|
||||
/*Notify all subscribers (only the label now) that the slider value has been changed*/
|
||||
lv_obj_t * slider = lv_event_get_target(e);
|
||||
int32_t v = lv_slider_get_value(slider);
|
||||
lv_msg_send(MSG_NEW_TEMPERATURE, &v);
|
||||
}
|
||||
|
||||
static void label_event_cb(lv_event_t * e)
|
||||
{
|
||||
lv_obj_t * label = lv_event_get_target(e);
|
||||
lv_msg_t * m = lv_event_get_msg(e);
|
||||
|
||||
const char * fmt = lv_msg_get_user_data(m);
|
||||
const int32_t * v = lv_msg_get_payload(m);
|
||||
|
||||
lv_label_set_text_fmt(label, fmt, *v);
|
||||
}
|
||||
|
||||
#endif
|
||||
168
examples/others/msg/lv_example_msg_2.c
Normal file
168
examples/others/msg/lv_example_msg_2.c
Normal file
@@ -0,0 +1,168 @@
|
||||
#include "../../lv_examples.h"
|
||||
#if LV_USE_MSG && LV_USE_SLIDER && LV_USE_LABEL && LV_BUILD_EXAMPLES
|
||||
|
||||
/*Define a message ID*/
|
||||
#define MSG_LOGIN_ATTEMPT 1
|
||||
#define MSG_LOG_OUT 2
|
||||
#define MSG_LOGIN_ERROR 3
|
||||
#define MSG_LOGIN_OK 4
|
||||
|
||||
static void auth_manager(void * s, lv_msg_t * m);
|
||||
static void textarea_event_cb(lv_event_t * e);
|
||||
static void log_out_event_cb(lv_event_t * e);
|
||||
static void start_engine_msg_event_cb(lv_event_t * e);
|
||||
static void info_label_msg_event_cb(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Simple PIN login screen.
|
||||
* No global variables are used, all state changes are communicated via messages.
|
||||
*/
|
||||
void lv_example_msg_2(void)
|
||||
{
|
||||
lv_msg_subsribe(MSG_LOGIN_ATTEMPT, auth_manager, "hello");
|
||||
|
||||
/*Create a slider in the center of the display*/
|
||||
lv_obj_t * ta = lv_textarea_create(lv_scr_act());
|
||||
lv_obj_set_pos(ta, 10, 10);
|
||||
lv_obj_set_width(ta, 200);
|
||||
lv_textarea_set_one_line(ta, true);
|
||||
lv_textarea_set_password_mode(ta, true);
|
||||
lv_textarea_set_placeholder_text(ta, "The password is: hello");
|
||||
lv_obj_add_event_cb(ta, textarea_event_cb, LV_EVENT_ALL, NULL);
|
||||
lv_msg_subsribe_obj(MSG_LOGIN_ERROR, ta, NULL);
|
||||
lv_msg_subsribe_obj(MSG_LOGIN_OK, ta, NULL);
|
||||
lv_msg_subsribe_obj(MSG_LOG_OUT, ta, NULL);
|
||||
|
||||
lv_obj_t * kb = lv_keyboard_create(lv_scr_act());
|
||||
lv_keyboard_set_textarea(kb, ta);
|
||||
|
||||
lv_obj_t * btn;
|
||||
lv_obj_t * label;
|
||||
|
||||
/*Create a log out button which will be active only when logged in*/
|
||||
btn = lv_btn_create(lv_scr_act());
|
||||
lv_obj_set_pos(btn, 240, 10);
|
||||
lv_obj_add_event_cb(btn, log_out_event_cb, LV_EVENT_ALL, NULL);
|
||||
lv_msg_subsribe_obj(MSG_LOGIN_OK, btn, NULL);
|
||||
lv_msg_subsribe_obj(MSG_LOG_OUT, btn, NULL);
|
||||
|
||||
label = lv_label_create(btn);
|
||||
lv_label_set_text(label, "LOG OUT");
|
||||
|
||||
/*Create a label to show info*/
|
||||
label = lv_label_create(lv_scr_act());
|
||||
lv_label_set_text(label, "");
|
||||
lv_obj_add_event_cb(label, info_label_msg_event_cb, LV_EVENT_MSG_RECEIVED, NULL);
|
||||
lv_obj_set_pos(label, 10, 60);
|
||||
lv_msg_subsribe_obj(MSG_LOGIN_ERROR, label, NULL);
|
||||
lv_msg_subsribe_obj(MSG_LOGIN_OK, label, NULL);
|
||||
lv_msg_subsribe_obj(MSG_LOG_OUT, label, NULL);
|
||||
|
||||
/*Create button which will be active only when logged in*/
|
||||
btn = lv_btn_create(lv_scr_act());
|
||||
lv_obj_set_pos(btn, 10, 80);
|
||||
lv_obj_add_event_cb(btn, start_engine_msg_event_cb, LV_EVENT_MSG_RECEIVED, NULL);
|
||||
lv_obj_add_flag(btn, LV_OBJ_FLAG_CHECKABLE);
|
||||
lv_msg_subsribe_obj(MSG_LOGIN_OK, btn, NULL);
|
||||
lv_msg_subsribe_obj(MSG_LOG_OUT, btn, NULL);
|
||||
|
||||
label = lv_label_create(btn);
|
||||
lv_label_set_text(label, "START ENGINE");
|
||||
|
||||
lv_msg_send(MSG_LOG_OUT, NULL);
|
||||
}
|
||||
|
||||
static void auth_manager(void * s, lv_msg_t * m)
|
||||
{
|
||||
LV_UNUSED(s);
|
||||
const char * pin_act = lv_msg_get_payload(m);
|
||||
const char * pin_expexted = lv_msg_get_user_data(m);
|
||||
if(strcmp(pin_act, pin_expexted) == 0) {
|
||||
lv_msg_send(MSG_LOGIN_OK, NULL);
|
||||
} else {
|
||||
lv_msg_send(MSG_LOGIN_ERROR, "Incorrect PIN");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void textarea_event_cb(lv_event_t * e)
|
||||
{
|
||||
lv_obj_t * ta = lv_event_get_target(e);
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
if(code == LV_EVENT_READY) {
|
||||
lv_msg_send(MSG_LOGIN_ATTEMPT, lv_textarea_get_text(ta));
|
||||
} else if (code == LV_EVENT_MSG_RECEIVED) {
|
||||
lv_msg_t * m = lv_event_get_msg(e);
|
||||
switch(lv_msg_get_id(m)) {
|
||||
case MSG_LOGIN_ERROR:
|
||||
/*If there was an error, clean the text area*/
|
||||
if(strlen(lv_msg_get_payload(m))) lv_textarea_set_text(ta, "");
|
||||
break;
|
||||
case MSG_LOGIN_OK:
|
||||
lv_obj_add_state(ta, LV_STATE_DISABLED);
|
||||
lv_obj_clear_state(ta, LV_STATE_FOCUSED | LV_STATE_FOCUS_KEY);
|
||||
break;
|
||||
case MSG_LOG_OUT:
|
||||
lv_textarea_set_text(ta, "");
|
||||
lv_obj_clear_state(ta, LV_STATE_DISABLED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void log_out_event_cb(lv_event_t * e)
|
||||
{
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
if(code == LV_EVENT_CLICKED) {
|
||||
lv_msg_send(MSG_LOG_OUT, NULL);
|
||||
} else if (code == LV_EVENT_MSG_RECEIVED) {
|
||||
lv_msg_t * m = lv_event_get_msg(e);
|
||||
lv_obj_t * btn = lv_event_get_target(e);
|
||||
switch(lv_msg_get_id(m)) {
|
||||
case MSG_LOGIN_OK:
|
||||
lv_obj_clear_state(btn, LV_STATE_DISABLED);
|
||||
break;
|
||||
case MSG_LOG_OUT:
|
||||
lv_obj_add_state(btn, LV_STATE_DISABLED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void start_engine_msg_event_cb(lv_event_t * e)
|
||||
{
|
||||
lv_msg_t * m = lv_event_get_msg(e);
|
||||
lv_obj_t * btn = lv_event_get_target(e);
|
||||
switch(lv_msg_get_id(m)) {
|
||||
case MSG_LOGIN_OK:
|
||||
lv_obj_clear_state(btn, LV_STATE_DISABLED);
|
||||
break;
|
||||
case MSG_LOG_OUT:
|
||||
lv_obj_add_state(btn, LV_STATE_DISABLED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void info_label_msg_event_cb(lv_event_t * e)
|
||||
{
|
||||
lv_obj_t * label = lv_event_get_target(e);
|
||||
lv_msg_t * m = lv_event_get_msg(e);
|
||||
switch(lv_msg_get_id(m)) {
|
||||
case MSG_LOGIN_ERROR:
|
||||
lv_label_set_text(label, lv_msg_get_payload(m));
|
||||
lv_obj_set_style_text_color(label, lv_palette_main(LV_PALETTE_RED), 0);
|
||||
break;
|
||||
case MSG_LOGIN_OK:
|
||||
lv_label_set_text(label, "Login successful");
|
||||
lv_obj_set_style_text_color(label, lv_palette_main(LV_PALETTE_GREEN), 0);
|
||||
break;
|
||||
case MSG_LOG_OUT:
|
||||
lv_label_set_text(label, "Logged out");
|
||||
lv_obj_set_style_text_color(label, lv_palette_main(LV_PALETTE_GREY), 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
152
examples/others/msg/lv_example_msg_3.c
Normal file
152
examples/others/msg/lv_example_msg_3.c
Normal file
@@ -0,0 +1,152 @@
|
||||
#include "../../lv_examples.h"
|
||||
#if LV_USE_MSG && LV_USE_SLIDER && LV_USE_LABEL && LV_BUILD_EXAMPLES
|
||||
|
||||
/*Define a message ID*/
|
||||
#define MSG_INC 1
|
||||
#define MSG_DEC 2
|
||||
#define MSG_SET 3
|
||||
#define MSG_UPDATE 4
|
||||
#define MSG_UPDATE_REQUEST 5
|
||||
|
||||
static void value_handler(void * s, lv_msg_t * m);
|
||||
static void value_handler(void * s, lv_msg_t * m);
|
||||
static void btn_event_cb(lv_event_t * e);
|
||||
static void label_event_cb(lv_event_t * e);
|
||||
static void slider_event_cb(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* Show how an increment button, a decrement button, as slider can set a value
|
||||
* and a label display it.
|
||||
* The current value (i.e. the system's state) is stored only in one static variable in a function
|
||||
* and no global variables are required.
|
||||
*/
|
||||
void lv_example_msg_3(void)
|
||||
{
|
||||
|
||||
lv_msg_subsribe(MSG_INC, value_handler, NULL);
|
||||
lv_msg_subsribe(MSG_DEC, value_handler, NULL);
|
||||
lv_msg_subsribe(MSG_SET, value_handler, NULL);
|
||||
lv_msg_subsribe(MSG_UPDATE, value_handler, NULL);
|
||||
lv_msg_subsribe(MSG_UPDATE_REQUEST, value_handler, NULL);
|
||||
|
||||
lv_obj_t * panel = lv_obj_create(lv_scr_act());
|
||||
lv_obj_set_size(panel, 250, LV_SIZE_CONTENT);
|
||||
lv_obj_center(panel);
|
||||
lv_obj_set_flex_flow(panel, LV_FLEX_FLOW_ROW);
|
||||
lv_obj_set_flex_align(panel, LV_FLEX_ALIGN_SPACE_BETWEEN, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_START);
|
||||
|
||||
lv_obj_t * btn;
|
||||
lv_obj_t * label;
|
||||
|
||||
/*Up button*/
|
||||
btn = lv_btn_create(panel);
|
||||
lv_obj_set_flex_grow(btn, 1);
|
||||
lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_ALL, NULL);
|
||||
label = lv_label_create(btn);
|
||||
lv_label_set_text(label, LV_SYMBOL_LEFT);
|
||||
lv_obj_center(label);
|
||||
|
||||
/*Current value*/
|
||||
label = lv_label_create(panel);
|
||||
lv_obj_set_flex_grow(label, 2);
|
||||
lv_obj_set_style_text_align(label, LV_TEXT_ALIGN_CENTER, 0);
|
||||
lv_label_set_text(label, "?");
|
||||
lv_msg_subsribe_obj(MSG_UPDATE, label, NULL);
|
||||
lv_obj_add_event_cb(label, label_event_cb, LV_EVENT_MSG_RECEIVED, NULL);
|
||||
|
||||
/*Down button*/
|
||||
btn = lv_btn_create(panel);
|
||||
lv_obj_set_flex_grow(btn, 1);
|
||||
lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_ALL, NULL);
|
||||
label = lv_label_create(btn);
|
||||
lv_label_set_text(label, LV_SYMBOL_RIGHT);
|
||||
lv_obj_center(label);
|
||||
|
||||
/*Slider*/
|
||||
lv_obj_t * slider = lv_slider_create(panel);
|
||||
lv_obj_set_flex_grow(slider, 1);
|
||||
lv_obj_add_flag(slider, LV_OBJ_FLAG_FLEX_IN_NEW_TRACK);
|
||||
lv_obj_add_event_cb(slider, slider_event_cb, LV_EVENT_ALL, NULL);
|
||||
lv_msg_subsribe_obj(MSG_UPDATE, slider, NULL);
|
||||
|
||||
|
||||
/* As there are new UI elements that don't know the system's state
|
||||
* send an UPDATE REQUEST message which will trigger an UPDATE message with the current value*/
|
||||
lv_msg_send(MSG_UPDATE_REQUEST, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void value_handler(void * s, lv_msg_t * m)
|
||||
{
|
||||
LV_UNUSED(s);
|
||||
|
||||
static int32_t value = 10;
|
||||
int32_t old_value = value;
|
||||
switch(lv_msg_get_id(m)) {
|
||||
case MSG_INC:
|
||||
if(value < 100) value++;
|
||||
break;
|
||||
case MSG_DEC:
|
||||
if(value > 0) value--;
|
||||
break;
|
||||
case MSG_SET: {
|
||||
const int32_t * new_value = lv_msg_get_payload(m);
|
||||
value = *new_value;
|
||||
}
|
||||
break;
|
||||
case MSG_UPDATE_REQUEST:
|
||||
lv_msg_send(MSG_UPDATE, &value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(value != old_value) {
|
||||
lv_msg_send(MSG_UPDATE, &value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void btn_event_cb(lv_event_t * e)
|
||||
{
|
||||
lv_obj_t * btn = lv_event_get_target(e);
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
if(code == LV_EVENT_CLICKED || code == LV_EVENT_LONG_PRESSED_REPEAT) {
|
||||
if(lv_obj_get_index(btn) == 0) { /*First object is the dec. button*/
|
||||
lv_msg_send(MSG_DEC, NULL);
|
||||
} else {
|
||||
lv_msg_send(MSG_INC, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void label_event_cb(lv_event_t * e)
|
||||
{
|
||||
lv_obj_t * label = lv_event_get_target(e);
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
if (code == LV_EVENT_MSG_RECEIVED) {
|
||||
lv_msg_t * m = lv_event_get_msg(e);
|
||||
if(lv_msg_get_id(m) == MSG_UPDATE) {
|
||||
const int32_t *v = lv_msg_get_payload(m);
|
||||
lv_label_set_text_fmt(label, "%d %%", *v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void slider_event_cb(lv_event_t * e)
|
||||
{
|
||||
lv_obj_t * slider = lv_event_get_target(e);
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
if(code == LV_EVENT_VALUE_CHANGED) {
|
||||
int32_t v = lv_slider_get_value(slider);
|
||||
lv_msg_send(MSG_SET, &v);
|
||||
} else if (code == LV_EVENT_MSG_RECEIVED) {
|
||||
lv_msg_t * m = lv_event_get_msg(e);
|
||||
if(lv_msg_get_id(m) == MSG_UPDATE) {
|
||||
const int32_t *v = lv_msg_get_payload(m);
|
||||
lv_slider_set_value(slider, *v, LV_ANIM_OFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user