[reorg]: Move api/sixtyfps-rs/sixtyfps-* into api/rs

This commit is contained in:
Tobias Hunger 2022-01-31 14:06:41 +01:00 committed by Tobias Hunger
parent 2813441cd9
commit 842f75e653
95 changed files with 65 additions and 72 deletions

4
api/cpp/docs/.gitignore vendored Normal file
View 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
View 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
View 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
View 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
View 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
View 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")

View 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`

View 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);
});
```

View file

@ -0,0 +1,6 @@
.. Copyright © SixtyFPS GmbH <info@sixtyfps.io>
.. SPDX-License-Identifier: (GPL-3.0-only OR LicenseRef-SixtyFPS-commercial)
===========
Index (C++)
===========

View 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
View 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
View 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

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 10 KiB

View 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
View 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
View 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;
};
```