slint 1.4.0

GUI toolkit to efficiently develop fluid graphical user interfaces for embedded devices and desktop applications
Documentation
<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js light">
    <head>
        <!-- Book generated using mdBook -->
        <meta charset="UTF-8">
        <title>Getting Started - SixtyFPS Memory Game Tutorial (C++)</title>
                

        <!-- Custom HTML head -->
        <!--
    This file is used to add syntax highlighting of the `.60` snippets in the generated rustdoc, sphinx and mdbook documentation.
    It can be injected via the `--html-in-header sixtyfps-docs-highlight.html` option of rustdoc, is included via _templates/layout.html
    in sphinx and via head.hbs in mdbook.
-->
<link rel="stylesheet" href="https://sixtyfps.io/resources/highlightjs/11.0.1/default.min.css">
<script src="https://sixtyfps.io/resources/highlightjs/11.0.1/highlight.min.js"></script>
<script>
  hljs.registerLanguage("60", function (hljs) {
    const KEYWORDS = {
      keyword:
        'struct export import signal property animate for in if states transitions parent root self',
      literal:
        'true false',
      built_in:
        'Rectangle Image Text TouchArea Flickable Clip TextInput Window GridLayout Row HorizontalLayout VerticalLayout Path MoveTo LineTo ArcTo CubicTo QuadraticTo Close FocusScope Clip PopupWindow',
      type:
        'bool string int float length logical_length duration resource',
    };

    return {
      name: 'sixtyfps',
      aliases: ['60'],
      case_insensitive: false,
      keywords: KEYWORDS,
      contains: [
        hljs.QUOTE_STRING_MODE,
        hljs.C_LINE_COMMENT_MODE,
        hljs.C_BLOCK_COMMENT_MODE,
        hljs.COMMENT('/\\*', '\\*/', {
          contains: ['self']
        }),
        {
          className: 'number',
          begin: '\\b\\d+(\\.\\d+)?(\\w+)?',
          relevance: 0
        },
        {
          className: 'title',
          begin: '\\b[_a-zA-Z][_\\-a-zA-Z0-9]* *:=',
        },
        {
          className: 'symbol',
          begin: '\\b[_a-zA-Z][_\\-a-zA-Z0-9]*(:| *=>)',
        },
        {
          className: 'built_in',
          begin: '\\b[_a-zA-Z][_\\-a-zA-Z0-9]*!',
        },
      ],
      illegal: /@/
    };
  });

  window.addEventListener("DOMContentLoaded", () => {
    const rustDoc = document.querySelector('meta[name="generator"]')?.content == "rustdoc";
    if (rustDoc) {
      // Only highlight .60 blocks, leave the others to rustdoc
      for (dot60Block of document.querySelectorAll("pre code.language-60")) {
        hljs.highlightElement(dot60Block)
      }

      // Some of the rustdoc selectors require the pre element to have the rust class
      for (codeBlock of document.querySelectorAll(".language-60.hljs")) {
        codeBlock.parentElement.classList.add("rust")
      }

      // Change the hljs generated classes to the rustdoc
      // ones, so that the highlighting adjusts to the theme correctly.
      const highlightJSToRustDoc = [
        ["comment", "comment"],
        ["number", "number"],
        ["symbol", "struct"], // width:
        ["keyword", "kw"],
        ["built_in", "primitive"],
        ["string", "string"],
        ["title", "fnname"], // Foo :=
        ["type", "type"]
      ];

      for ([hljs_class, rustdoc_class] of highlightJSToRustDoc) {
        for (titleElement of document.querySelectorAll(`.hljs-${hljs_class}`)) {
          titleElement.classList.remove(`hljs-${hljs_class}`);
          titleElement.classList.add(rustdoc_class);
        }
      }
    } else {
      // For use with the mdbook Tutorial
      hljs.highlightAll();

      // The Sphinx/my_st generated HTML for code blocks does not use <code> tags, so highlight.js'
      // default selector "pre code" does not match. Let's do it by hand:
      for (block of document.querySelectorAll("div.highlight-60 div.highlight pre, div.highlight-60-no-preview div.highlight pre")) {
        hljs.highlightElement(block)
      }
    }
  });
</script>

        <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="theme-color" content="#ffffff" />

                <link rel="icon" href="favicon.svg">
                        <link rel="shortcut icon" href="favicon.png">
                <link rel="stylesheet" href="css/variables.css">
        <link rel="stylesheet" href="css/general.css">
        <link rel="stylesheet" href="css/chrome.css">
                <link rel="stylesheet" href="css/print.css" media="print">
        
        <!-- Fonts -->
        <link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
                <link rel="stylesheet" href="fonts/fonts.css">
        
        <!-- Highlight.js Stylesheets -->
        <link rel="stylesheet" href="highlight.css">
        <link rel="stylesheet" href="tomorrow-night.css">
        <link rel="stylesheet" href="ayu-highlight.css">

        <!-- Custom theme stylesheets -->
        
            </head>
    <body>
        <!-- Provide site root to javascript -->
        <script type="text/javascript">
            var path_to_root = "";
            var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
        </script>

        <!-- Work around some values being stored in localStorage wrapped in quotes -->
        <script type="text/javascript">
            try {
                var theme = localStorage.getItem('mdbook-theme');
                var sidebar = localStorage.getItem('mdbook-sidebar');

                if (theme.startsWith('"') && theme.endsWith('"')) {
                    localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
                }

                if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
                    localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
                }
            } catch (e) { }
        </script>

        <!-- Set the theme before any content is loaded, prevents flash -->
        <script type="text/javascript">
            var theme;
            try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
            if (theme === null || theme === undefined) { theme = default_theme; }
            var html = document.querySelector('html');
            html.classList.remove('no-js')
            html.classList.remove('light')
            html.classList.add(theme);
            html.classList.add('js');
        </script>

        <!-- Hide / unhide sidebar before it is displayed -->
        <script type="text/javascript">
            var html = document.querySelector('html');
            var sidebar = 'hidden';
            if (document.body.clientWidth >= 1080) {
                try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
                sidebar = sidebar || 'visible';
            }
            html.classList.remove('sidebar-visible');
            html.classList.add("sidebar-" + sidebar);
        </script>

        <nav id="sidebar" class="sidebar" aria-label="Table of contents">
            <div class="sidebar-scrollbox">
                <ol class="chapter"><li class="chapter-item expanded "><a href="introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li class="chapter-item expanded "><a href="getting_started.html" class="active"><strong aria-hidden="true">2.</strong> Getting Started</a></li><li class="chapter-item expanded "><a href="memory_tile.html"><strong aria-hidden="true">3.</strong> Memory Tile</a></li><li class="chapter-item expanded "><a href="polishing_the_tile.html"><strong aria-hidden="true">4.</strong> Polishing the Tile</a></li><li class="chapter-item expanded "><a href="from_one_to_multiple_tiles.html"><strong aria-hidden="true">5.</strong> From One To Multiple Tiles</a></li><li class="chapter-item expanded "><a href="creating_the_tiles_from_cpp.html"><strong aria-hidden="true">6.</strong> Creating The Tiles From C++</a></li><li class="chapter-item expanded "><a href="game_logic_in_cpp.html"><strong aria-hidden="true">7.</strong> Game Logic In C++</a></li><li class="chapter-item expanded "><a href="ideas_for_the_reader.html"><strong aria-hidden="true">8.</strong> Ideas For The Reader</a></li><li class="chapter-item expanded "><a href="conclusion.html"><strong aria-hidden="true">9.</strong> Conclusion</a></li></ol>            </div>
            <div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
        </nav>

        <div id="page-wrapper" class="page-wrapper">

            <div class="page">
                
                <div id="menu-bar-hover-placeholder"></div>
                <div id="menu-bar" class="menu-bar sticky bordered">
                    <div class="left-buttons">
                        <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
                            <i class="fa fa-bars"></i>
                        </button>
                        <button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
                            <i class="fa fa-paint-brush"></i>
                        </button>
                        <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
                            <li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
                        </ul>
                                                <button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
                            <i class="fa fa-search"></i>
                        </button>
                                            </div>

                    <h1 class="menu-title">SixtyFPS Memory Game Tutorial (C++)</h1>

                    <div class="right-buttons">
                                                <a href="print.html" title="Print this book" aria-label="Print this book">
                            <i id="print-button" class="fa fa-print"></i>
                        </a>
                                                                        
                    </div>
                </div>

                                <div id="search-wrapper" class="hidden">
                    <form id="searchbar-outer" class="searchbar-outer">
                        <input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
                    </form>
                    <div id="searchresults-outer" class="searchresults-outer hidden">
                        <div id="searchresults-header" class="searchresults-header"></div>
                        <ul id="searchresults">
                        </ul>
                    </div>
                </div>
                
                <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
                <script type="text/javascript">
                    document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
                    document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
                    Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
                        link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
                    });
                </script>

                <div id="content" class="content">
                    <main>
                        <h1 id="getting-started"><a class="header" href="#getting-started">Getting Started</a></h1>
<p>In this tutorial, we use C++ as the host programming language. We also support other programming languages like
<a href="https://sixtyfps.io/docs/rust/sixtyfps/">Rust</a> or <a href="https://sixtyfps.io/docs/node/">JavaScript</a>.</p>
<p>You will need a development environment that can compile C++17 with CMake 3.16.
We do not provide binaries of SixtyFPS yet, so we will use the CMake integration that will automatically build
the tools and library from source. Since it is implemented in the Rust programming language, this means that
you also need to install a Rust compiler (1.48). You can easily install a Rust compiler
following the instruction from <a href="https://www.rust-lang.org/learn/get-started">the Rust website</a>.
We are going to use <code>cmake</code>'s builtin FetchContent module to fetch the source code of SixtyFPS.</p>
<p>In a new directory, we create a new <code>CMakeLists.txt</code> file.</p>
<pre><code class="language-cmake"># CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(memory LANGUAGES CXX)

include(FetchContent)
FetchContent_Declare(
    SixtyFPS
    GIT_REPOSITORY https://github.com/sixtyfpsui/sixtyfps.git
    GIT_TAG v0.0.6
    SOURCE_SUBDIR api/sixtyfps-cpp
)
FetchContent_MakeAvailable(SixtyFPS)

add_executable(memory_game main.cpp)
target_link_libraries(memory_game PRIVATE SixtyFPS::SixtyFPS)
sixtyfps_target_60_sources(memory_game memory.60)
</code></pre>
<p>This should look familiar to people familiar with CMake. We see that this CMakeLists.txt
references a <code>main.cpp</code>, which we will add later, and it also has a line
<code>sixtyfps_target_60_sources(memory_game memory.60)</code>, which is a SixtyFPS function used to
add the <code>memory.60</code> file to the target. We must then create, in the same directory,
the <code>memory.60</code> file. Let's just fill it with a hello world for now:</p>
<pre><code class="language-60">// memory.60
MainWindow := Window {
    Text {
        text: &quot;hello world&quot;;
        color: green;
    }
}
</code></pre>
<p>What's still missing is the <code>main.cpp</code>:</p>
<pre><code class="language-cpp">// main.cpp

#include &quot;memory.h&quot; // generated header from memory.60

int main()
{
    auto main_window = MainWindow::create();
    main_window-&gt;run();
}
</code></pre>
<p>To recap, we now have a directory with a <code>CMakeLists.txt</code>, <code>memory.60</code> and <code>main.cpp</code>.</p>
<p>We can now compile and run this program:</p>
<pre><code class="language-sh">cmake -GNinja .
cmake --build .
./memory_game
</code></pre>
<p>and a window will appear with the green &quot;Hello World&quot; greeting.</p>
<p><img src="https://sixtyfps.io/blog/memory-game-tutorial/getting-started.png" alt="Screenshot of initial tutorial app showing Hello World" title="Hello World" /></p>
<p>Feel free to use your favorite IDE for this purpose, or use out-of-tree build, or Ninja, ...
We just keep it simple here for the purpose of this blog.</p>
<p><em>Note</em>: When configuring with CMake, the FetchContent module will fetch the source code of SixtyFPS via git.
this may take some time. When building for the first time, the first thing that need to be build
is the SixtyFPS runtime and compiler, this can take a few minutes.</p>

                    </main>

                    <nav class="nav-wrapper" aria-label="Page navigation">
                        <!-- Mobile navigation buttons -->
                                                    <a rel="prev" href="introduction.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                                <i class="fa fa-angle-left"></i>
                            </a>
                        
                                                    <a rel="next" href="memory_tile.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                                <i class="fa fa-angle-right"></i>
                            </a>
                        
                        <div style="clear: both"></div>
                    </nav>
                </div>
            </div>

            <nav class="nav-wide-wrapper" aria-label="Page navigation">
                                    <a rel="prev" href="introduction.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                        <i class="fa fa-angle-left"></i>
                    </a>
                
                                    <a rel="next" href="memory_tile.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                        <i class="fa fa-angle-right"></i>
                    </a>
                            </nav>

        </div>

        
        
        
                <script type="text/javascript">
            window.playground_copyable = true;
        </script>
        
        
                <script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="mark.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="searcher.js" type="text/javascript" charset="utf-8"></script>
        
        <script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="highlight.js" type="text/javascript" charset="utf-8"></script>
        <script src="book.js" type="text/javascript" charset="utf-8"></script>

        <!-- Custom JS scripts -->
        
        
    </body>
</html>