#![allow(unsafe_code)]
#![allow(non_upper_case_globals)]
#![allow(missing_docs)]
use crate::graphics::{Brush, Color, Point, Rect};
use crate::input::{
FocusEvent, FocusEventResult, InputEventFilterResult, InputEventResult, KeyEvent,
KeyEventResult, MouseEvent,
};
use crate::item_rendering::CachedRenderingData;
pub use crate::item_tree::ItemRc;
use crate::layout::{LayoutInfo, Orientation};
#[cfg(feature = "rtti")]
use crate::rtti::*;
use crate::window::WindowRc;
use crate::{Callback, Coord, Property, SharedString};
use const_field_offset::FieldOffsets;
use core::cell::Cell;
use core::pin::Pin;
use i_slint_core_macros::*;
use vtable::*;
mod flickable;
pub use flickable::*;
mod text;
pub use text::*;
mod image;
pub use self::image::*;
#[cfg(feature = "std")]
mod path;
#[cfg(feature = "std")]
pub use path::*;
type ItemRendererRef<'a> = &'a mut dyn crate::item_rendering::ItemRenderer;
pub type VoidArg = ();
pub type KeyEventArg = (KeyEvent,);
type PointerEventArg = (PointerEvent,);
type PointArg = (Point,);
#[cfg(all(feature = "ffi", windows))]
#[macro_export]
macro_rules! declare_item_vtable {
(fn $getter:ident() -> $item_vtable_ty:ident for $item_ty:ty) => {
ItemVTable_static! {
#[no_mangle]
pub static $item_vtable_ty for $item_ty
}
#[no_mangle]
pub extern "C" fn $getter() -> *const ItemVTable {
use vtable::HasStaticVTable;
<$item_ty>::static_vtable()
}
};
}
#[cfg(not(all(feature = "ffi", windows)))]
#[macro_export]
macro_rules! declare_item_vtable {
(fn $getter:ident() -> $item_vtable_ty:ident for $item_ty:ty) => {
ItemVTable_static! {
#[no_mangle]
pub static $item_vtable_ty for $item_ty
}
};
}
#[repr(C)]
pub enum RenderingResult {
ContinueRenderingChildren,
ContinueRenderingWithoutChildren,
}
impl Default for RenderingResult {
fn default() -> Self {
Self::ContinueRenderingChildren
}
}
#[vtable]
#[repr(C)]
pub struct ItemVTable {
pub init: extern "C" fn(core::pin::Pin<VRef<ItemVTable>>, window: &WindowRc),
pub geometry: extern "C" fn(core::pin::Pin<VRef<ItemVTable>>) -> Rect,
#[allow(non_upper_case_globals)]
#[field_offset(CachedRenderingData)]
pub cached_rendering_data_offset: usize,
pub layout_info: extern "C" fn(
core::pin::Pin<VRef<ItemVTable>>,
orientation: Orientation,
window: &WindowRc,
) -> LayoutInfo,
pub input_event_filter_before_children: extern "C" fn(
core::pin::Pin<VRef<ItemVTable>>,
MouseEvent,
window: &WindowRc,
self_rc: &ItemRc,
) -> InputEventFilterResult,
pub input_event: extern "C" fn(
core::pin::Pin<VRef<ItemVTable>>,
MouseEvent,
window: &WindowRc,
self_rc: &ItemRc,
) -> InputEventResult,
pub focus_event: extern "C" fn(
core::pin::Pin<VRef<ItemVTable>>,
&FocusEvent,
window: &WindowRc,
) -> FocusEventResult,
pub key_event: extern "C" fn(
core::pin::Pin<VRef<ItemVTable>>,
&KeyEvent,
window: &WindowRc,
) -> KeyEventResult,
pub render: extern "C" fn(
core::pin::Pin<VRef<ItemVTable>>,
backend: &mut ItemRendererRef,
self_rc: &ItemRc,
) -> RenderingResult,
}
pub type ItemRef<'a> = vtable::VRef<'a, ItemVTable>;
#[repr(C)]
#[derive(FieldOffsets, Default, SlintElement)]
#[pin]
pub struct Rectangle {
pub background: Property<Brush>,
pub x: Property<Coord>,
pub y: Property<Coord>,
pub width: Property<Coord>,
pub height: Property<Coord>,
pub cached_rendering_data: CachedRenderingData,
}
impl Item for Rectangle {
fn init(self: Pin<&Self>, _window: &WindowRc) {}
fn geometry(self: Pin<&Self>) -> Rect {
euclid::rect(self.x(), self.y(), self.width(), self.height())
}
fn layout_info(self: Pin<&Self>, _orientation: Orientation, _window: &WindowRc) -> LayoutInfo {
LayoutInfo { stretch: 1., ..LayoutInfo::default() }
}
fn input_event_filter_before_children(
self: Pin<&Self>,
_: MouseEvent,
_window: &WindowRc,
_self_rc: &ItemRc,
) -> InputEventFilterResult {
InputEventFilterResult::ForwardAndIgnore
}
fn input_event(
self: Pin<&Self>,
_: MouseEvent,
_window: &WindowRc,
_self_rc: &ItemRc,
) -> InputEventResult {
InputEventResult::EventIgnored
}
fn key_event(self: Pin<&Self>, _: &KeyEvent, _window: &WindowRc) -> KeyEventResult {
KeyEventResult::EventIgnored
}
fn focus_event(self: Pin<&Self>, _: &FocusEvent, _window: &WindowRc) -> FocusEventResult {
FocusEventResult::FocusIgnored
}
fn render(
self: Pin<&Self>,
backend: &mut ItemRendererRef,
_self_rc: &ItemRc,
) -> RenderingResult {
(*backend).draw_rectangle(self);
RenderingResult::ContinueRenderingChildren
}
}
impl ItemConsts for Rectangle {
const cached_rendering_data_offset: const_field_offset::FieldOffset<
Rectangle,
CachedRenderingData,
> = Rectangle::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
}
declare_item_vtable! {
fn slint_get_RectangleVTable() -> RectangleVTable for Rectangle
}
#[repr(C)]
#[derive(FieldOffsets, Default, SlintElement)]
#[pin]
pub struct BorderRectangle {
pub background: Property<Brush>,
pub x: Property<Coord>,
pub y: Property<Coord>,
pub width: Property<Coord>,
pub height: Property<Coord>,
pub border_width: Property<Coord>,
pub border_radius: Property<Coord>,
pub border_color: Property<Brush>,
pub cached_rendering_data: CachedRenderingData,
}
impl Item for BorderRectangle {
fn init(self: Pin<&Self>, _window: &WindowRc) {}
fn geometry(self: Pin<&Self>) -> Rect {
euclid::rect(self.x(), self.y(), self.width(), self.height())
}
fn layout_info(self: Pin<&Self>, _orientation: Orientation, _window: &WindowRc) -> LayoutInfo {
LayoutInfo { stretch: 1., ..LayoutInfo::default() }
}
fn input_event_filter_before_children(
self: Pin<&Self>,
_: MouseEvent,
_window: &WindowRc,
_self_rc: &ItemRc,
) -> InputEventFilterResult {
InputEventFilterResult::ForwardAndIgnore
}
fn input_event(
self: Pin<&Self>,
_: MouseEvent,
_window: &WindowRc,
_self_rc: &ItemRc,
) -> InputEventResult {
InputEventResult::EventIgnored
}
fn key_event(self: Pin<&Self>, _: &KeyEvent, _window: &WindowRc) -> KeyEventResult {
KeyEventResult::EventIgnored
}
fn focus_event(self: Pin<&Self>, _: &FocusEvent, _window: &WindowRc) -> FocusEventResult {
FocusEventResult::FocusIgnored
}
fn render(
self: Pin<&Self>,
backend: &mut ItemRendererRef,
_self_rc: &ItemRc,
) -> RenderingResult {
(*backend).draw_border_rectangle(self);
RenderingResult::ContinueRenderingChildren
}
}
impl ItemConsts for BorderRectangle {
const cached_rendering_data_offset: const_field_offset::FieldOffset<
BorderRectangle,
CachedRenderingData,
> = BorderRectangle::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
}
declare_item_vtable! {
fn slint_get_BorderRectangleVTable() -> BorderRectangleVTable for BorderRectangle
}
#[repr(C)]
#[derive(FieldOffsets, Default, SlintElement)]
#[pin]
pub struct TouchArea {
pub x: Property<Coord>,
pub y: Property<Coord>,
pub width: Property<Coord>,
pub height: Property<Coord>,
pub enabled: Property<bool>,
pub pressed: Property<bool>,
pub has_hover: Property<bool>,
pub pressed_x: Property<Coord>,
pub pressed_y: Property<Coord>,
pub mouse_x: Property<Coord>,
pub mouse_y: Property<Coord>,
pub mouse_cursor: Property<MouseCursor>,
pub clicked: Callback<VoidArg>,
pub moved: Callback<VoidArg>,
pub pointer_event: Callback<PointerEventArg>,
pub cached_rendering_data: CachedRenderingData,
grabbed: Cell<bool>,
}
impl Item for TouchArea {
fn init(self: Pin<&Self>, _window: &WindowRc) {}
fn geometry(self: Pin<&Self>) -> Rect {
euclid::rect(self.x(), self.y(), self.width(), self.height())
}
fn layout_info(self: Pin<&Self>, _orientation: Orientation, _window: &WindowRc) -> LayoutInfo {
LayoutInfo::default()
}
fn input_event_filter_before_children(
self: Pin<&Self>,
event: MouseEvent,
window: &WindowRc,
_self_rc: &ItemRc,
) -> InputEventFilterResult {
if !self.enabled() {
return InputEventFilterResult::ForwardAndIgnore;
}
if let Some(pos) = event.pos() {
Self::FIELD_OFFSETS.mouse_x.apply_pin(self).set(pos.x);
Self::FIELD_OFFSETS.mouse_y.apply_pin(self).set(pos.y);
}
let hovering = !matches!(event, MouseEvent::MouseExit);
Self::FIELD_OFFSETS.has_hover.apply_pin(self).set(hovering);
if hovering {
window.set_mouse_cursor(self.mouse_cursor());
}
InputEventFilterResult::ForwardAndInterceptGrab
}
fn input_event(
self: Pin<&Self>,
event: MouseEvent,
window: &WindowRc,
_self_rc: &ItemRc,
) -> InputEventResult {
if matches!(event, MouseEvent::MouseExit) {
Self::FIELD_OFFSETS.has_hover.apply_pin(self).set(false);
window.set_mouse_cursor(MouseCursor::default);
}
if !self.enabled() {
return InputEventResult::EventIgnored;
}
let result = if let MouseEvent::MouseReleased { pos, button } = event {
if button == PointerEventButton::left
&& euclid::rect(0 as Coord, 0 as Coord, self.width(), self.height()).contains(pos)
{
Self::FIELD_OFFSETS.clicked.apply_pin(self).call(&());
}
InputEventResult::EventAccepted
} else {
InputEventResult::GrabMouse
};
match event {
MouseEvent::MousePressed { pos, button } => {
self.grabbed.set(true);
if button == PointerEventButton::left {
Self::FIELD_OFFSETS.pressed_x.apply_pin(self).set(pos.x);
Self::FIELD_OFFSETS.pressed_y.apply_pin(self).set(pos.y);
Self::FIELD_OFFSETS.pressed.apply_pin(self).set(true);
}
Self::FIELD_OFFSETS
.pointer_event
.apply_pin(self)
.call(&(PointerEvent { button, kind: PointerEventKind::down },));
}
MouseEvent::MouseExit => {
Self::FIELD_OFFSETS.pressed.apply_pin(self).set(false);
if self.grabbed.replace(false) {
Self::FIELD_OFFSETS.pointer_event.apply_pin(self).call(&(PointerEvent {
button: PointerEventButton::none,
kind: PointerEventKind::cancel,
},));
}
}
MouseEvent::MouseReleased { button, .. } => {
self.grabbed.set(false);
if button == PointerEventButton::left {
Self::FIELD_OFFSETS.pressed.apply_pin(self).set(false);
}
Self::FIELD_OFFSETS
.pointer_event
.apply_pin(self)
.call(&(PointerEvent { button, kind: PointerEventKind::up },));
}
MouseEvent::MouseMoved { .. } => {
return if self.grabbed.get() {
Self::FIELD_OFFSETS.moved.apply_pin(self).call(&());
InputEventResult::GrabMouse
} else {
InputEventResult::EventAccepted
}
}
MouseEvent::MouseWheel { .. } => {
return if self.grabbed.get() {
InputEventResult::GrabMouse
} else {
InputEventResult::EventAccepted
}
}
};
result
}
fn key_event(self: Pin<&Self>, _: &KeyEvent, _window: &WindowRc) -> KeyEventResult {
KeyEventResult::EventIgnored
}
fn focus_event(self: Pin<&Self>, _: &FocusEvent, _window: &WindowRc) -> FocusEventResult {
FocusEventResult::FocusIgnored
}
fn render(
self: Pin<&Self>,
_backend: &mut ItemRendererRef,
_self_rc: &ItemRc,
) -> RenderingResult {
RenderingResult::ContinueRenderingChildren
}
}
impl ItemConsts for TouchArea {
const cached_rendering_data_offset: const_field_offset::FieldOffset<
TouchArea,
CachedRenderingData,
> = TouchArea::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
}
declare_item_vtable! {
fn slint_get_TouchAreaVTable() -> TouchAreaVTable for TouchArea
}
#[repr(C)]
#[derive(FieldOffsets, Default, SlintElement)]
#[pin]
pub struct FocusScope {
pub x: Property<Coord>,
pub y: Property<Coord>,
pub width: Property<Coord>,
pub height: Property<Coord>,
pub enabled: Property<bool>,
pub has_focus: Property<bool>,
pub key_pressed: Callback<KeyEventArg, EventResult>,
pub key_released: Callback<KeyEventArg, EventResult>,
pub cached_rendering_data: CachedRenderingData,
}
impl Item for FocusScope {
fn init(self: Pin<&Self>, _window: &WindowRc) {}
fn geometry(self: Pin<&Self>) -> Rect {
euclid::rect(self.x(), self.y(), self.width(), self.height())
}
fn layout_info(self: Pin<&Self>, _orientation: Orientation, _window: &WindowRc) -> LayoutInfo {
LayoutInfo::default()
}
fn input_event_filter_before_children(
self: Pin<&Self>,
_: MouseEvent,
_window: &WindowRc,
_self_rc: &ItemRc,
) -> InputEventFilterResult {
InputEventFilterResult::ForwardEvent
}
fn input_event(
self: Pin<&Self>,
event: MouseEvent,
window: &WindowRc,
self_rc: &ItemRc,
) -> InputEventResult {
if self.enabled() && matches!(event, MouseEvent::MousePressed { .. }) && !self.has_focus() {
window.clone().set_focus_item(self_rc);
}
InputEventResult::EventIgnored
}
fn key_event(self: Pin<&Self>, event: &KeyEvent, _window: &WindowRc) -> KeyEventResult {
let r = match event.event_type {
KeyEventType::KeyPressed => {
Self::FIELD_OFFSETS.key_pressed.apply_pin(self).call(&(event.clone(),))
}
KeyEventType::KeyReleased => {
Self::FIELD_OFFSETS.key_released.apply_pin(self).call(&(event.clone(),))
}
};
match r {
EventResult::accept => KeyEventResult::EventAccepted,
EventResult::reject => KeyEventResult::EventIgnored,
}
}
fn focus_event(self: Pin<&Self>, event: &FocusEvent, _window: &WindowRc) -> FocusEventResult {
if !self.enabled() {
return FocusEventResult::FocusIgnored;
}
match event {
FocusEvent::FocusIn | FocusEvent::WindowReceivedFocus => {
self.has_focus.set(true);
}
FocusEvent::FocusOut | FocusEvent::WindowLostFocus => {
self.has_focus.set(false);
}
}
FocusEventResult::FocusAccepted
}
fn render(
self: Pin<&Self>,
_backend: &mut ItemRendererRef,
_self_rc: &ItemRc,
) -> RenderingResult {
RenderingResult::ContinueRenderingChildren
}
}
impl ItemConsts for FocusScope {
const cached_rendering_data_offset: const_field_offset::FieldOffset<
FocusScope,
CachedRenderingData,
> = FocusScope::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
}
declare_item_vtable! {
fn slint_get_FocusScopeVTable() -> FocusScopeVTable for FocusScope
}
#[repr(C)]
#[derive(FieldOffsets, Default, SlintElement)]
#[pin]
pub struct Clip {
pub x: Property<Coord>,
pub y: Property<Coord>,
pub width: Property<Coord>,
pub height: Property<Coord>,
pub border_radius: Property<Coord>,
pub border_width: Property<Coord>,
pub cached_rendering_data: CachedRenderingData,
pub clip: Property<bool>,
}
impl Item for Clip {
fn init(self: Pin<&Self>, _window: &WindowRc) {}
fn geometry(self: Pin<&Self>) -> Rect {
euclid::rect(self.x(), self.y(), self.width(), self.height())
}
fn layout_info(self: Pin<&Self>, _orientation: Orientation, _window: &WindowRc) -> LayoutInfo {
LayoutInfo { stretch: 1., ..LayoutInfo::default() }
}
fn input_event_filter_before_children(
self: Pin<&Self>,
event: MouseEvent,
_window: &WindowRc,
_self_rc: &ItemRc,
) -> InputEventFilterResult {
if let Some(pos) = event.pos() {
if self.clip()
&& (pos.x < 0 as Coord
|| pos.y < 0 as Coord
|| pos.x > self.width()
|| pos.y > self.height())
{
return InputEventFilterResult::Intercept;
}
}
InputEventFilterResult::ForwardAndIgnore
}
fn input_event(
self: Pin<&Self>,
_: MouseEvent,
_window: &WindowRc,
_self_rc: &ItemRc,
) -> InputEventResult {
InputEventResult::EventIgnored
}
fn key_event(self: Pin<&Self>, _: &KeyEvent, _window: &WindowRc) -> KeyEventResult {
KeyEventResult::EventIgnored
}
fn focus_event(self: Pin<&Self>, _: &FocusEvent, _window: &WindowRc) -> FocusEventResult {
FocusEventResult::FocusIgnored
}
fn render(
self: Pin<&Self>,
backend: &mut ItemRendererRef,
self_rc: &ItemRc,
) -> RenderingResult {
(*backend).visit_clip(self, self_rc)
}
}
impl ItemConsts for Clip {
const cached_rendering_data_offset: const_field_offset::FieldOffset<Clip, CachedRenderingData> =
Clip::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
}
declare_item_vtable! {
fn slint_get_ClipVTable() -> ClipVTable for Clip
}
#[repr(C)]
#[derive(FieldOffsets, Default, SlintElement)]
#[pin]
pub struct Opacity {
pub x: Property<Coord>,
pub y: Property<Coord>,
pub width: Property<Coord>,
pub height: Property<Coord>,
pub opacity: Property<f32>,
pub cached_rendering_data: CachedRenderingData,
}
impl Item for Opacity {
fn init(self: Pin<&Self>, _window: &WindowRc) {}
fn geometry(self: Pin<&Self>) -> Rect {
euclid::rect(self.x(), self.y(), self.width(), self.height())
}
fn layout_info(self: Pin<&Self>, _orientation: Orientation, _window: &WindowRc) -> LayoutInfo {
LayoutInfo { stretch: 1., ..LayoutInfo::default() }
}
fn input_event_filter_before_children(
self: Pin<&Self>,
_: MouseEvent,
_window: &WindowRc,
_self_rc: &ItemRc,
) -> InputEventFilterResult {
InputEventFilterResult::ForwardAndIgnore
}
fn input_event(
self: Pin<&Self>,
_: MouseEvent,
_window: &WindowRc,
_self_rc: &ItemRc,
) -> InputEventResult {
InputEventResult::EventIgnored
}
fn key_event(self: Pin<&Self>, _: &KeyEvent, _window: &WindowRc) -> KeyEventResult {
KeyEventResult::EventIgnored
}
fn focus_event(self: Pin<&Self>, _: &FocusEvent, _window: &WindowRc) -> FocusEventResult {
FocusEventResult::FocusIgnored
}
fn render(
self: Pin<&Self>,
backend: &mut ItemRendererRef,
self_rc: &ItemRc,
) -> RenderingResult {
backend.visit_opacity(self, self_rc)
}
}
impl Opacity {
pub fn need_layer(self_rc: &ItemRc, opacity: f32) -> bool {
if opacity == 1.0 {
return false;
}
let opacity_child = match self_rc.first_child() {
Some(first_child) => first_child,
None => return false, };
if opacity_child.next_sibling().is_some() {
return true; }
opacity_child.first_child().is_some()
}
}
impl ItemConsts for Opacity {
const cached_rendering_data_offset: const_field_offset::FieldOffset<
Opacity,
CachedRenderingData,
> = Opacity::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
}
declare_item_vtable! {
fn slint_get_OpacityVTable() -> OpacityVTable for Opacity
}
#[repr(C)]
#[derive(FieldOffsets, Default, SlintElement)]
#[pin]
pub struct Layer {
pub x: Property<Coord>,
pub y: Property<Coord>,
pub width: Property<Coord>,
pub height: Property<Coord>,
pub cache_rendering_hint: Property<bool>,
pub cached_rendering_data: CachedRenderingData,
}
impl Item for Layer {
fn init(self: Pin<&Self>, _window: &WindowRc) {}
fn geometry(self: Pin<&Self>) -> Rect {
euclid::rect(self.x(), self.y(), self.width(), self.height())
}
fn layout_info(self: Pin<&Self>, _orientation: Orientation, _window: &WindowRc) -> LayoutInfo {
LayoutInfo { stretch: 1., ..LayoutInfo::default() }
}
fn input_event_filter_before_children(
self: Pin<&Self>,
_: MouseEvent,
_window: &WindowRc,
_self_rc: &ItemRc,
) -> InputEventFilterResult {
InputEventFilterResult::ForwardAndIgnore
}
fn input_event(
self: Pin<&Self>,
_: MouseEvent,
_window: &WindowRc,
_self_rc: &ItemRc,
) -> InputEventResult {
InputEventResult::EventIgnored
}
fn key_event(self: Pin<&Self>, _: &KeyEvent, _window: &WindowRc) -> KeyEventResult {
KeyEventResult::EventIgnored
}
fn focus_event(self: Pin<&Self>, _: &FocusEvent, _window: &WindowRc) -> FocusEventResult {
FocusEventResult::FocusIgnored
}
fn render(
self: Pin<&Self>,
backend: &mut ItemRendererRef,
self_rc: &ItemRc,
) -> RenderingResult {
backend.visit_layer(self, self_rc)
}
}
impl ItemConsts for Layer {
const cached_rendering_data_offset: const_field_offset::FieldOffset<
Layer,
CachedRenderingData,
> = Layer::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
}
declare_item_vtable! {
fn slint_get_LayerVTable() -> LayerVTable for Layer
}
#[repr(C)]
#[derive(FieldOffsets, Default, SlintElement)]
#[pin]
pub struct Rotate {
pub angle: Property<f32>,
pub origin_x: Property<Coord>,
pub origin_y: Property<Coord>,
pub width: Property<Coord>,
pub height: Property<Coord>,
pub cached_rendering_data: CachedRenderingData,
}
impl Item for Rotate {
fn init(self: Pin<&Self>, _window: &WindowRc) {}
fn geometry(self: Pin<&Self>) -> Rect {
euclid::rect(0, 0, 0, 0).cast()
}
fn layout_info(self: Pin<&Self>, _orientation: Orientation, _window: &WindowRc) -> LayoutInfo {
LayoutInfo { stretch: 1., ..LayoutInfo::default() }
}
fn input_event_filter_before_children(
self: Pin<&Self>,
_: MouseEvent,
_window: &WindowRc,
_self_rc: &ItemRc,
) -> InputEventFilterResult {
InputEventFilterResult::ForwardAndIgnore
}
fn input_event(
self: Pin<&Self>,
_: MouseEvent,
_window: &WindowRc,
_self_rc: &ItemRc,
) -> InputEventResult {
InputEventResult::EventIgnored
}
fn key_event(self: Pin<&Self>, _: &KeyEvent, _window: &WindowRc) -> KeyEventResult {
KeyEventResult::EventIgnored
}
fn focus_event(self: Pin<&Self>, _: &FocusEvent, _window: &WindowRc) -> FocusEventResult {
FocusEventResult::FocusIgnored
}
fn render(
self: Pin<&Self>,
backend: &mut ItemRendererRef,
_self_rc: &ItemRc,
) -> RenderingResult {
(*backend).translate(self.origin_x(), self.origin_y());
(*backend).rotate(self.angle());
(*backend).translate(-self.origin_x(), -self.origin_y());
RenderingResult::ContinueRenderingChildren
}
}
impl ItemConsts for Rotate {
const cached_rendering_data_offset: const_field_offset::FieldOffset<
Rotate,
CachedRenderingData,
> = Rotate::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
}
declare_item_vtable! {
fn slint_get_RotateVTable() -> RotateVTable for Rotate
}
declare_item_vtable! {
fn slint_get_FlickableVTable() -> FlickableVTable for Flickable
}
#[repr(C)]
#[derive(FieldOffsets, SlintElement, Clone, Debug)]
#[pin]
pub struct PropertyAnimation {
#[rtti_field]
pub delay: i32,
#[rtti_field]
pub duration: i32,
#[rtti_field]
pub iteration_count: f32,
#[rtti_field]
pub easing: crate::animations::EasingCurve,
}
impl Default for PropertyAnimation {
fn default() -> Self {
Self { delay: 0, duration: 0, iteration_count: 1., easing: Default::default() }
}
}
#[repr(C)]
#[derive(FieldOffsets, Default, SlintElement)]
#[pin]
pub struct WindowItem {
pub width: Property<Coord>,
pub height: Property<Coord>,
pub background: Property<Color>,
pub title: Property<SharedString>,
pub no_frame: Property<bool>,
pub icon: Property<crate::graphics::Image>,
pub default_font_family: Property<SharedString>,
pub default_font_size: Property<Coord>,
pub default_font_weight: Property<i32>,
pub cached_rendering_data: CachedRenderingData,
}
impl Item for WindowItem {
fn init(self: Pin<&Self>, _window: &WindowRc) {}
fn geometry(self: Pin<&Self>) -> Rect {
euclid::rect(0 as _, 0 as _, self.width(), self.height())
}
fn layout_info(self: Pin<&Self>, _orientation: Orientation, _window: &WindowRc) -> LayoutInfo {
LayoutInfo::default()
}
fn input_event_filter_before_children(
self: Pin<&Self>,
_: MouseEvent,
_window: &WindowRc,
_self_rc: &ItemRc,
) -> InputEventFilterResult {
InputEventFilterResult::ForwardAndIgnore
}
fn input_event(
self: Pin<&Self>,
_event: MouseEvent,
_window: &WindowRc,
_self_rc: &ItemRc,
) -> InputEventResult {
InputEventResult::EventIgnored
}
fn key_event(self: Pin<&Self>, _: &KeyEvent, _window: &WindowRc) -> KeyEventResult {
KeyEventResult::EventIgnored
}
fn focus_event(self: Pin<&Self>, _: &FocusEvent, _window: &WindowRc) -> FocusEventResult {
FocusEventResult::FocusIgnored
}
fn render(
self: Pin<&Self>,
_backend: &mut ItemRendererRef,
_self_rc: &ItemRc,
) -> RenderingResult {
RenderingResult::ContinueRenderingChildren
}
}
impl WindowItem {
pub fn default_font_properties(self: Pin<&Self>) -> crate::graphics::FontRequest {
crate::graphics::FontRequest {
family: {
let maybe_family = self.default_font_family();
if !maybe_family.is_empty() {
Some(maybe_family)
} else {
None
}
},
pixel_size: {
let font_size = self.default_font_size();
if font_size <= 0 as Coord {
None
} else {
Some(font_size)
}
},
weight: {
let font_weight = self.default_font_weight();
if font_weight == 0 {
None
} else {
Some(font_weight)
}
},
..Default::default()
}
}
}
impl ItemConsts for WindowItem {
const cached_rendering_data_offset: const_field_offset::FieldOffset<Self, CachedRenderingData> =
Self::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
}
declare_item_vtable! {
fn slint_get_WindowItemVTable() -> WindowItemVTable for WindowItem
}
#[repr(C)]
#[derive(FieldOffsets, Default, SlintElement)]
#[pin]
pub struct BoxShadow {
pub x: Property<Coord>,
pub y: Property<Coord>,
pub width: Property<Coord>,
pub height: Property<Coord>,
pub border_radius: Property<Coord>,
pub offset_x: Property<Coord>,
pub offset_y: Property<Coord>,
pub color: Property<Color>,
pub blur: Property<Coord>,
pub cached_rendering_data: CachedRenderingData,
}
impl Item for BoxShadow {
fn init(self: Pin<&Self>, _window: &WindowRc) {}
fn geometry(self: Pin<&Self>) -> Rect {
euclid::rect(self.x(), self.y(), self.width(), self.height())
}
fn layout_info(self: Pin<&Self>, _orientation: Orientation, _window: &WindowRc) -> LayoutInfo {
LayoutInfo { stretch: 1., ..LayoutInfo::default() }
}
fn input_event_filter_before_children(
self: Pin<&Self>,
_: MouseEvent,
_window: &WindowRc,
_self_rc: &ItemRc,
) -> InputEventFilterResult {
InputEventFilterResult::ForwardAndIgnore
}
fn input_event(
self: Pin<&Self>,
_event: MouseEvent,
_window: &WindowRc,
_self_rc: &ItemRc,
) -> InputEventResult {
InputEventResult::EventIgnored
}
fn key_event(self: Pin<&Self>, _: &KeyEvent, _window: &WindowRc) -> KeyEventResult {
KeyEventResult::EventIgnored
}
fn focus_event(self: Pin<&Self>, _: &FocusEvent, _window: &WindowRc) -> FocusEventResult {
FocusEventResult::FocusIgnored
}
fn render(
self: Pin<&Self>,
backend: &mut ItemRendererRef,
_self_rc: &ItemRc,
) -> RenderingResult {
(*backend).draw_box_shadow(self);
RenderingResult::ContinueRenderingChildren
}
}
impl ItemConsts for BoxShadow {
const cached_rendering_data_offset: const_field_offset::FieldOffset<Self, CachedRenderingData> =
Self::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
}
declare_item_vtable! {
fn slint_get_BoxShadowVTable() -> BoxShadowVTable for BoxShadow
}
declare_item_vtable! {
fn slint_get_TextVTable() -> TextVTable for Text
}
declare_item_vtable! {
fn slint_get_TextInputVTable() -> TextInputVTable for TextInput
}
declare_item_vtable! {
fn slint_get_ImageItemVTable() -> ImageItemVTable for ImageItem
}
declare_item_vtable! {
fn slint_get_ClippedImageVTable() -> ClippedImageVTable for ClippedImage
}
#[cfg(feature = "std")]
declare_item_vtable! {
fn slint_get_PathVTable() -> PathVTable for Path
}
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 {
($(Self::$Value,)*).0
}
}
)*
};
}
i_slint_common::for_each_enums!(declare_enums);
#[derive(Debug, Clone, PartialEq, Default)]
#[repr(C)]
pub struct PointerEvent {
pub button: PointerEventButton,
pub kind: PointerEventKind,
}