1 //
2 // ToolStripTextBox.cs
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 //
23 // Copyright (c) 2006 Jonathan Pobst
24 //
25 // Authors:
26 //	Jonathan Pobst (monkey@jpobst.com)
27 //
28 
29 using System.Drawing;
30 using System.ComponentModel;
31 using System.Windows.Forms.Design;
32 using System.Runtime.InteropServices;
33 
34 namespace System.Windows.Forms
35 {
36 	[ToolStripItemDesignerAvailability (ToolStripItemDesignerAvailability.ToolStrip | ToolStripItemDesignerAvailability.MenuStrip | ToolStripItemDesignerAvailability.ContextMenuStrip)]
37 	public class ToolStripTextBox : ToolStripControlHost
38 	{
39 		private BorderStyle border_style;
40 
41 		#region Public Constructors
ToolStripTextBox()42 		public ToolStripTextBox () : base (new ToolStripTextBoxControl ())
43 		{
44 			ToolStripTextBoxControl text_box = TextBox as ToolStripTextBoxControl;
45 			text_box.OwnerItem = this;
46 			text_box.border_style = BorderStyle.None;
47 			text_box.TopMargin = 3; // need to explicitly set the margin
48 			text_box.Border = BorderStyle.Fixed3D; // ToolStripTextBoxControl impl, not TextBox
49 			this.border_style = BorderStyle.Fixed3D;
50 		}
51 
52 		[EditorBrowsable (EditorBrowsableState.Never)]
ToolStripTextBox(Control c)53 		public ToolStripTextBox (Control c) : base (c)
54 		{
55 			throw new NotSupportedException ("This construtor cannot be used.");
56 		}
57 
ToolStripTextBox(string name)58 		public ToolStripTextBox (string name) : this ()
59 		{
60 			base.Name = name;
61 		}
62 		#endregion
63 
64 		#region Public Properties
65 		[DefaultValue (false)]
66 		public bool AcceptsReturn {
67 			get { return this.TextBox.AcceptsReturn; }
68 			set { this.TextBox.AcceptsReturn = value; }
69 		}
70 
71 		[DefaultValue (false)]
72 		public bool AcceptsTab {
73 			get { return this.TextBox.AcceptsTab; }
74 			set { this.TextBox.AcceptsTab = value; }
75 		}
76 
77 		[MonoTODO ("AutoCompletion algorithm is currently not implemented.")]
78 		[Browsable (true)]
79 		[Localizable (true)]
80 		[EditorBrowsable (EditorBrowsableState.Always)]
81 		[DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
82 		[Editor ("System.Windows.Forms.Design.ListControlStringCollectionEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
83 		public AutoCompleteStringCollection AutoCompleteCustomSource {
84 			get { return this.TextBox.AutoCompleteCustomSource; }
85 			set { this.TextBox.AutoCompleteCustomSource = value; }
86 		}
87 
88 		[MonoTODO("AutoCompletion algorithm is currently not implemented.")]
89 		[Browsable (true)]
90 		[DefaultValue (AutoCompleteMode.None)]
91 		[EditorBrowsable (EditorBrowsableState.Always)]
92 		public AutoCompleteMode AutoCompleteMode {
93 			get { return this.TextBox.AutoCompleteMode; }
94 			set { this.TextBox.AutoCompleteMode = value; }
95 		}
96 
97 		[MonoTODO("AutoCompletion algorithm is currently not implemented.")]
98 		[Browsable (true)]
99 		[DefaultValue (AutoCompleteSource.None)]
100 		[EditorBrowsable (EditorBrowsableState.Always)]
101 		public AutoCompleteSource AutoCompleteSource {
102 			get { return this.TextBox.AutoCompleteSource; }
103 			set { this.TextBox.AutoCompleteSource = value; }
104 		}
105 
106 		[Browsable (false)]
107 		[EditorBrowsable (EditorBrowsableState.Never)]
108 		[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
109 		public override Image BackgroundImage {
110 			get { return base.BackgroundImage; }
111 			set { base.BackgroundImage = value; }
112 		}
113 
114 		[Browsable (false)]
115 		[EditorBrowsable (EditorBrowsableState.Never)]
116 		[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
117 		public override ImageLayout BackgroundImageLayout {
118 			get { return base.BackgroundImageLayout; }
119 			set { base.BackgroundImageLayout = value; }
120 		}
121 
122 		[DefaultValue (BorderStyle.Fixed3D)]
123 		[DispId (-504)]
124 		public BorderStyle BorderStyle {
125 			get { return this.border_style; }
126 			set {
127 				if (this.border_style != value) {
128 					this.border_style = value;
129 					(base.Control as ToolStripTextBoxControl).Border = value;
130 					this.OnBorderStyleChanged (EventArgs.Empty);
131 				}
132 			}
133 		}
134 
135 		[Browsable (false)]
136 		[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
137 		public bool CanUndo {
138 			get { return this.TextBox.CanUndo; }
139 		}
140 
141 		[DefaultValue (CharacterCasing.Normal)]
142 		public CharacterCasing CharacterCasing {
143 			get { return this.TextBox.CharacterCasing; }
144 			set { this.TextBox.CharacterCasing = value; }
145 		}
146 
147 		[DefaultValue (true)]
148 		public bool HideSelection {
149 			get { return this.TextBox.HideSelection; }
150 			set { this.TextBox.HideSelection = value; }
151 		}
152 
153 		[Localizable (true)]
154 		[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
155 		[Editor ("System.Windows.Forms.Design.StringArrayEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
156 		public string[] Lines {
157 			get { return this.TextBox.Lines; }
158 			set { this.TextBox.Lines = value; }
159 		}
160 
161 		[Localizable (true)]
162 		[DefaultValue (32767)]
163 		public int MaxLength {
164 			get { return this.TextBox.MaxLength; }
165 			set { this.TextBox.MaxLength = value; }
166 		}
167 
168 		[Browsable (false)]
169 		[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
170 		public bool Modified {
171 			get { return this.TextBox.Modified; }
172 			set { this.TextBox.Modified = value; }
173 		}
174 
175 		[Localizable (true)]
176 		[Browsable (false)]
177 		[EditorBrowsable (EditorBrowsableState.Never)]
178 		[DefaultValue (false)]
179 		[RefreshProperties (RefreshProperties.All)]
180 		public bool Multiline {
181 			get { return this.TextBox.Multiline; }
182 			set { this.TextBox.Multiline = value; }
183 		}
184 
185 		[DefaultValue (false)]
186 		public bool ReadOnly {
187 			get { return this.TextBox.ReadOnly; }
188 			set { this.TextBox.ReadOnly = value; }
189 		}
190 
191 		[Browsable (false)]
192 		[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
193 		public string SelectedText {
194 			get { return this.TextBox.SelectedText; }
195 			set { this.TextBox.SelectedText = value; }
196 		}
197 
198 		[Browsable (false)]
199 		[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
200 		public int SelectionLength {
201 			get { return this.TextBox.SelectionLength == -1 ? 0 : this.TextBox.SelectionLength; }
202 			set { this.TextBox.SelectionLength = value; }
203 		}
204 
205 		[Browsable (false)]
206 		[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
207 		public int SelectionStart {
208 			get { return this.TextBox.SelectionStart; }
209 			set { this.TextBox.SelectionStart = value; }
210 		}
211 
212 		[DefaultValue (true)]
213 		public bool ShortcutsEnabled {
214 			get { return this.TextBox.ShortcutsEnabled; }
215 			set { this.TextBox.ShortcutsEnabled = value; }
216 		}
217 
218 		[Browsable (false)]
219 		[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
220 		public TextBox TextBox {
221 			get { return (TextBox)base.Control; }
222 		}
223 
224 		[Localizable (true)]
225 		[DefaultValue (HorizontalAlignment.Left)]
226 		public HorizontalAlignment TextBoxTextAlign {
227 			get { return this.TextBox.TextAlign; }
228 			set { this.TextBox.TextAlign = value; }
229 		}
230 
231 		[Browsable (false)]
232 		public int TextLength {
233 			get { return this.TextBox.TextLength; }
234 		}
235 
236 		[Localizable (true)]
237 		[Browsable (false)]
238 		[EditorBrowsable (EditorBrowsableState.Never)]
239 		[DefaultValue (true)]
240 		public bool WordWrap {
241 			get { return this.TextBox.WordWrap; }
242 			set { this.TextBox.WordWrap = value; }
243 		}
244 		#endregion
245 
246 		#region Protected Properties
247 		protected internal override Padding DefaultMargin { get { return new Padding (1, 0, 1, 0); } }
248 		protected override Size DefaultSize { get { return new Size (100, 22); } }
249 		#endregion
250 
251 		#region Public Methods
AppendText(string text)252 		public void AppendText (string text)
253 		{
254 			this.TextBox.AppendText (text);
255 		}
256 
Clear()257 		public void Clear ()
258 		{
259 			this.TextBox.Clear ();
260 		}
261 
ClearUndo()262 		public void ClearUndo ()
263 		{
264 			this.TextBox.ClearUndo ();
265 		}
266 
Copy()267 		public void Copy ()
268 		{
269 			this.TextBox.Copy ();
270 		}
271 
Cut()272 		public void Cut ()
273 		{
274 			this.TextBox.Cut ();
275 		}
276 
DeselectAll()277 		public void DeselectAll ()
278 		{
279 			this.TextBox.DeselectAll ();
280 		}
281 
GetCharFromPosition(Point pt)282 		public char GetCharFromPosition (Point pt)
283 		{
284 			return this.TextBox.GetCharFromPosition (pt);
285 		}
286 
GetCharIndexFromPosition(Point pt)287 		public int GetCharIndexFromPosition (Point pt)
288 		{
289 			return this.TextBox.GetCharIndexFromPosition (pt);
290 		}
291 
GetFirstCharIndexFromLine(int lineNumber)292 		public int GetFirstCharIndexFromLine (int lineNumber)
293 		{
294 			return this.TextBox.GetFirstCharIndexFromLine (lineNumber);
295 		}
296 
GetFirstCharIndexOfCurrentLine()297 		public int GetFirstCharIndexOfCurrentLine ()
298 		{
299 			return this.TextBox.GetFirstCharIndexOfCurrentLine ();
300 		}
301 
GetLineFromCharIndex(int index)302 		public int GetLineFromCharIndex (int index)
303 		{
304 			return this.TextBox.GetLineFromCharIndex (index);
305 		}
306 
GetPositionFromCharIndex(int index)307 		public Point GetPositionFromCharIndex (int index)
308 		{
309 			return this.TextBox.GetPositionFromCharIndex (index);
310 		}
311 
GetPreferredSize(Size constrainingSize)312 		public override Size GetPreferredSize (Size constrainingSize)
313 		{
314 			return base.GetPreferredSize (constrainingSize);
315 		}
316 
Paste()317 		public void Paste ()
318 		{
319 			this.TextBox.Paste ();
320 		}
321 
ScrollToCaret()322 		public void ScrollToCaret ()
323 		{
324 			this.TextBox.ScrollToCaret ();
325 		}
326 
Select(int start, int length)327 		public void Select (int start, int length)
328 		{
329 			this.TextBox.Select (start, length);
330 		}
331 
SelectAll()332 		public void SelectAll ()
333 		{
334 			this.TextBox.SelectAll ();
335 		}
336 
Undo()337 		public void Undo ()
338 		{
339 			this.TextBox.Undo ();
340 		}
341 		#endregion
342 
343 		#region Protected Methods
OnAcceptsTabChanged(EventArgs e)344 		protected virtual void OnAcceptsTabChanged (EventArgs e)
345 		{
346 			EventHandler eh = (EventHandler)Events [AcceptsTabChangedEvent];
347 			if (eh != null)
348 				eh (this, e);
349 		}
350 
OnBorderStyleChanged(EventArgs e)351 		protected virtual void OnBorderStyleChanged (EventArgs e)
352 		{
353 			EventHandler eh = (EventHandler)Events [BorderStyleChangedEvent];
354 			if (eh != null)
355 				eh (this, e);
356 		}
357 
OnHideSelectionChanged(EventArgs e)358 		protected virtual void OnHideSelectionChanged (EventArgs e)
359 		{
360 			EventHandler eh = (EventHandler)Events [HideSelectionChangedEvent];
361 			if (eh != null)
362 				eh (this, e);
363 		}
364 
OnModifiedChanged(EventArgs e)365 		protected virtual void OnModifiedChanged (EventArgs e)
366 		{
367 			EventHandler eh = (EventHandler)Events [ModifiedChangedEvent];
368 			if (eh != null)
369 				eh (this, e);
370 		}
371 
OnMultilineChanged(EventArgs e)372 		protected virtual void OnMultilineChanged (EventArgs e)
373 		{
374 			EventHandler eh = (EventHandler)Events [MultilineChangedEvent];
375 			if (eh != null)
376 				eh (this, e);
377 		}
378 
OnReadOnlyChanged(EventArgs e)379 		protected virtual void OnReadOnlyChanged (EventArgs e)
380 		{
381 			EventHandler eh = (EventHandler)Events [ReadOnlyChangedEvent];
382 			if (eh != null)
383 				eh (this, e);
384 		}
385 
OnSubscribeControlEvents(Control control)386 		protected override void OnSubscribeControlEvents (Control control)
387 		{
388 			base.OnSubscribeControlEvents (control);
389 
390 			this.TextBox.AcceptsTabChanged += new EventHandler (HandleAcceptsTabChanged);
391 			this.TextBox.HideSelectionChanged += new EventHandler (HandleHideSelectionChanged);
392 			this.TextBox.ModifiedChanged += new EventHandler (HandleModifiedChanged);
393 			this.TextBox.MultilineChanged += new EventHandler (HandleMultilineChanged);
394 			this.TextBox.ReadOnlyChanged += new EventHandler (HandleReadOnlyChanged);
395 			this.TextBox.TextAlignChanged += new EventHandler (HandleTextAlignChanged);
396 			this.TextBox.TextChanged += new EventHandler (HandleTextChanged);
397 		}
398 
OnUnsubscribeControlEvents(Control control)399 		protected override void OnUnsubscribeControlEvents (Control control)
400 		{
401 			base.OnUnsubscribeControlEvents (control);
402 		}
403 		#endregion
404 
405 		#region Public Events
406 		static object AcceptsTabChangedEvent = new object ();
407 		static object BorderStyleChangedEvent = new object ();
408 		static object HideSelectionChangedEvent = new object ();
409 		static object ModifiedChangedEvent = new object ();
410 		static object MultilineChangedEvent = new object ();
411 		static object ReadOnlyChangedEvent = new object ();
412 		static object TextBoxTextAlignChangedEvent = new object ();
413 
414 		public event EventHandler AcceptsTabChanged {
415 			add { Events.AddHandler (AcceptsTabChangedEvent, value); }
416 			remove {Events.RemoveHandler (AcceptsTabChangedEvent, value); }
417 		}
418 		public event EventHandler BorderStyleChanged {
419 			add { Events.AddHandler (BorderStyleChangedEvent, value); }
420 			remove {Events.RemoveHandler (BorderStyleChangedEvent, value); }
421 		}
422 		public event EventHandler HideSelectionChanged {
423 			add { Events.AddHandler (HideSelectionChangedEvent, value); }
424 			remove {Events.RemoveHandler (HideSelectionChangedEvent, value); }
425 		}
426 		public event EventHandler ModifiedChanged {
427 			add { Events.AddHandler (ModifiedChangedEvent, value); }
428 			remove {Events.RemoveHandler (ModifiedChangedEvent, value); }
429 		}
430 		[Browsable (false)]
431 		[EditorBrowsable (EditorBrowsableState.Never)]
432 		public event EventHandler MultilineChanged {
433 			add { Events.AddHandler (MultilineChangedEvent, value); }
434 			remove {Events.RemoveHandler (MultilineChangedEvent, value); }
435 		}
436 		public event EventHandler ReadOnlyChanged {
437 			add { Events.AddHandler (ReadOnlyChangedEvent, value); }
438 			remove {Events.RemoveHandler (ReadOnlyChangedEvent, value); }
439 		}
440 		public event EventHandler TextBoxTextAlignChanged {
441 			add { Events.AddHandler (TextBoxTextAlignChangedEvent, value); }
442 			remove {Events.RemoveHandler (TextBoxTextAlignChangedEvent, value); }
443 		}
444 		#endregion
445 
446 		#region Private Methods
HandleTextAlignChanged(object sender, EventArgs e)447 		private void HandleTextAlignChanged (object sender, EventArgs e)
448 		{
449 			EventHandler eh = (EventHandler)(Events [TextBoxTextAlignChangedEvent]);
450 			if (eh != null)
451 				eh (this, e);
452 		}
453 
HandleReadOnlyChanged(object sender, EventArgs e)454 		private void HandleReadOnlyChanged (object sender, EventArgs e)
455 		{
456 			OnReadOnlyChanged (e);
457 		}
458 
HandleMultilineChanged(object sender, EventArgs e)459 		private void HandleMultilineChanged (object sender, EventArgs e)
460 		{
461 			OnMultilineChanged (e);
462 		}
463 
HandleModifiedChanged(object sender, EventArgs e)464 		private void HandleModifiedChanged (object sender, EventArgs e)
465 		{
466 			OnModifiedChanged (e);
467 		}
468 
HandleHideSelectionChanged(object sender, EventArgs e)469 		private void HandleHideSelectionChanged (object sender, EventArgs e)
470 		{
471 			OnHideSelectionChanged (e);
472 		}
473 
HandleAcceptsTabChanged(object sender, EventArgs e)474 		private void HandleAcceptsTabChanged (object sender, EventArgs e)
475 		{
476 			OnAcceptsTabChanged (e);
477 		}
478 
HandleTextChanged(object sender, EventArgs e)479 		private void HandleTextChanged (object sender, EventArgs e)
480 		{
481 			OnTextChanged (e);
482 		}
483 		#endregion
484 
485 		private class ToolStripTextBoxControl : TextBox
486 		{
487 			private BorderStyle border;
488 			private Timer tooltip_timer;
489 			private ToolTip tooltip_window;
490 			private ToolStripItem owner_item;
491 
ToolStripTextBoxControl()492 			public ToolStripTextBoxControl () : base ()
493 			{
494 			}
495 
OnLostFocus(EventArgs e)496 			protected override void OnLostFocus (EventArgs e)
497 			{
498 				base.OnLostFocus (e);
499 				Invalidate ();
500 			}
501 
OnMouseEnter(EventArgs e)502 			protected override void OnMouseEnter (EventArgs e)
503 			{
504 				base.OnMouseEnter (e);
505 				Invalidate ();
506 
507 				if (ShowToolTips)
508 					ToolTipTimer.Start ();
509 
510 			}
511 
OnMouseLeave(EventArgs e)512 			protected override void OnMouseLeave (EventArgs e)
513 			{
514 				base.OnMouseLeave (e);
515 				Invalidate ();
516 
517 				ToolTipTimer.Stop ();
518 				ToolTipWindow.Hide (this);
519 			}
520 
OnPaintInternal(PaintEventArgs e)521 			internal override void OnPaintInternal (PaintEventArgs e)
522 			{
523 				base.OnPaintInternal (e);
524 
525 				if ((this.Focused || this.Entered || border == BorderStyle.FixedSingle) && border != BorderStyle.None) {
526 					ToolStripRenderer tsr = (this.Parent as ToolStrip).Renderer;
527 
528 					if (tsr is ToolStripProfessionalRenderer)
529 						using (Pen p = new Pen ((tsr as ToolStripProfessionalRenderer).ColorTable.ButtonSelectedBorder))
530 							e.Graphics.DrawRectangle (p, new Rectangle (0, 0, this.Width - 1, this.Height - 1));
531 				}
532 			}
533 
534 			internal BorderStyle Border {
535 				set {
536 					border = value;
537 					Invalidate ();
538 				}
539 			}
540 
541 			internal ToolStripItem OwnerItem {
542 				set { owner_item = value; }
543 			}
544 
545 			#region Stuff for ToolTips
546 			private bool ShowToolTips {
547 				get {
548 					if (Parent == null)
549 						return false;
550 
551 					return (Parent as ToolStrip).ShowItemToolTips;
552 				}
553 			}
554 
555 			private Timer ToolTipTimer {
556 				get {
557 					if (tooltip_timer == null) {
558 						tooltip_timer = new Timer ();
559 						tooltip_timer.Enabled = false;
560 						tooltip_timer.Interval = 500;
561 						tooltip_timer.Tick += new EventHandler (ToolTipTimer_Tick);
562 					}
563 
564 					return tooltip_timer;
565 				}
566 			}
567 
568 			private ToolTip ToolTipWindow {
569 				get {
570 					if (tooltip_window == null)
571 						tooltip_window = new ToolTip ();
572 
573 					return tooltip_window;
574 				}
575 			}
576 
ToolTipTimer_Tick(object o, EventArgs args)577 			private void ToolTipTimer_Tick (object o, EventArgs args)
578 			{
579 				string tooltip = owner_item.GetToolTip ();
580 
581 				if (!string.IsNullOrEmpty (tooltip))
582 					ToolTipWindow.Present (this, tooltip);
583 
584 				ToolTipTimer.Stop ();
585 			}
586 			#endregion
587 		}
588 	}
589 }
590