LiquidMenu.h
Go to the documentation of this file.
/*
The MIT License (MIT)
Copyright (c) 2016 Vasil Kalchev
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
#include <stdint.h>
#if defined(__AVR__)
# include <avr/pgmspace.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include "LiquidMenu_config.h"
#include "LiquidMenu_debug.h"
#if LIQUIDMENU_LIBRARY == LiquidCrystal_LIBRARY
# pragma message ("LiquidMenu: Selected 'LiquidCrystal' (parallel) library. Edit 'LiquidMenu_config.h' file to change it.")
#elif LIQUIDMENU_LIBRARY == LiquidCrystal_I2C_LIBRARY
# pragma message ("LiquidMenu: Selected 'LiquidCrystal_I2C' (I2C) library. Edit 'LiquidMenu_config.h' file to change it.")
#else
# pragma message ("LiquidMenu: Selected custom library. Edit 'LiquidMenu_config.h' file to change it.")
#endif
#if LIQUIDMENU_DEBUG
# warning "LiquidMenu: Debugging messages are enabled."
#endif
typedef bool (*boolFnPtr)();
typedef int8_t (*int8tFnPtr)();
typedef uint8_t (*uint8tFnPtr)();
typedef int16_t (*int16tFnPtr)();
typedef uint16_t (*uint16tFnPtr)();
typedef int32_t (*int32tFnPtr)();
typedef uint32_t (*uint32tFnPtr)();
typedef float (*floatFnPtr)();
typedef double (*doubleFnPtr)();
typedef char (*charFnPtr)();
typedef char * (*charPtrFnPtr)();
typedef const char * (*constcharPtrFnPtr)();
const char LIQUIDMENU_VERSION[] = "1.5";
enum class DataType : uint8_t {
NOT_USED = 0,
BOOL = 1, BOOLEAN = 1,
INT8_T = 8,
UINT8_T = 9,
INT16_T = 16,
UINT16_T = 17,
INT32_T = 32,
UINT32_T = 33,
FLOAT = 50, DOUBLE = 50,
CHAR = 60,
CHAR_PTR = 61,
CONST_CHAR_PTR = 62,
PROG_CONST_CHAR_PTR = 65,
GLYPH = 70,
BOOL_GETTER = 201, BOOLEAN_GETTER = 201,
INT8_T_GETTER = 208,
UINT8_T_GETTER = 209, BYTE_GETTER = 209,
INT16_T_GETTER = 216,
UINT16_T_GETTER = 217,
INT32_T_GETTER = 232,
UINT32_T_GETTER = 233,
FLOAT_GETTER = 240, DOUBLE_GETTER = 240,
CHAR_GETTER = 250,
CHAR_PTR_GETTER = 251,
CONST_CHAR_PTR_GETTER = 252
};
/*
Used to store and set the relative or absolute position of the focus indicator.
*/
enum class Position : uint8_t {
RIGHT = 1, NORMAL = 1,
LEFT = 2,
CUSTOM = 3,
};
DataType recognizeType(bool variable);
DataType recognizeType(char variable);
DataType recognizeType(char* variable);
DataType recognizeType(const char* variable);
DataType recognizeType(int8_t variable);
DataType recognizeType(uint8_t variable);
DataType recognizeType(int16_t variable);
DataType recognizeType(uint16_t variable);
DataType recognizeType(int32_t variable);
DataType recognizeType(uint32_t variable);
DataType recognizeType(float variable);
DataType recognizeType(double variable);
DataType recognizeType(boolFnPtr variable);
DataType recognizeType(int8tFnPtr variable);
DataType recognizeType(uint8tFnPtr variable);
DataType recognizeType(int16tFnPtr variable);
DataType recognizeType(uint16tFnPtr variable);
DataType recognizeType(int32tFnPtr variable);
DataType recognizeType(uint32tFnPtr varible);
DataType recognizeType(floatFnPtr variable);
DataType recognizeType(doubleFnPtr variable);
DataType recognizeType(charFnPtr variable);
DataType recognizeType(charPtrFnPtr variable);
DataType recognizeType(constcharPtrFnPtr variable);
void print_me(uintptr_t address);
class LiquidLine {
friend class LiquidScreen;
public:
LiquidLine(uint8_t column, uint8_t row)
: _row(row), _column(column), _focusRow(row - 1),
_focusColumn(column - 1), _focusPosition(Position::NORMAL),
_variableCount(0), _focusable(false) {
for (uint8_t i = 0; i < MAX_VARIABLES; i++) {
_variable[i] = nullptr;
_variableType[i] = DataType::NOT_USED;
}
for (uint8_t f = 0; f < MAX_FUNCTIONS; f++) {
_function[f] = 0;
}
_floatDecimalPlaces = 2;
}
template <typename A>
LiquidLine(uint8_t column, uint8_t row, A &variableA)
: LiquidLine(column, row) {
add_variable(variableA);
}
template <typename A, typename B>
LiquidLine(uint8_t column, uint8_t row,
A &variableA, B &variableB)
: LiquidLine(column, row, variableA) {
add_variable(variableB);
}
template <typename A, typename B, typename C>
LiquidLine(uint8_t column, uint8_t row,
A &variableA, B &variableB, C &variableC)
: LiquidLine(column, row, variableA, variableB) {
add_variable(variableC);
}
template <typename A, typename B, typename C, typename D>
LiquidLine(uint8_t column, uint8_t row,
A &variableA, B &variableB, C &variableC, D &variableD)
: LiquidLine(column, row, variableA, variableB, variableC) {
add_variable(variableD);
}
template <typename T>
bool add_variable(T &variable) {
print_me(reinterpret_cast<uintptr_t>(this));
if (_variableCount < MAX_VARIABLES) {
_variable[_variableCount] = (void*)&variable;
_variableType[_variableCount] = recognizeType(variable);
# if LIQUIDMENU_DEBUG
DEBUG(F("Added variable "));
// Check if the variable is actually a getter functions
// and don't diplay it if so.
if ((uint8_t)_variableType[_variableCount] < 200) { // 200+ are getters
DEBUG(reinterpret_cast<uintptr_t>(variable)); DEBUGLN(F(""));
}
# endif
_variableCount++;
return true;
}
# if LIQUIDMENU_DEBUG
DEBUG(F("Adding variable "));
// Check if the variable is actually a getter functions
// and don't diplay it if so.
if ((uint8_t)_variableType[_variableCount] < 200) { // 200+ are getters
DEBUG(reinterpret_cast<uintptr_t>(variable));
}
# endif
DEBUGLN(F(" failed, edit LiquidMenu_config.h to allow for more variables"));
return false;
}
bool attach_function(uint8_t number, void (*function)(void));
void set_decimalPlaces(uint8_t decimalPlaces);
bool set_focusPosition(Position position,
uint8_t column = 0, uint8_t row = 0);
bool set_asGlyph(uint8_t number);
bool set_asProgmem(uint8_t number);
private:
void print(DisplayClass *p_liquidCrystal, bool isFocused);
void print_variable(DisplayClass *p_liquidCrystal, uint8_t number);
bool is_callable(uint8_t number) const;
bool call_function(uint8_t number) const;
uint8_t _row, _column, _focusRow, _focusColumn;
Position _focusPosition;
uint8_t _floatDecimalPlaces;
uint8_t _variableCount;
void (*_function[MAX_FUNCTIONS])(void);
const void *_variable[MAX_VARIABLES];
DataType _variableType[MAX_VARIABLES];
bool _focusable;
};
class LiquidScreen {
friend class LiquidMenu;
public:
LiquidScreen();
explicit LiquidScreen(LiquidLine &liquidLine);
LiquidScreen(LiquidLine &liquidLine1, LiquidLine &liquidLine2);
LiquidScreen(LiquidLine &liquidLine1, LiquidLine &liquidLine2,
LiquidLine &liquidLine3);
LiquidScreen(LiquidLine &liquidLine1, LiquidLine &liquidLine2,
LiquidLine &liquidLine3, LiquidLine &liquidLine4);
bool add_line(LiquidLine &liquidLine);
bool set_focusPosition(Position position);
void set_displayLineCount(uint8_t lineCount);
void hide(bool hide);
private:
void print(DisplayClass *p_liquidCrystal) const;
void switch_focus(bool forward = true);
bool set_focusedLine(uint8_t lineIndex);
uint8_t get_focusedLine() const;
bool is_callable(uint8_t number) const;
bool call_function(uint8_t number) const;
LiquidLine *_p_liquidLine[MAX_LINES];
uint8_t _lineCount;
uint8_t _focus;
uint8_t _displayLineCount;
bool _hidden;
};
class LiquidMenu {
friend class LiquidSystem;
public:
LiquidMenu(DisplayClass &liquidCrystal, uint8_t startingScreen = 1);
LiquidMenu(DisplayClass &liquidCrystal, LiquidScreen &liquidScreen,
uint8_t startingScreen = 1);
LiquidMenu(DisplayClass &liquidCrystal, LiquidScreen &liquidScreen1,
LiquidScreen &liquidScreen2, uint8_t startingScreen = 1);
LiquidMenu(DisplayClass &liquidCrystal, LiquidScreen &liquidScreen1,
LiquidScreen &liquidScreen2, LiquidScreen &liquidScreen3,
uint8_t startingScreen = 1);
LiquidMenu(DisplayClass &liquidCrystal, LiquidScreen &liquidScreen1,
LiquidScreen &liquidScreen2, LiquidScreen &liquidScreen3,
LiquidScreen &liquidScreen4, uint8_t startingScreen = 1);
bool add_screen(LiquidScreen &liquidScreen);
LiquidScreen* get_currentScreen() const;
void next_screen();
void operator++();
void operator++(int);
void previous_screen();
void operator--();
void operator--(int);
bool change_screen(LiquidScreen *p_liquidScreen);
bool change_screen(uint8_t number);
bool operator=(LiquidScreen *p_liquidScreen);
bool operator=(uint8_t number);
void switch_focus(bool forward = true);
bool set_focusedLine(uint8_t lineIndex);
uint8_t get_focusedLine() const;
bool set_focusPosition(Position position);
bool set_focusSymbol(Position position, uint8_t symbol[8]);
bool is_callable(uint8_t number) const;
bool call_function(uint8_t number) const;
void update() const;
void softUpdate() const;
void init() const;
private:
DisplayClass *_p_liquidCrystal;
LiquidScreen *_p_liquidScreen[MAX_SCREENS];
uint8_t _screenCount;
uint8_t _currentScreen;
};
class LiquidSystem {
public:
explicit LiquidSystem(uint8_t startingMenu = 1);
LiquidSystem(LiquidMenu &liquidMenu1, LiquidMenu &liquidMenu2,
uint8_t startingMenu = 1);
LiquidSystem(LiquidMenu &liquidMenu1, LiquidMenu &liquidMenu2,
LiquidMenu &liquidMenu3, uint8_t startingMenu = 1);
LiquidSystem(LiquidMenu &liquidMenu1, LiquidMenu &liquidMenu2,
LiquidMenu &liquidMenu3, LiquidMenu &liquidMenu4,
uint8_t startingMenu = 1);
bool add_menu(LiquidMenu &liquidMenu);
bool change_menu(LiquidMenu &p_liquidMenu);
LiquidScreen* get_currentScreen() const;
void next_screen();
void operator++();
void operator++(int);
void previous_screen();
void operator--();
void operator--(int);
bool change_screen(LiquidScreen *p_liquidScreen);
bool change_screen(uint8_t number);
bool operator=(LiquidScreen *p_liquidScreen);
bool operator=(uint8_t number);
void switch_focus(bool forward = true);
bool set_focusedLine(uint8_t lineIndex);
uint8_t get_focusedLine() const;
bool set_focusPosition(Position position);
bool set_focusSymbol(Position position, uint8_t symbol[8]);
bool is_callable(uint8_t number) const;
bool call_function(uint8_t number) const;
void update() const;
void softUpdate() const;
private:
LiquidMenu *_p_liquidMenu[MAX_MENUS];
uint8_t _menuCount;
uint8_t _currentMenu;
};
LiquidLine::LiquidLine
LiquidLine(uint8_t column, uint8_t row, A &variableA, B &variableB, C &variableC)
Constructor for three variables/constants.
Definition: LiquidMenu.h:368
LiquidSystem::operator--
void operator--()
Switches to the previous screen.
Definition: LiquidSystem.cpp:109
LiquidSystem::is_callable
bool is_callable(uint8_t number) const
Check if there is an attached function at the specified number.
Definition: LiquidSystem.cpp:153
LiquidSystem::LiquidSystem
LiquidSystem(uint8_t startingMenu=1)
The main constructor.
Definition: LiquidSystem.cpp:32
LiquidSystem
Represents a collection of menus forming a menu system.
Definition: LiquidMenu.h:1034
LiquidSystem::change_screen
bool change_screen(LiquidScreen *p_liquidScreen)
Switches to the specified screen.
Definition: LiquidSystem.cpp:121
LiquidSystem::get_focusedLine
uint8_t get_focusedLine() const
Get the index of the currently focused line.
Definition: LiquidSystem.cpp:141
LiquidLine
Represents the individual lines printed on the display.
Definition: LiquidMenu.h:305
LiquidSystem::update
void update() const
Prints the current screen to the display.
Definition: LiquidSystem.cpp:164
LiquidSystem::set_focusedLine
bool set_focusedLine(uint8_t lineIndex)
Directly select focused line.
Definition: LiquidSystem.cpp:137
LiquidSystem::softUpdate
void softUpdate() const
Prints the current screen to the display (without clearing).
Definition: LiquidSystem.cpp:168
LiquidLine::set_asGlyph
bool set_asGlyph(uint8_t number)
Converts a byte variable into a glyph index.
Definition: LiquidLine.cpp:77
LiquidLine::set_asProgmem
bool set_asProgmem(uint8_t number)
Converts a const char pointer variable into const char pointer PROGMEM one.
Definition: LiquidLine.cpp:89
LiquidSystem::switch_focus
void switch_focus(bool forward=true)
Switches the focus.
Definition: LiquidSystem.cpp:133
LiquidLine::add_variable
bool add_variable(T &variable)
Adds a variable to the line.
Definition: LiquidMenu.h:409
LiquidScreen::set_displayLineCount
void set_displayLineCount(uint8_t lineCount)
Specifies the line size of the display (required for scrolling).
Definition: LiquidScreen.cpp:91
LiquidSystem::previous_screen
void previous_screen()
Switches to the previous screen.
Definition: LiquidSystem.cpp:105
LiquidSystem::set_focusPosition
bool set_focusPosition(Position position)
Sets the focus position for the whole menu at once.
Definition: LiquidSystem.cpp:145
LiquidLine::LiquidLine
LiquidLine(uint8_t column, uint8_t row, A &variableA, B &variableB)
Constructor for two variables/constants.
Definition: LiquidMenu.h:353
LiquidScreen
Represents a screen shown on the display.
Definition: LiquidMenu.h:573
LiquidSystem::set_focusSymbol
bool set_focusSymbol(Position position, uint8_t symbol[8])
Changes the focus indicator&#39;s symbol.
Definition: LiquidSystem.cpp:149
LiquidSystem::call_function
bool call_function(uint8_t number) const
Calls an attached function specified by the number.
Definition: LiquidSystem.cpp:157
LiquidSystem::operator=
bool operator=(LiquidScreen *p_liquidScreen)
Switches to the specified screen.
Definition: LiquidSystem.cpp:129
LiquidSystem::add_menu
bool add_menu(LiquidMenu &liquidMenu)
Adds a LiquidMenu object to the menu system.
Definition: LiquidSystem.cpp:58
LiquidScreen::add_line
bool add_line(LiquidLine &liquidLine)
Adds a LiquidLine object to the screen.
Definition: LiquidScreen.cpp:57
LiquidLine::LiquidLine
LiquidLine(uint8_t column, uint8_t row)
The main constructor.
Definition: LiquidMenu.h:319
LiquidScreen::hide
void hide(bool hide)
Hides the screen.
Definition: LiquidScreen.cpp:95
LiquidSystem::change_menu
bool change_menu(LiquidMenu &p_liquidMenu)
Switches to the specified menu.
Definition: LiquidSystem.cpp:73
LiquidScreen::LiquidScreen
LiquidScreen()
The main constructor.
Definition: LiquidScreen.cpp:32
LiquidLine::LiquidLine
LiquidLine(uint8_t column, uint8_t row, A &variableA, B &variableB, C &variableC, D &variableD)
Constructor for four variables/constants.
Definition: LiquidMenu.h:384
LiquidLine::attach_function
bool attach_function(uint8_t number, void(*function)(void))
Attaches a callback function to the line.
Definition: LiquidLine.cpp:39
LiquidLine::set_focusPosition
bool set_focusPosition(Position position, uint8_t column=0, uint8_t row=0)
Configures the focus indicator position for the line.
Definition: LiquidLine.cpp:58
LiquidLine::set_decimalPlaces
void set_decimalPlaces(uint8_t decimalPlaces)
Sets the decimal places for floating point variables.
Definition: LiquidLine.cpp:53
LiquidSystem::next_screen
void next_screen()
Switches to the next screen.
Definition: LiquidSystem.cpp:93
LiquidSystem::get_currentScreen
LiquidScreen * get_currentScreen() const
Returns a reference to the current screen.
Definition: LiquidSystem.cpp:89
LiquidLine::LiquidLine
LiquidLine(uint8_t column, uint8_t row, A &variableA)
Constructor for one variable/constant.
Definition: LiquidMenu.h:340
LiquidSystem::operator++
void operator++()
Switches to the next screen.
Definition: LiquidSystem.cpp:97
LiquidScreen::set_focusPosition
bool set_focusPosition(Position position)
Sets the focus position for the whole screen at once.
Definition: LiquidScreen.cpp:77