[NUI] Add constructor with style instance
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.Components / Controls / Navigation / ContentPage.cs
1 /*
2  * Copyright(c) 2021 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17 using System.ComponentModel;
18 using Tizen.NUI.BaseComponents;
19
20 namespace Tizen.NUI.Components
21 {
22     /// <summary>
23     /// The ContentPage class is a class which is a formatted full screen page.
24     /// ContentPage contains title app bar and content.
25     /// </summary>
26     /// <since_tizen> 9 </since_tizen>
27     public partial class ContentPage : Page
28     {
29         private AppBar appBar = null;
30         private View content = null;
31
32         private void Initialize()
33         {
34             Layout = new ContentPageLayout();
35
36             // ContentPage matches to parent by default.
37             WidthSpecification = LayoutParamPolicies.MatchParent;
38             HeightSpecification = LayoutParamPolicies.MatchParent;
39         }
40
41         /// <summary>
42         /// Creates a new instance of a ContentPage.
43         /// </summary>
44         /// <since_tizen> 9 </since_tizen>
45         public ContentPage() : base()
46         {
47             Initialize();
48         }
49
50         /// <summary>
51         /// Creates a new instance of a ContentPage with style.
52         /// </summary>
53         /// <param name="style">A style applied to the newly created ContentPage.</param>
54         [EditorBrowsable(EditorBrowsableState.Never)]
55         public ContentPage(ControlStyle style) : base(style)
56         {
57             Initialize();
58         }
59
60         /// <summary>
61         /// Dispose ContentPage and all children on it.
62         /// </summary>
63         /// <param name="type">Dispose type.</param>
64         [EditorBrowsable(EditorBrowsableState.Never)]
65         protected override void Dispose(DisposeTypes type)
66         {
67             if (disposed)
68             {
69                 return;
70             }
71
72             if (type == DisposeTypes.Explicit)
73             {
74                 if (appBar != null)
75                 {
76                     Utility.Dispose(appBar);
77                 }
78
79                 if (content != null)
80                 {
81                     Utility.Dispose(content);
82                 }
83             }
84
85             base.Dispose(type);
86         }
87
88         /// <inheritdoc/>
89         [EditorBrowsable(EditorBrowsableState.Never)]
90         public override void OnInitialize()
91         {
92             base.OnInitialize();
93
94             AccessibilityRole = Role.PageTab;
95         }
96
97         /// <summary>
98         /// AppBar of ContentPage.
99         /// AppBar is added as a child of ContentPage automatically.
100         /// AppBar is positioned at the top of the Page.
101         /// </summary>
102         /// <since_tizen> 9 </since_tizen>
103         public AppBar AppBar
104         {
105             get
106             {
107                 return GetValue(AppBarProperty) as AppBar;
108             }
109             set
110             {
111                 SetValue(AppBarProperty, value);
112                 NotifyPropertyChanged();
113             }
114         }
115         private AppBar InternalAppBar
116         {
117             get
118             {
119                 return appBar;
120             }
121             set
122             {
123                 if (appBar == value)
124                 {
125                     return;
126                 }
127
128                 if (appBar != null)
129                 {
130                     Remove(appBar);
131                 }
132
133                 appBar = value;
134                 if (appBar == null)
135                 {
136                     return;
137                 }
138
139                 Add(appBar);
140             }
141         }
142
143         /// <summary>
144         /// Content of ContentPage.
145         /// Content is added as a child of ContentPage automatically.
146         /// Content is positioned below AppBar.
147         /// Content is resized to fill the full screen except AppBar.
148         /// </summary>
149         /// <since_tizen> 9 </since_tizen>
150         public View Content
151         {
152             get
153             {
154                 return GetValue(ContentProperty) as View;
155             }
156             set
157             {
158                 SetValue(ContentProperty, value);
159                 NotifyPropertyChanged();
160             }
161         }
162
163         /// <summary>
164         /// for the case of ContentPage, it sets key focus on AppBar's NavigationContent
165         /// </summary>
166         protected internal override void RestoreKeyFocus()
167         {
168             if (FocusManager.Instance.IsDefaultAlgorithmEnabled())
169             {
170                 if (LastFocusedView)
171                 {
172                     FocusManager.Instance.SetCurrentFocusView(LastFocusedView);
173                 }
174                 else
175                 {
176                     if (AppBar != null)
177                     {
178                         FocusManager.Instance.SetCurrentFocusView(AppBar.PassFocusableViewInsideIfNeeded());
179                     }
180                     else
181                     {
182                         FocusManager.Instance.ClearFocus();
183                     }
184                 }
185             }
186         }
187
188         private View InternalContent
189         {
190             get
191             {
192                 return content;
193             }
194             set
195             {
196                 if (content == value)
197                 {
198                     return;
199                 }
200
201                 if (content != null)
202                 {
203                     Remove(content);
204                 }
205
206                 content = value;
207                 if (content == null)
208                 {
209                     return;
210                 }
211
212                 Add(content);
213             }
214         }
215
216         private class ContentPageLayout : AbsoluteLayout
217         {
218             protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
219             {
220                 float maxWidth = SuggestedMinimumWidth.AsDecimal();
221                 float maxHeight = SuggestedMinimumHeight.AsDecimal();
222
223                 MeasuredSize.StateType childWidthState = MeasuredSize.StateType.MeasuredSizeOK;
224                 MeasuredSize.StateType childHeightState = MeasuredSize.StateType.MeasuredSizeOK;
225
226                 var appBar = (Owner as ContentPage)?.AppBar;
227                 var content = (Owner as ContentPage)?.Content;
228
229                 bool measureAppBarLayout = false;
230
231                 if ((appBar != null) && (appBar.Layout != null) && (LayoutChildren.Contains(appBar.Layout)) && appBar.Layout.SetPositionByLayout)
232                 {
233                     MeasureChildWithoutPadding(appBar.Layout, widthMeasureSpec, heightMeasureSpec);
234                     measureAppBarLayout = true;
235                 }
236
237                 foreach (var childLayout in LayoutChildren)
238                 {
239                     if (!childLayout.SetPositionByLayout)
240                     {
241                         continue;
242                     }
243
244                     if ((content != null) && (content == childLayout.Owner) && (content.HeightSpecification == LayoutParamPolicies.MatchParent) && measureAppBarLayout)
245                     {
246                         var contentSizeH = heightMeasureSpec.Size.AsDecimal() - Padding.Top - Padding.Bottom - content.Margin.Top - content.Margin.Bottom - (appBar?.Layout.MeasuredHeight.Size.AsDecimal() ?? 0);
247                         MeasureSpecification contentHeightSpec = new MeasureSpecification(new LayoutLength(contentSizeH), MeasureSpecification.ModeType.Exactly);
248                         MeasureChildWithoutPadding(childLayout, widthMeasureSpec, contentHeightSpec);
249                     }
250                     else if (!measureAppBarLayout || (appBar != childLayout.Owner)) // if childLayout is not appBar.Layout
251                     {
252                         MeasureChildWithoutPadding(childLayout, widthMeasureSpec, heightMeasureSpec);
253                     }
254
255                     float childRight = childLayout.MeasuredWidth.Size.AsDecimal() + childLayout.Owner.PositionX;
256                     float childBottom = childLayout.MeasuredHeight.Size.AsDecimal() + childLayout.Owner.PositionY;
257
258                     if (maxWidth < childRight)
259                         maxWidth = childRight;
260
261                     if (maxHeight < childBottom)
262                         maxHeight = childBottom;
263
264                     if (childLayout.MeasuredWidth.State == MeasuredSize.StateType.MeasuredSizeTooSmall)
265                     {
266                         childWidthState = MeasuredSize.StateType.MeasuredSizeTooSmall;
267                     }
268                     if (childLayout.MeasuredHeight.State == MeasuredSize.StateType.MeasuredSizeTooSmall)
269                     {
270                         childHeightState = MeasuredSize.StateType.MeasuredSizeTooSmall;
271                     }
272                 }
273
274                 SetMeasuredDimensions(ResolveSizeAndState(new LayoutLength(maxWidth), widthMeasureSpec, childWidthState),
275                                       ResolveSizeAndState(new LayoutLength(maxHeight), heightMeasureSpec, childHeightState));
276             }
277
278             protected override void OnLayout(bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom)
279             {
280                 foreach (var childLayout in LayoutChildren)
281                 {
282                     if (!childLayout.SetPositionByLayout)
283                     {
284                         continue;
285                     }
286
287                     LayoutLength childWidth = childLayout.MeasuredWidth.Size;
288                     LayoutLength childHeight = childLayout.MeasuredHeight.Size;
289
290                     LayoutLength childLeft = new LayoutLength(childLayout.Owner.PositionX);
291                     LayoutLength childTop = new LayoutLength(childLayout.Owner.PositionY);
292
293                     var appBar = (Owner as ContentPage)?.AppBar;
294                     var content = (Owner as ContentPage)?.Content;
295
296                     if ((content != null) && (content == childLayout.Owner))
297                     {
298                         childTop = new LayoutLength(Padding.Top + content.Margin.Top + (appBar?.Layout.MeasuredHeight.Size.AsDecimal() ?? 0));
299                         childLayout.Layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight, false);
300                     }
301                     else
302                     {
303                         childLayout.Layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight, true);
304                     }
305                 }
306             }
307         }
308     }
309 }