2383 lines
		
	
	
		
			93 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			2383 lines
		
	
	
		
			93 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using DevComponents.DotNetBar.Primitives;
 | |
| using DevComponents.DotNetBar.Rendering;
 | |
| using DevComponents.DotNetBar.TextMarkup;
 | |
| using DevComponents.Editors;
 | |
| using System;
 | |
| using System.Collections.Generic;
 | |
| using System.ComponentModel;
 | |
| using System.Drawing;
 | |
| using System.Drawing.Design;
 | |
| using System.Drawing.Drawing2D;
 | |
| using System.Text;
 | |
| using System.Windows.Forms;
 | |
| 
 | |
| namespace DevComponents.DotNetBar.Controls
 | |
| {
 | |
|     [ToolboxItem(true), ToolboxBitmap(typeof(TokenEditor), "Controls.TokenEditor.ico")]
 | |
|     [Designer("DevComponents.DotNetBar.Design.TokenEditorDesigner, DevComponents.DotNetBar.Design, Version=14.1.0.37, Culture=neutral,  PublicKeyToken=90f470f34c89ccaf")]
 | |
|     [DefaultEvent("SelectedTokensChanged")]
 | |
|     public class TokenEditor : Control, IMessageHandlerClient
 | |
|     {
 | |
|         #region Constructor
 | |
|         private TextBoxX _EditBox;
 | |
|         private VScrollBarAdv _VScrollBar = null;
 | |
|         /// <summary>
 | |
|         /// Initializes a new instance of the TokenEditor class.
 | |
|         /// </summary>
 | |
|         public TokenEditor()
 | |
|         {
 | |
|             _SelectedTokens = new CustomCollection<EditToken>();
 | |
|             _SelectedTokens.CollectionChanged += SelectedTokensCollectionChanged;
 | |
|             _Tokens = new CustomCollection<EditToken>();
 | |
|             _Tokens.CollectionChanged += TokensCollectionChanged;
 | |
|             this.SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint |
 | |
|             ControlStyles.Opaque | ControlStyles.ResizeRedraw | ControlStyles.Selectable |
 | |
|             ControlStyles.StandardDoubleClick | DisplayHelp.DoubleBufferFlag, true);
 | |
|             _BackgroundStyle = new ElementStyle();
 | |
|             _BackgroundStyle.Class = ElementStyleClassKeys.DateTimeInputBackgroundKey;
 | |
|             _BackgroundStyle.StyleChanged += new EventHandler(this.VisualPropertyChanged);
 | |
| 
 | |
|             _EditBox = new TextBoxX();
 | |
|             _EditBox.BorderStyle = BorderStyle.None;
 | |
|             _EditBox.Visible = false;
 | |
|             _EditBox.TextChanged += EditBoxTextChanged;
 | |
|             _EditBox.KeyDown += EditBoxKeyDown;
 | |
|             _EditBox.GotFocus += EditBoxGotFocus;
 | |
|             this.Controls.Add(_EditBox);
 | |
|             _EditBox.SetAutoHeight();
 | |
| 
 | |
|             _VScrollBar = new VScrollBarAdv();
 | |
|             _VScrollBar.Visible = false;
 | |
|             _VScrollBar.Scroll += VScrollBarScroll;
 | |
|             this.Controls.Add(_VScrollBar);
 | |
| 
 | |
|             VisualGroup group = new VisualGroup();
 | |
|             group.HorizontalItemSpacing = 0;
 | |
|             group.ArrangeInvalid += ButtonGroupArrangeInvalid;
 | |
|             group.RenderInvalid += ButtonGroupRenderInvalid;
 | |
|             group.ResetMouseHover += ButtonGroupResetMouseHover;
 | |
|             _ButtonGroup = group;
 | |
|             CreateButtons();
 | |
|         }
 | |
| 
 | |
|         protected override void Dispose(bool disposing)
 | |
|         {
 | |
|             if (_MessageHandlerInstalled)
 | |
|             {
 | |
|                 MessageHandler.UnregisterMessageClient(this);
 | |
|                 _MessageHandlerInstalled = false;
 | |
|             }
 | |
|             base.Dispose(disposing);
 | |
|         }
 | |
|         #endregion
 | |
| 
 | |
|         #region Implementation
 | |
| 
 | |
|         protected override void ScaleControl(SizeF factor, BoundsSpecified specified)
 | |
|         {
 | |
|             if (Dpi.RecordScalePerControl)
 | |
|                 Dpi.SetScaling(factor);
 | |
|             base.ScaleControl(factor, specified);
 | |
|             _EditBox.SetAutoHeight();
 | |
|             LayoutTokens();
 | |
|         }
 | |
| 
 | |
|         private void EditBoxGotFocus(object sender, EventArgs e)
 | |
|         {
 | |
|             FocusToken = null;
 | |
|         }
 | |
|         private TokenEditorColorTable GetTokenColorTable()
 | |
|         {
 | |
|             return ((Office2007Renderer)GlobalManager.Renderer).ColorTable.TokenEditor;
 | |
|         }
 | |
|         protected override void OnPaint(PaintEventArgs e)
 | |
|         {
 | |
|             if ((this.BackColor.IsEmpty || this.BackColor == Color.Transparent))
 | |
|             {
 | |
|                 base.OnPaintBackground(e);
 | |
|             }
 | |
| 
 | |
|             if (_BackgroundStyle != null)
 | |
|                 _BackgroundStyle.SetColorScheme(this.GetColorScheme());
 | |
|             TokenEditorColorTable colorTable = GetTokenColorTable();
 | |
|             PaintBackground(e);
 | |
|             Rectangle clientBounds = GetClientBounds();
 | |
|             e.Graphics.SetClip(clientBounds);
 | |
| 
 | |
|             if (this.WatermarkEnabled && this.WatermarkText.Length > 0 && this.IsWatermarkRendered)
 | |
|             {
 | |
|                 DrawWatermark(e.Graphics);
 | |
|             }
 | |
| 
 | |
|             foreach (EditToken token in _SelectedTokens)
 | |
|             {
 | |
|                 PaintToken(token, e, colorTable);
 | |
|             }
 | |
| 
 | |
|             PaintButtons(e.Graphics);
 | |
| 
 | |
|             e.Graphics.ResetClip();
 | |
|             base.OnPaint(e);
 | |
|         }
 | |
| 
 | |
|         private void PaintToken(EditToken token, PaintEventArgs e, TokenEditorColorTable colorTable)
 | |
|         {
 | |
|             Graphics g = e.Graphics;
 | |
|             Rectangle r = token.Bounds;
 | |
|             r.Offset(_AutoScrollPosition);
 | |
| 
 | |
|             SmoothingMode sm = g.SmoothingMode;
 | |
|             g.SmoothingMode = SmoothingMode.HighQuality;
 | |
| 
 | |
|             Color textColor = colorTable.Normal.TextColor;
 | |
|             LinearGradientColorTable background = colorTable.Normal.Background;
 | |
| 
 | |
|             if (token.IsFocused)
 | |
|             {
 | |
|                 textColor = colorTable.Focused.TextColor;
 | |
|                 background = colorTable.Focused.Background;
 | |
|             }
 | |
|             else if (token.MouseOverPart == eTokenPart.Token || token.MouseOverPart == eTokenPart.Image)
 | |
|                 background = colorTable.MouseOver.Background;
 | |
| 
 | |
|             DisplayHelp.FillRoundedRectangle(g, r, 2, background.Start, background.End, background.GradientAngle);
 | |
| 
 | |
|             g.SmoothingMode = sm;
 | |
|             string text = GetTokenText(token);
 | |
|             Rectangle rText = r;
 | |
| 
 | |
|             if (EffectiveRemoveTokenButtonVisible)
 | |
|             {
 | |
|                 Rectangle removeBounds = new Rectangle(r.X, r.Y + (r.Height - _RemoveTokenButtonSize.Height) / 2,
 | |
|                     _RemoveTokenButtonSize.Width, _RemoveTokenButtonSize.Height);
 | |
|                 Color closeTextColor = textColor;
 | |
|                 if (token.MouseOverPart == eTokenPart.RemoveButton)
 | |
|                 {
 | |
|                     Office2007ColorTable ct = ((Office2007Renderer)GlobalManager.Renderer).ColorTable;
 | |
|                     Office2007ButtonItemColorTable buttonColorTable = ct.ButtonItemColors[Enum.GetName(typeof(eButtonColor), eButtonColor.OrangeWithBackground)];
 | |
|                     Office2007ButtonItemPainter.PaintBackground(g, buttonColorTable.MouseOver, removeBounds, RoundRectangleShapeDescriptor.RectangleShape);
 | |
|                     closeTextColor = buttonColorTable.MouseOver.Text;
 | |
|                     //g.FillRectangle(Brushes.Red, removeBounds);
 | |
|                 }
 | |
| 
 | |
|                 float symbolSize = Math.Max(1, Math.Min(removeBounds.Width, removeBounds.Height) * 72 / g.DpiX - 1.5f);
 | |
|                 TextDrawing.DrawStringLegacy(g, "\uf00d", Symbols.GetFont(symbolSize, eSymbolSet.Awesome),
 | |
|                     closeTextColor, removeBounds, eTextFormat.HorizontalCenter | eTextFormat.VerticalCenter);
 | |
| 
 | |
|                 token.RemoveButtonBounds = removeBounds;
 | |
|                 rText.X = removeBounds.Right + _TokenPartSpacing;
 | |
|                 rText.Width -= rText.Right - r.Right;
 | |
|             }
 | |
| 
 | |
|             if (!string.IsNullOrEmpty(token.SymbolRealized))
 | |
|             {
 | |
|                 Rectangle imageBounds = new Rectangle(rText.X, r.Y, r.Height, r.Height);
 | |
|                 float symbolSize = Math.Max(1, Math.Min(imageBounds.Width, imageBounds.Height) * 72 / g.DpiX - 1.5f);
 | |
|                 TextDrawing.DrawStringLegacy(g, token.SymbolRealized, Symbols.GetFont(symbolSize, token.SymbolSet),
 | |
|                     (token.SymbolColor.IsEmpty ? textColor : token.SymbolColor),
 | |
|                     imageBounds, eTextFormat.HorizontalCenter | eTextFormat.VerticalCenter);
 | |
|                 token.ImageBounds = imageBounds;
 | |
|                 rText.X = imageBounds.Right + _TokenPartSpacing;
 | |
|                 rText.Width -= rText.Right - r.Right;
 | |
|             }
 | |
|             else if (token.Image != null)
 | |
|             {
 | |
|                 Rectangle imageBounds = new Rectangle(rText.X, r.Y, token.ImageBounds.Width, token.Image.Height);
 | |
|                 g.DrawImage(token.Image, imageBounds);
 | |
|                 token.ImageBounds = imageBounds;
 | |
|                 rText.X = imageBounds.Right + _TokenPartSpacing;
 | |
|                 rText.Width -= rText.Right - r.Right;
 | |
|             }
 | |
|             TextDrawing.DrawString(g, text, this.Font, textColor, rText, eTextFormat.Default | eTextFormat.VerticalCenter);
 | |
|         }
 | |
| 
 | |
|         protected virtual void PaintBackground(PaintEventArgs e)
 | |
|         {
 | |
|             Graphics g = e.Graphics;
 | |
|             Rectangle r = this.ClientRectangle;
 | |
|             ElementStyle style = _BackgroundStyle;
 | |
| 
 | |
|             if (!this.BackColor.IsEmpty && this.BackColor != Color.Transparent)
 | |
|             {
 | |
|                 DisplayHelp.FillRectangle(g, r, this.BackColor);
 | |
|             }
 | |
| 
 | |
|             if (this.BackgroundImage != null)
 | |
|                 base.OnPaintBackground(e);
 | |
| 
 | |
|             if (style.Custom)
 | |
|             {
 | |
|                 SmoothingMode sm = g.SmoothingMode;
 | |
|                 //if (m_AntiAlias)
 | |
|                 //    g.SmoothingMode = SmoothingMode.HighQuality;
 | |
|                 ElementStyleDisplayInfo displayInfo = new ElementStyleDisplayInfo(style, e.Graphics, r);
 | |
|                 ElementStyleDisplay.Paint(displayInfo);
 | |
|                 //if (m_AntiAlias)
 | |
|                 //    g.SmoothingMode = sm;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         protected override void OnResize(EventArgs e)
 | |
|         {
 | |
|             LayoutTokens();
 | |
|             base.OnResize(e);
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets or sets the location of the auto-scroll position.
 | |
|         /// </summary>
 | |
|         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Browsable(false), Description("Indicates location of the auto-scroll position.")]
 | |
|         public Point AutoScrollPosition
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return _AutoScrollPosition;
 | |
|             }
 | |
|             set
 | |
|             {
 | |
|                 if (_AutoScrollPosition == value) return;
 | |
|                 _AutoScrollPosition = value;
 | |
|                 if (_VScrollBar != null && _VScrollBar.Value != -_AutoScrollPosition.Y)
 | |
|                     _VScrollBar.Value = Math.Min(_VScrollBar.Maximum, Math.Max(_VScrollBar.Minimum, -_AutoScrollPosition.Y));
 | |
|                 RepositionEditTextBox();
 | |
|                 Invalidate();
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private Rectangle GetClientBounds()
 | |
|         {
 | |
|             bool disposeStyle = false;
 | |
|             ElementStyle style = ElementStyleDisplay.GetElementStyle(_BackgroundStyle, out disposeStyle);
 | |
|             Rectangle clientRect = this.ClientRectangle;
 | |
|             clientRect.X += style.PaddingLeft;
 | |
|             clientRect.Width -= style.PaddingHorizontal;
 | |
|             clientRect.Y += style.PaddingTop;
 | |
|             clientRect.Height -= style.PaddingVertical;
 | |
|             if (disposeStyle)
 | |
|                 style.Dispose();
 | |
|             style = null;
 | |
| 
 | |
|             return clientRect;
 | |
|         }
 | |
| 
 | |
|         private Point _AutoScrollPosition = Point.Empty;
 | |
|         private int _TokenSpacing = 2;
 | |
|         private int _TokenPartSpacing = 2; // Spacing between different parts of the token, like between image and text and image and close button etc. Its spacing between each part.
 | |
|         private readonly Size _TokenPadding = new Size(2, 2);
 | |
|         private void LayoutTokens()
 | |
|         {
 | |
|             if (!this.IsHandleCreated || this.IsDisposed || this.Width == 0 || this.Height == 0) return;
 | |
| 
 | |
|             int lineCount = 0;
 | |
|             Rectangle clientRect = GetClientBounds();
 | |
|             Graphics g = this.CreateGraphics();
 | |
|             Size totalSize = LayoutTokens(g, clientRect, out lineCount);
 | |
| 
 | |
|             if (_AutoSizeHeight)
 | |
|             {
 | |
|                 int heightLines = Math.Min(_MaxHeightLines, lineCount);
 | |
|                 int newHeight = (int)(Math.Ceiling((double)totalSize.Height / lineCount) * heightLines) + (this.Height - clientRect.Height);
 | |
|                 if (_MaxHeightLines == 1)
 | |
|                     newHeight = GetSingleLineTextBoxHeight();
 | |
|                 if (newHeight != this.Height)
 | |
|                 {
 | |
|                     g.Dispose();
 | |
|                     this.Height = newHeight;
 | |
|                     return;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             if (totalSize.Height > clientRect.Height)
 | |
|             {
 | |
|                 Rectangle reducedBounds = clientRect;
 | |
| 
 | |
|                 int visibleLines = (int)(clientRect.Height / (Math.Ceiling((double)totalSize.Height / lineCount)));
 | |
|                 if (_DropDownButtonVisible && visibleLines <= 2 || visibleLines == 1)
 | |
|                 {
 | |
|                     // Using scroll button due to space limitation
 | |
|                     _VScrollBar.Visible = false;
 | |
|                     _ScrollButton.Visible = true;
 | |
|                     reducedBounds.Width -= SystemInformation.VerticalScrollBarWidth * (_DropDownButtonVisible ? 2 : 1);
 | |
|                     if (visibleLines > 1)
 | |
|                         _ButtonGroup.Orientation = eOrientation.Vertical;
 | |
|                     else
 | |
|                         _ButtonGroup.Orientation = eOrientation.Horizontal;
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     int buttonOffset = (_DropDownButtonVisible ? GetButtonHeight() + 1 : 0);
 | |
|                     // Activate Scroll-bar
 | |
|                     _VScrollBar.Bounds = new Rectangle(clientRect.Right - SystemInformation.VerticalScrollBarWidth,
 | |
|                         clientRect.Y + buttonOffset,
 | |
|                         SystemInformation.VerticalScrollBarWidth,
 | |
|                         clientRect.Height - buttonOffset);
 | |
|                     _VScrollBar.Visible = true;
 | |
|                     _ScrollButton.Visible = false;
 | |
|                     reducedBounds.Width -= _VScrollBar.Width;
 | |
|                 }
 | |
| 
 | |
|                 totalSize = LayoutTokens(g, reducedBounds, out lineCount);
 | |
| 
 | |
|                 _VScrollBar.Maximum = totalSize.Height;
 | |
|                 _VScrollBar.LargeChange = clientRect.Height;
 | |
|                 if (this.SelectedTokens.Count > 0)
 | |
|                     _VScrollBar.SmallChange = this.SelectedTokens[0].Bounds.Height;
 | |
|                 else
 | |
|                     _VScrollBar.SmallChange = 17;
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 _VScrollBar.Visible = false;
 | |
|                 _AutoScrollPosition = Point.Empty;
 | |
|                 _ScrollButton.Visible = false;
 | |
|             }
 | |
| 
 | |
|             g.Dispose();
 | |
| 
 | |
|             RepositionEditTextBox();
 | |
|             EnsureTextBoxScrollPosition();
 | |
|             UpdateButtons();
 | |
| 
 | |
|             this.Invalidate();
 | |
|         }
 | |
| 
 | |
|         private int GetSingleLineTextBoxHeight()
 | |
|         {
 | |
|             Font font = this.Font;
 | |
|             return font.Height + ((SystemInformation.BorderSize.Height * 4) + 4);
 | |
|         }
 | |
|         private Size LayoutTokens(Graphics g, Rectangle clientRect, out int lineCount)
 | |
|         {
 | |
|             lineCount = 0;
 | |
|             if (!this.IsHandleCreated || this.IsDisposed) return Size.Empty;
 | |
| 
 | |
|             clientRect.Inflate(-1, -1);
 | |
|             Font font = this.Font;
 | |
|             Size totalSize = Size.Empty;
 | |
|             int singleLineTextBoxHeight = GetSingleLineTextBoxHeight() - 2; // 2 is for top and bottom border
 | |
| 
 | |
|             if (_SelectedTokens.Count == 0)
 | |
|             {
 | |
|                 lineCount = 1;
 | |
|                 totalSize = new Size(clientRect.Width, singleLineTextBoxHeight);
 | |
|                 _EditBoxLocation = new Point(clientRect.X, clientRect.Y + (totalSize.Height - _EditBox.Height) / 2);
 | |
|                 _EditBox.Width = clientRect.Width - (_DropDownButtonVisible ? SystemInformation.VerticalScrollBarWidth : 0);
 | |
| 
 | |
|                 return totalSize;
 | |
|             }
 | |
| 
 | |
|             int largestTokenHeight = 0;
 | |
|             foreach (EditToken token in _SelectedTokens)
 | |
|             {
 | |
|                 token.RemoveButtonBounds = Rectangle.Empty;
 | |
|                 token.ImageBounds = Rectangle.Empty;
 | |
|                 string text = GetTokenText(token);
 | |
|                 Size size = TextDrawing.MeasureString(g, (string.IsNullOrEmpty(text) ? "A" : text), font);
 | |
|                 size.Width += _TokenPadding.Width * 2;
 | |
|                 size.Height += _TokenPadding.Height * 2;
 | |
|                 if (EffectiveRemoveTokenButtonVisible)
 | |
|                 {
 | |
|                     size.Width += _RemoveTokenButtonSize.Width + _TokenPartSpacing;
 | |
|                     if (_RemoveTokenButtonSize.Height > size.Height)
 | |
|                         size.Height = _RemoveTokenButtonSize.Height;
 | |
|                 }
 | |
| 
 | |
|                 if (!string.IsNullOrEmpty(token.SymbolRealized))
 | |
|                 {
 | |
|                     size.Width += size.Height + _TokenPartSpacing;
 | |
|                 }
 | |
|                 else if (token.Image != null)
 | |
|                 {
 | |
|                     size.Width += token.Image.Width + _TokenPartSpacing;
 | |
|                     if (token.Image.Height > size.Height)
 | |
|                         size.Height = token.Image.Height;
 | |
|                 }
 | |
|                 largestTokenHeight = Math.Max(largestTokenHeight, size.Height);
 | |
|                 token.Bounds = new Rectangle(Point.Empty, size);
 | |
|             }
 | |
| 
 | |
|             lineCount = 1;
 | |
|             totalSize.Height = largestTokenHeight;
 | |
|             Point currentPos = clientRect.Location;
 | |
| 
 | |
|             foreach (EditToken token in _SelectedTokens)
 | |
|             {
 | |
|                 Rectangle tokenBounds = new Rectangle(currentPos.X, currentPos.Y, token.Bounds.Width, largestTokenHeight);
 | |
|                 if (tokenBounds.Right > clientRect.Right && currentPos.X > clientRect.X)
 | |
|                 {
 | |
|                     currentPos.Y += largestTokenHeight + _TokenSpacing;
 | |
|                     currentPos.X = clientRect.X;
 | |
|                     tokenBounds.Y = currentPos.Y;
 | |
|                     tokenBounds.X = currentPos.X;
 | |
|                     totalSize.Height += largestTokenHeight + _TokenSpacing;
 | |
|                     lineCount++;
 | |
|                 }
 | |
|                 currentPos.X += tokenBounds.Width + _TokenSpacing;
 | |
|                 token.Bounds = tokenBounds;
 | |
| 
 | |
|                 if (tokenBounds.Right - clientRect.X > totalSize.Width)
 | |
|                     totalSize.Width = tokenBounds.Right - clientRect.X;
 | |
|             }
 | |
| 
 | |
|             if (clientRect.Right - currentPos.X < _TextBoxMinWidth)
 | |
|             {
 | |
|                 currentPos.Y += largestTokenHeight + _TokenSpacing;
 | |
|                 currentPos.X = clientRect.X;
 | |
|                 lineCount++;
 | |
|                 totalSize.Height += largestTokenHeight + _TokenSpacing;
 | |
|             }
 | |
| 
 | |
|             if (lineCount == 1)
 | |
|                 totalSize.Height = Math.Max(totalSize.Height, singleLineTextBoxHeight);
 | |
| 
 | |
|             _EditBoxLocation = new Point(currentPos.X, currentPos.Y + (largestTokenHeight - _EditBox.Height) / 2);
 | |
|             _EditBox.Width = clientRect.Right - currentPos.X - (lineCount == 1 && _DropDownButtonVisible ? SystemInformation.VerticalScrollBarWidth : 0);
 | |
| 
 | |
|             return totalSize;
 | |
|         }
 | |
| 
 | |
|         private Point _EditBoxLocation = Point.Empty;
 | |
|         private void RepositionEditTextBox()
 | |
|         {
 | |
|             Point loc = _EditBoxLocation;
 | |
|             loc.Offset(_AutoScrollPosition);
 | |
|             _EditBox.Location = loc;
 | |
|         }
 | |
| 
 | |
|         private void VScrollBarScroll(object sender, ScrollEventArgs e)
 | |
|         {
 | |
|             if (e.NewValue != e.OldValue)
 | |
|             {
 | |
|                 _AutoScrollPosition.Y = -e.NewValue;
 | |
|                 RepositionEditTextBox();
 | |
|                 this.Invalidate();
 | |
|             }
 | |
|         }
 | |
|         private const int _TextBoxMinWidth = 36;
 | |
| 
 | |
|         protected override void OnHandleCreated(EventArgs e)
 | |
|         {
 | |
|             _EditBox.SetAutoHeight();
 | |
|             LayoutTokens();
 | |
|             base.OnHandleCreated(e);
 | |
|         }
 | |
| 
 | |
|         private string GetTokenText(EditToken token)
 | |
|         {
 | |
|             if (!string.IsNullOrEmpty(token.Text))
 | |
|                 return token.Text;
 | |
|             return token.Value;
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Returns the color scheme used by control. Color scheme for Office2007 style will be retrieved from the current renderer instead of
 | |
|         /// local color scheme referenced by ColorScheme property.
 | |
|         /// </summary>
 | |
|         /// <returns>An instance of ColorScheme object.</returns>
 | |
|         protected virtual ColorScheme GetColorScheme()
 | |
|         {
 | |
|             BaseRenderer r = Rendering.GlobalManager.Renderer;
 | |
|             if (r is Office2007Renderer)
 | |
|                 return ((Office2007Renderer)r).ColorTable.LegacyColors;
 | |
|             return new ColorScheme();
 | |
|         }
 | |
| 
 | |
|         private ElementStyle _BackgroundStyle = null;
 | |
|         /// <summary>
 | |
|         /// Specifies the background style of the control.
 | |
|         /// </summary>
 | |
|         [Browsable(true), Category("Style"), Description("Gets or sets bar background style."), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
 | |
|         public ElementStyle BackgroundStyle
 | |
|         {
 | |
|             get { return _BackgroundStyle; }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Resets style to default value. Used by windows forms designer.
 | |
|         /// </summary>
 | |
|         [EditorBrowsable(EditorBrowsableState.Never)]
 | |
|         public void ResetBackgroundStyle()
 | |
|         {
 | |
|             _BackgroundStyle.StyleChanged -= new EventHandler(this.VisualPropertyChanged);
 | |
|             _BackgroundStyle = new ElementStyle();
 | |
|             _BackgroundStyle.StyleChanged += new EventHandler(this.VisualPropertyChanged);
 | |
|             this.Invalidate();
 | |
|         }
 | |
|         private void VisualPropertyChanged(object sender, EventArgs e)
 | |
|         {
 | |
|             this.Invalidate();
 | |
|         }
 | |
| 
 | |
|         private CustomCollection<EditToken> _SelectedTokens;
 | |
|         /// <summary>
 | |
|         /// Gets the collection of the selected tokens.
 | |
|         /// </summary>
 | |
|         [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
 | |
|         public CustomCollection<EditToken> SelectedTokens
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return _SelectedTokens;
 | |
|             }
 | |
|         }
 | |
|         private void SelectedTokensCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
 | |
|         {
 | |
|             if (e.Action == NotifyCollectionChangedAction.Add)
 | |
|             {
 | |
|                 foreach (object item in e.NewItems)
 | |
|                 {
 | |
|                     ((EditToken)item).IsSelected = true;
 | |
|                 }
 | |
|             }
 | |
|             else if (e.Action == NotifyCollectionChangedAction.Remove)
 | |
|             {
 | |
|                 foreach (object item in e.OldItems)
 | |
|                 {
 | |
|                     ((EditToken)item).IsSelected = false;
 | |
|                 }
 | |
|             }
 | |
|             else if (e.Action == NotifyCollectionChangedAction.Replace)
 | |
|             {
 | |
|                 foreach (object item in e.NewItems)
 | |
|                 {
 | |
|                     ((EditToken)item).IsSelected = true;
 | |
|                 }
 | |
|                 foreach (object item in e.OldItems)
 | |
|                 {
 | |
|                     ((EditToken)item).IsSelected = false;
 | |
|                 }
 | |
|             }
 | |
|             else if (e.Action == NotifyCollectionChangedAction.Reset)
 | |
|             {
 | |
|                 foreach (EditToken item in _Tokens)
 | |
|                 {
 | |
|                     item.IsSelected = false;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             LayoutTokens();
 | |
|             UpdateText();
 | |
|             UpdateEditBoxWatermark();
 | |
|             OnSelectedTokensChanged(EventArgs.Empty);
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Occurs when SelectedTokens collection changes.
 | |
|         /// </summary>
 | |
|         [Description("Occurs when SelectedTokens collection changes.")]
 | |
|         public event EventHandler SelectedTokensChanged;
 | |
|         /// <summary>
 | |
|         /// Raises SelectedTokensChanged event.
 | |
|         /// </summary>
 | |
|         /// <param name="e">Provides event arguments.</param>
 | |
|         protected virtual void OnSelectedTokensChanged(EventArgs e)
 | |
|         {
 | |
|             EventHandler handler = SelectedTokensChanged;
 | |
|             if (handler != null)
 | |
|                 handler(this, e);
 | |
|         }
 | |
| 
 | |
|         private CustomCollection<EditToken> _Tokens;
 | |
|         /// <summary>
 | |
|         /// Gets the collection of the tokens available for selection.
 | |
|         /// </summary>
 | |
|         [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
 | |
|         public CustomCollection<EditToken> Tokens
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return _Tokens;
 | |
|             }
 | |
|         }
 | |
|         private void TokensCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
 | |
|         {
 | |
| 
 | |
|         }
 | |
| 
 | |
|         private bool EffectiveRemoveTokenButtonVisible
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return _RemoveTokenButtonVisible && !_ReadOnly;
 | |
|             }
 | |
|         }
 | |
|         private Size _RemoveTokenButtonSize = new Size(14, 14);
 | |
|         private bool _RemoveTokenButtonVisible = true;
 | |
|         /// <summary>
 | |
|         /// Indicates whether remove token button is displayed on individual tokens so they can be removed from the selection.
 | |
|         /// </summary>
 | |
|         [DefaultValue(true), Category("Behavior"), Description("Indicates whether remove token button is displayed on individual tokens so they can be removed from the selection.")]
 | |
|         public bool RemoveTokenButtonVisible
 | |
|         {
 | |
|             get { return _RemoveTokenButtonVisible; }
 | |
|             set
 | |
|             {
 | |
|                 if (value != _RemoveTokenButtonVisible)
 | |
|                 {
 | |
|                     bool oldValue = _RemoveTokenButtonVisible;
 | |
|                     _RemoveTokenButtonVisible = value;
 | |
|                     OnRemoveTokenButtonVisibleChanged(oldValue, value);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         /// <summary>
 | |
|         /// Called when RemoveTokenButtonVisible property has changed.
 | |
|         /// </summary>
 | |
|         /// <param name="oldValue">Old property value</param>
 | |
|         /// <param name="newValue">New property value</param>
 | |
|         protected virtual void OnRemoveTokenButtonVisibleChanged(bool oldValue, bool newValue)
 | |
|         {
 | |
|             //OnPropertyChanged(new PropertyChangedEventArgs("RemoveTokenButtonVisible"));
 | |
|             if (_SelectedTokens.Count > 0)
 | |
|                 LayoutTokens();
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Returns the token from SelectedTokens at specified position or null/nothing if no token is at given location.
 | |
|         /// </summary>
 | |
|         /// <param name="p">Location in client coordinates to test.</param>
 | |
|         /// <returns>EditToken instance or null/nothing</returns>
 | |
|         public EditToken GetSelectedTokenAt(Point p)
 | |
|         {
 | |
|             foreach (EditToken token in _SelectedTokens)
 | |
|             {
 | |
|                 Rectangle tokenBounds = token.Bounds;
 | |
|                 tokenBounds.Offset(_AutoScrollPosition);
 | |
|                 if (tokenBounds.Contains(p))
 | |
|                     return token;
 | |
|             }
 | |
|             return null;
 | |
|         }
 | |
| 
 | |
|         private EditToken _MouseOverToken = null;
 | |
|         private EditToken MouseOverToken
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return _MouseOverToken;
 | |
|             }
 | |
|             set
 | |
|             {
 | |
|                 if (_MouseOverToken != value)
 | |
|                 {
 | |
|                     if (_MouseOverToken != null)
 | |
|                         _MouseOverToken = value;
 | |
|                     this.Invalidate();
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Occurs when mouse enters one of the SelectedTokens token.
 | |
|         /// </summary>
 | |
|         [Description("Occurs when mouse enters one of the SelectedTokens token.")]
 | |
|         public event EventHandler TokenMouseEnter;
 | |
|         /// <summary>
 | |
|         /// Raises TokenMouseEnter event.
 | |
|         /// </summary>
 | |
|         /// <param name="e">Provides event arguments.</param>
 | |
|         protected virtual void OnTokenMouseEnter(object sender, EventArgs e)
 | |
|         {
 | |
|             EventHandler handler = TokenMouseEnter;
 | |
|             if (handler != null)
 | |
|                 handler(sender, e);
 | |
|         }
 | |
|         /// <summary>
 | |
|         /// Occurs when mouse leaves one of the SelectedTokens token.
 | |
|         /// </summary>
 | |
|         [Description("Occurs when mouse leaves one of the SelectedTokens token.")]
 | |
|         public event EventHandler TokenMouseLeave;
 | |
|         /// <summary>
 | |
|         /// Raises TokenMouseLeave event.
 | |
|         /// </summary>
 | |
|         /// <param name="e">Provides event arguments.</param>
 | |
|         protected virtual void OnTokenMouseLeave(object sender, EventArgs e)
 | |
|         {
 | |
|             HideToolTip();
 | |
|             EventHandler handler = TokenMouseLeave;
 | |
|             if (handler != null)
 | |
|                 handler(sender, e);
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Occurs when mouse clicks one of the SelectedTokens token.
 | |
|         /// </summary>
 | |
|         [Description("Occurs when mouse clicks one of the SelectedTokens token.")]
 | |
|         public event MouseEventHandler TokenMouseClick;
 | |
|         /// <summary>
 | |
|         /// Raises TokenMouseClick event.
 | |
|         /// </summary>
 | |
|         /// <param name="e">Provides event arguments.</param>
 | |
|         protected virtual void OnTokenMouseClick(object sender, MouseEventArgs e)
 | |
|         {
 | |
|             MouseEventHandler handler = TokenMouseClick;
 | |
|             if (handler != null)
 | |
|                 handler(sender, e);
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Occurs when mouse double clicks one of the SelectedTokens token.
 | |
|         /// </summary>
 | |
|         [Description("Occurs when mouse double clicks one of the SelectedTokens token.")]
 | |
|         public event MouseEventHandler TokenMouseDoubleClick;
 | |
|         /// <summary>
 | |
|         /// Raises TokenMouseClick event.
 | |
|         /// </summary>
 | |
|         /// <param name="e">Provides event arguments.</param>
 | |
|         protected virtual void OnTokenMouseDoubleClick(object sender, MouseEventArgs e)
 | |
|         {
 | |
|             MouseEventHandler handler = TokenMouseDoubleClick;
 | |
|             if (handler != null)
 | |
|                 handler(sender, e);
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Occurs when mouse hovers one of the SelectedTokens token.
 | |
|         /// </summary>
 | |
|         [Description("Occurs when mouse hovers one of the SelectedTokens token.")]
 | |
|         public event EventHandler TokenMouseHover;
 | |
|         /// <summary>
 | |
|         /// Raises TokenMouseHover event.
 | |
|         /// </summary>
 | |
|         /// <param name="e">Provides event arguments.</param>
 | |
|         protected virtual void OnTokenMouseHover(object sender, EventArgs e)
 | |
|         {
 | |
|             EventHandler handler = TokenMouseHover;
 | |
|             if (handler != null)
 | |
|                 handler(sender, e);
 | |
|         }
 | |
| 
 | |
|         protected override void OnMouseMove(MouseEventArgs e)
 | |
|         {
 | |
|             EditToken token = GetSelectedTokenAt(e.Location);
 | |
|             if (token != _MouseOverToken)
 | |
|             {
 | |
|                 if (_MouseOverToken != null)
 | |
|                 {
 | |
|                     _MouseOverToken.MouseOverPart = eTokenPart.None;
 | |
|                     OnTokenMouseLeave(_MouseOverToken, e);
 | |
|                 }
 | |
|                 _MouseOverToken = token;
 | |
|                 this.Invalidate();
 | |
|                 DevComponents.AdvTree.Interop.WinApi.ResetHover(this);
 | |
|                 if (_MouseOverToken != null)
 | |
|                     OnTokenMouseEnter(_MouseOverToken, e);
 | |
|             }
 | |
|             if (_MouseOverToken != null)
 | |
|             {
 | |
|                 eTokenPart oldMouseOverPart = _MouseOverToken.MouseOverPart;
 | |
|                 if (EffectiveRemoveTokenButtonVisible && !_MouseOverToken.RemoveButtonBounds.IsEmpty && _MouseOverToken.RemoveButtonBounds.Contains(e.Location))
 | |
|                     _MouseOverToken.MouseOverPart = eTokenPart.RemoveButton;
 | |
|                 else if (!_MouseOverToken.ImageBounds.IsEmpty && _MouseOverToken.ImageBounds.Contains(e.Location))
 | |
|                     _MouseOverToken.MouseOverPart = eTokenPart.Image;
 | |
|                 else
 | |
|                     _MouseOverToken.MouseOverPart = eTokenPart.Token;
 | |
|                 if (oldMouseOverPart != _MouseOverToken.MouseOverPart)
 | |
|                     this.Invalidate();
 | |
|             }
 | |
|             if (_ButtonGroup.Visible)
 | |
|                 _ButtonGroup.ProcessMouseMove(e);
 | |
|             base.OnMouseMove(e);
 | |
|         }
 | |
|         protected override void OnMouseDown(MouseEventArgs e)
 | |
|         {
 | |
|             HideToolTip();
 | |
|             if (_MouseOverToken == null && !_ReadOnly && !(_ButtonGroup.Visible && _ButtonGroup.RenderBounds.Contains(e.Location)))
 | |
|             {
 | |
|                 ShowEditTextBox();
 | |
|             }
 | |
|             else
 | |
|                 this.Select();
 | |
|             if (_ButtonGroup.Visible)
 | |
|                 _ButtonGroup.ProcessMouseDown(e);
 | |
|             base.OnMouseDown(e);
 | |
|         }
 | |
|         protected override void OnMouseUp(MouseEventArgs e)
 | |
|         {
 | |
|             if (_ButtonGroup.Visible)
 | |
|                 _ButtonGroup.ProcessMouseUp(e);
 | |
|             base.OnMouseUp(e);
 | |
|         }
 | |
|         protected override void OnMouseClick(MouseEventArgs e)
 | |
|         {
 | |
|             if (_MouseOverToken != null && _MouseOverToken.MouseOverPart == eTokenPart.RemoveButton)
 | |
|             {
 | |
|                 EditToken token = _MouseOverToken;
 | |
|                 RemovingTokenEventArgs args = new RemovingTokenEventArgs(token, eEventSource.Mouse);
 | |
|                 OnRemovingToken(args);
 | |
|                 if (args.Cancel) return;
 | |
| 
 | |
|                 LeaveMouseOverToken();
 | |
|                 this.SelectedTokens.Remove(token);
 | |
|             }
 | |
|             else if (_MouseOverToken != null)
 | |
|             {
 | |
|                 OnTokenMouseClick(_MouseOverToken, e);
 | |
|             }
 | |
|             if (_ButtonGroup.Visible)
 | |
|                 _ButtonGroup.ProcessMouseClick(e);
 | |
|             base.OnMouseClick(e);
 | |
|         }
 | |
|         protected override void OnMouseDoubleClick(MouseEventArgs e)
 | |
|         {
 | |
|             if (_MouseOverToken != null)
 | |
|             {
 | |
|                 OnTokenMouseDoubleClick(_MouseOverToken, e);
 | |
|             }
 | |
|             base.OnMouseDoubleClick(e);
 | |
|         }
 | |
|         protected override void OnMouseHover(EventArgs e)
 | |
|         {
 | |
|             if (_MouseOverToken != null)
 | |
|             {
 | |
|                 OnTokenMouseHover(_MouseOverToken, e);
 | |
|                 ShowToolTip(_MouseOverToken);
 | |
|             }
 | |
| 
 | |
|             if (_ButtonGroup.Visible)
 | |
|                 _ButtonGroup.ProcessMouseHover(e);
 | |
|             base.OnMouseHover(e);
 | |
|         }
 | |
|         /// <summary>
 | |
|         /// Occurs before token is removed from the SelectedTokens by end user.
 | |
|         /// </summary>
 | |
|         [Description("Occurs before token is removed from the SelectedTokens by end user.")]
 | |
|         public event RemovingTokenEventHandler RemovingToken;
 | |
|         /// <summary>
 | |
|         /// Raises RemovingToken event.
 | |
|         /// </summary>
 | |
|         /// <param name="e">Provides event arguments.</param>
 | |
|         protected virtual void OnRemovingToken(RemovingTokenEventArgs e)
 | |
|         {
 | |
|             RemovingTokenEventHandler handler = RemovingToken;
 | |
|             if (handler != null)
 | |
|                 handler(this, e);
 | |
|         }
 | |
|         private void LeaveMouseOverToken()
 | |
|         {
 | |
|             HideToolTip();
 | |
|             if (_MouseOverToken != null)
 | |
|             {
 | |
|                 _MouseOverToken.MouseOverPart = eTokenPart.None;
 | |
|                 OnTokenMouseLeave(_MouseOverToken, EventArgs.Empty);
 | |
|                 _MouseOverToken = null;
 | |
|                 this.Invalidate();
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private bool _IsMouseOver = false;
 | |
|         protected override void OnMouseLeave(EventArgs e)
 | |
|         {
 | |
|             _IsMouseOver = false;
 | |
|             LeaveMouseOverToken();
 | |
|             if (_ButtonGroup.Visible)
 | |
|                 _ButtonGroup.ProcessMouseLeave();
 | |
|             base.OnMouseLeave(e);
 | |
|         }
 | |
|         protected override void OnMouseEnter(EventArgs e)
 | |
|         {
 | |
|             _IsMouseOver = true;
 | |
|             base.OnMouseEnter(e);
 | |
|         }
 | |
| 
 | |
|         private EditToken _FocusToken = null;
 | |
|         private EditToken FocusToken
 | |
|         {
 | |
|             get { return _FocusToken; }
 | |
|             set
 | |
|             {
 | |
|                 if (_FocusToken != value)
 | |
|                 {
 | |
|                     if (_FocusToken != null)
 | |
|                         _FocusToken.IsFocused = false;
 | |
|                     _FocusToken = value;
 | |
|                     if (_FocusToken != null)
 | |
|                         _FocusToken.IsFocused = true;
 | |
|                     this.Invalidate();
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private void FocusPreviousToken()
 | |
|         {
 | |
|             if (this.SelectedTokens.Count == 0) return;
 | |
|             int index = _SelectedTokens.Count - 1;
 | |
|             if (_FocusToken != null)
 | |
|                 index = Math.Max(0, _SelectedTokens.IndexOf(_FocusToken) - 1);
 | |
|             FocusToken = _SelectedTokens[index];
 | |
|         }
 | |
|         private void FocusNextToken()
 | |
|         {
 | |
|             if (this.SelectedTokens.Count == 0) return;
 | |
|             int index = 0;
 | |
|             if (_FocusToken != null)
 | |
|             {
 | |
|                 if (_SelectedTokens.IndexOf(_FocusToken) == _SelectedTokens.Count - 1)
 | |
|                 {
 | |
|                     FocusToken = null;
 | |
|                     _EditBox.Select();
 | |
|                     return;
 | |
|                 }
 | |
|                 index = Math.Min(_SelectedTokens.Count - 1, _SelectedTokens.IndexOf(_FocusToken) + 1);
 | |
|             }
 | |
|             FocusToken = _SelectedTokens[index];
 | |
|         }
 | |
|         private void DeleteFocusedToken(bool isBackspace, eEventSource eventSource)
 | |
|         {
 | |
|             EditToken focusToken = _FocusToken;
 | |
|             if (focusToken == null) return;
 | |
|             RemovingTokenEventArgs e = new RemovingTokenEventArgs(focusToken, eventSource);
 | |
|             OnRemovingToken(e);
 | |
|             if (e.Cancel) return;
 | |
|             FocusToken = null;
 | |
|             int index = Math.Max(0, _SelectedTokens.IndexOf(focusToken) - 1);
 | |
|             _SelectedTokens.Remove(focusToken);
 | |
|             if (_SelectedTokens.Count > 0)
 | |
|             {
 | |
|                 FocusToken = _SelectedTokens[index];
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 _EditBox.Select();
 | |
|             }
 | |
|         }
 | |
|         protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
 | |
|         {
 | |
|             if (!_EditBox.Focused)
 | |
|             {
 | |
|                 if (keyData == Keys.Left)
 | |
|                 {
 | |
|                     FocusPreviousToken();
 | |
|                     return true;
 | |
|                 }
 | |
|                 else if (keyData == Keys.Right)
 | |
|                 {
 | |
|                     FocusNextToken();
 | |
|                     return true;
 | |
|                 }
 | |
|                 else if (keyData == Keys.Back)
 | |
|                 {
 | |
|                     DeleteFocusedToken(true, eEventSource.Keyboard);
 | |
|                     return true;
 | |
|                 }
 | |
|                 else if (keyData == Keys.Delete)
 | |
|                 {
 | |
|                     DeleteFocusedToken(false, eEventSource.Keyboard);
 | |
|                     return true;
 | |
|                 }
 | |
|             }
 | |
|             return base.ProcessCmdKey(ref msg, keyData);
 | |
|         }
 | |
| 
 | |
|         protected override void OnKeyDown(KeyEventArgs e)
 | |
|         {
 | |
|             if (_FocusToken != null)
 | |
|             {
 | |
|                 FocusToken = null;
 | |
|                 _EditBox.Select();
 | |
|             }
 | |
|             base.OnKeyDown(e);
 | |
|         }
 | |
| 
 | |
|         protected override void OnLeave(EventArgs e)
 | |
|         {
 | |
|             if (_EditBox.Visible)
 | |
|             {
 | |
|                 _EditBox.Visible = false;
 | |
|                 if (_ValidateTokenTextOnLostFocus && !string.IsNullOrEmpty(_EditBox.Text))
 | |
|                 {
 | |
|                     ValidateAndConvertEditText(_EditBox.Text);
 | |
|                 }
 | |
|             }
 | |
|             _EditBox.Text = "";
 | |
|             FocusToken = null;
 | |
|             if (IsPopupOpen)
 | |
|                 CloseAutoCompleteDropDown();
 | |
|             HideToolTip();
 | |
|             base.OnLeave(e);
 | |
|         }
 | |
|         protected override void OnEnter(EventArgs e)
 | |
|         {
 | |
|             if (!_ReadOnly)
 | |
|             {
 | |
|                 ShowEditTextBox();
 | |
|             }
 | |
|             base.OnEnter(e);
 | |
|         }
 | |
| 
 | |
|         private bool _ReadOnly = false;
 | |
|         /// <summary>
 | |
|         /// Indicates whether tokens can be added or removed by end user. Default value is false.
 | |
|         /// </summary>
 | |
|         [DefaultValue(false), Category("Behavior"), Description("Indicates whether tokens can be added or removed by end user. Default value is false.")]
 | |
|         public bool ReadOnly
 | |
|         {
 | |
|             get { return _ReadOnly; }
 | |
|             set
 | |
|             {
 | |
|                 if (value != _ReadOnly)
 | |
|                 {
 | |
|                     bool oldValue = _ReadOnly;
 | |
|                     _ReadOnly = value;
 | |
|                     OnReadOnlyChanged(oldValue, value);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         private void ShowEditTextBox()
 | |
|         {
 | |
|             _EditBox.Visible = true;
 | |
|             _EditBox.Focus();
 | |
|             EnsureTextBoxScrollPosition();
 | |
|         }
 | |
|         private void EnsureTextBoxScrollPosition()
 | |
|         {
 | |
|             if (!_EditBox.Visible) return;
 | |
|             Rectangle clientBounds = GetClientBounds();
 | |
|             if (clientBounds.Contains(_EditBox.Bounds))
 | |
|                 return;
 | |
|             // Scroll content vertically to ensure text-box is withing client bounds
 | |
|             AutoScrollPosition = new Point(0, AutoScrollPosition.Y + (clientBounds.Bottom - _EditBox.Bounds.Bottom));
 | |
|         }
 | |
|         /// <summary>
 | |
|         /// Called when ReadOnly property has changed.
 | |
|         /// </summary>
 | |
|         /// <param name="oldValue">Old property value</param>
 | |
|         /// <param name="newValue">New property value</param>
 | |
|         protected virtual void OnReadOnlyChanged(bool oldValue, bool newValue)
 | |
|         {
 | |
|             //OnPropertyChanged(new PropertyChangedEventArgs("ReadOnly"));
 | |
|             if (_ReadOnly)
 | |
|             {
 | |
|                 if (_EditBox.Visible)
 | |
|                     _EditBox.Visible = false;
 | |
|             }
 | |
|             else if (this.Focused)
 | |
|             {
 | |
|                 ShowEditTextBox();
 | |
|                 _EditBox.Focus();
 | |
|             }
 | |
|             if (_RemoveTokenButtonVisible)
 | |
|                 LayoutTokens();
 | |
|         }
 | |
| 
 | |
|         private int _DropDownHeight = 120;
 | |
|         /// <summary>
 | |
|         /// Indicates the height of the auto-complete drop-down.
 | |
|         /// </summary>
 | |
|         [DefaultValue(120), Category("Appearance"), Description("Indicates the height of the auto-complete drop-down")]
 | |
|         public int DropDownHeight
 | |
|         {
 | |
|             get { return _DropDownHeight; }
 | |
|             set
 | |
|             {
 | |
|                 if (value != _DropDownHeight)
 | |
|                 {
 | |
|                     int oldValue = _DropDownHeight;
 | |
|                     _DropDownHeight = value;
 | |
|                     OnDropDownHeightChanged(oldValue, value);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         /// <summary>
 | |
|         /// Called when DropDownHeight property has changed.
 | |
|         /// </summary>
 | |
|         /// <param name="oldValue">Old property value</param>
 | |
|         /// <param name="newValue">New property value</param>
 | |
|         protected virtual void OnDropDownHeightChanged(int oldValue, int newValue)
 | |
|         {
 | |
|             //OnPropertyChanged(new PropertyChangedEventArgs("DropDownHeight"));   
 | |
|         }
 | |
| 
 | |
|         private int _DropDownWidth = 180;
 | |
|         /// <summary>
 | |
|         /// Indicates the width of the auto-complete drop-down.
 | |
|         /// </summary>
 | |
|         [DefaultValue(180), Category("Appearance"), Description("Indicates the width of the auto-complete drop-down.")]
 | |
|         public int DropDownWidth
 | |
|         {
 | |
|             get { return _DropDownWidth; }
 | |
|             set
 | |
|             {
 | |
|                 if (value != _DropDownWidth)
 | |
|                 {
 | |
|                     int oldValue = _DropDownWidth;
 | |
|                     _DropDownWidth = value;
 | |
|                     OnDropDownWidthChanged(oldValue, value);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         /// <summary>
 | |
|         /// Called when DropDownWidth property has changed.
 | |
|         /// </summary>
 | |
|         /// <param name="oldValue">Old property value</param>
 | |
|         /// <param name="newValue">New property value</param>
 | |
|         protected virtual void OnDropDownWidthChanged(int oldValue, int newValue)
 | |
|         {
 | |
|             //OnPropertyChanged(new PropertyChangedEventArgs("DropDownWidth"));
 | |
| 
 | |
|         }
 | |
| 
 | |
|         private bool _EnterKeyValidatesToken = true;
 | |
|         /// <summary>
 | |
|         /// Indicates whether when token text is entered into the text-box pressing the Enter key attempts to validate the token and converts the text to token.
 | |
|         /// </summary>
 | |
|         [DefaultValue(true), Category("Behavior"), Description("Indicates whether when token text is entered into the text-box pressing the Enter key attempts to validate the token and converts the text to token.")]
 | |
|         public bool EnterKeyValidatesToken
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return _EnterKeyValidatesToken;
 | |
|             }
 | |
|             set
 | |
|             {
 | |
|                 _EnterKeyValidatesToken = value;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private void EditBoxKeyDown(object sender, KeyEventArgs e)
 | |
|         {
 | |
|             if (e.KeyCode == Keys.Escape && IsPopupOpen)
 | |
|             {
 | |
|                 CloseAutoCompleteDropDown();
 | |
|             }
 | |
|             else if (e.KeyCode == Keys.Enter && IsPopupOpen && _AutoCompleteListBox != null && _AutoCompleteListBox.SelectedIndex >= 0)
 | |
|             {
 | |
|                 SelectToken(_Tokens[_AutoCompleteListBox.SelectedIndex]);
 | |
|             }
 | |
|             else if (e.KeyCode == Keys.Enter && EnterKeyValidatesToken)
 | |
|             {
 | |
|                 ValidateAndConvertEditText(_EditBox.Text);
 | |
|             }
 | |
|             else if (e.KeyCode == Keys.Down)
 | |
|             {
 | |
|                 if (IsPopupOpen && _AutoCompleteListBox != null)
 | |
|                 {
 | |
|                     _AutoCompleteListBox.SelectNextItem();
 | |
|                     e.Handled = true;
 | |
|                 }
 | |
|                 else if (!IsPopupOpen && string.IsNullOrEmpty(_EditBox.Text))
 | |
|                 {
 | |
|                     IsPopupOpen = true;
 | |
|                     e.Handled = true;
 | |
|                 }
 | |
|             }
 | |
|             else if (_AutoCompleteListBox != null && e.KeyCode == Keys.Up)
 | |
|             {
 | |
|                 _AutoCompleteListBox.SelectPreviousItem();
 | |
|                 e.Handled = true;
 | |
|             }
 | |
|             else if ((e.KeyCode == Keys.Left || e.KeyCode == Keys.Back) && string.IsNullOrEmpty(_EditBox.Text))
 | |
|             {
 | |
|                 CloseAutoCompleteDropDown();
 | |
|                 if (this.SelectedTokens.Count > 0)
 | |
|                 {
 | |
|                     this.Select();
 | |
|                     FocusPreviousToken();
 | |
|                 }
 | |
|                 e.Handled = true;
 | |
|             }
 | |
| 
 | |
|         }
 | |
| 
 | |
| 
 | |
|         private void AutoCompleteListBoxItemClick(object sender, EventArgs e)
 | |
|         {
 | |
|             if (_AutoCompleteListBox.SelectedIndex >= 0)
 | |
|                 SelectToken(_Tokens[_AutoCompleteListBox.SelectedIndex]);
 | |
|         }
 | |
| 
 | |
|         private bool SelectToken(EditToken token)
 | |
|         {
 | |
|             if (token.IsSelected) return false;
 | |
| 
 | |
|             ValidateTokenEventArgs args = new ValidateTokenEventArgs(token, false);
 | |
|             if (args.IsValid && args.Token != null)
 | |
|             {
 | |
|                 token = args.Token;
 | |
|                 this.SelectedTokens.Add(token);
 | |
|                 _EditBox.Text = "";
 | |
|                 CloseAutoCompleteDropDown();
 | |
|                 return true;
 | |
|             }
 | |
|             return false;
 | |
|         }
 | |
| 
 | |
|         private bool ValidateAndConvertEditText(string text)
 | |
|         {
 | |
|             if (string.IsNullOrEmpty(text))
 | |
|                 return false;
 | |
|             IsPopupOpen = false;
 | |
|             bool isNewToken = false;
 | |
|             EditToken token = FindOrCreateToken(text, out isNewToken);
 | |
|             ValidateTokenEventArgs args = new ValidateTokenEventArgs(token, isNewToken);
 | |
|             OnValidateToken(args);
 | |
|             if (args.IsValid && args.Token != null)
 | |
|             {
 | |
|                 token = args.Token;
 | |
|                 this.SelectedTokens.Add(token);
 | |
|                 _EditBox.Text = "";
 | |
|                 CloseAutoCompleteDropDown();
 | |
|                 return true;
 | |
|             }
 | |
|             return false;
 | |
|         }
 | |
| 
 | |
|         private bool IsSelected(EditToken item)
 | |
|         {
 | |
|             return item.IsSelected;
 | |
| 
 | |
|             //foreach (EditToken selectedToken in _SelectedTokens)
 | |
|             //{
 | |
|             //    if(selectedToken == item)
 | |
|             //        return true;
 | |
|             //}
 | |
|             //return false;
 | |
|         }
 | |
|         private EditToken FindOrCreateToken(string text, out bool isNew)
 | |
|         {
 | |
|             isNew = false;
 | |
|             foreach (EditToken item in _Tokens)
 | |
|             {
 | |
|                 if (!item.IsSelected && TokenExactMatch(text, item, _TokenFilterBehavior))
 | |
|                 {
 | |
|                     return item;
 | |
|                 }
 | |
|             }
 | |
|             isNew = true;
 | |
|             return new EditToken(text);
 | |
|         }
 | |
| 
 | |
|         private void EditBoxTextChanged(object sender, EventArgs e)
 | |
|         {
 | |
|             string text = _EditBox.Text;
 | |
| 
 | |
|             if (!_DroppedDown && FilteredTokenExists(text))
 | |
|             {
 | |
|                 OpenAutoCompleteDropDown();
 | |
|             }
 | |
|             if (_AutoCompleteListBox != null)
 | |
|             {
 | |
|                 FilterAutoCompleteBox(_AutoCompleteListBox, text);
 | |
|             }
 | |
| 
 | |
|             foreach (string separator in _Separators)
 | |
|             {
 | |
|                 if (text.EndsWith(separator))
 | |
|                 {
 | |
|                     text = text.Substring(0, text.Length - separator.Length);
 | |
|                     ValidateAndConvertEditText(text);
 | |
|                     break;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private PopupHostController _PopupController = null;
 | |
|         private ListBoxAdv _AutoCompleteListBox = null;
 | |
|         private DateTime _MultiDropDownOpenedAtTime = DateTime.MinValue;
 | |
|         private DateTime _MultiDropDownClosedAtTime = DateTime.MinValue;
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Occurs before token auto-complete popup is displayed and allows cancelation of popup display.
 | |
|         /// </summary>
 | |
|         [Description("Occurs before token auto-complete popup is displayed and allows cancelation of popup display.")]
 | |
|         public event CancelEventHandler BeforeAutoCompletePopupOpen;
 | |
|         /// <summary>
 | |
|         /// Occurs after auto-complete popup is open.
 | |
|         /// </summary>
 | |
|         [Description("Occurs after auto-complete popup is open.")]
 | |
|         public event EventHandler AutoCompletePopupOpened;
 | |
|         /// <summary>
 | |
|         /// Raises AutoCompletePopupOpened event.
 | |
|         /// </summary>
 | |
|         /// <param name="e">Provides event arguments.</param>
 | |
|         protected virtual void OnAutoCompletePopupOpened(EventArgs e)
 | |
|         {
 | |
|             EventHandler handler = AutoCompletePopupOpened;
 | |
|             if (handler != null)
 | |
|                 handler(this, e);
 | |
|         }
 | |
|         /// <summary>
 | |
|         /// Raises BeforeAutoCompletePopupOpen event.
 | |
|         /// </summary>
 | |
|         /// <param name="e">Provides event arguments.</param>
 | |
|         protected virtual void OnBeforeAutoCompletePopupOpen(CancelEventArgs e)
 | |
|         {
 | |
|             CancelEventHandler handler = BeforeAutoCompletePopupOpen;
 | |
|             if (handler != null)
 | |
|                 handler(this, e);
 | |
|         }
 | |
| 
 | |
|         private void OpenAutoCompleteDropDown()
 | |
|         {
 | |
|             if (_PopupController == null)
 | |
|             {
 | |
|                 _PopupController = new PopupHostController();
 | |
|                 _PopupController.Closed += PopupControllerClosed;
 | |
|             }
 | |
| 
 | |
|             if (_AutoCompleteListBox == null)
 | |
|             {
 | |
|                 _AutoCompleteListBox = CreateAutoCompleteListBox();
 | |
|                 //_AutoCompleteListBox.Resize += _AutoCompleteListBox_Resize;
 | |
|                 //this.Parent.Controls.Add(_AutoCompleteListBox);
 | |
|                 //_AutoCompleteListBox.Location = new Point(10,100);
 | |
|             }
 | |
|             
 | |
|             if (!_MessageHandlerInstalled && _DropDownButtonVisible)
 | |
|             {
 | |
|                 MessageHandler.RegisterMessageClient(this);
 | |
|                 _MessageHandlerInstalled = true;
 | |
|             }
 | |
| 
 | |
|             LoadAutoCompleteBox(_AutoCompleteListBox);
 | |
| 
 | |
|             if (!_PopupController.PopupUserSize || !_PreservePopupSize)
 | |
|             {
 | |
|                 _AutoCompleteListBox.Height = Dpi.Height(this.DropDownHeight);
 | |
|                 _AutoCompleteListBox.Width = (this.DropDownWidth > 0 ? Dpi.Width(this.DropDownWidth) : this.Width);
 | |
|                 //_AutoCompleteListBox.MinimumSize = _AutoCompleteListBox.Size;
 | |
|             }
 | |
| 
 | |
|             CancelEventArgs cancelArgs = new CancelEventArgs();
 | |
|             OnBeforeAutoCompletePopupOpen(cancelArgs);
 | |
|             if (cancelArgs.Cancel)
 | |
|                 return;
 | |
| 
 | |
|             Point location = PointToScreen(new Point(0, Height));
 | |
|             TokenEditorPopupEventArgs popupArgs = new TokenEditorPopupEventArgs(location, _AutoCompleteListBox.Size);
 | |
|             OnBeforePopupOpen(popupArgs);
 | |
|             location = popupArgs.PopupLocation;
 | |
|             ePopupResizeEdge resize = _EnablePopupResize ? ePopupResizeEdge.BottomRight : ePopupResizeEdge.None;
 | |
|             _PopupController.AutoClose = false;
 | |
| 
 | |
|             _PopupController.ParentControlBounds = new Rectangle(PointToScreen(Point.Empty), this.Size);
 | |
|             _PopupController.Show(_AutoCompleteListBox, location.X, location.Y, 0, 0, resize);
 | |
| 
 | |
|             _EditBox.Focus();
 | |
|             _EditBox.SelectionLength = 0; // Clear selection that happens upon focus
 | |
|             if (_EditBox.TextLength > 0)
 | |
|                 _EditBox.SelectionStart = _EditBox.TextLength;
 | |
|             _PopupController.AutoClose = true;
 | |
|             _DroppedDown = true;
 | |
|             _MultiDropDownOpenedAtTime = DateTime.Now;
 | |
| 
 | |
|             OnAutoCompletePopupOpened(EventArgs.Empty);
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Occurs before the auto-complete popup is displayed and allows you to adjust popup location.
 | |
|         /// </summary>
 | |
|         [Description("Occurs before the auto-complete popup is displayed and allows you to adjust popup location.")]
 | |
|         public event TokenEditorPopupEventHandler BeforePopupOpen;
 | |
|         /// <summary>
 | |
|         /// Raises BeforePopupOpen event.
 | |
|         /// </summary>
 | |
|         /// <param name="e">Provides event arguments.</param>
 | |
|         protected virtual void OnBeforePopupOpen(TokenEditorPopupEventArgs e)
 | |
|         {
 | |
|             TokenEditorPopupEventHandler handler = BeforePopupOpen;
 | |
|             if (handler != null)
 | |
|                 handler(this, e);
 | |
|         }
 | |
| 
 | |
|         private void LoadAutoCompleteBox(ListBoxAdv listBox)
 | |
|         {
 | |
|             listBox.BeginUpdate();
 | |
|             listBox.Items.Clear();
 | |
|             listBox.CheckBoxesVisible = _CheckBoxesVisible;
 | |
|             listBox.ShowToolTips = _ShowToolTips;
 | |
|             foreach (EditToken item in _Tokens)
 | |
|             {
 | |
|                 ListBoxItem listItem = new ListBoxItem();
 | |
|                 listItem.Text = GetTokenText(item);
 | |
|                 listItem.Tooltip = item.Tooltip;
 | |
|                 if (_CheckBoxesVisible)
 | |
|                     listItem.CheckState = (item.IsSelected ? CheckState.Checked : CheckState.Unchecked);
 | |
|                 else
 | |
|                     listItem.Visible = !item.IsSelected;
 | |
|                 listBox.Items.Add(listItem);
 | |
|             }
 | |
|             listBox.EndUpdate();
 | |
|         }
 | |
|         private bool FilteredTokenExists(string text)
 | |
|         {
 | |
|             foreach (EditToken item in _Tokens)
 | |
|             {
 | |
|                 if (item.IsSelected) continue;
 | |
|                 if (TokenMatch(text, item, _TokenFilterBehavior))
 | |
|                     return true;
 | |
|             }
 | |
|             return false;
 | |
|         }
 | |
| 
 | |
|         private eTokenFilterBehavior _TokenFilterBehavior = eTokenFilterBehavior.TextAndValue;
 | |
|         /// <summary>
 | |
|         /// Indicates how tokens are filtered based on the entered text
 | |
|         /// </summary>
 | |
|         [DefaultValue(eTokenFilterBehavior.TextAndValue), Category("Behavior"), Description("Indicates how tokens are filtered based on the entered text")]
 | |
|         public eTokenFilterBehavior TokenFilterBehavior
 | |
|         {
 | |
|             get { return _TokenFilterBehavior; }
 | |
|             set { _TokenFilterBehavior = value; }
 | |
|         }
 | |
|         private static bool TokenMatch(string filterText, EditToken token, eTokenFilterBehavior behavior)
 | |
|         {
 | |
|             filterText = filterText.ToLower();
 | |
|             if(behavior == eTokenFilterBehavior.Text)
 | |
|                 return !string.IsNullOrEmpty(token.Text) && token.Text.ToLower().Contains(filterText);
 | |
|             else if(behavior == eTokenFilterBehavior.Value)
 | |
|                 return !string.IsNullOrEmpty(token.Value) && token.Value.ToLower().Contains(filterText);
 | |
|             return !string.IsNullOrEmpty(token.Text) && token.Text.ToLower().Contains(filterText) || !string.IsNullOrEmpty(token.Value) && token.Value.ToLower().Contains(filterText);
 | |
|         }
 | |
|         private static bool TokenExactMatch(string filterText, EditToken token, eTokenFilterBehavior behavior)
 | |
|         {
 | |
|             filterText = filterText.ToLower();
 | |
|             if (behavior == eTokenFilterBehavior.Text)
 | |
|                 return !string.IsNullOrEmpty(token.Text) && token.Text.ToLower() == filterText;
 | |
|             else if (behavior == eTokenFilterBehavior.Value)
 | |
|                 return !string.IsNullOrEmpty(token.Value) && token.Value.ToLower() == filterText;
 | |
|             return !string.IsNullOrEmpty(token.Text) && token.Text.ToLower() == filterText || !string.IsNullOrEmpty(token.Value) && token.Value.ToLower() == filterText;
 | |
|         }
 | |
|         private void FilterAutoCompleteBox(ListBoxAdv listBox, string filterText)
 | |
|         {
 | |
|             bool oneVisible = false;
 | |
|             listBox.BeginUpdate();
 | |
|             if (string.IsNullOrEmpty(filterText))
 | |
|             {
 | |
|                 if (!_CheckBoxesVisible)
 | |
|                 {
 | |
|                     foreach (ListBoxItem item in listBox.Items)
 | |
|                     {
 | |
|                         item.IsSelected = false;
 | |
|                         item.Visible = !item.IsSelected;
 | |
|                         if (item.Visible)
 | |
|                             oneVisible = true;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 for (int i = 0; i < listBox.Items.Count; i++)
 | |
|                 {
 | |
|                     ListBoxItem item = (ListBoxItem)listBox.Items[i];
 | |
|                     EditToken token = _Tokens[i];
 | |
|                     if (!token.IsSelected && TokenMatch(filterText, token, _TokenFilterBehavior))
 | |
|                     {
 | |
|                         if (!_CheckBoxesVisible)
 | |
|                             item.Visible = true;
 | |
|                         if (!oneVisible)
 | |
|                             item.IsSelected = true;
 | |
|                         else
 | |
|                             item.IsSelected = false;
 | |
|                         oneVisible = true;
 | |
|                     }
 | |
|                     else if (!_CheckBoxesVisible)
 | |
|                         item.Visible = false;
 | |
|                     else
 | |
|                         item.IsSelected = false;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             listBox.EndUpdate();
 | |
| 
 | |
|             if (!oneVisible && !_CheckBoxesVisible)
 | |
|                 CloseAutoCompleteDropDown();
 | |
|         }
 | |
| 
 | |
|         private ListBoxAdv CreateAutoCompleteListBox()
 | |
|         {
 | |
|             ListBoxAdv listBox = new ListBoxAdv();
 | |
| #if (!TRIAL)
 | |
|             listBox.LicenseKey = "F962CEC7-CD8F-4911-A9E9-CAB39962FC1F";
 | |
| #endif
 | |
|             //listBox.BackColor = Color.White;
 | |
|             listBox.BackgroundStyle.Class = ElementStyleClassKeys.ListBoxAdvKey;
 | |
|             listBox.ItemClick += AutoCompleteListBoxItemClick;
 | |
|             listBox.ItemCheck += AutoCompleteListBoxItemCheck;
 | |
|             listBox.AutoScroll = true;
 | |
|             //listBox.BackgroundStyle.Reset();
 | |
|             //listBox.BackgroundStyle.BackColor = SystemColors.Window;
 | |
|             //listBox.BackgroundStyle.Border = eStyleBorderType.None;
 | |
|             return listBox;
 | |
| 
 | |
|         }
 | |
| 
 | |
|         void AutoCompleteListBoxItemCheck(object sender, ListBoxAdvItemCheckEventArgs e)
 | |
|         {
 | |
|             int index = _AutoCompleteListBox.Items.IndexOf(e.Item);
 | |
|             EditToken token = _Tokens[index];
 | |
|             if (e.Item.CheckState == CheckState.Unchecked && token.IsSelected)
 | |
|                 this.SelectedTokens.Remove(token);
 | |
|             else if (!token.IsSelected)
 | |
|                 this.SelectedTokens.Add(token);
 | |
|         }
 | |
|         private void PopupControllerClosed(object sender, ToolStripDropDownClosedEventArgs e)
 | |
|         {
 | |
|             _DroppedDown = false;
 | |
| 
 | |
|             //m_SelectedIndexInternal = this.SelectedIndex;
 | |
|             _MultiDropDownClosedAtTime = DateTime.Now;
 | |
|             //OnDropDownClosed(e);
 | |
|         }
 | |
|         private void CloseAutoCompleteDropDown()
 | |
|         {
 | |
|             if (_PopupController != null && _DroppedDown)
 | |
|             {
 | |
|                 _PopupController.Hide();
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private bool _PreservePopupSize = true;
 | |
|         /// <summary>
 | |
|         /// Indicates whether auto-complete popup size is preserved between popup displays if popup is resized by end-user.
 | |
|         /// </summary>
 | |
|         [DefaultValue(true), Category("Auto-Complete"), Description("Indicates whether auto-complete popup size is preserved between popup displays if popup is resized by end-user.")]
 | |
|         public bool PreservePopupSize
 | |
|         {
 | |
|             get { return _PreservePopupSize; }
 | |
|             set
 | |
|             {
 | |
|                 _PreservePopupSize = value;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private bool _EnablePopupResize = true;
 | |
|         /// <summary>
 | |
|         /// Indicates whether auto-complete popup can be resized by end user.
 | |
|         /// </summary>
 | |
|         [DefaultValue(true), Category("Auto-Complete"), Description("Indicates whether auto-complete popup can be resized by end user.")]
 | |
|         public bool EnablePopupResize
 | |
|         {
 | |
|             get { return _EnablePopupResize; }
 | |
|             set
 | |
|             {
 | |
|                 _EnablePopupResize = value;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private bool _PopupCloseButtonVisible = true;
 | |
|         /// <summary>
 | |
|         /// Indicates whether multi-column popup close button is visible.
 | |
|         /// </summary>
 | |
|         [DefaultValue(true), Category("Auto-Complete"), Description("Indicates whether multi-column popup close button is visible.")]
 | |
|         public bool PopupCloseButtonVisible
 | |
|         {
 | |
|             get { return _PopupCloseButtonVisible; }
 | |
|             set
 | |
|             {
 | |
|                 _PopupCloseButtonVisible = value;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private bool _DroppedDown = false;
 | |
|         /// <summary>
 | |
|         /// Gets or sets whether auto-complete popup window is open.
 | |
|         /// </summary>
 | |
|         [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
 | |
|         public bool IsPopupOpen
 | |
|         {
 | |
|             get { return _DroppedDown; }
 | |
|             set
 | |
|             {
 | |
|                 if (value != _DroppedDown)
 | |
|                 {
 | |
|                     if (value)
 | |
|                         OpenAutoCompleteDropDown();
 | |
|                     else
 | |
|                         CloseAutoCompleteDropDown();
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private List<string> _Separators = new List<string>();
 | |
|         /// <summary>
 | |
|         /// Gets the list of separators which are used to divide entered text into the tokens.
 | |
|         /// </summary>
 | |
|         [Category("Behavior"), Description("Gets the list of separators which are used to divide entered text into the tokens."), DesignerSerializationVisibility(DesignerSerializationVisibility.Content), MergableProperty(false), Localizable(true)]
 | |
|         [Editor("System.Windows.Forms.Design.ListControlStringCollectionEditor, System.Design, Version= 2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]
 | |
|         public List<string> Separators
 | |
|         {
 | |
|             get { return _Separators; }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Occurs when an token is selected from the auto-complete list or when text entry by end user is parsed into token to validate it.
 | |
|         /// </summary>
 | |
|         [Description("Occurs when an token is selected from the auto-complete list or when text entry by end user is parsed into token to validate it.")]
 | |
|         public event ValidateTokenEventHandler ValidateToken;
 | |
|         /// <summary>
 | |
|         /// Raises ValidateToken event.
 | |
|         /// </summary>
 | |
|         /// <param name="e">Provides event arguments.</param>
 | |
|         protected virtual void OnValidateToken(ValidateTokenEventArgs e)
 | |
|         {
 | |
|             ValidateTokenEventHandler handler = ValidateToken;
 | |
|             if (handler != null)
 | |
|                 handler(this, e);
 | |
|         }
 | |
| 
 | |
|         private bool _AutoSizeHeight = true;
 | |
|         /// <summary>
 | |
|         /// Indicates whether control automatically increases its height as more tokens are selected. MaxHeightLines property controls the maximum number of lines control will grow to before showing scroll-bar.
 | |
|         /// </summary>
 | |
|         [DefaultValue(true), Category("Behavior"), Description("Indicates whether control automatically increases its height as more tokens are selected. MaxHeightLines property controls the maximum number of lines control will grow to before showing scroll-bar.")]
 | |
|         public bool AutoSizeHeight
 | |
|         {
 | |
|             get { return _AutoSizeHeight; }
 | |
|             set
 | |
|             {
 | |
|                 if (_AutoSizeHeight != value)
 | |
|                 {
 | |
|                     _AutoSizeHeight = value;
 | |
|                     if (_AutoSizeHeight)
 | |
|                         LayoutTokens();
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private int _MaxHeightLines = 5;
 | |
|         /// <summary>
 | |
|         /// Indicates maximum number of lines control will grow to when AutoSizeHeight=true. Set to 0 to indicates unlimited growth.
 | |
|         /// Default value is 5.
 | |
|         /// </summary>
 | |
|         [DefaultValue(5), Category("Behavior"), Description("Indicates maximum number of lines control will grow to when AutoSizeHeight=true. Set to 0 to indicates unlimited growth.")]
 | |
|         public int MaxHeightLines
 | |
|         {
 | |
|             get { return _MaxHeightLines; }
 | |
|             set { _MaxHeightLines = value; }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets reference to internal text-box control that is used to input the token text.
 | |
|         /// </summary>
 | |
|         [Browsable(false)]
 | |
|         public TextBox EditTextBox
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return _EditBox;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private bool _ValidateTokenTextOnLostFocus = true;
 | |
|         /// <summary>
 | |
|         /// Indicates whether any text entered into the token editor is validated and converted to token when control loses focus.
 | |
|         /// </summary>
 | |
|         [DefaultValue(true), Category("Behavior"), Description("Indicates whether any text entered into the token editor is validated and converted to token when control loses focus.")]
 | |
|         public bool ValidateTokenTextOnLostFocus
 | |
|         {
 | |
|             get { return _ValidateTokenTextOnLostFocus; }
 | |
|             set { _ValidateTokenTextOnLostFocus = value; }
 | |
|         }
 | |
| 
 | |
|         private string _WatermarkText = "";
 | |
|         private Font _WatermarkFont = null;
 | |
|         private Color _WatermarkColor = SystemColors.GrayText;
 | |
| 
 | |
|         private bool _WatermarkEnabled = true;
 | |
|         /// <summary>
 | |
|         /// Gets or sets whether watermark text is displayed when control is empty. Default value is true.
 | |
|         /// </summary>
 | |
|         [DefaultValue(true), Description("Indicates whether watermark text is displayed when control is empty.")]
 | |
|         public virtual bool WatermarkEnabled
 | |
|         {
 | |
|             get { return _WatermarkEnabled; }
 | |
|             set { _WatermarkEnabled = value; this.Invalidate(); UpdateEditBoxWatermark(); }
 | |
|         }
 | |
| 
 | |
|         private Image _WatermarkImage = null;
 | |
|         /// <summary>
 | |
|         /// Gets or sets the watermark image displayed inside of the control when Text is not set and control does not have input focus.
 | |
|         /// </summary>
 | |
|         [DefaultValue(null), Category("Appearance"), Description("Indicates watermark image displayed inside of the control when Text is not set and control does not have input focus.")]
 | |
|         public Image WatermarkImage
 | |
|         {
 | |
|             get { return _WatermarkImage; }
 | |
|             set { _WatermarkImage = value; this.Invalidate(); UpdateEditBoxWatermark(); }
 | |
|         }
 | |
|         private ContentAlignment _WatermarkImageAlignment = ContentAlignment.MiddleLeft;
 | |
|         /// <summary>
 | |
|         /// Gets or sets the watermark image alignment.
 | |
|         /// </summary>
 | |
|         [DefaultValue(ContentAlignment.MiddleLeft), Category("Appearance"), Description("Indicates watermark image alignment.")]
 | |
|         public ContentAlignment WatermarkImageAlignment
 | |
|         {
 | |
|             get { return _WatermarkImageAlignment; }
 | |
|             set { _WatermarkImageAlignment = value; this.Invalidate(); UpdateEditBoxWatermark(); }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets or sets the watermark (tip) text displayed inside of the control when Text is not set and control does not have input focus. This property supports text-markup.
 | |
|         /// </summary>
 | |
|         [Browsable(true), DefaultValue(""), Localizable(true), Category("Appearance"), Description("Indicates watermark text displayed inside of the control when Text is not set and control does not have input focus."), Editor("DevComponents.DotNetBar.Design.TextMarkupUIEditor, DevComponents.DotNetBar.Design, Version=14.1.0.37, Culture=neutral,  PublicKeyToken=90f470f34c89ccaf", typeof(System.Drawing.Design.UITypeEditor))]
 | |
|         public string WatermarkText
 | |
|         {
 | |
|             get { return _WatermarkText; }
 | |
|             set
 | |
|             {
 | |
|                 if (value == null) value = "";
 | |
|                 _WatermarkText = value;
 | |
|                 MarkupTextChanged();
 | |
|                 UpdateEditBoxWatermark();
 | |
|                 this.Invalidate();
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets or sets the watermark font.
 | |
|         /// </summary>
 | |
|         [Browsable(true), Category("Appearance"), Description("Indicates watermark font."), DefaultValue(null)]
 | |
|         public Font WatermarkFont
 | |
|         {
 | |
|             get { return _WatermarkFont; }
 | |
|             set { _WatermarkFont = value; this.Invalidate(); UpdateEditBoxWatermark(); }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets or sets the watermark text color.
 | |
|         /// </summary>
 | |
|         [Browsable(true), Category("Appearance"), Description("Indicates watermark text color.")]
 | |
|         public Color WatermarkColor
 | |
|         {
 | |
|             get { return _WatermarkColor; }
 | |
|             set { _WatermarkColor = value; this.Invalidate(); UpdateEditBoxWatermark(); }
 | |
|         }
 | |
|         /// <summary>
 | |
|         /// Indicates whether property should be serialized by Windows Forms designer.
 | |
|         /// </summary>
 | |
|         [EditorBrowsable(EditorBrowsableState.Never)]
 | |
|         public bool ShouldSerializeWatermarkColor()
 | |
|         {
 | |
|             return _WatermarkColor != SystemColors.GrayText;
 | |
|         }
 | |
|         /// <summary>
 | |
|         /// Resets the property to default value.
 | |
|         /// </summary>
 | |
|         [EditorBrowsable(EditorBrowsableState.Never)]
 | |
|         public void ResetWatermarkColor()
 | |
|         {
 | |
|             this.WatermarkColor = SystemColors.GrayText;
 | |
|         }
 | |
| 
 | |
|         protected virtual bool IsWatermarkRendered
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return (!this.Focused || _WatermarkBehavior == eWatermarkBehavior.HideNonEmpty) && this.SelectedTokens.Count == 0;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private eWatermarkBehavior _WatermarkBehavior = eWatermarkBehavior.HideOnFocus;
 | |
|         /// <summary>
 | |
|         /// Gets or sets the watermark hiding behaviour. Default value indicates that watermark is hidden when control receives input focus.
 | |
|         /// </summary>
 | |
|         [DefaultValue(eWatermarkBehavior.HideOnFocus), Category("Behavior"), Description("Indicates watermark hiding behaviour.")]
 | |
|         public eWatermarkBehavior WatermarkBehavior
 | |
|         {
 | |
|             get { return _WatermarkBehavior; }
 | |
|             set { _WatermarkBehavior = value; this.Invalidate();
 | |
|                 UpdateEditBoxWatermark();
 | |
|             }
 | |
|         }
 | |
|         private void UpdateEditBoxWatermark()
 | |
|         {
 | |
|             _EditBox.WatermarkText = _WatermarkText;
 | |
|             _EditBox.WatermarkColor = _WatermarkColor;
 | |
|             _EditBox.WatermarkFont = _WatermarkFont;
 | |
|             _EditBox.WatermarkImage = _WatermarkImage;
 | |
|             _EditBox.WatermarkImageAlignment = _WatermarkImageAlignment;
 | |
|             if (this.SelectedTokens.Count > 0 || !_WatermarkEnabled)
 | |
|                 _EditBox.WatermarkEnabled = false;
 | |
|             else if (_WatermarkBehavior == eWatermarkBehavior.HideNonEmpty)
 | |
|             {
 | |
|                 _EditBox.WatermarkEnabled = true;
 | |
|                 _EditBox.WatermarkBehavior = eWatermarkBehavior.HideNonEmpty;
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 _EditBox.WatermarkBehavior = eWatermarkBehavior.HideOnFocus;
 | |
|             }
 | |
| 
 | |
|         }
 | |
| 
 | |
|         private TextMarkup.BodyElement _TextMarkup = null;
 | |
|         private void MarkupTextChanged()
 | |
|         {
 | |
|             _TextMarkup = null;
 | |
| 
 | |
|             if (!TextMarkup.MarkupParser.IsMarkup(ref _WatermarkText))
 | |
|                 return;
 | |
| 
 | |
|             _TextMarkup = TextMarkup.MarkupParser.Parse(_WatermarkText);
 | |
|             ResizeMarkup();
 | |
|         }
 | |
| 
 | |
|         private MarkupDrawContext GetMarkupDrawContext(Graphics g)
 | |
|         {
 | |
|             return new MarkupDrawContext(g, (_WatermarkFont == null ? this.Font : _WatermarkFont), _WatermarkColor, this.RightToLeft == RightToLeft.Yes);
 | |
|         }
 | |
|         private void ResizeMarkup()
 | |
|         {
 | |
|             if (_TextMarkup != null)
 | |
|             {
 | |
|                 using (Graphics g = this.CreateGraphics())
 | |
|                 {
 | |
|                     MarkupDrawContext dc = GetMarkupDrawContext(g);
 | |
|                     _TextMarkup.Measure(GetWatermarkBounds().Size, dc);
 | |
|                     Size sz = _TextMarkup.Bounds.Size;
 | |
|                     _TextMarkup.Arrange(new Rectangle(GetWatermarkBounds().Location, sz), dc);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private Rectangle GetWatermarkBounds()
 | |
|         {
 | |
|             Rectangle r = this.ClientRectangle;
 | |
|             r.Inflate(-1, 0);
 | |
|             r.X += 2;
 | |
|             r.Width -= 2;
 | |
|             return r;
 | |
|         }
 | |
| 
 | |
|         private void DrawWatermark(Graphics g)
 | |
|         {
 | |
| 
 | |
|             Rectangle bounds = GetWatermarkBounds();
 | |
|             if (_WatermarkImage != null)
 | |
|             {
 | |
|                 Rectangle imageBounds = new Rectangle(Point.Empty, _WatermarkImage.Size);
 | |
|                 if (_WatermarkImageAlignment == ContentAlignment.BottomCenter)
 | |
|                     imageBounds.Location = new Point(bounds.X + (bounds.Width - imageBounds.Width) / 2, bounds.Bottom - imageBounds.Height);
 | |
|                 else if (_WatermarkImageAlignment == ContentAlignment.BottomLeft)
 | |
|                     imageBounds.Location = new Point(bounds.X, bounds.Bottom - imageBounds.Height);
 | |
|                 else if (_WatermarkImageAlignment == ContentAlignment.BottomRight)
 | |
|                     imageBounds.Location = new Point(bounds.Right - imageBounds.Width, bounds.Bottom - imageBounds.Height);
 | |
|                 else if (_WatermarkImageAlignment == ContentAlignment.MiddleCenter)
 | |
|                     imageBounds.Location = new Point(bounds.X + (bounds.Width - imageBounds.Width) / 2, bounds.Y + (bounds.Height - imageBounds.Height) / 2);
 | |
|                 else if (_WatermarkImageAlignment == ContentAlignment.MiddleLeft)
 | |
|                     imageBounds.Location = new Point(bounds.X, bounds.Y + (bounds.Height - imageBounds.Height) / 2);
 | |
|                 else if (_WatermarkImageAlignment == ContentAlignment.MiddleRight)
 | |
|                     imageBounds.Location = new Point(bounds.Right - imageBounds.Width, bounds.Y + (bounds.Height - imageBounds.Height) / 2);
 | |
|                 else if (_WatermarkImageAlignment == ContentAlignment.TopCenter)
 | |
|                     imageBounds.Location = new Point(bounds.X + (bounds.Width - imageBounds.Width) / 2, bounds.Y);
 | |
|                 else if (_WatermarkImageAlignment == ContentAlignment.TopLeft)
 | |
|                     imageBounds.Location = new Point(bounds.X, bounds.Y);
 | |
|                 else if (_WatermarkImageAlignment == ContentAlignment.TopRight)
 | |
|                     imageBounds.Location = new Point(bounds.Right - imageBounds.Width, bounds.Y);
 | |
|                 g.DrawImage(_WatermarkImage, imageBounds);
 | |
| 
 | |
|                 if (_WatermarkImageAlignment == ContentAlignment.BottomLeft || _WatermarkImageAlignment == ContentAlignment.MiddleLeft || _WatermarkImageAlignment == ContentAlignment.TopLeft)
 | |
|                 {
 | |
|                     bounds.X = imageBounds.Right;
 | |
|                     bounds.Width = Math.Max(0, bounds.Width - imageBounds.Width);
 | |
|                 }
 | |
|                 else if (_WatermarkImageAlignment == ContentAlignment.BottomRight || _WatermarkImageAlignment == ContentAlignment.MiddleRight || _WatermarkImageAlignment == ContentAlignment.TopRight)
 | |
|                 {
 | |
|                     bounds.Width = Math.Max(0, bounds.Width - imageBounds.Width);
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             if (bounds.Width <= 0) return;
 | |
| 
 | |
|             if (_TextMarkup != null)
 | |
|             {
 | |
|                 MarkupDrawContext dc = GetMarkupDrawContext(g);
 | |
|                 if (_TextMarkup.Bounds.Height < bounds.Height)
 | |
|                     _TextMarkup.Bounds = new Rectangle(bounds.X, bounds.Y + (bounds.Height - _TextMarkup.Bounds.Height) / 2, _TextMarkup.Bounds.Width, _TextMarkup.Bounds.Height);
 | |
|                 _TextMarkup.Render(dc);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 eTextFormat tf = eTextFormat.Left | eTextFormat.VerticalCenter;
 | |
| 
 | |
|                 if (this.RightToLeft == RightToLeft.Yes) tf |= eTextFormat.RightToLeft;
 | |
| 
 | |
|                 tf |= eTextFormat.EndEllipsis;
 | |
|                 tf |= eTextFormat.WordBreak;
 | |
|                 TextDrawing.DrawString(g, _WatermarkText, (_WatermarkFont == null ? this.Font : _WatermarkFont),
 | |
|                     _WatermarkColor, bounds, tf);
 | |
|             }
 | |
| 
 | |
|         }
 | |
| 
 | |
|         protected override void OnTextChanged(EventArgs e)
 | |
|         {
 | |
|             if (!_UpdatingText)
 | |
|             {
 | |
|                 this.SelectedTokens.Clear();
 | |
|                 if (!string.IsNullOrEmpty(this.Text))
 | |
|                 {
 | |
|                     if (!string.IsNullOrEmpty(_TextSeparator))
 | |
|                     {
 | |
|                         string[] tokens = this.Text.Split(new string[] { _TextSeparator }, StringSplitOptions.RemoveEmptyEntries);
 | |
|                         foreach (string item in tokens)
 | |
|                         {
 | |
|                             bool isNew = false;
 | |
|                             SelectToken(FindOrCreateToken(this.Text, out isNew));
 | |
|                         }
 | |
|                     }
 | |
|                     else
 | |
|                     {
 | |
|                         bool isNew = false;
 | |
|                         SelectToken(FindOrCreateToken(this.Text, out isNew));
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             base.OnTextChanged(e);
 | |
|         }
 | |
| 
 | |
|         private bool _UpdatingText = false;
 | |
|         private void UpdateText()
 | |
|         {
 | |
|             _UpdatingText = true;
 | |
|             string text = "";
 | |
|             for (int i = 0; i < _SelectedTokens.Count; i++)
 | |
|             {
 | |
|                 text += GetTokenText(_SelectedTokens[i]);
 | |
|                 if (i < _SelectedTokens.Count - 1)
 | |
|                     text += _TextSeparator;
 | |
|             }
 | |
| 
 | |
|             this.Text = text;
 | |
| 
 | |
|             _UpdatingText = false;
 | |
|         }
 | |
| 
 | |
|         private string _TextSeparator = ",";
 | |
|         /// <summary>
 | |
|         /// Indicates the character separator that is used to separate tokens when controls Text property is updated or parsed.
 | |
|         /// </summary>
 | |
|         [DefaultValue(","), Category("Behavior"), Description("Indicates the character separator that is used to separate tokens when controls Text property is updated or parsed.")]
 | |
|         public string TextSeparator
 | |
|         {
 | |
|             get { return _TextSeparator; }
 | |
|             set
 | |
|             {
 | |
|                 if (value != _TextSeparator)
 | |
|                 {
 | |
|                     string oldValue = _TextSeparator;
 | |
|                     _TextSeparator = value;
 | |
|                     OnTextSeparatorChanged(oldValue, value);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         /// <summary>
 | |
|         /// Called when TextSeparator property has changed.
 | |
|         /// </summary>
 | |
|         /// <param name="oldValue">Old property value</param>
 | |
|         /// <param name="newValue">New property value</param>
 | |
|         protected virtual void OnTextSeparatorChanged(string oldValue, string newValue)
 | |
|         {
 | |
|             //OnPropertyChanged(new PropertyChangedEventArgs("TextSeparator"));
 | |
|             UpdateText();
 | |
|         }
 | |
| 
 | |
|         [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
 | |
|         public override string Text
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return base.Text;
 | |
|             }
 | |
|             set
 | |
|             {
 | |
|                 base.Text = value;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private bool _DropDownButtonVisible = false;
 | |
|         /// <summary>
 | |
|         /// Indicates whether drop-down button which shows available token popup is displayed
 | |
|         /// </summary>
 | |
|         [DefaultValue(false), Category("Appearance"), Description("Indicates whether drop-down button which shows available token popup is displayed")]
 | |
|         public bool DropDownButtonVisible
 | |
|         {
 | |
|             get { return _DropDownButtonVisible; }
 | |
|             set
 | |
|             {
 | |
|                 if (value != _DropDownButtonVisible)
 | |
|                 {
 | |
|                     bool oldValue = _DropDownButtonVisible;
 | |
|                     _DropDownButtonVisible = value;
 | |
|                     OnDropDownButtonVisibleChanged(oldValue, value);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         /// <summary>
 | |
|         /// Called when DropDownButtonVisible property has changed.
 | |
|         /// </summary>
 | |
|         /// <param name="oldValue">Old property value</param>
 | |
|         /// <param name="newValue">New property value</param>
 | |
|         protected virtual void OnDropDownButtonVisibleChanged(bool oldValue, bool newValue)
 | |
|         {
 | |
|             //OnPropertyChanged(new PropertyChangedEventArgs("DropDownButtonVisible"));
 | |
|             UpdateButtons();
 | |
|             LayoutTokens();
 | |
|             Invalidate();
 | |
|         }
 | |
| 
 | |
|         private bool _CheckBoxesVisible = false;
 | |
|         /// <summary>
 | |
|         /// Indicates whether check-boxes are displayed on popup token selection list and used for token selection.
 | |
|         /// </summary>
 | |
|         [DefaultValue(false), Category("Behavior"), Description("Indicates whether check-boxes are displayed on popup token selection list and used for token selection.")]
 | |
|         public bool CheckBoxesVisible
 | |
|         {
 | |
|             get { return _CheckBoxesVisible; }
 | |
|             set
 | |
|             {
 | |
|                 if (value != _CheckBoxesVisible)
 | |
|                 {
 | |
|                     bool oldValue = _CheckBoxesVisible;
 | |
|                     _CheckBoxesVisible = value;
 | |
|                     OnCheckBoxesVisibleChanged(oldValue, value);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         /// <summary>
 | |
|         /// Called when CheckBoxesVisible property has changed.
 | |
|         /// </summary>
 | |
|         /// <param name="oldValue">Old property value</param>
 | |
|         /// <param name="newValue">New property value</param>
 | |
|         protected virtual void OnCheckBoxesVisibleChanged(bool oldValue, bool newValue)
 | |
|         {
 | |
|             //OnPropertyChanged(new PropertyChangedEventArgs("CheckBoxesVisible"));
 | |
| 
 | |
|         }
 | |
| 
 | |
|         private VisualGroup _ButtonGroup = null;
 | |
|         private VisualDropDownButton _DropDownButton = null;
 | |
|         private VisualUpDownButton _ScrollButton = null;
 | |
|         private int GetButtonHeight()
 | |
|         {
 | |
|             return GetSingleLineTextBoxHeight() - 4;
 | |
|         }
 | |
|         private void UpdateButtons()
 | |
|         {
 | |
|             if (!_DropDownButtonVisible && !_ScrollButton.Visible)
 | |
|                 _ButtonGroup.Visible = false;
 | |
|             else
 | |
|             {
 | |
|                 _ButtonGroup.Visible = true;
 | |
|                 _DropDownButton.Height = GetButtonHeight();
 | |
|             }
 | |
|             _DropDownButton.Visible = _DropDownButtonVisible;
 | |
|             _ButtonGroup.InvalidateArrange();
 | |
|         }
 | |
| 
 | |
|         protected virtual void CreateButtons()
 | |
|         {
 | |
|             _DropDownButton = new VisualDropDownButton();
 | |
|             _DropDownButton.MouseClick += DropDownButtonClick;
 | |
|             _DropDownButton.Visible = false;
 | |
|             _ButtonGroup.Items.Add(_DropDownButton);
 | |
| 
 | |
|             _ScrollButton = new VisualUpDownButton();
 | |
|             _ScrollButton.UpClick += ScrollButtonUpClick;
 | |
|             _ScrollButton.DownClick += ScrollButtonDownClick;
 | |
|             _ScrollButton.Visible = false;
 | |
|             _ButtonGroup.Items.Add(_ScrollButton);
 | |
|         }
 | |
| 
 | |
|         void ScrollButtonDownClick(object sender, EventArgs e)
 | |
|         {
 | |
|             if (Math.Abs(_AutoScrollPosition.Y) < (_VScrollBar.Maximum - _VScrollBar.LargeChange - 1))
 | |
|                 AutoScrollPosition = new Point(_AutoScrollPosition.X, _AutoScrollPosition.Y - _VScrollBar.SmallChange);
 | |
|         }
 | |
| 
 | |
|         void ScrollButtonUpClick(object sender, EventArgs e)
 | |
|         {
 | |
|             if (_AutoScrollPosition.Y < 0)
 | |
|                 AutoScrollPosition = new Point(_AutoScrollPosition.X, Math.Min(0, _AutoScrollPosition.Y + _VScrollBar.SmallChange));
 | |
|         }
 | |
| 
 | |
|         void DropDownButtonClick(object sender, MouseEventArgs e)
 | |
|         {
 | |
|             IsPopupOpen = !IsPopupOpen;
 | |
|         }
 | |
|         private void ButtonGroupRenderInvalid(object sender, EventArgs e)
 | |
|         {
 | |
|             Invalidate();
 | |
|         }
 | |
| 
 | |
|         private void ButtonGroupArrangeInvalid(object sender, EventArgs e)
 | |
|         {
 | |
|             Invalidate();
 | |
|         }
 | |
| 
 | |
|         private void ButtonGroupResetMouseHover(object sender, EventArgs e)
 | |
|         {
 | |
|             DevComponents.AdvTree.Interop.WinApi.ResetHover(this);
 | |
|         }
 | |
| 
 | |
|         private void PaintButtons(Graphics g)
 | |
|         {
 | |
|             PaintInfo p = CreatePaintInfo(g);
 | |
|             if (!_ButtonGroup.IsLayoutValid)
 | |
|             {
 | |
|                 _ButtonGroup.PerformLayout(p);
 | |
|             }
 | |
|             bool disposeStyle = false;
 | |
|             ElementStyle style = ElementStyleDisplay.GetElementStyle(_BackgroundStyle, out disposeStyle);
 | |
|             _ButtonGroup.RenderBounds = new Rectangle(this.Width - (ElementStyleLayout.RightWhiteSpace(style, eSpacePart.Border) + 1) - _ButtonGroup.Size.Width, ElementStyleLayout.TopWhiteSpace(style, eSpacePart.Border) + 1,
 | |
|                 _ButtonGroup.Size.Width, _ButtonGroup.Size.Height);
 | |
|             _ButtonGroup.ProcessPaint(p);
 | |
|             if (disposeStyle) style.Dispose();
 | |
|         }
 | |
|         private PaintInfo CreatePaintInfo(Graphics g)
 | |
|         {
 | |
|             PaintInfo p = new PaintInfo();
 | |
|             p.Graphics = g;
 | |
|             p.DefaultFont = this.Font;
 | |
|             p.ForeColor = this.ForeColor;
 | |
|             p.RenderOffset = new System.Drawing.Point();
 | |
|             Size s = this.Size;
 | |
|             bool disposeStyle = false;
 | |
|             ElementStyle style = ElementStyleDisplay.GetElementStyle(_BackgroundStyle, out disposeStyle);
 | |
|             s.Height -= (ElementStyleLayout.TopWhiteSpace(style, eSpacePart.Border) + ElementStyleLayout.BottomWhiteSpace(style, eSpacePart.Border)) + 2;
 | |
|             s.Width -= (ElementStyleLayout.LeftWhiteSpace(style, eSpacePart.Border) + ElementStyleLayout.RightWhiteSpace(style, eSpacePart.Border)) + 2;
 | |
|             p.AvailableSize = s;
 | |
|             p.ParentEnabled = this.Enabled;
 | |
|             p.MouseOver = _IsMouseOver || this.Focused;
 | |
|             if (disposeStyle) style.Dispose();
 | |
|             return p;
 | |
|         }
 | |
|         #endregion
 | |
| 
 | |
|         #region Tooltip Support
 | |
|         private DevComponents.DotNetBar.ToolTip _ToolTipWnd = null;
 | |
|         /// <summary>
 | |
|         /// Shows tooltip for this item.
 | |
|         /// </summary>
 | |
|         public virtual void ShowToolTip(EditToken token)
 | |
|         {
 | |
|             if (this.DesignMode || token==null || !token.IsSelected)
 | |
|                 return;
 | |
| 
 | |
|             if (this.Visible && this.ShowToolTips )
 | |
|             {
 | |
|                 string tooltip = token.Tooltip;
 | |
|                 if (!string.IsNullOrEmpty(tooltip))
 | |
|                 {
 | |
|                     if (_ToolTipWnd == null)
 | |
|                         _ToolTipWnd = new DevComponents.DotNetBar.ToolTip();
 | |
|                     _ToolTipWnd.Style = StyleManager.GetEffectiveStyle();
 | |
|                     _ToolTipWnd.Text = tooltip;
 | |
|                     _ToolTipWnd.ReferenceRectangle = new Rectangle(PointToScreen(token.Bounds.Location), token.Bounds.Size);
 | |
| 
 | |
|                     OnToolTipVisibleChanged(new EventArgs());
 | |
|                     _ToolTipWnd.ShowToolTip();
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         /// <summary>
 | |
|         /// Destroys tooltip window.
 | |
|         /// </summary>
 | |
|         internal protected void HideToolTip()
 | |
|         {
 | |
|             if (_ToolTipWnd != null)
 | |
|             {
 | |
|                 System.Drawing.Rectangle tipRect = _ToolTipWnd.Bounds;
 | |
|                 tipRect.Width += 5;
 | |
|                 tipRect.Height += 6;
 | |
| 
 | |
|                 OnToolTipVisibleChanged(new EventArgs());
 | |
|                 try
 | |
|                 {
 | |
|                     if (_ToolTipWnd != null)
 | |
|                     {
 | |
|                         _ToolTipWnd.Hide();
 | |
|                         _ToolTipWnd.Dispose();
 | |
|                         _ToolTipWnd = null;
 | |
|                     }
 | |
|                 }
 | |
|                 catch { }
 | |
|                 this.Invalidate();
 | |
|             }
 | |
|         }
 | |
|         /// <summary>
 | |
|         /// Occurs when item's tooltip visibility has changed.
 | |
|         /// </summary>
 | |
|         [System.ComponentModel.Description("Occurs when item's tooltip visibility has changed.")]
 | |
|         public event EventHandler ToolTipVisibleChanged;
 | |
|         private void OnToolTipVisibleChanged(EventArgs eventArgs)
 | |
|         {
 | |
|             EventHandler h = ToolTipVisibleChanged;
 | |
|             if (h != null)
 | |
|                 ToolTipVisibleChanged(this, eventArgs);
 | |
|         }
 | |
| 
 | |
|         private bool _ShowToolTips = true;
 | |
|         /// <summary>
 | |
|         /// Gets or sets whether tooltips are shown when mouse is over the selected token when Tooltip property is set.
 | |
|         /// </summary>
 | |
|         [DefaultValue(true), Category("Behavior"), Description("Indicates whether tooltips are shown when mouse is over the cell when Tooltip property is set.")]
 | |
|         public bool ShowToolTips
 | |
|         {
 | |
|             get { return _ShowToolTips; }
 | |
|             set
 | |
|             {
 | |
|                 _ShowToolTips = value;
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         #endregion
 | |
| 
 | |
|         #region IMessageHandlerClient
 | |
|         private bool _MessageHandlerInstalled = false;
 | |
|         bool IMessageHandlerClient.OnSysKeyDown(IntPtr hWnd, IntPtr wParam, IntPtr lParam)
 | |
|         {
 | |
|             return false;
 | |
|         }
 | |
| 
 | |
|         bool IMessageHandlerClient.OnSysKeyUp(IntPtr hWnd, IntPtr wParam, IntPtr lParam)
 | |
|         {
 | |
|             return false;
 | |
|         }
 | |
| 
 | |
|         bool IMessageHandlerClient.OnKeyDown(IntPtr hWnd, IntPtr wParam, IntPtr lParam)
 | |
|         {
 | |
|             return false;
 | |
|         }
 | |
| 
 | |
|         bool IMessageHandlerClient.OnMouseDown(IntPtr hWnd, IntPtr wParam, IntPtr lParam)
 | |
|         {
 | |
|             if (IsPopupOpen && _PopupController != null)
 | |
|             {
 | |
|                 if (!_PopupController.Bounds.Contains(Control.MousePosition))
 | |
|                 {
 | |
|                     IsPopupOpen = false;
 | |
|                 }
 | |
|             }
 | |
|             return false;
 | |
|         }
 | |
| 
 | |
|         bool IMessageHandlerClient.OnMouseMove(IntPtr hWnd, IntPtr wParam, IntPtr lParam)
 | |
|         {
 | |
|             return false;
 | |
|         }
 | |
| 
 | |
|         bool IMessageHandlerClient.OnMouseWheel(IntPtr hWnd, IntPtr wParam, IntPtr lParam)
 | |
|         {
 | |
|             return false;
 | |
|         }
 | |
| 
 | |
|         bool IMessageHandlerClient.IsModal
 | |
|         {
 | |
|             get { return false; }
 | |
|         }
 | |
|         #endregion
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Delegate for the ValidateTokenEvent event.
 | |
|     /// </summary>
 | |
|     public delegate void ValidateTokenEventHandler(object sender, ValidateTokenEventArgs ea);
 | |
|     /// <summary>
 | |
|     /// Arguments for the ValidateTokenEvent event.
 | |
|     /// </summary>
 | |
|     public class ValidateTokenEventArgs : EventArgs
 | |
|     {
 | |
|         /// <summary>
 | |
|         /// Indicates whether validated token is valid. Default value is true. When you set this property to false the token being validated will be discared.
 | |
|         /// </summary>
 | |
|         public bool IsValid = true;
 | |
|         /// <summary>
 | |
|         /// Indicates the Token that will be accepted by the control if IsValid=true.
 | |
|         /// </summary>
 | |
|         public EditToken Token = null;
 | |
|         /// <summary>
 | |
|         /// Indicates whether token is newly created. When false it means that token was taken from Tokens collection.
 | |
|         /// </summary>
 | |
|         public readonly bool IsNewToken;
 | |
|         /// <summary>
 | |
|         /// Initializes a new instance of the ValidateTokenEventArgs class.
 | |
|         /// </summary>
 | |
|         /// <param name="token"></param>
 | |
|         public ValidateTokenEventArgs(EditToken token, bool isNewToken)
 | |
|         {
 | |
|             Token = token;
 | |
|             IsNewToken = isNewToken;
 | |
|         }
 | |
|     }
 | |
|     /// <summary>
 | |
|     /// Delegate for RemovingToken event.
 | |
|     /// </summary>
 | |
|     public delegate void RemovingTokenEventHandler(object sender, RemovingTokenEventArgs ea);
 | |
|     /// <summary>
 | |
|     /// Defines event arguments for RemovingToken event.
 | |
|     /// </summary>
 | |
|     public class RemovingTokenEventArgs : EventArgs
 | |
|     {
 | |
|         /// <summary>
 | |
|         /// Indicates the Token that will be removed.
 | |
|         /// </summary>
 | |
|         public readonly EditToken Token;
 | |
|         /// <summary>
 | |
|         /// Set to true to cancel removal of the token.
 | |
|         /// </summary>
 | |
|         public bool Cancel = false;
 | |
|         /// <summary>
 | |
|         /// Indicates the source of the event.
 | |
|         /// </summary>
 | |
|         public readonly eEventSource EventSource;
 | |
|         /// <summary>
 | |
|         /// Initializes a new instance of the RemovingTokenEventArgs class.
 | |
|         /// </summary>
 | |
|         /// <param name="token"></param>
 | |
|         public RemovingTokenEventArgs(EditToken token, eEventSource eventSource)
 | |
|         {
 | |
|             Token = token;
 | |
|             EventSource = eventSource;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Specifies the filter behavior on token editor popup list.
 | |
|     /// </summary>
 | |
|     public enum eTokenFilterBehavior
 | |
|     {
 | |
|         /// <summary>
 | |
|         /// Token text is searched for the match.
 | |
|         /// </summary>
 | |
|         Text,
 | |
|         /// <summary>
 | |
|         /// Token value is searched for the match.
 | |
|         /// </summary>
 | |
|         Value,
 | |
|         /// <summary>
 | |
|         /// Both token text and value are searched for the match.
 | |
|         /// </summary>
 | |
|         TextAndValue
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Delegate for TokenEditor.BeforePopupOpen event.
 | |
|     /// </summary>
 | |
|     public delegate void TokenEditorPopupEventHandler(object sender, TokenEditorPopupEventArgs ea);
 | |
|     /// <summary>
 | |
|     /// Defines event arguments for BeforePopupOpen event.
 | |
|     /// </summary>
 | |
|     public class TokenEditorPopupEventArgs : EventArgs
 | |
|     {
 | |
|         /// <summary>
 | |
|         /// Gets or sets the screen location of the popup in relation to the TokenEditor control.
 | |
|         /// </summary>
 | |
|         public Point PopupLocation = Point.Empty;
 | |
|         /// <summary>
 | |
|         /// Gets the suggested popup size.
 | |
|         /// </summary>
 | |
|         public readonly Size PopupSize;
 | |
|         /// <summary>
 | |
|         /// Initializes a new instance of the TokenEditorPopupEventArgs class.
 | |
|         /// </summary>
 | |
|         /// <param name="token"></param>
 | |
|         public TokenEditorPopupEventArgs(Point popupLocation, Size popupSize)
 | |
|         {
 | |
|             PopupLocation = popupLocation;
 | |
|             PopupSize = popupSize;
 | |
|         }
 | |
|     }
 | |
| }
 |