mirror of
https://github.com/slint-ui/slint.git
synced 2025-11-01 12:24:16 +00:00
[reorg]: Move api/sixtyfps-rs/sixtyfps-* into api/rs
This commit is contained in:
parent
2813441cd9
commit
842f75e653
95 changed files with 65 additions and 72 deletions
4
api/cpp/docs/.gitignore
vendored
Normal file
4
api/cpp/docs/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
# Copyright © 2021 SixtyFPS GmbH <info@sixtyfps.io>
|
||||
# SPDX-License-Identifier: (GPL-3.0-only OR LicenseRef-SixtyFPS-commercial)
|
||||
|
||||
Pipfile.lock
|
||||
20
api/cpp/docs/Pipfile
Normal file
20
api/cpp/docs/Pipfile
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# Copyright © 2021 SixtyFPS GmbH <info@sixtyfps.io>
|
||||
# SPDX-License-Identifier: (GPL-3.0-only OR LicenseRef-SixtyFPS-commercial)
|
||||
|
||||
[[source]]
|
||||
name = "pypi"
|
||||
url = "https://pypi.org/simple"
|
||||
verify_ssl = true
|
||||
|
||||
[dev-packages]
|
||||
|
||||
[packages]
|
||||
breathe = "*"
|
||||
sphinx-rtd-theme = "*"
|
||||
sphinx = "*"
|
||||
exhale = "*"
|
||||
myst_parser = "*"
|
||||
sphinx-markdown-tables = "*"
|
||||
|
||||
[requires]
|
||||
python_version = "3.8"
|
||||
14
api/cpp/docs/_static/theme_tweak.css
vendored
Normal file
14
api/cpp/docs/_static/theme_tweak.css
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
.wy-table-responsive table td, .wy-table-responsive table th {
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.wy-table-responsive {
|
||||
margin-bottom: 24px;
|
||||
max-width: 100%;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
img.logo {
|
||||
max-height: 70px;
|
||||
border-radius: 12% !important;
|
||||
}
|
||||
6
api/cpp/docs/_templates/layout.html
vendored
Normal file
6
api/cpp/docs/_templates/layout.html
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{% extends "!layout.html" %}
|
||||
{% block scripts %}
|
||||
{{ super() }}
|
||||
{% include "../../../../docs/resources/sixtyfps-docs-preview.html" %}
|
||||
{% include "../../../../docs/resources/sixtyfps-docs-highlight.html" %}
|
||||
{% endblock %}
|
||||
112
api/cpp/docs/cmake.md
Normal file
112
api/cpp/docs/cmake.md
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
# Installing or Building with CMake
|
||||
|
||||
SixtyFPS comes with a CMake integration that automates the compilation step of the `.60` markup language files and
|
||||
offers a CMake target for convenient linkage.
|
||||
|
||||
*Note*: We recommend using the Ninja generator of CMake for the most efficient build and `.60` dependency tracking.
|
||||
You can select the CMake Ninja backend by passing `-GNinja` or setting the `CMAKE_GENERATOR` environment variable to `Ninja`.
|
||||
|
||||
## Binary Packages
|
||||
|
||||
We also provide binary packages of SixtyFPS for use with C++, which eliminates the need to have Rust installed in your development environment.
|
||||
|
||||
You can download one of our pre-built binaries for Linux or Windows on x86-64 architectures:
|
||||
|
||||
1. Open <https://github.com/sixtyfpsui/sixtyfps/releases>
|
||||
2. Click on the latest release
|
||||
3. From "Assets" download either `sixtyfps-cpp-XXX-Linux-x86_64.tar.gz` for a Linux archive
|
||||
or `sixtyfps-cpp-XXX-win64.exe` for a Windows installer. ("XXX" refers to the version of the latest release)
|
||||
4. Uncompress the downloaded archive or run the installer.
|
||||
|
||||
After extracting the artifact or running the installer, you can place the `lib` sub-directory into your `CMAKE_PREFIX_PATH` and `find_package(SixtyFPS)` should succeed in locating the package.
|
||||
|
||||
In the next section you will learn how to use the installed library in your application
|
||||
and load `.60` UI files.
|
||||
|
||||
## Building from Sources
|
||||
|
||||
The recommended and most flexible way to use the C++ API is to build SixtyFPS from sources.
|
||||
|
||||
First you need to install the prerequisites:
|
||||
|
||||
* Install Rust by following the [Rust Getting Started Guide](https://www.rust-lang.org/learn/get-started). If you already
|
||||
have Rust installed, make sure that it's at least version 1.56 or newer. You can check which version you have installed
|
||||
by running `rustc --version`. Once this is done, you should have the ```rustc``` compiler and the ```cargo``` build system installed in your path.
|
||||
* **[cmake](https://cmake.org/download/)** (3.19 or newer)
|
||||
* A C++ compiler that supports C++20 (e.g., **MSVC 2019 16.6** on Windows)
|
||||
|
||||
You can include SixtyFPS in your CMake project using CMake's [`FetchContent`](https://cmake.org/cmake/help/latest/module/FetchContent.html) feature.
|
||||
Insert the following snippet into your `CMakeLists.txt` to make CMake download the latest release, compile it and make the CMake integration available:
|
||||
|
||||
```cmake
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
SixtyFPS
|
||||
GIT_REPOSITORY https://github.com/sixtyfpsui/sixtyfps.git
|
||||
GIT_TAG v0.1.6
|
||||
SOURCE_SUBDIR api/cpp
|
||||
)
|
||||
FetchContent_MakeAvailable(SixtyFPS)
|
||||
```
|
||||
|
||||
If you prefer to treat SixtyFPS as an external CMake package, then you can also build SixtyFPS from source like a regular
|
||||
CMake project, install it into a prefix directory of your choice and use `find_package(SixtyFPS)` in your `CMakeLists.txt`.
|
||||
|
||||
### Features
|
||||
|
||||
The SixtyFPS run-time library supports different features that can be toggled. You might want to enable a feature that is
|
||||
not enabled by default but that is revelant for you, or you may want to disable a feature that you know you do not need and
|
||||
therefore reduce the size of the resulting library.
|
||||
|
||||
The CMake configure step offers CMake options for various feature that are all prefixed with `SIXTYFPS_FEATURE_`. For example
|
||||
you can enable support for the Wayland windowing system on Linux by enabling the `SIXTYFPS_FEATURE_WAYLAND` feature. There are
|
||||
different ways of toggling CMake options. For example on the command line using the `-D` parameter:
|
||||
|
||||
`cmake -DSIXTYFPS_FEATURE_WAYLAND=ON ...`
|
||||
|
||||
Alternatively, after the configure step you can use `cmake-gui` or `ccmake` on the build directory for a list of all features
|
||||
and their description.
|
||||
|
||||
This works when compiling SixtyFPS as a package, using `cmake --build` and `cmake --install`, or when including SixtyFPS
|
||||
using `FetchContent`.
|
||||
|
||||
### Cross-compiling
|
||||
|
||||
It is possible to cross-compile SixtyFPS to a different target architecture when building with CMake. In order to complete
|
||||
that, you need to make sure that your CMake setup is ready for cross-compilation. You can find more information about
|
||||
how to set this up in the [upstream CMake documentation](https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling).
|
||||
If you are building against a Yocto SDK, it is sufficient to source the SDK's environment setup file.
|
||||
|
||||
Since SixtyFPS is implemented using the Rust programming language, you need to determine which Rust target
|
||||
matches the target architecture that you're compiling to. Please consult the [upstream Rust documentation](https://doc.rust-lang.org/nightly/rustc/platform-support.html) to find the correct target name. Now you need to install the Rust toolchain:
|
||||
|
||||
```sh
|
||||
rustup target add <target-name>
|
||||
```
|
||||
|
||||
Then you're ready to invoke CMake and you need to add `-DRust_CARGO_TARGET=<target name>` to the CMake command line.
|
||||
This ensures that the SixtyFPS library is built for the correct architecture.
|
||||
|
||||
For example if you are building against an embedded Linux Yocto SDK targeting an ARM64 board, the following commands
|
||||
show how to compile:
|
||||
|
||||
Install the Rust targe toolchain once:
|
||||
|
||||
<!-- cSpell:disable -->
|
||||
```sh
|
||||
rustup target add aarch64-unknown-linux-gnu
|
||||
```
|
||||
<!-- cSpell:enable -->
|
||||
|
||||
Set up the environment and build:
|
||||
|
||||
<!-- cSpell:disable -->
|
||||
```sh
|
||||
. /path/to/yocto/sdk/environment-setup-cortexa53-crypto-poky-linux
|
||||
cd sixtyfps
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DRust_CARGO_TARGET=aarch64-unknown-linux-gnu -DCMAKE_INSTALL_PREFIX=/sixtyfps/install/path ..
|
||||
cmake --build .
|
||||
cmake --install .
|
||||
```
|
||||
124
api/cpp/docs/conf.py
Normal file
124
api/cpp/docs/conf.py
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
# Copyright © 2021 SixtyFPS GmbH <info@sixtyfps.io>
|
||||
# SPDX-License-Identifier: (GPL-3.0-only OR LicenseRef-SixtyFPS-commercial)
|
||||
|
||||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# This file only contains a selection of the most common options. For a full
|
||||
# list see the documentation:
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||
|
||||
# -- Path setup --------------------------------------------------------------
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
# import os
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
import textwrap
|
||||
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = "SixtyFPS C++"
|
||||
copyright = "2021, info@sixtyfps.io"
|
||||
author = "info@sixtyfps.io"
|
||||
|
||||
# The full version, including alpha/beta/rc tags
|
||||
version = "0.2.0"
|
||||
|
||||
cpp_index_common_prefix = ["sixtyfps::", "sixtyfps::interpreter::"]
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = ["breathe", "myst_parser", "exhale", "sphinx_markdown_tables"]
|
||||
|
||||
breathe_projects = {"SixtyFPS": "./docs/xml"}
|
||||
breathe_default_project = "SixtyFPS"
|
||||
|
||||
exhale_args = {
|
||||
"containmentFolder": "./api",
|
||||
"rootFileName": "library_root.rst",
|
||||
"rootFileTitle": "C++ API Reference",
|
||||
"afterTitleDescription": textwrap.dedent(
|
||||
"""
|
||||
The following sections present the C++ API Reference. All types are
|
||||
within the :ref:`sixtyfps<namespace_sixtyfps>` namespace and are accessible by including
|
||||
the :code:`sixtyfps.h` header file.
|
||||
|
||||
If you choose to load :code:`.60` files dynamically at run-time, then
|
||||
you can use the classes in :ref:`sixtyfps::interpreter<namespace_sixtyfps__interpreter>`, starting at
|
||||
:cpp:class:`sixtyfps::interpreter::ComponentCompiler`. You need to include
|
||||
the :code:`sixtyfps_interpreter.h` header file.
|
||||
"""
|
||||
),
|
||||
"doxygenStripFromPath": "..",
|
||||
"createTreeView": True,
|
||||
"exhaleExecutesDoxygen": True,
|
||||
"exhaleDoxygenStdin": """INPUT = ../../api/cpp/include generated_include
|
||||
EXCLUDE_SYMBOLS = sixtyfps::cbindgen_private* sixtyfps::private_api* vtable* SIXTYFPS_DECL_ITEM
|
||||
EXCLUDE = ../../api/cpp/include/vtable.h ../../api/sixtyfps-cpp/include/sixtyfps_testing.h
|
||||
ENABLE_PREPROCESSING = YES
|
||||
PREDEFINED += DOXYGEN
|
||||
WARN_AS_ERROR = YES""",
|
||||
}
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ["_templates"]
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This pattern also affects html_static_path and html_extra_path.
|
||||
exclude_patterns = [
|
||||
"_build",
|
||||
"html/_static/collapsible-lists/LICENSE.md",
|
||||
"Thumbs.db",
|
||||
".DS_Store",
|
||||
"markdown/tutorial",
|
||||
"markdown/building.md",
|
||||
"markdown/development.md",
|
||||
"markdown/install_qt.md",
|
||||
"markdown/README.md",
|
||||
"README.md",
|
||||
]
|
||||
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
html_theme = "sphinx_rtd_theme"
|
||||
|
||||
html_theme_options = {"collapse_navigation": False}
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ["_static"]
|
||||
|
||||
html_show_sourcelink = False
|
||||
|
||||
html_logo = "logo.drawio.svg"
|
||||
|
||||
myst_enable_extensions = [
|
||||
"html_image",
|
||||
]
|
||||
|
||||
# Annotate h1/h2 elements with anchors
|
||||
myst_heading_anchors = 2
|
||||
|
||||
rst_epilog = """
|
||||
.. |ListView| replace:: :code:`ListView`
|
||||
.. _ListView: ../markdown/widgets.html#listview
|
||||
.. |Repetition| replace:: :code:`for` - :code:`in`
|
||||
.. _Repetition: ../markdown/langref.html#repetition
|
||||
"""
|
||||
|
||||
|
||||
def setup(app):
|
||||
app.add_css_file("theme_tweak.css")
|
||||
60
api/cpp/docs/cpp_migration.md
Normal file
60
api/cpp/docs/cpp_migration.md
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
# Migrating from Older Versions
|
||||
|
||||
The C++ library is versioned according to the principles of [Semantic Versioning](https://semver.org). We define that the left-most non-zero component of the version is the major version, followed by the minor and optionally patch version. That means releases in the "0.y.z" series treat changes in "y" as a major release, which can contain incompatible API changes, while changes in just "z" are minor. For example the release 0.1.6 is fully backwards compatible to 0.1.5, but it contains new functionality. The release 0.2.0 however is a new major version compared to 0.1.x and may contain API incompatible changes.
|
||||
|
||||
This guide lists all API incompatible changes between major versions and describes how you can migrate your application's source code.
|
||||
|
||||
## Migrating from Version 0.1.x to 0.2.0
|
||||
|
||||
In version 0.2.0 we have increased the minimum version of C++. You need to have a C++ compiler installed that supports C++ 20 or newer.
|
||||
|
||||
If you are building SixtyFPS from source, you need to make sure that your Rust installation is up-to-date. If you have installed Rust using `rustup`, then you can upgrade to the latest Version of Rust by running `rustup update`.
|
||||
|
||||
### Models
|
||||
|
||||
`Model::row_data` returns now a `std::optional<ModelData>` and can thus be used with indices that are out of bounds.
|
||||
|
||||
This also means that `Model`s must handle invalid indices and may not crash when a invalid index is passed in.
|
||||
|
||||
Old code:
|
||||
|
||||
```cpp
|
||||
float value = another_model->row_data(2);
|
||||
do_something(value)
|
||||
```
|
||||
|
||||
New code:
|
||||
|
||||
```cpp
|
||||
// `another_model` is a model that contains floats.
|
||||
std::optional<float> value = another_model->row_data(2);
|
||||
if (value.has_value()) {
|
||||
do_something(*value);
|
||||
} else {
|
||||
// row index 2 is out of bounds
|
||||
}
|
||||
```
|
||||
|
||||
### C++ Interpreter API
|
||||
|
||||
#### Callbacks
|
||||
|
||||
Callbacks declared in `.60` markup can be invoked from C++ using {cpp:func}`sixtyfps::interpreter::ComponentInstance::invoke_callback()` or {cpp:func}`sixtyfps::interpreter::ComponentInstance::invoke_global_callback()`. The arguments to the callback at invocation time used to require the use of `sixtyfps::Slice` type. This was changed to use the C++ 20 [`std::span`](https://en.cppreference.com/w/cpp/container/span) type, for easier passing.
|
||||
|
||||
Old code:
|
||||
|
||||
```cpp
|
||||
sixtyfps::Value args[] = { SharedString("Hello"), 42. };
|
||||
instance->invoke_callback("foo", sixtyfps::Slice{ args, 2 });
|
||||
```
|
||||
|
||||
New code:
|
||||
|
||||
```cpp
|
||||
sixtyfps::Value args[] = { SharedString("Hello"), 42. };
|
||||
instance->invoke_callback("foo", args);
|
||||
```
|
||||
|
||||
#### Models
|
||||
|
||||
The `Value::Type::Array` has been replaced by `Value::Type::Model`
|
||||
122
api/cpp/docs/generated_code.md
Normal file
122
api/cpp/docs/generated_code.md
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
# Generated code
|
||||
|
||||
The SixtyFPS compiler called by the build system will generate a header file for the root `.60`
|
||||
file. This header file will contain a `class` with the same name as the component.
|
||||
|
||||
This class will have the following public member functions:
|
||||
|
||||
* A `create` constructor function and a destructor.
|
||||
* A `show` function, which will show the component on the screen. Note that in order to render
|
||||
and react to user input, it's still necessary to spin the event loop, by calling {cpp:func}`sixtyfps::run_event_loop()`
|
||||
or using the convenience `fun` function in this class.
|
||||
* A `hide` function, which de-registers the component from the windowing system.
|
||||
* A `window` function that provides access to the {cpp:class}`sixtyfps::Window`, allow for further customization
|
||||
towards the windowing system.
|
||||
* A `run` convenience function, which will show the component and starts the event loop.
|
||||
* for each properties:
|
||||
* A getter `get_<property_name>` returning the property type.
|
||||
* A setter `set_<property_name>` taking the new value of the property by const reference
|
||||
* for each callbacks:
|
||||
* `invoke_<callback_name>` function which takes the callback argument as parameter and call the callback.
|
||||
* `on_<callback_name>` function which takes a functor as an argument and sets the callback handler
|
||||
for this callback. the functor must accept the type parameter of the callback
|
||||
* A `global` function, to provide access to any exported global singletons.
|
||||
|
||||
The class is instantiated with the `create` function, which returns the type wrapped in {cpp:class}`sixtyfps::ComponentHandle`.
|
||||
This is a smart pointer that owns the actual instance and keeps it alive as long as at least one {cpp:class}`sixtyfps::ComponentHandle`
|
||||
is in scope, similar to `std::shared_ptr<T>`.
|
||||
|
||||
For more complex UIs it is common to supply data in the form of an abstract data model, that is used with
|
||||
[`for` - `in`](markdown/langref.md#repetition) repetitions or [`ListView`](markdown/widgets.md#listview) elements in the `.60` language.
|
||||
All models in C++ are sub-classes of the {cpp:class}`sixtyfps::Model` and you can sub-class it yourself. For convenience,
|
||||
the {cpp:class}`sixtyfps::VectorModel` provides an implementation that is backed by a `std::vector<T>`.
|
||||
|
||||
## Example
|
||||
|
||||
Let's assume we have this code in our `.60` file
|
||||
|
||||
```60
|
||||
SampleComponent := Window {
|
||||
property<int> counter;
|
||||
property<string> user_name;
|
||||
callback hello;
|
||||
// ... maybe more elements here
|
||||
}
|
||||
```
|
||||
|
||||
This will generate a header with the following contents (edited for documentation purpose)
|
||||
|
||||
```cpp
|
||||
#include <array>
|
||||
#include <limits>
|
||||
#include <sixtyfps.h>
|
||||
|
||||
|
||||
class SampleComponent {
|
||||
public:
|
||||
/// Constructor function
|
||||
inline auto create () -> sixtyfps::ComponentHandle<MainWindow>;
|
||||
/// Destructor
|
||||
inline ~SampleComponent ();
|
||||
|
||||
/// Show this component, and runs the event loop
|
||||
inline void run () const;
|
||||
|
||||
/// Show the window that renders this component. Call `sixtyfps::run_event_loop()`
|
||||
/// to continuously render the contents and react to user input.
|
||||
inline void show () const;
|
||||
|
||||
/// Hide the window that renders this component.
|
||||
inline void hide () const;
|
||||
|
||||
/// Getter for the `counter` property
|
||||
inline int get_counter () const;
|
||||
/// Setter for the `counter` property
|
||||
inline void set_counter (const int &value) const;
|
||||
|
||||
/// Getter for the `user_name` property
|
||||
inline sixtyfps::SharedString get_user_name () const;
|
||||
/// Setter for the `user_name` property
|
||||
inline void set_user_name (const sixtyfps::SharedString &value) const;
|
||||
|
||||
/// Call this function to call the `hello` callback
|
||||
inline void invoke_hello () const;
|
||||
/// Sets the callback handler for the `hello` callback.
|
||||
template<typename Functor> inline void on_hello (Functor && callback_handler) const;
|
||||
|
||||
// Returns a reference to a global singleton that's exported.
|
||||
inline template<typename T>
|
||||
const T &global() const;
|
||||
|
||||
private:
|
||||
/// private fields omitted
|
||||
};
|
||||
```
|
||||
|
||||
## Global Singletons
|
||||
|
||||
In `.60` files it is possible to declare [singletons that are globally available](markdown/langref.md#global-singletons).
|
||||
You can access them from to your C++ code by exporting them and using the `global()` getter function in the
|
||||
C++ class generated for your entry component. Each global singleton creates a class that has getter/setter functions
|
||||
for properties and callbacks, similar to API that's created for your `.60` component, as demonstrated in the previous section.
|
||||
|
||||
For example the following `.60` markup defines a global `Logic` singleton that's also exported:
|
||||
|
||||
```60,ignore
|
||||
export global Logic := {
|
||||
callback to_uppercase(string) -> string;
|
||||
}
|
||||
```
|
||||
|
||||
If this were used together with the `SampleComponent` from the previous section, then you can access it
|
||||
like this:
|
||||
|
||||
```cpp
|
||||
auto app = SampleComponent::create();
|
||||
// ...
|
||||
app->global<Logic>().on_to_uppercase([](SharedString str) -> SharedString {
|
||||
std::string arg(str);
|
||||
std::transform(arg.begin(), arg.end(), arg.begin(), toupper);
|
||||
return SharedString(arg);
|
||||
});
|
||||
```
|
||||
6
api/cpp/docs/genindex.rst
Normal file
6
api/cpp/docs/genindex.rst
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
.. Copyright © SixtyFPS GmbH <info@sixtyfps.io>
|
||||
.. SPDX-License-Identifier: (GPL-3.0-only OR LicenseRef-SixtyFPS-commercial)
|
||||
|
||||
===========
|
||||
Index (C++)
|
||||
===========
|
||||
81
api/cpp/docs/getting_started.md
Normal file
81
api/cpp/docs/getting_started.md
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
# Getting Started
|
||||
|
||||
Once SixtyFPS is built, you can use it in your CMake application or library target in two steps:
|
||||
|
||||
1. Associate the `.60` files that you'd like to use by calling the `sixtyfps_target_60_sources` cmake command. The first parameter is
|
||||
your application (or library) CMake target, and the parameters following are the names of the `.60` files. This will result in the
|
||||
`.60` files to be compiled into C++ source code.
|
||||
2. The generated C++ source code also needs the SixtyFPS run-time library. This dependency is satisfied by linking `SixtyFPS::SixtyFPS`
|
||||
into your target with the `target_link_libraries` command.
|
||||
|
||||
A typical example looks like this:
|
||||
|
||||
```cmake
|
||||
cmake_minimum_required(VERSION 3.19)
|
||||
project(my_application LANGUAGES CXX)
|
||||
|
||||
# Note: Use find_package(SixtyFPS) instead of the following three commands,
|
||||
# if you prefer the package approach.
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
SixtyFPS
|
||||
GIT_REPOSITORY https://github.com/sixtyfpsui/sixtyfps.git
|
||||
GIT_TAG v0.1.6
|
||||
SOURCE_SUBDIR api/cpp
|
||||
)
|
||||
FetchContent_MakeAvailable(SixtyFPS)
|
||||
|
||||
add_executable(my_application main.cpp)
|
||||
sixtyfps_target_60_sources(my_application my_application_ui.60)
|
||||
target_link_libraries(my_application PRIVATE SixtyFPS::SixtyFPS)
|
||||
```
|
||||
|
||||
Suppose `my_application_ui.60` was a "Hello World" like this:
|
||||
|
||||
```60,ignore
|
||||
HelloWorld := Window {
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
|
||||
// Declare an alias that exposes the label's text property to C++
|
||||
property my_label <=> label.text;
|
||||
|
||||
label := Text {
|
||||
y: parent.width / 2;
|
||||
x: parent.x + 200px;
|
||||
text: "Hello, world";
|
||||
color: blue;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
then you can use the following code in you `main` function to show the [`Window`](markdown/builtin_elements.md#window)
|
||||
and change the text:
|
||||
|
||||
```cpp
|
||||
#include "my_application_ui.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
auto hello_world = HelloWorld::create();
|
||||
hello_world->set_my_label("Hello from C++");
|
||||
// Show the window and spin the event loop until the window is closed.
|
||||
hello_world->run();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
This works because the SixtyFPS compiler translated `my_application_ui.60` to C++ code, in the `my_application_ui.h`
|
||||
header file. That generated code has a C++ class that corresponds to the `HelloWorld` element and has API to create
|
||||
the ui, read or write properties or set callbacks. You can learn more about how this API looks like in general in the
|
||||
[](generated_code.md) section.
|
||||
|
||||
## Tutorial
|
||||
|
||||
For an in-depth walk-through, you may be interested in reading our walk-through <a href="../tutorial/cpp">SixtyFPS Memory Game Tutorial Tutorial</a>.
|
||||
It will guide you through the `.60` mark-up language and the C++ API by building a little memory game.
|
||||
|
||||
## Template
|
||||
|
||||
You can clone the [Template Repository](https://github.com/sixtyfpsui/sixtyfps-cpp-template) repository with
|
||||
the code of a minimal C++ application using SixtyFPS that can be used as a starting point to your program.
|
||||
96
api/cpp/docs/index.rst
Normal file
96
api/cpp/docs/index.rst
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
.. Copyright © SixtyFPS GmbH <info@sixtyfps.io>
|
||||
.. SPDX-License-Identifier: (GPL-3.0-only OR LicenseRef-SixtyFPS-commercial)
|
||||
|
||||
.. SixtyFPS C++ documentation master file
|
||||
|
||||
Welcome to SixtyFPS C++'s documentation!
|
||||
========================================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:hidden:
|
||||
:caption: Getting Started
|
||||
|
||||
cmake.md
|
||||
|
||||
First Steps <getting_started.md>
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:hidden:
|
||||
:caption: C++ / .60 Integration
|
||||
|
||||
Overview <overview.md>
|
||||
|
||||
Type Mapping to C++ <types.md>
|
||||
|
||||
Example Generated Code <generated_code.md>
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:hidden:
|
||||
:caption: Reference
|
||||
|
||||
api/library_root
|
||||
|
||||
genindex
|
||||
|
||||
language.rst
|
||||
|
||||
markdown/debugging_techniques.md
|
||||
|
||||
cpp_migration.md
|
||||
|
||||
.. image:: https://github.com/sixtyfpsui/sixtyfps/workflows/CI/badge.svg
|
||||
:target: https://github.com/sixtyfpsui/sixtyfps/actions
|
||||
:alt: GitHub CI Build Status
|
||||
|
||||
.. image:: https://img.shields.io/github/discussions/sixtyfpsui/sixtyfps
|
||||
:target: https://github.com/sixtyfpsui/sixtyfps/discussions
|
||||
:alt: GitHub Discussions
|
||||
|
||||
`SixtyFPS <https://sixtyfps.io/>`_ is a toolkit to efficiently develop fluid graphical user interfaces for any display: embedded devices and desktop applications.
|
||||
SixtyFPS C++ is the C++ API to interact with a SixtyFPS UI from C++.
|
||||
|
||||
The .60 Markup Language
|
||||
=======================
|
||||
|
||||
SixtyFPS comes with a markup language that is specifically designed for user interfaces. This language provides a
|
||||
powerful way to describe graphical elements, their placement, and the flow of data through the different states. It is a familiar syntax to describe the hierarchy
|
||||
of elements and property bindings. Here's the obligatory "Hello World":
|
||||
|
||||
.. code-block:: 60-no-preview
|
||||
|
||||
HelloWorld := Window {
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
|
||||
Text {
|
||||
y: parent.width / 2;
|
||||
x: parent.x + 200px;
|
||||
text: "Hello, world";
|
||||
color: blue;
|
||||
}
|
||||
}
|
||||
|
||||
Check out the `language reference <markdown/langref.html>`_ for more details.
|
||||
|
||||
Architecture
|
||||
============
|
||||
|
||||
An application is composed of the business logic written in C++ and the `.60` user interface design markup, which
|
||||
is compiled to native code.
|
||||
|
||||
.. image:: https://sixtyfps.io/resources/architecture.drawio.svg
|
||||
:alt: Architecture Overview
|
||||
|
||||
Developing
|
||||
==========
|
||||
|
||||
You can create and edit `.60` files using our `SixtyFPS Visual Studio Code Extension <https://marketplace.visualstudio.com/items?itemName=SixtyFPS.sixtyfps-vscode>`_,
|
||||
which features syntax highlighting and live design preview.
|
||||
|
||||
For a quick edit and preview cycle, you can also use the :code:`sixtyfps-viewer` command line tool, which can be installed using :code:`cargo install sixtyfps-viewer`,
|
||||
if you have `Cargo <https://marketplace.visualstudio.com/items?itemName=SixtyFPS.sixtyfps-vscode>`_ installed.
|
||||
|
||||
In the next section you will learn how to install the SixtyFPS C++ library and the CMake build system integration.
|
||||
12
api/cpp/docs/language.rst
Normal file
12
api/cpp/docs/language.rst
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
.. Copyright © SixtyFPS GmbH <info@sixtyfps.io>
|
||||
.. SPDX-License-Identifier: (GPL-3.0-only OR LicenseRef-SixtyFPS-commercial)
|
||||
|
||||
The .60 UI Design Language
|
||||
==========================
|
||||
|
||||
.. toctree::
|
||||
|
||||
Language Reference<markdown/langref.md>
|
||||
markdown/builtin_elements.md
|
||||
markdown/widgets.md
|
||||
markdown/layouting.md
|
||||
3
api/cpp/docs/logo.drawio.svg
Normal file
3
api/cpp/docs/logo.drawio.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 10 KiB |
3
api/cpp/docs/logo.drawio.svg.license
Normal file
3
api/cpp/docs/logo.drawio.svg.license
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
Copyright © SixtyFPS GmbH <info@sixtyfps.io>
|
||||
|
||||
SPDX-License-Identifier: CC-BY-ND-4.0
|
||||
56
api/cpp/docs/overview.md
Normal file
56
api/cpp/docs/overview.md
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
|
||||
# Overview
|
||||
|
||||
The following two sections explain how you can integrate your `.60` designs into your
|
||||
C++ application. The entry point is a `.60` file that contains your primary component
|
||||
that you instantiate from C++.
|
||||
|
||||
There are two ways in that you can instantiate your `.60` designs in your C++ application,
|
||||
either by compiling them ahead of time or by dynamically loading them at run-time.
|
||||
|
||||
Once instantiated you feed data into it, for example by setting properties, populating
|
||||
data models or setting up callbacks that are invoked when the user activates certain elements.
|
||||
|
||||
|
||||
## Compiled `.60` designs
|
||||
|
||||
You can choose to compile a `.60` file to C++, which provides the best performance
|
||||
and lowest memory consumption.
|
||||
|
||||
The `sixtyfps_target_60_sources` cmake command makes the translation automatic
|
||||
and [generated code](generated_code.md) has an API that allows setting and getting
|
||||
property values, etc. That API will use types from the {ref}`sixtyfps <namespace_sixtyfps>`
|
||||
namespace, for example {cpp:class}`sixtyfps::SharedString` or {cpp:class}`sixtyfps::Color`.
|
||||
|
||||
## Run-time interpreted `.60` designs
|
||||
|
||||
Instead of compiling `.60` designs to C++, you can also choose to dynamically load `.60`
|
||||
files at run-time. This is slower than compiling them ahead of time and requires more memory,
|
||||
however it provides more flexibility in your application design.
|
||||
|
||||
The entry point to loading a `.60` file is the {cpp:class}`sixtyfps::interpreter::ComponentCompiler`
|
||||
class in the {ref}`sixtyfps::interpreter <namespace_sixtyfps__interpreter>` namespace.
|
||||
|
||||
With the help of {cpp:class}`sixtyfps::interpreter::ComponentCompiler` you create a {cpp:class}`sixtyfps::interpreter::ComponentDefinition`,
|
||||
which provides you with information about properties and callbacks that are common to all instances. The
|
||||
{cpp:func}`sixtyfps::interpreter::ComponentDefinition::create()` function creates new instances, which
|
||||
are wrapped in {cpp:class}`sixtyfps::ComponentHandle`. This is a smart pointer that owns the actual instance
|
||||
and keeps it alive as long as at least one {cpp:class}`sixtyfps::ComponentHandle` is in scope, similar to `std::shared_ptr<T>`.
|
||||
|
||||
All property values in `.60` are mapped to {cpp:class}`sixtyfps::interpreter::Value` in C++. This is a
|
||||
polymorphic data type that can hold different kinds of values, such as numbers, strings or even data models.
|
||||
|
||||
For more complex UIs it is common to supply data in the form of an abstract data model, that is used with
|
||||
[`for` - `in`](markdown/langref.md#repetition) repetitions or [`ListView`](markdown/widgets.md#listview) elements in the `.60` language.
|
||||
All models in C++ with the interpreter API are sub-classes of the {cpp:class}`sixtyfps::Model` where the template
|
||||
parameter is {cpp:class}`sixtyfps::interpreter::Value`. Therefore to provide your own data model, you can subclass
|
||||
`sixtyfps::Model<sixtyfps::interpreter::Value>`.
|
||||
|
||||
In `.60` files it is possible to declare [singletons that are globally available](markdown/langref.md#global-singletons).
|
||||
You can access them from to your C++ code by exporting them and using the getter and setter functions on
|
||||
{cpp:class}`sixtyfps::interpreter::ComponentInstance` to change properties and callbacks:
|
||||
|
||||
1. {cpp:func}`sixtyfps::interpreter::ComponentInstance::set_global_property()`
|
||||
1. {cpp:func}`sixtyfps::interpreter::ComponentInstance::get_global_property()`
|
||||
1. {cpp:func}`sixtyfps::interpreter::ComponentInstance::set_global_callback()`
|
||||
1. {cpp:func}`sixtyfps::interpreter::ComponentInstance::invoke_global_callback()`
|
||||
43
api/cpp/docs/types.md
Normal file
43
api/cpp/docs/types.md
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
# Type Mappings
|
||||
|
||||
The types used for properties in `.60` design markup each translate to specific types in C++.
|
||||
The follow table summarizes the entire mapping:
|
||||
|
||||
| `.60` Type | C++ Type | Note |
|
||||
| --- | --- | --- |
|
||||
| `int` | `int` | |
|
||||
| `float` | `float` | |
|
||||
| `bool` | `bool` | |
|
||||
| `string` | [`sixtyfps::SharedString`](api/structsixtyfps_1_1_shared_string.html) | A reference-counted string type that uses UTF-8 encoding and can be easily converted to a std::string_view or a const char *. |
|
||||
| `color` | [`sixtyfps::Color`](api/classsixtyfps_1_1_color.html) | |
|
||||
| `brush` | [`sixtyfps::Brush`](api/classsixtyfps_1_1_brush.html) | |
|
||||
| `image` | [`sixtyfps::Image`](api/structsixtyfps_1_1_image.html) | |
|
||||
| `physical_length` | `float` | The unit are physical pixels. |
|
||||
| `length` | `float` | At run-time, logical lengths are automatically translated to physical pixels using the device pixel ratio. |
|
||||
| `duration` | `std::int64_t` | At run-time, durations are always represented as signed 64-bit integers with millisecond precision. |
|
||||
| `angle` | `float` | The value in degrees. |
|
||||
| structure | A `class` of the same name | The order of the data member are in the lexicographic order of their name |
|
||||
|
||||
## Structures
|
||||
|
||||
For user-defined structures in the .60 code, a `class` of the same name is generated with data member
|
||||
in lexicographic order.
|
||||
|
||||
For example, if you have this structure in the .60 file
|
||||
|
||||
```60,ignore
|
||||
export struct MyStruct := {
|
||||
foo: int,
|
||||
bar: string,
|
||||
}
|
||||
```
|
||||
|
||||
It would result in the following type being generated:
|
||||
|
||||
```cpp
|
||||
class MyStruct {
|
||||
public:
|
||||
sixtyfps::SharedString bar;
|
||||
int foo;
|
||||
};
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue