diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/bindey/.clang-format | 72 | ||||
| -rw-r--r-- | lib/bindey/.github/workflows/ci.yml | 44 | ||||
| -rw-r--r-- | lib/bindey/.gitignore | 5 | ||||
| -rw-r--r-- | lib/bindey/.gitmodules | 6 | ||||
| -rw-r--r-- | lib/bindey/CMakeLists.txt | 6 | ||||
| -rw-r--r-- | lib/bindey/LICENSE.md | 21 | ||||
| -rw-r--r-- | lib/bindey/README.md | 116 | ||||
| -rw-r--r-- | lib/bindey/include/bindey/binding.h | 47 | ||||
| -rw-r--r-- | lib/bindey/include/bindey/property.h | 137 | ||||
| -rw-r--r-- | lib/bindey/include/nod/nod.hpp | 681 | ||||
| -rw-r--r-- | lib/luavgl/src/lvgl.lua | 495 | ||||
| -rw-r--r-- | lib/luavgl/src/widgets/slider.c | 88 | ||||
| -rw-r--r-- | lib/luavgl/src/widgets/switch.c | 57 | ||||
| -rw-r--r-- | lib/luavgl/src/widgets/widgets.c | 24 |
14 files changed, 447 insertions, 1352 deletions
diff --git a/lib/bindey/.clang-format b/lib/bindey/.clang-format deleted file mode 100644 index c3b36785..00000000 --- a/lib/bindey/.clang-format +++ /dev/null @@ -1,72 +0,0 @@ -AccessModifierOffset: -4 -AlignAfterOpenBracket: Align -AlignConsecutiveAssignments: true -AlignConsecutiveDeclarations: true -AlignEscapedNewlinesLeft: true -AlignOperands: true -AlignTrailingComments: true -AllowAllParametersOfDeclarationOnNextLine: true -AllowShortBlocksOnASingleLine: false -AllowShortFunctionsOnASingleLine: None -AllowShortIfStatementsOnASingleLine: false -AllowShortLoopsOnASingleLine: false -AlwaysBreakBeforeMultilineStrings: false -AlwaysBreakTemplateDeclarations: true -BinPackArguments: false -BinPackParameters: false -BraceWrapping: - AfterClass: true - AfterControlStatement: true - AfterEnum: true - AfterFunction: true - AfterNamespace: true - AfterObjCDeclaration: true - AfterStruct: true - AfterUnion: true - BeforeCatch: true - BeforeElse: true - IndentBraces: false -BreakBeforeBinaryOperators: NonAssignment -BreakBeforeBraces: Custom -BreakBeforeTernaryOperators: true -BreakConstructorInitializersBeforeComma: true -ColumnLimit: 120 -CommentPragmas: '^!' -ConstructorInitializerAllOnOneLineOrOnePerLine: false -ConstructorInitializerIndentWidth: 0 -ContinuationIndentWidth: 4 -Cpp11BracedListStyle: true -DerivePointerAlignment: false -DisableFormat: false -ExperimentalAutoDetectBinPacking: false -ForEachMacros: [ foreach, BOOST_FOREACH ] -IndentCaseLabels: true -IndentFunctionDeclarationAfterType: false -IndentWidth: 4 -IndentWrappedFunctionNames: false -KeepEmptyLinesAtTheStartOfBlocks: true -Language: Cpp -MaxEmptyLinesToKeep: 2 -NamespaceIndentation: None -ObjCSpaceAfterProperty: false -ObjCSpaceBeforeProtocolList: true -PenaltyBreakBeforeFirstCallParameter: 19 -PenaltyBreakComment: 300 -PenaltyBreakFirstLessLess: 120 -PenaltyBreakString: 1000 -PenaltyExcessCharacter: 100 -PenaltyReturnTypeOnItsOwnLine: 600 -PointerAlignment: Left -SpaceAfterCStyleCast: true -SpaceBeforeAssignmentOperators: true -SpaceBeforeParens: ControlStatements -SpaceInEmptyParentheses: false -SpacesBeforeTrailingComments: 1 -SpacesInAngles: false -SpacesInContainerLiterals: true -SpacesInCStyleCastParentheses: false -SpacesInParentheses: true -SpacesInSquareBrackets: false -Standard: Cpp11 -TabWidth: 4 -UseTab: Never diff --git a/lib/bindey/.github/workflows/ci.yml b/lib/bindey/.github/workflows/ci.yml deleted file mode 100644 index 060f14e4..00000000 --- a/lib/bindey/.github/workflows/ci.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: ci - -on: [pull_request] - -env: - # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) - BUILD_TYPE: Release - -jobs: - Build-And-Test: - runs-on: macos-latest - - steps: - - uses: actions/checkout@v2 - with: - submodules: true - - - name: Create Build Environment - # Some projects don't allow in-source building, so create a separate build directory - # We'll use this as our working directory for all subsequent commands - run: cmake -E make_directory ${{runner.workspace}}/build - - - name: Configure - shell: bash - working-directory: ${{runner.workspace}}/build - run: cmake $GITHUB_WORKSPACE -GXcode -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DBINDEY_BUILD_TESTS=ON - env: - CC: clang - CXX: clang - - - name: Build - working-directory: ${{runner.workspace}}/build - shell: bash - run: cmake --build . --config $BUILD_TYPE - env: - CC: clang - CXX: clang - - - name: Test - working-directory: ${{runner.workspace}}/build - shell: bash - # Execute tests defined by the CMake configuration. - # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail - run: ctest -C $BUILD_TYPE diff --git a/lib/bindey/.gitignore b/lib/bindey/.gitignore deleted file mode 100644 index 92b4043c..00000000 --- a/lib/bindey/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -*.a -*.lib -*.o -*.pdb -.DS_Store diff --git a/lib/bindey/.gitmodules b/lib/bindey/.gitmodules deleted file mode 100644 index 67f59dd4..00000000 --- a/lib/bindey/.gitmodules +++ /dev/null @@ -1,6 +0,0 @@ -[submodule "lib/Catch2"] - path = lib/Catch2 - url = git@github.com:catchorg/Catch2.git -[submodule "lib/nod"] - path = lib/nod - url = git@github.com:fr00b0/nod.git diff --git a/lib/bindey/CMakeLists.txt b/lib/bindey/CMakeLists.txt deleted file mode 100644 index f71c176a..00000000 --- a/lib/bindey/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -# Copyright 2023 jacqueline <me@jacqueline.id.au> -# -# SPDX-License-Identifier: GPL-3.0-only -idf_component_register( - INCLUDE_DIRS "include" -) diff --git a/lib/bindey/LICENSE.md b/lib/bindey/LICENSE.md deleted file mode 100644 index 5ba17155..00000000 --- a/lib/bindey/LICENSE.md +++ /dev/null @@ -1,21 +0,0 @@ -## The MIT License (MIT) - -Copyright (c) 2021 Kevin Dixon - -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. diff --git a/lib/bindey/README.md b/lib/bindey/README.md deleted file mode 100644 index 0ef0e62b..00000000 --- a/lib/bindey/README.md +++ /dev/null @@ -1,116 +0,0 @@ -# bindey - -Everyone knows Model-View-ViewModel is the best architecture, but how can we realize it in C++ applications with minimal overhead, and no complicated framework impositions? - -`bindey` provides the basic building block of MVVM -- an observable "Property" and a databinding mechanism. - -## Property Usage - -At minimum, `bindey::property` can allow you to avoid writing getters and setters. Consider this example: - -``` -#include <bindey/property.h> - -using namespace bindey; - -class Person -{ -public: - property<std::string> name; - property<int> age; -}; -``` -Then we can use it like this: -``` -Person p; -p.name("Kevin"); -p.age(666); - -auto thatDudesName = p.name(); -auto ageIsJustANumber = p.age(); -``` - -`property` default initializes its value with `{}`, and of course allows initialization. -``` -Person::Person() -: name("Default Name") -, age(0) -{} -``` -## Data Binding -`bindey` provides a simple binding mechanism to connect a "source" `property` to an arbitrary object. This base signature is -``` -template <typename T, typename To> -binding bind( property<T>& from, To& to ); -``` -And a specialization for `property` to `property` binding of the same type is provided. -``` -template<typename T> -binding bind( property<T>& from, property<T>& to ) -{ - return from.onChanged( [&]( const auto& newValue ) { to( newValue ); } ); -} -``` - -### Writing Your Own Bindings -Where this becomes fun is when you get to reduce boilerplate. For example, assume a `Button` class from some UI Framework. -``` -struct Button -{ - void setText(const std::string& text) - { - this->text = text; - } - - std::string text; -}; -``` -To make your life better, simply implement a template speciailization in the `bindey` namespace. -``` -namespace bindey -{ -template <> -binding bind( property<std::string>& from, Button& to ) -{ - return from.onChanged( [&]( const auto& newValue ){ to.setText( newValue ); } ); -} -} // namespace bindey -``` -Then, bind your property to the button as needed: -``` -bindey::property<std::string> name; -... -Button someButton; -... -bindey::bind( name, someButton ); -``` - -### Binding Lifetimes -The result of a call to `bind` is a `bindey::binding` object. If this return value is discarded, then the binding's lifetime is coupled to the `property`'s. - -Otherwise, this token can be used to disconnect the binding as needed, the easiest way is to capture it in a `scoped_binding` object. - -For example, if your binding involves objects who's lifetime you do not control, you should certainly capture the binding to avoid crashes. -``` -struct GreatObj -{ - GreatObj(Button* b) - { - mSomeButton = b; - mButtonBinding = bindey::bind( name, *mSomeButton ); - } - - void updateButton(Button* newB) - { - mSomeButton = nullptr; - mButtonBinding = {}; // disconnect from old button - if( newB != nullptr ) - { - mSomeButton = newB; - mButtonBinding = bindey::bind( name, *mSomeButton ); - } - } - - bindey::scoped_binding mButtonBinding; -}; -``` diff --git a/lib/bindey/include/bindey/binding.h b/lib/bindey/include/bindey/binding.h deleted file mode 100644 index 69baa5cf..00000000 --- a/lib/bindey/include/bindey/binding.h +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once - -#include "property.h" - -#include <nod/nod.hpp> - -#include <functional> -#include <type_traits> - -namespace bindey -{ - -using binding = nod::connection; -using scoped_binding = nod::scoped_connection; - -/** - * base binding signature - */ -template <typename T, typename To> -binding bind( property<T>& from, To& to ); - -/** - * binds two properties of the same type - */ -template <typename T> -binding bind( property<T>& from, property<T>& to ) -{ - return from.onChanged( [&]( const auto& newValue ) { to( newValue ); } ); -} - -/** - * binds two properties of differing types using a Converter callable - * @param from property to observe - * @param to property to write to - * @param bindingConverter a callable to invoke to convert between the types - */ -template <typename TFrom, typename TTo, typename Converter> -binding bind( property<TFrom>& from, property<TTo>& to, Converter&& bindingConverter ) -{ - static_assert( std::is_convertible<Converter&&, std::function<TTo( const TFrom& )>>::value, - "Wrong Signature for binding converter!" ); - - return from.onChanged( - [&to, converter = bindingConverter]( const auto& newValue ) { to( converter( newValue ) ); } ); -} - -} // namespace bindey diff --git a/lib/bindey/include/bindey/property.h b/lib/bindey/include/bindey/property.h deleted file mode 100644 index 369f01f0..00000000 --- a/lib/bindey/include/bindey/property.h +++ /dev/null @@ -1,137 +0,0 @@ -#pragma once - -#include <nod/nod.hpp> - -#include <functional> - -namespace bindey -{ - -/** - * Optional always_update policy to notify subscribers everytime the property value is set, not just when it changes - */ -class always_update -{ -public: - template <typename T> - bool operator()( const T&, const T& ) const - { - return true; - } -}; - -template <typename T, - typename UpdatePolicy = std::not_equal_to<T>, - typename Signal = nod::unsafe_signal<void( const T& )>> -class property -{ -public: - property() - { - } - property( T&& value ) - : mStorage( std::move( value ) ) - { - } - property( const property& ) = delete; - property& operator=(const property&) = delete; - - - /** - * gets the current value - * @return const reference to the value - */ - const T& get() const - { - return mStorage; - } - - /** - * gets the current value - * @return mutable reference to the value - */ - T& get() - { - return mStorage; - } - - const T& operator()() const - { - return get(); - } - - T& operator()() - { - return get(); - } - - /** - * sets the value of the property. - * @param value the new value - * @discussion the value will only be updated if the UpdatePolicy's critera is met. - * if the value is changed, then the @ref changed event will be fired. - */ - void set( const T& value ) - { - if ( UpdatePolicy{}( mStorage, value ) ) - { - mStorage = value; - changed( mStorage ); - } - } - - void set( T&& value ) - { - if ( UpdatePolicy{}( mStorage, value ) ) - { - mStorage = std::move( value ); - changed( mStorage ); - } - } - - void operator()( const T& value ) - { - set( value ); - } - - void operator()( T&& value ) - { - set( std::move( value ) ); - } - - /** - * this signal is invoked whenever the the value changes per the UpdatePolicy - * @discussion nod::unsafe_signal is used here for speed. Take care of your own threading. - */ - Signal changed; - - /** - * convience function to attach a change listener to this property - */ - auto onChanged( typename decltype( changed )::slot_type&& c ) - { - return changed.connect( std::move( c ) ); - } - - /** - * convience function to attach a change listener to this property and call it right away - */ - auto onChangedAndNow( typename decltype( changed )::slot_type&& c ) - { - auto connection = onChanged( std::move( c ) ); - changed( mStorage ); - return connection; - } - - -private: - T mStorage{}; -}; - -/** - * thread safe property type based on nod::signal - */ -template <typename T, typename UpdatePolicy = std::not_equal_to<T>> -using safe_property = property<T, UpdatePolicy, nod::signal<void( const T& )>>; - -} // namespace bindey diff --git a/lib/bindey/include/nod/nod.hpp b/lib/bindey/include/nod/nod.hpp deleted file mode 100644 index 68e7b8d4..00000000 --- a/lib/bindey/include/nod/nod.hpp +++ /dev/null @@ -1,681 +0,0 @@ -#ifndef IG_NOD_INCLUDE_NOD_HPP -#define IG_NOD_INCLUDE_NOD_HPP - -#include <vector> // std::vector -#include <functional> // std::function -#include <mutex> // std::mutex, std::lock_guard -#include <memory> // std::shared_ptr, std::weak_ptr -#include <algorithm> // std::find_if() -#include <cassert> // assert() -#include <thread> // std::this_thread::yield() -#include <type_traits> // std::is_same -#include <iterator> // std::back_inserter - -namespace nod { - // implementational details - namespace detail { - /// Interface for type erasure when disconnecting slots - struct disconnector { - virtual ~disconnector() {} - virtual void operator()( std::size_t index ) const = 0; - }; - /// Deleter that doesn't delete - inline void no_delete(disconnector*){ - }; - } // namespace detail - - /// Base template for the signal class - template <class P, class T> - class signal_type; - - - /// Connection class. - /// - /// This is used to be able to disconnect slots after they have been connected. - /// Used as return type for the connect method of the signals. - /// - /// Connections are default constructible. - /// Connections are not copy constructible or copy assignable. - /// Connections are move constructible and move assignable. - /// - class connection { - public: - /// Default constructor - connection() : - _index() - {} - - // Connection are not copy constructible or copy assignable - connection( connection const& ) = delete; - connection& operator=( connection const& ) = delete; - - /// Move constructor - /// @param other The instance to move from. - connection( connection&& other ) : - _weak_disconnector( std::move(other._weak_disconnector) ), - _index( other._index ) - {} - - /// Move assign operator. - /// @param other The instance to move from. - connection& operator=( connection&& other ) { - _weak_disconnector = std::move( other._weak_disconnector ); - _index = other._index; - return *this; - } - - /// @returns `true` if the connection is connected to a signal object, - /// and `false` otherwise. - bool connected() const { - return !_weak_disconnector.expired(); - } - - /// Disconnect the slot from the connection. - /// - /// If the connection represents a slot that is connected to a signal object, calling - /// this method will disconnect the slot from that object. The result of this operation - /// is that the slot will stop receiving calls when the signal is invoked. - void disconnect(); - - private: - /// The signal template is a friend of the connection, since it is the - /// only one allowed to create instances using the meaningful constructor. - template<class P,class T> friend class signal_type; - - /// Create a connection. - /// @param shared_disconnector Disconnector instance that will be used to disconnect - /// the connection when the time comes. A weak pointer - /// to the disconnector will be held within the connection - /// object. - /// @param index The slot index of the connection. - connection( std::shared_ptr<detail::disconnector> const& shared_disconnector, std::size_t index ) : - _weak_disconnector( shared_disconnector ), - _index( index ) - {} - - /// Weak pointer to the current disconnector functor. - std::weak_ptr<detail::disconnector> _weak_disconnector; - /// Slot index of the connected slot. - std::size_t _index; - }; - - /// Scoped connection class. - /// - /// This type of connection is automatically disconnected when - /// the connection object is destructed. - /// - class scoped_connection - { - public: - /// Scoped are default constructible - scoped_connection() = default; - /// Scoped connections are not copy constructible - scoped_connection( scoped_connection const& ) = delete; - /// Scoped connections are not copy assingable - scoped_connection& operator=( scoped_connection const& ) = delete; - - /// Move constructor - scoped_connection( scoped_connection&& other ) : - _connection( std::move(other._connection) ) - {} - - /// Move assign operator. - /// @param other The instance to move from. - scoped_connection& operator=( scoped_connection&& other ) { - reset( std::move( other._connection ) ); - return *this; - } - - /// Construct a scoped connection from a connection object - /// @param connection The connection object to manage - scoped_connection( connection&& c ) : - _connection( std::forward<connection>(c) ) - {} - - /// destructor - ~scoped_connection() { - disconnect(); - } - - /// Assignment operator moving a new connection into the instance. - /// @note If the scoped_connection instance already contains a - /// connection, that connection will be disconnected as if - /// the scoped_connection was destroyed. - /// @param c New connection to manage - scoped_connection& operator=( connection&& c ) { - reset( std::forward<connection>(c) ); - return *this; - } - - /// Reset the underlying connection to another connection. - /// @note The connection currently managed by the scoped_connection - /// instance will be disconnected when resetting. - /// @param c New connection to manage - void reset( connection&& c = {} ) { - disconnect(); - _connection = std::move(c); - } - - /// Release the underlying connection, without disconnecting it. - /// @returns The newly released connection instance is returned. - connection release() { - connection c = std::move(_connection); - _connection = connection{}; - return c; - } - - /// - /// @returns `true` if the connection is connected to a signal object, - /// and `false` otherwise. - bool connected() const { - return _connection.connected(); - } - - /// Disconnect the slot from the connection. - /// - /// If the connection represents a slot that is connected to a signal object, calling - /// this method will disconnect the slot from that object. The result of this operation - /// is that the slot will stop receiving calls when the signal is invoked. - void disconnect() { - _connection.disconnect(); - } - - private: - /// Underlying connection object - connection _connection; - }; - - /// Policy for multi threaded use of signals. - /// - /// This policy provides mutex and lock types for use in - /// a multithreaded environment, where signals and slots - /// may exists in different threads. - /// - /// This policy is used in the `nod::signal` type provided - /// by the library. - struct multithread_policy - { - using mutex_type = std::mutex; - using mutex_lock_type = std::unique_lock<mutex_type>; - /// Function that yields the current thread, allowing - /// the OS to reschedule. - static void yield_thread() { - std::this_thread::yield(); - } - /// Function that defers a lock to a lock function that prevents deadlock - static mutex_lock_type defer_lock(mutex_type & m){ - return mutex_lock_type{m, std::defer_lock}; - } - /// Function that locks two mutexes and prevents deadlock - static void lock(mutex_lock_type & a,mutex_lock_type & b) { - std::lock(a,b); - } - }; - - /// Policy for single threaded use of signals. - /// - /// This policy provides dummy implementations for mutex - /// and lock types, resulting in that no synchronization - /// will take place. - /// - /// This policy is used in the `nod::unsafe_signal` type - /// provided by the library. - struct singlethread_policy - { - /// Dummy mutex type that doesn't do anything - struct mutex_type{}; - /// Dummy lock type, that doesn't do any locking. - struct mutex_lock_type - { - /// A lock type must be constructible from a - /// mutex type from the same thread policy. - explicit mutex_lock_type( mutex_type const& ) { - } - }; - /// Dummy implementation of thread yielding, that - /// doesn't do any actual yielding. - static void yield_thread() { - } - /// Dummy implemention of defer_lock that doesn't - /// do anything - static mutex_lock_type defer_lock(mutex_type &m){ - return mutex_lock_type{m}; - } - /// Dummy implemention of lock that doesn't - /// do anything - static void lock(mutex_lock_type &,mutex_lock_type &) { - } - }; - - /// Signal accumulator class template. - /// - /// This acts sort of as a proxy for triggering a signal and - /// accumulating the slot return values. - /// - /// This class is not really intended to instantiate by client code. - /// Instances are aquired as return values of the method `accumulate()` - /// called on signals. - /// - /// @tparam S Type of signal. The signal_accumulator acts - /// as a type of proxy for a signal instance of - /// this type. - /// @tparam T Type of initial value of the accumulate algorithm. - /// This type must meet the requirements of `CopyAssignable` - /// and `CopyConstructible` - /// @tparam F Type of accumulation function. - /// @tparam A... Argument types of the underlying signal type. - /// - template <class S, class T, class F, class...A> - class signal_accumulator - { - public: - /// Result type when calling the accumulating function operator. - using result_type = typename std::result_of<F(T, typename S::slot_type::result_type)>::type; - - /// Construct a signal_accumulator as a proxy to a given signal - // - /// @param signal Signal instance. - /// @param init Initial value of the accumulate algorithm. - /// @param func Binary operation function object that will be - /// applied to all slot return values. - /// The signature of the function should be - /// equivalent of the following: - /// `R func( T1 const& a, T2 const& b )` - /// - The signature does not need to have `const&`. - /// - The initial value, type `T`, must be implicitly - /// convertible to `R` - /// - The return type `R` must be implicitly convertible - /// to type `T1`. - /// - The type `R` must be `CopyAssignable`. - /// - The type `S::slot_type::result_type` (return type of - /// the signals slots) must be implicitly convertible to - /// type `T2`. - signal_accumulator( S const& signal, T init, F func ) : - _signal( signal ), - _init( init ), - _func( func ) - {} - - /// Function call operator. - /// - /// Calling this will trigger the underlying signal and accumulate - /// all of the connected slots return values with the current - /// initial value and accumulator function. - /// - /// When called, this will invoke the accumulator function will - /// be called for each return value of the slots. The semantics - /// are similar to the `std::accumulate` algorithm. - /// - /// @param args Arguments to propagate to the slots of the - /// underlying when triggering the signal. - result_type operator()( A const& ... args ) const { - return _signal.trigger_with_accumulator( _init, _func, args... ); - } - - private: - - /// Reference to the underlying signal to proxy. - S const& _signal; - /// Initial value of the accumulate algorithm. - T _init; - /// Accumulator function. - F _func; - - }; - - /// Signal template specialization. - /// - /// This is the main signal implementation, and it is used to - /// implement the observer pattern whithout the overhead - /// boilerplate code that typically comes with it. - /// - /// Any function or function object is considered a slot, and - /// can be connected to a signal instance, as long as the signature - /// of the slot matches the signature of the signal. - /// - /// @tparam P Threading policy for the signal. - /// A threading policy must provide two type definitions: - /// - P::mutex_type, this type will be used as a mutex - /// in the signal_type class template. - /// - P::mutex_lock_type, this type must implement a - /// constructor that takes a P::mutex_type as a parameter, - /// and it must have the semantics of a scoped mutex lock - /// like std::lock_guard, i.e. locking in the constructor - /// and unlocking in the destructor. - /// - /// @tparam R Return value type of the slots connected to the signal. - /// @tparam A... Argument types of the slots connected to the signal. - template <class P, class R, class... A > - class signal_type<P,R(A...)> - { - public: - /// signals are not copy constructible - signal_type( signal_type const& ) = delete; - /// signals are not copy assignable - signal_type& operator=( signal_type const& ) = delete; - /// signals are move constructible - signal_type(signal_type&& other) - { - mutex_lock_type lock{other._mutex}; - _slot_count = std::move(other._slot_count); - _slots = std::move(other._slots); - if(other._shared_disconnector != nullptr) - { - _disconnector = disconnector{ this }; - _shared_disconnector = std::move(other._shared_disconnector); - // replace the disconnector with our own disconnector - *static_cast<disconnector*>(_shared_disconnector.get()) = _disconnector; - } - } - /// signals are move assignable - signal_type& operator=(signal_type&& other) - { - auto lock = thread_policy::defer_lock(_mutex); - auto other_lock = thread_policy::defer_lock(other._mutex); - thread_policy::lock(lock,other_lock); - - _slot_count = std::move(other._slot_count); - _slots = std::move(other._slots); - if(other._shared_disconnector != nullptr) - { - _disconnector = disconnector{ this }; - _shared_disconnector = std::move(other._shared_disconnector); - // replace the disconnector with our own disconnector - *static_cast<disconnector*>(_shared_disconnector.get()) = _disconnector; - } - return *this; - } - - /// signals are default constructible - signal_type() : - _slot_count(0) - {} - - // Destruct the signal object. - ~signal_type() { - invalidate_disconnector(); - } - - /// Type that will be used to store the slots for this signal type. - using slot_type = std::function<R(A...)>; - /// Type that is used for counting the slots connected to this signal. - using size_type = typename std::vector<slot_type>::size_type; - - - /// Connect a new slot to the signal. - /// - /// The connected slot will be called every time the signal - /// is triggered. - /// @param slot The slot to connect. This must be a callable with - /// the same signature as the signal itself. - /// @return A connection object is returned, and can be used to - /// disconnect the slot. - template <class T> - connection connect( T&& slot ) { - mutex_lock_type lock{ _mutex }; - _slots.push_back( std::forward<T>(slot) ); - std::size_t index = _slots.size()-1; - if( _shared_disconnector == nullptr ) { - _disconnector = disconnector{ this }; - _shared_disconnector = std::shared_ptr<detail::disconnector>{&_disconnector, detail::no_delete}; - } - ++_slot_count; - return connection{ _shared_disconnector, index }; - } - - /// Function call operator. - /// - /// Calling this is how the signal is triggered and the - /// connected slots are called. - /// - /// @note The slots will be called in the order they were - /// connected to the signal. - /// - /// @param args Arguments that will be propagated to the - /// connected slots when they are called. - void operator()( A const&... args ) const { - for( auto const& slot : copy_slots() ) { - if( slot ) { - slot( args... ); - } - } - } - - /// Construct a accumulator proxy object for the signal. - /// - /// The intended purpose of this function is to create a function - /// object that can be used to trigger the signal and accumulate - /// all the slot return values. - /// - /// The algorithm used to accumulate slot return values is similar - /// to `std::accumulate`. A given binary function is called for - /// each return value with the parameters consisting of the - /// return value of the accumulator function applied to the - /// previous slots return value, and the current slots return value. - /// A initial value must be provided for the first slot return type. - /// - /// @note This can only be used on signals that have slots with - /// non-void return types, since we can't accumulate void - /// values. - /// - /// @tparam T The type of the initial value given to the accumulator. - /// @tparam F The accumulator function type. - /// @param init Initial value given to the accumulator. - /// @param op Binary operator function object to apply by the accumulator. - /// The signature of the function should be - /// equivalent of the following: - /// `R func( T1 const& a, T2 const& b )` - /// - The signature does not need to have `const&`. - /// - The initial value, type `T`, must be implicitly - /// convertible to `R` - /// - The return type `R` must be implicitly convertible - /// to type `T1`. - /// - The type `R` must be `CopyAssignable`. - /// - The type `S::slot_type::result_type` (return type of - /// the signals slots) must be implicitly convertible to - /// type `T2`. - template <class T, class F> - signal_accumulator<signal_type, T, F, A...> accumulate( T init, F op ) const { - static_assert( std::is_same<R,void>::value == false, "Unable to accumulate slot return values with 'void' as return type." ); - return { *this, init, op }; - } - - - /// Trigger the signal, calling the slots and aggregate all - /// the slot return values into a container. - /// - /// @tparam C The type of container. This type must be - /// `DefaultConstructible`, and usable with - /// `std::back_insert_iterator`. Additionally it - /// must be either copyable or moveable. - /// @param args The arguments to propagate to the slots. - template <class C> - C aggregate( A const&... args ) const { - static_assert( std::is_same<R,void>::value == false, "Unable to aggregate slot return values with 'void' as return type." ); - C container; - auto iterator = std::back_inserter( container ); - for( auto const& slot : copy_slots() ) { - if( slot ) { - (*iterator) = slot( args... ); - } - } - return container; - } - - /// Count the number of slots connected to this signal - /// @returns The number of connected slots - size_type slot_count() const { - return _slot_count; - } - - /// Determine if the signal is empty, i.e. no slots are connected - /// to it. - /// @returns `true` is returned if the signal has no connected - /// slots, and `false` otherwise. - bool empty() const { - return slot_count() == 0; - } - - /// Disconnects all slots - /// @note This operation invalidates all scoped_connection objects - void disconnect_all_slots() { - mutex_lock_type lock{ _mutex }; - _slots.clear(); - _slot_count = 0; - invalidate_disconnector(); - } - - private: - template<class, class, class, class...> friend class signal_accumulator; - /// Thread policy currently in use - using thread_policy = P; - /// Type of mutex, provided by threading policy - using mutex_type = typename thread_policy::mutex_type; - /// Type of mutex lock, provided by threading policy - using mutex_lock_type = typename thread_policy::mutex_lock_type; - - /// Invalidate the internal disconnector object in a way - /// that is safe according to the current thread policy. - /// - /// This will effectively make all current connection objects to - /// to this signal incapable of disconnecting, since they keep a - /// weak pointer to the shared disconnector object. - void invalidate_disconnector() { - // If we are unlucky, some of the connected slots - // might be in the process of disconnecting from other threads. - // If this happens, we are risking to destruct the disconnector - // object managed by our shared pointer before they are done - // disconnecting. This would be bad. To solve this problem, we - // discard the shared pointer (that is pointing to the disconnector - // object within our own instance), but keep a weak pointer to that - // instance. We then stall the destruction until all other weak - // pointers have released their "lock" (indicated by the fact that - // we will get a nullptr when locking our weak pointer). - std::weak_ptr<detail::disconnector> weak{_shared_disconnector}; - _shared_disconnector.reset(); - while( weak.lock() != nullptr ) { - // we just yield here, allowing the OS to reschedule. We do - // this until all threads has released the disconnector object. - thread_policy::yield_thread(); - } - } - - /// Retrieve a copy of the current slots - /// - /// It's useful and necessary to copy the slots so we don't need - /// to hold the lock while calling the slots. If we hold the lock - /// we prevent the called slots from modifying the slots vector. - /// This simple "double buffering" will allow slots to disconnect - /// themself or other slots and connect new slots. - std::vector<slot_type> copy_slots() const - { - mutex_lock_type lock{ _mutex }; - return _slots; - } - - /// Implementation of the signal accumulator function call - template <class T, class F> - typename signal_accumulator<signal_type, T, F, A...>::result_type trigger_with_accumulator( T value, F& func, A const&... args ) const { - for( auto const& slot : copy_slots() ) { - if( slot ) { - value = func( value, slot( args... ) ); - } - } - return value; - } - - /// Implementation of the disconnection operation. - /// - /// This is private, and only called by the connection - /// objects created when connecting slots to this signal. - /// @param index The slot index of the slot that should - /// be disconnected. - void disconnect( std::size_t index ) { - mutex_lock_type lock( _mutex ); - assert( _slots.size() > index ); - if( _slots[ index ] != nullptr ) { - --_slot_count; - } - _slots[ index ] = slot_type{}; - while( _slots.size()>0 && !_slots.back() ) { - _slots.pop_back(); - } - } - - /// Implementation of the shared disconnection state - /// used by all connection created by signal instances. - /// - /// This inherits the @ref detail::disconnector interface - /// for type erasure. - struct disconnector : - detail::disconnector - { - /// Default constructor, resulting in a no-op disconnector. - disconnector() : - _ptr(nullptr) - {} - - /// Create a disconnector that works with a given signal instance. - /// @param ptr Pointer to the signal instance that the disconnector - /// should work with. - disconnector( signal_type<P,R(A...)>* ptr ) : - _ptr( ptr ) - {} - - /// Disconnect a given slot on the current signal instance. - /// @note If the instance is default constructed, or created - /// with `nullptr` as signal pointer this operation will - /// effectively be a no-op. - /// @param index The index of the slot to disconnect. - void operator()( std::size_t index ) const override { - if( _ptr ) { - _ptr->disconnect( index ); - } - } - - /// Pointer to the current signal. - signal_type<P,R(A...)>* _ptr; - }; - - /// Mutex to synchronize access to the slot vector - mutable mutex_type _mutex; - /// Vector of all connected slots - std::vector<slot_type> _slots; - /// Number of connected slots - size_type _slot_count; - /// Disconnector operation, used for executing disconnection in a - /// type erased manner. - disconnector _disconnector; - /// Shared pointer to the disconnector. All connection objects has a - /// weak pointer to this pointer for performing disconnections. - std::shared_ptr<detail::disconnector> _shared_disconnector; - }; - - // Implementation of the disconnect operation of the connection class - inline void connection::disconnect() { - auto ptr = _weak_disconnector.lock(); - if( ptr ) { - (*ptr)( _index ); - } - _weak_disconnector.reset(); - } - - /// Signal type that is safe to use in multithreaded environments, - /// where the signal and slots exists in different threads. - /// The multithreaded policy provides mutexes and locks to synchronize - /// access to the signals internals. - /// - /// This is the recommended signal type, even for single threaded - /// environments. - template <class T> using signal = signal_type<multithread_policy, T>; - - /// Signal type that is unsafe in multithreaded environments. - /// No synchronizations are provided to the signal_type for accessing - /// the internals. - /// - /// Only use this signal type if you are sure that your environment is - /// single threaded and performance is of importance. - template <class T> using unsafe_signal = signal_type<singlethread_policy, T>; -} // namespace nod - -#endif // IG_NOD_INCLUDE_NOD_HPP diff --git a/lib/luavgl/src/lvgl.lua b/lib/luavgl/src/lvgl.lua index 67c2960e..32061c1f 100644 --- a/lib/luavgl/src/lvgl.lua +++ b/lib/luavgl/src/lvgl.lua @@ -9,278 +9,278 @@ lvgl = {} --- @enum ObjEventCode lvgl.EVENT = { - ALL = 0, - PRESSED = 0, - PRESSING = 0, - PRESS_LOST = 0, - SHORT_CLICKED = 0, - LONG_PRESSED = 0, - LONG_PRESSED_REPEAT = 0, - CLICKED = 0, - RELEASED = 0, - SCROLL_BEGIN = 0, - SCROLL_END = 0, - SCROLL = 0, - GESTURE = 0, - KEY = 0, - FOCUSED = 0, - DEFOCUSED = 0, - LEAVE = 0, - HIT_TEST = 0, - COVER_CHECK = 0, - REFR_EXT_DRAW_SIZE = 0, - DRAW_MAIN_BEGIN = 0, - DRAW_MAIN = 0, - DRAW_MAIN_END = 0, - DRAW_POST_BEGIN = 0, - DRAW_POST = 0, - DRAW_POST_END = 0, - DRAW_PART_BEGIN = 0, - DRAW_PART_END = 0, - VALUE_CHANGED = 0, - INSERT = 0, - REFRESH = 0, - READY = 0, - CANCEL = 0, - DELETE = 0, - CHILD_CHANGED = 0, - CHILD_CREATED = 0, - CHILD_DELETED = 0, - SCREEN_UNLOAD_START = 0, - SCREEN_LOAD_START = 0, - SCREEN_LOADED = 0, - SCREEN_UNLOADED = 0, - SIZE_CHANGED = 0, - STYLE_CHANGED = 0, - LAYOUT_CHANGED = 0, - GET_SELF_SIZE = 0, + ALL = 0, + PRESSED = 0, + PRESSING = 0, + PRESS_LOST = 0, + SHORT_CLICKED = 0, + LONG_PRESSED = 0, + LONG_PRESSED_REPEAT = 0, + CLICKED = 0, + RELEASED = 0, + SCROLL_BEGIN = 0, + SCROLL_END = 0, + SCROLL = 0, + GESTURE = 0, + KEY = 0, + FOCUSED = 0, + DEFOCUSED = 0, + LEAVE = 0, + HIT_TEST = 0, + COVER_CHECK = 0, + REFR_EXT_DRAW_SIZE = 0, + DRAW_MAIN_BEGIN = 0, + DRAW_MAIN = 0, + DRAW_MAIN_END = 0, + DRAW_POST_BEGIN = 0, + DRAW_POST = 0, + DRAW_POST_END = 0, + DRAW_PART_BEGIN = 0, + DRAW_PART_END = 0, + VALUE_CHANGED = 0, + INSERT = 0, + REFRESH = 0, + READY = 0, + CANCEL = 0, + DELETE = 0, + CHILD_CHANGED = 0, + CHILD_CREATED = 0, + CHILD_DELETED = 0, + SCREEN_UNLOAD_START = 0, + SCREEN_LOAD_START = 0, + SCREEN_LOADED = 0, + SCREEN_UNLOADED = 0, + SIZE_CHANGED = 0, + STYLE_CHANGED = 0, + LAYOUT_CHANGED = 0, + GET_SELF_SIZE = 0, } --- object flag for obj:add_flag obj:clear_flag --- @enum ObjFlag lvgl.FLAG = { - PRESSED = 0, - HIDDEN = 0, - CLICKABLE = 0, - CLICK_FOCUSABLE = 0, - CHECKABLE = 0, - SCROLLABLE = 0, - SCROLL_ELASTIC = 0, - SCROLL_MOMENTUM = 0, - SCROLL_ONE = 0, - SCROLL_CHAIN_HOR = 0, - SCROLL_CHAIN_VER = 0, - SCROLL_CHAIN = 0, - SCROLL_ON_FOCUS = 0, - SCROLL_WITH_ARROW = 0, - SNAPPABLE = 0, - PRESS_LOCK = 0, - EVENT_BUBBLE = 0, - GESTURE_BUBBLE = 0, - ADV_HITTEST = 0, - IGNORE_LAYOUT = 0, - FLOATING = 0, - OVERFLOW_VISIBLE = 0, - LAYOUT_1 = 0, - LAYOUT_2 = 0, - WIDGET_1 = 0, - WIDGET_2 = 0, - USER_1 = 0, - USER_2 = 0, - USER_3 = 0, - USER_4 = 0, + PRESSED = 0, + HIDDEN = 0, + CLICKABLE = 0, + CLICK_FOCUSABLE = 0, + CHECKABLE = 0, + SCROLLABLE = 0, + SCROLL_ELASTIC = 0, + SCROLL_MOMENTUM = 0, + SCROLL_ONE = 0, + SCROLL_CHAIN_HOR = 0, + SCROLL_CHAIN_VER = 0, + SCROLL_CHAIN = 0, + SCROLL_ON_FOCUS = 0, + SCROLL_WITH_ARROW = 0, + SNAPPABLE = 0, + PRESS_LOCK = 0, + EVENT_BUBBLE = 0, + GESTURE_BUBBLE = 0, + ADV_HITTEST = 0, + IGNORE_LAYOUT = 0, + FLOATING = 0, + OVERFLOW_VISIBLE = 0, + LAYOUT_1 = 0, + LAYOUT_2 = 0, + WIDGET_1 = 0, + WIDGET_2 = 0, + USER_1 = 0, + USER_2 = 0, + USER_3 = 0, + USER_4 = 0, } --- @enum ObjState lvgl.STATE = { - DEFAULT = 0, - CHECKED = 0, - FOCUSED = 0, - FOCUS_KEY = 0, - EDITED = 0, - HOVERED = 0, - PRESSED = 0, - SCROLLED = 0, - DISABLED = 0, - USER_1 = 0, - USER_2 = 0, - USER_3 = 0, - USER_4 = 0, - ANY = 0, + DEFAULT = 0, + CHECKED = 0, + FOCUSED = 0, + FOCUS_KEY = 0, + EDITED = 0, + HOVERED = 0, + PRESSED = 0, + SCROLLED = 0, + DISABLED = 0, + USER_1 = 0, + USER_2 = 0, + USER_3 = 0, + USER_4 = 0, + ANY = 0, } --- @enum ObjAlignType lvgl.ALIGN = { - DEFAULT = 0, - TOP_LEFT = 0, - TOP_MID = 0, - TOP_RIGHT = 0, - BOTTOM_LEFT = 0, - BOTTOM_MID = 0, - BOTTOM_RIGHT = 0, - LEFT_MID = 0, - RIGHT_MID = 0, - CENTER = 0, - OUT_TOP_LEFT = 0, - OUT_TOP_MID = 0, - OUT_TOP_RIGHT = 0, - OUT_BOTTOM_LEFT = 0, - OUT_BOTTOM_MID = 0, - OUT_BOTTOM_RIGHT = 0, - OUT_LEFT_TOP = 0, - OUT_LEFT_MID = 0, - OUT_LEFT_BOTTOM = 0, - OUT_RIGHT_TOP = 0, - OUT_RIGHT_MID = 0, - OUT_RIGHT_BOTTOM = 0, + DEFAULT = 0, + TOP_LEFT = 0, + TOP_MID = 0, + TOP_RIGHT = 0, + BOTTOM_LEFT = 0, + BOTTOM_MID = 0, + BOTTOM_RIGHT = 0, + LEFT_MID = 0, + RIGHT_MID = 0, + CENTER = 0, + OUT_TOP_LEFT = 0, + OUT_TOP_MID = 0, + OUT_TOP_RIGHT = 0, + OUT_BOTTOM_LEFT = 0, + OUT_BOTTOM_MID = 0, + OUT_BOTTOM_RIGHT = 0, + OUT_LEFT_TOP = 0, + OUT_LEFT_MID = 0, + OUT_LEFT_BOTTOM = 0, + OUT_RIGHT_TOP = 0, + OUT_RIGHT_MID = 0, + OUT_RIGHT_BOTTOM = 0, } --- @enum BuiltinFont lvgl.BUILTIN_FONT = { - MONTSERRAT_8 = 0, - MONTSERRAT_10 = 0, - MONTSERRAT_12 = 0, - MONTSERRAT_14 = 0, - MONTSERRAT_16 = 0, - MONTSERRAT_18 = 0, - MONTSERRAT_20 = 0, - MONTSERRAT_22 = 0, - MONTSERRAT_24 = 0, - MONTSERRAT_26 = 0, - MONTSERRAT_28 = 0, - MONTSERRAT_30 = 0, - MONTSERRAT_32 = 0, - MONTSERRAT_34 = 0, - MONTSERRAT_36 = 0, - MONTSERRAT_38 = 0, - MONTSERRAT_40 = 0, - MONTSERRAT_42 = 0, - MONTSERRAT_44 = 0, - MONTSERRAT_46 = 0, - MONTSERRAT_48 = 0, - MONTSERRAT_12_SUBPX = 0, - MONTSERRAT_28_COMPRESSED = 0, - DEJAVU_16_PERSIAN_HEBREW = 0, - SIMSUN_16_CJK = 0, - UNSCII_8 = 0, - UNSCII_16 = 0, + MONTSERRAT_8 = 0, + MONTSERRAT_10 = 0, + MONTSERRAT_12 = 0, + MONTSERRAT_14 = 0, + MONTSERRAT_16 = 0, + MONTSERRAT_18 = 0, + MONTSERRAT_20 = 0, + MONTSERRAT_22 = 0, + MONTSERRAT_24 = 0, + MONTSERRAT_26 = 0, + MONTSERRAT_28 = 0, + MONTSERRAT_30 = 0, + MONTSERRAT_32 = 0, + MONTSERRAT_34 = 0, + MONTSERRAT_36 = 0, + MONTSERRAT_38 = 0, + MONTSERRAT_40 = 0, + MONTSERRAT_42 = 0, + MONTSERRAT_44 = 0, + MONTSERRAT_46 = 0, + MONTSERRAT_48 = 0, + MONTSERRAT_12_SUBPX = 0, + MONTSERRAT_28_COMPRESSED = 0, + DEJAVU_16_PERSIAN_HEBREW = 0, + SIMSUN_16_CJK = 0, + UNSCII_8 = 0, + UNSCII_16 = 0, } --- @enum LABEL lvgl.LABEL = { - LONG_WRAP = 0, - LONG_DOT = 0, - LONG_SCROLL = 0, - LONG_SCROLL_CIRCULAR = 0, - LONG_CLIP = 0, + LONG_WRAP = 0, + LONG_DOT = 0, + LONG_SCROLL = 0, + LONG_SCROLL_CIRCULAR = 0, + LONG_CLIP = 0, } --- @enum SCR_LOAD_ANIM lvgl.SCR_LOAD_ANIM = { - NONE = 0, - OVER_LEFT = 0, - OVER_RIGHT = 0, - OVER_TOP = 0, - OVER_BOTTOM = 0, - MOVE_LEFT = 0, - MOVE_RIGHT = 0, - MOVE_TOP = 0, - MOVE_BOTTOM = 0, - FADE_IN = 0, - FADE_ON = 0, - FADE_OUT = 0, - OUT_LEFT = 0, - OUT_RIGHT = 0, - OUT_TOP = 0, - OUT_BOTTOM = 0, + NONE = 0, + OVER_LEFT = 0, + OVER_RIGHT = 0, + OVER_TOP = 0, + OVER_BOTTOM = 0, + MOVE_LEFT = 0, + MOVE_RIGHT = 0, + MOVE_TOP = 0, + MOVE_BOTTOM = 0, + FADE_IN = 0, + FADE_ON = 0, + FADE_OUT = 0, + OUT_LEFT = 0, + OUT_RIGHT = 0, + OUT_TOP = 0, + OUT_BOTTOM = 0, } --- @enum ScrollbarMode lvgl.SCROLLBAR_MODE = { - OFF = 0, - ON = 0, - ACTIVE = 0, - AUTO = 0, + OFF = 0, + ON = 0, + ACTIVE = 0, + AUTO = 0, } --- @enum Dir lvgl.DIR = { - NONE = 0, - LEFT = 0, - RIGHT = 0, - TOP = 0, - BOTTOM = 0, - HOR = 0, - VER = 0, - ALL = 0, + NONE = 0, + LEFT = 0, + RIGHT = 0, + TOP = 0, + BOTTOM = 0, + HOR = 0, + VER = 0, + ALL = 0, } --- @enum KeyboardMode lvgl.KEYBOARD_MODE = { - TEXT_LOWER = 0, - TEXT_UPPER = 0, - SPECIAL = 0, - NUMBER = 0, - USER_1 = 0, - USER_2 = 0, - USER_3 = 0, - USER_4 = 0, - TEXT_ARABIC = 0, + TEXT_LOWER = 0, + TEXT_UPPER = 0, + SPECIAL = 0, + NUMBER = 0, + USER_1 = 0, + USER_2 = 0, + USER_3 = 0, + USER_4 = 0, + TEXT_ARABIC = 0, } --- @enum FlexFlow lvgl.FLEX_FLOW = { - ROW = 0, - COLUMN = 0, - ROW_WRAP = 0, - ROW_REVERSE = 0, - ROW_WRAP_REVERSE = 0, - COLUMN_WRAP = 0, - COLUMN_REVERSE = 0, - COLUMN_WRAP_REVERSE = 0, + ROW = 0, + COLUMN = 0, + ROW_WRAP = 0, + ROW_REVERSE = 0, + ROW_WRAP_REVERSE = 0, + COLUMN_WRAP = 0, + COLUMN_REVERSE = 0, + COLUMN_WRAP_REVERSE = 0, } --- @enum FlexAlign lvgl.FLEX_ALIGN = { - START = 0, - END = 0, - CENTER = 0, - SPACE_EVENLY = 0, - SPACE_AROUND = 0, - SPACE_BETWEEN = 0, + START = 0, + END = 0, + CENTER = 0, + SPACE_EVENLY = 0, + SPACE_AROUND = 0, + SPACE_BETWEEN = 0, } --- @enum GridAlign lvgl.GRID_ALIGN = { - START = 0, - CENTER = 0, - END = 0, - STRETCH = 0, - SPACE_EVENLY = 0, - SPACE_AROUND = 0, - SPACE_BETWEEN = 0, + START = 0, + CENTER = 0, + END = 0, + STRETCH = 0, + SPACE_EVENLY = 0, + SPACE_AROUND = 0, + SPACE_BETWEEN = 0, } --- @enum RollerMode lvgl.ROLLER_MODE = { - NORMAL = 0, - INFINITE = 0, + NORMAL = 0, + INFINITE = 0, } --- @enum KEY lvgl.KEY = { - UP = 0, - DOWN = 0, - RIGHT = 0, - LEFT = 0, - ESC = 0, - DEL = 0, - BACKSPACE = 0, - ENTER = 0, - NEXT = 0, - PREV = 0, - HOME = 0, - END = 0, + UP = 0, + DOWN = 0, + RIGHT = 0, + LEFT = 0, + ESC = 0, + DEL = 0, + BACKSPACE = 0, + ENTER = 0, + NEXT = 0, + PREV = 0, + HOME = 0, + END = 0, } lvgl.ANIM_REPEAT_INFINITE = 0 @@ -404,7 +404,6 @@ end function lvgl.Keyboard(parent, property) end - --- --- Create Led Widget on parent --- @param parent? Object | nil @@ -429,6 +428,20 @@ end function lvgl.Roller(parent, property) end +--- Create Slider widget on parent +--- @param parent? Object | nil +--- @param property? BarStyle +--- @return Slider +function lvgl.Slider(parent, property) +end + +--- Create Switch widget on parent +--- @param parent? Object | nil +--- @param property? StyleProp +--- @return Switch +function lvgl.Switch(parent, property) +end + --- --- Create Timer --- @param p TimerPara @@ -555,13 +568,27 @@ end function obj:List(property) end - --- --- Create Roller Widget on parent --- @param property? RollerStyle --- @return Roller function obj:Roller(parent, property) end + +--- +--- Create Slider on object +--- @param property? BarStyle +--- @return Slider +function obj:Slider(property) +end + +--- +--- Create switch on object +--- @param property? StyleProp +--- @return Switch +function obj:Switch(property) +end + --- --- Set object property --- @param p StyleProp @@ -1050,6 +1077,40 @@ function label:cut_text(pos, cnt) end --- +--- Slider widget +---@class Slider:Object +--- +local slider = {} + +--- set method for slider widget. Uses Bar widget's properties. +--- @param p BarStyle +--- @return nil +function slider:set(p) +end + +--- get value of slider +--- @return integer +function slider:value() +end + +--- +--- Switch widget +---@class Switch:Object +--- +local switch = {} + +--- set method for switch widget +--- @param p StyleProp +--- @return nil +function switch:set(p) +end + +--- get checked state of switch +--- @return boolean +function switch:enabled() +end + +--- --- Textarea widget ---@class Textarea: Object --- diff --git a/lib/luavgl/src/widgets/slider.c b/lib/luavgl/src/widgets/slider.c new file mode 100644 index 00000000..c385f6bb --- /dev/null +++ b/lib/luavgl/src/widgets/slider.c @@ -0,0 +1,88 @@ +#include "lua.h" +#include "luavgl.h" +#include "private.h" +#include <src/widgets/lv_slider.h> + +static int luavgl_slider_create(lua_State *L) { + return luavgl_obj_create_helper(L, lv_slider_create); +} + +static void _lv_slider_set_range(void *obj, lua_State *L) { + int min = 0, max = 100; + + int type = lua_type(L, -1); + if (type == LUA_TTABLE) { + lua_getfield(L, -1, "min"); + min = lua_tointeger(L, -1); + lua_pop(L, 1); + lua_getfield(L, -1, "max"); + max = luavgl_tointeger(L, -1); + lua_pop(L, 1); + } + + lv_slider_set_range(obj, min, max); +} + +static void _lv_slider_set_value(void *obj, int value) { + lv_slider_set_value(obj, value, LV_ANIM_OFF); +} + +static const luavgl_value_setter_t slider_property_table[] = { + {"range", SETTER_TYPE_STACK, {.setter_stack = _lv_slider_set_range}}, + {"value", SETTER_TYPE_INT, {.setter = (setter_int_t)_lv_slider_set_value}}, +}; + +LUALIB_API int luavgl_slider_set_property_kv(lua_State *L, void *data) { + lv_obj_t *obj = data; + int ret = luavgl_set_property(L, obj, slider_property_table); + + if (ret == 0) { + return 0; + } + /* a base obj property? */ + ret = luavgl_obj_set_property_kv(L, obj); + if (ret != 0) { + debug("unkown property for slider.\n"); + } + + return ret; +} + +static int luavgl_slider_set(lua_State *L) { + lv_obj_t *obj = luavgl_to_obj(L, 1); + + if (!lua_istable(L, -1)) { + luaL_error(L, "expect a table on 2nd para."); + return 0; + } + + luavgl_iterate(L, -1, luavgl_slider_set_property_kv, obj); + + return 0; +} + +static int luavgl_slider_value(lua_State *L) { + lv_obj_t *obj = luavgl_to_obj(L, 1); + lua_pushinteger(L, lv_slider_get_value(obj)); + return 1; +} + +static int luavgl_slider_tostring(lua_State *L) { + lv_obj_t *obj = luavgl_to_obj(L, 1); + lua_pushfstring(L, "lv_slider:%p", obj); + return 1; +} + +static const luaL_Reg luavgl_slider_methods[] = { + {"set", luavgl_slider_set}, + {"value", luavgl_slider_value}, + {NULL, NULL}, +}; + +static void luavgl_slider_init(lua_State *L) { + luavgl_obj_newmetatable(L, &lv_slider_class, "lv_slider", + luavgl_slider_methods); + lua_pushcfunction(L, luavgl_slider_tostring); + lua_setfield(L, -2, "__tostring"); + lua_pop(L, 1); +} diff --git a/lib/luavgl/src/widgets/switch.c b/lib/luavgl/src/widgets/switch.c new file mode 100644 index 00000000..e66f620e --- /dev/null +++ b/lib/luavgl/src/widgets/switch.c @@ -0,0 +1,57 @@ +#include "luavgl.h" +#include "private.h" +#include <src/widgets/lv_switch.h> + +static int luavgl_switch_create(lua_State *L) { + return luavgl_obj_create_helper(L, lv_switch_create); +} + +LUALIB_API int luavgl_switch_set_property_kv(lua_State *L, void *data) { + lv_obj_t *obj = data; + /* switches only use base properties */ + int ret = luavgl_obj_set_property_kv(L, obj); + if (ret != 0) { + debug("unkown property for switch.\n"); + } + + return ret; +} + +static int luavgl_switch_set(lua_State *L) { + lv_obj_t *obj = luavgl_to_obj(L, 1); + + if (!lua_istable(L, -1)) { + luaL_error(L, "expect a table on 2nd para."); + return 0; + } + + luavgl_iterate(L, -1, luavgl_switch_set_property_kv, obj); + + return 0; +} + +static int luavgl_switch_enabled(lua_State *L) { + lv_obj_t *obj = luavgl_to_obj(L, 1); + lua_pushboolean(L, lv_obj_has_state(obj, LV_STATE_CHECKED)); + return 1; +} + +static int luavgl_switch_tostring(lua_State *L) { + lv_obj_t *obj = luavgl_to_obj(L, 1); + lua_pushfstring(L, "lv_switch:%p", obj); + return 1; +} + +static const luaL_Reg luavgl_switch_methods[] = { + {"set", luavgl_switch_set}, + {"enabled", luavgl_switch_enabled}, + {NULL, NULL}, +}; + +static void luavgl_switch_init(lua_State *L) { + luavgl_obj_newmetatable(L, &lv_switch_class, "lv_switch", + luavgl_switch_methods); + lua_pushcfunction(L, luavgl_switch_tostring); + lua_setfield(L, -2, "__tostring"); + lua_pop(L, 1); +} diff --git a/lib/luavgl/src/widgets/widgets.c b/lib/luavgl/src/widgets/widgets.c index e5f64f23..4a7a126e 100644 --- a/lib/luavgl/src/widgets/widgets.c +++ b/lib/luavgl/src/widgets/widgets.c @@ -45,6 +45,14 @@ #include "roller.c" #endif +#if LV_USE_SLIDER +#include "slider.c" +#endif + +#if LV_USE_SWITCH +#include "switch.c" +#endif + #if LV_USE_TEXTAREA #include "textarea.c" #endif @@ -98,6 +106,14 @@ static const luaL_Reg widget_create_methods[] = { {"Roller", luavgl_roller_create }, #endif +#if LV_USE_SLIDER + {"Slider", luavgl_slider_create}, +#endif + +#if LV_USE_SWITCH + {"Switch", luavgl_switch_create}, +#endif + #if LV_USE_TEXTAREA {"Textarea", luavgl_textarea_create}, #endif @@ -154,4 +170,12 @@ static void luavgl_widgets_init(lua_State *L) luavgl_bar_init(L); #endif +#if LV_USE_SLIDER + luavgl_slider_init(L); +#endif + +#if LV_USE_SWITCH + luavgl_switch_init(L); +#endif + } |
