Add BackButtonPressed/MoreButtonPressed event on EvasObject
[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 letting an user enter text and each chunk of 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     public class MultiButtonEntry : Layout
30     {
31         HashSet<MultiButtonEntryItem> _children = new HashSet<MultiButtonEntryItem>();
32         List<Func<string, bool>> _filters = new List<Func<string, bool>>();
33         Entry _entry = null;
34
35         Interop.Elementary.MultiButtonEntryItemFilterCallback _filtercallback;
36
37         SmartEvent _clicked;
38         SmartEvent _expanded;
39         SmartEvent _contracted;
40         SmartEvent _expandedStateChanged;
41         SmartEvent<MultiButtonEntryItemEventArgs> _itemSelected;
42         SmartEvent<MultiButtonEntryItemEventArgs> _itemClicked;
43         SmartEvent<MultiButtonEntryItemEventArgs> _itemLongPressed;
44         SmartEvent<MultiButtonEntryItemEventArgs> _itemAdded;
45
46         /// <summary>
47         /// Creates and initializes a new instance of the MultiButtonEntry class.
48         /// </summary>
49         /// <param name="parent">The parent is a given container which will be attached by MultiButtonEntry as a child. It's <see cref="EvasObject"/> type.</param>
50         public MultiButtonEntry(EvasObject parent) : base(parent)
51         {
52             _clicked = new SmartEvent(this, "clicked");
53             _expanded = new SmartEvent(this, "expanded");
54             _contracted = new SmartEvent(this, "contracted");
55             _expandedStateChanged = new SmartEvent(this, "expand,state,changed");
56
57             _itemSelected = new SmartEvent<MultiButtonEntryItemEventArgs>(this, "item,selected", MultiButtonEntryItemEventArgs.CreateFromSmartEvent);
58             _itemClicked = new SmartEvent<MultiButtonEntryItemEventArgs>(this, "item,clicked", MultiButtonEntryItemEventArgs.CreateFromSmartEvent);
59             _itemLongPressed = new SmartEvent<MultiButtonEntryItemEventArgs>(this, "item,longpressed", MultiButtonEntryItemEventArgs.CreateFromSmartEvent);
60             _itemAdded = new SmartEvent<MultiButtonEntryItemEventArgs>(this, "item,added", MultiButtonEntryItemEventArgs.CreateAndAddFromSmartEvent);
61
62             _filtercallback = new Interop.Elementary.MultiButtonEntryItemFilterCallback(FilterCallbackHandler);
63
64             _clicked.On += (sender, e) => Clicked?.Invoke(this, EventArgs.Empty);
65             _expanded.On += (sender, e) => Expanded?.Invoke(this, EventArgs.Empty);
66             _contracted.On += (sender, e) => Contracted?.Invoke(this, EventArgs.Empty);
67             _expandedStateChanged.On += (sender, e) => ExpandedStateChanged?.Invoke(this, EventArgs.Empty);
68
69             _itemSelected.On += (sender, e) => { ItemSelected?.Invoke(this, e); };
70             _itemClicked.On += (sender, e) => { ItemClicked?.Invoke(this, e); };
71             _itemLongPressed.On += (sender, e) => { ItemLongPressed?.Invoke(this, e); };
72             _itemAdded.On += OnItemAdded;
73         }
74
75         /// <summary>
76         /// Clicked is raised when a MultiButtonEntry is clicked.
77         /// </summary>
78         public event EventHandler Clicked;
79
80         /// <summary>
81         /// Expanded is raised when a MultiButtonEntry is expanded.
82         /// </summary>
83         public event EventHandler Expanded;
84
85         /// <summary>
86         /// Contracted is raised when a MultiButtonEntry is contracted.
87         /// </summary>
88         public event EventHandler Contracted;
89
90         /// <summary>
91         /// ExpandedStateChanged is raised when shrink mode state of MultiButtonEntry is changed.
92         /// </summary>
93         public event EventHandler ExpandedStateChanged;
94
95         /// <summary>
96         /// ItemSelected is raised when an item is selected by api, user interaction, and etc.
97         /// This is also raised when a user press back space while cursor is on the first field of entry.
98         /// </summary>
99         public event EventHandler<MultiButtonEntryItemEventArgs> ItemSelected;
100
101         /// <summary>
102         /// ItemClicked is raised when an item is clicked by user interaction.
103         /// </summary>
104         public event EventHandler<MultiButtonEntryItemEventArgs> ItemClicked;
105
106         /// <summary>
107         /// ItemLongPressed is raised when MultiButtonEntry item is pressed for a long time.
108         /// </summary>
109         public event EventHandler<MultiButtonEntryItemEventArgs> ItemLongPressed;
110
111         /// <summary>
112         /// ItemAdded is raised when a new MultiButtonEntry item is added.
113         /// </summary>
114         public event EventHandler<MultiButtonEntryItemEventArgs> ItemAdded;
115
116         /// <summary>
117         /// ItemDeleted is raised when a MultiButtonEntry item is deleted.
118         /// </summary>
119         public event EventHandler<MultiButtonEntryItemEventArgs> ItemDeleted;
120
121         /// <summary>
122         /// Gets the selected item in the multibuttonentry.
123         /// </summary>
124         public MultiButtonEntryItem SelectedItem
125         {
126             get
127             {
128                 IntPtr handle = Interop.Elementary.elm_multibuttonentry_selected_item_get(RealHandle);
129                 return ItemObject.GetItemByHandle(handle) as MultiButtonEntryItem;
130             }
131         }
132
133         /// <summary>
134         /// Gets or sets whether the multibuttonentry is editable or not.
135         /// </summary>
136         public bool IsEditable
137         {
138             get
139             {
140                 return Interop.Elementary.elm_multibuttonentry_editable_get(RealHandle);
141             }
142             set
143             {
144                 Interop.Elementary.elm_multibuttonentry_editable_set(RealHandle, value);
145             }
146         }
147
148         /// <summary>
149         /// Gets or sets the multibuttonentry to expanded state.
150         /// If true, expanded state.
151         /// If false, single line state.
152         /// </summary>
153         public bool IsExpanded
154         {
155             get
156             {
157                 return Interop.Elementary.elm_multibuttonentry_expanded_get(RealHandle);
158             }
159             set
160             {
161                 Interop.Elementary.elm_multibuttonentry_expanded_set(RealHandle, value);
162             }
163         }
164
165         /// <summary>
166         /// Gets the first item in the multibuttonentry.
167         /// </summary>
168         public MultiButtonEntryItem FirstItem
169         {
170             get
171             {
172                 IntPtr handle = Interop.Elementary.elm_multibuttonentry_first_item_get(RealHandle);
173                 return ItemObject.GetItemByHandle(handle) as MultiButtonEntryItem;
174             }
175         }
176
177         /// <summary>
178         /// Gets the last item in the multibuttonentry.
179         /// </summary>
180         public MultiButtonEntryItem LastItem
181         {
182             get
183             {
184                 IntPtr handle = Interop.Elementary.elm_multibuttonentry_last_item_get(RealHandle);
185                 return ItemObject.GetItemByHandle(handle) as MultiButtonEntryItem;
186             }
187         }
188
189         /// <summary>
190         /// Gets the entry object int the multibuttonentry.
191         /// </summary>
192         public Entry Entry
193         {
194             get
195             {
196                 if (_entry == null)
197                 {
198                     _entry = new EntryInner(this);
199                 }
200
201                 return _entry;
202             }
203         }
204
205         protected override IntPtr CreateHandle(EvasObject parent)
206         {
207             return Interop.Elementary.elm_multibuttonentry_add(parent.Handle);
208         }
209
210         /// <summary>
211         /// Append a new item to the multibuttonentry.
212         /// </summary>
213         /// <param name="label">The label of new item.</param>
214         /// <returns>A MultiButtonEntryItem to the item added.</returns>
215         public MultiButtonEntryItem Append(string label)
216         {
217             var handle = Interop.Elementary.elm_multibuttonentry_item_append(RealHandle, label, null, IntPtr.Zero);
218             MultiButtonEntryItem item = ItemObject.GetItemByHandle(handle) as MultiButtonEntryItem;
219             return item;
220         }
221
222         /// <summary>
223         /// Prepend a new item to the multibuttonentry.
224         /// </summary>
225         /// <param name="label">The label of new item.</param>
226         /// <returns>A MultiButtonEntryItem to the item added.</returns>
227         public MultiButtonEntryItem Prepend(string label)
228         {
229             var handle = Interop.Elementary.elm_multibuttonentry_item_prepend(RealHandle, label, null, IntPtr.Zero);
230             MultiButtonEntryItem item = ItemObject.GetItemByHandle(handle) as MultiButtonEntryItem;
231             return item;
232         }
233
234         /// <summary>
235         /// Add a new item to the multibuttonentry before the indicated object reference.
236         /// </summary>
237         /// <param name="before">The item before which to add it.</param>
238         /// <param name="label">The label of new item.</param>
239         /// <returns>A MultiButtonEntryItem to the item added.</returns>
240         public MultiButtonEntryItem InsertBefore(MultiButtonEntryItem before, string label)
241         {
242             var handle = Interop.Elementary.elm_multibuttonentry_item_insert_before(RealHandle, before.Handle, label, null, IntPtr.Zero);
243             MultiButtonEntryItem item = ItemObject.GetItemByHandle(handle) as MultiButtonEntryItem;
244             return item;
245         }
246
247         /// <summary>
248         /// Add a new item to the multibuttonentry after the indicated object.
249         /// </summary>
250         /// <param name="after">The item after which to add it.</param>
251         /// <param name="label">The label of new item.</param>
252         /// <returns>A MultiButtonEntryItem to the item added.</returns>
253         public MultiButtonEntryItem InsertAfter(MultiButtonEntryItem after, string label)
254         {
255             var handle = Interop.Elementary.elm_multibuttonentry_item_insert_after(RealHandle, after.Handle, label, null, IntPtr.Zero);
256             MultiButtonEntryItem item = ItemObject.GetItemByHandle(handle) as MultiButtonEntryItem;
257             return item;
258         }
259
260         /// <summary>
261         /// Remove all items in the multibuttonentry.
262         /// </summary>
263         public void Clear()
264         {
265             Interop.Elementary.elm_multibuttonentry_clear(RealHandle);
266             _children.Clear();
267         }
268
269         /// <summary>
270         /// Append an item filter function for text inserted in the Multibuttonentry.
271         /// </summary>
272         /// <param name="func">The function to use as item filter.</param>
273         public void AppendFilter(Func<string, bool> func)
274         {
275             _filters.Add(func);
276             if (_filters.Count == 1)
277             {
278                 Interop.Elementary.elm_multibuttonentry_item_filter_append(RealHandle, _filtercallback, IntPtr.Zero);
279             }
280         }
281
282         /// <summary>
283         /// Prepend a filter function for text inserted in the Multibuttonentry.
284         /// </summary>
285         /// <param name="func">The function to use as text filter.</param>
286         public void PrependFilter(Func<string, bool> func)
287         {
288             _filters.Insert(0, func);
289             if (_filters.Count == 1)
290             {
291                 Interop.Elementary.elm_multibuttonentry_item_filter_prepend(RealHandle, _filtercallback, IntPtr.Zero);
292             }
293         }
294
295         /// <summary>
296         /// Remove a filter from the list.
297         /// </summary>
298         /// <param name="func">The filter function to remove.</param>
299         public void RemoveFilter(Func<string, bool> func)
300         {
301             _filters.Remove(func);
302             if (_filters.Count == 0)
303             {
304                 Interop.Elementary.elm_multibuttonentry_item_filter_remove(RealHandle, _filtercallback, IntPtr.Zero);
305             }
306         }
307
308         void Item_Deleted(object sender, EventArgs e)
309         {
310             var removed = sender as MultiButtonEntryItem;
311             _children.Remove(removed);
312
313             // "item,deleted" event will be called after removing the item from ItemObject has been done.
314             // ItemObject will no longer have the item instance that is deleted after this.
315             // So, ItemDelete event with the removed item should be triggered here.
316             ItemDeleted?.Invoke(this, new MultiButtonEntryItemEventArgs() { Item = removed });
317         }
318
319         void OnItemAdded(object sender, MultiButtonEntryItemEventArgs e)
320         {
321             _children.Add(e.Item);
322             e.Item.Deleted += Item_Deleted;
323             ItemAdded?.Invoke(this, e);
324         }
325
326         bool FilterCallbackHandler(IntPtr obj, string label, IntPtr itemData, IntPtr data)
327         {
328             foreach (var func in _filters)
329             {
330                 if (!func(label))
331                     return false;
332             }
333             return true;
334         }
335
336         internal class EntryInner : Entry
337         {
338             internal EntryInner(EvasObject parent) : base(parent)
339             {
340             }
341
342             protected override IntPtr CreateHandle(EvasObject parent)
343             {
344                 return Interop.Elementary.elm_multibuttonentry_entry_get(parent.Handle);
345             }
346         }
347     }
348
349     /// <summary>
350     /// It inherits System.EventArgs.
351     /// The MultiButtonEntryItemEventArgs is a argument for all events of MultiButtonEntry.
352     /// It contains Item which is <see cref="MultiButtonEntryItem"/> type.
353     /// </summary>
354     public class MultiButtonEntryItemEventArgs : EventArgs
355     {
356         /// <summary>
357         /// Gets or sets MultiButtonEntryItem item. The return type is <see cref="MultiButtonEntryItem"/>.
358         /// </summary>
359         public MultiButtonEntryItem Item { get; set; }
360
361         internal static MultiButtonEntryItemEventArgs CreateFromSmartEvent(IntPtr data, IntPtr obj, IntPtr info)
362         {
363             MultiButtonEntryItem item = ItemObject.GetItemByHandle(info) as MultiButtonEntryItem;
364             return new MultiButtonEntryItemEventArgs() { Item = item };
365         }
366
367         internal static MultiButtonEntryItemEventArgs CreateAndAddFromSmartEvent(IntPtr data, IntPtr obj, IntPtr info)
368         {
369             // Item can be added throught calling Append method and user input.
370             // And since "item.added" event will be called before xx_append() method returns,
371             // ItemObject does NOT have an item that contains handle matched to "info" at this time.
372             // So, item should be created and added internally here.
373             MultiButtonEntryItem item = new MultiButtonEntryItem(info);
374             return new MultiButtonEntryItemEventArgs() { Item = item };
375         }
376     }
377 }