diff --git a/src/Tizen.NUI/src/public/BaseComponents/View.cs b/src/Tizen.NUI/src/public/BaseComponents/View.cs index a0741f5c854..0107deb2ba4 100755 --- a/src/Tizen.NUI/src/public/BaseComponents/View.cs +++ b/src/Tizen.NUI/src/public/BaseComponents/View.cs @@ -1,5 +1,5 @@ /* - * Copyright(c) 2022 Samsung Electronics Co., Ltd. + * Copyright(c) 2017-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. @@ -35,18 +35,9 @@ public partial class View : Container, IResourcesProvider private static bool defaultAllowOnlyOwnTouch = false; internal BackgroundExtraData backgroundExtraData; - - private bool layoutSet = false; - private LayoutItem layout; // Exclusive layout assigned to this View. - - // List of transitions paired with the condition that uses the transition. - private Dictionary layoutTransitions; - private int widthPolicy = LayoutParamPolicies.WrapContent; // Layout width policy - private int heightPolicy = LayoutParamPolicies.WrapContent; // Layout height policy - private float weight = 0.0f; // Weighting of child View in a Layout - private bool excludeLayouting = false; - private LayoutTransition layoutTransition; - private TransitionOptions transitionOptions = null; + private int widthPolicy = LayoutParamPolicies.WrapContent; + private int heightPolicy = LayoutParamPolicies.WrapContent; + private LayoutExtraData layoutExtraData; private ThemeData themeData; private Dictionary attached; private bool isThemeChanged = false; @@ -574,13 +565,7 @@ internal View(ViewImpl implementation, bool shown = true) : this(Interop.View.Ne /// /// This will be public opened after ACR done. Before ACR, need to be hidden as inhouse API. [EditorBrowsable(EditorBrowsableState.Never)] - public bool LayoutSet - { - get - { - return layoutSet; - } - } + public bool LayoutSet => layoutExtraData?.LayoutSet ?? false; /// /// Flag to allow Layouting to be disabled for Views. @@ -807,13 +792,10 @@ internal void SetInternalExcludeLayouting(bool excludeLayouting) private bool InternalExcludeLayouting { - get - { - return excludeLayouting; - } + get => layoutExtraData?.ExcludeLayouting ?? false; set { - excludeLayouting = value; + EnsureLayoutExtraData().ExcludeLayouting = value; if (Layout != null && Layout.SetPositionByLayout == value) { Layout.SetPositionByLayout = !value; @@ -2911,7 +2893,7 @@ internal void SetInternalSizeWidth(float sizeWidth) if (widthPolicy != widthPolicyCeiling) { widthPolicy = widthPolicyCeiling; - layout?.RequestLayout(); + RequestLayout(); } Object.InternalSetPropertyFloat(SwigCPtr, Property.SizeWidth, width); @@ -2975,7 +2957,7 @@ internal void SetInternalSizeHeight(float sizeHeight) if (heightPolicy != heightPolicyCeiling) { heightPolicy = heightPolicyCeiling; - layout?.RequestLayout(); + RequestLayout(); } Object.InternalSetPropertyFloat(SwigCPtr, Property.SizeHeight, height); @@ -4208,7 +4190,7 @@ public Size2D MinimumSize { throw new ArgumentNullException(nameof(value)); } - if (layout != null) + if (layoutExtraData?.Layout is LayoutItem layout) { // Note: it only works if minimum size is >= than natural size. // To force the size it should be done through the width&height spec or Size2D. @@ -4260,10 +4242,7 @@ public Size2D MaximumSize { // We don't have Layout.Maximum(Width|Height) so we cannot apply it to layout. // MATCH_PARENT spec + parent container size can be used to limit - if (layout != null) - { - layout.RequestLayout(); - } + RequestLayout(); if (NUIApplication.IsUsingXaml) { @@ -4578,7 +4557,7 @@ public ViewLayoutDirectionType LayoutDirection SetInternalLayoutDirection(value); } NotifyPropertyChanged(); - layout?.RequestLayout(); + RequestLayout(); } } @@ -4711,7 +4690,7 @@ private int InternalWidthSpecification { SizeWidth = widthPolicy; } - layout?.RequestLayout(); + RequestLayout(); } } @@ -4786,7 +4765,7 @@ private int InternalHeightSpecification { SizeHeight = heightPolicy; } - layout?.RequestLayout(); + RequestLayout(); } } @@ -4798,11 +4777,13 @@ public Dictionary LayoutTransitions { get { - if (layoutTransitions == null) + var layoutExtraData = EnsureLayoutExtraData(); + + if (layoutExtraData.LayoutTransitions == null) { - layoutTransitions = new Dictionary(); + layoutExtraData.LayoutTransitions = new Dictionary(); } - return layoutTransitions; + return layoutExtraData.LayoutTransitions; } } @@ -4843,26 +4824,26 @@ public LayoutTransition LayoutTransition private LayoutTransition InternalLayoutTransition { - get - { - return layoutTransition; - } + get => EnsureLayoutExtraData().LayoutTransition; set { if (value == null) { throw new global::System.ArgumentNullException(nameof(value)); } - if (layoutTransitions == null) + + var layoutExtraData = EnsureLayoutExtraData(); + + if (layoutExtraData.LayoutTransitions == null) { - layoutTransitions = new Dictionary(); + layoutExtraData.LayoutTransitions = new Dictionary(); } - LayoutTransitionsHelper.AddTransitionForCondition(layoutTransitions, value.Condition, value, true); + LayoutTransitionsHelper.AddTransitionForCondition(layoutExtraData.LayoutTransitions, value.Condition, value, true); AttachTransitionsToChildren(value); - layoutTransition = value; + layoutExtraData.LayoutTransition = value; } } @@ -4919,7 +4900,7 @@ private Extents InternalPaddingEX SetProperty(View.Property.PADDING, temp); temp.Dispose(); NotifyPropertyChanged(); - layout?.RequestLayout(); + RequestLayout(); } } @@ -5146,20 +5127,19 @@ public LayoutItem Layout private LayoutItem InternalLayout { - get - { - return layout; - } + get => layoutExtraData?.Layout; set { + var layoutExtraData = EnsureLayoutExtraData(); + // Do nothing if layout provided is already set on this View. - if (value == layout) + if (value == layoutExtraData.Layout) { return; } LayoutingDisabled = false; - layoutSet = true; + layoutExtraData.LayoutSet = true; // If new layout being set already has a owner then that owner receives a replacement default layout. // First check if the layout to be set already has a owner. @@ -5177,20 +5157,20 @@ private LayoutItem InternalLayout // Copy Margin and Padding to new layout being set or restore padding and margin back to // View if no replacement. Previously margin and padding values would have been moved from // the View to the layout. - if (layout != null) // Existing layout + if (layoutExtraData.Layout != null) // Existing layout { if (value != null) { // Existing layout being replaced so copy over margin and padding values. - value.Margin = layout.Margin; - value.Padding = layout.Padding; - value.SetPositionByLayout = !excludeLayouting; + value.Margin = layoutExtraData.Layout.Margin; + value.Padding = layoutExtraData.Layout.Padding; + value.SetPositionByLayout = !layoutExtraData.ExcludeLayouting; } else { // Layout not being replaced so restore margin and padding to View. - SetValue(MarginProperty, layout.Margin); - SetValue(PaddingProperty, layout.Padding); + SetValue(MarginProperty, layoutExtraData.Layout.Margin); + SetValue(PaddingProperty, layoutExtraData.Layout.Padding); NotifyPropertyChanged(); } } @@ -5233,12 +5213,12 @@ private LayoutItem InternalLayout NotifyPropertyChanged(); } - value.SetPositionByLayout = !excludeLayouting; + value.SetPositionByLayout = !layoutExtraData.ExcludeLayouting; } } // Remove existing layout from it's parent layout group. - layout?.Unparent(); + layoutExtraData.Layout?.Unparent(); // Set layout to this view SetLayout(value); @@ -5251,14 +5231,12 @@ private LayoutItem InternalLayout /// 6 public float Weight { - get - { - return weight; - } + get => layoutExtraData?.Weight ?? 0; set { - weight = value; - layout?.RequestLayout(); + var layoutExtraData = EnsureLayoutExtraData(); + layoutExtraData.Weight = value; + layoutExtraData.Layout?.RequestLayout(); } } @@ -5922,14 +5900,8 @@ public TransitionOptions TransitionOptions private TransitionOptions InternalTransitionOptions { - set - { - transitionOptions = value; - } - get - { - return transitionOptions; - } + get => layoutExtraData?.TransitionOptions; + set => EnsureLayoutExtraData().TransitionOptions = value; } /// @@ -6024,5 +5996,17 @@ private OffScreenRenderingType GetInternalOffScreenRendering() default: return OffScreenRenderingType.None; } } + + private LayoutExtraData EnsureLayoutExtraData() + { + if (layoutExtraData == null) + { + layoutExtraData = new LayoutExtraData(); + } + + return layoutExtraData; + } + + private void RequestLayout() => layoutExtraData?.Layout?.RequestLayout(); } } diff --git a/src/Tizen.NUI/src/public/BaseComponents/ViewBindableProperty.cs b/src/Tizen.NUI/src/public/BaseComponents/ViewBindableProperty.cs index 5dd8ea343b1..804620512d7 100755 --- a/src/Tizen.NUI/src/public/BaseComponents/ViewBindableProperty.cs +++ b/src/Tizen.NUI/src/public/BaseComponents/ViewBindableProperty.cs @@ -1,5 +1,5 @@ /* - * Copyright(c) 2019-2022 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. @@ -798,12 +798,13 @@ internal static void SetInternalSize2DProperty(BindableObject bindable, object o } if (relayoutRequired) { - view.layout?.RequestLayout(); + view.RequestLayout(); } Object.InternalSetPropertyVector2ActualVector3(view.SwigCPtr, View.Property.SIZE, ((Size2D)newValue).SwigCPtr); } } + internal static object GetInternalSize2DProperty(BindableObject bindable) { var view = (View)bindable; @@ -1577,7 +1578,7 @@ internal static void SetInternalSizeProperty(BindableObject bindable, object old } if (relayoutRequired) { - view.layout?.RequestLayout(); + view.RequestLayout(); } view.SetSize(width, height, depth); diff --git a/src/Tizen.NUI/src/public/BaseComponents/ViewInternal.cs b/src/Tizen.NUI/src/public/BaseComponents/ViewInternal.cs index 89da7529f6d..deef3c36959 100755 --- a/src/Tizen.NUI/src/public/BaseComponents/ViewInternal.cs +++ b/src/Tizen.NUI/src/public/BaseComponents/ViewInternal.cs @@ -192,9 +192,9 @@ internal void SetLayout(LayoutItem layout) { LayoutCount++; - this.layout = layout; - this.layout?.AttachToOwner(this); - this.layout?.RequestLayout(); + EnsureLayoutExtraData().Layout = layout; + layout?.AttachToOwner(this); + layout?.RequestLayout(); } internal void AttachTransitionsToChildren(LayoutTransition transition) @@ -1172,7 +1172,7 @@ internal void ResetLayout() { LayoutCount--; - layout = null; + EnsureLayoutExtraData().Layout = null; } internal ResourceLoadingStatusType GetBackgroundResourceStatus() diff --git a/src/Tizen.NUI/src/public/BaseComponents/ViewPublicMethods.cs b/src/Tizen.NUI/src/public/BaseComponents/ViewPublicMethods.cs index 4ed34092100..c1c8f18e53a 100755 --- a/src/Tizen.NUI/src/public/BaseComponents/ViewPublicMethods.cs +++ b/src/Tizen.NUI/src/public/BaseComponents/ViewPublicMethods.cs @@ -127,8 +127,6 @@ public Animation AnimateColor(string targetVisual, object destinationColor, int /// 4 public override void Add(View child) { - bool hasLayout = (layout != null); - if (null == child) { Tizen.Log.Fatal("NUI", "Child is null"); @@ -186,14 +184,12 @@ public override void Remove(View child) return; } - bool hasLayout = (layout != null); - // If View has a layout then do a deferred child removal // Actual child removal is performed by the layouting system so // transitions can be completed. - if (hasLayout) + if (Layout != null) { - (layout as LayoutGroup)?.RemoveChildFromLayoutGroup(child); + (Layout as LayoutGroup)?.RemoveChildFromLayoutGroup(child); } RemoveChild(child); diff --git a/src/Tizen.NUI/src/public/ViewProperty/LayoutExtraData.cs b/src/Tizen.NUI/src/public/ViewProperty/LayoutExtraData.cs new file mode 100755 index 00000000000..86fc969d131 --- /dev/null +++ b/src/Tizen.NUI/src/public/ViewProperty/LayoutExtraData.cs @@ -0,0 +1,73 @@ +/* + * 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; +using System.Collections.Generic; + +namespace Tizen.NUI.BaseComponents +{ + /// + /// The class storing Layout properties. + /// + internal sealed class LayoutExtraData : IDisposable + { + private bool disposed; + + // Indicates whether the layout has been set by user or not. + public bool LayoutSet { get; set; } + + // Exclusive layout assigned to this View. + public LayoutItem Layout { get; set; } + + // The List of transitions for this View. + public Dictionary LayoutTransitions { get; set; } + + // Layout transitions for this View. + public LayoutTransition LayoutTransition { get; set; } + + // TransitionOptions for the page transition. + public TransitionOptions TransitionOptions { get; set; } + + // The weight of the View, used to share available space in a layout with siblings. + public float Weight { get; set; } + + // The status of whether the view is excluded from its parent's layouting or not. + public bool ExcludeLayouting { get; set; } + + ~LayoutExtraData() => Dispose(false); + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private void Dispose(bool disposing) + { + if (disposed) + { + return; + } + if (disposing) + { + TransitionOptions?.Dispose(); + } + disposed = true; + } + } +} + +