* TreeView.cs: Don't draw the selected node when we lose
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / LinkLabel.cs
1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
8 //
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 //
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 //
20 // Copyright (c) 2004-2005 Novell, Inc.
21 //
22 // Authors:
23 //      Jordi Mas i Hernandez, jordi@ximian.com
24 //
25 // Based on work by:
26 //      Daniel Carrera, dcarrera@math.toronto.edu (stubbed out)
27 //      Jaak Simm (jaaksimm@firm.ee) (stubbed out)
28 //
29
30 // COMPLETE
31
32
33 using System.ComponentModel;
34 using System.Collections;
35 using System.Drawing;
36 using System.Drawing.Drawing2D;
37
38 namespace System.Windows.Forms
39 {
40         [DefaultEvent("LinkClicked")]
41         public class LinkLabel : Label, IButtonControl
42         {
43                 /* Encapsulates a piece of text (regular or link)*/
44                 internal class Piece
45                 {
46                         public string           text;
47                         public int              start;
48                         public int              end;
49                         public LinkLabel.Link   link;   // Empty link indicates regular text
50                         public Rectangle        rect;
51                         public bool             clicked;
52                         public bool             focused;
53
54                         public Piece ()
55                         {
56                                 start = end = 0;
57                                 link = null;
58                                 clicked = false;
59                                 focused = false;                                
60                         }
61                 }
62
63                 private Color active_link;
64                 private Color disabled_link;
65                 private Color link_color;
66                 private Color visited_color;
67                 private LinkArea link_area;
68                 private LinkBehavior link_behavior;
69                 private LinkCollection link_collection;
70                 private bool link_visited;              
71                 private bool link_click;
72                 internal Piece[] pieces;
73                 internal int num_pieces;
74                 internal Font link_font;                
75                 private Cursor override_cursor;
76                 private DialogResult dialog_result;
77
78                 #region Events
79                 public event LinkLabelLinkClickedEventHandler LinkClicked;
80                 #endregion // Events
81
82                 public LinkLabel ()
83                 {
84                         LinkArea = new LinkArea (0, -1);
85                         link_behavior = LinkBehavior.SystemDefault;
86                         link_visited = false;
87                         link_click = false;
88                         pieces = null;
89                         num_pieces = 0;
90                         link_font = null;                       
91
92                         ActiveLinkColor = Color.Red;
93                         DisabledLinkColor = ThemeEngine.Current.ColorGrayText;
94                         LinkColor = Color.FromArgb (255, 0, 0, 255);
95                         VisitedLinkColor = Color.FromArgb (255, 128, 0, 128);
96                         SetStyle (ControlStyles.Selectable, false);
97                         SetStyle (ControlStyles.Opaque, true);
98                 }
99
100                 #region Public Properties
101
102                 public Color ActiveLinkColor {
103                         get { return active_link;}
104                         set {
105                                 if (active_link == value)
106                                         return;
107
108                                 active_link = value;
109                                 Refresh ();
110                         }
111                 }
112
113                 public Color DisabledLinkColor {
114
115                         get { return disabled_link;}
116                         set {
117                                 if (disabled_link == value)
118                                         return;
119
120                                 disabled_link = value;
121                                 Refresh ();
122                         }
123                 }
124
125                 public Color LinkColor {
126                         get { return link_color;}
127                         set {
128                                 if (link_color == value)
129                                         return;
130
131                                 link_color = value;
132                                 Refresh ();
133                         }
134                 }
135
136                 public Color VisitedLinkColor {
137                         get { return visited_color;}
138                         set {
139                                 if (visited_color == value)
140                                         return;
141
142                                 visited_color = value;
143                                 Refresh ();
144                         }
145                 }
146
147                 [Localizable (true)]
148                 [Editor ("System.Windows.Forms.Design.LinkAreaEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]                           
149                 public LinkArea LinkArea {
150                         get { return link_area;}
151                         set {
152
153                                 if (value.Start <0 || value.Length < -1)
154                                         throw new ArgumentException ();
155
156                                 if (!value.IsEmpty)
157                                         Links.Add (value.Start, value.Length);
158
159                                 link_area = value;
160                                 Refresh ();
161                         }
162                 }
163                                 
164                 [DefaultValue (LinkBehavior.SystemDefault)]
165                 public LinkBehavior LinkBehavior {
166
167                         get { return link_behavior;}
168                         set {
169                                 if (link_behavior == value)
170                                         return;
171
172                                 link_behavior = value;
173                                 Refresh ();
174                         }
175                 }
176         
177                 [Browsable (false)]
178                 [EditorBrowsable (EditorBrowsableState.Advanced)]
179                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
180                 public LinkLabel.LinkCollection Links {
181                         get {
182                                 if (link_collection == null)
183                                         link_collection = new LinkCollection (this);
184                                         
185                                 return link_collection;
186                         }
187                 }
188
189                 [DefaultValue (false)]
190                 public bool LinkVisited {
191                         get { return link_visited;}
192                         set {
193                                 if (link_visited == value)
194                                         return;
195
196                                 link_visited = value;
197                                 Refresh ();
198                         }
199                 }
200                 
201                 protected Cursor OverrideCursor {
202                         get { return override_cursor;}
203                         set { override_cursor = value;}
204                 }
205
206                 [RefreshProperties(RefreshProperties.Repaint)]
207                 public override string Text {
208                         get { return base.Text; }
209                         set {
210                                 if (base.Text == value)
211                                         return;
212
213                                 base.Text = value;
214                                 CreateLinkPieces ();                            
215                         }
216                 }
217
218                 #endregion // Public Properties
219
220                 DialogResult IButtonControl.DialogResult {
221                         get { return dialog_result; }
222                         set { dialog_result = value; }
223                 }
224
225
226                 void IButtonControl.NotifyDefault (bool value)
227                 {
228
229                 }
230
231                 void IButtonControl.PerformClick ()
232                 {
233                         
234                 }
235
236                 #region Public Methods
237                 protected override AccessibleObject CreateAccessibilityInstance ()
238                 {
239                         return base.CreateAccessibilityInstance();
240                 }
241
242                 protected override void CreateHandle ()
243                 {
244                         base.CreateHandle ();
245                         CreateLinkFont ();
246                         CreateLinkPieces ();                    
247                 }
248
249                 protected override void OnEnabledChanged (EventArgs e)
250                 {
251                         base.OnEnabledChanged (e);
252                         Refresh ();
253                 }
254
255                 protected override void OnFontChanged (EventArgs e)
256                 {
257                         base.OnFontChanged (e);
258                         CreateLinkFont ();
259                         CreateLinkPieces ();
260                 }
261
262                 protected override void OnGotFocus (EventArgs e)
263                 {
264                         base.OnGotFocus (e);                    
265                         
266                         // Set focus to the first enabled link piece                    
267                         for (int i = 0; i < num_pieces; i++) {
268                                 if (pieces[i].link != null && pieces[i].link.Enabled) {
269                                          pieces[i].focused = true;
270                                          Invalidate (pieces[i].rect);
271                                          break;
272                                 }
273                         }                       
274                 }
275
276                 protected override void OnKeyDown (KeyEventArgs e)
277                 {       
278                         base.OnKeyDown(e);              
279                         
280                         // Set focus to the next link piece
281                         if (e.KeyCode == Keys.Tab || e.KeyCode == Keys.Right) {
282                                 for (int i = 0; i < num_pieces; i++) {
283                                         if (pieces[i].focused) {
284                                                 pieces[i].focused = false;
285                                                 Invalidate (pieces[i].rect);
286                                                 
287                                                 for (int n = i + 1; n < num_pieces; n++) {
288                                                         if (pieces[n].link != null && pieces[n].link.Enabled) {                                                 
289                                                                 pieces[n].focused = true;
290                                                                 e.Handled = true;
291                                                                 Invalidate (pieces[n].rect);
292                                                                 return;
293                                                         }               
294                                                 }
295                                         }
296                                 }
297                         } else if (e.KeyCode == Keys.Return) {                                                                                  
298                                 for (int i = 0; i < num_pieces; i++) {
299                                         if (pieces[i].focused && pieces[i].link != null) {
300                                                 OnLinkClicked (new LinkLabelLinkClickedEventArgs (pieces[i].link));
301                                                 break;
302                                         }
303                                 }
304                         }
305                 }
306
307                 protected virtual void OnLinkClicked (LinkLabelLinkClickedEventArgs e)
308                 {
309                         if (LinkClicked != null)
310                                 LinkClicked (this, e);
311                 }
312
313                 protected override void OnLostFocus (EventArgs e)
314                 {
315                         base.OnLostFocus (e);                   
316                         
317                         // Clean focus in link pieces
318                         for (int i = 0; i < num_pieces; i++) {
319                                 if (pieces[i].focused) {
320                                         pieces[i].focused = false;                                      
321                                 }
322                         }
323                         
324                         Refresh ();
325                 }
326
327                 protected override void OnMouseDown (MouseEventArgs e)
328                 {
329                         if (!Enabled) return;
330
331                         base.OnMouseDown (e);
332                         this.Capture = true;
333
334                         for (int i = 0; i < num_pieces; i++) {
335                                 if (pieces[i].rect.Contains (e.X, e.Y)) {
336                                         if (pieces[i].link!= null) {
337                                                 pieces[i].clicked = true;
338                                                 Invalidate (pieces[i].rect);
339                                         }
340                                         break;
341                                 }
342                         }
343                 }
344
345                 protected override void OnMouseLeave(EventArgs e)
346                 {
347                         if (!Enabled) return;
348
349                         base.OnMouseLeave (e);
350                 }
351
352                 protected override void OnMouseMove (MouseEventArgs e)
353                 {
354                         base.OnMouseMove (e);
355                         
356                         Link link = PointInLink (e.X, e.Y);
357                         
358                         if (link == null) {
359                                 Cursor = Cursors.Default;
360                                 bool changed = false;
361                                 if (link_behavior == LinkBehavior.HoverUnderline) {
362                                         for (int i = 0; i < Links.Count; i++) {
363                                                 if (Links[i].Hoovered == true)  {
364                                                         changed = true;
365                                                         Links[i].Hoovered = false;
366                                                 }
367                                         }
368
369                                         if (changed == true)
370                                                 Refresh ();
371                                 }
372                                 return;
373                         }
374                         
375                         if (link_behavior == LinkBehavior.HoverUnderline) {
376                                 if (link.Hoovered != true) {
377                                         link.Hoovered = true;
378                                         Refresh ();
379                                 }
380                         }
381                         
382                         Cursor = Cursors.Hand;
383                 }
384
385                 protected override void OnMouseUp (MouseEventArgs e)
386                 {
387                         if (!Enabled) return;
388
389                         base.OnMouseUp (e);
390                         this.Capture = false;
391
392                         for (int i = 0; i < num_pieces; i++) {
393                                 if (pieces[i].link!= null && pieces[i].clicked == true) {
394                                         OnLinkClicked (new LinkLabelLinkClickedEventArgs (pieces[i].link));                                     
395                                         pieces[i].clicked = false;
396                                         Invalidate (pieces[i].rect);
397                                         break;
398                                 }
399                         }
400                 }
401
402                 protected override void OnPaint (PaintEventArgs pevent)
403                 {
404                         ThemeEngine.Current.DrawLinkLabel (pevent.Graphics, pevent.ClipRectangle, this);
405                         DrawImage (pevent.Graphics, Image, ClientRectangle, image_align);
406                         // Do not call base.OnPaint since it's the Label class 
407                 }
408
409                 protected override void OnPaintBackground (PaintEventArgs e)
410                 {
411                         base.OnPaintBackground (e);
412                 }
413
414                 protected override void OnTextAlignChanged (EventArgs e)
415                 {
416                         base.OnTextAlignChanged (e);
417                         CreateLinkPieces ();                    
418                 }
419
420                 protected override void OnTextChanged (EventArgs e)
421                 {
422                         base.OnTextChanged (e);                 
423                 }
424                 
425                 protected Link PointInLink (int x, int y)
426                 {
427                         for (int i = 0; i < num_pieces; i++) {
428                                 if (pieces[i].rect.Contains (x,y) && pieces[i].link != null)
429                                         return pieces[i].link;
430                         }
431
432                         return null;
433                 }
434
435                 protected override bool ProcessDialogKey (Keys keyData)
436                 {
437                         return base.ProcessDialogKey (keyData);
438                 }
439
440                 protected override void Select (bool directed, bool forward)
441                 {
442                         base.Select (directed, forward);
443                 }
444
445                 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
446                 {
447                         base.SetBoundsCore (x, y, width, height, specified);                    
448                 }
449
450                 protected override void WndProc (ref Message m)
451                 {
452                         base.WndProc (ref m);
453                 }
454
455                 #endregion //Public Methods
456
457                 #region Private Methods
458
459                 internal void CreateLinkPieces ()
460                 {
461                         if (Links.Count == 0 || IsHandleCreated == false || Text.Length == 0)
462                                 return;
463
464                         int cur_piece = 0;
465                         num_pieces = 0;
466
467                         if (Links.Count == 1 && Links[0].Start == 0 &&  Links[0].Length == -1) {
468                                 Links[0].Length = Text.Length;                          
469                         }
470
471                         pieces = new Piece [(Links.Count * 2) + 1];
472                         pieces[cur_piece] = new Piece();
473                         pieces[cur_piece].start = 0;
474
475                         for (int i = 0; i < Text.Length; i++) { /* Every char on the text*/
476                                 for (int l = 0; l < Links.Count; l++)   { /* Every link that we know of*/
477                                         if (Links[l].Start == i) {
478                                                 if (i > 0) {                                                    
479                                                         /*Push prev. regular text*/
480                                                         pieces[cur_piece].end = i;
481                                                         pieces[cur_piece].text = Text.Substring (pieces[cur_piece].start,
482                                                                 pieces[cur_piece].end - pieces[cur_piece].start);
483
484                                                         cur_piece++;
485
486                                                         /* New link*/
487                                                         pieces[cur_piece] = new Piece ();                                                       
488                                                 }
489                                                 
490                                                 int end;
491                                                 
492                                                 if (Links[l].Start + Links[l].Length > Text.Length) {
493                                                         end = Text.Length - Links[l].Start;
494                                                 }
495                                                 else {
496                                                         end = Links[l].Length;
497                                                 }                                               
498                                                 
499                                                 pieces[cur_piece].start = Links[l].Start;
500                                                 pieces[cur_piece].end = Links[l].Start + end;
501                                                 pieces[cur_piece].link = Links[l];
502                                                 
503                                                 pieces[cur_piece].text = Text.Substring (pieces[cur_piece].start, end);
504
505                                                 cur_piece++; /* Push link*/
506                                                 pieces[cur_piece] = new Piece();
507                                                 i+= Links[l].Length;
508                                                 pieces[cur_piece].start = i;
509                                         }
510                                 }
511                         }                       
512
513                         if (pieces[cur_piece].end == 0 && pieces[cur_piece].start < Text.Length) {
514                                 pieces[cur_piece].end = Text.Length;
515                                 pieces[cur_piece].text = Text.Substring (pieces[cur_piece].start, pieces[cur_piece].end - pieces[cur_piece].start);
516                                 cur_piece++;
517                         }
518                         
519                         num_pieces = cur_piece;
520
521                         CharacterRange[] charRanges = new CharacterRange [num_pieces];
522
523                         for (int i = 0; i < num_pieces; i++)
524                                 charRanges[i] = new CharacterRange (pieces[i].start, pieces[i].end - pieces[i].start);
525
526                         Region[] charRegions = new Region [num_pieces];                 
527                         string_format.SetMeasurableCharacterRanges (charRanges);
528
529                         // BUG: This sizes do not match the ones used later when drawing
530                         charRegions = DeviceContext.MeasureCharacterRanges (Text, link_font, ClientRectangle, string_format);
531         
532                         RectangleF rect;
533                         for (int i = 0; i < num_pieces; i++)  {                         
534                                 rect = charRegions[i].GetBounds (DeviceContext);
535                                 pieces[i].rect = Rectangle.Ceiling (rect);
536                                 charRegions[i].Dispose ();
537                         }
538
539                         if (Visible && IsHandleCreated)
540                                 Refresh ();
541
542                 }
543
544                 /* Check if the links overlap */
545                 internal void CheckLinks ()
546                 {
547                         for (int i = 0; i < Links.Count; i++) {
548                                 for (int l = 0; l < Links.Count; l++) {
549                                         if (i==l) continue;
550
551                                         if (((Links[i].Start + Links[i].Length) >= Links[l].Start &&
552                                                 Links[i].Start + Links[i].Length <= Links[l].Start + Links[l].Length) ||
553                                                 (Links[i].Start  >= Links[l].Start &&
554                                                 Links[i].Start  <= Links[l].Start + Links[l].Length))
555                                                 throw new InvalidOperationException ("Overlapping link regions.");
556                                 }
557                         }
558                 }
559                 
560                 internal Font GetPieceFont (Piece piece)
561                 {
562                         switch (link_behavior) {                                
563                                 case LinkBehavior.AlwaysUnderline:
564                                 case LinkBehavior.SystemDefault: // Depends on IE configuration
565                                 {
566                                         if (piece.link == null) {
567                                                 return Font;
568                                         } else {
569                                                 return link_font;
570                                         }
571                                 }                               
572                                 case LinkBehavior.HoverUnderline:
573                                 {
574                                         if (piece.link != null && piece.link.Hoovered) {
575                                                 return link_font;
576                                         } else {
577                                                 return Font;
578                                         }                                                               
579                                 }
580                                 
581                                 case LinkBehavior.NeverUnderline:                               
582                                 default:
583                                         return Font;                                    
584                         }
585                         
586                 }               
587                 
588
589                 internal Color GetLinkColor (Piece piece, int i)
590                 {
591                         Color color;
592
593                         if (Enabled == false ||
594                                 (piece.link != null && piece.link.Enabled == false))
595                                 color = DisabledLinkColor;
596                         else
597                                 if (piece.clicked == true)
598                                         color = ActiveLinkColor;
599                                 else
600                                         if ((LinkVisited == true && i == 0) ||
601                                                 (piece.link != null && piece.link.Visited == true))
602                                                 color = VisitedLinkColor;
603                                         else
604                                                 color = LinkColor;
605
606                         return color;
607                 }
608
609                 private void CreateLinkFont ()
610                 {
611                         if (link_font != null)
612                                 link_font.Dispose ();
613                                 
614                         link_font  = new Font (Font.FontFamily, Font.Size, Font.Style | FontStyle.Underline,
615                                  Font.Unit);
616                 }
617
618                 #endregion // Private Methods
619
620                 //
621                 // System.Windows.Forms.LinkLabel.Link
622                 //
623                 public class Link
624                 {
625                         private bool enabled;
626                         internal int length;
627                         private object linkData;
628                         private int start;
629                         private bool visited;                   
630                         private LinkLabel owner;
631                         private bool hoovered;
632
633                         internal Link ()
634                         {
635                                 enabled = true;
636                                 visited = false;
637                                 length = start = 0;
638                                 linkData = null;
639                                 owner = null;                           
640                         }
641
642                         internal Link (LinkLabel owner)
643                         {
644                                 enabled = true;
645                                 visited = false;
646                                 length = start = 0;
647                                 linkData = null;
648                                 this.owner = owner;
649                         }
650
651                         public bool Enabled {
652                                 get { return enabled; }
653                                 set {
654                                         if (enabled == value)
655                                                 return;
656
657                                         enabled = value;        
658                                         
659                                         if (owner != null)
660                                                 owner.Refresh ();
661                                 }
662                         }
663
664                         public int Length {
665                                 get { 
666                                         if (length == -1) {
667                                                 return owner.Text.Length;
668                                         }
669                                         
670                                         return length; 
671                                 }
672                                 set {
673                                         if (length == value)
674                                                 return;                                         
675                                         
676                                         length = value;
677
678                                         if (owner != null)
679                                                 owner.CreateLinkPieces ();
680                                 }
681                         }
682
683                         public object LinkData {
684                                 get { return linkData; }
685                                 set { linkData = value; }
686                         }
687
688                         public int Start {
689                                 get { return start; }
690                                 set {
691                                         if (start == value)
692                                                 return;
693
694                                         start = value;
695
696                                         if (owner != null)
697                                                 owner.CreateLinkPieces ();
698                                 }
699                         }
700
701                         public bool Visited {
702                                 get { return visited; }
703                                 set {
704                                         if (visited == value)
705                                                 return;
706
707                                         visited = value;
708                                         
709                                         if (owner != null)
710                                                 owner.Refresh ();
711                                 }
712                         }
713                         
714                         internal bool Hoovered {
715                                 get { return hoovered; }
716                                 set { hoovered = value; }
717                         }
718                 }
719
720                 //
721                 // System.Windows.Forms.LinkLabel.Link
722                 //
723                 public class LinkCollection :  IList, ICollection, IEnumerable
724                 {
725                         private LinkLabel owner;
726                         private ArrayList collection = new ArrayList();
727
728                         public LinkCollection (LinkLabel owner)
729                         {
730                                 if (owner==null)
731                                         throw new ArgumentNullException ();
732
733                                 this.owner = owner;
734                         }
735
736                         [Browsable (false)]
737                         public int Count {
738                                 get { return collection.Count; }
739                         }
740
741                         public bool IsReadOnly {
742                                 get { return false; }
743                         }
744
745                         public virtual LinkLabel.Link this[int index]  {
746                                 get {
747                                         if (index < 0 || index >= Count)
748                                                 throw  new  ArgumentOutOfRangeException();
749
750                                         return (LinkLabel.Link) collection[index];
751                                 }
752                                 set {
753                                         if (index < 0 || index >= Count)
754                                                 throw new  ArgumentOutOfRangeException();
755
756                                         collection[index] = value;
757                                 }
758                         }
759
760                         public Link Add (int start, int length)
761                         {
762                                 return Add (start, length, null);
763                         }
764
765
766                         public Link Add (int start, int length, object o)
767                         {
768                                 Link link = new Link (owner);
769                                 int idx;
770
771                                 if (Count == 1 && this[0].Start == 0
772                                         && this[0].length == -1) {
773                                         Clear ();
774                                 }
775
776                                 link.Length = length;
777                                 link.Start = start;
778                                 link.LinkData = o;
779                                 idx = collection.Add (link);
780
781                                 owner.CheckLinks ();
782                                 owner.CreateLinkPieces ();
783                                 return (Link) collection[idx];
784                         }
785
786                         public virtual void Clear ()
787                         {
788                                 collection.Clear();
789                                 owner.CreateLinkPieces ();
790                         }
791
792                         public bool Contains (LinkLabel.Link link)
793                         {
794                                 return collection.Contains (link);
795                         }
796
797                         public IEnumerator GetEnumerator ()
798                         {
799                                 return collection.GetEnumerator ();
800                         }
801
802                         public int IndexOf (LinkLabel.Link link)
803                         {
804                                 return collection.IndexOf (link);
805                         }
806
807                         public void Remove (LinkLabel.Link value)
808                         {
809                                 collection.Remove (value);
810                                 owner.CreateLinkPieces ();
811                         }
812
813                         public void RemoveAt (int index)
814                         {
815                                 if (index >= Count)
816                                         throw new ArgumentOutOfRangeException ("Invalid value for array index");
817
818                                 collection.Remove (collection[index]);
819                                 owner.CreateLinkPieces ();
820                         }
821
822                         bool IList.IsFixedSize {
823                                 get {return false;}
824                         }
825
826                         object IList.this[int index] {
827                                 get { return collection[index]; }
828                                 set { collection[index] = value; }
829                         }
830
831                         object ICollection.SyncRoot {
832                                 get {return this;}
833                         }
834
835                         bool ICollection.IsSynchronized {
836                                 get {return false;}
837                         }
838
839                         void ICollection.CopyTo (Array dest, int index)
840                         {
841                                 collection.CopyTo (dest, index);
842                         }
843
844                         int IList.Add (object control)
845                         {
846                                 int idx = collection.Add (control);
847                                 owner.CheckLinks ();
848                                 owner.CreateLinkPieces ();
849                                 return idx;
850                         }
851
852                         bool IList.Contains (object control)
853                         {
854                                 return collection.Contains (control);
855                         }
856
857                         int IList.IndexOf (object control)
858                         {
859                                 return collection.IndexOf (control);
860                         }
861
862                         void IList.Insert (int index, object value)
863                         {
864                                 collection.Insert (index, value);
865                                 owner.CheckLinks ();
866                                 owner.CreateLinkPieces ();
867                         }
868
869                         void IList.Remove (object control)
870                         {
871                                 collection.Remove (control);
872                                 owner.CreateLinkPieces ();
873                         }
874                 }
875         }
876 }