/* Copyright (c) Citrix Systems Inc. * All rights reserved. * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided * that the following conditions are met: * * * Redistributions of source code must retain the above * copyright notice, this list of conditions and the * following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other * materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Text; using System.Windows.Forms; using System.Windows.Forms.VisualStyles; using XenAdmin.Core; using XenAdmin.Properties; namespace XenAdmin.Controls { public partial class SearchTextBox : UserControl { /// /// If true the TextChanged event should not be fired. This is the case when the text /// changes from Messages.SEARCH_TEXT_BOX_INITIAL_TEXT to string.Empty and vice-versa. /// private bool m_isTextChangeSilent; public SearchTextBox() { SetStyle(ControlStyles.AllPaintingInWmPaint, true); SetStyle(ControlStyles.ResizeRedraw, true); SetStyle(ControlStyles.UserPaint, true); InitializeComponent(); textBox1.Text = Messages.SEARCH_TEXT_BOX_INITIAL_TEXT; textBox1.LostFocus += textBox1_LostFocus; textBox1.GotFocus += textBox1_GotFocus; SetTextGrey(true); } public void Reset() { textBox1_LostFocus(this, EventArgs.Empty); } private void SetTextGrey(bool grey) { if (grey) { textBox1.ForeColor = Color.Gray; textBox1.Font = new Font(textBox1.Font, FontStyle.Italic); } else { textBox1.ForeColor = SystemColors.WindowText; textBox1.Font = new Font(textBox1.Font, FontStyle.Regular); } } protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); Graphics g = e.Graphics; var borderRect = new Rectangle(0, 0, Width, Height); if (Application.RenderWithVisualStyles) { TextBoxRenderer.DrawTextBox(g, borderRect, TextBoxState.Selected); } else { ControlPaint.DrawBorder3D(g, borderRect); g.FillRectangle(Brushes.White, new Rectangle(2, 2, Width - 4, Height - 4)); } g.TextRenderingHint = Drawing.TextRenderingHint; // Draw magnifying glass or cross icon Image image = textBox1.Text.Length > 0 && textBox1.Text != Messages.SEARCH_TEXT_BOX_INITIAL_TEXT ? Resources.cross : Resources._000_Search_h32bit_16; g.DrawImage(image, new Rectangle(textBox1.Width + textBox1.Left, Height / 2 - image.Height / 2, image.Width, image.Height)); } protected override void OnSizeChanged(EventArgs e) { base.OnSizeChanged(e); const int leftMargin = 4; const int iconWidth = 20; textBox1.Location = new Point(leftMargin, Height / 2 - textBox1.Height / 2); textBox1.Size = new Size(Width - leftMargin - iconWidth, textBox1.Height); } private void textBox1_TextChanged(object sender, EventArgs e) { Invalidate(); if (!m_isTextChangeSilent) OnTextChanged(EventArgs.Empty); } protected override void OnMouseLeave(EventArgs e) { base.OnMouseLeave(e); Refresh(); } private void textBox1_LostFocus(object sender, EventArgs e) { if (textBox1.Text.Length == 0) { m_isTextChangeSilent = true; textBox1.Text = Messages.SEARCH_TEXT_BOX_INITIAL_TEXT; m_isTextChangeSilent = false; SetTextGrey(true); } Refresh(); } private void textBox1_GotFocus(object sender, EventArgs e) { if (textBox1.Text == Messages.SEARCH_TEXT_BOX_INITIAL_TEXT) { m_isTextChangeSilent = true; textBox1.Text = string.Empty; m_isTextChangeSilent = false; SetTextGrey(false); } Refresh(); } [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] [Browsable(false)] public override string Text { get { return textBox1.Text != Messages.SEARCH_TEXT_BOX_INITIAL_TEXT ? textBox1.Text : string.Empty; } set { if (value == "" && !this.Focused) { textBox1.Text = Messages.SEARCH_TEXT_BOX_INITIAL_TEXT; SetTextGrey(true); } else { textBox1.Text = value; SetTextGrey(false); } } } [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] [Browsable(false)] public bool Matches(string name) { return name.IndexOf(this.Text, StringComparison.CurrentCultureIgnoreCase) >= 0; } protected override void OnTextChanged(EventArgs e) { base.OnTextChanged(e); var handler = this.TextChanged; if (handler != null) { handler(this, e); } } protected override void OnMouseClick(MouseEventArgs e) { base.OnMouseClick(e); if (e.X > textBox1.Left + textBox1.Width) { if (textBox1.Text.Length > 0) { textBox1.Text = string.Empty; } else { textBox1.Focus(); } Refresh(); } } protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); Cursor = e.X > textBox1.Left + textBox1.Width ? Cursors.Hand : Cursors.IBeam; } [Browsable(true)] public new event EventHandler TextChanged; private bool wasFocused; private int cursorLoc; public void SaveState() { wasFocused = textBox1.ContainsFocus; cursorLoc = textBox1.SelectionStart; } public void RestoreState() { if (!wasFocused || ContainsFocus) return; textBox1.Select(); textBox1.Select(cursorLoc, 0); } } }