Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NUI] Add AbsoluteLayout APIs for Bounds and LayoutFlags #6663

Draft
wants to merge 1 commit into
base: DevelNUI
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 143 additions & 1 deletion src/Tizen.NUI/src/public/Layouting/AbsoluteLayout.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (c) 2021 Samsung Electronics Co., Ltd.
/* Copyright (c) 2019-2025 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -13,6 +13,10 @@
* limitations under the License.
*
*/
using System;
using System.ComponentModel;
using Tizen.NUI.BaseComponents;
using Tizen.NUI.Binding;

namespace Tizen.NUI
{
Expand All @@ -30,6 +34,117 @@ public AbsoluteLayout()
{
}

/// <summary>
/// LayoutBoundsXProperty
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public static readonly BindableProperty LayoutBoundsXProperty = BindableProperty.CreateAttached("LayoutBoundsX", typeof(float), typeof(AbsoluteLayout), float.NaN, propertyChanged: OnChildPropertyChanged);

/// <summary>
/// LayoutBoundsYProperty
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public static readonly BindableProperty LayoutBoundsYProperty = BindableProperty.CreateAttached("LayoutBoundsY", typeof(float), typeof(AbsoluteLayout), float.NaN, propertyChanged: OnChildPropertyChanged);

/// <summary>
/// LayoutBoundsWidthProperty
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public static readonly BindableProperty LayoutBoundsWidthProperty = BindableProperty.CreateAttached("LayoutBoundsWidth", typeof(float), typeof(AbsoluteLayout), float.NaN, propertyChanged: OnChildPropertyChanged);

/// <summary>
/// LayoutBoundsHeightProperty
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public static readonly BindableProperty LayoutBoundsHeightProperty = BindableProperty.CreateAttached("LayoutBoundsHeight", typeof(float), typeof(AbsoluteLayout), float.NaN, propertyChanged: OnChildPropertyChanged);

/// <summary>
/// LayoutFlagsProperty
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public static readonly BindableProperty LayoutFlagsProperty = BindableProperty.CreateAttached("LayoutFlags", typeof(AbsoluteLayoutFlags), typeof(AbsoluteLayout), default(AbsoluteLayoutFlags), validateValue: ValidateEnum((int)AbsoluteLayoutFlags.None, (int)AbsoluteLayoutFlags.All), propertyChanged: OnChildPropertyChanged);

/// <summary>
/// Gets the layout bounds x of the child view. The default layout bounds x is float.NaN.
/// </summary>
/// <param name="view">The child view.</param>
/// <returns>The layout bounds x of <paramref name="view"/>.</returns>
/// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
public static float GetLayoutBoundsX(View view) => GetAttachedValue<float>(view, LayoutBoundsXProperty);

/// <summary>
/// Sets the layout bounds x of the child view. The default layout bounds x is float.NaN.
/// </summary>
/// <param name="view">The child view.</param>
/// <param name="value">The layout bounds x of <paramref name="view"/>.</param>
/// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
public static void SetLayoutBoundsX(View view, float value) => SetAttachedValue(view, LayoutBoundsXProperty, value);

/// <summary>
/// Gets the layout bounds y of the child view. The default layout bounds y is float.NaN.
/// </summary>
/// <param name="view">The child view.</param>
/// <returns>The layout bounds y of <paramref name="view"/>.</returns>
/// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
public static float GetLayoutBoundsY(View view) => GetAttachedValue<float>(view, LayoutBoundsYProperty);

/// <summary>
/// Sets the layout bounds y of the child view. The default layout bounds y is float.NaN.
/// </summary>
/// <param name="view">The child view.</param>
/// <param name="value">The layout bounds y of <paramref name="view"/>.</param>
/// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
public static void SetLayoutBoundsY(View view, float value) => SetAttachedValue(view, LayoutBoundsYProperty, value);

/// <summary>
/// Gets the layout bounds width of the child view. The default layout bounds width is float.NaN.
/// </summary>
/// <param name="view">The child view.</param>
/// <returns>The layout bounds width of <paramref name="view"/>.</returns>
/// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
public static float GetLayoutBoundsWidth(View view) => GetAttachedValue<float>(view, LayoutBoundsWidthProperty);

/// <summary>
/// Sets the layout bounds width of the child view. The default layout bounds width is float.NaN.
/// </summary>
/// <param name="view">The child view.</param>
/// <param name="value">The layout bounds width of <paramref name="view"/>.</param>
/// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
public static void SetLayoutBoundsWidth(View view, float value) => SetAttachedValue(view, LayoutBoundsWidthProperty, value);

/// <summary>
/// Gets the layout bounds height of the child view. The default layout bounds height is float.NaN.
/// </summary>
/// <param name="view">The child view.</param>
/// <returns>The layout bounds height of <paramref name="view"/>.</returns>
/// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
public static float GetLayoutBoundsHeight(View view) => GetAttachedValue<float>(view, LayoutBoundsHeightProperty);

/// <summary>
/// Sets the layout bounds height of the child view. The default layout bounds height is float.NaN.
/// </summary>
/// <param name="view">The child view.</param>
/// <param name="value">The layout bounds height of <paramref name="view"/>.</param>
/// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
public static void SetLayoutBoundsHeight(View view, float value) => SetAttachedValue(view, LayoutBoundsHeightProperty, value);

/// <summary>
/// Gets the absolute layout flags of the child view. The default absolute layout flags is <see cref="AbsoluteLayoutFlags.None"/>.
/// </summary>
/// <param name="view">The child view.</param>
/// <returns>The absolute layout flags of <paramref name="view"/>.</returns>
/// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
public static AbsoluteLayoutFlags GetLayoutFlags(View view) => GetAttachedValue<AbsoluteLayoutFlags>(view, LayoutFlagsProperty);

/// <summary>
/// Sets the absolute layout flags of the child view. The default absolute layout flags is <see cref="AbsoluteLayoutFlags.None"/>.
/// </summary>
/// <param name="view">The child view.</param>
/// <param name="value">The absolute layout flags of <paramref name="view"/>.</param>
/// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
/// <exception cref="ArgumentException">The <paramref name="value"/> should be <see cref="AbsoluteLayoutFlags"/>.</exception>
public static void SetLayoutFlags(View view, AbsoluteLayoutFlags value) => SetAttachedValue(view, LayoutFlagsProperty, value);

/// <summary>
/// Measure the layout and its content to determine the measured width and the measured height.<br />
/// </summary>
Expand All @@ -52,6 +167,17 @@ protected override void OnMeasure(MeasureSpecification widthMeasureSpec, Measure
continue;
}

// var boundsX = GetLayoutBoundsX(childLayout.Owner);
// var boundsY = GetLayoutBoundsY(childLayout.Owner);
// var boundsWidth = GetLayoutBoundsWidth(childLayout.Owner);
// var boundsHeight = GetLayoutBoundsHeight(childLayout.Owner);
// var flags = GetLayoutFlags(childLayout.Owner);
// bool isWidthProportional = flags.HasFlag(AbsoluteLayoutFlags.WidthProportional);
// bool isHeightProportional = flags.HasFlag(AbsoluteLayoutFlags.HeightProportional);

// var measureWidth = ResolveChildMeasureConstraint(boundsWidth, isWidthProportional, widthMeasureSpec.GetSize().AsDecimal());
// var measureHeight = ResolveChildMeasureConstraint(boundsHeight, isHeightProportional, heightMeasureSpec.GetSize().AsDecimal());

// Get size of child with no padding, no margin. we won't support margin, padding for AbsolutLayout.
MeasureChildWithoutPadding(childLayout, widthMeasureSpec, heightMeasureSpec);

Expand Down Expand Up @@ -109,5 +235,21 @@ protected override void OnLayout(bool changed, LayoutLength left, LayoutLength t
childLayout.Layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight, true);
}
}

static float ResolveChildMeasureConstraint(float boundsValue, bool proportional, float constraint)
{
if (boundsValue < 0)
{
// If the child view doesn't have bounds set by the AbsoluteLayout, then we'll let it auto-size
return float.PositiveInfinity;
}

if (proportional)
{
return boundsValue * constraint;
}

return boundsValue;
}
}
} // namespace
66 changes: 66 additions & 0 deletions src/Tizen.NUI/src/public/Layouting/AbsoluteLayoutFlags.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/* Copyright (c) 2025 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;

namespace Tizen.NUI
{
/// <summary>
/// Enumeration for AbsoluteLayoutFlags.
/// </summary>
[Flags]
public enum AbsoluteLayoutFlags
{
/// <summary>
/// No flags set.
/// </summary>
None = 0,

/// <summary>
/// Indicates that the X position of the child element should be proportional to its parent.
/// </summary>
XProportional = 1 << 0,

/// <summary>
/// Indicates that the Y position of the child element should be proportional to its parent.
/// </summary>
YProportional = 1 << 1,

/// <summary>
/// Indicates that the width of the child element should be proportional to its parent.
/// </summary>
WidthProportional = 1 << 2,

/// <summary>
/// Indicates that the height of the child element should be proportional to its parent.
/// </summary>
HeightProportional = 1 << 3,

/// <summary>
/// Indicates that both the X and Y positions of the child element should be proportional to its parent.
/// </summary>
PositionProportional = 1 | 1 << 1,

/// <summary>
/// Indicates that both the width and height of the child element should be proportional to its parent.
/// </summary>
SizeProportional = 1 << 2 | 1 << 3,

/// <summary>
/// Indicates that all properties of the child element should be proportional to its parent.
/// </summary>
All = ~0
}
}
Loading