2 * Copyright(c) 2022 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 using System.Collections.Generic;
20 using System.ComponentModel;
21 using Tizen.NUI.BaseComponents;
22 using Tizen.NUI.Binding;
23 using Tizen.NUI.Binding.Internals;
28 /// The Container is an abstract class to be inherited from by classes that desire to have views
31 /// <since_tizen> 4 </since_tizen>
32 public abstract class Container : Animatable, IResourcesProvider
34 /// <summary> XamlStyleProperty </summary>
35 [EditorBrowsable(EditorBrowsableState.Never)]
36 public static readonly BindableProperty XamlStyleProperty = BindableProperty.Create(nameof(XamlStyle), typeof(XamlStyle), typeof(Container), default(XamlStyle), propertyChanged: (bindable, oldvalue, newvalue) => ((View)bindable).MergedStyle.Style = (XamlStyle)newvalue);
38 internal BaseHandle InternalParent;
39 private List<View> childViews = new List<View>();
40 private MergedStyle mergedStyle = null;
41 ResourceDictionary _resources;
42 bool IResourcesProvider.IsResourcesCreated => _resources != null;
44 internal Container(global::System.IntPtr cPtr, bool cMemoryOwn) : base(cPtr, cMemoryOwn)
46 // No un-managed data hence no need to store a native ptr
49 /// This will be public opened in tizen_next after ACR done. Before ACR, need to be hidden as inhouse API.
50 [EditorBrowsable(EditorBrowsableState.Never)]
51 public ResourceDictionary XamlResources
55 if (_resources != null)
57 _resources = new ResourceDictionary();
58 ((IResourceDictionary)_resources).ValuesChanged += OnResourcesChanged;
63 if (_resources == value)
66 if (_resources != null)
67 ((IResourceDictionary)_resources).ValuesChanged -= OnResourcesChanged;
69 OnResourcesChanged(value);
70 if (_resources != null)
71 ((IResourceDictionary)_resources).ValuesChanged += OnResourcesChanged;
76 [EditorBrowsable(EditorBrowsableState.Never)]
77 public XamlStyle XamlStyle
81 return (XamlStyle)GetValue(XamlStyleProperty);
85 SetValue(XamlStyleProperty, value);
89 internal MergedStyle MergedStyle
93 if (null == mergedStyle)
95 mergedStyle = new MergedStyle(GetType(), this);
103 /// List of children of Container.
105 /// <since_tizen> 4 </since_tizen>
106 public List<View> Children
115 /// Gets the parent container.
118 /// <pre>The child container has been initialized.</pre>
119 /// <returns>The parent container.</returns>
120 /// <since_tizen> 4 </since_tizen>
121 [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1721: Property names should not match get methods")]
122 public new Container Parent
131 /// Gets the number of children for this container.
134 /// <pre>The container has been initialized.</pre>
135 /// <returns>The number of children.</returns>
136 /// <since_tizen> 4 </since_tizen>
137 public uint ChildCount
141 return Convert.ToUInt32(Children.Count);
146 /// Copy all properties, bindings.
147 /// Copy children without xName from other container, copy all properties, bindings of children with xName.
149 /// <param name="other"></param>
150 [EditorBrowsable(EditorBrowsableState.Never)]
151 public void CopyAndKeepXNameInstance(Container other)
155 var nameScopeOfOther = NameScope.GetNameScope(other) as NameScope;
156 var nameScope = NameScope.GetNameScope(this) as NameScope;
158 if (null == nameScopeOfOther)
160 if (null != nameScope)
165 else if (!nameScopeOfOther.Equal(nameScope))
170 var xNameToElementsOfOther = nameScopeOfOther?.NameToElement;
171 var xNameToElements = nameScope?.NameToElement;
173 if (null != xNameToElements)
175 foreach (var pair in xNameToElements)
177 if (pair.Value is View view)
179 view.Parent?.Remove(view);
184 for (int i = Children.Count - 1; i >= 0; i--)
186 var child = GetChildAt((uint)i);
189 child.DisposeIncludeChildren();
194 if (null != xNameToElementsOfOther)
196 foreach (var pair in xNameToElementsOfOther)
198 if (pair.Value is View view)
200 var parent = view.Parent;
204 if (null != xNameToElements)
206 var holdedXElements = xNameToElements[pair.Key] as View;
207 holdedXElements.CopyBindingRelationShip(view);
208 holdedXElements.CopyFrom(view);
210 parent.ReplaceChild(view, holdedXElements);
217 ReplaceBindingElementInWholeTree(xNameToElementsOfOther, xNameToElements);
219 if (null != xNameToElementsOfOther)
221 foreach (var pair in xNameToElementsOfOther)
223 if (pair.Value is View view)
232 /// Adds a child view to this Container.
234 /// <pre>This Container (the parent) has been initialized. The child view has been initialized. The child view is not the same as the parent view.</pre>
235 /// <post>The child will be referenced by its parent. This means that the child will be kept alive, even if the handle passed into this method is reset or destroyed.</post>
236 /// <remarks>If the child already has a parent, it will be removed from the old parent and reparented to this view. This may change child's position, color, scale, etc. as it now inherits them from this view.</remarks>
237 /// <param name="view">The child view to add.</param>
238 /// <since_tizen> 4 </since_tizen>
239 public abstract void Add(View view);
242 /// Removes a child view from this view. If the view was not a child of this view, this is a no-op.
244 /// <pre>This View(the parent) has been initialized. The child view is not the same as the parent view.</pre>
245 /// <param name="view">The view to remove</param>
246 /// <since_tizen> 4 </since_tizen>
247 public abstract void Remove(View view);
250 /// Retrieves the child view by the index.
252 /// <pre>The view has been initialized.</pre>
253 /// <param name="index">The index of the child to retrieve.</param>
254 /// <returns>The view for the given index or empty handle if children are not initialized.</returns>
255 /// <since_tizen> 4 </since_tizen>
256 public abstract View GetChildAt(uint index);
259 /// Gets the parent of this container.
261 /// <pre>The child container has been initialized.</pre>
262 /// <returns>The parent container.</returns>
263 /// <since_tizen> 4 </since_tizen>
264 [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1721: Property names should not match get methods")]
265 public abstract Container GetParent();
268 /// Gets the number of children for this container.
270 /// <pre>The container has been initialized.</pre>
271 /// <returns>The number of children.</returns>
272 /// <since_tizen> 4 </since_tizen>
273 [Obsolete("Deprecated in API9, will be removed in API11. Please use ChildCount property instead!")]
274 public abstract UInt32 GetChildCount();
276 internal abstract View FindCurrentChildById(uint id);
278 internal override void OnParentResourcesChanged(IEnumerable<KeyValuePair<string, object>> values)
283 if (!((IResourcesProvider)this).IsResourcesCreated || XamlResources.Count == 0)
285 base.OnParentResourcesChanged(values);
289 var innerKeys = new HashSet<string>();
290 var changedResources = new List<KeyValuePair<string, object>>();
291 foreach (KeyValuePair<string, object> c in XamlResources)
292 innerKeys.Add(c.Key);
293 foreach (KeyValuePair<string, object> value in values)
295 if (innerKeys.Add(value.Key))
296 changedResources.Add(value);
298 if (changedResources.Count != 0)
299 OnResourcesChanged(changedResources);
303 /// Invoked whenever the binding context of the element changes. Implement this method to add class handling for this event.
305 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
306 [EditorBrowsable(EditorBrowsableState.Never)]
307 protected override void OnBindingContextChanged()
309 var gotBindingContext = false;
312 for (var index = 0; index < Children.Count; index++)
314 Element child = Children[index];
316 if (!gotBindingContext)
319 gotBindingContext = true;
322 SetChildInheritedBindingContext(child, bc);
324 base.OnBindingContextChanged();
327 private void DisposeIncludeChildren()
329 foreach (var child in Children)
331 child.DisposeIncludeChildren();
341 private void CopyChildren(Container other)
343 var childrenOfOtherView = new List<View>();
345 foreach (var child in other.Children)
347 childrenOfOtherView.Add(child);
350 foreach (var child in childrenOfOtherView)
356 private void ReplaceChild(View child, View newChild)
358 int indexOfView = Children.FindIndex((View v) => { return v == child; });
360 var childrenNeedtoReAdd = new Stack<View>();
362 for (int i = Children.Count - 1; i > indexOfView; i--)
364 childrenNeedtoReAdd.Push(Children[i]);
370 childrenNeedtoReAdd.Push(newChild);
372 while (0 < childrenNeedtoReAdd.Count)
374 Add(childrenNeedtoReAdd.Pop());
378 private void ReplaceBindingElementInWholeTree(Dictionary<string, object> oldNameScope, Dictionary<string, object> newNameScope)
382 ReplaceBindingElement(oldNameScope, newNameScope);
384 foreach (var child in Children)
386 child.ReplaceBindingElementInWholeTree(oldNameScope, newNameScope);
391 } // namespace Tizen.NUI