wip text edit GUI (TODO: del/ins in the middle, entering space at the end)

textedit
Ondřej Hruška 5 years ago
parent e22d4fb9e2
commit dd689841bb
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 1
      main/CMakeLists.txt
  2. 4
      main/analog.c
  3. 4
      main/firehazard.c
  4. 4
      main/graphics/drawing.h
  5. 17
      main/scenes/scene_manual_menu.c
  6. 209
      main/scenes/scene_string.c
  7. 35
      main/scenes/scene_string.h
  8. 1
      main/scenes/scenes.h

@ -8,6 +8,7 @@ set(COMPONENT_SRCS
"scenes/scene_bootanim.c" "scenes/scene_bootanim.c"
"scenes/scene_menu.c" "scenes/scene_menu.c"
"scenes/scene_number.c" "scenes/scene_number.c"
"scenes/scene_string.c"
"scenes/scene_manual_menu.c" "scenes/scene_manual_menu.c"
"scenes/scene_popup_menu.c" "scenes/scene_popup_menu.c"
"scenes/scene_popup_test.c" "scenes/scene_popup_test.c"

@ -82,12 +82,12 @@ static void __attribute__((noreturn)) analog_service(void *arg) {
#define CORRECT -10; #define CORRECT -10;
mv += CORRECT; mv += CORRECT;
printf("Raw: %d ... Voltage: %dmV ...", adc_reading, mv); // printf("Raw: %d ... Voltage: %dmV ...", adc_reading, mv);
float volts = mv * 0.001f; float volts = mv * 0.001f;
float celsius = v_to_c(volts); float celsius = v_to_c(volts);
printf("Celsius: %.1f°C\n", celsius); // printf("Celsius: %.1f°C\n", celsius);
measurement_celsius = celsius; measurement_celsius = celsius;

@ -90,7 +90,7 @@ void fire_regulate(float cels) {
if (pid.ctlMode == PID_MANUAL) { if (pid.ctlMode == PID_MANUAL) {
pwm_set(0); pwm_set(0);
} else { } else {
printf("PID in %.2f°C, out %.3f, I %.3f\n", cels, pid.Output, pid.ITerm); // printf("PID in %.2f°C, out %.3f, I %.3f\n", cels, pid.Output, pid.ITerm);
pwm_set(pid.Output); pwm_set(pid.Output);
} }
} }
@ -126,7 +126,7 @@ static void pwm_set(float duty)
{ {
uint32_t max_duty = (1 << PWM_BIT_NUM);// - 1 uint32_t max_duty = (1 << PWM_BIT_NUM);// - 1
uint32_t dutycycle = lroundf((duty) * (float)max_duty); uint32_t dutycycle = lroundf((duty) * (float)max_duty);
printf("Dutycycle %d\n", dutycycle); // printf("Dutycycle %d\n", dutycycle);
ESP_ERROR_CHECK( ledc_set_duty(LEDC_HIGH_SPEED_MODE, PWM_CHANNEL, dutycycle) ); ESP_ERROR_CHECK( ledc_set_duty(LEDC_HIGH_SPEED_MODE, PWM_CHANNEL, dutycycle) );
ESP_ERROR_CHECK( ledc_update_duty(LEDC_HIGH_SPEED_MODE, PWM_CHANNEL) ); ESP_ERROR_CHECK( ledc_update_duty(LEDC_HIGH_SPEED_MODE, PWM_CHANNEL) );

@ -61,8 +61,8 @@ struct TextStyle {
bool bg; //!< Fill the characters background with the opposite color bool bg; //!< Fill the characters background with the opposite color
enum TextSize size; //!< Character size enum TextSize size; //!< Character size
enum TextAlign align; //!< Alignment (works only for single line) enum TextAlign align; //!< Alignment (works only for single line)
int limit; //!< Number of characters to print from the string, if > 0 size_t limit; //!< Number of characters to print from the string, if > 0
int skip; //!< Characters to skip before printing size_t skip; //!< Characters to skip before printing
int spacing_x; //!< Additional X spacing int spacing_x; //!< Additional X spacing
int spacing_y; //!< Additional Y spacing int spacing_y; //!< Additional Y spacing
bool nowrap; //!< Stop painting when the right edge of the screen is reached bool nowrap; //!< Stop painting when the right edge of the screen is reached

@ -11,7 +11,6 @@
#include "graphics/display_spec.h" #include "graphics/display_spec.h"
#include "scenes.h" #include "scenes.h"
#include "scene_menu.h"
struct Priv { struct Priv {
int _placeholder; int _placeholder;
@ -35,6 +34,16 @@ static struct SceneEvent onSelect(struct MenuScene *self) {
else if (self->selected == 2) { else if (self->selected == 2) {
return SceneEvent_OpenChild(NewScene_PopupTest(), 1); return SceneEvent_OpenChild(NewScene_PopupTest(), 1);
} }
else if (self->selected == 3) {
struct StringSceneOpts *opts = calloc(1, sizeof(struct StringSceneOpts));
strcpy(opts->value, "");
return SceneEvent_OpenChild(NewScene_String(opts), 1);
}
else if (self->selected == 4) {
struct StringSceneOpts *opts = calloc(1, sizeof(struct StringSceneOpts));
strcpy(opts->value, "AHOJ");
return SceneEvent_OpenChild(NewScene_String(opts), 1);
}
return SceneEvent_None(); return SceneEvent_None();
} }
@ -65,6 +74,8 @@ void print_labels(struct MenuItem *items) {
} }
strncpy(items[2].label, "▶Item with popup", MENUITEM_LABEL_LEN); strncpy(items[2].label, "▶Item with popup", MENUITEM_LABEL_LEN);
strncpy(items[3].label, "▶Empty str", MENUITEM_LABEL_LEN);
strncpy(items[4].label, "▶Filled str", MENUITEM_LABEL_LEN);
} }
static void paint(struct MenuScene *self) static void paint(struct MenuScene *self)
@ -94,11 +105,11 @@ static void paint(struct MenuScene *self)
} }
struct Scene *NewScene_MenuManual() { struct Scene *NewScene_MenuManual() {
struct MenuItem *items = calloc(3, sizeof(struct MenuItem)); struct MenuItem *items = calloc(5, sizeof(struct MenuItem));
print_labels(items); print_labels(items);
struct MenuScene * scene = NewScene_Menu(items, 3); struct MenuScene * scene = NewScene_Menu(items, 5);
scene->onSelect = onSelect; scene->onSelect = onSelect;
scene->x = XLINE; scene->x = XLINE;

@ -0,0 +1,209 @@
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#include <common_utils/utils.h>
#include "liquid.h"
#include "liquid/input_event.h"
#include "graphics/drawing.h"
#include "graphics/display_spec.h"
#include "scene_string.h"
enum Focus {
FOC_CHAR,
FOC_CHAR_EDIT,
FOC_SUBMIT,
FOC_CANCEL,
};
struct StringScene {
struct Scene base;
struct StringSceneOpts *opts;
int editedchar;
int length;
enum Focus foc;
};
// !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
const char SYMBOLS[] = " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
static void onWheel(struct StringScene *self, struct InputEvent event);
static struct SceneEvent onButton(struct StringScene *self, struct InputEvent event);
static void ensureCharNotNull(struct StringScene *self);
static void trimTailSpaces(struct StringScene *self);
static struct SceneEvent onInput(struct StringScene *self, struct InputEvent event) {
switch (event.kind) {
case InputEventKind_Wheel:
onWheel(self, event);
return SceneEvent_Repaint();
case InputEventKind_Button:
return onButton(self, event);
default:
return SceneEvent_None();
}
}
static struct SceneEvent onButton(struct StringScene *self, struct InputEvent event)
{
if (event.button.state) {
switch (self->foc) {
case FOC_CHAR:
printf("start char edit\n");
self->foc = FOC_CHAR_EDIT;
ensureCharNotNull(self);
return SceneEvent_Repaint();
case FOC_CHAR_EDIT:
if (self->editedchar == self->length) {
printf("submit last char\n");
if (self->opts->value[self->editedchar] == ' ') {
printf("empty, go to -> submit\n");
self->foc = FOC_SUBMIT;
}
else {
printf("not empty, advance and keep editing\n");
self->length += 1;
self->editedchar += 1;
}
}
else {
printf("exit char edit\n");
self->foc = FOC_CHAR;
}
return SceneEvent_Repaint();
case FOC_SUBMIT:
return SceneEvent_Close(1, NULL); // TODO copy str
case FOC_CANCEL:
return SceneEvent_Close(0, NULL);
}
}
return SceneEvent_None();
}
static void onWheel(struct StringScene *self, struct InputEvent event)
{
switch (self->foc) {
case FOC_CHAR:
self->editedchar += event.wheel.direction;
printf("Move cursor %d\n", event.wheel.direction);
if (self->editedchar < 0) {
self->editedchar = 0;
self->foc = FOC_CANCEL;
printf("chars -> cancel\n");
}
else if (self->editedchar > self->length) {
self->editedchar = self->length;
self->foc = FOC_SUBMIT;
printf("chars -> submit\n");
}
else {
printf("move within chars\n");
ensureCharNotNull(self);
}
trimTailSpaces(self);
break;
case FOC_CHAR_EDIT:;
// FIXME this looks buggy
const char *pos = strchr(SYMBOLS, self->opts->value[self->editedchar]) + event.wheel.direction;
if (pos < SYMBOLS) {
pos = SYMBOLS + strlen(SYMBOLS) - 1;
} else if (*pos == 0) {
pos = SYMBOLS;
}
self->opts->value[self->editedchar] = *pos;
printf("char %d change: %c\n", self->editedchar, *pos);
break;
case FOC_SUBMIT:
if (event.wheel.direction > 0) {
printf("submit -> cancel\n");
self->foc = FOC_CANCEL;
} else {
printf("submit -> last char\n");
self->foc = FOC_CHAR;
self->editedchar = self->length;
}
break;
case FOC_CANCEL:
if (event.wheel.direction > 0) {
printf("cancel -> first char\n");
self->foc = FOC_CHAR;
self->editedchar = 0;
} else {
printf("cancel -> submit\n");
self->foc = FOC_SUBMIT;
}
break;
}
}
static void paint(struct StringScene *self)
{
struct StringSceneOpts *opts = self->opts;
LCD_clearDisplay(0);
ensureCharNotNull(self);
LCD_setStrEx(opts->value, 1, 1, BLACK, (struct TextStyle) {
.limit = MAX(self->editedchar+1, self->length),
});
if (self->foc == FOC_CHAR) {
LCD_setRect(self->editedchar*6, 8, self->editedchar*6+5, 8, false, BLACK);
} else if (self->foc == FOC_CHAR_EDIT) {
LCD_setRect(self->editedchar*6, 8, self->editedchar*6+5, 9, false, BLACK);
}
LCD_setStrEx("Ok", 50, 15, self->foc == FOC_SUBMIT ? WHITE : BLACK, (struct TextStyle) {.size = FONT_BOLD, .bg=1});
LCD_setStrEx("Cancel", 1, 15, self->foc == FOC_CANCEL ? WHITE : BLACK, (struct TextStyle) {.size = FONT_BOLD, .bg=1});
}
static void ensureCharNotNull(struct StringScene *self)
{
struct StringSceneOpts *opts = self->opts;
// ensure there is something to draw
if (!opts->value[self->editedchar]) {
opts->value[self->editedchar] = ' ';
}
}
static void trimTailSpaces(struct StringScene *self)
{
int pos = self->length;
while (pos > 0 && self->opts->value[pos - 1] == ' ') {
pos--;
}
self->length = pos;
}
static void deinit(struct StringScene *self)
{
free(self->opts);
self->opts = NULL;
}
struct Scene *NewScene_String(struct StringSceneOpts *opts) {
struct StringScene *scene = calloc(1, sizeof(struct StringScene));
if (!scene) return NULL;
scene->opts = opts;
scene->base.onInput = (Scene_onInput_t) onInput;
scene->base.paint = (Scene_paint_t) paint;
scene->base.deinit = (Scene_deinit_t) deinit;
scene->length = strlen(opts->value);
scene->foc = scene->length==0? FOC_CHAR_EDIT : FOC_CHAR;
scene->editedchar = 0;
ensureCharNotNull(scene);
return (struct Scene *) scene;
}

@ -0,0 +1,35 @@
/**
* TODO file description
*
* Created on 2020/01/05.
*/
#ifndef REFLOWER_SCENE_STR_H
#define REFLOWER_SCENE_STR_H
#include <stdint.h>
#define STR_EDIT_VALUE_MAXLEN 17
/**
* Options passed to the StringScene constructor
*/
struct StringSceneOpts {
// Screen title
char label[15];
// Value
char value[STR_EDIT_VALUE_MAXLEN];
};
/**
* Create string picker.
*
* "opts" must be on heap and will be internally mutated.
* The scene frees them on exit, returning the selected value as data (heap string), or NULL on cancel.
*
* @param opts
* @return
*/
struct Scene *NewScene_String(struct StringSceneOpts *opts);
#endif //REFLOWER_SCENE_STR_H

@ -17,6 +17,7 @@ struct Scene *NewScene_PopupTest();
#include "scene_menu.h" #include "scene_menu.h"
#include "scene_number.h" #include "scene_number.h"
#include "scene_string.h"
struct MenuScene *NewScene_PopupMenu(struct MenuItem *items, size_t items_len); struct MenuScene *NewScene_PopupMenu(struct MenuItem *items, size_t items_len);

Loading…
Cancel
Save