mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-11 06:09:08 -07:00
barcodes
This commit is contained in:
510
applications/external/barcode_gen/views/barcode_view.c
vendored
Normal file
510
applications/external/barcode_gen/views/barcode_view.c
vendored
Normal file
@@ -0,0 +1,510 @@
|
||||
#include "../barcode_app.h"
|
||||
#include "barcode_view.h"
|
||||
#include "../encodings.h"
|
||||
|
||||
/**
|
||||
* @brief Draws a single bit from a barcode at a specified location
|
||||
* @param canvas
|
||||
* @param bit a 1 or a 0 to signify a bit of data
|
||||
* @param x the top left x coordinate
|
||||
* @param y the top left y coordinate
|
||||
* @param width the width of the bit
|
||||
* @param height the height of the bit
|
||||
*/
|
||||
static void draw_bit(Canvas* canvas, int bit, int x, int y, int width, int height) {
|
||||
if(bit == 1) {
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
} else {
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_box(canvas, x, y, width, height);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void draw_error_str(Canvas* canvas, const char* error) {
|
||||
canvas_clear(canvas);
|
||||
canvas_draw_str_aligned(canvas, 62, 30, AlignCenter, AlignCenter, error);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bits a string of 1's and 0's
|
||||
* @returns the x coordinate after the bits have been drawn, useful for drawing the next section of bits
|
||||
*/
|
||||
static int draw_bits(Canvas* canvas, const char* bits, int x, int y, int width, int height) {
|
||||
int bits_length = strlen(bits);
|
||||
for(int i = 0; i < bits_length; i++) {
|
||||
char c = bits[i];
|
||||
int num = c - '0';
|
||||
|
||||
draw_bit(canvas, num, x, y, width, height);
|
||||
|
||||
x += width;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws an EAN-8 type barcode, does not check if the barcode is valid
|
||||
* @param canvas the canvas
|
||||
* @param barcode_digits the digits in the barcode, must be 8 characters long
|
||||
*/
|
||||
static void draw_ean_8(Canvas* canvas, BarcodeData* barcode_data) {
|
||||
FuriString* barcode_digits = barcode_data->correct_data;
|
||||
BarcodeTypeObj* type_obj = barcode_data->type_obj;
|
||||
|
||||
int barcode_length = furi_string_size(barcode_digits);
|
||||
|
||||
int x = type_obj->start_pos;
|
||||
int y = BARCODE_Y_START;
|
||||
int width = 1;
|
||||
int height = BARCODE_HEIGHT;
|
||||
|
||||
//the guard patterns for the beginning, center, ending
|
||||
const char* end_bits = "101";
|
||||
const char* center_bits = "01010";
|
||||
|
||||
//draw the starting guard pattern
|
||||
x = draw_bits(canvas, end_bits, x, y, width, height + 5);
|
||||
|
||||
FuriString* code_part = furi_string_alloc();
|
||||
|
||||
//loop through each digit, find the encoding, and draw it
|
||||
for(int i = 0; i < barcode_length; i++) {
|
||||
char current_digit = furi_string_get_char(barcode_digits, i);
|
||||
|
||||
//the actual number and the index of the bits
|
||||
int index = current_digit - '0';
|
||||
//use the L-codes for the first 4 digits and the R-Codes for the last 4 digits
|
||||
if(i <= 3) {
|
||||
furi_string_set_str(code_part, UPC_EAN_L_CODES[index]);
|
||||
} else {
|
||||
furi_string_set_str(code_part, UPC_EAN_R_CODES[index]);
|
||||
}
|
||||
|
||||
//convert the current_digit char into a string so it can be printed
|
||||
char current_digit_string[2];
|
||||
snprintf(current_digit_string, 2, "%c", current_digit);
|
||||
|
||||
//set the canvas color to black to print the digit
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_draw_str(canvas, x + 1, y + height + 8, current_digit_string);
|
||||
|
||||
//draw the bits of the barcode
|
||||
x = draw_bits(canvas, furi_string_get_cstr(code_part), x, y, width, height);
|
||||
|
||||
//if the index has reached 3, that means 4 digits have been drawn and now draw the center guard pattern
|
||||
if(i == 3) {
|
||||
x = draw_bits(canvas, center_bits, x, y, width, height + 5);
|
||||
}
|
||||
}
|
||||
furi_string_free(code_part);
|
||||
|
||||
//draw the ending guard pattern
|
||||
x = draw_bits(canvas, end_bits, x, y, width, height + 5);
|
||||
}
|
||||
|
||||
static void draw_ean_13(Canvas* canvas, BarcodeData* barcode_data) {
|
||||
FuriString* barcode_digits = barcode_data->correct_data;
|
||||
BarcodeTypeObj* type_obj = barcode_data->type_obj;
|
||||
|
||||
int barcode_length = furi_string_size(barcode_digits);
|
||||
|
||||
int x = type_obj->start_pos;
|
||||
int y = BARCODE_Y_START;
|
||||
int width = 1;
|
||||
int height = BARCODE_HEIGHT;
|
||||
|
||||
//the guard patterns for the beginning, center, ending
|
||||
const char* end_bits = "101";
|
||||
const char* center_bits = "01010";
|
||||
|
||||
//draw the starting guard pattern
|
||||
x = draw_bits(canvas, end_bits, x, y, width, height + 5);
|
||||
|
||||
FuriString* left_structure = furi_string_alloc();
|
||||
FuriString* code_part = furi_string_alloc();
|
||||
|
||||
//loop through each digit, find the encoding, and draw it
|
||||
for(int i = 0; i < barcode_length; i++) {
|
||||
char current_digit = furi_string_get_char(barcode_digits, i);
|
||||
int index = current_digit - '0';
|
||||
|
||||
if(i == 0) {
|
||||
furi_string_set_str(left_structure, EAN_13_STRUCTURE_CODES[index]);
|
||||
|
||||
//convert the current_digit char into a string so it can be printed
|
||||
char current_digit_string[2];
|
||||
snprintf(current_digit_string, 2, "%c", current_digit);
|
||||
|
||||
//set the canvas color to black to print the digit
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_draw_str(canvas, x - 10, y + height + 8, current_digit_string);
|
||||
|
||||
continue;
|
||||
} else {
|
||||
//use the L-codes for the first 6 digits and the R-Codes for the last 6 digits
|
||||
if(i <= 6) {
|
||||
//get the encoding type at the current barcode bit position
|
||||
char encoding_type = furi_string_get_char(left_structure, i - 1);
|
||||
if(encoding_type == 'L') {
|
||||
furi_string_set_str(code_part, UPC_EAN_L_CODES[index]);
|
||||
} else {
|
||||
furi_string_set_str(code_part, EAN_G_CODES[index]);
|
||||
}
|
||||
} else {
|
||||
furi_string_set_str(code_part, UPC_EAN_R_CODES[index]);
|
||||
}
|
||||
|
||||
//convert the current_digit char into a string so it can be printed
|
||||
char current_digit_string[2];
|
||||
snprintf(current_digit_string, 2, "%c", current_digit);
|
||||
|
||||
//set the canvas color to black to print the digit
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_draw_str(canvas, x + 1, y + height + 8, current_digit_string);
|
||||
|
||||
//draw the bits of the barcode
|
||||
x = draw_bits(canvas, furi_string_get_cstr(code_part), x, y, width, height);
|
||||
|
||||
//if the index has reached 6, that means 6 digits have been drawn and we now draw the center guard pattern
|
||||
if(i == 6) {
|
||||
x = draw_bits(canvas, center_bits, x, y, width, height + 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
furi_string_free(left_structure);
|
||||
furi_string_free(code_part);
|
||||
|
||||
//draw the ending guard pattern
|
||||
x = draw_bits(canvas, end_bits, x, y, width, height + 5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw a UPC-A barcode
|
||||
*/
|
||||
static void draw_upc_a(Canvas* canvas, BarcodeData* barcode_data) {
|
||||
FuriString* barcode_digits = barcode_data->correct_data;
|
||||
BarcodeTypeObj* type_obj = barcode_data->type_obj;
|
||||
|
||||
int barcode_length = furi_string_size(barcode_digits);
|
||||
|
||||
int x = type_obj->start_pos;
|
||||
int y = BARCODE_Y_START;
|
||||
int width = 1;
|
||||
int height = BARCODE_HEIGHT;
|
||||
|
||||
//the guard patterns for the beginning, center, ending
|
||||
char* end_bits = "101";
|
||||
char* center_bits = "01010";
|
||||
|
||||
//draw the starting guard pattern
|
||||
x = draw_bits(canvas, end_bits, x, y, width, height + 5);
|
||||
|
||||
FuriString* code_part = furi_string_alloc();
|
||||
|
||||
//loop through each digit, find the encoding, and draw it
|
||||
for(int i = 0; i < barcode_length; i++) {
|
||||
char current_digit = furi_string_get_char(barcode_digits, i);
|
||||
int index = current_digit - '0'; //convert the number into an int (also the index)
|
||||
|
||||
//use the L-codes for the first 6 digits and the R-Codes for the last 6 digits
|
||||
if(i <= 5) {
|
||||
furi_string_set_str(code_part, UPC_EAN_L_CODES[index]);
|
||||
} else {
|
||||
furi_string_set_str(code_part, UPC_EAN_R_CODES[index]);
|
||||
}
|
||||
|
||||
//convert the current_digit char into a string so it can be printed
|
||||
char current_digit_string[2];
|
||||
snprintf(current_digit_string, 2, "%c", current_digit);
|
||||
|
||||
//set the canvas color to black to print the digit
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_draw_str(canvas, x + 1, y + height + 8, current_digit_string);
|
||||
|
||||
//draw the bits of the barcode
|
||||
x = draw_bits(canvas, furi_string_get_cstr(code_part), x, y, width, height);
|
||||
|
||||
//if the index has reached 6, that means 6 digits have been drawn and we now draw the center guard pattern
|
||||
if(i == 5) {
|
||||
x = draw_bits(canvas, center_bits, x, y, width, height + 5);
|
||||
}
|
||||
}
|
||||
|
||||
furi_string_free(code_part);
|
||||
|
||||
//draw the ending guard pattern
|
||||
x = draw_bits(canvas, end_bits, x, y, width, height + 5);
|
||||
}
|
||||
|
||||
static void draw_code_39(Canvas* canvas, BarcodeData* barcode_data) {
|
||||
FuriString* raw_data = barcode_data->raw_data;
|
||||
FuriString* barcode_digits = barcode_data->correct_data;
|
||||
//BarcodeTypeObj* type_obj = barcode_data->type_obj;
|
||||
|
||||
int barcode_length = furi_string_size(barcode_digits);
|
||||
int total_pixels = 0;
|
||||
|
||||
for(int i = 0; i < barcode_length; i++) {
|
||||
//1 for wide, 0 for narrow
|
||||
char wide_or_narrow = furi_string_get_char(barcode_digits, i);
|
||||
int wn_digit = wide_or_narrow - '0'; //wide(1) or narrow(0) digit
|
||||
|
||||
if(wn_digit == 1) {
|
||||
total_pixels += 3;
|
||||
} else {
|
||||
total_pixels += 1;
|
||||
}
|
||||
if((i + 1) % 9 == 0) {
|
||||
total_pixels += 1;
|
||||
}
|
||||
}
|
||||
|
||||
int x = (128 - total_pixels) / 2;
|
||||
int y = BARCODE_Y_START;
|
||||
int width = 1;
|
||||
int height = BARCODE_HEIGHT;
|
||||
bool filled_in = true;
|
||||
|
||||
//set the canvas color to black to print the digit
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
// canvas_draw_str_aligned(canvas, 62, 30, AlignCenter, AlignCenter, error);
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 62, y + height + 8, AlignCenter, AlignBottom, furi_string_get_cstr(raw_data));
|
||||
|
||||
for(int i = 0; i < barcode_length; i++) {
|
||||
//1 for wide, 0 for narrow
|
||||
char wide_or_narrow = furi_string_get_char(barcode_digits, i);
|
||||
int wn_digit = wide_or_narrow - '0'; //wide(1) or narrow(0) digit
|
||||
|
||||
if(filled_in) {
|
||||
if(wn_digit == 1) {
|
||||
x = draw_bits(canvas, "111", x, y, width, height);
|
||||
} else {
|
||||
x = draw_bits(canvas, "1", x, y, width, height);
|
||||
}
|
||||
filled_in = false;
|
||||
} else {
|
||||
if(wn_digit == 1) {
|
||||
x = draw_bits(canvas, "000", x, y, width, height);
|
||||
} else {
|
||||
x = draw_bits(canvas, "0", x, y, width, height);
|
||||
}
|
||||
filled_in = true;
|
||||
}
|
||||
if((i + 1) % 9 == 0) {
|
||||
x = draw_bits(canvas, "0", x, y, width, height);
|
||||
filled_in = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_code_128(Canvas* canvas, BarcodeData* barcode_data) {
|
||||
FuriString* raw_data = barcode_data->raw_data;
|
||||
FuriString* barcode_digits = barcode_data->correct_data;
|
||||
|
||||
int barcode_length = furi_string_size(barcode_digits);
|
||||
|
||||
int x = (128 - barcode_length) / 2;
|
||||
int y = BARCODE_Y_START;
|
||||
int width = 1;
|
||||
int height = BARCODE_HEIGHT;
|
||||
|
||||
x = draw_bits(canvas, furi_string_get_cstr(barcode_digits), x, y, width, height);
|
||||
|
||||
//set the canvas color to black to print the digit
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
// canvas_draw_str_aligned(canvas, 62, 30, AlignCenter, AlignCenter, error);
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 62, y + height + 8, AlignCenter, AlignBottom, furi_string_get_cstr(raw_data));
|
||||
}
|
||||
|
||||
static void draw_codabar(Canvas* canvas, BarcodeData* barcode_data) {
|
||||
FuriString* raw_data = barcode_data->raw_data;
|
||||
FuriString* barcode_digits = barcode_data->correct_data;
|
||||
//BarcodeTypeObj* type_obj = barcode_data->type_obj;
|
||||
|
||||
int barcode_length = furi_string_size(barcode_digits);
|
||||
int total_pixels = 0;
|
||||
|
||||
for(int i = 0; i < barcode_length; i++) {
|
||||
//1 for wide, 0 for narrow
|
||||
char wide_or_narrow = furi_string_get_char(barcode_digits, i);
|
||||
int wn_digit = wide_or_narrow - '0'; //wide(1) or narrow(0) digit
|
||||
|
||||
if(wn_digit == 1) {
|
||||
total_pixels += 3;
|
||||
} else {
|
||||
total_pixels += 1;
|
||||
}
|
||||
if((i + 1) % 7 == 0) {
|
||||
total_pixels += 1;
|
||||
}
|
||||
}
|
||||
|
||||
int x = (128 - total_pixels) / 2;
|
||||
int y = BARCODE_Y_START;
|
||||
int width = 1;
|
||||
int height = BARCODE_HEIGHT;
|
||||
bool filled_in = true;
|
||||
|
||||
//set the canvas color to black to print the digit
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
// canvas_draw_str_aligned(canvas, 62, 30, AlignCenter, AlignCenter, error);
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 62, y + height + 8, AlignCenter, AlignBottom, furi_string_get_cstr(raw_data));
|
||||
|
||||
for(int i = 0; i < barcode_length; i++) {
|
||||
//1 for wide, 0 for narrow
|
||||
char wide_or_narrow = furi_string_get_char(barcode_digits, i);
|
||||
int wn_digit = wide_or_narrow - '0'; //wide(1) or narrow(0) digit
|
||||
|
||||
if(filled_in) {
|
||||
if(wn_digit == 1) {
|
||||
x = draw_bits(canvas, "111", x, y, width, height);
|
||||
} else {
|
||||
x = draw_bits(canvas, "1", x, y, width, height);
|
||||
}
|
||||
filled_in = false;
|
||||
} else {
|
||||
if(wn_digit == 1) {
|
||||
x = draw_bits(canvas, "000", x, y, width, height);
|
||||
} else {
|
||||
x = draw_bits(canvas, "0", x, y, width, height);
|
||||
}
|
||||
filled_in = true;
|
||||
}
|
||||
if((i + 1) % 7 == 0) {
|
||||
x = draw_bits(canvas, "0", x, y, width, height);
|
||||
filled_in = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void barcode_draw_callback(Canvas* canvas, void* ctx) {
|
||||
furi_assert(ctx);
|
||||
BarcodeModel* barcode_model = ctx;
|
||||
BarcodeData* data = barcode_model->data;
|
||||
// const char* barcode_digits =;
|
||||
|
||||
canvas_clear(canvas);
|
||||
if(data->valid) {
|
||||
switch(data->type_obj->type) {
|
||||
case UPCA:
|
||||
draw_upc_a(canvas, data);
|
||||
break;
|
||||
case EAN8:
|
||||
draw_ean_8(canvas, data);
|
||||
break;
|
||||
case EAN13:
|
||||
draw_ean_13(canvas, data);
|
||||
break;
|
||||
case CODE39:
|
||||
draw_code_39(canvas, data);
|
||||
break;
|
||||
case CODE128:
|
||||
case CODE128C:
|
||||
draw_code_128(canvas, data);
|
||||
break;
|
||||
case CODABAR:
|
||||
draw_codabar(canvas, data);
|
||||
break;
|
||||
case UNKNOWN:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch(data->reason) {
|
||||
case WrongNumberOfDigits:
|
||||
draw_error_str(canvas, "Wrong # of characters");
|
||||
break;
|
||||
case InvalidCharacters:
|
||||
draw_error_str(canvas, "Invalid characters");
|
||||
break;
|
||||
case UnsupportedType:
|
||||
draw_error_str(canvas, "Unsupported barcode type");
|
||||
break;
|
||||
case FileOpening:
|
||||
draw_error_str(canvas, "Could not open file");
|
||||
break;
|
||||
case InvalidFileData:
|
||||
draw_error_str(canvas, "Invalid file data");
|
||||
break;
|
||||
case MissingEncodingTable:
|
||||
draw_error_str(canvas, "Missing encoding table");
|
||||
break;
|
||||
case EncodingTableError:
|
||||
draw_error_str(canvas, "Encoding table error");
|
||||
break;
|
||||
default:
|
||||
draw_error_str(canvas, "Could not read barcode data");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool barcode_input_callback(InputEvent* input_event, void* ctx) {
|
||||
UNUSED(ctx);
|
||||
//furi_assert(ctx);
|
||||
|
||||
//Barcode* test_view_object = ctx;
|
||||
|
||||
if(input_event->key == InputKeyBack) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Barcode* barcode_view_allocate(BarcodeApp* barcode_app) {
|
||||
furi_assert(barcode_app);
|
||||
|
||||
Barcode* barcode = malloc(sizeof(Barcode));
|
||||
|
||||
barcode->view = view_alloc();
|
||||
barcode->barcode_app = barcode_app;
|
||||
|
||||
view_set_context(barcode->view, barcode);
|
||||
view_allocate_model(barcode->view, ViewModelTypeLocking, sizeof(BarcodeModel));
|
||||
view_set_draw_callback(barcode->view, barcode_draw_callback);
|
||||
view_set_input_callback(barcode->view, barcode_input_callback);
|
||||
|
||||
return barcode;
|
||||
}
|
||||
|
||||
void barcode_free_model(Barcode* barcode) {
|
||||
with_view_model(
|
||||
barcode->view,
|
||||
BarcodeModel * model,
|
||||
{
|
||||
if(model->file_path != NULL) {
|
||||
furi_string_free(model->file_path);
|
||||
}
|
||||
if(model->data != NULL) {
|
||||
if(model->data->raw_data != NULL) {
|
||||
furi_string_free(model->data->raw_data);
|
||||
}
|
||||
if(model->data->correct_data != NULL) {
|
||||
furi_string_free(model->data->correct_data);
|
||||
}
|
||||
free(model->data);
|
||||
}
|
||||
},
|
||||
false);
|
||||
}
|
||||
|
||||
void barcode_free(Barcode* barcode) {
|
||||
furi_assert(barcode);
|
||||
|
||||
barcode_free_model(barcode);
|
||||
view_free(barcode->view);
|
||||
free(barcode);
|
||||
}
|
||||
|
||||
View* barcode_get_view(Barcode* barcode) {
|
||||
furi_assert(barcode);
|
||||
return barcode->view;
|
||||
}
|
||||
23
applications/external/barcode_gen/views/barcode_view.h
vendored
Normal file
23
applications/external/barcode_gen/views/barcode_view.h
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/view.h>
|
||||
|
||||
typedef struct BarcodeApp BarcodeApp;
|
||||
|
||||
typedef struct {
|
||||
View* view;
|
||||
BarcodeApp* barcode_app;
|
||||
} Barcode;
|
||||
|
||||
typedef struct {
|
||||
FuriString* file_path;
|
||||
BarcodeData* data;
|
||||
} BarcodeModel;
|
||||
|
||||
Barcode* barcode_view_allocate(BarcodeApp* barcode_app);
|
||||
|
||||
void barcode_free_model(Barcode* barcode);
|
||||
|
||||
void barcode_free(Barcode* barcode);
|
||||
|
||||
View* barcode_get_view(Barcode* barcode);
|
||||
494
applications/external/barcode_gen/views/create_view.c
vendored
Normal file
494
applications/external/barcode_gen/views/create_view.c
vendored
Normal file
@@ -0,0 +1,494 @@
|
||||
#include "../barcode_app.h"
|
||||
#include "create_view.h"
|
||||
#include <math.h>
|
||||
|
||||
#define LINE_HEIGHT 16
|
||||
#define TEXT_PADDING 4
|
||||
#define TOTAL_MENU_ITEMS 5
|
||||
|
||||
typedef enum {
|
||||
TypeMenuItem,
|
||||
FileNameMenuItem,
|
||||
BarcodeDataMenuItem,
|
||||
SaveMenuButton,
|
||||
DeleteMenuButton
|
||||
} MenuItems;
|
||||
|
||||
/**
|
||||
* Took this function from blackjack
|
||||
* @author @teeebor
|
||||
*/
|
||||
void draw_menu_item(
|
||||
Canvas* const canvas,
|
||||
const char* text,
|
||||
const char* value,
|
||||
int y,
|
||||
bool left_caret,
|
||||
bool right_caret,
|
||||
bool selected) {
|
||||
UNUSED(selected);
|
||||
if(y < 0 || y >= 64) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(selected) {
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_draw_box(canvas, 0, y, 123, LINE_HEIGHT);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
|
||||
canvas_draw_str_aligned(canvas, 4, y + TEXT_PADDING, AlignLeft, AlignTop, text);
|
||||
if(left_caret) {
|
||||
canvas_draw_str_aligned(canvas, 60, y + TEXT_PADDING, AlignLeft, AlignTop, "<");
|
||||
}
|
||||
|
||||
canvas_draw_str_aligned(canvas, 90, y + TEXT_PADDING, AlignCenter, AlignTop, value);
|
||||
if(right_caret) {
|
||||
canvas_draw_str_aligned(canvas, 120, y + TEXT_PADDING, AlignRight, AlignTop, ">");
|
||||
}
|
||||
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
}
|
||||
|
||||
void draw_button(Canvas* const canvas, const char* text, int y, bool selected) {
|
||||
if(selected) {
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_draw_box(canvas, 0, y, 123, LINE_HEIGHT);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
|
||||
canvas_draw_str_aligned(canvas, 64, y + TEXT_PADDING, AlignCenter, AlignTop, text);
|
||||
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
}
|
||||
|
||||
static void app_draw_callback(Canvas* canvas, void* ctx) {
|
||||
furi_assert(ctx);
|
||||
|
||||
CreateViewModel* create_view_model = ctx;
|
||||
|
||||
BarcodeTypeObj* type_obj = create_view_model->barcode_type;
|
||||
if(create_view_model->barcode_type == NULL) {
|
||||
return;
|
||||
}
|
||||
BarcodeType selected_type = type_obj->type;
|
||||
|
||||
int selected_menu_item = create_view_model->selected_menu_item;
|
||||
|
||||
int total_menu_items = create_view_model->mode == EditMode ? TOTAL_MENU_ITEMS :
|
||||
TOTAL_MENU_ITEMS - 1;
|
||||
|
||||
int startY = 0;
|
||||
|
||||
//the menu items index that is/would be in view
|
||||
//int current_last_menu_item = selected_menu_item + 3;
|
||||
if(selected_menu_item > 1) {
|
||||
int offset = 2;
|
||||
if(selected_menu_item + offset > total_menu_items) {
|
||||
offset = 3;
|
||||
}
|
||||
startY -= (LINE_HEIGHT * (selected_menu_item - offset));
|
||||
}
|
||||
|
||||
//ensure that the scroll height is atleast 1
|
||||
int scrollHeight = ceil(64.0 / total_menu_items);
|
||||
int scrollPos = scrollHeight * selected_menu_item;
|
||||
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
//draw the scroll bar box
|
||||
canvas_draw_box(canvas, 125, scrollPos, 3, scrollHeight);
|
||||
//draw the scroll bar track
|
||||
canvas_draw_box(canvas, 126, 0, 1, 64);
|
||||
|
||||
draw_menu_item(
|
||||
canvas,
|
||||
"Type",
|
||||
type_obj->name,
|
||||
TypeMenuItem * LINE_HEIGHT + startY,
|
||||
selected_type > 0,
|
||||
selected_type < NUMBER_OF_BARCODE_TYPES - 2,
|
||||
selected_menu_item == TypeMenuItem);
|
||||
|
||||
draw_menu_item(
|
||||
canvas,
|
||||
"Name",
|
||||
furi_string_empty(create_view_model->file_name) ?
|
||||
"--" :
|
||||
furi_string_get_cstr(create_view_model->file_name),
|
||||
FileNameMenuItem * LINE_HEIGHT + startY,
|
||||
false,
|
||||
false,
|
||||
selected_menu_item == FileNameMenuItem);
|
||||
|
||||
draw_menu_item(
|
||||
canvas,
|
||||
"Data",
|
||||
furi_string_empty(create_view_model->barcode_data) ?
|
||||
"--" :
|
||||
furi_string_get_cstr(create_view_model->barcode_data),
|
||||
BarcodeDataMenuItem * LINE_HEIGHT + startY,
|
||||
false,
|
||||
false,
|
||||
selected_menu_item == BarcodeDataMenuItem);
|
||||
|
||||
draw_button(
|
||||
canvas,
|
||||
"Save",
|
||||
SaveMenuButton * LINE_HEIGHT + startY,
|
||||
selected_menu_item == SaveMenuButton);
|
||||
|
||||
if(create_view_model->mode == EditMode) {
|
||||
draw_button(
|
||||
canvas,
|
||||
"Delete",
|
||||
DeleteMenuButton * LINE_HEIGHT + startY,
|
||||
selected_menu_item == DeleteMenuButton);
|
||||
}
|
||||
}
|
||||
|
||||
void text_input_callback(void* ctx) {
|
||||
CreateView* create_view_object = ctx;
|
||||
|
||||
with_view_model(
|
||||
create_view_object->view,
|
||||
CreateViewModel * model,
|
||||
{
|
||||
if(create_view_object->setter == FileNameSetter) {
|
||||
furi_string_set_str(model->file_name, create_view_object->input);
|
||||
}
|
||||
if(create_view_object->setter == BarcodeDataSetter) {
|
||||
furi_string_set_str(model->barcode_data, create_view_object->input);
|
||||
}
|
||||
},
|
||||
true);
|
||||
|
||||
view_dispatcher_switch_to_view(
|
||||
create_view_object->barcode_app->view_dispatcher, CreateBarcodeView);
|
||||
}
|
||||
|
||||
static bool app_input_callback(InputEvent* input_event, void* ctx) {
|
||||
furi_assert(ctx);
|
||||
|
||||
if(input_event->key == InputKeyBack) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CreateView* create_view_object = ctx;
|
||||
|
||||
//get the currently selected menu item from the model
|
||||
int selected_menu_item = 0;
|
||||
BarcodeTypeObj* barcode_type = NULL;
|
||||
FuriString* file_name;
|
||||
FuriString* barcode_data;
|
||||
CreateMode mode;
|
||||
|
||||
with_view_model(
|
||||
create_view_object->view,
|
||||
CreateViewModel * model,
|
||||
{
|
||||
selected_menu_item = model->selected_menu_item;
|
||||
barcode_type = model->barcode_type;
|
||||
file_name = model->file_name;
|
||||
barcode_data = model->barcode_data;
|
||||
mode = model->mode;
|
||||
},
|
||||
true);
|
||||
|
||||
int total_menu_items = mode == EditMode ? TOTAL_MENU_ITEMS : TOTAL_MENU_ITEMS - 1;
|
||||
|
||||
if(input_event->type == InputTypePress) {
|
||||
if(input_event->key == InputKeyUp && selected_menu_item > 0) {
|
||||
selected_menu_item--;
|
||||
} else if(input_event->key == InputKeyDown && selected_menu_item < total_menu_items - 1) {
|
||||
selected_menu_item++;
|
||||
} else if(input_event->key == InputKeyLeft) {
|
||||
if(selected_menu_item == TypeMenuItem && barcode_type != NULL) { //Select Barcode Type
|
||||
if(barcode_type->type > 0) {
|
||||
barcode_type = barcode_type_objs[barcode_type->type - 1];
|
||||
}
|
||||
}
|
||||
} else if(input_event->key == InputKeyRight) {
|
||||
if(selected_menu_item == TypeMenuItem && barcode_type != NULL) { //Select Barcode Type
|
||||
if(barcode_type->type < NUMBER_OF_BARCODE_TYPES - 2) {
|
||||
barcode_type = barcode_type_objs[barcode_type->type + 1];
|
||||
}
|
||||
}
|
||||
} else if(input_event->key == InputKeyOk) {
|
||||
if(selected_menu_item == FileNameMenuItem && barcode_type != NULL) {
|
||||
create_view_object->setter = FileNameSetter;
|
||||
|
||||
snprintf(
|
||||
create_view_object->input,
|
||||
sizeof(create_view_object->input),
|
||||
"%s",
|
||||
furi_string_get_cstr(file_name));
|
||||
|
||||
text_input_set_result_callback(
|
||||
create_view_object->barcode_app->text_input,
|
||||
text_input_callback,
|
||||
create_view_object,
|
||||
create_view_object->input,
|
||||
TEXT_BUFFER_SIZE - BARCODE_EXTENSION_LENGTH, //remove the barcode length
|
||||
//clear default text
|
||||
false);
|
||||
text_input_set_header_text(
|
||||
create_view_object->barcode_app->text_input, "File Name");
|
||||
|
||||
view_dispatcher_switch_to_view(
|
||||
create_view_object->barcode_app->view_dispatcher, TextInputView);
|
||||
}
|
||||
if(selected_menu_item == BarcodeDataMenuItem && barcode_type != NULL) {
|
||||
create_view_object->setter = BarcodeDataSetter;
|
||||
|
||||
snprintf(
|
||||
create_view_object->input,
|
||||
sizeof(create_view_object->input),
|
||||
"%s",
|
||||
furi_string_get_cstr(barcode_data));
|
||||
|
||||
text_input_set_result_callback(
|
||||
create_view_object->barcode_app->text_input,
|
||||
text_input_callback,
|
||||
create_view_object,
|
||||
create_view_object->input,
|
||||
TEXT_BUFFER_SIZE,
|
||||
//clear default text
|
||||
false);
|
||||
text_input_set_header_text(
|
||||
create_view_object->barcode_app->text_input, "Barcode Data");
|
||||
|
||||
view_dispatcher_switch_to_view(
|
||||
create_view_object->barcode_app->view_dispatcher, TextInputView);
|
||||
}
|
||||
if(selected_menu_item == SaveMenuButton && barcode_type != NULL) {
|
||||
save_barcode(create_view_object);
|
||||
}
|
||||
if(selected_menu_item == DeleteMenuButton && barcode_type != NULL) {
|
||||
if(mode == EditMode) {
|
||||
remove_barcode(create_view_object);
|
||||
} else if(mode == NewMode) {
|
||||
view_dispatcher_switch_to_view(
|
||||
create_view_object->barcode_app->view_dispatcher, MainMenuView);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//change the currently selected menu item
|
||||
with_view_model(
|
||||
create_view_object->view,
|
||||
CreateViewModel * model,
|
||||
{
|
||||
model->selected_menu_item = selected_menu_item;
|
||||
model->barcode_type = barcode_type;
|
||||
},
|
||||
true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CreateView* create_view_allocate(BarcodeApp* barcode_app) {
|
||||
furi_assert(barcode_app);
|
||||
|
||||
CreateView* create_view_object = malloc(sizeof(CreateView));
|
||||
|
||||
create_view_object->view = view_alloc();
|
||||
create_view_object->barcode_app = barcode_app;
|
||||
|
||||
view_set_context(create_view_object->view, create_view_object);
|
||||
view_allocate_model(create_view_object->view, ViewModelTypeLocking, sizeof(CreateViewModel));
|
||||
view_set_draw_callback(create_view_object->view, app_draw_callback);
|
||||
view_set_input_callback(create_view_object->view, app_input_callback);
|
||||
|
||||
return create_view_object;
|
||||
}
|
||||
|
||||
void create_view_free_model(CreateView* create_view_object) {
|
||||
with_view_model(
|
||||
create_view_object->view,
|
||||
CreateViewModel * model,
|
||||
{
|
||||
if(model->file_path != NULL) {
|
||||
furi_string_free(model->file_path);
|
||||
}
|
||||
if(model->file_name != NULL) {
|
||||
furi_string_free(model->file_name);
|
||||
}
|
||||
if(model->barcode_data != NULL) {
|
||||
furi_string_free(model->barcode_data);
|
||||
}
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
void remove_barcode(CreateView* create_view_object) {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
|
||||
bool success = false;
|
||||
|
||||
with_view_model(
|
||||
create_view_object->view,
|
||||
CreateViewModel * model,
|
||||
{
|
||||
FURI_LOG_I(TAG, "Attempting to remove file");
|
||||
if(model->file_path != NULL) {
|
||||
FURI_LOG_I(TAG, "Removing File: %s", furi_string_get_cstr(model->file_path));
|
||||
if(storage_simply_remove(storage, furi_string_get_cstr(model->file_path))) {
|
||||
FURI_LOG_I(
|
||||
TAG,
|
||||
"File: \"%s\" was successfully removed",
|
||||
furi_string_get_cstr(model->file_path));
|
||||
success = true;
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Unable to remove file!");
|
||||
success = false;
|
||||
}
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Could not remove barcode file");
|
||||
success = false;
|
||||
}
|
||||
},
|
||||
true);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
with_view_model(
|
||||
create_view_object->barcode_app->message_view->view,
|
||||
MessageViewModel * model,
|
||||
{
|
||||
if(success) {
|
||||
model->message = "File Deleted";
|
||||
} else {
|
||||
model->message = "Could not delete file";
|
||||
}
|
||||
},
|
||||
true);
|
||||
|
||||
view_dispatcher_switch_to_view(
|
||||
create_view_object->barcode_app->view_dispatcher, MessageErrorView);
|
||||
}
|
||||
|
||||
void save_barcode(CreateView* create_view_object) {
|
||||
BarcodeTypeObj* barcode_type = NULL;
|
||||
FuriString* file_path; //this may be empty
|
||||
FuriString* file_name;
|
||||
FuriString* barcode_data;
|
||||
CreateMode mode;
|
||||
|
||||
with_view_model(
|
||||
create_view_object->view,
|
||||
CreateViewModel * model,
|
||||
{
|
||||
file_path = model->file_path;
|
||||
file_name = model->file_name;
|
||||
barcode_data = model->barcode_data;
|
||||
barcode_type = model->barcode_type;
|
||||
mode = model->mode;
|
||||
},
|
||||
true);
|
||||
|
||||
if(file_name == NULL || furi_string_empty(file_name)) {
|
||||
FURI_LOG_E(TAG, "File Name cannot be empty");
|
||||
return;
|
||||
}
|
||||
if(barcode_data == NULL || furi_string_empty(barcode_data)) {
|
||||
FURI_LOG_E(TAG, "Barcode Data cannot be empty");
|
||||
return;
|
||||
}
|
||||
if(barcode_type == NULL) {
|
||||
FURI_LOG_E(TAG, "Type not defined");
|
||||
return;
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
|
||||
FuriString* full_file_path = furi_string_alloc_set(DEFAULT_USER_BARCODES);
|
||||
furi_string_push_back(full_file_path, '/');
|
||||
furi_string_cat(full_file_path, file_name);
|
||||
furi_string_cat_str(full_file_path, BARCODE_EXTENSION);
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
|
||||
if(mode == EditMode) {
|
||||
if(!furi_string_empty(file_path)) {
|
||||
if(!furi_string_equal(file_path, full_file_path)) {
|
||||
FS_Error error = storage_common_rename(
|
||||
storage,
|
||||
furi_string_get_cstr(file_path),
|
||||
furi_string_get_cstr(full_file_path));
|
||||
if(error != FSE_OK) {
|
||||
FURI_LOG_E(TAG, "Rename error: %s", storage_error_get_desc(error));
|
||||
} else {
|
||||
FURI_LOG_I(TAG, "Rename Success");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FlipperFormat* ff = flipper_format_file_alloc(storage);
|
||||
|
||||
FURI_LOG_I(TAG, "Saving Barcode to: %s", furi_string_get_cstr(full_file_path));
|
||||
|
||||
bool file_opened_status = false;
|
||||
if(mode == NewMode) {
|
||||
file_opened_status =
|
||||
flipper_format_file_open_new(ff, furi_string_get_cstr(full_file_path));
|
||||
} else if(mode == EditMode) {
|
||||
file_opened_status =
|
||||
flipper_format_file_open_always(ff, furi_string_get_cstr(full_file_path));
|
||||
}
|
||||
|
||||
if(file_opened_status) {
|
||||
// Filetype: Barcode
|
||||
// Version: 1
|
||||
|
||||
// # Types - UPC-A, EAN-8, EAN-13, CODE-39
|
||||
// Type: CODE-39
|
||||
// Data: AB
|
||||
flipper_format_write_string_cstr(ff, "Filetype", "Barcode");
|
||||
|
||||
flipper_format_write_string_cstr(ff, "Version", FILE_VERSION);
|
||||
|
||||
flipper_format_write_comment_cstr(
|
||||
ff, "Types - UPC-A, EAN-8, EAN-13, CODE-39, CODE-128, Codabar");
|
||||
|
||||
flipper_format_write_string_cstr(ff, "Type", barcode_type->name);
|
||||
|
||||
flipper_format_write_string_cstr(ff, "Data", furi_string_get_cstr(barcode_data));
|
||||
|
||||
success = true;
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Save error");
|
||||
success = false;
|
||||
}
|
||||
furi_string_free(full_file_path);
|
||||
flipper_format_free(ff);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
with_view_model(
|
||||
create_view_object->barcode_app->message_view->view,
|
||||
MessageViewModel * model,
|
||||
{
|
||||
if(success) {
|
||||
model->message = "File Saved!";
|
||||
} else {
|
||||
model->message = "A saving error has occurred";
|
||||
}
|
||||
},
|
||||
true);
|
||||
|
||||
view_dispatcher_switch_to_view(
|
||||
create_view_object->barcode_app->view_dispatcher, MessageErrorView);
|
||||
}
|
||||
|
||||
void create_view_free(CreateView* create_view_object) {
|
||||
furi_assert(create_view_object);
|
||||
|
||||
create_view_free_model(create_view_object);
|
||||
view_free(create_view_object->view);
|
||||
free(create_view_object);
|
||||
}
|
||||
|
||||
View* create_get_view(CreateView* create_view_object) {
|
||||
furi_assert(create_view_object);
|
||||
return create_view_object->view;
|
||||
}
|
||||
46
applications/external/barcode_gen/views/create_view.h
vendored
Normal file
46
applications/external/barcode_gen/views/create_view.h
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/view.h>
|
||||
|
||||
typedef struct BarcodeApp BarcodeApp;
|
||||
|
||||
typedef enum {
|
||||
FileNameSetter,
|
||||
BarcodeDataSetter
|
||||
} InputSetter; //what value to set for the text input view
|
||||
|
||||
typedef enum {
|
||||
EditMode,
|
||||
|
||||
NewMode
|
||||
} CreateMode;
|
||||
|
||||
typedef struct {
|
||||
View* view;
|
||||
BarcodeApp* barcode_app;
|
||||
|
||||
InputSetter setter;
|
||||
char input[TEXT_BUFFER_SIZE];
|
||||
} CreateView;
|
||||
|
||||
typedef struct {
|
||||
int selected_menu_item;
|
||||
|
||||
CreateMode mode;
|
||||
BarcodeTypeObj* barcode_type;
|
||||
FuriString* file_path; //the current file that is opened
|
||||
FuriString* file_name;
|
||||
FuriString* barcode_data;
|
||||
} CreateViewModel;
|
||||
|
||||
CreateView* create_view_allocate(BarcodeApp* barcode_app);
|
||||
|
||||
void remove_barcode(CreateView* create_view_object);
|
||||
|
||||
void save_barcode(CreateView* create_view_object);
|
||||
|
||||
void create_view_free_model(CreateView* create_view_object);
|
||||
|
||||
void create_view_free(CreateView* create_view_object);
|
||||
|
||||
View* create_get_view(CreateView* create_view_object);
|
||||
66
applications/external/barcode_gen/views/message_view.c
vendored
Normal file
66
applications/external/barcode_gen/views/message_view.c
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
#include "../barcode_app.h"
|
||||
#include "message_view.h"
|
||||
|
||||
static void app_draw_callback(Canvas* canvas, void* ctx) {
|
||||
furi_assert(ctx);
|
||||
|
||||
MessageViewModel* message_view_model = ctx;
|
||||
|
||||
canvas_clear(canvas);
|
||||
if(message_view_model->message != NULL) {
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 62, 30, AlignCenter, AlignCenter, message_view_model->message);
|
||||
}
|
||||
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_draw_box(canvas, 100, 52, 28, 12);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
canvas_draw_str_aligned(canvas, 114, 58, AlignCenter, AlignCenter, "OK");
|
||||
}
|
||||
|
||||
static bool app_input_callback(InputEvent* input_event, void* ctx) {
|
||||
furi_assert(ctx);
|
||||
|
||||
MessageView* message_view_object = ctx;
|
||||
|
||||
if(input_event->key == InputKeyBack) {
|
||||
view_dispatcher_switch_to_view(
|
||||
message_view_object->barcode_app->view_dispatcher, MainMenuView);
|
||||
}
|
||||
if(input_event->type == InputTypeShort) {
|
||||
if(input_event->key == InputKeyOk) {
|
||||
view_dispatcher_switch_to_view(
|
||||
message_view_object->barcode_app->view_dispatcher, MainMenuView);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
MessageView* message_view_allocate(BarcodeApp* barcode_app) {
|
||||
furi_assert(barcode_app);
|
||||
|
||||
MessageView* message_view_object = malloc(sizeof(MessageView));
|
||||
|
||||
message_view_object->view = view_alloc();
|
||||
message_view_object->barcode_app = barcode_app;
|
||||
|
||||
view_set_context(message_view_object->view, message_view_object);
|
||||
view_allocate_model(message_view_object->view, ViewModelTypeLocking, sizeof(MessageViewModel));
|
||||
view_set_draw_callback(message_view_object->view, app_draw_callback);
|
||||
view_set_input_callback(message_view_object->view, app_input_callback);
|
||||
|
||||
return message_view_object;
|
||||
}
|
||||
|
||||
void message_view_free(MessageView* message_view_object) {
|
||||
furi_assert(message_view_object);
|
||||
|
||||
view_free(message_view_object->view);
|
||||
free(message_view_object);
|
||||
}
|
||||
|
||||
View* message_get_view(MessageView* message_view_object) {
|
||||
furi_assert(message_view_object);
|
||||
return message_view_object->view;
|
||||
}
|
||||
22
applications/external/barcode_gen/views/message_view.h
vendored
Normal file
22
applications/external/barcode_gen/views/message_view.h
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/view.h>
|
||||
|
||||
typedef struct BarcodeApp BarcodeApp;
|
||||
|
||||
typedef struct {
|
||||
View* view;
|
||||
BarcodeApp* barcode_app;
|
||||
} MessageView;
|
||||
|
||||
typedef struct {
|
||||
const char* message;
|
||||
} MessageViewModel;
|
||||
|
||||
MessageView* message_view_allocate(BarcodeApp* barcode_app);
|
||||
|
||||
void message_view_free_model(MessageView* message_view_object);
|
||||
|
||||
void message_view_free(MessageView* message_view_object);
|
||||
|
||||
View* message_get_view(MessageView* message_view_object);
|
||||
Reference in New Issue
Block a user