Remove duplicated geometry properties from items

This commit is contained in:
Guilhem Vallat 2023-07-18 14:04:32 +02:00 committed by Olivier Goffart
parent 06fc251729
commit 5cf1a45e41
23 changed files with 88 additions and 270 deletions

View file

@ -45,8 +45,9 @@ type ItemRendererRef<'a> = &'a mut dyn ItemRenderer;
/// and return Default::default in case the size is too small
macro_rules! get_size {
($self:ident) => {{
let width = $self.width().get();
let height = $self.height().get();
let geo = $self.geometry();
let width = geo.width();
let height = geo.height();
if width < 1. || height < 1. {
return Default::default();
};
@ -89,8 +90,9 @@ macro_rules! fn_render {
backend.draw_cached_pixmap(
item_rc,
&|callback| {
let width = self.width().get() * $dpr;
let height = self.height().get() * $dpr;
let geo = item_rc.geometry();
let width = geo.width() * $dpr;
let height = geo.height() * $dpr;
if width < 1. || height < 1. {
return Default::default();
};

View file

@ -104,10 +104,6 @@ type ActualStandardButtonKind = Option<StandardButtonKind>;
#[derive(FieldOffsets, Default, SlintElement)]
#[pin]
pub struct NativeButton {
pub x: Property<LogicalLength>,
pub y: Property<LogicalLength>,
pub width: Property<LogicalLength>,
pub height: Property<LogicalLength>,
pub text: Property<SharedString>,
pub icon: Property<i_slint_core::graphics::Image>,
pub pressed: Property<bool>,
@ -252,7 +248,7 @@ impl Item for NativeButton {
self: Pin<&Self>,
event: MouseEvent,
_window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &i_slint_core::items::ItemRc,
self_rc: &i_slint_core::items::ItemRc,
) -> InputEventResult {
if matches!(event, MouseEvent::Exit) {
Self::FIELD_OFFSETS.has_hover.apply_pin(self).set(false);
@ -277,12 +273,8 @@ impl Item for NativeButton {
MouseEvent::Wheel { .. } => return InputEventResult::EventIgnored,
});
if let MouseEvent::Released { position, .. } = event {
if LogicalRect::new(
LogicalPoint::default(),
LogicalSize::from_lengths(self.width(), self.height()),
)
.contains(position)
&& was_pressed
let geo = self_rc.geometry();
if LogicalRect::new(LogicalPoint::default(), geo.size).contains(position) && was_pressed
{
self.activate();
}

View file

@ -9,10 +9,6 @@ use super::*;
#[derive(FieldOffsets, Default, SlintElement)]
#[pin]
pub struct NativeCheckBox {
pub x: Property<LogicalLength>,
pub y: Property<LogicalLength>,
pub width: Property<LogicalLength>,
pub height: Property<LogicalLength>,
pub enabled: Property<bool>,
pub has_focus: Property<bool>,
pub toggled: Callback<VoidArg>,
@ -73,18 +69,14 @@ impl Item for NativeCheckBox {
self: Pin<&Self>,
event: MouseEvent,
_window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &i_slint_core::items::ItemRc,
self_rc: &i_slint_core::items::ItemRc,
) -> InputEventResult {
if !self.enabled() {
return InputEventResult::EventIgnored;
}
if let MouseEvent::Released { position, .. } = event {
if LogicalRect::new(
LogicalPoint::default(),
LogicalSize::from_lengths(self.width(), self.height()),
)
.contains(position)
{
let geo = self_rc.geometry();
if LogicalRect::new(LogicalPoint::default(), geo.size).contains(position) {
Self::FIELD_OFFSETS.checked.apply_pin(self).set(!self.checked());
Self::FIELD_OFFSETS.toggled.apply_pin(self).call(&())
}

View file

@ -9,10 +9,6 @@ use super::*;
#[derive(FieldOffsets, Default, SlintElement)]
#[pin]
pub struct NativeComboBox {
pub x: Property<LogicalLength>,
pub y: Property<LogicalLength>,
pub width: Property<LogicalLength>,
pub height: Property<LogicalLength>,
pub enabled: Property<bool>,
pub pressed: Property<bool>,
pub is_open: Property<bool>,
@ -145,10 +141,6 @@ fn slint_get_NativeComboBoxVTable() -> NativeComboBoxVTable for NativeComboBox
#[derive(FieldOffsets, Default, SlintElement)]
#[pin]
pub struct NativeComboBoxPopup {
pub x: Property<LogicalLength>,
pub y: Property<LogicalLength>,
pub width: Property<LogicalLength>,
pub height: Property<LogicalLength>,
widget_ptr: std::cell::Cell<SlintTypeErasedWidgetPtr>,
animation_tracker: Property<i32>,
pub cached_rendering_data: CachedRenderingData,

View file

@ -9,10 +9,6 @@ use super::*;
#[derive(FieldOffsets, Default, SlintElement)]
#[pin]
pub struct NativeGroupBox {
pub x: Property<LogicalLength>,
pub y: Property<LogicalLength>,
pub width: Property<LogicalLength>,
pub height: Property<LogicalLength>,
pub enabled: Property<bool>,
pub title: Property<SharedString>,
pub cached_rendering_data: CachedRenderingData,

View file

@ -10,10 +10,6 @@ use super::*;
#[derive(FieldOffsets, Default, SlintElement)]
#[pin]
pub struct NativeLineEdit {
pub x: Property<LogicalLength>,
pub y: Property<LogicalLength>,
pub width: Property<LogicalLength>,
pub height: Property<LogicalLength>,
pub cached_rendering_data: CachedRenderingData,
pub native_padding_left: Property<LogicalLength>,
pub native_padding_right: Property<LogicalLength>,

View file

@ -9,10 +9,6 @@ use super::*;
#[derive(FieldOffsets, Default, SlintElement)]
#[pin]
pub struct NativeStandardListViewItem {
pub x: Property<LogicalLength>,
pub y: Property<LogicalLength>,
pub width: Property<LogicalLength>,
pub height: Property<LogicalLength>,
pub item: Property<i_slint_core::model::StandardListViewItem>,
pub index: Property<i32>,
pub is_selected: Property<bool>,

View file

@ -9,10 +9,6 @@ use super::*;
#[derive(FieldOffsets, Default, SlintElement)]
#[pin]
pub struct NativeProgressIndicator {
pub x: Property<LogicalLength>,
pub y: Property<LogicalLength>,
pub width: Property<LogicalLength>,
pub height: Property<LogicalLength>,
pub indeterminate: Property<bool>,
pub progress: Property<f32>,
widget_ptr: std::cell::Cell<SlintTypeErasedWidgetPtr>,

View file

@ -9,10 +9,6 @@ use super::*;
#[derive(FieldOffsets, Default, SlintElement)]
#[pin]
pub struct NativeScrollView {
pub x: Property<LogicalLength>,
pub y: Property<LogicalLength>,
pub width: Property<LogicalLength>,
pub height: Property<LogicalLength>,
pub horizontal_max: Property<LogicalLength>,
pub horizontal_page_size: Property<LogicalLength>,
pub horizontal_value: Property<LogicalLength>,
@ -119,9 +115,9 @@ impl Item for NativeScrollView {
self: Pin<&Self>,
event: MouseEvent,
_window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &i_slint_core::items::ItemRc,
self_rc: &i_slint_core::items::ItemRc,
) -> InputEventResult {
let size: qttypes::QSize = get_size!(self);
let size: qttypes::QSize = get_size!(self_rc);
let mut data = self.data();
let active_controls = data.active_controls;
let pressed = data.pressed;

View file

@ -22,10 +22,6 @@ type FloatArg = (f32,);
#[derive(FieldOffsets, Default, SlintElement)]
#[pin]
pub struct NativeSlider {
pub x: Property<LogicalLength>,
pub y: Property<LogicalLength>,
pub width: Property<LogicalLength>,
pub height: Property<LogicalLength>,
pub orientation: Property<Orientation>,
pub enabled: Property<bool>,
pub value: Property<f32>,
@ -146,9 +142,9 @@ impl Item for NativeSlider {
self: Pin<&Self>,
event: MouseEvent,
_window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &i_slint_core::items::ItemRc,
self_rc: &i_slint_core::items::ItemRc,
) -> InputEventResult {
let size: qttypes::QSize = get_size!(self);
let size: qttypes::QSize = get_size!(self_rc);
let enabled = self.enabled();
let value = self.value();
let min = self.minimum();

View file

@ -18,10 +18,6 @@ type IntArg = (i32,);
#[derive(FieldOffsets, Default, SlintElement)]
#[pin]
pub struct NativeSpinBox {
pub x: Property<LogicalLength>,
pub y: Property<LogicalLength>,
pub width: Property<LogicalLength>,
pub height: Property<LogicalLength>,
pub enabled: Property<bool>,
pub has_focus: Property<bool>,
pub value: Property<i32>,
@ -128,7 +124,7 @@ impl Item for NativeSpinBox {
window_adapter: &Rc<dyn WindowAdapter>,
self_rc: &i_slint_core::items::ItemRc,
) -> InputEventResult {
let size: qttypes::QSize = get_size!(self);
let size: qttypes::QSize = get_size!(self_rc);
let enabled = self.enabled();
let mut data = self.data();
let active_controls = data.active_controls;

View file

@ -9,10 +9,6 @@ use super::*;
#[derive(FieldOffsets, Default, SlintElement)]
#[pin]
pub struct NativeTableHeaderSection {
pub x: Property<LogicalLength>,
pub y: Property<LogicalLength>,
pub width: Property<LogicalLength>,
pub height: Property<LogicalLength>,
pub item: Property<i_slint_core::model::TableColumn>,
pub index: Property<i32>,
pub cached_rendering_data: CachedRenderingData,

View file

@ -11,8 +11,6 @@ use super::*;
#[derive(FieldOffsets, Default, SlintElement)]
#[pin]
pub struct NativeTabWidget {
pub x: Property<LogicalLength>,
pub y: Property<LogicalLength>,
pub width: Property<LogicalLength>,
pub height: Property<LogicalLength>,
pub cached_rendering_data: CachedRenderingData,
@ -332,10 +330,6 @@ fn slint_get_NativeTabWidgetVTable() -> NativeTabWidgetVTable for NativeTabWidge
#[derive(FieldOffsets, Default, SlintElement)]
#[pin]
pub struct NativeTab {
pub x: Property<LogicalLength>,
pub y: Property<LogicalLength>,
pub width: Property<LogicalLength>,
pub height: Property<LogicalLength>,
pub title: Property<SharedString>,
pub icon: Property<i_slint_core::graphics::Image>,
pub enabled: Property<bool>,

View file

@ -789,8 +789,8 @@ impl ItemRenderer for QtItemRenderer<'_> {
}}
}
fn draw_path(&mut self, path: Pin<&items::Path>, _: &ItemRc, size: LogicalSize) {
let (offset, path_events) = match path.fitted_path_events() {
fn draw_path(&mut self, path: Pin<&items::Path>, item_rc: &ItemRc, size: LogicalSize) {
let (offset, path_events) = match path.fitted_path_events(item_rc) {
Some(offset_and_events) => offset_and_events,
None => return,
};

View file

@ -21,10 +21,6 @@
*/
component Empty {
in property <length> x;
in property <length> y;
in property <length> width;
in property <length> height;
//-is_internal
}
@ -43,6 +39,8 @@ component BorderRectangle inherits Rectangle {
export { BorderRectangle as Rectangle }
component ImageItem inherits Empty {
in property <length> width;
in property <length> height;
in property <image> source;
in property <ImageFit> image-fit;
in property <ImageRendering> image-rendering;
@ -74,6 +72,8 @@ export component Rotate inherits Empty {
}
export component Text inherits Empty {
in property <length> width;
in property <length> height;
in property <string> text;
in property <string> font-family;
in property <length> font-size;
@ -89,10 +89,6 @@ export component Text inherits Empty {
}
export component TouchArea {
in property <length> x;
in property <length> y;
in property <length> width;
in property <length> height;
in property <bool> enabled: true;
out property <bool> pressed;
out property <bool> has_hover;
@ -108,10 +104,6 @@ export component TouchArea {
}
export component FocusScope {
in property <length> x;
in property <length> y;
in property <length> width;
in property <length> height;
in property <bool> enabled: true;
out property <bool> has-focus;
callback key_pressed(KeyEvent) -> EventResult;
@ -168,8 +160,6 @@ export component TextInput {
in property <TextVerticalAlignment> vertical-alignment;
in property <TextWrap> wrap;
in property <length> letter-spacing;
in property <length> x;
in property <length> y;
in property <length> width;
in property <length> height;
in property <length> text-cursor-width; // StyleMetrics.text-cursor-width set in apply_default_properties_from_style
@ -197,10 +187,6 @@ export component TextInput {
}
export component Clip {
in property <length> x;
in property <length> y;
in property <length> width;
in property <length> height;
in property <length> border-radius;
in property <length> border-width;
in property <bool> clip;
@ -209,10 +195,6 @@ export component Clip {
}
export component Opacity {
in property <length> x;
in property <length> y;
in property <length> width;
in property <length> height;
in property <float> opacity: 1;
//-default_size_binding:expands_to_parent_geometry
//-is_internal
@ -310,10 +292,6 @@ component Close {
}
export component Path {
in property <length> x;
in property <length> y;
in property <length> width;
in property <length> height;
in property <brush> fill;
in property <FillRule> fill-rule;
in property <brush> stroke;
@ -342,11 +320,6 @@ component Tab {
// Note: not a native class, handled in the lower_tabs pass
export component TabWidget {
in property <length> x;
in property <length> y;
in property <length> width;
in property <length> height;
in-out property <int> current-index;
//-disallow_global_types_as_child_elements
@ -384,10 +357,6 @@ export global TextInputInterface {
}
export component NativeButton {
in property <length> x;
in property <length> y;
in property <length> width;
in property <length> height;
in property <string> text;
in property <image> icon;
out property <bool> pressed;
@ -403,10 +372,6 @@ export component NativeButton {
}
export component NativeCheckBox {
in property <length> x;
in property <length> y;
in property <length> width;
in property <length> height;
in property <bool> enabled: true;
in property <string> text;
in-out property <bool> checked;
@ -416,10 +381,6 @@ export component NativeCheckBox {
}
export component NativeSpinBox {
in property <length> x;
in property <length> y;
in property <length> width;
in property <length> height;
in property <bool> enabled: true;
out property <bool> has-focus;
in-out property <int> value;
@ -430,10 +391,6 @@ export component NativeSpinBox {
}
export component NativeSlider {
in property <length> x;
in property <length> y;
in property <length> width;
in property <length> height;
in property <bool> enabled: true;
in-out property <float> value;
in property <float> minimum;
@ -444,20 +401,12 @@ export component NativeSlider {
}
export component NativeProgressIndicator {
in property <length> x;
in property <length> y;
in property <length> width;
in property <length> height;
in property <bool> indeterminate;
in property <float> progress;
//-is_internal
}
export component NativeGroupBox {
in property <length> x;
in property <length> y;
in property <length> width;
in property <length> height;
in property <bool> enabled: true;
in property <string> title;
out property <length> native-padding-left;
@ -469,10 +418,6 @@ export component NativeGroupBox {
}
export component NativeLineEdit {
in property <length> x;
in property <length> y;
in property <length> width;
in property <length> height;
out property <length> native-padding-left;
out property <length> native-padding-right;
out property <length> native-padding-top;
@ -483,10 +428,6 @@ export component NativeLineEdit {
}
export component NativeScrollView {
in property <length> x;
in property <length> y;
in property <length> width;
in property <length> height;
in property <length> horizontal-max;
in property <length> horizontal-page-size;
in property <length> horizontal-value;
@ -504,10 +445,6 @@ export component NativeScrollView {
}
export component NativeStandardListViewItem {
in property <length> x;
in property <length> y;
in property <length> width;
in property <length> height;
in property <int> index;
in property <StandardListViewItem> item;
in-out property <bool> is_selected;
@ -517,10 +454,6 @@ export component NativeStandardListViewItem {
}
export component NativeTableHeaderSection {
in property <length> x;
in property <length> y;
in property <length> width;
in property <length> height;
in property <int> index;
in property <TableColumn> item;
in property <bool> has_hover;
@ -528,26 +461,16 @@ export component NativeTableHeaderSection {
}
export component NativeComboBox {
in property <length> x;
in property <length> y;
in property <length> width;
in property <length> height;
in-out property <string> current_value;
in property <bool> enabled: true;
//-is_internal
}
export component NativeComboBoxPopup {
in property <length> x;
in property <length> y;
in property <length> width;
in property <length> height;
//-is_internal
}
export component NativeTabWidget {
in property <length> x;
in property <length> y;
in property <length> width;
in property <length> height;
@ -571,11 +494,6 @@ export component NativeTabWidget {
}
export component NativeTab {
in property <length> x;
in property <length> y;
in property <length> width;
in property <length> height;
in property<string> title;
in property<image> icon;
in property<bool> enabled : true;

View file

@ -9,6 +9,7 @@ use std::{cell::RefCell, collections::BTreeMap};
use super::euclid;
use crate::items::ItemRc;
use crate::lengths::RectLengths;
use crate::{
lengths::{PhysicalPx, ScaleFactor},
Color,
@ -57,6 +58,7 @@ impl BoxShadowOptions {
/// coordinates to physical pixels used in the BoxShadowOptions. Returns None if for example the
/// alpha on the box shadow would imply that no shadow is to be rendered.
pub fn new(
item_rc: &ItemRc,
box_shadow: std::pin::Pin<&crate::items::BoxShadow>,
scale_factor: ScaleFactor,
) -> Option<Self> {
@ -64,8 +66,9 @@ impl BoxShadowOptions {
if color.alpha() == 0 {
return None;
}
let width = box_shadow.width() * scale_factor;
let height = box_shadow.height() * scale_factor;
let geometry = item_rc.geometry();
let width = geometry.width_length() * scale_factor;
let height = geometry.height_length() * scale_factor;
if width.get() < 1. || height.get() < 1. {
return None;
}
@ -99,7 +102,7 @@ impl<ImageType: Clone> BoxShadowCache<ImageType> {
shadow_render_fn: impl FnOnce(&BoxShadowOptions) -> ImageType,
) -> Option<ImageType> {
item_cache.get_or_update_cache_entry(item_rc, || {
let shadow_options = BoxShadowOptions::new(box_shadow, scale_factor)?;
let shadow_options = BoxShadowOptions::new(item_rc, box_shadow, scale_factor)?;
self.0
.borrow_mut()
.entry(shadow_options.clone())

View file

@ -29,7 +29,7 @@ use crate::item_rendering::CachedRenderingData;
pub use crate::item_tree::ItemRc;
use crate::layout::LayoutInfo;
use crate::lengths::{
LogicalLength, LogicalPoint, LogicalRect, LogicalSize, LogicalVector, PointLengths,
LogicalLength, LogicalPoint, LogicalRect, LogicalSize, LogicalVector, PointLengths, RectLengths,
};
#[cfg(feature = "rtti")]
use crate::rtti::*;
@ -174,10 +174,6 @@ pub type ItemRef<'a> = vtable::VRef<'a, ItemVTable>;
#[pin]
/// The implementation of an empty items that does nothing
pub struct Empty {
pub x: Property<LogicalLength>,
pub y: Property<LogicalLength>,
pub width: Property<LogicalLength>,
pub height: Property<LogicalLength>,
pub cached_rendering_data: CachedRenderingData,
}
@ -255,10 +251,6 @@ declare_item_vtable! {
/// The implementation of the `Rectangle` element
pub struct Rectangle {
pub background: Property<Brush>,
pub x: Property<LogicalLength>,
pub y: Property<LogicalLength>,
pub width: Property<LogicalLength>,
pub height: Property<LogicalLength>,
pub cached_rendering_data: CachedRenderingData,
}
@ -337,10 +329,6 @@ declare_item_vtable! {
/// The implementation of the `BorderRectangle` element
pub struct BorderRectangle {
pub background: Property<Brush>,
pub x: Property<LogicalLength>,
pub y: Property<LogicalLength>,
pub width: Property<LogicalLength>,
pub height: Property<LogicalLength>,
pub border_width: Property<LogicalLength>,
pub border_radius: Property<LogicalLength>,
pub border_color: Property<Brush>,
@ -421,10 +409,6 @@ declare_item_vtable! {
#[derive(FieldOffsets, Default, SlintElement)]
#[pin]
pub struct TouchArea {
pub x: Property<LogicalLength>,
pub y: Property<LogicalLength>,
pub width: Property<LogicalLength>,
pub height: Property<LogicalLength>,
pub enabled: Property<bool>,
/// FIXME: We should annotate this as an "output" property.
pub pressed: Property<bool>,
@ -485,7 +469,7 @@ impl Item for TouchArea {
self: Pin<&Self>,
event: MouseEvent,
window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
self_rc: &ItemRc,
) -> InputEventResult {
if matches!(event, MouseEvent::Exit) {
Self::FIELD_OFFSETS.has_hover.apply_pin(self).set(false);
@ -497,12 +481,9 @@ impl Item for TouchArea {
return InputEventResult::EventIgnored;
}
let result = if let MouseEvent::Released { position, button, .. } = event {
let geometry = self_rc.geometry();
if button == PointerEventButton::Left
&& LogicalRect::new(
LogicalPoint::default(),
LogicalSize::from_lengths(self.width(), self.height()),
)
.contains(position)
&& LogicalRect::new(LogicalPoint::default(), geometry.size).contains(position)
&& self.pressed()
{
Self::FIELD_OFFSETS.clicked.apply_pin(self).call(&());
@ -610,10 +591,6 @@ declare_item_vtable! {
#[derive(FieldOffsets, Default, SlintElement)]
#[pin]
pub struct FocusScope {
pub x: Property<LogicalLength>,
pub y: Property<LogicalLength>,
pub width: Property<LogicalLength>,
pub height: Property<LogicalLength>,
pub enabled: Property<bool>,
pub has_focus: Property<bool>,
pub key_pressed: Callback<KeyEventArg, EventResult>,
@ -726,10 +703,6 @@ declare_item_vtable! {
#[pin]
/// The implementation of the `Clip` element
pub struct Clip {
pub x: Property<LogicalLength>,
pub y: Property<LogicalLength>,
pub width: Property<LogicalLength>,
pub height: Property<LogicalLength>,
pub border_radius: Property<LogicalLength>,
pub border_width: Property<LogicalLength>,
pub cached_rendering_data: CachedRenderingData,
@ -751,14 +724,15 @@ impl Item for Clip {
self: Pin<&Self>,
event: MouseEvent,
_window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
self_rc: &ItemRc,
) -> InputEventFilterResult {
if let Some(pos) = event.position() {
let geometry = self_rc.geometry();
if self.clip()
&& (pos.x < 0 as Coord
|| pos.y < 0 as Coord
|| pos.x_length() > self.width()
|| pos.y_length() > self.height())
|| pos.x_length() > geometry.width_length()
|| pos.y_length() > geometry.height_length())
{
return InputEventFilterResult::Intercept;
}
@ -818,10 +792,6 @@ declare_item_vtable! {
/// The Opacity Item is not meant to be used directly by the .slint code, instead, the `opacity: xxx` or `visible: false` should be used
pub struct Opacity {
// FIXME: this element shouldn't need these geometry property
pub x: Property<LogicalLength>,
pub y: Property<LogicalLength>,
pub width: Property<LogicalLength>,
pub height: Property<LogicalLength>,
pub opacity: Property<f32>,
pub cached_rendering_data: CachedRenderingData,
}
@ -926,11 +896,6 @@ declare_item_vtable! {
#[pin]
/// The Layer Item is not meant to be used directly by the .slint code, instead, the `layer: xxx` property should be used
pub struct Layer {
// FIXME: this element shouldn't need these geometry property
pub x: Property<LogicalLength>,
pub y: Property<LogicalLength>,
pub width: Property<LogicalLength>,
pub height: Property<LogicalLength>,
pub cache_rendering_hint: Property<bool>,
pub cached_rendering_data: CachedRenderingData,
}
@ -1008,13 +973,9 @@ declare_item_vtable! {
#[pin]
/// The implementation of the `Rotate` element
pub struct Rotate {
pub x: Property<LogicalLength>,
pub y: Property<LogicalLength>,
pub rotation_angle: Property<f32>,
pub rotation_origin_x: Property<LogicalLength>,
pub rotation_origin_y: Property<LogicalLength>,
pub width: Property<LogicalLength>,
pub height: Property<LogicalLength>,
pub cached_rendering_data: CachedRenderingData,
}
@ -1236,11 +1197,6 @@ declare_item_vtable! {
#[derive(FieldOffsets, Default, SlintElement)]
#[pin]
pub struct BoxShadow {
// Rectangle properties
pub x: Property<LogicalLength>,
pub y: Property<LogicalLength>,
pub width: Property<LogicalLength>,
pub height: Property<LogicalLength>,
pub border_radius: Property<LogicalLength>,
// Shadow specific properties
pub offset_x: Property<LogicalLength>,

View file

@ -16,7 +16,7 @@ use crate::item_rendering::CachedRenderingData;
use crate::items::PropertyAnimation;
use crate::layout::{LayoutInfo, Orientation};
use crate::lengths::{
LogicalLength, LogicalPoint, LogicalRect, LogicalSize, LogicalVector, PointLengths,
LogicalLength, LogicalPoint, LogicalRect, LogicalSize, LogicalVector, PointLengths, RectLengths,
};
#[cfg(feature = "rtti")]
use crate::rtti::*;
@ -41,11 +41,6 @@ use num_traits::Float;
#[derive(FieldOffsets, Default, SlintElement)]
#[pin]
pub struct Flickable {
pub x: Property<LogicalLength>,
pub y: Property<LogicalLength>,
pub width: Property<LogicalLength>,
pub height: Property<LogicalLength>,
pub viewport_x: Property<LogicalLength>,
pub viewport_y: Property<LogicalLength>,
pub viewport_width: Property<LogicalLength>,
@ -73,13 +68,14 @@ impl Item for Flickable {
self: Pin<&Self>,
event: MouseEvent,
_window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
self_rc: &ItemRc,
) -> InputEventFilterResult {
if let Some(pos) = event.position() {
let geometry = self_rc.geometry();
if pos.x < 0 as _
|| pos.y < 0 as _
|| pos.x_length() > self.width()
|| pos.y_length() > self.height()
|| pos.x_length() > geometry.width_length()
|| pos.y_length() > geometry.height_length()
{
return InputEventFilterResult::Intercept;
}
@ -87,30 +83,31 @@ impl Item for Flickable {
if !self.interactive() && !matches!(event, MouseEvent::Wheel { .. }) {
return InputEventFilterResult::ForwardAndIgnore;
}
self.data.handle_mouse_filter(self, event)
self.data.handle_mouse_filter(self, event, self_rc)
}
fn input_event(
self: Pin<&Self>,
event: MouseEvent,
window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
self_rc: &ItemRc,
) -> InputEventResult {
if !self.interactive() && !matches!(event, MouseEvent::Wheel { .. }) {
return InputEventResult::EventIgnored;
}
if let Some(pos) = event.position() {
let geometry = self_rc.geometry();
if matches!(event, MouseEvent::Wheel { .. } | MouseEvent::Pressed { .. })
&& (pos.x < 0 as _
|| pos.y < 0 as _
|| pos.x_length() > self.width()
|| pos.y_length() > self.height())
|| pos.x_length() > geometry.width_length()
|| pos.y_length() > geometry.height_length())
{
return InputEventResult::EventIgnored;
}
}
self.data.handle_mouse(self, event, window_adapter)
self.data.handle_mouse(self, event, window_adapter, self_rc)
}
fn key_event(
@ -196,10 +193,11 @@ pub struct FlickableData {
}
impl FlickableData {
pub fn handle_mouse_filter(
fn handle_mouse_filter(
&self,
flick: Pin<&Flickable>,
event: MouseEvent,
flick_rc: &ItemRc,
) -> InputEventFilterResult {
let mut inner = self.inner.borrow_mut();
match event {
@ -218,7 +216,7 @@ impl FlickableData {
}
MouseEvent::Exit | MouseEvent::Released { button: PointerEventButton::Left, .. } => {
let was_capturing = inner.capture_events;
Self::mouse_released(&mut inner, flick, event);
Self::mouse_released(&mut inner, flick, event, flick_rc);
if was_capturing {
InputEventFilterResult::Intercept
} else {
@ -234,8 +232,9 @@ impl FlickableData {
// Check if the mouse was moved more than the DISTANCE_THRESHOLD in a
// direction in which the flickable can flick
let diff = position - inner.pressed_pos;
let w = flick.width();
let h = flick.height();
let geo = flick_rc.geometry();
let w = geo.width_length();
let h = geo.height_length();
let vw = (Flickable::FIELD_OFFSETS.viewport_width).apply_pin(flick).get();
let vh = (Flickable::FIELD_OFFSETS.viewport_height).apply_pin(flick).get();
let x = (Flickable::FIELD_OFFSETS.viewport_x).apply_pin(flick).get();
@ -262,11 +261,12 @@ impl FlickableData {
}
}
pub fn handle_mouse(
fn handle_mouse(
&self,
flick: Pin<&Flickable>,
event: MouseEvent,
window_adapter: &Rc<dyn WindowAdapter>,
flick_rc: &ItemRc,
) -> InputEventResult {
let mut inner = self.inner.borrow_mut();
match event {
@ -276,7 +276,7 @@ impl FlickableData {
}
MouseEvent::Exit | MouseEvent::Released { .. } => {
let was_capturing = inner.capture_events;
Self::mouse_released(&mut inner, flick, event);
Self::mouse_released(&mut inner, flick, event, flick_rc);
if was_capturing {
InputEventResult::EventAccepted
} else {
@ -289,8 +289,9 @@ impl FlickableData {
let x = (Flickable::FIELD_OFFSETS.viewport_x).apply_pin(flick);
let y = (Flickable::FIELD_OFFSETS.viewport_y).apply_pin(flick);
let should_capture = || {
let w = flick.width();
let h = flick.height();
let geo = flick_rc.geometry();
let w = geo.width_length();
let h = geo.height_length();
let vw = (Flickable::FIELD_OFFSETS.viewport_width).apply_pin(flick).get();
let vh = (Flickable::FIELD_OFFSETS.viewport_height).apply_pin(flick).get();
let zero = LogicalLength::zero();
@ -301,7 +302,7 @@ impl FlickableData {
};
if inner.capture_events || should_capture() {
let new_pos = ensure_in_bound(flick, new_pos);
let new_pos = ensure_in_bound(flick, new_pos, flick_rc);
x.set(new_pos.x_length());
y.set(new_pos.y_length());
inner.capture_events = true;
@ -327,7 +328,7 @@ impl FlickableData {
} else {
LogicalVector::new(delta_x as _, delta_y as _)
};
let new_pos = ensure_in_bound(flick, old_pos + delta);
let new_pos = ensure_in_bound(flick, old_pos + delta, flick_rc);
(Flickable::FIELD_OFFSETS.viewport_x).apply_pin(flick).set(new_pos.x_length());
(Flickable::FIELD_OFFSETS.viewport_y).apply_pin(flick).set(new_pos.y_length());
InputEventResult::EventAccepted
@ -335,7 +336,12 @@ impl FlickableData {
}
}
fn mouse_released(inner: &mut FlickableDataInner, flick: Pin<&Flickable>, event: MouseEvent) {
fn mouse_released(
inner: &mut FlickableDataInner,
flick: Pin<&Flickable>,
event: MouseEvent,
flick_rc: &ItemRc,
) {
if let (Some(pressed_time), Some(pos)) = (inner.pressed_time, event.position()) {
let dist = (pos - inner.pressed_pos).cast::<f32>();
@ -350,6 +356,7 @@ impl FlickableData {
let final_pos = ensure_in_bound(
flick,
(inner.pressed_viewport_pos.cast() + dist + speed * (duration as f32)).cast(),
flick_rc,
);
let anim = PropertyAnimation {
duration,
@ -374,9 +381,10 @@ fn abs(l: LogicalLength) -> LogicalLength {
}
/// Make sure that the point is within the bounds
fn ensure_in_bound(flick: Pin<&Flickable>, p: LogicalPoint) -> LogicalPoint {
let w = flick.width();
let h = flick.height();
fn ensure_in_bound(flick: Pin<&Flickable>, p: LogicalPoint, flick_rc: &ItemRc) -> LogicalPoint {
let geo = flick_rc.geometry();
let w = geo.width_length();
let h = geo.height_length();
let vw = (Flickable::FIELD_OFFSETS.viewport_width).apply_pin(flick).get();
let vh = (Flickable::FIELD_OFFSETS.viewport_height).apply_pin(flick).get();

View file

@ -31,8 +31,6 @@ use i_slint_core_macros::*;
/// The implementation of the `Image` element
pub struct ImageItem {
pub source: Property<crate::graphics::Image>,
pub x: Property<LogicalLength>,
pub y: Property<LogicalLength>,
pub width: Property<LogicalLength>,
pub height: Property<LogicalLength>,
pub image_fit: Property<ImageFit>,
@ -122,8 +120,6 @@ impl ItemConsts for ImageItem {
/// The implementation of the `ClippedImage` element
pub struct ClippedImage {
pub source: Property<crate::graphics::Image>,
pub x: Property<LogicalLength>,
pub y: Property<LogicalLength>,
pub width: Property<LogicalLength>,
pub height: Property<LogicalLength>,
pub image_fit: Property<ImageFit>,

View file

@ -17,7 +17,7 @@ use crate::input::{
use crate::item_rendering::CachedRenderingData;
use crate::layout::{LayoutInfo, Orientation};
use crate::lengths::{LogicalLength, LogicalSize, LogicalVector, PointLengths};
use crate::lengths::{LogicalLength, LogicalSize, LogicalVector, PointLengths, RectLengths};
#[cfg(feature = "rtti")]
use crate::rtti::*;
use crate::window::WindowAdapter;
@ -33,10 +33,6 @@ use i_slint_core_macros::*;
#[derive(FieldOffsets, Default, SlintElement)]
#[pin]
pub struct Path {
pub x: Property<LogicalLength>,
pub y: Property<LogicalLength>,
pub width: Property<LogicalLength>,
pub height: Property<LogicalLength>,
pub elements: Property<PathData>,
pub fill: Property<Brush>,
pub fill_rule: Property<FillRule>,
@ -65,14 +61,15 @@ impl Item for Path {
self: Pin<&Self>,
event: MouseEvent,
_window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
self_rc: &ItemRc,
) -> InputEventFilterResult {
if let Some(pos) = event.position() {
let geometry = self_rc.geometry();
if self.clip()
&& (pos.x < 0 as _
|| pos.y < 0 as _
|| pos.x_length() > self.width()
|| pos.y_length() > self.height())
|| pos.x_length() > geometry.width_length()
|| pos.y_length() > geometry.height_length())
{
return InputEventFilterResult::Intercept;
}
@ -130,12 +127,16 @@ impl Path {
/// Returns an iterator of the events of the path and an offset, so that the
/// shape fits into the width/height of the path while respecting the stroke
/// width.
pub fn fitted_path_events(self: Pin<&Self>) -> Option<(LogicalVector, PathDataIterator)> {
pub fn fitted_path_events(
self: Pin<&Self>,
self_rc: &ItemRc,
) -> Option<(LogicalVector, PathDataIterator)> {
let mut elements_iter = self.elements().iter()?;
let stroke_width = self.stroke_width();
let bounds_width = (self.width() - stroke_width).max(LogicalLength::zero());
let bounds_height = (self.height() - stroke_width).max(LogicalLength::zero());
let geometry = self_rc.geometry();
let bounds_width = (geometry.width_length() - stroke_width).max(LogicalLength::zero());
let bounds_height = (geometry.height_length() - stroke_width).max(LogicalLength::zero());
let offset =
LogicalVector::from_lengths(stroke_width / 2 as Coord, stroke_width / 2 as Coord);

View file

@ -50,8 +50,6 @@ pub struct Text {
pub wrap: Property<TextWrap>,
pub overflow: Property<TextOverflow>,
pub letter_spacing: Property<LogicalLength>,
pub x: Property<LogicalLength>,
pub y: Property<LogicalLength>,
pub width: Property<LogicalLength>,
pub height: Property<LogicalLength>,
pub cached_rendering_data: CachedRenderingData,
@ -220,8 +218,6 @@ pub struct TextInput {
pub wrap: Property<TextWrap>,
pub input_type: Property<InputType>,
pub letter_spacing: Property<LogicalLength>,
pub x: Property<LogicalLength>,
pub y: Property<LogicalLength>,
pub width: Property<LogicalLength>,
pub height: Property<LogicalLength>,
pub cursor_position_byte_offset: Property<i32>,

View file

@ -533,12 +533,12 @@ impl<'a> ItemRenderer for GLItemRenderer<'a> {
}
}
fn draw_path(&mut self, path: Pin<&items::Path>, _: &ItemRc, _size: LogicalSize) {
fn draw_path(&mut self, path: Pin<&items::Path>, item_rc: &ItemRc, _size: LogicalSize) {
if self.global_alpha_transparent() {
return;
}
let (offset, path_events) = match path.fitted_path_events() {
let (offset, path_events) = match path.fitted_path_events(item_rc) {
Some(offset_and_events) => offset_and_events,
None => return,
};

View file

@ -577,7 +577,7 @@ impl<'a> ItemRenderer for SkiaItemRenderer<'a> {
let (physical_offset, skpath): (crate::euclid::Vector2D<f32, PhysicalPx>, _) =
match self.path_cache.get_or_update_cache_entry(item_rc, || {
let (logical_offset, path_events): (crate::euclid::Vector2D<f32, LogicalPx>, _) =
path.fitted_path_events()?;
path.fitted_path_events(item_rc)?;
let mut skpath = skia_safe::Path::new();