/*
* Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the License);
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections.Generic;
namespace ElmSharp
{
///
/// It inherits .
/// The MultiButtonEntry is a widget letting an user enter text and each chunk of text managed as a set of buttons.
/// 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.
/// 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.
/// 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.
///
public class MultiButtonEntry : Layout
{
HashSet _children = new HashSet();
List> _filters = new List>();
Func _formatFunc = null;
Entry _entry = null;
Interop.Elementary.MultiButtonEntryItemFilterCallback _filterCallback;
Interop.Elementary.MultiButtonEntryFormatCallback _formatCallback;
SmartEvent _clicked;
SmartEvent _expanded;
SmartEvent _contracted;
SmartEvent _expandedStateChanged;
SmartEvent _itemSelected;
SmartEvent _itemClicked;
SmartEvent _itemLongPressed;
SmartEvent _itemAdded;
///
/// Creates and initializes a new instance of the MultiButtonEntry class.
///
/// The parent is a given container which will be attached by MultiButtonEntry as a child. It's type.
public MultiButtonEntry(EvasObject parent) : base(parent)
{
_clicked = new SmartEvent(this, "clicked");
_expanded = new SmartEvent(this, "expanded");
_contracted = new SmartEvent(this, "contracted");
_expandedStateChanged = new SmartEvent(this, "expand,state,changed");
_itemSelected = new SmartEvent(this, "item,selected", MultiButtonEntryItemEventArgs.CreateFromSmartEvent);
_itemClicked = new SmartEvent(this, "item,clicked", MultiButtonEntryItemEventArgs.CreateFromSmartEvent);
_itemLongPressed = new SmartEvent(this, "item,longpressed", MultiButtonEntryItemEventArgs.CreateFromSmartEvent);
_itemAdded = new SmartEvent(this, "item,added", MultiButtonEntryItemEventArgs.CreateAndAddFromSmartEvent);
_filterCallback = new Interop.Elementary.MultiButtonEntryItemFilterCallback(FilterCallbackHandler);
_formatCallback = new Interop.Elementary.MultiButtonEntryFormatCallback(FormatCallbackHandler);
_clicked.On += (sender, e) => Clicked?.Invoke(this, EventArgs.Empty);
_expanded.On += (sender, e) => Expanded?.Invoke(this, EventArgs.Empty);
_contracted.On += (sender, e) => Contracted?.Invoke(this, EventArgs.Empty);
_expandedStateChanged.On += (sender, e) => ExpandedStateChanged?.Invoke(this, EventArgs.Empty);
_itemSelected.On += (sender, e) => { ItemSelected?.Invoke(this, e); };
_itemClicked.On += (sender, e) => { ItemClicked?.Invoke(this, e); };
_itemLongPressed.On += (sender, e) => { ItemLongPressed?.Invoke(this, e); };
_itemAdded.On += OnItemAdded;
}
///
/// Clicked is raised when a MultiButtonEntry is clicked.
///
public event EventHandler Clicked;
///
/// Expanded is raised when a MultiButtonEntry is expanded.
///
public event EventHandler Expanded;
///
/// Contracted is raised when a MultiButtonEntry is contracted.
///
public event EventHandler Contracted;
///
/// ExpandedStateChanged is raised when shrink mode state of MultiButtonEntry is changed.
///
public event EventHandler ExpandedStateChanged;
///
/// ItemSelected is raised when an item is selected by api, user interaction, and etc.
/// This is also raised when a user press back space while cursor is on the first field of entry.
///
public event EventHandler ItemSelected;
///
/// ItemClicked is raised when an item is clicked by user interaction.
///
public event EventHandler ItemClicked;
///
/// ItemLongPressed is raised when MultiButtonEntry item is pressed for a long time.
///
public event EventHandler ItemLongPressed;
///
/// ItemAdded is raised when a new MultiButtonEntry item is added.
///
public event EventHandler ItemAdded;
///
/// ItemDeleted is raised when a MultiButtonEntry item is deleted.
///
public event EventHandler ItemDeleted;
///
/// Gets the selected item in the multibuttonentry.
///
public MultiButtonEntryItem SelectedItem
{
get
{
IntPtr handle = Interop.Elementary.elm_multibuttonentry_selected_item_get(RealHandle);
return ItemObject.GetItemByHandle(handle) as MultiButtonEntryItem;
}
}
///
/// Gets or sets whether the multibuttonentry is editable or not.
///
public bool IsEditable
{
get
{
return Interop.Elementary.elm_multibuttonentry_editable_get(RealHandle);
}
set
{
Interop.Elementary.elm_multibuttonentry_editable_set(RealHandle, value);
}
}
///
/// Gets or sets the multibuttonentry to expanded state.
/// If true, expanded state.
/// If false, single line state.
///
public bool IsExpanded
{
get
{
return Interop.Elementary.elm_multibuttonentry_expanded_get(RealHandle);
}
set
{
Interop.Elementary.elm_multibuttonentry_expanded_set(RealHandle, value);
}
}
///
/// Gets the first item in the multibuttonentry.
///
public MultiButtonEntryItem FirstItem
{
get
{
IntPtr handle = Interop.Elementary.elm_multibuttonentry_first_item_get(RealHandle);
return ItemObject.GetItemByHandle(handle) as MultiButtonEntryItem;
}
}
///
/// Gets the last item in the multibuttonentry.
///
public MultiButtonEntryItem LastItem
{
get
{
IntPtr handle = Interop.Elementary.elm_multibuttonentry_last_item_get(RealHandle);
return ItemObject.GetItemByHandle(handle) as MultiButtonEntryItem;
}
}
///
/// Gets the entry object int the multibuttonentry.
///
public Entry Entry
{
get
{
if (_entry == null)
{
_entry = new EntryInner(this);
}
return _entry;
}
}
protected override IntPtr CreateHandle(EvasObject parent)
{
return Interop.Elementary.elm_multibuttonentry_add(parent.Handle);
}
///
/// Append a new item to the multibuttonentry.
///
/// The label of new item.
/// A MultiButtonEntryItem to the item added.
public MultiButtonEntryItem Append(string label)
{
var handle = Interop.Elementary.elm_multibuttonentry_item_append(RealHandle, label, null, IntPtr.Zero);
MultiButtonEntryItem item = ItemObject.GetItemByHandle(handle) as MultiButtonEntryItem;
return item;
}
///
/// Prepend a new item to the multibuttonentry.
///
/// The label of new item.
/// A MultiButtonEntryItem to the item added.
public MultiButtonEntryItem Prepend(string label)
{
var handle = Interop.Elementary.elm_multibuttonentry_item_prepend(RealHandle, label, null, IntPtr.Zero);
MultiButtonEntryItem item = ItemObject.GetItemByHandle(handle) as MultiButtonEntryItem;
return item;
}
///
/// Add a new item to the multibuttonentry before the indicated object reference.
///
/// The item before which to add it.
/// The label of new item.
/// A MultiButtonEntryItem to the item added.
public MultiButtonEntryItem InsertBefore(MultiButtonEntryItem before, string label)
{
var handle = Interop.Elementary.elm_multibuttonentry_item_insert_before(RealHandle, before.Handle, label, null, IntPtr.Zero);
MultiButtonEntryItem item = ItemObject.GetItemByHandle(handle) as MultiButtonEntryItem;
return item;
}
///
/// Add a new item to the multibuttonentry after the indicated object.
///
/// The item after which to add it.
/// The label of new item.
/// A MultiButtonEntryItem to the item added.
public MultiButtonEntryItem InsertAfter(MultiButtonEntryItem after, string label)
{
var handle = Interop.Elementary.elm_multibuttonentry_item_insert_after(RealHandle, after.Handle, label, null, IntPtr.Zero);
MultiButtonEntryItem item = ItemObject.GetItemByHandle(handle) as MultiButtonEntryItem;
return item;
}
///
/// Remove all items in the multibuttonentry.
///
public void Clear()
{
Interop.Elementary.elm_multibuttonentry_clear(RealHandle);
foreach (var item in _children)
{
item.Deleted -= Item_Deleted;
}
_children.Clear();
}
///
/// Append an item filter function for text inserted in the Multibuttonentry.
///
/// The function to use as item filter.
public void AppendFilter(Func func)
{
_filters.Add(func);
if (_filters.Count == 1)
{
Interop.Elementary.elm_multibuttonentry_item_filter_append(RealHandle, _filterCallback, IntPtr.Zero);
}
}
///
/// Prepend a filter function for text inserted in the Multibuttonentry.
///
/// The function to use as text filter.
public void PrependFilter(Func func)
{
_filters.Insert(0, func);
if (_filters.Count == 1)
{
Interop.Elementary.elm_multibuttonentry_item_filter_prepend(RealHandle, _filterCallback, IntPtr.Zero);
}
}
///
/// Remove a filter from the list.
///
/// The filter function to remove.
public void RemoveFilter(Func func)
{
_filters.Remove(func);
if (_filters.Count == 0)
{
Interop.Elementary.elm_multibuttonentry_item_filter_remove(RealHandle, _filterCallback, IntPtr.Zero);
}
}
///
/// Set a function to format the string that will be used to display the hidden items counter.
/// If func is NULL, the default format will be used, which is "+ 'the hidden items counter'".
///
/// The function to return string to show
public void SetFormatCallback(Func func)
{
if (func == null)
{
Interop.Elementary.elm_multibuttonentry_format_function_set(RealHandle, null, IntPtr.Zero);
}
else
{
_formatFunc = func;
Interop.Elementary.elm_multibuttonentry_format_function_set(RealHandle, _formatCallback, IntPtr.Zero);
}
}
string FormatCallbackHandler(int count, IntPtr data)
{
return _formatFunc(count);
}
void Item_Deleted(object sender, EventArgs e)
{
var removed = sender as MultiButtonEntryItem;
_children.Remove(removed);
// "item,deleted" event will be called after removing the item from ItemObject has been done.
// ItemObject will no longer have the item instance that is deleted after this.
// So, ItemDelete event with the removed item should be triggered here.
ItemDeleted?.Invoke(this, new MultiButtonEntryItemEventArgs() { Item = removed });
}
void OnItemAdded(object sender, MultiButtonEntryItemEventArgs e)
{
_children.Add(e.Item);
e.Item.Deleted += Item_Deleted;
ItemAdded?.Invoke(this, e);
}
bool FilterCallbackHandler(IntPtr obj, string label, IntPtr itemData, IntPtr data)
{
foreach (var func in _filters)
{
if (!func(label))
return false;
}
return true;
}
internal class EntryInner : Entry
{
internal EntryInner(EvasObject parent) : base(parent)
{
}
protected override IntPtr CreateHandle(EvasObject parent)
{
return Interop.Elementary.elm_multibuttonentry_entry_get(parent.Handle);
}
}
}
///
/// It inherits System.EventArgs.
/// The MultiButtonEntryItemEventArgs is a argument for all events of MultiButtonEntry.
/// It contains Item which is type.
///
public class MultiButtonEntryItemEventArgs : EventArgs
{
///
/// Gets or sets MultiButtonEntryItem item. The return type is .
///
public MultiButtonEntryItem Item { get; set; }
internal static MultiButtonEntryItemEventArgs CreateFromSmartEvent(IntPtr data, IntPtr obj, IntPtr info)
{
MultiButtonEntryItem item = ItemObject.GetItemByHandle(info) as MultiButtonEntryItem;
return new MultiButtonEntryItemEventArgs() { Item = item };
}
internal static MultiButtonEntryItemEventArgs CreateAndAddFromSmartEvent(IntPtr data, IntPtr obj, IntPtr info)
{
// Item can be added throught calling Append method and user input.
// And since "item.added" event will be called before xx_append() method returns,
// ItemObject does NOT have an item that contains handle matched to "info" at this time.
// So, item should be created and added internally here.
MultiButtonEntryItem item = new MultiButtonEntryItem(info);
return new MultiButtonEntryItemEventArgs() { Item = item };
}
}
}