Declare .slint enum in one place in i-slint-common

This avoid repeating the enums both in the compiler and in
the runtime library, and register them in a bunch of other places.

So it should be easier to add enums and enum values

Since cbindgen doesn't see through the macro, generate the enum
manually
This commit is contained in:
Olivier Goffart 2022-04-14 19:17:48 +02:00 committed by GitHub
parent 5a270313d2
commit e85e69fda0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 366 additions and 520 deletions

View file

@ -141,6 +141,7 @@ endforeach()
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_string_internal.h
${CMAKE_CURRENT_BINARY_DIR}/generated_include/slint_brush_internal.h
${CMAKE_CURRENT_BINARY_DIR}/generated_include/slint_sharedvector_internal.h

View file

@ -44,3 +44,4 @@ slint-interpreter = { version = "=0.2.2", path="../../internal/interpreter", def
anyhow = "1.0"
cbindgen = "0.21"
proc-macro2 = "1.0.11"
i-slint-common = { version = "=0.2.2", path="../../internal/common" }

View file

@ -2,11 +2,36 @@
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
use anyhow::Context;
use std::io::Write;
use std::iter::Extend;
use std::path::{Path, PathBuf};
// cSpell: ignore compat constexpr corelib deps sharedvector pathdata
fn enums(path: &Path) -> anyhow::Result<()> {
let mut enums =
std::fs::File::create(path).context("Error creating slint_internal_enums.h file")?;
writeln!(enums, "#pragma once")?;
writeln!(enums, "// This file is auto-generated from {}", file!())?;
writeln!(enums, "namespace slint::cbindgen_private {{")?;
macro_rules! print_enums {
($( $(#[doc = $enum_doc:literal])* enum $Name:ident { $( $(#[doc = $value_doc:literal])* $Value:ident,)* })*) => {
$(
$(writeln!(enums, "///{}", $enum_doc)?;)*
writeln!(enums, "enum class {} {{", stringify!($Name))?;
$(
$(writeln!(enums, " ///{}", $value_doc)?;)*
writeln!(enums, " {},", i_slint_common::enums::cpp_escape_keyword(stringify!($Value).trim_start_matches("r#")))?;
)*
writeln!(enums, "}};")?;
)*
}
}
i_slint_common::for_each_enums!(print_enums);
writeln!(enums, "}}")?;
Ok(())
}
fn ensure_cargo_rerun_for_crate(
crate_dir: &Path,
dependencies: &mut Vec<PathBuf>,
@ -314,6 +339,7 @@ fn gen_corelib(
// .with_src(crate_dir.join("input.rs"))
.with_src(crate_dir.join("item_rendering.rs"))
.with_src(crate_dir.join("window.rs"))
.with_include("slint_enums_internal.h")
.generate()
.with_context(|| format!("Unable to generate bindings for {}", internal_header))?
.write_to_file(include_dir.join(internal_header));
@ -399,6 +425,7 @@ fn gen_corelib(
.with_include("slint_pathdata.h")
.with_include("slint_brush.h")
.with_include("slint_generated_public.h")
.with_include("slint_enums_internal.h")
.with_after_include(
r"
namespace slint {
@ -594,6 +621,7 @@ pub fn gen_all(root_dir: &Path, include_dir: &Path) -> anyhow::Result<Vec<PathBu
proc_macro2::fallback::force(); // avoid a abort if panic=abort is set
std::fs::create_dir_all(include_dir).context("Could not create the include directory")?;
let mut deps = Vec::new();
enums(&include_dir.join("slint_enums_internal.h"))?;
gen_corelib(root_dir, include_dir, &mut deps)?;
gen_backend_qt(root_dir, include_dir, &mut deps)?;
gen_backend_selector(root_dir, include_dir, &mut deps)?;

View file

@ -6,19 +6,15 @@
#include <string_view>
#include "slint_pathdata_internal.h"
// The C++ code generator assumes that enums are in the cbindgen_private namespace
namespace slint::cbindgen_private {
using cbindgen_private::types::PathEvent;
}
namespace slint::private_api {
using cbindgen_private::types::PathArcTo;
using cbindgen_private::types::PathCubicTo;
using cbindgen_private::types::PathElement;
using cbindgen_private::types::PathEvent;
using cbindgen_private::types::PathLineTo;
using cbindgen_private::types::PathMoveTo;
using cbindgen_private::types::PathQuadraticTo;
using cbindgen_private::types::Point;
using cbindgen_private::PathEvent;
struct PathData
{

189
internal/common/enums.rs Normal file
View file

@ -0,0 +1,189 @@
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
//! This module contains all enums exposed in the .slint language.
/// Call a macro with every enum exposed in the .slint language
///
/// ## Example
/// ```rust
/// macro_rules! print_enums {
/// ($( $(#[$enum_doc:meta])* enum $Name:ident { $( $(#[$value_doc:meta])* $Value:ident,)* })*) => {
/// $(println!("{} => [{}]", stringify!($Name), stringify!($($Value),*));)*
/// }
/// }
/// i_slint_common::for_each_enums!(print_enums);
/// ```
// NOTE: the documentation for .slint enum is in builtin_elements.md
#[macro_export]
macro_rules! for_each_enums {
($macro:ident) => {
$macro![
enum StandardButtonKind {
ok,
cancel,
apply,
close,
reset,
help,
yes,
no,
abort,
retry,
ignore,
}
enum DialogButtonRole {
none,
accept,
reject,
apply,
reset,
action,
help,
}
enum PointerEventKind {
cancel,
down,
up,
}
enum PointerEventButton {
none,
left,
right,
middle,
}
enum MouseCursor {
default,
none,
//context_menu,
help,
pointer,
progress,
wait,
//cell,
crosshair,
text,
//vertical_text,
alias,
copy,
r#move,
no_drop,
not_allowed,
grab,
grabbing,
//all_scroll,
col_resize,
row_resize,
n_resize,
e_resize,
s_resize,
w_resize,
ne_resize,
nw_resize,
se_resize,
sw_resize,
ew_resize,
ns_resize,
nesw_resize,
nwse_resize,
//zoom_in,
//zoom_out,
}
enum ImageFit {
fill,
contain,
cover,
}
enum ImageRendering {
smooth,
pixelated,
}
enum FillRule {
nonzero,
evenodd,
}
/// This enum defines the input type in a text input which for now only distinguishes a normal
/// input from a password input
enum InputType {
/// This type is used for a normal text input
text,
/// This type is used for password inputs where the characters are represented as *'s
password,
}
enum TextHorizontalAlignment {
left,
center,
right,
}
enum TextVerticalAlignment {
top,
center,
bottom,
}
enum TextWrap {
no_wrap,
word_wrap,
}
enum TextOverflow {
clip,
elide,
}
/// Enum representing the alignment property of a BoxLayout or HorizontalLayout
enum LayoutAlignment {
stretch,
center,
start,
end,
space_between,
space_around,
}
/// PathEvent is a low-level data structure describing the composition of a path. Typically it is
/// generated at compile time from a higher-level description, such as SVG commands.
enum PathEvent {
/// The beginning of the path.
begin,
/// A straight line on the path.
line,
/// A quadratic bezier curve on the path.
quadratic,
/// A cubic bezier curve on the path.
cubic,
/// The end of the path that remains open.
end_open,
/// The end of a path that is closed.
end_closed,
}
/// What is returned from the event handler
enum EventResult {
reject,
accept,
}
/// This enum defines the different kinds of key events that can happen.
enum KeyEventType {
/// A key on a keyboard was pressed.
KeyPressed,
/// A key on a keyboard was released.
KeyReleased,
}
];
};
}
/// add an underscore to a C++ keyword used as an enum
pub fn cpp_escape_keyword(kw: &str) -> &str {
match kw {
"default" => "default_",
other => other,
}
}

View file

@ -1,10 +1,10 @@
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
// This module is meant to be included by different crate and each crate must define the macro for_each_keys
// The key code comes from https://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/CORPCHAR.TXT
// the names comes should match with https://www.w3.org/TR/uievents-key/#named-key-attribute-values,
//! This module is meant to be included by different crate and each crate must define the macro for_each_keys
//!
//! The key code comes from https://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/CORPCHAR.TXT
//! the names comes should match with https://www.w3.org/TR/uievents-key/#named-key-attribute-values,
// NOTE: Update builtin_elements.md when changing/adding/removing keys, to keep the docs in sync!
#[macro_export]

View file

@ -5,4 +5,5 @@
#![doc(html_logo_url = "https://slint-ui.com/logo/slint-logo-square-light.svg")]
#![no_std]
pub mod enums;
pub mod key_codes;

View file

@ -2184,7 +2184,11 @@ fn compile_expression(expr: &llr::Expression, ctx: &EvaluationContext) -> String
)
}
Expression::EnumerationValue(value) => {
format!("slint::cbindgen_private::{}::{}", value.enumeration.name, ident(&value.to_string()))
format!(
"slint::cbindgen_private::{}::{}",
value.enumeration.name,
ident(i_slint_common::enums::cpp_escape_keyword(&value.to_string())),
)
}
Expression::ReturnStatement(Some(expr)) => format!(
"throw slint::private_api::ReturnWrapper<{}>({})",

View file

@ -499,7 +499,7 @@ fn solve_layout(
if let (Some(button_roles), Orientation::Horizontal) = (&layout.dialog_button_roles, o)
{
let cells_ty = cells.ty(ctx);
let e = crate::typeregister::DIALOG_BUTTON_ROLE_ENUM.with(|e| e.clone());
let e = crate::typeregister::BUILTIN_ENUMS.with(|e| e.DialogButtonRole.clone());
let roles = button_roles
.iter()
.map(|r| {
@ -569,8 +569,8 @@ fn solve_layout(
("padding", padding.ty(ctx), padding),
(
"alignment",
crate::typeregister::LAYOUT_ALIGNMENT_ENUM
.with(|e| Type::Enumeration(e.clone())),
crate::typeregister::BUILTIN_ENUMS
.with(|e| Type::Enumeration(e.LayoutAlignment.clone())),
bld.alignment,
),
("cells", bld.cells.ty(ctx), bld.cells),
@ -661,7 +661,7 @@ fn box_layout_data(
let alignment = if let Some(expr) = &layout.geometry.alignment {
llr_Expression::PropertyReference(ctx.map_property_reference(expr))
} else {
let e = crate::typeregister::LAYOUT_ALIGNMENT_ENUM.with(|e| e.clone());
let e = crate::typeregister::BUILTIN_ENUMS.with(|e| e.LayoutAlignment.clone());
llr_Expression::EnumerationValue(EnumerationValue {
value: e.default_value,
enumeration: e,

View file

@ -120,7 +120,7 @@ pub fn compile_paths(
fn compile_path_from_string_literal(commands: &str) -> Option<BindingExpression> {
let path_builder = lyon_path::Path::builder().with_svg();
lyon_svg::path_utils::build_path(path_builder, commands).ok().map(|path| {
let event_enum = crate::typeregister::PATH_EVENT_ENUM.with(|e| e.clone());
let event_enum = crate::typeregister::BUILTIN_ENUMS.with(|e| e.PathEvent.clone());
let point_type = Type::Struct {
fields: IntoIterator::into_iter([
("x".to_owned(), Type::Float32),
@ -162,9 +162,9 @@ fn compile_path_from_string_literal(commands: &str) -> Option<BindingExpression>
}
lyon_path::Event::End { first: _, last: _, close } => {
if close {
event_enum.clone().try_value_from_string("end_closed").unwrap()
event_enum.clone().try_value_from_string("end-closed").unwrap()
} else {
event_enum.clone().try_value_from_string("end_open").unwrap()
event_enum.clone().try_value_from_string("end-open").unwrap()
}
}
})

View file

@ -37,40 +37,37 @@ const RESERVED_LAYOUT_PROPERTIES: &[(&str, Type)] = &[
("rowspan", Type::Int32),
];
macro_rules! declare_enums {
($( $(#[$enum_doc:meta])* enum $Name:ident { $( $(#[$value_doc:meta])* $Value:ident,)* })*) => {
pub struct BuiltinEnums {
$(pub $Name : Rc<Enumeration>),*
}
impl BuiltinEnums {
fn new() -> Self {
Self {
$($Name : Rc::new(Enumeration {
name: stringify!($Name).replace('_', "-"),
values: vec![$(stringify!($Value).trim_start_matches("r#").replace('_', "-")),*],
default_value: 0,
})),*
}
}
fn fill_register(&self, register: &mut TypeRegister) {
$(if stringify!($Name) != "PathEvent" {
register.insert_type_with_name(
Type::Enumeration(self.$Name.clone()),
stringify!($Name).replace('_', "-")
);
})*
}
}
};
}
i_slint_common::for_each_enums!(declare_enums);
thread_local! {
pub static DIALOG_BUTTON_ROLE_ENUM: Rc<Enumeration> =
Rc::new(Enumeration {
name: "DialogButtonRole".into(),
values: IntoIterator::into_iter([
"none".to_owned(),
"accept".to_owned(),
"reject".to_owned(),
"apply".to_owned(),
"reset".to_owned(),
"action".to_owned(),
"help".to_owned(),
])
.collect(),
default_value: 0,
});
pub static LAYOUT_ALIGNMENT_ENUM: Rc<Enumeration> =
Rc::new(Enumeration {
name: "LayoutAlignment".into(),
values: IntoIterator::into_iter(
["stretch", "center", "start", "end", "space-between", "space-around"]
).map(String::from).collect(),
default_value: 0,
});
pub static PATH_EVENT_ENUM: Rc<Enumeration> =
Rc::new(Enumeration {
name: "PathEvent".into(),
values: IntoIterator::into_iter(
["begin", "line", "quadratic", "cubic", "end_open", "end_closed"]
).map(String::from).collect(),
default_value: 0,
});
pub static BUILTIN_ENUMS: BuiltinEnums = BuiltinEnums::new();
}
const RESERVED_OTHER_PROPERTIES: &[(&str, Type)] = &[
@ -98,7 +95,10 @@ pub fn reserved_properties() -> impl Iterator<Item = (&'static str, Type)> {
.chain(IntoIterator::into_iter([
("forward-focus", Type::ElementReference),
("focus", BuiltinFunction::SetFocusItem.ty()),
("dialog-button-role", Type::Enumeration(DIALOG_BUTTON_ROLE_ENUM.with(|e| e.clone()))),
(
"dialog-button-role",
Type::Enumeration(BUILTIN_ENUMS.with(|e| e.DialogButtonRole.clone())),
),
]))
}
@ -183,73 +183,7 @@ impl TypeRegister {
register.insert_type(Type::Angle);
register.insert_type(Type::Brush);
let mut declare_enum = |name: &str, values: &[&str]| {
register.insert_type_with_name(
Type::Enumeration(Rc::new(Enumeration {
name: name.to_owned(),
values: values.iter().cloned().map(String::from).collect(),
default_value: 0,
})),
name.to_owned(),
);
};
declare_enum("TextHorizontalAlignment", &["left", "center", "right"]);
declare_enum("TextVerticalAlignment", &["top", "center", "bottom"]);
declare_enum("TextWrap", &["no-wrap", "word-wrap"]);
declare_enum("TextOverflow", &["clip", "elide"]);
declare_enum("ImageFit", &["fill", "contain", "cover"]);
declare_enum("ImageRendering", &["smooth", "pixelated"]);
declare_enum("EventResult", &["reject", "accept"]);
declare_enum("FillRule", &["nonzero", "evenodd"]);
declare_enum("InputType", &["text", "password"]);
declare_enum(
"MouseCursor",
&[
"default",
"none",
"help",
"pointer",
"progress",
"wait",
"crosshair",
"text",
"alias",
"copy",
"move",
"no-drop",
"not-allowed",
"grab",
"grabbing",
"col-resize",
"row-resize",
"n-resize",
"e-resize",
"s-resize",
"w-resize",
"ne-resize",
"nw-resize",
"se-resize",
"sw-resize",
"ew-resize",
"ns-resize",
"nesw-resize",
"nwse-resize",
],
);
declare_enum(
"StandardButtonKind",
&[
"ok", "cancel", "apply", "close", "reset", "help", "yes", "no", "abort", "retry",
"ignore",
],
);
declare_enum("PointerEventKind", &["cancel", "down", "up"]);
declare_enum("PointerEventButton", &["none", "left", "right", "middle"]);
DIALOG_BUTTON_ROLE_ENUM
.with(|e| register.insert_type_with_name(Type::Enumeration(e.clone()), e.name.clone()));
LAYOUT_ALIGNMENT_ENUM
.with(|e| register.insert_type_with_name(Type::Enumeration(e.clone()), e.name.clone()));
BUILTIN_ENUMS.with(|e| e.fill_register(&mut register));
register.supported_property_animation_types.insert(Type::Float32.to_string());
register.supported_property_animation_types.insert(Type::Int32.to_string());

View file

@ -5,6 +5,7 @@
This module contains path related types and functions for the run-time library.
*/
use crate::items::PathEvent;
#[cfg(feature = "rtti")]
use crate::rtti::*;
use auto_enums::auto_enum;
@ -134,26 +135,6 @@ pub enum PathElement {
Close,
}
#[repr(C)]
#[derive(Clone, Debug, PartialEq, strum::EnumString, strum::Display)]
#[allow(non_camel_case_types)]
/// PathEvent is a low-level data structure describing the composition of a path. Typically it is
/// generated at compile time from a higher-level description, such as SVG commands.
pub enum PathEvent {
/// The beginning of the path.
begin,
/// A straight line on the path.
line,
/// A quadratic bezier curve on the path.
quadratic,
/// A cubic bezier curve on the path.
cubic,
/// The end of the path that remains open.
end_open,
/// The end of a path that is closed.
end_closed,
}
struct ToLyonPathEventIterator<'a> {
events_it: core::slice::Iter<'a, PathEvent>,
coordinates_it: core::slice::Iter<'a, lyon_path::math::Point>,

View file

@ -7,7 +7,8 @@
use crate::graphics::Point;
use crate::item_tree::{ItemRc, ItemVisitorResult, ItemWeak, VisitChildrenResult};
use crate::items::{ItemRef, PointerEventButton, TextCursorDirection};
use crate::items::{ItemRef, TextCursorDirection};
pub use crate::items::{KeyEventType, PointerEventButton};
use crate::window::WindowRc;
use crate::{component::ComponentRc, SharedString};
use crate::{Coord, Property};
@ -142,22 +143,6 @@ pub struct KeyboardModifiers {
pub shift: bool,
}
#[derive(Debug, Clone, PartialEq, strum::EnumString, strum::Display)]
#[repr(C)]
/// This enum defines the different kinds of key events that can happen.
pub enum KeyEventType {
/// A key on a keyboard was pressed.
KeyPressed,
/// A key on a keyboard was released.
KeyReleased,
}
impl Default for KeyEventType {
fn default() -> Self {
Self::KeyPressed
}
}
/// Represents a key event sent by the windowing system.
#[derive(Debug, Clone, PartialEq, Default)]
#[repr(C)]

View file

@ -23,7 +23,7 @@ When adding an item or a property, it needs to be kept in sync with different pl
use crate::graphics::{Brush, Color, Point, Rect};
use crate::input::{
FocusEvent, FocusEventResult, InputEventFilterResult, InputEventResult, KeyEvent,
KeyEventResult, KeyEventType, MouseEvent,
KeyEventResult, MouseEvent,
};
use crate::item_rendering::CachedRenderingData;
pub use crate::item_tree::ItemRc;
@ -311,53 +311,6 @@ declare_item_vtable! {
fn slint_get_BorderRectangleVTable() -> BorderRectangleVTable for BorderRectangle
}
#[derive(Copy, Clone, Debug, PartialEq, strum::EnumString, strum::Display)]
#[repr(C)]
#[allow(non_camel_case_types)]
pub enum MouseCursor {
default,
none,
//context_menu,
help,
pointer,
progress,
wait,
//cell,
crosshair,
text,
//vertical_text,
alias,
copy,
r#move,
no_drop,
not_allowed,
grab,
grabbing,
//all_scroll,
col_resize,
row_resize,
n_resize,
e_resize,
s_resize,
w_resize,
ne_resize,
nw_resize,
se_resize,
sw_resize,
ew_resize,
ns_resize,
nesw_resize,
nwse_resize,
//zoom_in,
//zoom_out,
}
impl Default for MouseCursor {
fn default() -> Self {
Self::default
}
}
/// The implementation of the `TouchArea` element
#[repr(C)]
#[derive(FieldOffsets, Default, SlintElement)]
@ -524,21 +477,6 @@ declare_item_vtable! {
fn slint_get_TouchAreaVTable() -> TouchAreaVTable for TouchArea
}
#[derive(Copy, Clone, Debug, PartialEq, strum::EnumString, strum::Display)]
#[repr(C)]
#[allow(non_camel_case_types)]
/// What is returned from the event handler
pub enum EventResult {
reject,
accept,
}
impl Default for EventResult {
fn default() -> Self {
Self::reject
}
}
/// A runtime item that exposes key
#[repr(C)]
#[derive(FieldOffsets, Default, SlintElement)]
@ -1327,78 +1265,28 @@ declare_item_vtable! {
fn slint_get_PathVTable() -> PathVTable for Path
}
#[derive(Copy, Clone, Debug, PartialEq, strum::EnumString, strum::Display)]
#[repr(C)]
#[allow(non_camel_case_types)]
pub enum StandardButtonKind {
ok,
cancel,
apply,
close,
reset,
help,
yes,
no,
abort,
retry,
ignore,
macro_rules! declare_enums {
($( $(#[$enum_doc:meta])* enum $Name:ident { $( $(#[$value_doc:meta])* $Value:ident,)* })*) => {
$(
#[derive(Copy, Clone, Debug, PartialEq, Eq, strum::EnumString, strum::Display, Hash)]
#[repr(C)]
#[allow(non_camel_case_types)]
$(#[$enum_doc])*
pub enum $Name {
$( $(#[$value_doc])* $Value),*
}
impl Default for $Name {
fn default() -> Self {
// Always return the first value
($(Self::$Value,)*).0
}
}
)*
};
}
impl Default for StandardButtonKind {
fn default() -> Self {
Self::ok
}
}
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, strum::EnumString, strum::Display)]
#[repr(C)]
#[allow(non_camel_case_types)]
pub enum DialogButtonRole {
none,
accept,
reject,
apply,
reset,
action,
help,
}
impl Default for DialogButtonRole {
fn default() -> Self {
Self::none
}
}
#[derive(Copy, Clone, Debug, PartialEq, strum::EnumString, strum::Display)]
#[repr(C)]
#[allow(non_camel_case_types)]
pub enum PointerEventKind {
cancel,
down,
up,
}
impl Default for PointerEventKind {
fn default() -> Self {
Self::cancel
}
}
#[derive(Copy, Clone, Debug, PartialEq, strum::EnumString, strum::Display)]
#[repr(C)]
#[allow(non_camel_case_types)]
pub enum PointerEventButton {
none,
left,
right,
middle,
}
impl Default for PointerEventButton {
fn default() -> Self {
Self::none
}
}
i_slint_common::for_each_enums!(declare_enums);
/// Represents a key event sent by the windowing system.
#[derive(Debug, Clone, PartialEq, Default)]

View file

@ -7,7 +7,7 @@ This module contains the builtin image related items.
When adding an item or a property, it needs to be kept in sync with different place.
Lookup the [`crate::items`] module documentation.
*/
use super::{Item, ItemConsts, ItemRc, RenderingResult};
use super::{ImageFit, ImageRendering, Item, ItemConsts, ItemRc, RenderingResult};
use crate::graphics::Rect;
use crate::input::{
FocusEvent, FocusEventResult, InputEventFilterResult, InputEventResult, KeyEvent,
@ -24,35 +24,6 @@ use const_field_offset::FieldOffsets;
use core::pin::Pin;
use i_slint_core_macros::*;
#[derive(Copy, Clone, Debug, PartialEq, strum::EnumString, strum::Display)]
#[repr(C)]
#[allow(non_camel_case_types)]
pub enum ImageFit {
fill,
contain,
cover,
}
impl Default for ImageFit {
fn default() -> Self {
ImageFit::fill
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, strum::EnumString, strum::Display)]
#[repr(C)]
#[allow(non_camel_case_types)]
pub enum ImageRendering {
smooth,
pixelated,
}
impl Default for ImageRendering {
fn default() -> Self {
ImageRendering::smooth
}
}
#[repr(C)]
#[derive(FieldOffsets, Default, SlintElement)]
#[pin]

View file

@ -8,7 +8,7 @@ When adding an item or a property, it needs to be kept in sync with different pl
Lookup the [`crate::items`] module documentation.
*/
use super::{Item, ItemConsts, ItemRc, ItemRendererRef, RenderingResult};
use super::{FillRule, Item, ItemConsts, ItemRc, ItemRendererRef, RenderingResult};
use crate::graphics::{Brush, PathData, PathDataIterator, Rect};
use crate::input::{
FocusEvent, FocusEventResult, InputEventFilterResult, InputEventResult, KeyEvent,
@ -25,20 +25,6 @@ use const_field_offset::FieldOffsets;
use core::pin::Pin;
use i_slint_core_macros::*;
#[derive(Copy, Clone, Debug, PartialEq, strum::EnumString, strum::Display)]
#[repr(C)]
#[allow(non_camel_case_types)]
pub enum FillRule {
nonzero,
evenodd,
}
impl Default for FillRule {
fn default() -> Self {
Self::nonzero
}
}
/// The implementation of the `Path` element
#[repr(C)]
#[derive(FieldOffsets, Default, SlintElement)]

View file

@ -8,11 +8,15 @@ When adding an item or a property, it needs to be kept in sync with different pl
Lookup the [`crate::items`] module documentation.
*/
use super::{Item, ItemConsts, ItemRc, PointArg, PointerEventButton, RenderingResult, VoidArg};
use super::{
InputType, Item, ItemConsts, ItemRc, KeyEventResult, KeyEventType, PointArg,
PointerEventButton, RenderingResult, TextHorizontalAlignment, TextOverflow,
TextVerticalAlignment, TextWrap, VoidArg,
};
use crate::graphics::{Brush, Color, FontRequest, Rect};
use crate::input::{
key_codes, FocusEvent, FocusEventResult, InputEventFilterResult, InputEventResult, KeyEvent,
KeyEventResult, KeyEventType, KeyboardModifiers, MouseEvent, StandardShortcut, TextShortcut,
KeyboardModifiers, MouseEvent, StandardShortcut, TextShortcut,
};
use crate::item_rendering::{CachedRenderingData, ItemRenderer};
use crate::layout::{LayoutInfo, Orientation};
@ -28,81 +32,6 @@ use euclid::num::Ceil;
use i_slint_core_macros::*;
use unicode_segmentation::UnicodeSegmentation;
/// This enum defines the input type in a text input which for now only distinguishes a normal
/// input from a password input
#[derive(Copy, Clone, Debug, PartialEq, strum::EnumString, strum::Display)]
#[repr(C)]
#[allow(non_camel_case_types)]
pub enum InputType {
/// This type is used for a normal text input
text,
/// This type is used for password inputs where the characters are represented as *'s
password,
}
impl Default for InputType {
fn default() -> Self {
Self::text
}
}
#[derive(Copy, Clone, Debug, PartialEq, strum::EnumString, strum::Display)]
#[repr(C)]
#[allow(non_camel_case_types)]
pub enum TextHorizontalAlignment {
left,
center,
right,
}
impl Default for TextHorizontalAlignment {
fn default() -> Self {
Self::left
}
}
#[derive(Copy, Clone, Debug, PartialEq, strum::EnumString, strum::Display)]
#[repr(C)]
#[allow(non_camel_case_types)]
pub enum TextVerticalAlignment {
top,
center,
bottom,
}
impl Default for TextVerticalAlignment {
fn default() -> Self {
Self::top
}
}
#[derive(Copy, Clone, Debug, PartialEq, strum::EnumString, strum::Display)]
#[repr(C)]
#[allow(non_camel_case_types)]
pub enum TextWrap {
no_wrap,
word_wrap,
}
impl Default for TextWrap {
fn default() -> Self {
Self::no_wrap
}
}
#[derive(Copy, Clone, Debug, PartialEq, strum::EnumString, strum::Display)]
#[repr(C)]
#[allow(non_camel_case_types)]
pub enum TextOverflow {
clip,
elide,
}
impl Default for TextOverflow {
fn default() -> Self {
Self::clip
}
}
/// The implementation of the `Text` element
#[repr(C)]
#[derive(FieldOffsets, Default, SlintElement)]

View file

@ -5,7 +5,8 @@
// cspell:ignore coord
use crate::{items::DialogButtonRole, slice::Slice, Coord, SharedVector};
use crate::items::{DialogButtonRole, LayoutAlignment};
use crate::{slice::Slice, Coord, SharedVector};
use alloc::vec::Vec;
/// Vertical or Horizontal orientation
@ -434,25 +435,6 @@ pub fn grid_layout_info(
LayoutInfo { min, max, min_percent: 0 as _, max_percent: 100 as _, preferred, stretch }
}
/// Enum representing the alignment property of a BoxLayout or HorizontalLayout
#[derive(Copy, Clone, Debug, PartialEq, strum::EnumString, strum::Display)]
#[repr(C)]
#[allow(non_camel_case_types)]
pub enum LayoutAlignment {
stretch,
center,
start,
end,
space_between,
space_around,
}
impl Default for LayoutAlignment {
fn default() -> Self {
Self::stretch
}
}
#[repr(C)]
#[derive(Debug)]
/// The BoxLayoutData is used to represent both a Horizontal and Vertical layout.

View file

@ -17,40 +17,34 @@ macro_rules! declare_ValueType {
pub trait ValueType: 'static + Default + Clone $(+ TryInto<$ty> + TryFrom<$ty>)* {}
};
}
declare_ValueType![
(),
bool,
u32,
u64,
i32,
i64,
f32,
f64,
crate::SharedString,
crate::graphics::Image,
crate::Color,
crate::PathData,
crate::animations::EasingCurve,
crate::items::TextHorizontalAlignment,
crate::items::TextVerticalAlignment,
crate::items::TextOverflow,
crate::items::TextWrap,
crate::model::StandardListViewItem,
crate::items::ImageFit,
crate::items::ImageRendering,
crate::input::KeyEvent,
crate::items::EventResult,
crate::Brush,
crate::items::FillRule,
crate::items::MouseCursor,
crate::items::DialogButtonRole,
crate::items::StandardButtonKind,
crate::graphics::Point,
crate::items::PointerEvent,
crate::items::PointerEventButton,
crate::items::PointerEventKind,
crate::items::InputType,
];
macro_rules! declare_ValueType_2 {
($( $(#[$enum_doc:meta])* enum $Name:ident { $($body:tt)* })*) => {
declare_ValueType![
(),
bool,
u32,
u64,
i32,
i64,
f32,
f64,
crate::SharedString,
crate::graphics::Image,
crate::Color,
crate::PathData,
crate::animations::EasingCurve,
crate::model::StandardListViewItem,
crate::input::KeyEvent,
crate::Brush,
crate::graphics::Point,
crate::items::PointerEvent,
$(crate::items::$Name,)*
];
};
}
i_slint_common::for_each_enums!(declare_ValueType_2);
/// What kind of animation is on a binding
pub enum AnimatedBindingKind {

View file

@ -5,7 +5,8 @@
#![warn(missing_docs)]
#![allow(unsafe_code)]
use crate::input::{KeyEvent, KeyEventType, KeyboardModifiers, MouseEvent};
use crate::input::{KeyEvent, KeyboardModifiers, MouseEvent};
use crate::items::KeyEventType;
use crate::window::WindowRc;
use crate::Coord;
use crate::SharedString;

View file

@ -9,11 +9,9 @@
use crate::api::CloseRequestResponse;
use crate::component::{ComponentRc, ComponentWeak};
use crate::graphics::{Point, Rect, Size};
use crate::input::{
key_codes, KeyEvent, KeyEventType, MouseEvent, MouseInputState, TextCursorBlinker,
};
use crate::input::{key_codes, KeyEvent, MouseEvent, MouseInputState, TextCursorBlinker};
use crate::item_tree::ItemRc;
use crate::items::{ItemRef, MouseCursor};
use crate::items::{ItemRef, KeyEventType, MouseCursor};
use crate::properties::{Property, PropertyTracker};
use crate::{Callback, Coord};
use alloc::boxed::Box;

View file

@ -58,6 +58,7 @@ backend-gl-wayland = ["i-slint-backend-selector/backend-gl-wayland", "i-slint-ba
[dependencies]
i-slint-compiler = { version = "=0.2.2", path = "../compiler" }
i-slint-common = { version = "=0.2.2", path = "../common" }
i-slint-core = { version = "=0.2.2", path = "../core", features = ["rtti"] }
i-slint-backend-selector = { version = "=0.2.2", path = "../../internal/backends/selector" }

View file

@ -268,30 +268,30 @@ declare_value_struct_conversion!(struct i_slint_core::items::PointerEvent { kind
/// The `enum` must derive `Display` and `FromStr`
/// (can be done with `strum_macros::EnumString`, `strum_macros::Display` derive macro)
macro_rules! declare_value_enum_conversion {
($ty:ty, $n:ident) => {
impl From<$ty> for Value {
fn from(v: $ty) -> Self {
($( $(#[$enum_doc:meta])* enum $Name:ident { $($body:tt)* })*) => { $(
impl From<i_slint_core::items::$Name> for Value {
fn from(v: i_slint_core::items::$Name) -> Self {
Value::EnumerationValue(
stringify!($n).to_owned(),
stringify!($Name).to_owned(),
v.to_string().trim_start_matches("r#").replace('_', "-"),
)
}
}
impl TryInto<$ty> for Value {
impl TryInto<i_slint_core::items::$Name> for Value {
type Error = ();
fn try_into(self) -> Result<$ty, ()> {
fn try_into(self) -> Result<i_slint_core::items::$Name, ()> {
use std::str::FromStr;
match self {
Self::EnumerationValue(enumeration, value) => {
if enumeration != stringify!($n) {
if enumeration != stringify!($Name) {
return Err(());
}
<$ty>::from_str(value.as_str())
<i_slint_core::items::$Name>::from_str(value.as_str())
.or_else(|_| {
let norm = value.as_str().replace('-', "_");
<$ty>::from_str(&norm)
.or_else(|_| <$ty>::from_str(&format!("r#{}", norm)))
<i_slint_core::items::$Name>::from_str(&norm)
.or_else(|_| <i_slint_core::items::$Name>::from_str(&format!("r#{}", norm)))
})
.map_err(|_| ())
}
@ -299,29 +299,10 @@ macro_rules! declare_value_enum_conversion {
}
}
}
};
)*};
}
declare_value_enum_conversion!(
i_slint_core::items::TextHorizontalAlignment,
TextHorizontalAlignment
);
declare_value_enum_conversion!(i_slint_core::items::TextVerticalAlignment, TextVerticalAlignment);
declare_value_enum_conversion!(i_slint_core::items::TextOverflow, TextOverflow);
declare_value_enum_conversion!(i_slint_core::items::TextWrap, TextWrap);
declare_value_enum_conversion!(i_slint_core::layout::LayoutAlignment, LayoutAlignment);
declare_value_enum_conversion!(i_slint_core::items::ImageFit, ImageFit);
declare_value_enum_conversion!(i_slint_core::items::ImageRendering, ImageRendering);
declare_value_enum_conversion!(i_slint_core::input::KeyEventType, KeyEventType);
declare_value_enum_conversion!(i_slint_core::items::EventResult, EventResult);
declare_value_enum_conversion!(i_slint_core::items::FillRule, FillRule);
declare_value_enum_conversion!(i_slint_core::items::MouseCursor, MouseCursor);
declare_value_enum_conversion!(i_slint_core::items::StandardButtonKind, StandardButtonKind);
declare_value_enum_conversion!(i_slint_core::items::PointerEventKind, PointerEventKind);
declare_value_enum_conversion!(i_slint_core::items::PointerEventButton, PointerEventButton);
declare_value_enum_conversion!(i_slint_core::items::DialogButtonRole, DialogButtonRole);
declare_value_enum_conversion!(i_slint_core::items::InputType, InputType);
declare_value_enum_conversion!(i_slint_core::graphics::PathEvent, PathEvent);
i_slint_common::for_each_enums!(declare_value_enum_conversion);
impl From<i_slint_core::animations::Instant> for Value {
fn from(value: i_slint_core::animations::Instant) -> Self {

View file

@ -958,26 +958,19 @@ pub(crate) fn generate_component<'id>(
Type::Struct { .. } => property_info::<Value>(),
Type::Array(_) => property_info::<Value>(),
Type::Percent => property_info::<f32>(),
Type::Enumeration(e) => match e.name.as_ref() {
"LayoutAlignment" => property_info::<i_slint_core::layout::LayoutAlignment>(),
"TextHorizontalAlignment" => {
property_info::<i_slint_core::items::TextHorizontalAlignment>()
Type::Enumeration(e) => {
macro_rules! match_enum_type {
($( $(#[$enum_doc:meta])* enum $Name:ident { $($body:tt)* })*) => {
match e.name.as_str() {
$(
stringify!($Name) => property_info::<i_slint_core::items::$Name>(),
)*
_ => panic!("unknown enum"),
}
}
}
"TextVerticalAlignment" => {
property_info::<i_slint_core::items::TextVerticalAlignment>()
}
"InputType" => property_info::<i_slint_core::items::InputType>(),
"TextWrap" => property_info::<i_slint_core::items::TextWrap>(),
"TextOverflow" => property_info::<i_slint_core::items::TextOverflow>(),
"ImageFit" => property_info::<i_slint_core::items::ImageFit>(),
"FillRule" => property_info::<i_slint_core::items::FillRule>(),
"MouseCursor" => property_info::<i_slint_core::items::MouseCursor>(),
"StandardButtonKind" => property_info::<i_slint_core::items::StandardButtonKind>(),
"DialogButtonRole" => property_info::<i_slint_core::items::DialogButtonRole>(),
"PointerEventButton" => property_info::<i_slint_core::items::PointerEventButton>(),
"PointerEventKind" => property_info::<i_slint_core::items::PointerEventKind>(),
_ => panic!("unknown enum"),
},
i_slint_common::for_each_enums!(match_enum_type)
}
Type::LayoutCache => property_info::<SharedVector<f32>>(),
_ => panic!("bad type {:?}", &decl.property_type),
};

View file

@ -208,7 +208,7 @@ fn box_layout_data(
component: InstanceRef,
expr_eval: &impl Fn(&NamedReference) -> f32,
mut repeater_indices: Option<&mut Vec<u32>>,
) -> (Vec<core_layout::BoxLayoutCellData>, core_layout::LayoutAlignment) {
) -> (Vec<core_layout::BoxLayoutCellData>, i_slint_core::items::LayoutAlignment) {
let window = eval::window_ref(component).unwrap();
let mut cells = Vec::with_capacity(box_layout.elems.len());
for cell in &box_layout.elems {

View file

@ -21,6 +21,7 @@ TestCase := Rectangle {
x: 3phx;
width: 4phx;
clicked => { touch3+=1; }
mouse-cursor: default;
}
}
TouchArea {

View file

@ -23,3 +23,4 @@ serde_json = "1.0"
cbindgen = "0.21"
proc-macro2 = "1.0.11"
which = "4.2.4"
i-slint-common = { version = "=0.2.2", path="../internal/common" }