[NUI] TCSACR-226 code change (#1032)
[platform/core/csapi/tizenfx.git] / src / ElmSharp / ElmSharp / MultiButtonEntry.cs
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
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;
18 using System.Collections.Generic;
19
20 namespace ElmSharp
21 {
22     /// <summary>
23     /// It inherits <see cref="Layout"/>.
24     /// The MultiButtonEntry is a widget, that lets a user enter text and each chunk of the text managed as a set of buttons.
25     /// Each text button is inserted by pressing the "return" key. If there is no space in the current row, a new button is added to the next row.
26     /// When a text button is pressed, it will become focused. Backspace removes the focus. When the multi-button entry loses focus, items longer than one line are shrunk to one line.
27     /// The typical use case of multi-button entry is composing emails/messages to a group of addresses, each of which is an item that can be clicked for further actions.
28     /// </summary>
29     /// <since_tizen> preview </since_tizen>
30     public class MultiButtonEntry : Layout
31     {
32         HashSet<MultiButtonEntryItem> _children = new HashSet<MultiButtonEntryItem>();
33         List<Func<string, bool>> _filters = new List<Func<string, bool>>();
34         Func<int, string> _formatFunc = null;
35         Entry _entry = null;
36
37         Interop.Elementary.MultiButtonEntryItemFilterCallback _filterCallback;
38         Interop.Elementary.MultiButtonEntryFormatCallback _formatCallback;
39
40         SmartEvent _clicked;
41         SmartEvent _expanded;
42         SmartEvent _contracted;
43         SmartEvent _expandedStateChanged;
44         SmartEvent<MultiButtonEntryItemEventArgs> _itemSelected;
45         SmartEvent<MultiButtonEntryItemEventArgs> _itemClicked;
46         SmartEvent<MultiButtonEntryItemEventArgs> _itemLongPressed;
47         SmartEvent<MultiButtonEntryItemEventArgs> _itemAdded;
48
49         /// <summary>
50         /// Creates and initializes a new instance of the MultiButtonEntry class.
51         /// </summary>
52         /// <param name="parent">The parent is a given container, which will be attached by the MultiButtonEntry as a child. It's <see cref="EvasObject"/> type.</param>
53         /// <since_tizen> preview </since_tizen>
54         public MultiButtonEntry(EvasObject parent) : base(parent)
55         {
56             _clicked = new SmartEvent(this, "clicked");
57             _expanded = new SmartEvent(this, "expanded");
58             _contracted = new SmartEvent(this, "contracted");
59             _expandedStateChanged = new SmartEvent(this, "expand,state,changed");
60
61             _itemSelected = new SmartEvent<MultiButtonEntryItemEventArgs>(this, "item,selected", MultiButtonEntryItemEventArgs.CreateFromSmartEvent);
62             _itemClicked = new SmartEvent<MultiButtonEntryItemEventArgs>(this, "item,clicked", MultiButtonEntryItemEventArgs.CreateFromSmartEvent);
63             _itemLongPressed = new SmartEvent<MultiButtonEntryItemEventArgs>(this, "item,longpressed", MultiButtonEntryItemEventArgs.CreateFromSmartEvent);
64             _itemAdded = new SmartEvent<MultiButtonEntryItemEventArgs>(this, "item,added", MultiButtonEntryItemEventArgs.CreateAndAddFromSmartEvent);
65
66             _filterCallback = new Interop.Elementary.MultiButtonEntryItemFilterCallback(FilterCallbackHandler);
67             _formatCallback = new Interop.Elementary.MultiButtonEntryFormatCallback(FormatCallbackHandler);
68
69             _clicked.On += (sender, e) => Clicked?.Invoke(this, EventArgs.Empty);
70             _expanded.On += (sender, e) => Expanded?.Invoke(this, EventArgs.Empty);
71             _contracted.On += (sender, e) => Contracted?.Invoke(this, EventArgs.Empty);
72             _expandedStateChanged.On += (sender, e) => ExpandedStateChanged?.Invoke(this, EventArgs.Empty);
73
74             _itemSelected.On += (sender, e) => { ItemSelected?.Invoke(this, e); };
75             _itemClicked.On += (sender, e) => { ItemClicked?.Invoke(this, e); };
76             _itemLongPressed.On += (sender, e) => { ItemLongPressed?.Invoke(this, e); };
77             _itemAdded.On += OnItemAdded;
78         }
79
80         /// <summary>
81         /// Clicked is raised when a MultiButtonEntry is clicked.
82         /// </summary>
83         /// <since_tizen> preview </since_tizen>
84         public event EventHandler Clicked;
85
86         /// <summary>
87         /// Expanded is raised when a MultiButtonEntry is expanded.
88         /// </summary>
89         /// <since_tizen> preview </since_tizen>
90         public event EventHandler Expanded;
91
92         /// <summary>
93         /// Contracted is raised when a MultiButtonEntry is contracted.
94         /// </summary>
95         /// <since_tizen> preview </since_tizen>
96         public event EventHandler Contracted;
97
98         /// <summary>
99         /// ExpandedStateChanged is raised when shrink mode state of MultiButtonEntry is changed.
100         /// </summary>
101         /// <since_tizen> preview </since_tizen>
102         public event EventHandler ExpandedStateChanged;
103
104         /// <summary>
105         /// ItemSelected is raised when an item is selected by API, user interaction, and etc.
106         /// This is also raised when a user presses backspace, while the cursor is on the first field of the entry.
107         /// </summary>
108         /// <since_tizen> preview </since_tizen>
109         public event EventHandler<MultiButtonEntryItemEventArgs> ItemSelected;
110
111         /// <summary>
112         /// ItemClicked is raised when an item is clicked by user interaction.
113         /// </summary>
114         /// <since_tizen> preview </since_tizen>
115         public event EventHandler<MultiButtonEntryItemEventArgs> ItemClicked;
116
117         /// <summary>
118         /// ItemLongPressed is raised when MultiButtonEntry item is pressed for a long time.
119         /// </summary>
120         /// <since_tizen> preview </since_tizen>
121         public event EventHandler<MultiButtonEntryItemEventArgs> ItemLongPressed;
122
123         /// <summary>
124         /// ItemAdded is raised when a new MultiButtonEntry item is added.
125         /// </summary>
126         /// <since_tizen> preview </since_tizen>
127         public event EventHandler<MultiButtonEntryItemEventArgs> ItemAdded;
128
129         /// <summary>
130         /// ItemDeleted is raised when a MultiButtonEntry item is deleted.
131         /// </summary>
132         /// <since_tizen> preview </since_tizen>
133         public event EventHandler<MultiButtonEntryItemEventArgs> ItemDeleted;
134
135         /// <summary>
136         /// Gets the selected item in the MultiButtonEntry.
137         /// </summary>
138         /// <since_tizen> preview </since_tizen>
139         public MultiButtonEntryItem SelectedItem
140         {
141             get
142             {
143                 IntPtr handle = Interop.Elementary.elm_multibuttonentry_selected_item_get(RealHandle);
144                 return ItemObject.GetItemByHandle(handle) as MultiButtonEntryItem;
145             }
146         }
147
148         /// <summary>
149         /// Gets or sets whether the MultiButtonEntry is editable or not.
150         /// </summary>
151         /// <since_tizen> preview </since_tizen>
152         public bool IsEditable
153         {
154             get
155             {
156                 return Interop.Elementary.elm_multibuttonentry_editable_get(RealHandle);
157             }
158             set
159             {
160                 Interop.Elementary.elm_multibuttonentry_editable_set(RealHandle, value);
161             }
162         }
163
164         /// <summary>
165         /// Gets or sets the MultiButtonEntry to expanded state.
166         /// If true, expanded state.
167         /// If false, single line state.
168         /// </summary>
169         /// <since_tizen> preview </since_tizen>
170         public bool IsExpanded
171         {
172             get
173             {
174                 return Interop.Elementary.elm_multibuttonentry_expanded_get(RealHandle);
175             }
176             set
177             {
178                 Interop.Elementary.elm_multibuttonentry_expanded_set(RealHandle, value);
179             }
180         }
181
182         /// <summary>
183         /// Gets the first item in the MultiButtonEntry.
184         /// </summary>
185         /// <since_tizen> preview </since_tizen>
186         public MultiButtonEntryItem FirstItem
187         {
188             get
189             {
190                 IntPtr handle = Interop.Elementary.elm_multibuttonentry_first_item_get(RealHandle);
191                 return ItemObject.GetItemByHandle(handle) as MultiButtonEntryItem;
192             }
193         }
194
195         /// <summary>
196         /// Gets the last item in the MultiButtonEntry.
197         /// </summary>
198         /// <since_tizen> preview </since_tizen>
199         public MultiButtonEntryItem LastItem
200         {
201             get
202             {
203                 IntPtr handle = Interop.Elementary.elm_multibuttonentry_last_item_get(RealHandle);
204                 return ItemObject.GetItemByHandle(handle) as MultiButtonEntryItem;
205             }
206         }
207
208         /// <summary>
209         /// Gets the entry object int the MultiButtonEntry.
210         /// </summary>
211         /// <since_tizen> preview </since_tizen>
212         public Entry Entry
213         {
214             get
215             {
216                 if (_entry == null)
217                 {
218                     _entry = new EntryInner(this);
219                 }
220
221                 return _entry;
222             }
223         }
224
225         /// <summary>
226         /// Creates a widget handle.
227         /// </summary>
228         /// <param name="parent">Parent EvasObject.</param>
229         /// <returns>Handle IntPtr.</returns>
230         /// <since_tizen> preview </since_tizen>
231         protected override IntPtr CreateHandle(EvasObject parent)
232         {
233             return Interop.Elementary.elm_multibuttonentry_add(parent.Handle);
234         }
235
236         /// <summary>
237         /// Appends a new item to the multibuttonentry.
238         /// </summary>
239         /// <param name="label">The label of the new item.</param>
240         /// <returns>A MultiButtonEntryItem to the item added.</returns>
241         /// <since_tizen> preview </since_tizen>
242         public MultiButtonEntryItem Append(string label)
243         {
244             var handle = Interop.Elementary.elm_multibuttonentry_item_append(RealHandle, label, null, IntPtr.Zero);
245             MultiButtonEntryItem item = ItemObject.GetItemByHandle(handle) as MultiButtonEntryItem;
246             return item;
247         }
248
249         /// <summary>
250         /// Prepends a new item to the MultiButtonEntry.
251         /// </summary>
252         /// <param name="label">The label of the new item.</param>
253         /// <returns>A MultiButtonEntryItem to the item added.</returns>
254         /// <since_tizen> preview </since_tizen>
255         public MultiButtonEntryItem Prepend(string label)
256         {
257             var handle = Interop.Elementary.elm_multibuttonentry_item_prepend(RealHandle, label, null, IntPtr.Zero);
258             MultiButtonEntryItem item = ItemObject.GetItemByHandle(handle) as MultiButtonEntryItem;
259             return item;
260         }
261
262         /// <summary>
263         /// Adds a new item to the MultiButtonEntry before the indicated object reference.
264         /// </summary>
265         /// <param name="before">The item before which to add it.</param>
266         /// <param name="label">The label of new item.</param>
267         /// <returns>A MultiButtonEntryItem to the item added.</returns>
268         /// <since_tizen> preview </since_tizen>
269         public MultiButtonEntryItem InsertBefore(MultiButtonEntryItem before, string label)
270         {
271             var handle = Interop.Elementary.elm_multibuttonentry_item_insert_before(RealHandle, before.Handle, label, null, IntPtr.Zero);
272             MultiButtonEntryItem item = ItemObject.GetItemByHandle(handle) as MultiButtonEntryItem;
273             return item;
274         }
275
276         /// <summary>
277         /// Adds a new item to the MultiButtonEntry after the indicated object.
278         /// </summary>
279         /// <param name="after">The item after which to add it.</param>
280         /// <param name="label">The label of new item.</param>
281         /// <returns>A MultiButtonEntryItem to the item added.</returns>
282         /// <since_tizen> preview </since_tizen>
283         public MultiButtonEntryItem InsertAfter(MultiButtonEntryItem after, string label)
284         {
285             var handle = Interop.Elementary.elm_multibuttonentry_item_insert_after(RealHandle, after.Handle, label, null, IntPtr.Zero);
286             MultiButtonEntryItem item = ItemObject.GetItemByHandle(handle) as MultiButtonEntryItem;
287             return item;
288         }
289
290         /// <summary>
291         /// Removes all items in the MultiButtonEntry.
292         /// </summary>
293         /// <since_tizen> preview </since_tizen>
294         public void Clear()
295         {
296             Interop.Elementary.elm_multibuttonentry_clear(RealHandle);
297             foreach (var item in _children)
298             {
299                 item.Deleted -= Item_Deleted;
300             }
301             _children.Clear();
302         }
303
304         /// <summary>
305         /// Appends an item filter function for the text inserted in the multibuttonentry.
306         /// </summary>
307         /// <param name="func">The function to use as item filter.</param>
308         /// <since_tizen> preview </since_tizen>
309         public void AppendFilter(Func<string, bool> func)
310         {
311             _filters.Add(func);
312             if (_filters.Count == 1)
313             {
314                 Interop.Elementary.elm_multibuttonentry_item_filter_append(RealHandle, _filterCallback, IntPtr.Zero);
315             }
316         }
317
318         /// <summary>
319         /// Prepends a filter function for the text inserted in the MultiButtonEntry.
320         /// </summary>
321         /// <param name="func">The function to use as text filter.</param>
322         /// <since_tizen> preview </since_tizen>
323         public void PrependFilter(Func<string, bool> func)
324         {
325             _filters.Insert(0, func);
326             if (_filters.Count == 1)
327             {
328                 Interop.Elementary.elm_multibuttonentry_item_filter_prepend(RealHandle, _filterCallback, IntPtr.Zero);
329             }
330         }
331
332         /// <summary>
333         /// Removes a filter from the list.
334         /// </summary>
335         /// <param name="func">The filter function to remove.</param>
336         /// <since_tizen> preview </since_tizen>
337         public void RemoveFilter(Func<string, bool> func)
338         {
339             _filters.Remove(func);
340             if (_filters.Count == 0)
341             {
342                 Interop.Elementary.elm_multibuttonentry_item_filter_remove(RealHandle, _filterCallback, IntPtr.Zero);
343             }
344         }
345
346         /// <summary>
347         /// Sets a function to format the string that will be used to display the hidden items counter.
348         /// If func is NULL, the default format will be used, which is "+ 'the hidden items counter'".
349         /// </summary>
350         /// <param name="func">The function to return string to show.</param>
351         /// <since_tizen> preview </since_tizen>
352         public void SetFormatCallback(Func<int, string> func)
353         {
354             if (func == null)
355             {
356                 Interop.Elementary.elm_multibuttonentry_format_function_set(RealHandle, null, IntPtr.Zero);
357             }
358             else
359             {
360                 _formatFunc = func;
361                 Interop.Elementary.elm_multibuttonentry_format_function_set(RealHandle, _formatCallback, IntPtr.Zero);
362             }
363         }
364
365         string FormatCallbackHandler(int count, IntPtr data)
366         {
367             return _formatFunc(count);
368         }
369
370         void Item_Deleted(object sender, EventArgs e)
371         {
372             var removed = sender as MultiButtonEntryItem;
373             _children.Remove(removed);
374
375             // "item,deleted" event will be called after removing the item from ItemObject has been done.
376             // ItemObject will no longer have the item instance that is deleted after this.
377             // So, ItemDelete event with the removed item should be triggered here.
378             ItemDeleted?.Invoke(this, new MultiButtonEntryItemEventArgs { Item = removed });
379         }
380
381         void OnItemAdded(object sender, MultiButtonEntryItemEventArgs e)
382         {
383             e.Item.Parent = this;
384             _children.Add(e.Item);
385             e.Item.Deleted += Item_Deleted;
386             ItemAdded?.Invoke(this, e);
387         }
388
389         bool FilterCallbackHandler(IntPtr obj, string label, IntPtr itemData, IntPtr data)
390         {
391             foreach (var func in _filters)
392             {
393                 if (!func(label))
394                     return false;
395             }
396             return true;
397         }
398
399         internal class EntryInner : Entry
400         {
401             /// <summary>
402             /// Creates and initializes a new instance of the EntryInner class.
403             /// </summary>
404             /// <param name="parent">The parent is a given container, which will be attached by the MultiButtonEntry as a child. It's <see cref="EvasObject"/> type.</param>
405             internal EntryInner(EvasObject parent) : base(parent)
406             {
407             }
408
409             /// <summary>
410             /// Creates a widget handle.
411             /// </summary>
412             /// <param name="parent">Parent EvasObject.</param>
413             /// <returns>Handle IntPtr.</returns>
414             protected override IntPtr CreateHandle(EvasObject parent)
415             {
416                 return Interop.Elementary.elm_multibuttonentry_entry_get(parent.Handle);
417             }
418         }
419     }
420
421     /// <summary>
422     /// It inherits System.EventArgs.
423     /// The MultiButtonEntryItemEventArgs is a argument for all events of MultiButtonEntry.
424     /// It contains the Item which is <see cref="MultiButtonEntryItem"/> type.
425     /// </summary>
426     /// <since_tizen> preview </since_tizen>
427     public class MultiButtonEntryItemEventArgs : EventArgs
428     {
429         /// <summary>
430         /// Gets or sets the MultiButtonEntryItem item. The return type is <see cref="MultiButtonEntryItem"/>.
431         /// </summary>
432         /// <since_tizen> preview </since_tizen>
433         public MultiButtonEntryItem Item { get; set; }
434
435         internal static MultiButtonEntryItemEventArgs CreateFromSmartEvent(IntPtr data, IntPtr obj, IntPtr info)
436         {
437             MultiButtonEntryItem item = ItemObject.GetItemByHandle(info) as MultiButtonEntryItem;
438             return new MultiButtonEntryItemEventArgs { Item = item };
439         }
440
441         internal static MultiButtonEntryItemEventArgs CreateAndAddFromSmartEvent(IntPtr data, IntPtr obj, IntPtr info)
442         {
443             // Item can be added throught calling Append method and user input.
444             // And since "item.added" event will be called before xx_append() method returns,
445             // ItemObject does NOT have an item that contains handle matched to "info" at this time.
446             // So, item should be created and added internally here.
447
448             MultiButtonEntryItem item = new MultiButtonEntryItem(info);
449             return new MultiButtonEntryItemEventArgs { Item = item };
450         }
451     }
452 }