| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326 |
- #include "multi_converter_mode_display.h"
- #define MULTI_CONVERTER_DISPLAY_KEYS 18 // [0] to [F] + [BACK] + [SELECT]
- #define MULTI_CONVERTER_DISPLAY_KEY_NEGATIVE 0 // long press
- #define MULTI_CONVERTER_DISPLAY_KEY_COMMA 1 // long press
- #define MULTI_CONVERTER_DISPLAY_KEY_DEL 16
- #define MULTI_CONVERTER_DISPLAY_KEY_SELECT 17
- #define MULTI_CONVERTER_DISPLAY_CHAR_COMMA '.'
- #define MULTI_CONVERTER_DISPLAY_CHAR_NEGATIVE '-'
- #define MULTI_CONVERTER_DISPLAY_CHAR_DEL '<'
- #define MULTI_CONVERTER_DISPLAY_CHAR_SELECT '#'
- #define MULTI_CONVERTER_DISPLAY_CHAR_BLANK ' '
- #define MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN 3
- #define MULTI_CONVERTER_DISPLAY_KEY_CHAR_HEIGHT 8
- void multi_converter_mode_display_convert(MultiConverterState* const multi_converter_state) {
- // 1.- if origin == destination (in theory user won't be allowed to choose the same options, but it's kinda "valid"...)
- // just copy buffer_orig to buffer_dest and that's it
- if(multi_converter_state->unit_type_orig == multi_converter_state->unit_type_dest) {
- memcpy(
- multi_converter_state->buffer_dest,
- multi_converter_state->buffer_orig,
- MULTI_CONVERTER_NUMBER_DIGITS);
- return;
- }
- // 2.- origin_buffer has not null functions
- if(multi_converter_get_unit(multi_converter_state->unit_type_orig).convert_function == NULL ||
- multi_converter_get_unit(multi_converter_state->unit_type_orig).allowed_function == NULL)
- return;
- // 3.- valid destination type (using allowed_destinations function)
- if(!multi_converter_get_unit(multi_converter_state->unit_type_orig)
- .allowed_function(multi_converter_state->unit_type_dest))
- return;
- multi_converter_get_unit(multi_converter_state->unit_type_orig)
- .convert_function(multi_converter_state);
- }
- void multi_converter_mode_display_draw(
- Canvas* const canvas,
- const MultiConverterState* multi_converter_state) {
- canvas_set_color(canvas, ColorBlack);
- // ORIGIN
- canvas_set_font(canvas, FontPrimary);
- canvas_draw_str(
- canvas, 2, 10, multi_converter_get_unit(multi_converter_state->unit_type_orig).mini_name);
- canvas_set_font(canvas, FontPrimary);
- canvas_draw_str(canvas, 2 + 30, 10, multi_converter_state->buffer_orig);
- // DESTINATION
- canvas_set_font(canvas, FontPrimary);
- canvas_draw_str(
- canvas,
- 2,
- 10 + 12,
- multi_converter_get_unit(multi_converter_state->unit_type_dest).mini_name);
- canvas_set_font(canvas, FontPrimary);
- canvas_draw_str(canvas, 2 + 30, 10 + 12, multi_converter_state->buffer_dest);
- // SEPARATOR_LINE
- canvas_draw_line(canvas, 2, 25, 128 - 3, 25);
- // KEYBOARD
- uint8_t _x = 5;
- uint8_t _y = 25 + 15; // line + 10
- for(int i = 0; i < MULTI_CONVERTER_DISPLAY_KEYS; i++) {
- char g;
- if(i < 10)
- g = (i + '0');
- else if(i < 16)
- g = ((i - 10) + 'A');
- else if(i == MULTI_CONVERTER_DISPLAY_KEY_DEL)
- g = MULTI_CONVERTER_DISPLAY_CHAR_DEL;
- else
- g = MULTI_CONVERTER_DISPLAY_CHAR_SELECT;
- uint8_t g_w = canvas_glyph_width(canvas, g);
- if(i < 16 &&
- i > multi_converter_get_unit(multi_converter_state->unit_type_orig).max_number_keys -
- 1) {
- // some units won't use the full [0] - [F] keyboard, in those situations just hide the char
- // (won't be selectable anyway, so no worries here; this is just about drawing stuff)
- g = MULTI_CONVERTER_DISPLAY_CHAR_BLANK;
- }
- // currently hover key is highlighted
- if((multi_converter_state->display).key == i) {
- canvas_draw_box(
- canvas,
- _x - MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN,
- _y - (MULTI_CONVERTER_DISPLAY_KEY_CHAR_HEIGHT +
- MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN),
- MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN + g_w +
- MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN,
- MULTI_CONVERTER_DISPLAY_KEY_CHAR_HEIGHT +
- MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN * 2);
- canvas_set_color(canvas, ColorWhite);
- } else {
- canvas_draw_frame(
- canvas,
- _x - MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN,
- _y - (MULTI_CONVERTER_DISPLAY_KEY_CHAR_HEIGHT +
- MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN),
- MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN + g_w +
- MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN,
- MULTI_CONVERTER_DISPLAY_KEY_CHAR_HEIGHT +
- MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN * 2);
- }
- // draw key
- canvas_draw_glyph(canvas, _x, _y, g);
- // certain keys have long_press features, draw whatever they're using there too
- if(i == MULTI_CONVERTER_DISPLAY_KEY_NEGATIVE) {
- canvas_draw_box(
- canvas,
- _x + MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN + g_w - 4,
- _y + MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN - 2,
- 4,
- 2);
- } else if(i == MULTI_CONVERTER_DISPLAY_KEY_COMMA) {
- canvas_draw_box(
- canvas,
- _x + MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN + g_w - 2,
- _y + MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN - 2,
- 2,
- 2);
- }
- // back to black
- canvas_set_color(canvas, ColorBlack);
- if(i < 8) {
- _x += g_w + MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN * 2 + 2;
- } else if(i == 8) {
- _y += (MULTI_CONVERTER_DISPLAY_KEY_CHAR_HEIGHT +
- MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN * 2) +
- 3;
- _x = 8; // some padding at the beginning on second line
- } else {
- _x += g_w + MULTI_CONVERTER_DISPLAY_KEY_FRAME_MARGIN * 2 + 1;
- }
- }
- }
- void multi_converter_mode_display_navigation(
- InputKey key,
- MultiConverterState* const multi_converter_state) {
- // first move to keyboard position, then check if the ORIGIN allows that specific key, if not jump to the "closest one"
- switch(key) {
- default:
- break;
- case InputKeyUp:
- case InputKeyDown:
- if((multi_converter_state->display).key >= 9)
- (multi_converter_state->display).key -= 9;
- else
- (multi_converter_state->display).key += 9;
- break;
- case InputKeyLeft:
- case InputKeyRight:
- (multi_converter_state->display).key += (key == InputKeyLeft ? -1 : 1);
- if((multi_converter_state->display).key > MULTI_CONVERTER_DISPLAY_KEYS - 1)
- (multi_converter_state->display).key = 0;
- else if((multi_converter_state->display).key < 0)
- (multi_converter_state->display).key = MULTI_CONVERTER_DISPLAY_KEYS - 1;
- break;
- }
- // if destination key is disabled by max_number_keys, move to the closest one
- // (this could be improved with more accurate keys movements, probably...)
- if(multi_converter_get_unit(multi_converter_state->unit_type_orig).max_number_keys >= 16)
- return; // weird, since this means "do not show any number on the keyboard, but just in case..."
- int8_t i = -1;
- if(key == InputKeyRight || key == InputKeyDown) i = 1;
- while((multi_converter_state->display).key < 16 &&
- (multi_converter_state->display).key >
- multi_converter_get_unit(multi_converter_state->unit_type_orig).max_number_keys -
- 1) {
- (multi_converter_state->display).key += i;
- if((multi_converter_state->display).key > MULTI_CONVERTER_DISPLAY_KEYS - 1)
- (multi_converter_state->display).key = 0;
- else if((multi_converter_state->display).key < 0)
- (multi_converter_state->display).key = MULTI_CONVERTER_DISPLAY_KEYS - 1;
- }
- }
- void multi_converter_mode_display_reset(MultiConverterState* const multi_converter_state) {
- // clean the buffers
- for(int i = 0; i < MULTI_CONVERTER_NUMBER_DIGITS; i++) {
- multi_converter_state->buffer_orig[i] = MULTI_CONVERTER_DISPLAY_CHAR_BLANK;
- multi_converter_state->buffer_dest[i] = MULTI_CONVERTER_DISPLAY_CHAR_BLANK;
- }
- // reset the display flags and index
- multi_converter_state->display.cursor = 0;
- multi_converter_state->display.key = 0;
- multi_converter_state->display.comma = 0;
- multi_converter_state->display.negative = 0;
- }
- void multi_converter_mode_display_toggle_negative(
- MultiConverterState* const multi_converter_state) {
- if(multi_converter_get_unit(multi_converter_state->unit_type_orig).allow_negative) {
- if(!(multi_converter_state->display).negative) {
- // shift origin buffer one to right + add the "-" sign (last digit will be lost)
- for(int i = MULTI_CONVERTER_NUMBER_DIGITS - 1; i > 0; i--) {
- // we could avoid the blanks, but nevermind
- multi_converter_state->buffer_orig[i] = multi_converter_state->buffer_orig[i - 1];
- }
- multi_converter_state->buffer_orig[0] = MULTI_CONVERTER_DISPLAY_CHAR_NEGATIVE;
- // only increment cursor if we're not out of bound
- if((multi_converter_state->display).cursor < MULTI_CONVERTER_NUMBER_DIGITS)
- (multi_converter_state->display).cursor++;
- } else {
- // shift origin buffer one to left, append ' ' on the end
- for(int i = 0; i < MULTI_CONVERTER_NUMBER_DIGITS - 1; i++) {
- if(multi_converter_state->buffer_orig[i] == MULTI_CONVERTER_DISPLAY_CHAR_BLANK)
- break;
- multi_converter_state->buffer_orig[i] = multi_converter_state->buffer_orig[i + 1];
- }
- multi_converter_state->buffer_orig[MULTI_CONVERTER_NUMBER_DIGITS - 1] =
- MULTI_CONVERTER_DISPLAY_CHAR_BLANK;
- (multi_converter_state->display).cursor--;
- }
- // toggle flag
- (multi_converter_state->display).negative ^= 1;
- }
- }
- void multi_converter_mode_display_add_comma(MultiConverterState* const multi_converter_state) {
- if(!multi_converter_get_unit(multi_converter_state->unit_type_orig).allow_comma ||
- (multi_converter_state->display).comma || !(multi_converter_state->display).cursor ||
- ((multi_converter_state->display).cursor == (MULTI_CONVERTER_NUMBER_DIGITS - 1)))
- return; // maybe not allowerd; or one comma already in place; also cannot add commas as first or last chars
- // set flag to one
- (multi_converter_state->display).comma = 1;
- multi_converter_state->buffer_orig[(multi_converter_state->display).cursor] =
- MULTI_CONVERTER_DISPLAY_CHAR_COMMA;
- (multi_converter_state->display).cursor++;
- }
- void multi_converter_mode_display_add_number(MultiConverterState* const multi_converter_state) {
- if((multi_converter_state->display).key >
- multi_converter_get_unit(multi_converter_state->unit_type_orig).max_number_keys - 1)
- return;
- if((multi_converter_state->display).key < 10) {
- multi_converter_state->buffer_orig[(multi_converter_state->display).cursor] =
- (multi_converter_state->display).key + '0';
- } else {
- multi_converter_state->buffer_orig[(multi_converter_state->display).cursor] =
- ((multi_converter_state->display).key - 10) + 'A';
- }
- (multi_converter_state->display).cursor++;
- }
- MultiConverterModeTrigger multi_converter_mode_display_ok(
- uint8_t long_press,
- MultiConverterState* const multi_converter_state) {
- if((multi_converter_state->display).key < MULTI_CONVERTER_DISPLAY_KEY_DEL) {
- if((multi_converter_state->display).cursor >= MULTI_CONVERTER_NUMBER_DIGITS)
- return None; // limit reached, ignore
- // long press on 0 toggle NEGATIVE if allowed, on 1 adds COMMA if allowed
- if(long_press) {
- if((multi_converter_state->display).key == MULTI_CONVERTER_DISPLAY_KEY_NEGATIVE) {
- // toggle negative
- multi_converter_mode_display_toggle_negative(multi_converter_state);
- } else if((multi_converter_state->display).key == MULTI_CONVERTER_DISPLAY_KEY_COMMA) {
- // add comma
- multi_converter_mode_display_add_comma(multi_converter_state);
- }
- } else {
- // regular keys
- multi_converter_mode_display_add_number(multi_converter_state);
- }
- multi_converter_mode_display_convert(multi_converter_state);
- } else if((multi_converter_state->display).key == MULTI_CONVERTER_DISPLAY_KEY_DEL) {
- if((multi_converter_state->display).cursor > 0) (multi_converter_state->display).cursor--;
- if(multi_converter_state->buffer_orig[(multi_converter_state->display).cursor] ==
- MULTI_CONVERTER_DISPLAY_CHAR_COMMA)
- (multi_converter_state->display).comma = 0;
- if(multi_converter_state->buffer_orig[(multi_converter_state->display).cursor] ==
- MULTI_CONVERTER_DISPLAY_CHAR_NEGATIVE)
- (multi_converter_state->display).negative = 0;
- multi_converter_state->buffer_orig[(multi_converter_state->display).cursor] =
- MULTI_CONVERTER_DISPLAY_CHAR_BLANK;
- multi_converter_mode_display_convert(multi_converter_state);
- } else { // MULTI_CONVERTER_DISPLAY_KEY_SELECT
- return Reset;
- }
- return None;
- }
|