diff --git a/compositor_api/src/types/component.rs b/compositor_api/src/types/component.rs index c3a928eed..740e1f035 100644 --- a/compositor_api/src/types/component.rs +++ b/compositor_api/src/types/component.rs @@ -93,6 +93,15 @@ pub struct View { /// List of box shadows. pub box_shadow: Option>, + /// (**default=`0.0`**) Padding for all sides of the component. + pub padding: Option, + + /// (**default=`0.0`**) Padding for the top and bottom of the component. + pub padding_vertical: Option, + + /// (**default=`0.0`**) Padding for the left and right of the component. + pub padding_horizontal: Option, + /// (**default=`0.0`**) Padding on top side in pixels. pub padding_top: Option, diff --git a/compositor_api/src/types/from_component.rs b/compositor_api/src/types/from_component.rs index 13988454f..825e93f18 100644 --- a/compositor_api/src/types/from_component.rs +++ b/compositor_api/src/types/from_component.rs @@ -87,10 +87,26 @@ impl TryFrom for scene::ViewComponent { None => scene::Overflow::Hidden, }; let padding = scene::Padding { - top: view.padding_top.unwrap_or(0.0), - right: view.padding_right.unwrap_or(0.0), - bottom: view.padding_bottom.unwrap_or(0.0), - left: view.padding_left.unwrap_or(0.0), + top: view + .padding_top + .or(view.padding_vertical) + .or(view.padding) + .unwrap_or(0.0), + bottom: view + .padding_bottom + .or(view.padding_vertical) + .or(view.padding) + .unwrap_or(0.0), + left: view + .padding_left + .or(view.padding_horizontal) + .or(view.padding) + .unwrap_or(0.0), + right: view + .padding_right + .or(view.padding_horizontal) + .or(view.padding) + .unwrap_or(0.0), }; if padding.top < 0.0 || padding.right < 0.0 || padding.bottom < 0.0 || padding.left < 0.0 { diff --git a/compositor_render/src/scene/layout.rs b/compositor_render/src/scene/layout.rs index 55c161086..710661c46 100644 --- a/compositor_render/src/scene/layout.rs +++ b/compositor_render/src/scene/layout.rs @@ -8,7 +8,7 @@ use crate::{ use super::{ rescaler_component::StatefulRescalerComponent, tiles_component::StatefulTilesComponent, view_component::StatefulViewComponent, AbsolutePosition, BorderRadius, ComponentId, - HorizontalPosition, Padding, Position, RGBAColor, Size, StatefulComponent, VerticalPosition, + HorizontalPosition, Position, RGBAColor, Size, StatefulComponent, VerticalPosition, }; #[derive(Debug, Clone)] @@ -161,28 +161,18 @@ impl StatefulLayoutComponent { child: &mut StatefulComponent, position: AbsolutePosition, parent_size: Size, - child_padding: Padding, - parent_padding: Padding, pts: Duration, ) -> NestedLayout { - let width = position - .width - .unwrap_or(parent_size.width + child_padding.horizontal()); - let height = position - .height - .unwrap_or(parent_size.height + child_padding.vertical()); + let width = position.width.unwrap_or(parent_size.width); + let height = position.height.unwrap_or(parent_size.height); let top = match position.position_vertical { - VerticalPosition::TopOffset(top) => top + parent_padding.top, - VerticalPosition::BottomOffset(bottom) => { - parent_size.height - bottom - height - parent_padding.bottom + parent_padding.top - } + VerticalPosition::TopOffset(top) => top, + VerticalPosition::BottomOffset(bottom) => parent_size.height - bottom - height, }; let left = match position.position_horizontal { - HorizontalPosition::LeftOffset(left) => left + parent_padding.left, - HorizontalPosition::RightOffset(right) => { - parent_size.width - right - width - parent_padding.right + parent_padding.left - } + HorizontalPosition::LeftOffset(left) => left, + HorizontalPosition::RightOffset(right) => parent_size.width - right - width, }; let rotation_degrees = position.rotation_degrees; diff --git a/compositor_render/src/scene/view_component.rs b/compositor_render/src/scene/view_component.rs index 0f51bdd2b..7a3608234 100644 --- a/compositor_render/src/scene/view_component.rs +++ b/compositor_render/src/scene/view_component.rs @@ -66,10 +66,6 @@ impl StatefulViewComponent { .with_padding(view.padding) } - pub(super) fn padding(&self, pts: Duration) -> Padding { - self.view(pts).padding - } - pub(super) fn component_id(&self) -> Option<&ComponentId> { self.end.id.as_ref() } diff --git a/compositor_render/src/scene/view_component/layout.rs b/compositor_render/src/scene/view_component/layout.rs index cf77b15a9..9bfddf3f4 100644 --- a/compositor_render/src/scene/view_component/layout.rs +++ b/compositor_render/src/scene/view_component/layout.rs @@ -2,8 +2,8 @@ use std::time::Duration; use crate::{ scene::{ - layout::StatefulLayoutComponent, BorderRadius, Overflow, Padding, Position, RGBAColor, - Size, StatefulComponent, ViewChildrenDirection, + layout::StatefulLayoutComponent, BorderRadius, Overflow, Position, RGBAColor, Size, + StatefulComponent, ViewChildrenDirection, }, transformations::layout::{LayoutContent, Mask, NestedLayout}, }; @@ -72,18 +72,12 @@ impl ViewComponentParam { let children: Vec<_> = children .iter_mut() .map(|child| { - let (position, padding) = match child { - StatefulComponent::Layout(StatefulLayoutComponent::View(view)) => { - (view.position(pts), view.padding(pts)) - } - StatefulComponent::Layout(layout) => (layout.position(pts), Padding::default()), - ref non_layout_component => ( - Position::Static { - width: non_layout_component.width(pts), - height: non_layout_component.height(pts), - }, - Padding::default(), - ), + let position = match child { + StatefulComponent::Layout(layout) => layout.position(pts), + ref non_layout_component => Position::Static { + width: non_layout_component.width(pts), + height: non_layout_component.height(pts), + }, }; match position { Position::Static { width, height } => { @@ -105,12 +99,7 @@ impl ViewComponentParam { } Position::Absolute(position) => { StatefulLayoutComponent::layout_absolute_position_child( - child, - position, - size, - padding, - self.padding, - pts, + child, position, size, pts, ) } } @@ -143,27 +132,22 @@ impl ViewComponentParam { pts: Duration, ) -> (NestedLayout, f32) { let mut static_offset = opts.static_offset; - - let (static_width, static_height) = match self.direction { - ViewChildrenDirection::Row => (opts.static_child_size, opts.parent_size.height), - ViewChildrenDirection::Column => (opts.parent_size.width, opts.static_child_size), - }; - - // Parent padding can shrink the child if it doesn't have width/height provided - let static_width = static_width - self.padding.horizontal(); - let static_height = static_height - self.padding.vertical(); - - let width = opts.width.unwrap_or(static_width); - let height = opts.height.unwrap_or(static_height); - let (top, left, width, height) = match self.direction { ViewChildrenDirection::Row => { + let width = opts.width.unwrap_or(opts.static_child_size); + let height = opts + .height + .unwrap_or(opts.parent_size.height - self.padding.vertical()); let top = opts.parent_border_width + self.padding.top; let left = static_offset + self.padding.left; static_offset += width; (top, left, width, height) } ViewChildrenDirection::Column => { + let height = opts.height.unwrap_or(opts.static_child_size); + let width = opts + .width + .unwrap_or(opts.parent_size.width - self.padding.horizontal()); let top = static_offset + self.padding.top; let left = opts.parent_border_width + self.padding.left; static_offset += height; @@ -222,8 +206,8 @@ impl ViewComponentParam { /// size represents dimensions of content (without a border). fn static_child_size(&self, size: Size, children: &[StatefulComponent], pts: Duration) -> f32 { let max_size = match self.direction { - super::ViewChildrenDirection::Row => size.width, - super::ViewChildrenDirection::Column => size.height, + super::ViewChildrenDirection::Row => size.width - self.padding.horizontal(), + super::ViewChildrenDirection::Column => size.height - self.padding.vertical(), }; let children_with_unknown_size_count = Self::static_children_iter(children, pts) diff --git a/schemas/scene.schema.json b/schemas/scene.schema.json index 94f57f08d..c6a71b8ff 100644 --- a/schemas/scene.schema.json +++ b/schemas/scene.schema.json @@ -252,6 +252,30 @@ "$ref": "#/definitions/BoxShadow" } }, + "padding": { + "description": "(**default=`0.0`**) Padding for all sides of the component.", + "type": [ + "number", + "null" + ], + "format": "float" + }, + "padding_vertical": { + "description": "(**default=`0.0`**) Padding for the top and bottom of the component.", + "type": [ + "number", + "null" + ], + "format": "float" + }, + "padding_horizontal": { + "description": "(**default=`0.0`**) Padding for the left and right of the component.", + "type": [ + "number", + "null" + ], + "format": "float" + }, "padding_top": { "description": "(**default=`0.0`**) Padding on top side in pixels.", "type": [ diff --git a/snapshot_tests/snapshots b/snapshot_tests/snapshots index ee860bd99..08ee85a40 160000 --- a/snapshot_tests/snapshots +++ b/snapshot_tests/snapshots @@ -1 +1 @@ -Subproject commit ee860bd99af91b945a637c0efc8252f1cc35297e +Subproject commit 08ee85a40b0e54582e647f8261c783c1ab526b44 diff --git a/snapshot_tests/view/column_view_padding_static_children.scene.json b/snapshot_tests/view/column_view_padding_static_children.scene.json deleted file mode 100644 index de34427c2..000000000 --- a/snapshot_tests/view/column_view_padding_static_children.scene.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "video": { - "root": { - "type": "view", - "background_color": "#000000FF", - "children": [ - { - "type": "view", - "background_color": "#FF0000FF", - "direction": "column", - "width": 300, - "height": 300, - "children": [ - { - "type": "view", - "padding_top": 10, - "padding_left": 20, - "border_width": 4, - "border_color": "#FF00FFFF", - "background_color": "#0000FFFF", - "children": [] - }, - { - "type": "view", - "padding_top": 10, - "padding_bottom": 30, - "padding_right": 10, - "padding_left": 20, - "border_width": 4, - "border_color": "#0F0FF0FF", - "background_color": "#00FF00FF", - "children": [ - { - "type": "view", - "width": 250, - "height": 250, - "border_width": 4, - "border_color": "#FF00FFFF", - "background_color": "#00FFFFFF", - "children": [] - } - ] - } - ] - } - ] - } - } -} diff --git a/snapshot_tests/view/nested_padding_static_children.scene.json b/snapshot_tests/view/nested_padding_static_children.scene.json index 0b6a65fce..f3baf48b5 100644 --- a/snapshot_tests/view/nested_padding_static_children.scene.json +++ b/snapshot_tests/view/nested_padding_static_children.scene.json @@ -6,45 +6,40 @@ "children": [ { "type": "view", - "background_color": "#FF0000FF", + "background_color": "red", "direction": "row", - "width": 300, - "height": 300, "children": [ { "type": "view", - "padding_top": 10, - "padding_left": 5, - "border_width": 4, - "border_color": "#FF00FFFF", - "background_color": "#0000FFFF", + "border_width": 10, + "border_color": "blue", "children": [] }, { "type": "view", - "padding_top": 10, - "padding_left": 15, - "border_width": 4, - "border_color": "#00FF00FF", + "padding_top": 20, + "padding_left": 20, + "border_width": 10, + "border_color": "blue", "children": [ { "type": "view", - "padding_top": 10, + "padding_top": 20, "padding_bottom": 20, - "padding_right": 10, - "border_width": 4, - "border_color": "#0000FFFF", "padding_left": 20, - "background_color": "#00FF00FF", + "padding_right": 40, + "border_width": 10, + "border_color": "green", + "background_color": "blue", "children": [ { "type": "view", - "width": 250, - "height": 250, - "padding_top": 40, - "border_width": 4, - "border_color": "#FF0000FF", - "background_color": "#00FFFFFF", + "width": 150, + "height": 150, + "padding_left": 80, + "border_width": 10, + "border_color": "magenta", + "background_color": "yellow", "children": [] } ] diff --git a/snapshot_tests/view/padding_absolute_right_children.scene.json b/snapshot_tests/view/padding_absolute_children.scene.json similarity index 70% rename from snapshot_tests/view/padding_absolute_right_children.scene.json rename to snapshot_tests/view/padding_absolute_children.scene.json index a0291caad..182346ed6 100644 --- a/snapshot_tests/view/padding_absolute_right_children.scene.json +++ b/snapshot_tests/view/padding_absolute_children.scene.json @@ -6,31 +6,28 @@ "children": [ { "type": "view", - "background_color": "#FF0000FF", + "background_color": "red", "direction": "row", "width": 300, "height": 300, "children": [ { "type": "view", - "padding_top": 10, - "padding_left": 5, - "background_color": "#0000FFFF", + "background_color": "blue", "children": [] }, { "type": "view", - "padding_top": 10, - "padding_left": 15, + "padding_top": 20, + "padding_left": 20, "children": [ { "type": "view", - "background_color": "#00FF00FF", - "top": 10, - "right": 30, + "background_color": "yellow", + "top": 40, + "left": 40, "padding_top": 20, "padding_left": 20, - "padding_right": 550, "children": [ { "type": "input_stream", diff --git a/snapshot_tests/view/padding_absolute_left_children.scene.json b/snapshot_tests/view/padding_absolute_left_children.scene.json deleted file mode 100644 index fc72b44f0..000000000 --- a/snapshot_tests/view/padding_absolute_left_children.scene.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "video": { - "root": { - "type": "view", - "background_color": "#000000FF", - "children": [ - { - "type": "view", - "background_color": "#FF0000FF", - "direction": "row", - "width": 300, - "height": 300, - "children": [ - { - "type": "view", - "padding_top": 10, - "padding_left": 5, - "background_color": "#0000FFFF", - "children": [] - }, - { - "type": "view", - "padding_top": 10, - "padding_left": 15, - "children": [ - { - "type": "view", - "background_color": "#00FF00FF", - "top": 10, - "left": 20, - "padding_top": 10, - "padding_left": 20, - "children": [ - { - "type": "view", - "width": 250, - "height": 250, - "background_color": "#FF00FFFF", - "children": [] - } - ] - } - ] - } - ] - } - ] - } - } -} diff --git a/snapshot_tests/view/row_view_padding_static_children.scene.json b/snapshot_tests/view/unsized_view_padding_static_children.scene.json similarity index 53% rename from snapshot_tests/view/row_view_padding_static_children.scene.json rename to snapshot_tests/view/unsized_view_padding_static_children.scene.json index 53c2a39d7..5b221aef7 100644 --- a/snapshot_tests/view/row_view_padding_static_children.scene.json +++ b/snapshot_tests/view/unsized_view_padding_static_children.scene.json @@ -6,30 +6,29 @@ "children": [ { "type": "view", - "background_color": "#FF0000FF", - "direction": "row", - "width": 300, - "height": 300, + "background_color": "red", + "direction": "column", "children": [ { "type": "view", - "padding_left": 20, - "background_color": "#0000FFFF", + "border_width": 10, + "border_color": "blue", "children": [] }, { "type": "view", - "padding_bottom": 30, + "padding_top": 20, + "padding_bottom": 40, + "padding_right": 20, "padding_left": 20, - "padding_top": 10, - "padding_right": 10, - "background_color": "#00FF00FF", + "border_width": 10, + "border_color": "blue", "children": [ { "type": "view", - "width": 250, - "height": 250, - "background_color": "#00FFFFFF", + "border_width": 10, + "border_color": "magenta", + "background_color": "yellow", "children": [] } ] diff --git a/snapshot_tests/view/view_padding_multiple_children.scene.json b/snapshot_tests/view/view_padding_multiple_children.scene.json new file mode 100644 index 000000000..9a45f5c43 --- /dev/null +++ b/snapshot_tests/view/view_padding_multiple_children.scene.json @@ -0,0 +1,46 @@ +{ + "video": { + "root": { + "type": "view", + "background_color": "#000000FF", + "children": [ + { + "type": "view", + "background_color": "blue", + "direction": "row", + "children": [ + { + "type": "view", + "children": [] + }, + { + "type": "view", + "padding_bottom": 20, + "padding_left": 20, + "padding_right": 20, + "direction": "column", + "background_color": "green", + "children": [ + { + "type": "view", + "background_color": "red", + "children": [] + }, + { + "type": "view", + "height": 250, + "background_color": "yellow" + }, + { + "type": "view", + "background_color": "magenta", + "children": [] + } + ] + } + ] + } + ] + } + } +} diff --git a/src/snapshot_tests/view_tests.rs b/src/snapshot_tests/view_tests.rs index 24eaa1f50..4dd002d32 100644 --- a/src/snapshot_tests/view_tests.rs +++ b/src/snapshot_tests/view_tests.rs @@ -215,16 +215,16 @@ fn view_tests() { ..default.clone() }); runner.add(TestCase { - name: "view/column_view_padding_static_children", + name: "view/unsized_view_padding_static_children", scene_updates: scene_from_json(include_str!( - "../../snapshot_tests/view/column_view_padding_static_children.scene.json" + "../../snapshot_tests/view/unsized_view_padding_static_children.scene.json" )), ..default.clone() }); runner.add(TestCase { - name: "view/row_view_padding_static_children", + name: "view/view_padding_multiple_children", scene_updates: scene_from_json(include_str!( - "../../snapshot_tests/view/row_view_padding_static_children.scene.json" + "../../snapshot_tests/view/view_padding_multiple_children.scene.json" )), ..default.clone() }); @@ -236,16 +236,9 @@ fn view_tests() { ..default.clone() }); runner.add(TestCase { - name: "view/padding_absolute_children_left", + name: "view/padding_absolute_children", scene_updates: scene_from_json(include_str!( - "../../snapshot_tests/view/padding_absolute_left_children.scene.json" - )), - ..default.clone() - }); - runner.add(TestCase { - name: "view/padding_absolute_children_right", - scene_updates: scene_from_json(include_str!( - "../../snapshot_tests/view/padding_absolute_right_children.scene.json" + "../../snapshot_tests/view/padding_absolute_children.scene.json" )), ..default.clone() }); diff --git a/ts/live-compositor/src/api.generated.ts b/ts/live-compositor/src/api.generated.ts index 9b73a865e..820a34d07 100644 --- a/ts/live-compositor/src/api.generated.ts +++ b/ts/live-compositor/src/api.generated.ts @@ -328,6 +328,18 @@ export type Component = * List of box shadows. */ box_shadow?: BoxShadow[] | null; + /** + * (**default=`0.0`**) Padding for all sides of the component. + */ + padding?: number | null; + /** + * (**default=`0.0`**) Padding for the top and bottom of the component. + */ + padding_vertical?: number | null; + /** + * (**default=`0.0`**) Padding for the left and right of the component. + */ + padding_horizontal?: number | null; /** * (**default=`0.0`**) Padding on top side in pixels. */ diff --git a/ts/live-compositor/src/components/View.ts b/ts/live-compositor/src/components/View.ts index d8a3cb702..ae7112d45 100644 --- a/ts/live-compositor/src/components/View.ts +++ b/ts/live-compositor/src/components/View.ts @@ -149,10 +149,13 @@ function sceneBuilder( box_shadow: style.boxShadow, - padding_top: style.paddingTop ?? style.paddingVertical ?? style.padding, - padding_bottom: style.paddingBottom ?? style.paddingVertical ?? style.padding, - padding_right: style.paddingRight ?? style.paddingHorizontal ?? style.padding, - padding_left: style.paddingLeft ?? style.paddingHorizontal ?? style.padding, + padding: style.padding, + padding_vertical: style.paddingVertical, + padding_horizontal: style.paddingHorizontal, + padding_top: style.paddingTop, + padding_bottom: style.paddingBottom, + padding_right: style.paddingRight, + padding_left: style.paddingLeft, }; }