diff --git a/lib/applications/src/launcher.cpp b/lib/applications/src/launcher.cpp index 6ba24100..3b7015d4 100644 --- a/lib/applications/src/launcher.cpp +++ b/lib/applications/src/launcher.cpp @@ -9,6 +9,7 @@ #include #include #include +#include /** @@ -139,6 +140,9 @@ void applications::launcher::update() { launcherWindow->updateAll(); } + // Update all events + eventHandlerApp.update(); + // Check touch events if (brightnessSliderBox->isFocused(true)) { diff --git a/lib/gui/src/elements/List.cpp b/lib/gui/src/elements/List.cpp index 767c6e3b..e22bb2de 100644 --- a/lib/gui/src/elements/List.cpp +++ b/lib/gui/src/elements/List.cpp @@ -13,6 +13,7 @@ namespace gui::elements m_lineSpace = 25; m_verticalScrollEnabled = true; m_hasEvents = true; + m_selectionFocus == SelectionFocus::UP; } VerticalList::~VerticalList() = default; @@ -22,6 +23,14 @@ namespace gui::elements m_surface->fillRect(0, 0, m_width, m_height, COLOR_WHITE); } + void VerticalList::postRender() + { + if(m_selectionFocus == SelectionFocus::CENTER && m_children.size()) + { + m_surface->fillRect(0, getHeight()/2 - m_children[m_focusedIndex]->getHeight()/2, 1, m_children[m_focusedIndex]->getHeight(), COLOR_BLACK); + } + } + void VerticalList::add(ElementBase* widget) { m_verticalScrollEnabled = true; @@ -46,6 +55,7 @@ namespace gui::elements void VerticalList::updateFocusedIndex() { eventHandlerApp.setTimeout(new Callback<>([&](){ + std::cout << "updateFocusedIndex" << std::endl; if(m_children.size() == 0) { m_focusedIndex = 0; @@ -53,7 +63,11 @@ namespace gui::elements } m_verticalScroll = m_children[m_focusedIndex]->m_y; + if(m_selectionFocus == SelectionFocus::CENTER) + m_verticalScroll = m_verticalScroll - getHeight() / 2 + m_children[m_focusedIndex]->getHeight() / 2; + localGraphicalUpdate(); + std::cout << "updateFocusedIndex end: " << m_selectionFocus << std::endl; // for (int i = 0; i < m_children.size(); i++) // { @@ -82,6 +96,17 @@ namespace gui::elements updateFocusedIndex(); } } + + void VerticalList::setSelectionFocus(SelectionFocus focus) + { + m_selectionFocus = focus; + updateFocusedIndex(); + } + + int VerticalList::getFocusedElement() + { + return m_focusedIndex; + } HorizontalList::HorizontalList(uint16_t x, uint16_t y, uint16_t width, uint16_t height) diff --git a/lib/gui/src/elements/List.hpp b/lib/gui/src/elements/List.hpp index 69021214..664e3ccc 100644 --- a/lib/gui/src/elements/List.hpp +++ b/lib/gui/src/elements/List.hpp @@ -12,6 +12,7 @@ namespace gui::elements ~VerticalList() override; void render() override; + void postRender(); void add(ElementBase* widget); void setIndex(int index); @@ -22,9 +23,19 @@ namespace gui::elements void onScrollUp(); void onScrollDown(); + enum SelectionFocus + { + UP, + CENTER + }; + + void setSelectionFocus(SelectionFocus focus); + int getFocusedElement(); + private: int16_t m_focusedIndex = 0; uint16_t m_lineSpace = 0; + SelectionFocus m_selectionFocus = SelectionFocus::UP; }; class HorizontalList final : public ElementBase diff --git a/lib/lua/src/lua_canvas.cpp b/lib/lua/src/lua_canvas.cpp index 2bf1e7b9..c446da93 100644 --- a/lib/lua/src/lua_canvas.cpp +++ b/lib/lua/src/lua_canvas.cpp @@ -14,8 +14,8 @@ sol::table LuaCanvas::getTouch() int16_t x = gui::ElementBase::touchX, y = gui::ElementBase::touchY; sol::table result = lua->lua.create_table(); - result.set(1, x); - result.set(2, y); + result.set(1, x - widget->getAbsoluteX()); + result.set(2, y - widget->getAbsoluteY()); return result; } diff --git a/lib/lua/src/lua_file.cpp b/lib/lua/src/lua_file.cpp index c8d6799d..60fb065d 100755 --- a/lib/lua/src/lua_file.cpp +++ b/lib/lua/src/lua_file.cpp @@ -11,6 +11,9 @@ #include #include +#include +#include + /* LuaHttpClient::LuaHttpClient(LuaFile* lua) @@ -112,6 +115,150 @@ int custom_panic_handler(lua_State* L) { return 0; } +template +void writeBinaryValue(std::ofstream& file, const T& value) { + file.write(reinterpret_cast(&value), sizeof(T)); +} + +void saveTableToBinaryFile(std::ofstream& file, const sol::table& table) { + // Write the number of key-value pairs + size_t numPairs = table.size(); + writeBinaryValue(file, numPairs); + + for (const auto& pair : table) { + sol::object key = pair.first; + sol::object value = pair.second; + + // Write the key type + if (key.is()) { + writeBinaryValue(file, static_cast(1)); // 1 for string key + std::string keyStr = key.as(); + size_t keySize = keyStr.size(); + writeBinaryValue(file, keySize); + file.write(keyStr.c_str(), keySize); + } else if (key.is() || key.is()) { + writeBinaryValue(file, static_cast(2)); // 2 for numeric key + double numericKey = key.as(); + writeBinaryValue(file, numericKey); + } else { + throw std::runtime_error("Unsupported table key type for binary serialization"); + } + + // Write the value type and value + if (value.is()) { + writeBinaryValue(file, static_cast(1)); // 1 for string + std::string valueStr = value.as(); + size_t valueSize = valueStr.size(); + writeBinaryValue(file, valueSize); + file.write(valueStr.c_str(), valueSize); + } else if (value.is() || value.is()) { + writeBinaryValue(file, static_cast(2)); // 2 for number + double numericValue = value.as(); + writeBinaryValue(file, numericValue); + } else if (value.is()) { + writeBinaryValue(file, static_cast(3)); // 3 for boolean + bool boolValue = value.as(); + writeBinaryValue(file, boolValue); + } else if (value.is()) { + writeBinaryValue(file, static_cast(4)); // 4 for nil + } else if (value.is()) { + writeBinaryValue(file, static_cast(5)); // 5 for table + saveTableToBinaryFile(file, value.as()); // Recursively save + } else { + throw std::runtime_error("Unsupported table value type for binary serialization"); + } + } +} + +void saveTableToBinaryFile(const std::string& filename, const sol::table& table) { + std::ofstream file(filename, std::ios::binary); + if (!file.is_open()) { + throw std::runtime_error("Error opening file for writing: " + filename); + } + + try { + saveTableToBinaryFile(file, table); + } catch (const std::exception& e) { + file.close(); + throw std::runtime_error(std::string("Error while writing to file: ") + e.what()); + } + + file.close(); +} + +template +T readBinaryValue(std::ifstream& file) { + T value; + file.read(reinterpret_cast(&value), sizeof(T)); + return value; +} + +sol::table loadTableFromBinaryFile(sol::state& lua, std::ifstream& file) { + sol::table table = lua.create_table(); + + size_t numPairs = readBinaryValue(file); + + for (size_t i = 0; i < numPairs; ++i) { + // Read key + uint8_t keyType = readBinaryValue(file); + sol::object key; + + if (keyType == 1) { // String key + size_t keySize = readBinaryValue(file); + std::vector keyBuffer(keySize); + file.read(keyBuffer.data(), keySize); + key = sol::make_object(lua, std::string(keyBuffer.data(), keySize)); + } else if (keyType == 2) { // Numeric key + key = sol::make_object(lua, readBinaryValue(file)); + } else { + throw std::runtime_error("Unsupported key type in binary file"); + } + + // Read value + uint8_t valueType = readBinaryValue(file); + + switch (valueType) { + case 1: { // String + size_t valueSize = readBinaryValue(file); + std::vector valueBuffer(valueSize); + file.read(valueBuffer.data(), valueSize); + table[key] = std::string(valueBuffer.data(), valueSize); + break; + } + case 2: // Number + table[key] = readBinaryValue(file); + break; + case 3: // Boolean + table[key] = readBinaryValue(file); + break; + case 4: // Nil + table[key] = sol::nil; + break; + case 5: // Nested table + table[key] = loadTableFromBinaryFile(lua, file); + break; + default: + throw std::runtime_error("Unsupported value type in binary file"); + } + } + + return table; +} + +sol::table loadTableFromBinaryFile(sol::state& lua, const std::string& filename) { + std::ifstream file(filename, std::ios::binary); + if (!file.is_open()) { + throw std::runtime_error("Error opening file for reading: " + filename); + } + + try { + return loadTableFromBinaryFile(lua, file); + } catch (const std::exception& e) { + file.close(); + throw std::runtime_error(std::string("Error while reading from file: ") + e.what()); + } +} + void LuaFile::load() { StandbyMode::triggerPower(); @@ -155,6 +302,30 @@ void LuaFile::load() lua.set_function("nonothing", []() { }); + lua["require"] = [&](const std::string& filename) -> sol::object { + storage::Path lib(filename); + + // Load the file + sol::load_result chunk = lua.load_file(this->lua_storage.convertPath(lib).str()); + if (!chunk.valid()) { + sol::error err = chunk; + throw std::runtime_error("Error loading module '" + filename + "': " + err.what()); + } + + // 4. Execute the loaded chunk and return its results + return chunk(); + }; + + lua["saveTable"] = [&](const std::string& filename, const sol::table& table) + { + saveTableToBinaryFile(lua_storage.convertPath(filename).str(), table); + }; + + lua["loadTable"] = [&](const std::string& filename) + { + return loadTableFromBinaryFile(lua, lua_storage.convertPath(filename).str()); + }; + if (perms.acces_hardware) // si hardware est autorisé { lua.new_usertype("hardware", @@ -351,6 +522,8 @@ void LuaFile::load() lua.new_usertype("LuaVList", "setIndex", &LuaVerticalList::setIndex, "setSpaceLine", &LuaVerticalList::setSpaceLine, + "setSelectionFocus", &LuaVerticalList::setFocus, + "getSelected", &LuaVerticalList::getSelected, sol::base_classes, sol::bases()); lua.new_usertype("LuaHList", diff --git a/lib/lua/src/lua_list.hpp b/lib/lua/src/lua_list.hpp index 115a6a1e..a0f888df 100644 --- a/lib/lua/src/lua_list.hpp +++ b/lib/lua/src/lua_list.hpp @@ -11,6 +11,8 @@ class LuaVerticalList : public LuaWidget void addChild(LuaWidget* widget){ this->children.push_back(widget); widget->parent = this; this->widget->add(widget->widget); } void setSpaceLine(int line){ this->widget->setSpaceLine(line); } void setIndex(int i = 0) { this->widget->setIndex(i); }; + void setFocus(VerticalList::SelectionFocus focus) { std::cout << "setFocus: " << focus << std::endl; this->widget->setSelectionFocus(focus); }; + int getSelected() { return this->widget->getFocusedElement(); }; VerticalList* widget = nullptr; };