[NUI] Introduce CollectionView and related classes. (#2525)
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.Components / Controls / RecyclerView / Item / DefaultTitleItem.cs
1 /* Copyright (c) 2021 Samsung Electronics Co., Ltd.
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  *
15  */
16 using System;
17 using System.ComponentModel;
18 using Tizen.NUI.BaseComponents;
19 using Tizen.NUI.Binding;
20 using Tizen.NUI.Components.Extension;
21 using Tizen.NUI.Accessibility;
22
23 namespace Tizen.NUI.Components
24 {
25     /// <summary>
26     /// DefaultTitleItem is one kind of common component, a DefaultTitleItem clearly describes what action will occur when the user selects it.
27     /// DefaultTitleItem may contain text or an icon.
28     /// </summary>
29     [EditorBrowsable(EditorBrowsableState.Never)]
30     public class DefaultTitleItem : RecyclerViewItem
31     {
32         private TextLabel itemLabel;
33         private View itemIcon;
34         private View itemSeperator;
35         private bool layoutChanged;
36         private Size prevSize;
37         private DefaultTitleItemStyle ItemStyle => ViewStyle as DefaultTitleItemStyle;
38
39         /// <summary>
40         /// Return a copied Style instance of DefaultTitleItem
41         /// </summary>
42         /// <remarks>
43         /// It returns copied Style instance and changing it does not effect to the DefaultTitleItem.
44         /// Style setting is possible by using constructor or the function of ApplyStyle(ViewStyle viewStyle)
45         /// </remarks>
46         [EditorBrowsable(EditorBrowsableState.Never)]
47         public new DefaultTitleItemStyle Style
48         {
49             get
50             {
51                 var result = new DefaultTitleItemStyle(ItemStyle);
52                 result.CopyPropertiesFromView(this);
53                 if (itemLabel) result.Label.CopyPropertiesFromView(itemLabel);
54                 if (itemIcon) result.Icon.CopyPropertiesFromView(itemIcon);
55                 if (itemSeperator) result.Seperator.CopyPropertiesFromView(itemSeperator);
56
57                 return result;
58             }
59         }
60
61         static DefaultTitleItem() {}
62
63         /// <summary>
64         /// Creates a new instance of DefaultTitleItem.
65         /// </summary>
66         [EditorBrowsable(EditorBrowsableState.Never)]
67         public DefaultTitleItem() : base()
68         {
69             Initialize();
70         }
71
72         /// <summary>
73         /// Creates a new instance of a DefaultTitleItem with style.
74         /// </summary>
75         /// <param name="style">Create DefaultTitleItem by style defined in UX.</param>
76         [EditorBrowsable(EditorBrowsableState.Never)]
77         public DefaultTitleItem(string style) : base(style)
78         {
79             Initialize();
80         }
81
82         /// <summary>
83         /// Creates a new instance of a DefaultTitleItem with style.
84         /// </summary>
85         /// <param name="itemStyle">Create DefaultTitleItem by style customized by user.</param>
86         [EditorBrowsable(EditorBrowsableState.Never)]
87         public DefaultTitleItem(DefaultTitleItemStyle itemStyle) : base(itemStyle)
88         {
89             Initialize();
90         }
91
92         /// <summary>
93         /// Icon part of DefaultTitleItem.
94         /// </summary>
95         [EditorBrowsable(EditorBrowsableState.Never)]
96         public View Icon
97         {
98             get
99             {
100                 if (itemIcon == null)
101                 {
102                     itemIcon = CreateIcon(ItemStyle?.Icon);
103                     if (itemIcon != null)
104                     {
105                         layoutChanged = true;
106                         Add(itemIcon);
107                         itemIcon.Relayout += OnIconRelayout;
108                     }
109                 }
110                 return itemIcon;
111             }
112             set
113             {
114                 itemIcon = value;
115             }
116         }
117
118         /* open when imageView using Uri not string.
119         /// <summary>
120         /// Icon image's resource url. Only activatable for icon as ImageView.
121         /// </summary>
122         [EditorBrowsable(EditorBrowsableState.Never)]
123         public string IconUrl
124         {
125             get
126             {
127                 return (Icon as ImageView)?.ResourceUrl;
128             }
129             set
130             {
131                 if (itemIcon != null && !(itemIcon is ImageView))
132                 {
133                     // Tizen.Log.Error("IconUrl only can set Icon is ImageView");
134                     return;
135                 }
136                 (Icon as ImageView).ResourceUrl = value; 
137             }
138         }
139         */
140
141         /// <summary>
142         /// DefaultTitleItem's text part of DefaultTitleItem
143         /// </summary>
144         [EditorBrowsable(EditorBrowsableState.Never)]
145         public TextLabel Label
146         {
147             get
148             {
149                 if (itemLabel == null)
150                 {
151                     itemLabel = CreateLabel(ItemStyle?.Label);
152                     if (itemLabel != null)
153                     {
154                         layoutChanged = true;
155                         Add(itemLabel);
156                     }
157                 }
158                 return itemLabel;
159             }
160             internal set
161             {
162                 itemLabel = value;
163                 AccessibilityManager.Instance.SetAccessibilityAttribute(this, AccessibilityManager.AccessibilityAttribute.Label, itemLabel.Text);
164             }
165         }
166
167         /// <summary>
168         /// The text of DefaultTitleItem.
169         /// </summary>
170        [EditorBrowsable(EditorBrowsableState.Never)]
171         public string Text
172         {
173             get
174             {
175                 return Label.Text;
176             }
177             set
178             {
179                 Label.Text = value;
180             }
181         }
182
183         /// <summary>
184         /// Seperator devider of DefaultTitleItem. it will place at the end of item.
185         /// </summary>
186         [EditorBrowsable(EditorBrowsableState.Never)]
187         public View Seperator
188         {
189             get
190             {
191                 if (itemSeperator == null)
192                 {
193                     itemSeperator = new View(ItemStyle?.Seperator)
194                     {
195                         //need to consider horizontal/vertical!
196                         WidthSpecification = LayoutParamPolicies.MatchParent,
197                         HeightSpecification = 2,
198                         ExcludeLayouting = true
199                     };
200                     layoutChanged = true;
201                     Add(itemSeperator);
202                 }
203                 return itemSeperator;
204             }
205         }
206
207         /// <summary>
208         /// Apply style to DefaultTitleItemStyle.
209         /// </summary>
210         /// <param name="viewStyle">The style to apply.</param>
211         [EditorBrowsable(EditorBrowsableState.Never)]
212         public override void ApplyStyle(ViewStyle viewStyle)
213         {
214
215             base.ApplyStyle(viewStyle);
216             if (viewStyle != null && viewStyle is DefaultTitleItemStyle defaultStyle)
217             {
218                 if (itemLabel != null)
219                     itemLabel.ApplyStyle(defaultStyle.Label);
220                 if (itemIcon != null)
221                     itemIcon.ApplyStyle(defaultStyle.Icon);
222                 if (itemSeperator != null)
223                     itemSeperator.ApplyStyle(defaultStyle.Seperator);
224             }
225         }
226
227         /// <inheritdoc />
228         [EditorBrowsable(EditorBrowsableState.Never)]
229         public override void OnRelayout(Vector2 size, RelayoutContainer container)
230         {
231             base.OnRelayout(size, container);
232
233             if (prevSize != Size)
234             {
235                 prevSize = Size;
236                 if (itemSeperator)
237                 {
238                     var margin = itemSeperator.Margin;
239                     itemSeperator.SizeWidth = SizeWidth - margin.Start - margin.End;
240                     itemSeperator.SizeHeight = itemSeperator.HeightSpecification;
241                     itemSeperator.Position = new Position(margin.Start, SizeHeight - margin.Bottom -itemSeperator.SizeHeight);
242                 }
243             }
244         }
245
246         /// <summary>
247         /// Creates Item's text part.
248         /// </summary>
249         /// <return>The created Item's text part.</return>
250         [EditorBrowsable(EditorBrowsableState.Never)]
251         protected virtual TextLabel CreateLabel(TextLabelStyle style)
252         {
253             return new TextLabel(style)
254             {
255                 HorizontalAlignment = HorizontalAlignment.Begin,
256                 VerticalAlignment = VerticalAlignment.Center
257             };
258         }
259
260         /// <summary>
261         /// Creates Item's icon part.
262         /// </summary>
263         /// <return>The created Item's icon part.</return>
264         [EditorBrowsable(EditorBrowsableState.Never)]
265         protected virtual ImageView CreateIcon(ViewStyle style)
266         {
267             return new ImageView(style);
268         }
269
270         /// <inheritdoc/>
271         [EditorBrowsable(EditorBrowsableState.Never)]
272         protected override void MeasureChild()
273         {
274             if (itemLabel)
275             {
276                 var pad = Padding;
277                 var margin = itemLabel.Margin;
278                 itemLabel.SizeWidth = SizeWidth - pad.Start - pad.End - margin.Start - margin.End;
279             }
280         }
281
282         /// <inheritdoc/>
283         [EditorBrowsable(EditorBrowsableState.Never)]
284         protected override void LayoutChild()
285         {
286             if (!layoutChanged) return;
287             if (itemLabel == null) return;
288
289             layoutChanged = false;
290
291             if (itemIcon != null)
292             {
293                 RelativeLayout.SetLeftTarget(itemIcon, this);
294                 RelativeLayout.SetLeftRelativeOffset(itemIcon, 1.0F);
295                 RelativeLayout.SetRightTarget(itemIcon, this);
296                 RelativeLayout.SetRightRelativeOffset(itemIcon, 1.0F);
297                 RelativeLayout.SetTopTarget(itemIcon, this);
298                 RelativeLayout.SetTopRelativeOffset(itemIcon, 0.0F);
299                 RelativeLayout.SetBottomTarget(itemIcon, this);
300                 RelativeLayout.SetBottomRelativeOffset(itemIcon, 1.0F);
301                 RelativeLayout.SetVerticalAlignment(itemIcon, RelativeLayout.Alignment.Center);
302                 RelativeLayout.SetHorizontalAlignment(itemIcon, RelativeLayout.Alignment.End);
303             }
304
305             RelativeLayout.SetLeftTarget(itemLabel, this);
306             RelativeLayout.SetLeftRelativeOffset(itemLabel, 0.0F);
307             if (itemIcon)
308             {
309                 RelativeLayout.SetRightTarget(itemLabel, itemIcon);
310                 RelativeLayout.SetRightRelativeOffset(itemLabel, 0.0F);
311             }
312             else
313             {
314                 RelativeLayout.SetRightTarget(itemLabel, this);
315                 RelativeLayout.SetRightRelativeOffset(itemLabel, 1.0F);
316             }
317
318             RelativeLayout.SetTopTarget(itemLabel, this);
319             RelativeLayout.SetTopRelativeOffset(itemLabel, 0.0F);
320             RelativeLayout.SetBottomTarget(itemLabel, this);
321             RelativeLayout.SetBottomRelativeOffset(itemLabel, 1.0F);
322             RelativeLayout.SetVerticalAlignment(itemLabel, RelativeLayout.Alignment.Center);
323             RelativeLayout.SetHorizontalAlignment(itemLabel, RelativeLayout.Alignment.Center);
324             RelativeLayout.SetFillHorizontal(itemLabel, true);
325
326             if (prevSize != Size)
327             {
328                 prevSize = Size;
329                 if (itemSeperator)
330                 {
331                     var margin = itemSeperator.Margin;
332                     itemSeperator.SizeWidth = SizeWidth - margin.Start - margin.End;
333                     itemSeperator.SizeHeight = itemSeperator.HeightSpecification;
334                     itemSeperator.Position = new Position(margin.Start, SizeHeight - margin.Bottom -itemSeperator.SizeHeight);
335                 }
336             }
337         }
338
339         /// <summary>
340         /// Dispose Item and all children on it.
341         /// </summary>
342         /// <param name="type">Dispose type.</param>
343         [EditorBrowsable(EditorBrowsableState.Never)]
344         protected override void Dispose(DisposeTypes type)
345         {
346             if (disposed)
347             {
348                 return;
349             }
350
351             if (type == DisposeTypes.Explicit)
352             {
353                 //Extension : Extension?.OnDispose(this);
354
355                 if (itemIcon != null)
356                 {
357                     Utility.Dispose(itemIcon);
358                 }
359                 if (itemLabel != null)
360                 {
361                     Utility.Dispose(itemLabel);
362                 }
363                 if (itemSeperator != null)
364                 {
365                     Utility.Dispose(itemSeperator);
366                 }
367             }
368
369             base.Dispose(type);
370         }
371
372         /// <summary>
373         /// Get DefaultTitleItem style.
374         /// </summary>
375         /// <returns>The default DefaultTitleItem style.</returns>
376         [EditorBrowsable(EditorBrowsableState.Never)]
377         protected override ViewStyle CreateViewStyle()
378         {
379             return new DefaultTitleItemStyle();
380         }
381
382         private void Initialize()
383         {
384             base.OnInitialize();
385             Layout = new RelativeLayout();
386             var seperator = Seperator;
387             layoutChanged = true;
388             LayoutDirectionChanged += OnLayoutDirectionChanged;
389         }
390
391         private void OnLayoutDirectionChanged(object sender, LayoutDirectionChangedEventArgs e)
392         {
393             MeasureChild();
394             LayoutChild();
395         }
396
397         private void OnIconRelayout(object sender, EventArgs e)
398         {
399             MeasureChild();
400             LayoutChild();
401         }
402
403         private void OnExtraRelayout(object sender, EventArgs e)
404         {
405             MeasureChild();
406             LayoutChild();
407         }        
408     }
409 }