You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Ender3V2S1/Marlin/src/lcd/e3v2/proui/menus.h

234 lines
8.8 KiB
C++

/**
* Menu functions for ProUI
* Author: Miguel A. Risco-Castillo
* Version: 3.2.1
* Date: 2023/09/30
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#include "dwinui.h"
#define MENU_CHAR_LIMIT 24
#ifndef MENU_MAX_ITEMS
#define MENU_MAX_ITEMS 64
#endif
// Create and draw menu
#define SET_MENU(I,L) setMenu(I, GET_TEXT_F(L))
#define SET_MENU_F(I,L) setMenu(I, F(L))
// Create and add a MenuItem object to the menu array
#define BACK_ITEM(OC) menuItemAdd(ICON_Back, GET_TEXT_F(MSG_BUTTON_BACK), onDrawMenuItem, OC, nullptr)
#define MENU_ITEM(I,L,OD,OC) menuItemAdd(I, GET_TEXT_F(L), OD, OC, nullptr)
#define EDIT_ITEM(I,L,OD,OC,V) menuItemAdd(I, GET_TEXT_F(L), OD, OC, V)
#define MENU_ITEM_F(I,L,OD,OC) menuItemAdd(I, F(L), OD, OC, nullptr)
#define EDIT_ITEM_F(I,L,OD,OC,V) menuItemAdd(I, F(L), OD, OC, V)
typedef struct {
int32_t maxValue = 0; // Auxiliar max integer/scaled float value
int32_t minValue = 0; // Auxiliar min integer/scaled float value
int8_t dp = 0; // Auxiliar decimal places
int32_t value = 0; // Auxiliar integer / scaled float value
int16_t *intPtr = nullptr; // Auxiliar pointer to 16 bit integer variable
float *floatPtr = nullptr; // Auxiliar pointer to float variable
void (*apply)() = nullptr; // Auxiliar apply function
void (*liveUpdate)() = nullptr; // Auxiliar live update function
} MenuData_t;
extern MenuData_t menuData;
typedef void (*OnDrawItem)(int8_t pos, int8_t line);
typedef void (*OnClickItem)();
struct MenuItem_t {
uint8_t icon = 0;
FSTR_P caption = nullptr;
OnDrawItem onDraw = nullptr;
OnClickItem onClick = nullptr;
void* value;
};
extern int8_t menuItemCount;
constexpr uint8_t menu_max_items = MENU_MAX_ITEMS;
class Menu {
public:
int8_t topline = 0;
int8_t selected = 0;
char caption[32];
Menu();
virtual ~Menu(){};
inline int8_t line() { return selected - topline; };
inline int8_t line(int8_t pos) {return pos - topline; };
virtual void draw();
virtual void onScroll(bool dir);
virtual void setCaption(const char * const titleStr);
inline void setCaption(FSTR_P fTitle) { setCaption((char *)fTitle); }
void onClick();
uint8_t count;
MenuItem_t selectedItem();
};
extern Menu *currentMenu;
extern Menu *previousMenu;
// Menuitem Drawing functions =================================================
void drawMenuCursor(const int8_t line);
void eraseMenuCursor(const int8_t line);
void eraseMenuText(const int8_t line);
void drawMenuItem(const int8_t line, const uint8_t icon=0, const char * const label=nullptr, bool more=false, bool selected=false);
inline void drawMenuItem(const int8_t line, const uint8_t icon=0, FSTR_P label=nullptr, bool more=false, bool selected=false) {
drawMenuItem(line, icon, FTOP(label), more, selected);
}
void drawCheckboxLine(const int8_t line, const bool checked);
void showCheckboxLine(const bool checked);
void toggleCheckboxLine(bool &checked);
void drawMenuIntValue(uint16_t bcolor, const int8_t line, uint8_t iNum, const int32_t value=0);
void drawItem(int8_t pos, int8_t line);
void onDrawMenuItem(int8_t pos, int8_t line);
void onDrawSubMenu(int8_t pos, int8_t line);
void onDrawIntMenu(int8_t pos, int8_t line, int32_t value);
void onDrawPIntMenu(int8_t pos, int8_t line);
void onDrawPInt8Menu(int8_t pos, int8_t line);
void onDrawPInt32Menu(int8_t pos, int8_t line);
void onDrawFloatMenu(int8_t pos, int8_t line, uint8_t dp, const float value);
void onDrawPFloatMenu(int8_t pos, int8_t line, uint8_t dp);
inline void onDrawPFloatMenu(int8_t pos, int8_t line) { onDrawPFloatMenu(pos, line, UNITFDIGITS); };
inline void onDrawPFloat2Menu(int8_t pos, int8_t line) { onDrawPFloatMenu(pos, line, 2); };
inline void onDrawPFloat3Menu(int8_t pos, int8_t line) { onDrawPFloatMenu(pos, line, 3); };
inline void onDrawPFloat4Menu(int8_t pos, int8_t line) { onDrawPFloatMenu(pos, line, 4); };
void onDrawChkbMenu(int8_t pos, int8_t line);
// On click functions =========================================================
// Generic onclick event without draw
// process: process id HMI destiny
// lo: low limit
// hi: high limit
// dp: decimal places, 0 for integers
// val: value / scaled value
// liveUpdate: live update function when the encoder changes
// apply: update function when the encoder is pressed
void setOnClick(uint8_t process, const int32_t lo, const int32_t hi, uint8_t dp, const int32_t val, void (*apply)()=nullptr, void (*liveUpdate)()=nullptr);
// Generic onclick event for integer values
// process: process id HMI destiny
// lo: scaled low limit
// hi: scaled high limit
// val: value
// liveUpdate: live update function when the encoder changes
// apply: update function when the encoder is pressed
void setValueOnClick(uint8_t process, const int32_t lo, const int32_t hi, const int32_t val, void (*apply)()=nullptr, void (*liveUpdate)()=nullptr);
// Generic onclick event for float values
// process: process id HMI destiny
// lo: scaled low limit
// hi: scaled high limit
// val: value
// liveUpdate: live update function when the encoder changes
// apply: update function when the encoder is pressed
void setValueOnClick(uint8_t process, const float lo, const float hi, uint8_t dp, const float val, void (*apply)()=nullptr, void (*liveUpdate)()=nullptr);
// Generic onclick event for integer values
// lo: scaled low limit
// hi: scaled high limit
// val: value
// liveUpdate: live update function when the encoder changes
// apply: update function when the encoder is pressed
void setIntOnClick(const int32_t lo, const int32_t hi, const int32_t val, void (*apply)()=nullptr, void (*liveUpdate)()=nullptr);
// Generic onclick event for set pointer to 16 bit integer values
// lo: low limit
// hi: high limit
// liveUpdate: live update function when the encoder changes
// apply: update function when the encoder is pressed
void setPIntOnClick(const int32_t lo, const int32_t hi, void (*apply)()=nullptr, void (*liveUpdate)()=nullptr);
// Generic onclick event for float values
// process: process id HMI destiny
// lo: low limit
// hi: high limit
// dp: decimal places
// val: value
void setFloatOnClick(const float lo, const float hi, uint8_t dp, const float val, void (*apply)()=nullptr, void (*liveUpdate)()=nullptr);
// Generic onclick event for set pointer to float values
// lo: low limit
// hi: high limit
// liveUpdate: live update function when the encoder changes
// apply: update function when the encoder is pressed
void setPFloatOnClick(const float lo, const float hi, uint8_t dp, void (*apply)()=nullptr, void (*liveUpdate)()=nullptr);
// HMI user control functions =================================================
// Generic menu control using the encoder
void hmiMenu();
// Set and draw a value using the encoder
void hmiSetDraw();
// Set an value without drawing
void hmiSetNoDraw();
// Set an integer pointer variable using the encoder
void hmiSetPInt();
// Set a scaled float pointer variable using the encoder
void hmiSetPFloat();
// Menu auxiliary functions ===================================================
// Initialize menu
void initMenu();
// Create a new menu (pass menu pointer as reference)
bool setMenu(Menu* &menu, FSTR_P fTitle);
inline bool setMenu(Menu* &menu) { return setMenu(menu, nullptr); };
// Reset top line and selected item
void resetMenu(Menu* &menu);
// Invalidate currentMenu to prepare for full menu drawing
void invalidateMenu();
//Redraw the current Menu if it is valid
void redrawMenu(bool force = false);
//Redraw menu item at pos in the array
void redrawItem(uint8_t pos, bool erase=false);
//Redraw selected menu item
void redrawItem();
// Clear menuItems array and free menuItems elements
void menuItemsClear();
// Is not the current menu
bool notCurrentMenu(Menu* menu);
// Is the screen a menu and that menu argument is current?
inline bool isMenu(Menu* menu) {
return ((checkkey == ID_Menu) && !!currentMenu && currentMenu == menu);
}
// Add elements to the menuItems array
int8_t menuItemAdd(uint8_t cicon, FSTR_P text=nullptr, OnDrawItem ondraw=nullptr, OnClickItem onclick=nullptr, void* value=nullptr);
inline int8_t menuItemAdd(OnDrawItem ondraw=nullptr, OnClickItem onclick=nullptr) { return menuItemAdd(0, nullptr, ondraw, onclick); };
// Get an element from the menuItems array
MenuItem_t * getMenuItem(const int8_t pos);