14bb7ce8a01c2e0af39e4dbb05525f53951684ec
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.Components / Controls / RecyclerView / Item / RecyclerViewItem.cs
1 /* Copyright (c) 2022 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
21 namespace Tizen.NUI.Components
22 {
23     /// <summary>
24     /// This class provides a basic item for CollectionView.
25     /// </summary>
26     /// <since_tizen> 9 </since_tizen>
27     public partial class RecyclerViewItem : Control
28     {
29         /// <summary>
30         /// Property of boolean Enable flag.
31         /// </summary>
32         /// <since_tizen> 9 </since_tizen>
33         public static readonly BindableProperty IsEnabledProperty = View.IsEnabledProperty;
34
35         /// <summary>
36         /// Property of boolean Selected flag.
37         /// </summary>
38         /// <since_tizen> 9 </since_tizen>
39         public static readonly BindableProperty IsSelectedProperty = BindableProperty.Create(nameof(IsSelected), typeof(bool), typeof(RecyclerViewItem), false, propertyChanged: (bindable, oldValue, newValue) =>
40         {
41             var instance = (RecyclerViewItem)bindable;
42             if (newValue != null)
43             {
44                 bool newSelected = (bool)newValue;
45                 if (instance.isSelected != newSelected)
46                 {
47                     instance.isSelected = newSelected;
48
49                     if (instance.isSelectable)
50                     {
51                         instance.UpdateState();
52                     }
53                 }
54             }
55         },
56         defaultValueCreator: (bindable) =>
57         {
58             var instance = (RecyclerViewItem)bindable;
59             return instance.isSelectable && instance.isSelected;
60         });
61
62         /// <summary>
63         /// Property of boolean Selectable flag.
64         /// </summary>
65         /// <since_tizen> 9 </since_tizen>
66         public static readonly BindableProperty IsSelectableProperty = BindableProperty.Create(nameof(IsSelectable), typeof(bool), typeof(RecyclerViewItem), true, propertyChanged: (bindable, oldValue, newValue) =>
67         {
68             var instance = (RecyclerViewItem)bindable;
69             if (newValue != null)
70             {
71                 bool newSelectable = (bool)newValue;
72                 if (instance.isSelectable != newSelectable)
73                 {
74                     instance.isSelectable = newSelectable;
75                     instance.UpdateState();
76                 }
77             }
78         },
79         defaultValueCreator: (bindable) => ((RecyclerViewItem)bindable).isSelectable);
80
81         private bool isSelected = false;
82         private bool isSelectable = true;
83         private RecyclerViewItemStyle ItemStyle => ViewStyle as RecyclerViewItemStyle;
84
85         static RecyclerViewItem() { }
86
87         /// <summary>
88         /// Creates a new instance of RecyclerViewItem.
89         /// </summary>
90         /// <since_tizen> 9 </since_tizen>
91         public RecyclerViewItem() : base()
92         {
93         }
94
95         /// <summary>
96         /// Creates a new instance of RecyclerViewItem with style.
97         /// </summary>
98         /// <param name="style">Create RecyclerViewItem by special style defined in UX.</param>
99         /// <since_tizen> 9 </since_tizen>
100         public RecyclerViewItem(string style) : base(style)
101         {
102         }
103
104         /// <summary>
105         /// Creates a new instance of a RecyclerViewItem with style.
106         /// </summary>
107         /// <param name="itemStyle">Create RecyclerViewItem by style customized by user.</param>
108         /// <since_tizen> 9 </since_tizen>
109         public RecyclerViewItem(RecyclerViewItemStyle itemStyle) : base(itemStyle)
110         {
111         }
112
113         /// <summary>
114         /// An event for the RecyclerViewItem clicked signal which can be used to subscribe or unsubscribe the event handler provided by the user.
115         /// </summary>
116         /// <since_tizen> 9 </since_tizen>
117         public event EventHandler<ClickedEventArgs> Clicked;
118
119         /// <summary>
120         /// Flag to decide RecyclerViewItem can be selected or not.
121         /// </summary>
122         /// <since_tizen> 9 </since_tizen>
123         public bool IsSelectable
124         {
125             get => (bool)GetValue(IsSelectableProperty);
126             set => SetValue(IsSelectableProperty, value);
127         }
128
129         /// <summary>
130         /// Flag to decide selected state in RecyclerViewItem.
131         /// </summary>
132         /// <since_tizen> 9 </since_tizen>
133         public bool IsSelected
134         {
135             get => (bool)GetValue(IsSelectedProperty);
136             set => SetValue(IsSelectedProperty, value);
137         }
138
139         /// <summary>
140         /// Flag to decide enabled state in RecyclerViewItem.
141         /// Set enabled state false makes item untouchable and unfocusable.
142         /// </summary>
143         /// <since_tizen> 9 </since_tizen>
144         public new bool IsEnabled
145         {
146             get => base.IsEnabled;
147             set
148             {
149                 base.IsEnabled = value;
150             }
151         }
152
153         /// <summary>
154         /// Data index which is binded to item.
155         /// Can access to data using this index.
156         /// </summary>
157         [EditorBrowsable(EditorBrowsableState.Never)]
158         public int Index { get; internal set; } = 0;
159
160         /// <summary>
161         /// DataTemplate of this view object
162         /// </summary>
163         [EditorBrowsable(EditorBrowsableState.Never)]
164         public DataTemplate Template { get; internal set; }
165
166         /// <summary>
167         /// State of Realization
168         /// </summary>
169         [EditorBrowsable(EditorBrowsableState.Never)]
170         public bool IsRealized { get; internal set; }
171         internal bool IsHeader { get; set; }
172         internal bool IsFooter { get; set; }
173         internal bool IsPressed { get; set; } = false;
174
175         /// <summary>
176         /// Called after a key event is received by the view that has had its focus set.
177         /// </summary>
178         /// <param name="key">The key event.</param>
179         /// <returns>True if the key event should be consumed.</returns>
180         [EditorBrowsable(EditorBrowsableState.Never)]
181         public override bool OnKey(Key key)
182         {
183             bool clicked = false;
184
185             if (!IsEnabled || null == key || null == BindingContext)
186             {
187                 return false;
188             }
189
190             if (key.State == Key.StateType.Down)
191             {
192                 if (key.KeyPressedName == "Return")
193                 {
194                     IsPressed = true;
195                     UpdateState();
196                 }
197             }
198             else if (key.State == Key.StateType.Up)
199             {
200                 if (key.KeyPressedName == "Return")
201                 {
202                     clicked = IsPressed && IsEnabled;
203
204                     IsPressed = false;
205
206                     if (IsSelectable)
207                     {
208                         // Extension : Extension?.SetTouchInfo(touch);
209                         if (ParentItemsView is CollectionView colView)
210                         {
211                             switch (colView.SelectionMode)
212                             {
213                                 case ItemSelectionMode.Single:
214                                     colView.SelectedItem = IsSelected ? null : BindingContext;
215                                     break;
216                                 case ItemSelectionMode.SingleAlways:
217                                     if (colView.SelectedItem != BindingContext)
218                                         colView.SelectedItem = BindingContext;
219                                     break;
220                                 case ItemSelectionMode.Multiple:
221                                     var selectedItems = colView.SelectedItems;
222                                     if (selectedItems.Contains(BindingContext)) selectedItems.Remove(BindingContext);
223                                     else selectedItems.Add(BindingContext);
224                                     break;
225                                 case ItemSelectionMode.None:
226                                     break;
227                             }
228                         }
229                     }
230
231                     if (clicked)
232                     {
233                         ClickedEventArgs eventArgs = new ClickedEventArgs();
234                         OnClickedInternal(eventArgs);
235                     }
236
237                     UpdateState();
238                 }
239             }
240             return base.OnKey(key) || clicked;
241         }
242
243         /// <summary>
244         /// Called when the control gain key input focus. Should be overridden by derived classes if they need to customize what happens when the focus is gained.
245         /// </summary>
246         [EditorBrowsable(EditorBrowsableState.Never)]
247         public override void OnFocusGained()
248         {
249             base.OnFocusGained();
250             UpdateState();
251         }
252
253         /// <summary>
254         /// Called when the control loses key input focus.
255         /// Should be overridden by derived classes if they need to customize
256         /// what happens when the focus is lost.
257         /// </summary>
258         [EditorBrowsable(EditorBrowsableState.Never)]
259         public override void OnFocusLost()
260         {
261             base.OnFocusLost();
262             UpdateState();
263         }
264
265         /// <summary>
266         /// Apply style to RecyclerViewItem.
267         /// </summary>
268         /// <param name="viewStyle">The style to apply.</param>
269         /// <since_tizen> 9 </since_tizen>
270         public override void ApplyStyle(ViewStyle viewStyle)
271         {
272             styleApplied = false;
273
274             base.ApplyStyle(viewStyle);
275             if (viewStyle != null)
276             {
277                 //Extension = RecyclerViewItemStyle.CreateExtension();
278                 //FIXME : currently padding and margin are not applied by ApplyStyle automatically as missing binding features.
279                 Padding = new Extents(viewStyle.Padding);
280                 Margin = new Extents(viewStyle.Margin);
281             }
282
283             styleApplied = true;
284         }
285
286         /// <summary>
287         /// Get ViewItem style.
288         /// </summary>
289         /// <returns>The default ViewItem style.</returns>
290         /// <since_tizen> 9 </since_tizen>
291         protected override ViewStyle CreateViewStyle()
292         {
293             return new RecyclerViewItemStyle();
294         }
295
296         /// <summary>
297         /// Called when the ViewItem is Clicked by a user
298         /// </summary>
299         /// <param name="eventArgs">The click information.</param>
300         /// <since_tizen> 9 </since_tizen>
301         protected virtual void OnClicked(ClickedEventArgs eventArgs)
302         {
303             //Console.WriteLine("On Clicked Called {0}", this.Index);
304         }
305
306         /// <inheritdoc/>
307         /// <since_tizen> 9 </since_tizen>
308         protected override void Dispose(DisposeTypes type)
309         {
310             if (disposed)
311             {
312                 return;
313             }
314
315             if (type == DisposeTypes.Explicit)
316             {
317                 //
318             }
319
320             base.Dispose(type);
321         }
322     }
323 }