using System; using ElmSharp; using EColor = ElmSharp.Color; using ESize = ElmSharp.Size; using ERect = ElmSharp.Rect; using ERectangle = ElmSharp.Rectangle; namespace Xamarin.Forms.Platform.Tizen.Native { /// /// Provides implementation of the search bar widget. /// public class SearchBar : Canvas, IMeasurable { /// /// The height of the background of the search bar. /// const int BackgroundHeight = 120; /// /// The style of the cancel button. /// const string CancelButtonLayoutStyle = "editfield_clear"; /// /// The horizontal padding of the cancel button. /// const int CancelButtonPaddingHorizontal = 17; /// /// The size of the cancel button. /// const int CancelButtonSize = 80; /// /// The height of the entry. /// const int EntryHeight = 54; /// /// The horizontal padding of the entry. /// const int EntryPaddingHorizontal = 42; /// /// The vertical padding of the entry. /// const int EntryPaddingVertical = 33; /// /// The height of the rectangle used to draw underline effect. /// const int RectangleHeight = 2; /// /// The bottom padding of the rectangle used to draw underline effect. /// const int RectanglePaddingBottom = 20; /// /// The horizontal padding of the rectangle used to draw underline effect. /// const int RectanglePaddingHorizontal = 32; /// /// The top padding of the rectangle used to draw underline effect. /// const int RectanglePaddingTop = 11; //TODO: read default platform color /// /// The color of the underline rectangle. /// static readonly EColor s_underlineColor = EColor.Aqua; /// /// The dimmed color of the underline rectangle. /// static readonly EColor s_underlineDimColor = EColor.Gray; /// /// The cancel button. /// Button _cancelButton; /// /// The text entry. /// Entry _entry; /// /// The underline rectangle. /// ERectangle _underlineRectangle; /// /// Initializes a new instance of the class. /// /// Parent evas object. public SearchBar(EvasObject parent) : base(parent) { _entry = new Entry(parent) { IsSingleLine = true, }; _entry.SetInputPanelReturnKeyType(InputPanelReturnKeyType.Search); _entry.TextChanged += EntryTextChanged; _entry.Activated += EntryActivated; _entry.Focused += EntryFocused; _entry.Unfocused += EntryUnfocused; _entry.Show(); _cancelButton = new Button(parent); _cancelButton.Style = CancelButtonLayoutStyle; _cancelButton.Clicked += CancelButtonClicked; _underlineRectangle = new ERectangle(parent) { Color = IsEnabled ? s_underlineColor : s_underlineDimColor, }; _underlineRectangle.Show(); Children.Add(_entry); Children.Add(_cancelButton); Children.Add(_underlineRectangle); Show(); this.LayoutUpdated += SearchBarLayoutUpdated; } /// /// Occurs when the search button on the keyboard is pressed. /// public event EventHandler SearchButtonPressed; /// /// Occurs when the entry's text has changed. /// public event EventHandler TextChanged; /// /// Gets or sets the color of the cancel button. /// /// Color of the cancel button. public EColor CancelButtonColor { get { return _cancelButton.Color; } set { if (!_cancelButton.Color.Equals(value)) { _cancelButton.Color = value; } } } /// /// Gets or sets the font attributes of the search bar's entry. /// /// The font attributes. public FontAttributes FontAttributes { get { return _entry.FontAttributes; } set { if (value != _entry.FontAttributes) { _entry.FontAttributes = value; } } } /// /// Gets or sets the font family of the search bar's entry. /// /// The font family. public string FontFamily { get { return _entry.FontFamily; } set { if (value != _entry.FontFamily) { _entry.FontFamily = value; } } } /// /// Gets or sets the size of the font of the search bar's entry. /// /// The size of the font. public double FontSize { get { return _entry.FontSize; } set { if (value != _entry.FontSize) { _entry.FontSize = value; } } } /// /// Gets or sets the horizontal text alignment of the search bar's entry. /// /// The horizontal text alignment. public TextAlignment HorizontalTextAlignment { get { return _entry.HorizontalTextAlignment; } set { if (value != _entry.HorizontalTextAlignment) { _entry.HorizontalTextAlignment = value; } } } /// /// Gets or sets the placeholder of the search bar's entry. /// /// The placeholder. public string Placeholder { get { return _entry.Placeholder; } set { if (value != _entry.Placeholder) { _entry.Placeholder = value; } } } /// /// Gets or sets the color of the placeholder. /// /// The color of the placeholder. public EColor PlaceholderColor { get { return _entry.PlaceholderColor; } set { if (!_entry.PlaceholderColor.Equals(value)) { _entry.PlaceholderColor = value; } } } /// /// Gets or sets the text of the search bar's entry. /// /// The text. public override string Text { get { return _entry.Text; } set { if (value != _entry.Text) { _entry.Text = value; } } } /// /// Gets or sets the color of the text. /// /// The color of the text. public EColor TextColor { get { return _entry.TextColor; } set { if (!_entry.TextColor.Equals(value)) { _entry.TextColor = value; } } } /// /// Implementation of the IMeasurable.Measure() method. /// public ESize Measure(int availableWidth, int availableHeight) { ESize entrySize = _entry.Measure(availableWidth, availableHeight); int width = entrySize.Width + (CancelButtonPaddingHorizontal * 2) + CancelButtonSize; return new ESize(width, BackgroundHeight); } internal void BatchBegin() { _entry.BatchBegin(); } internal void BatchCommit() { _entry.BatchCommit(); } /// /// Handles the event triggered by the cancel button being clicked. /// /// Sender of the event. /// Event arguments, ignored. void CancelButtonClicked(object sender, EventArgs e) { _entry.Text = string.Empty; _cancelButton.Hide(); } /// /// Handles the event triggered by clicking the search button on the keyboard. /// /// Sender of the event. /// Event arguments, ignored. void EntryActivated(object sender, EventArgs e) { SearchButtonPressed?.Invoke(this, EventArgs.Empty); } /// /// Handles the event triggered by entry gaining the focus. /// /// Sender of the event. /// Event arguments, ignored. void EntryFocused(object sender, EventArgs e) { _underlineRectangle.Color = s_underlineColor; } /// /// Handles the event triggered by entry's text being changed. /// /// Sender of the event. /// Event arguments. void EntryTextChanged(object sender, TextChangedEventArgs e) { if (string.IsNullOrEmpty(e.NewTextValue)) { _cancelButton.Hide(); } else if (!_cancelButton.IsVisible) { _cancelButton.Show(); } TextChanged?.Invoke(this, e); } /// /// Handles the event triggered by entry losing the focus. /// /// Sender of the event. /// Event arguments, ignored. void EntryUnfocused(object sender, EventArgs e) { _underlineRectangle.Color = s_underlineDimColor; } /// /// Handles the event triggered by search bar's layout being changed. /// /// /// Updates the geometry of the widgets comprising the search bar. /// /// Sender of the event. /// Event arguments. void SearchBarLayoutUpdated(object sender, LayoutEventArgs e) { _underlineRectangle.Geometry = new ERect(e.Geometry.Left + RectanglePaddingHorizontal, e.Geometry.Top + EntryPaddingVertical + EntryHeight + RectanglePaddingTop, e.Geometry.Width - (RectanglePaddingHorizontal * 2), RectangleHeight); _entry.Geometry = new ERect(e.Geometry.Left + EntryPaddingHorizontal, e.Geometry.Top + EntryPaddingVertical, e.Geometry.Width - (EntryPaddingHorizontal + (CancelButtonPaddingHorizontal * 2) + CancelButtonSize), EntryHeight); _cancelButton.Geometry = new ERect(e.Geometry.Right - CancelButtonSize - CancelButtonPaddingHorizontal, e.Geometry.Top + RectanglePaddingBottom, CancelButtonSize, CancelButtonSize); } } }