-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit a0f4f73
Showing
10 changed files
with
1,204 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
--- | ||
Language: Cpp | ||
BasedOnStyle: LLVM | ||
DerivePointerAlignment: false | ||
PointerAlignment: Left | ||
IndentWidth: 4 | ||
PPIndentWidth: 4 | ||
IndentPPDirectives: AfterHash | ||
AccessModifierOffset: -4 | ||
BreakConstructorInitializers: AfterColon | ||
PackConstructorInitializers: NextLine | ||
BreakBeforeBraces: Linux | ||
AlwaysBreakTemplateDeclarations: Yes |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
name: CMake | ||
|
||
on: | ||
push: | ||
branches: [ "master" ] | ||
pull_request: | ||
branches: [ "master" ] | ||
|
||
env: | ||
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) | ||
BUILD_TYPE: Release | ||
|
||
jobs: | ||
build: | ||
# The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac. | ||
# You can convert this to a matrix build if you need cross-platform coverage. | ||
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix | ||
strategy: | ||
matrix: | ||
os: [ubuntu-latest, windows-latest, macos-latest] | ||
|
||
runs-on: ${{ matrix.os }} | ||
|
||
steps: | ||
- uses: actions/checkout@v3 | ||
|
||
- name: Install gtest | ||
if: ${{ matrix.os == 'ubuntu-latest' }} | ||
run: sudo apt install libgtest-dev | ||
|
||
- name: Configure CMake | ||
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. | ||
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type | ||
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DBUILD_TESTING=ON | ||
|
||
- name: Build | ||
# Build your program with the given configuration | ||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} | ||
|
||
- name: Test | ||
working-directory: ${{github.workspace}}/build | ||
# Execute tests defined by the CMake configuration. | ||
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail | ||
run: ctest -C ${{env.BUILD_TYPE}} --output-on-failure | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
build | ||
.cache |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
cmake_minimum_required(VERSION 3.9) | ||
|
||
project( | ||
bindable_properties | ||
VERSION 1.0.0 | ||
DESCRIPTION "Bindable properties for C++ inspired by Qt's QProperty" | ||
LANGUAGES CXX | ||
) | ||
|
||
add_library( | ||
${PROJECT_NAME} | ||
src/bindable_properties.h | ||
src/bindable_properties.cpp | ||
) | ||
|
||
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 11) | ||
|
||
include(GNUInstallDirs) | ||
include(CMakePackageConfigHelpers) | ||
|
||
target_include_directories(${PROJECT_NAME} | ||
INTERFACE | ||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>/src | ||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}> | ||
) | ||
|
||
write_basic_package_version_file( | ||
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake | ||
VERSION | ||
${PROJECT_VERSION} | ||
COMPATIBILITY AnyNewerVersion | ||
) | ||
|
||
configure_package_config_file( | ||
cmake/${PROJECT_NAME}-config.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake | ||
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}/ | ||
) | ||
|
||
install( | ||
FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake | ||
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake | ||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} | ||
) | ||
|
||
install( | ||
FILES src/bindable_properties.h | ||
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}" | ||
) | ||
|
||
install( | ||
TARGETS ${PROJECT_NAME} | ||
EXPORT ${PROJECT_NAME}-targets | ||
) | ||
|
||
install( | ||
EXPORT ${PROJECT_NAME}-targets | ||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" | ||
) | ||
|
||
# testing | ||
if(BUILD_TESTING) | ||
enable_testing() | ||
find_package(GTest) | ||
if(NOT GTest_FOUND) | ||
include(FetchContent) | ||
FetchContent_Declare( | ||
googletest | ||
URL https://github.com/google/googletest/archive/refs/tags/v1.13.0.zip | ||
) | ||
# For Windows: Prevent overriding the parent project's compiler/linker settings | ||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) | ||
FetchContent_MakeAvailable(googletest) | ||
endif() | ||
add_executable(tests tests/tests.cpp) | ||
target_link_libraries(tests PRIVATE GTest::gtest_main bindable_properties) | ||
target_include_directories(tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tests) | ||
|
||
gtest_discover_tests(tests) | ||
endif() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2023 theartful | ||
|
||
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
# Bindable Properties for C++11 | ||
|
||
This is a C++ library that provides an implementation of properties that can | ||
be bound to each other. It allows for properties to be treated as data members, | ||
while also providing the ability to automatically update other properties when a | ||
property's value is changed. | ||
|
||
## Features | ||
|
||
- Support simple property views and complex bindings to one or more properties. | ||
- Automatic updates for bound properties. | ||
- Define custom notifications for when property changes its value. | ||
- Views and bound properties can request the original property to change. | ||
|
||
## Semantics | ||
|
||
### Property Ownership | ||
|
||
There are two ways to create a property: as an owner, or as a view/binding. When | ||
you create a property as an owner, the property owns its data, and is responsible | ||
for handling change requests. When you create a property as a view or a binding, | ||
the property value is a function of one or more other properties, and any changes | ||
made to these properties will be reflected in the view. | ||
|
||
You can transfer ownership of a property to another property by using the move | ||
constructor or move assignment operator. | ||
```C++ | ||
property<int> x = 5; | ||
property<int> y = x; // now y is a view of x, any changes to x will be reflected in y | ||
|
||
property<int> z = std::move(x); // x is moved into z, so any changes to z is reflected in y | ||
``` | ||
|
||
### Property Binding | ||
|
||
There are two types of property bindings: | ||
1. Views, or simple bindings. These can be done using the copy constructor. | ||
These are lightweight and don't require any allocations. | ||
```C++ | ||
property<int> x; | ||
property<int> y = x; | ||
|
||
x = 4; | ||
assert(y.value() == 4); | ||
``` | ||
2. Complex bindings, where a property is a function of one or more other properties. | ||
Bound properties are automatically updated when any of their dependencies change | ||
value. | ||
```C++ | ||
property<int> x; | ||
property<int> y; | ||
property<int> z; | ||
z.set_binding([=]() { return x.value() + y.value(); }); | ||
x = 4; | ||
y = 5; | ||
assert_eq(z.value() == 9); | ||
``` | ||
|
||
|
||
### Notifications | ||
|
||
You can register a single notification lambda function to be called whenever a | ||
property's value changes. Notifications can only be set on bound properties, | ||
since owner properties are the ones making the change. | ||
```C++ | ||
x.set_notifier([](int new_value) { std::cout << "x changed to " << new_value; }); | ||
``` | ||
### Change Requests and Setters | ||
Bound properties can request owner properties to change their values. Owner | ||
properties respond to this request by calling the registered `setter` lambda, | ||
or simply accept the change if no lambda is registered. | ||
```C++ | ||
property<int> owner; | ||
owner.set_setter([&](int value) { owner = value; }); | ||
property<int> view = owner; | ||
view.request_change(5); | ||
assert(view.value() == 5); | ||
``` | ||
|
||
### Example with Complex Bindings | ||
|
||
```C++ | ||
using namespace bindable_properties; | ||
|
||
property<int> x = 20; | ||
property<int> y = 21; | ||
property<double> hypotenuse; // Represents the hypotenuse of a right triangle | ||
|
||
// Binding: hypotenuse = sqrt(x^2 + y^2) | ||
hypotenuse.set_binding( | ||
// binding expression | ||
[&] { return std::sqrt(x * x + y * y); }, | ||
// handles change requests by trying to change y to achieve the requested | ||
// hypotenuse | ||
[&](double value) { | ||
// Setter that calls request_change on the x property | ||
y.request_change(std::sqrt(value * value - x * x)); | ||
} | ||
); | ||
|
||
assert(hypotenuse.value() == 29.0); | ||
|
||
hypotenuse.request_change(101.0); | ||
assert(x.value() == 20); | ||
assert(y.value() == 99); | ||
assert(hypotenuse.value() == 101.0); | ||
``` | ||
## No Allocations | ||
This library doesn't do any memory allocations as long as you: | ||
1. Use lambdas with only a single pointer as a state. | ||
2. Don't use complex bindings and only use property views. | ||
## Use | ||
Add the following lines to your CMakeLists.txt file: | ||
```cmake | ||
include(FetchContent) | ||
FetchContent_Declare( | ||
bindable_properties | ||
GIT_REPOSITORY https://github.com/theartful/bindable_properties | ||
GIT_TAG master | ||
) | ||
FetchContent_MakeAvailable(bindable_properties) | ||
target_link_libraries(target PUBLIC bindable_properties) | ||
``` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
@PACKAGE_INIT@ | ||
|
||
include(${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@-targets.cmake) |
Oops, something went wrong.