From 76682193517a28b028e9a9df9b8292b25bf68848 Mon Sep 17 00:00:00 2001 From: Mario Krehl Date: Mon, 29 May 2023 09:37:01 +0200 Subject: [PATCH 1/3] Add changelog entry for transform-origin-properties --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e1e81922..84c0486c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ All notable changes to eww will be listed here, starting at changes since versio - Add scss support for the `:style` widget property (By: ovalkonia) - Add `min` and `max` function calls to simplexpr (By: ovalkonia) - Add `flip-x`, `flip-y`, `vertical` options to the graph widget to determine its direction +- Add `transform-origin-x`/`transform-origin-y` properties to transform widget (By: mario-kr) ## [0.6.0] (21.04.2024) From f76229e99c4cf955846f39d291f2dcaa406faa16 Mon Sep 17 00:00:00 2001 From: Mario Krehl Date: Thu, 25 May 2023 21:29:38 +0200 Subject: [PATCH 2/3] Implement explicitly setting a center of rotation The transform-Widget provides "rotate" to rotate its child. However, the default center of rotation is (0, 0) (aka top-left), so it was not possible to, for example, rotate a child in-place. This commit implements the additional options `transform-origin-x` and `transform-origin-y`. Both are optional, and the default value is 0.0 for each, so previous configurations should produce the same results. --- crates/eww/src/widgets/transform.rs | 28 +++++++++++++++++++- crates/eww/src/widgets/widget_definitions.rs | 4 +++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/crates/eww/src/widgets/transform.rs b/crates/eww/src/widgets/transform.rs index 79390ace..d7b672eb 100644 --- a/crates/eww/src/widgets/transform.rs +++ b/crates/eww/src/widgets/transform.rs @@ -17,6 +17,12 @@ pub struct TransformPriv { #[property(get, set, nick = "Rotate", blurb = "The Rotation", minimum = f64::MIN, maximum = f64::MAX, default = 0f64)] rotate: RefCell, + #[property(get, set, nick = "Transform-Origin X", blurb = "X coordinate (%/px) for the Transform-Origin", default = None)] + transform_origin_x: RefCell>, + + #[property(get, set, nick = "Transform-Origin Y", blurb = "Y coordinate (%/px) for the Transform-Origin", default = None)] + transform_origin_y: RefCell>, + #[property(get, set, nick = "Translate x", blurb = "The X Translation", default = None)] translate_x: RefCell>, @@ -37,6 +43,8 @@ impl Default for TransformPriv { fn default() -> Self { TransformPriv { rotate: RefCell::new(0.0), + transform_origin_x: RefCell::new(None), + transform_origin_y: RefCell::new(None), translate_x: RefCell::new(None), translate_y: RefCell::new(None), scale_x: RefCell::new(None), @@ -57,6 +65,14 @@ impl ObjectImpl for TransformPriv { self.rotate.replace(value.get().unwrap()); self.obj().queue_draw(); // Queue a draw call with the updated value } + "transform-origin-x" => { + self.transform_origin_x.replace(value.get().unwrap()); + self.obj().queue_draw(); // Queue a draw call with the updated value + } + "transform-origin-y" => { + self.transform_origin_y.replace(value.get().unwrap()); + self.obj().queue_draw(); // Queue a draw call with the updated value + } "translate-x" => { self.translate_x.replace(value.get().unwrap()); self.obj().queue_draw(); // Queue a draw call with the updated value @@ -128,6 +144,15 @@ impl WidgetImpl for TransformPriv { cr.save()?; + let transform_origin_x = match &*self.transform_origin_x.borrow() { + Some(rcx) => NumWithUnit::from_str(rcx)?.pixels_relative_to(total_width as i32) as f64, + None => 0.0, + }; + let transform_origin_y = match &*self.transform_origin_y.borrow() { + Some(rcy) => NumWithUnit::from_str(rcy)?.pixels_relative_to(total_height as i32) as f64, + None => 0.0, + }; + let translate_x = match &*self.translate_x.borrow() { Some(tx) => NumWithUnit::from_str(tx)?.pixels_relative_to(total_width as i32) as f64, None => 0.0, @@ -149,8 +174,9 @@ impl WidgetImpl for TransformPriv { }; cr.scale(scale_x, scale_y); + cr.translate(transform_origin_x, transform_origin_y); cr.rotate(perc_to_rad(rotate)); - cr.translate(translate_x, translate_y); + cr.translate(translate_x - transform_origin_x, translate_y - transform_origin_y); // Children widget if let Some(child) = &*self.content.borrow() { diff --git a/crates/eww/src/widgets/widget_definitions.rs b/crates/eww/src/widgets/widget_definitions.rs index 4cfd7621..0fb88f13 100644 --- a/crates/eww/src/widgets/widget_definitions.rs +++ b/crates/eww/src/widgets/widget_definitions.rs @@ -1188,6 +1188,10 @@ fn build_transform(bargs: &mut BuilderArgs) -> Result { def_widget!(bargs, _g, w, { // @prop rotate - the percentage to rotate prop(rotate: as_f64) { w.set_property("rotate", rotate); }, + // @prop transform-origin-x - x coordinate of origin of transformation (px or %) + prop(transform_origin_x: as_string) { w.set_property("transform-origin-x", transform_origin_x) }, + // @prop transform-origin-y - y coordinate of origin of transformation (px or %) + prop(transform_origin_y: as_string) { w.set_property("transform-origin-y", transform_origin_y) }, // @prop translate-x - the amount to translate in the x direction (px or %) prop(translate_x: as_string) { w.set_property("translate-x", translate_x); }, // @prop translate-y - the amount to translate in the y direction (px or %) From d3113ffe98a99856470144d9f1f3d91a3e8fbdcd Mon Sep 17 00:00:00 2001 From: Mario Krehl Date: Thu, 29 Aug 2024 19:33:03 +0200 Subject: [PATCH 3/3] Fix: transform order should be rotate->translate->scale --- crates/eww/src/widgets/transform.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/eww/src/widgets/transform.rs b/crates/eww/src/widgets/transform.rs index d7b672eb..5e184b64 100644 --- a/crates/eww/src/widgets/transform.rs +++ b/crates/eww/src/widgets/transform.rs @@ -173,10 +173,10 @@ impl WidgetImpl for TransformPriv { None => 1.0, }; - cr.scale(scale_x, scale_y); cr.translate(transform_origin_x, transform_origin_y); cr.rotate(perc_to_rad(rotate)); cr.translate(translate_x - transform_origin_x, translate_y - transform_origin_y); + cr.scale(scale_x, scale_y); // Children widget if let Some(child) = &*self.content.borrow() {