Skip to content

Commit

Permalink
Refactoring: define macro rules to group builtin structs
Browse files Browse the repository at this point in the history
apply new macro for struct declaration, type register,
doc generation, cpp header generation, struct-value conversion.
  • Loading branch information
darknight authored and ogoffart committed Aug 3, 2023
1 parent 3e79b69 commit 37488f0
Show file tree
Hide file tree
Showing 15 changed files with 483 additions and 254 deletions.
2 changes: 2 additions & 0 deletions api/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,8 @@ set(generated_headers
${CMAKE_CURRENT_BINARY_DIR}/generated_include/slint_internal.h
${CMAKE_CURRENT_BINARY_DIR}/generated_include/slint_enums_internal.h
${CMAKE_CURRENT_BINARY_DIR}/generated_include/slint_enums.h
${CMAKE_CURRENT_BINARY_DIR}/generated_include/slint_builtin_structs_internal.h
${CMAKE_CURRENT_BINARY_DIR}/generated_include/slint_builtin_structs.h
${CMAKE_CURRENT_BINARY_DIR}/generated_include/slint_string_internal.h
${CMAKE_CURRENT_BINARY_DIR}/generated_include/slint_brush_internal.h
${CMAKE_CURRENT_BINARY_DIR}/generated_include/slint_sharedvector_internal.h
Expand Down
93 changes: 78 additions & 15 deletions api/cpp/cbindgen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use std::path::{Path, PathBuf};

fn enums(path: &Path) -> anyhow::Result<()> {
let mut enums_priv = std::fs::File::create(path.join("slint_enums_internal.h"))
.context("Error creating slint_internal_enums.h file")?;
.context("Error creating slint_enums_internal.h file")?;
writeln!(enums_priv, "#pragma once")?;
writeln!(enums_priv, "// This file is auto-generated from {}", file!())?;
writeln!(enums_priv, "#include \"slint_enums.h\"")?;
Expand Down Expand Up @@ -80,6 +80,81 @@ namespace slint::platform::key_codes {{
Ok(())
}

fn builtin_structs(path: &Path) -> anyhow::Result<()> {
let mut structs_pub = std::fs::File::create(path.join("slint_builtin_structs.h"))
.context("Error creating slint_builtin_structs.h file")?;
writeln!(structs_pub, "#pragma once")?;
writeln!(structs_pub, "// This file is auto-generated from {}", file!())?;
writeln!(structs_pub, "namespace slint {{")?;

let mut structs_priv = std::fs::File::create(path.join("slint_builtin_structs_internal.h"))
.context("Error creating slint_builtin_structs_internal.h file")?;
writeln!(structs_priv, "#pragma once")?;
writeln!(structs_priv, "// This file is auto-generated from {}", file!())?;
writeln!(structs_priv, "#include \"slint_builtin_structs.h\"")?;
writeln!(structs_priv, "#include \"slint_enums_internal.h\"")?;
writeln!(structs_priv, "namespace slint::cbindgen_private {{")?;
writeln!(structs_priv, "enum class KeyEventType;")?;
macro_rules! struct_file {
(StandardListViewItem) => {{
writeln!(structs_priv, "using slint::StandardListViewItem;")?;
&mut structs_pub
}};
($_:ident) => {
&mut structs_priv
};
}
macro_rules! print_structs {
($(
$(#[doc = $struct_doc:literal])*
$(#[non_exhaustive])?
$(#[derive(Copy, Eq)])?
struct $Name:ident {
@name = $inner_name:literal
export {
$( $(#[doc = $pub_doc:literal])* $pub_field:ident : $pub_type:ty, )*
}
private {
$( $(#[doc = $pri_doc:literal])* $pri_field:ident : $pri_type:ty, )*
}
}
)*) => {
$(
let file = struct_file!($Name);
$(writeln!(file, "///{}", $struct_doc)?;)*
writeln!(file, "struct {} {{", stringify!($Name))?;
$(
$(writeln!(file, " ///{}", $pub_doc)?;)*
let pub_type = match stringify!($pub_type) {
"i32" => "int32_t",
"f32" | "Coord" => "float",
other => other,
};
writeln!(file, " {} {};", pub_type, stringify!($pub_field))?;
)*
$(
$(writeln!(file, " ///{}", $pri_doc)?;)*
let pri_type = match stringify!($pri_type) {
"usize" => "uintptr_t",
"crate::animations::Instant" => "uint64_t",
other => other,
};
writeln!(file, " {} {};", pri_type, stringify!($pri_field))?;
)*
writeln!(file, " /// \\private")?;
writeln!(file, " {}", format!("friend bool operator==(const {name}&, const {name}&) = default;", name = stringify!($Name)))?;
writeln!(file, " /// \\private")?;
writeln!(file, " {}", format!("friend bool operator!=(const {name}&, const {name}&) = default;", name = stringify!($Name)))?;
writeln!(file, "}};")?;
)*
};
}
i_slint_common::for_each_builtin_structs!(print_structs);
writeln!(structs_priv, "}}")?;
writeln!(structs_pub, "}}")?;
Ok(())
}

fn ensure_cargo_rerun_for_crate(
crate_dir: &Path,
dependencies: &mut Vec<PathBuf>,
Expand Down Expand Up @@ -308,11 +383,6 @@ fn gen_corelib(

let mut properties_config = config.clone();
properties_config.export.exclude.clear();
properties_config.export.include.push("StateInfo".into());
properties_config
.export
.pre_body
.insert("StateInfo".to_owned(), " using Instant = uint64_t;".into());
properties_config.structure.derive_eq = true;
properties_config.structure.derive_neq = true;
private_exported_types.extend(properties_config.export.include.iter().cloned());
Expand Down Expand Up @@ -467,10 +537,6 @@ fn gen_corelib(
public_config.export.exclude = private_exported_types.into_iter().collect();
public_config.export.exclude.push("Point".into());
public_config.export.include = public_exported_types.into_iter().map(str::to_string).collect();
public_config.export.body.insert(
"StandardListViewItem".to_owned(),
"/// \\private\nfriend bool operator==(const StandardListViewItem&, const StandardListViewItem&) = default;".into(),
);
public_config.export.body.insert(
"Rgb8Pixel".to_owned(),
"/// \\private\nfriend bool operator==(const Rgb8Pixel&, const Rgb8Pixel&) = default;"
Expand Down Expand Up @@ -538,16 +604,11 @@ fn gen_corelib(
friend inline LayoutInfo operator+(const LayoutInfo &a, const LayoutInfo &b) { return a.merge(b); }
friend bool operator==(const LayoutInfo&, const LayoutInfo&) = default;".into(),
);
config.export.body.insert(
"TableColumn".to_owned(),
"friend bool operator==(const TableColumn&, const TableColumn&) = default;".into(),
);
config
.export
.body
.insert("Flickable".to_owned(), " inline Flickable(); inline ~Flickable();".into());
config.export.pre_body.insert("FlickableDataBox".to_owned(), "struct FlickableData;".into());
config.export.include.push("TableColumn".into());
cbindgen::Builder::new()
.with_config(config)
.with_src(crate_dir.join("lib.rs"))
Expand All @@ -564,6 +625,7 @@ fn gen_corelib(
.with_include("slint_generated_public.h")
.with_include("slint_enums_internal.h")
.with_include("slint_point.h")
.with_include("slint_builtin_structs_internal.h")
.with_after_include(
r"
namespace slint {
Expand Down Expand Up @@ -798,6 +860,7 @@ pub fn gen_all(
std::fs::create_dir_all(include_dir).context("Could not create the include directory")?;
let mut deps = Vec::new();
enums(include_dir)?;
builtin_structs(include_dir)?;
gen_corelib(root_dir, include_dir, &mut deps, enabled_features)?;
gen_backend_qt(root_dir, include_dir, &mut deps)?;
gen_backend(root_dir, include_dir, &mut deps)?;
Expand Down
1 change: 1 addition & 0 deletions api/cpp/include/slint_properties.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ struct PropertyAnimation;
}

#include "slint_properties_internal.h"
#include "slint_builtin_structs_internal.h"

namespace slint::private_api {

Expand Down
65 changes: 0 additions & 65 deletions docs/language/src/builtins/structs.md

This file was deleted.

140 changes: 140 additions & 0 deletions internal/common/builtin_structs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
// Copyright © SixtyFPS GmbH <info@slint.dev>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-1.1 OR LicenseRef-Slint-commercial

//! This module contains all builtin structures exposed in the .slint language.

/// Call a macro with every builtin structures exposed in the .slint language
///
/// ## Example
/// ```rust
/// macro_rules! print_builtin_structs {
/// ($(
/// $(#[$struct_attr:meta])*
/// struct $Name:ident {
/// @name = $inner_name:literal
/// export {
/// $( $(#[$pub_attr:meta])* $pub_field:ident : $pub_type:ty, )*
/// }
/// private {
/// $( $(#[$pri_attr:meta])* $pri_field:ident : $pri_type:ty, )*
/// }
/// }
/// )*) => {
/// $(println!("{} => export:[{}] private:[{}]", stringify!($Name), stringify!($($pub_field),*), stringify!($($pri_field),*));)*
/// };
/// }
/// i_slint_common::for_each_builtin_structs!(print_builtin_structs);
/// ```
#[macro_export]
macro_rules! for_each_builtin_structs {
($macro:ident) => {
$macro![
/// KeyboardModifier provides booleans to indicate possible modifier keys on a keyboard, such as Shift, Control, etc.
/// This structure is generated as part of `KeyEvent`
/// On macOS, the command key is mapped to the meta modifier.
/// On Windows, the windows key is mapped to the meta modifier.
#[derive(Copy, Eq)]
struct KeyboardModifiers {
@name = "slint::private_api::KeyboardModifiers"
export {
/// Indicates the alt key on a keyboard.
alt: bool,
/// Indicates the control key on a keyboard.
control: bool,
/// Indicates the shift key on a keyboard.
shift: bool,
/// Indicates the command key on macos.
meta: bool,
}
private {
}
}

/// Represents a Pointer event sent by the windowing system.
/// This structure is generated and passed to the `pointer-event` callback of the `TouchArea` element.
struct PointerEvent {
@name = "slint::private_api::PointerEvent"
export {
/// The button that was pressed or released
button: PointerEventButton,
/// The kind of the event
kind: PointerEventKind,
/// The keyboard modifiers pressed during the event
modifiers: KeyboardModifiers,
}
private {
}
}

/// This structure is generated and passed to the key press and release callbacks of the `FocusScope` element.
struct KeyEvent {
@name = "slint::private_api::KeyEvent"
export {
/// The unicode representation of the key pressed.
text: SharedString,
/// The keyboard modifiers active at the time of the key press event.
modifiers: KeyboardModifiers,
}
private {
/// Indicates whether the key was pressed or released
event_type: KeyEventType,
/// If the event type is KeyEventType::UpdateComposition, then this field specifies
/// the start of the selection as byte offsets within the preedit text.
preedit_selection_start: usize,
/// If the event type is KeyEventType::UpdateComposition, then this field specifies
/// the end of the selection as byte offsets within the preedit text.
preedit_selection_end: usize,
}
}

/// Represents an item in a StandardListView and a StandardTableView. This is the Rust/C++ type for
/// the StandardListViewItem type in Slint files, when declaring for example a `property <[StandardListViewItem]> my-list-view-model;`.
#[non_exhaustive]
struct StandardListViewItem {
@name = "slint::StandardListViewItem"
export {
/// The text content of the item
text: SharedString,
}
private {
}
}

/// This is used to define the column and the column header of a TableView
#[non_exhaustive]
struct TableColumn {
@name = "TableColumn"
export {
/// The title of the column header
title: SharedString,
/// The minimum column width (logical length)
min_width: Coord,
/// The horizontal column stretch
horizontal_stretch: f32,
/// Sorts the column
sort_order: SortOrder,
/// the actual width of the column (logical length)
width: Coord,
}
private {
}
}

/// Value of the state property
/// A state is just the current state, but also has information about the previous state and the moment it changed
struct StateInfo {
@name = "slint::private_api::StateInfo"
export {
/// The current state value
current_state: i32,
/// The previous state
previous_state: i32,
}
private {
/// The instant in which the state changed last
change_time: crate::animations::Instant,
}
}
];
};
}
1 change: 1 addition & 0 deletions internal/common/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#![doc(html_logo_url = "https://slint.dev/logo/slint-logo-square-light.svg")]
#![cfg_attr(not(feature = "shared-fontdb"), no_std)]

pub mod builtin_structs;
pub mod enums;
pub mod key_codes;

Expand Down
Loading

0 comments on commit 37488f0

Please sign in to comment.