[NUI] Add bindable properties to Components.
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.Components / Controls / RecyclerView / Item / DefaultGridItem.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.Accessibility;
20
21 namespace Tizen.NUI.Components
22 {
23     /// <summary>
24     /// DefaultGridItem is one kind of common component, a DefaultGridItem clearly describes what action will occur when the user selects it.
25     /// DefaultGridItem may contain text or an icon.
26     /// </summary>
27     [EditorBrowsable(EditorBrowsableState.Never)]
28     public partial class DefaultGridItem : RecyclerViewItem
29     {
30         private TextLabel itemLabel;
31         private ImageView itemImage;
32         private View itemBadge;
33         private LabelOrientation labelOrientation;
34         private bool layoutChanged;
35
36         private DefaultGridItemStyle ItemStyle => ViewStyle as DefaultGridItemStyle;
37
38         static DefaultGridItem() { }
39
40         /// <summary>
41         /// Creates a new instance of DefaultGridItem.
42         /// </summary>
43         [EditorBrowsable(EditorBrowsableState.Never)]
44         public DefaultGridItem() : base()
45         {
46         }
47
48         /// <summary>
49         /// Creates a new instance of DefaultGridItem with style
50         /// </summary>
51         /// <param name="style=">Create DefaultGridItem by special style defined in UX.</param>
52         [EditorBrowsable(EditorBrowsableState.Never)]
53         public DefaultGridItem(string style) : base(style)
54         {
55         }
56
57         /// <summary>
58         /// Creates a new instance of DefaultGridItem with style
59         /// </summary>
60         /// <param name="itemStyle=">Create DefaultGridItem by style customized by user.</param>
61         [EditorBrowsable(EditorBrowsableState.Never)]
62         public DefaultGridItem(DefaultGridItemStyle itemStyle) : base(itemStyle)
63         {
64         }
65
66         /// <summary>
67         /// Label orientation.
68         /// </summary>
69         [EditorBrowsable(EditorBrowsableState.Never)]
70         public enum LabelOrientation
71         {
72             /// <summary>
73             /// Outside of image bottom edge.
74             /// </summary>
75             [EditorBrowsable(EditorBrowsableState.Never)]
76             OutsideBottom,
77             /// <summary>
78             /// Outside of image top edge.
79             /// </summary>
80             [EditorBrowsable(EditorBrowsableState.Never)]
81             OutsideTop,
82             /// <summary>
83             /// inside of image bottom edge.
84             /// </summary>
85             [EditorBrowsable(EditorBrowsableState.Never)]
86             InsideBottom,
87             /// <summary>
88             /// inside of image top edge.
89             /// </summary>
90             [EditorBrowsable(EditorBrowsableState.Never)]
91             InsideTop,
92         }
93
94         /// <summary>
95         /// DefaultGridItem's icon part.
96         /// </summary>
97         [EditorBrowsable(EditorBrowsableState.Never)]
98         public ImageView Image
99         {
100             get
101             {
102                 if (itemImage == null)
103                 {
104                     itemImage = CreateImage(ItemStyle.Image);
105                     if (itemImage != null)
106                     {
107                         Add(itemImage);
108                         itemImage.Relayout += OnImageRelayout;
109                         layoutChanged = true;
110                     }
111                 }
112                 return itemImage;
113             }
114             internal set
115             {
116                 if (itemImage != null) Remove(itemImage);
117                 itemImage = value;
118                 if (itemImage != null)
119                 {
120                     //FIXME: User applied image's style can be overwritten!
121                     if (ItemStyle != null) itemImage.ApplyStyle(ItemStyle.Image);
122                     Add(itemImage);
123                     itemImage.Relayout += OnImageRelayout;
124                 }
125                 layoutChanged = true;
126             }
127         }
128
129
130         /// <summary>
131         /// DefaultGridItem's badge object. will be placed in right-top edge.
132         /// </summary>
133         [EditorBrowsable(EditorBrowsableState.Never)]
134         public View Badge
135         {
136             get
137             {
138                 return GetValue(BadgeProperty) as View;
139             }
140             set
141             {
142                 SetValue(BadgeProperty, value);
143                 NotifyPropertyChanged();
144             }
145         }
146         private View InternalBadge
147         {
148             get
149             {
150                 return itemBadge;
151
152             }
153             set
154             {
155                 if (itemBadge != null) Remove(itemBadge);
156                 itemBadge = value;
157                 if (itemBadge != null)
158                 {
159                     //FIXME: User applied badge's style can be overwritten!
160                     if (ItemStyle != null) itemBadge.ApplyStyle(ItemStyle.Badge);
161                     Add(itemBadge);
162                 }
163                 layoutChanged = true;
164             }
165         }
166
167         /* open when ImageView using Uri not string
168                 /// <summary>
169                 /// Image image's resource url in DefaultGridItem.
170                 /// </summary>
171                 [EditorBrowsable(EditorBrowsableState.Never)]
172                 public string ImageUrl
173                 {
174                     get
175                     {
176                         return Image.ResourceUrl;
177                     }
178                     set
179                     {
180                         Image.ResourceUrl = value;
181                     }
182                 }
183         */
184
185         /// <summary>
186         /// DefaultGridItem's text part.
187         /// </summary>
188         [EditorBrowsable(EditorBrowsableState.Never)]
189         public TextLabel Label
190         {
191             get
192             {
193                 if (itemLabel == null)
194                 {
195                     itemLabel = CreateLabel(ItemStyle.Label);
196                     if (itemLabel != null)
197                     {
198                         Add(itemLabel);
199                         layoutChanged = true;
200                     }
201                 }
202                 return itemLabel;
203             }
204             internal set
205             {
206                 itemLabel = value;
207                 layoutChanged = true;
208                 AccessibilityManager.Instance.SetAccessibilityAttribute(this, AccessibilityManager.AccessibilityAttribute.Label, itemLabel.Text);
209             }
210         }
211
212         /// <summary>
213         /// The text of DefaultGridItem.
214         /// </summary>
215         [EditorBrowsable(EditorBrowsableState.Never)]
216         public string Text
217         {
218             get
219             {
220                 return GetValue(TextProperty) as string;
221             }
222             set
223             {
224                 SetValue(TextProperty, value);
225                 NotifyPropertyChanged();
226             }
227         }
228         private string InternalText
229         {
230             get
231             {
232                 return Label.Text;
233             }
234             set
235             {
236                 Label.Text = value;
237             }
238         }
239
240         /// <summary>
241         /// Label relative orientation with image in DefaultGridItem.
242         /// </summary>
243         [EditorBrowsable(EditorBrowsableState.Never)]
244         public LabelOrientation LabelOrientationType
245         {
246             get
247             {
248                 return (Tizen.NUI.Components.DefaultGridItem.LabelOrientation)GetValue(LabelOrientationTypeProperty);
249             }
250             set
251             {
252                 SetValue(LabelOrientationTypeProperty, value);
253                 NotifyPropertyChanged();
254             }
255         }
256         private Tizen.NUI.Components.DefaultGridItem.LabelOrientation InternalLabelOrientationType
257         {
258             get
259             {
260                 return labelOrientation;
261             }
262             set
263             {
264                 labelOrientation = value;
265                 layoutChanged = true;
266             }
267         }
268
269         /// <summary>
270         /// Apply style to DefaultLinearItemStyle.
271         /// </summary>
272         /// <param name="viewStyle">The style to apply.</param>
273         [EditorBrowsable(EditorBrowsableState.Never)]
274         public override void ApplyStyle(ViewStyle viewStyle)
275         {
276
277             base.ApplyStyle(viewStyle);
278             if (viewStyle != null && viewStyle is DefaultGridItemStyle defaultStyle)
279             {
280                 if (itemLabel != null)
281                     itemLabel.ApplyStyle(defaultStyle.Label);
282                 if (itemImage != null)
283                     itemImage.ApplyStyle(defaultStyle.Image);
284                 if (itemBadge != null)
285                     itemBadge.ApplyStyle(defaultStyle.Badge);
286             }
287         }
288
289         /// <summary>
290         /// Creates Item's text part.
291         /// </summary>
292         /// <return>The created Item's text part.</return>
293         [EditorBrowsable(EditorBrowsableState.Never)]
294         protected virtual TextLabel CreateLabel(TextLabelStyle textStyle)
295         {
296             return new TextLabel(textStyle)
297             {
298                 HorizontalAlignment = HorizontalAlignment.Center,
299                 VerticalAlignment = VerticalAlignment.Center
300             };
301         }
302
303         /// <summary>
304         /// Creates Item's icon part.
305         /// </summary>
306         /// <return>The created Item's icon part.</return>
307         [EditorBrowsable(EditorBrowsableState.Never)]
308         protected virtual ImageView CreateImage(ImageViewStyle imageStyle)
309         {
310             return new ImageView(imageStyle);
311         }
312
313         /// <inheritdoc/>
314         [EditorBrowsable(EditorBrowsableState.Never)]
315         protected override void MeasureChild()
316         {
317             //nothing to do.
318             if (itemLabel)
319             {
320                 var pad = Padding;
321                 var margin = itemLabel.Margin;
322                 itemLabel.SizeWidth = SizeWidth - pad.Start - pad.End - margin.Start - margin.End;
323             }
324         }
325
326         /// <inheritdoc/>
327         [EditorBrowsable(EditorBrowsableState.Never)]
328         protected override void LayoutChild()
329         {
330             if (!layoutChanged) return;
331             if (itemImage == null) return;
332
333             layoutChanged = false;
334
335             RelativeLayout.SetLeftTarget(itemImage, this);
336             RelativeLayout.SetLeftRelativeOffset(itemImage, 0.0F);
337             RelativeLayout.SetRightTarget(itemImage, this);
338             RelativeLayout.SetRightRelativeOffset(itemImage, 1.0F);
339             RelativeLayout.SetHorizontalAlignment(itemImage, RelativeLayout.Alignment.Center);
340
341             if (itemLabel != null)
342             {
343                 itemLabel.RaiseAbove(itemImage);
344                 RelativeLayout.SetLeftTarget(itemLabel, itemImage);
345                 RelativeLayout.SetLeftRelativeOffset(itemLabel, 0.0F);
346                 RelativeLayout.SetRightTarget(itemLabel, itemImage);
347                 RelativeLayout.SetRightRelativeOffset(itemLabel, 1.0F);
348                 RelativeLayout.SetHorizontalAlignment(itemLabel, RelativeLayout.Alignment.Center);
349                 RelativeLayout.SetFillHorizontal(itemLabel, true);
350             }
351             else
352             {
353                 RelativeLayout.SetTopTarget(itemImage, this);
354                 RelativeLayout.SetTopRelativeOffset(itemImage, 0.0F);
355                 RelativeLayout.SetBottomTarget(itemImage, this);
356                 RelativeLayout.SetBottomRelativeOffset(itemImage, 1.0F);
357                 RelativeLayout.SetVerticalAlignment(itemImage, RelativeLayout.Alignment.Center);
358             }
359
360             if (itemBadge)
361             {
362                 RelativeLayout.SetLeftTarget(itemBadge, itemImage);
363                 RelativeLayout.SetLeftRelativeOffset(itemBadge, 1.0F);
364                 RelativeLayout.SetRightTarget(itemBadge, itemImage);
365                 RelativeLayout.SetRightRelativeOffset(itemBadge, 1.0F);
366                 RelativeLayout.SetHorizontalAlignment(itemBadge, RelativeLayout.Alignment.End);
367             }
368
369             switch (labelOrientation)
370             {
371                 case LabelOrientation.OutsideBottom:
372                     if (itemLabel != null)
373                     {
374                         RelativeLayout.SetTopTarget(itemLabel, this);
375                         RelativeLayout.SetTopRelativeOffset(itemLabel, 1.0F);
376                         RelativeLayout.SetBottomTarget(itemLabel, this);
377                         RelativeLayout.SetBottomRelativeOffset(itemLabel, 1.0F);
378                         RelativeLayout.SetVerticalAlignment(itemLabel, RelativeLayout.Alignment.End);
379
380                         RelativeLayout.SetTopTarget(itemImage, this);
381                         RelativeLayout.SetTopRelativeOffset(itemImage, 0.0F);
382                         RelativeLayout.SetBottomTarget(itemImage, itemLabel);
383                         RelativeLayout.SetBottomRelativeOffset(itemImage, 0.0F);
384                         RelativeLayout.SetVerticalAlignment(itemImage, RelativeLayout.Alignment.Center);
385                     }
386
387                     if (itemBadge)
388                     {
389                         RelativeLayout.SetTopTarget(itemBadge, itemImage);
390                         RelativeLayout.SetTopRelativeOffset(itemBadge, 0.0F);
391                         RelativeLayout.SetBottomTarget(itemBadge, itemImage);
392                         RelativeLayout.SetBottomRelativeOffset(itemBadge, 0.0F);
393                         RelativeLayout.SetVerticalAlignment(itemBadge, RelativeLayout.Alignment.Start);
394                     }
395                     break;
396
397                 case LabelOrientation.OutsideTop:
398                     if (itemLabel != null)
399                     {
400                         RelativeLayout.SetTopTarget(itemLabel, this);
401                         RelativeLayout.SetTopRelativeOffset(itemLabel, 0.0F);
402                         RelativeLayout.SetBottomTarget(itemLabel, this);
403                         RelativeLayout.SetBottomRelativeOffset(itemLabel, 0.0F);
404                         RelativeLayout.SetVerticalAlignment(itemLabel, RelativeLayout.Alignment.Start);
405
406                         RelativeLayout.SetTopTarget(itemImage, itemLabel);
407                         RelativeLayout.SetTopRelativeOffset(itemImage, 1.0F);
408                         RelativeLayout.SetBottomTarget(itemImage, this);
409                         RelativeLayout.SetBottomRelativeOffset(itemImage, 1.0F);
410                         RelativeLayout.SetVerticalAlignment(itemImage, RelativeLayout.Alignment.Center);
411                     }
412
413                     if (itemBadge)
414                     {
415                         RelativeLayout.SetTopTarget(itemBadge, itemImage);
416                         RelativeLayout.SetTopRelativeOffset(itemBadge, 1.0F);
417                         RelativeLayout.SetBottomTarget(itemBadge, itemImage);
418                         RelativeLayout.SetBottomRelativeOffset(itemBadge, 1.0F);
419                         RelativeLayout.SetVerticalAlignment(itemBadge, RelativeLayout.Alignment.End);
420                     }
421                     break;
422
423                 case LabelOrientation.InsideBottom:
424                     if (itemLabel != null)
425                     {
426                         RelativeLayout.SetTopTarget(itemLabel, this);
427                         RelativeLayout.SetTopRelativeOffset(itemLabel, 1.0F);
428                         RelativeLayout.SetBottomTarget(itemLabel, this);
429                         RelativeLayout.SetBottomRelativeOffset(itemLabel, 1.0F);
430                         RelativeLayout.SetVerticalAlignment(itemLabel, RelativeLayout.Alignment.End);
431
432                         RelativeLayout.SetTopTarget(itemImage, this);
433                         RelativeLayout.SetTopRelativeOffset(itemImage, 0.0F);
434                         RelativeLayout.SetBottomTarget(itemImage, this);
435                         RelativeLayout.SetBottomRelativeOffset(itemImage, 1.0F);
436                         RelativeLayout.SetVerticalAlignment(itemImage, RelativeLayout.Alignment.Center);
437                     }
438
439                     if (itemBadge)
440                     {
441                         RelativeLayout.SetTopTarget(itemBadge, itemImage);
442                         RelativeLayout.SetTopRelativeOffset(itemBadge, 0.0F);
443                         RelativeLayout.SetBottomTarget(itemBadge, itemImage);
444                         RelativeLayout.SetBottomRelativeOffset(itemBadge, 0.0F);
445                         RelativeLayout.SetVerticalAlignment(itemBadge, RelativeLayout.Alignment.Start);
446                     }
447                     break;
448
449                 case LabelOrientation.InsideTop:
450                     if (itemLabel != null)
451                     {
452                         RelativeLayout.SetTopTarget(itemLabel, this);
453                         RelativeLayout.SetTopRelativeOffset(itemLabel, 0.0F);
454                         RelativeLayout.SetBottomTarget(itemLabel, this);
455                         RelativeLayout.SetBottomRelativeOffset(itemLabel, 0.0F);
456                         RelativeLayout.SetVerticalAlignment(itemLabel, RelativeLayout.Alignment.Start);
457
458                         RelativeLayout.SetTopTarget(itemImage, this);
459                         RelativeLayout.SetTopRelativeOffset(itemImage, 0.0F);
460                         RelativeLayout.SetBottomTarget(itemImage, this);
461                         RelativeLayout.SetBottomRelativeOffset(itemImage, 1.0F);
462                         RelativeLayout.SetVerticalAlignment(itemImage, RelativeLayout.Alignment.Center);
463                     }
464
465                     if (itemBadge)
466                     {
467                         RelativeLayout.SetTopTarget(itemBadge, itemImage);
468                         RelativeLayout.SetTopRelativeOffset(itemBadge, 1.0F);
469                         RelativeLayout.SetBottomTarget(itemBadge, itemImage);
470                         RelativeLayout.SetBottomRelativeOffset(itemBadge, 1.0F);
471                         RelativeLayout.SetVerticalAlignment(itemBadge, RelativeLayout.Alignment.End);
472                     }
473                     break;
474             }
475
476
477         }
478
479         /// <summary>
480         /// Initializes AT-SPI object.
481         /// </summary>
482         [EditorBrowsable(EditorBrowsableState.Never)]
483         public override void OnInitialize()
484         {
485             base.OnInitialize();
486             Layout = new RelativeLayout();
487             layoutChanged = true;
488             LayoutDirectionChanged += OnLayoutDirectionChanged;
489         }
490
491         /// <summary>
492         /// Dispose Item and all children on it.
493         /// </summary>
494         /// <param name="type">Dispose type.</param>
495         [EditorBrowsable(EditorBrowsableState.Never)]
496         protected override void Dispose(DisposeTypes type)
497         {
498             if (disposed)
499             {
500                 return;
501             }
502
503             if (type == DisposeTypes.Explicit)
504             {
505                 //Extension : Extension?.OnDispose(this);
506
507                 // Arugable to disposing user-created members.
508                 /*
509                 if (itemBadge != null)
510                 {
511                     Utility.Dispose(itemBadge);
512                 }
513                 */
514
515                 if (itemImage != null)
516                 {
517                     Utility.Dispose(itemImage);
518                     itemImage = null;
519                 }
520                 if (itemLabel != null)
521                 {
522                     Utility.Dispose(itemLabel);
523                     itemLabel = null;
524                 }
525
526             }
527
528             base.Dispose(type);
529         }
530
531         private void OnLayoutDirectionChanged(object sender, LayoutDirectionChangedEventArgs e)
532         {
533             MeasureChild();
534             LayoutChild();
535         }
536         private void OnImageRelayout(object sender, EventArgs e)
537         {
538             MeasureChild();
539             LayoutChild();
540         }
541     }
542 }