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:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
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.
20 // Copyright (c) 2004 Novell, Inc.
23 // Jordi Mas i Hernandez, jordi@ximian.com
26 // - Keyboard navigation
27 // - Horizontal item scroll
28 // - Performance testing
36 using System.Collections;
37 using System.ComponentModel;
38 using System.Reflection;
40 namespace System.Windows.Forms
43 public class ListBox : ListControl
45 internal class ListBoxInfo
47 internal int item_height; /* Item's height */
48 internal int top_item; /* First item that we show the in the current page */
49 internal int last_item; /* Last visible item */
50 internal int page_size; /* Number of listbox items per page. In MultiColumn listbox indicates items per column */
51 internal Rectangle textdrawing_rect; /* Displayable Client Rectangle minus the scrollbars and with IntegralHeight calculated*/
52 internal bool show_verticalsb; /* Is Vertical scrollbar show it? */
53 internal bool show_horizontalsb; /* Is Horizontal scrollbar show it? */
54 internal Rectangle client_rect; /* Client Rectangle. Usually = ClientRectangle except when IntegralHeight has been applied*/
55 internal int max_itemwidth; /* Maxium item width within the listbox */
64 show_verticalsb = false;
65 show_horizontalsb = false;
69 internal class ListBoxItem
72 internal bool Selected;
74 public ListBoxItem (int index)
81 private BorderStyle border_style;
82 private int column_width;
83 private DrawMode draw_mode;
84 private int horizontal_extent;
85 private bool horizontal_scrollbar;
86 private bool integral_height;
87 private ObjectCollection items;
88 private bool multicolumn;
89 private bool scroll_always_visible;
90 private int selected_index;
91 private SelectedIndexCollection selected_indices;
92 private object selected_item;
93 private SelectedObjectCollection selected_items;
94 private SelectionMode selection_mode;
96 private bool use_tabstops;
97 private int preferred_height;
98 private int top_index;
99 private StringFormat string_format;
100 private int column_width_internal;
101 private ListBoxInfo listbox_info;
102 private VScrollBar vscrollbar_ctrl;
103 private HScrollBar hscrollbar_ctrl;
104 private bool suspend_ctrlupdate;
108 border_style = BorderStyle.Fixed3D;
\r
109 draw_mode = DrawMode.Normal;
\r
110 horizontal_extent = 0;
\r
111 horizontal_scrollbar = false;
\r
112 integral_height = true;
\r
113 multicolumn = false;
\r
114 preferred_height = 7;
\r
115 scroll_always_visible = false;
\r
116 selected_index = -1;
\r
117 selected_item = null;
\r
118 selection_mode = SelectionMode.One;
\r
122 BackColor = ThemeEngine.Current.ColorWindow;
124 suspend_ctrlupdate = false;
126 items = new ObjectCollection (this);
127 selected_indices = new SelectedIndexCollection (this);
128 selected_items = new SelectedObjectCollection (this);
129 listbox_info = new ListBoxInfo ();
130 string_format = new StringFormat ();
131 listbox_info.item_height = FontHeight;
133 /* Vertical scrollbar */
134 vscrollbar_ctrl = new VScrollBar ();
135 vscrollbar_ctrl.Minimum = 0;
136 vscrollbar_ctrl.SmallChange = 1;
137 vscrollbar_ctrl.LargeChange = 1;
138 vscrollbar_ctrl.Maximum = 0;
139 vscrollbar_ctrl.ValueChanged += new EventHandler (VerticalScrollEvent);
140 vscrollbar_ctrl.Visible = false;
142 /* Horizontal scrollbar */
143 hscrollbar_ctrl = new HScrollBar ();
144 hscrollbar_ctrl.Minimum = 0;
145 hscrollbar_ctrl.SmallChange = 1;
146 hscrollbar_ctrl.LargeChange = 1;
147 hscrollbar_ctrl.Maximum = 0;
148 hscrollbar_ctrl.Visible = false;
149 hscrollbar_ctrl.ValueChanged += new EventHandler (HorizontalScrollEvent);
152 MouseDown += new MouseEventHandler (OnMouseDownLB);
154 UpdateFormatString ();
158 public new event EventHandler BackgroundImageChanged;
159 public new event EventHandler Click;
160 public event DrawItemEventHandler DrawItem;
161 public event MeasureItemEventHandler MeasureItem;
162 public new event PaintEventHandler Paint;
163 public event EventHandler SelectedIndexChanged;
164 public new event EventHandler TextChanged;
167 #region Public Properties
168 public override Color BackColor {
169 get { return base.BackColor; }
171 if (base.BackColor == value)
174 base.BackColor = value;
179 public override Image BackgroundImage {
180 get { return base.BackgroundImage; }
182 if (base.BackgroundImage == value)
185 base.BackgroundImage = value;
187 if (BackgroundImageChanged != null)
188 BackgroundImageChanged (this, EventArgs.Empty);
194 public BorderStyle BorderStyle {
195 get { return border_style; }
198 if (!Enum.IsDefined (typeof (BorderStyle), value))
199 throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for BorderStyle", value));
201 if (border_style == value)
204 border_style = value;
209 public int ColumnWidth {
210 get { return column_width; }
212 if (column_width < 0)
213 throw new ArgumentException ("A value less than zero is assigned to the property.");
215 column_width = value;
218 ColumnWidthInternal = 120;
220 ColumnWidthInternal = value;
226 protected override CreateParams CreateParams {
227 get { return base.CreateParams;}
230 protected override Size DefaultSize {
231 get { return new Size (120, 96); }
234 public virtual DrawMode DrawMode {
235 get { return draw_mode; }
238 if (!Enum.IsDefined (typeof (DrawMode), value))
239 throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for DrawMode", value));
241 if (draw_mode == value)
249 public override Color ForeColor {
250 get { return base.ForeColor; }
253 if (base.ForeColor == value)
256 base.ForeColor = value;
261 public int HorizontalExtent {
262 get { return horizontal_extent; }
264 if (horizontal_extent == value)
267 horizontal_extent = value;
272 public bool HorizontalScrollbar {
273 get { return horizontal_scrollbar; }
275 if (horizontal_scrollbar == value)
278 horizontal_scrollbar = value;
279 UpdateShowHorizontalScrollBar ();
284 public bool IntegralHeight {
285 get { return integral_height; }
287 if (integral_height == value)
290 integral_height = value;
295 public virtual int ItemHeight {
296 get { return listbox_info.item_height; }
299 throw new ArgumentOutOfRangeException ("The ItemHeight property was set beyond 255 pixels");
301 listbox_info.item_height = value;
306 public ObjectCollection Items {
307 get { return items; }
310 public bool MultiColumn {
311 get { return multicolumn; }
313 if (multicolumn == value)
316 if (value == true && DrawMode == DrawMode.OwnerDrawVariable)
317 throw new ArgumentException ("A multicolumn ListBox cannot have a variable-sized height.");
320 UpdateShowVerticalScrollBar (); /* the needs for scrollbars may change */
321 UpdateShowHorizontalScrollBar ();
326 public int PreferredHeight {
327 get { return preferred_height;}
330 public override RightToLeft RightToLeft {
331 get { return base.RightToLeft; }
333 if (base.RightToLeft == value)
336 base.RightToLeft = value;
337 UpdateFormatString ();
342 // Only afects the Vertical ScrollBar
343 public bool ScrollAlwaysVisible {
344 get { return scroll_always_visible; }
346 if (scroll_always_visible == value)
349 scroll_always_visible = value;
350 UpdateShowVerticalScrollBar ();
351 UpdateShowHorizontalScrollBar ();
355 public override int SelectedIndex {
356 get { return selected_index;}
358 if (value < -1 || value >= Items.Count)
359 throw new ArgumentOutOfRangeException ("Index of out range");
361 if (SelectionMode == SelectionMode.None)
362 throw new ArgumentException ("cannot call this method if SelectionMode is SelectionMode.None");
364 if (selected_index == value)
367 if (SelectionMode == SelectionMode.One)
368 UnSelectItem (selected_index, true);
371 selected_index = value;
372 OnSelectedIndexChanged (new EventArgs ());
376 public SelectedIndexCollection SelectedIndices {
377 get { return selected_indices; }
380 public object SelectedItem {
382 if (SelectedItems.Count > 0)
383 return SelectedItems[0];
388 if (selected_item == value)
391 int index = Items.IndexOf (value);
396 SelectedIndex = index;
400 public SelectedObjectCollection SelectedItems {
401 get {return selected_items;}
404 public virtual SelectionMode SelectionMode {
405 get { return selection_mode; }
407 if (!Enum.IsDefined (typeof (SelectionMode), value))
408 throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for SelectionMode", value));
410 if (selection_mode == value)
413 selection_mode = value;
419 get { return sorted; }
430 public override string Text {
432 if (SelectionMode != SelectionMode.None && SelectedIndex != -1)
433 return Items[SelectedIndex].ToString ();
441 if (SelectionMode == SelectionMode.None)
446 index = FindStringExact (value);
451 SelectedIndex = index;
455 public int TopIndex {
456 get { return top_index;}
458 if (value == top_index)
461 if (value < 0 || value >= Items.Count)
469 public bool UseTabStops {
470 get { return use_tabstops; }
473 if (use_tabstops == value)
476 use_tabstops = value;
477 UpdateFormatString ();
482 #endregion Public Properties
484 #region Private Properties
486 internal ListBoxInfo LBoxInfo {
487 get { return listbox_info; }
490 private int ColumnWidthInternal {
491 get { return column_width_internal; }
492 set { column_width_internal = value; }
495 #endregion Private Properties
497 #region Public Methods
498 protected virtual void AddItemsCore (object[] value)
500 items.AddRange (value);
503 public void BeginUpdate ()
505 suspend_ctrlupdate = true;
508 public void ClearSelected ()
510 foreach (int i in selected_indices) {
511 UnSelectItem (i, false);
514 selected_indices.ClearIndices ();
515 selected_items.ClearObjects ();
518 protected virtual ObjectCollection CreateItemCollection ()
520 return new ObjectCollection (this);
523 public void EndUpdate ()
525 suspend_ctrlupdate = false;
526 UpdateItemInfo (false, -1, -1);
530 public int FindString (String s)
532 return FindString (s, 0);
535 public int FindString (string s, int startIndex)
537 for (int i = startIndex; i < Items.Count; i++) {
538 if ((Items[i].ToString ()).StartsWith (s))
545 public int FindStringExact (string s)
547 return FindStringExact (s, 0);
550 public int FindStringExact (string s, int startIndex)
552 for (int i = startIndex; i < Items.Count; i++) {
553 if ((Items[i].ToString ()).Equals (s))
560 public int GetItemHeight (int index)
562 if (index < 0 || index >= Items.Count)
563 throw new ArgumentOutOfRangeException ("Index of out range");
568 public Rectangle GetItemRectangle (int index)
570 if (index < 0 || index >= Items.Count)
571 throw new ArgumentOutOfRangeException ("GetItemRectangle index out of range.");
573 Rectangle rect = new Rectangle ();
575 if (MultiColumn == false) {
578 rect.Y = ItemHeight * index;
579 rect.Height = ItemHeight;
580 rect.Width = listbox_info.textdrawing_rect.Width;
583 int which_page = index / listbox_info.page_size;
585 rect.X = which_page * ColumnWidthInternal;
586 rect.Y = (index % listbox_info.page_size) * ItemHeight;
587 rect.Height = ItemHeight;
588 rect.Width = ColumnWidthInternal;
594 public bool GetSelected (int index)
596 if (index < 0 || index >= Items.Count)
597 throw new ArgumentOutOfRangeException ("Index of out range");
599 return (Items.GetListBoxItem (index)).Selected;
602 public int IndexFromPoint (Point p)
604 return IndexFromPoint (p.X, p.Y);
607 // Only returns visible points
608 public int IndexFromPoint (int x, int y)
610 for (int i = LBoxInfo.top_item; i < LBoxInfo.last_item; i++) {
611 if (GetItemRectangle (i).Contains (x,y) == true)
618 protected override void OnChangeUICues (UICuesEventArgs e)
620 base.OnChangeUICues (e);
623 protected override void OnDataSourceChanged (EventArgs e)
625 base.OnDataSourceChanged (e);
628 protected override void OnDisplayMemberChanged (EventArgs e)
630 base.OnDisplayMemberChanged (e);
633 protected virtual void OnDrawItem (DrawItemEventArgs e)
635 if (DrawItem != null && (DrawMode == DrawMode.OwnerDrawFixed || DrawMode == DrawMode.OwnerDrawVariable))
638 if ((e.State & DrawItemState.Selected) == DrawItemState.Selected) {
639 e.Graphics.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush
640 (ThemeEngine.Current.ColorHilight), e.Bounds);
642 e.Graphics.DrawString (Items[e.Index].ToString (), e.Font,
643 ThemeEngine.Current.ResPool.GetSolidBrush (ThemeEngine.Current.ColorHilightText),
644 e.Bounds, string_format);
647 e.Graphics.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush
648 (e.BackColor), e.Bounds);
650 e.Graphics.DrawString (Items[e.Index].ToString (), e.Font,
651 ThemeEngine.Current.ResPool.GetSolidBrush (e.ForeColor),
652 e.Bounds, string_format);
656 protected override void OnFontChanged (EventArgs e)
658 base.OnFontChanged (e);
660 UpdateShowHorizontalScrollBar ();
661 UpdateShowVerticalScrollBar ();
662 RellocateScrollBars ();
664 UpdateItemInfo (false, -1, -1);
667 protected override void OnHandleCreated (EventArgs e)
669 base.OnHandleCreated (e);
671 UpdateInternalClientRect (ClientRectangle);
672 Controls.Add (vscrollbar_ctrl);
673 Controls.Add (hscrollbar_ctrl);
677 protected override void OnHandleDestroyed (EventArgs e)
679 base.OnHandleDestroyed (e);
682 protected virtual void OnMeasureItem (MeasureItemEventArgs e)
687 protected override void OnParentChanged (EventArgs e)
689 base.OnParentChanged (e);
692 protected override void OnResize (EventArgs e)
695 UpdateInternalClientRect (ClientRectangle);
698 protected override void OnSelectedIndexChanged (EventArgs e)
700 base.OnSelectedIndexChanged (e);
702 if (SelectedIndexChanged != null)
703 SelectedIndexChanged (this, e);
706 protected override void OnSelectedValueChanged (EventArgs e)
708 base.OnSelectedValueChanged (e);
711 public override void Refresh ()
716 protected override void RefreshItem (int index)
721 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
723 base.SetBoundsCore (x, y, width, height, specified);
726 protected override void SetItemCore (int index, object value)
728 if (index < 0 || index >= Items.Count)
731 Items[index] = value;
734 protected override void SetItemsCore (IList value)
739 public void SetSelected (int index, bool value)
741 if (index < 0 || index >= Items.Count)
742 throw new ArgumentOutOfRangeException ("Index of out range");
744 if (SelectionMode == SelectionMode.None)
745 throw new InvalidOperationException ();
750 UnSelectItem (index, true);
753 protected virtual void Sort ()
755 if (Items.Count == 0)
762 public override string ToString ()
764 return base.ToString () + ", Items Count: " + Items.Count;
767 protected virtual void WmReflectCommand (ref Message m)
772 protected override void WndProc (ref Message m)
774 switch ((Msg) m.Msg) {
777 PaintEventArgs paint_event;
778 paint_event = XplatUI.PaintEventStart (Handle);
779 OnPaintLB (paint_event);
780 XplatUI.PaintEventEnd (Handle);
784 case Msg.WM_ERASEBKGND:
785 m.Result = (IntPtr) 1;
792 base.WndProc (ref m);
795 #endregion Public Methods
797 #region Private Methods
799 internal void CalcClientArea ()
801 listbox_info.textdrawing_rect = listbox_info.client_rect;
802 listbox_info.textdrawing_rect.Y += ThemeEngine.Current.DrawListBoxDecorationTop (BorderStyle);
803 listbox_info.textdrawing_rect.X += ThemeEngine.Current.DrawListBoxDecorationLeft (BorderStyle);
804 listbox_info.textdrawing_rect.Height -= ThemeEngine.Current.DrawListBoxDecorationBottom (BorderStyle);
805 listbox_info.textdrawing_rect.Width -= ThemeEngine.Current.DrawListBoxDecorationRight (BorderStyle);
807 if (listbox_info.show_verticalsb)
808 listbox_info.textdrawing_rect.Width -= vscrollbar_ctrl.Width;
810 if (listbox_info.show_horizontalsb)
811 listbox_info.textdrawing_rect.Height -= hscrollbar_ctrl.Height;
813 //listbox_info.page_size = listbox_info.client_rect.Height / listbox_info.item_height;
814 listbox_info.page_size = listbox_info.textdrawing_rect.Height / listbox_info.item_height;
816 /* Adjust size to visible the maxim number of displayable items */
817 if (IntegralHeight == true) {
819 // From MS Docs: The integral height is based on the height of the ListBox, rather than
820 // the client area height. As a result, when the IntegralHeight property is set true,
821 // items can still be partially shown if scroll bars are displayed.
823 int remaining = (listbox_info.client_rect.Height -
824 ThemeEngine.Current.DrawListBoxDecorationBottom (BorderStyle) -
825 ThemeEngine.Current.DrawListBoxDecorationBottom (BorderStyle)) %
826 listbox_info.item_height;
829 listbox_info.client_rect.Height -= remaining;
831 RellocateScrollBars ();
836 LBoxInfo.last_item = LastVisibleItem ();
839 internal void Draw (Rectangle clip)
841 if (LBoxInfo.textdrawing_rect.Contains (clip) == false) {
842 // IntegralHeight has effect, we also have to paint the unused area
843 if (ClientRectangle.Height > listbox_info.client_rect.Height) {
844 Region area = new Region (ClientRectangle);
845 area.Exclude (listbox_info.client_rect);
847 DeviceContext.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (Parent.BackColor),
848 area.GetBounds (DeviceContext));
851 DeviceContext.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (BackColor), LBoxInfo.textdrawing_rect);
852 ThemeEngine.Current.DrawListBoxDecorations (DeviceContext, this);
855 if (Items.Count > 0) {
857 DrawItemState state = DrawItemState.None;
859 for (int i = LBoxInfo.top_item; i < LBoxInfo.last_item; i++) {
860 item_rect = GetItemDisplayRectangle (i, LBoxInfo.top_item);
862 if (clip.IntersectsWith (item_rect) == false)
866 state = DrawItemState.None;
868 if ((Items.GetListBoxItem (i)).Selected) {
869 state |= DrawItemState.Selected;
872 OnDrawItem (new DrawItemEventArgs (DeviceContext, Font, item_rect,
873 i, state, ForeColor, BackColor));
878 // Converts a GetItemRectangle to a one that we can display
879 private Rectangle GetItemDisplayRectangle (int index, int first_displayble)
882 Rectangle first_item_rect = GetItemRectangle (first_displayble);
883 item_rect = GetItemRectangle (index);
884 item_rect.X -= first_item_rect.X;
885 item_rect.Y -= first_item_rect.Y;
887 item_rect.Y += ThemeEngine.Current.DrawListBoxDecorationTop (BorderStyle);
888 item_rect.X += ThemeEngine.Current.DrawListBoxDecorationLeft (BorderStyle);
889 item_rect.Width -= ThemeEngine.Current.DrawListBoxDecorationRight (BorderStyle);
895 private void HorizontalScrollEvent (object sender, EventArgs e)
897 LBoxInfo.top_item = listbox_info.page_size * hscrollbar_ctrl.Value;
898 LBoxInfo.last_item = LastVisibleItem ();
902 private int LastVisibleItem ()
905 int top_y = LBoxInfo.textdrawing_rect.Y + LBoxInfo.textdrawing_rect.Height;
908 for (i = LBoxInfo.top_item; i < Items.Count; i++) {
910 item_rect = GetItemDisplayRectangle (i, LBoxInfo.top_item);
914 if (item_rect.X > LBoxInfo.textdrawing_rect.Width)
918 if (IntegralHeight) {
919 if (item_rect.Y + item_rect.Height > top_y)
923 if (item_rect.Y > top_y)
932 private void OnMouseDownLB (object sender, MouseEventArgs e)
936 for (int i = LBoxInfo.top_item; i < LBoxInfo.last_item; i++) {
937 if (GetItemDisplayRectangle (i, LBoxInfo.top_item).Contains (e.X, e.Y) == true) {
943 if (index == -1) return;
945 switch (SelectionMode) {
946 case SelectionMode.None: // Do nothing
948 case SelectionMode.One: {
949 SelectedIndex = index;
953 case SelectionMode.MultiSimple: {
954 if (selected_index == -1) {
955 SelectedIndex = index;
958 if ((Items.GetListBoxItem (index)).Selected)
959 UnSelectItem (index, true);
962 OnSelectedIndexChanged (new EventArgs ());
972 private void OnPaintLB (PaintEventArgs pevent)
974 if (Width <= 0 || Height <= 0 || Visible == false || suspend_ctrlupdate == true)
977 /* Copies memory drawing buffer to screen*/
978 Draw (pevent.ClipRectangle);
979 pevent.Graphics.DrawImage (ImageBuffer, pevent.ClipRectangle, pevent.ClipRectangle, GraphicsUnit.Pixel);
982 Paint (this, pevent);
985 internal void RellocateScrollBars ()
987 if (listbox_info.show_verticalsb) {
989 vscrollbar_ctrl.Size = new Size (vscrollbar_ctrl.Width,
990 listbox_info.client_rect.Height - ThemeEngine.Current.DrawListBoxDecorationTop (BorderStyle) -
991 ThemeEngine.Current.DrawListBoxDecorationBottom (BorderStyle));
993 vscrollbar_ctrl.Location = new Point (listbox_info.client_rect.Width - vscrollbar_ctrl.Width
994 - ThemeEngine.Current.DrawListBoxDecorationRight (BorderStyle),
995 ThemeEngine.Current.DrawListBoxDecorationTop (BorderStyle));
999 if (listbox_info.show_horizontalsb) {
1003 width = listbox_info.client_rect.Width - (ThemeEngine.Current.DrawListBoxDecorationLeft (BorderStyle) + ThemeEngine.Current.DrawListBoxDecorationRight (BorderStyle));
1005 if (listbox_info.show_verticalsb)
1006 width -= vscrollbar_ctrl.Width;
1008 hscrollbar_ctrl.Size = new Size (width, hscrollbar_ctrl.Height);
1010 hscrollbar_ctrl.Location = new Point (ThemeEngine.Current.DrawListBoxDecorationLeft (BorderStyle),
1011 listbox_info.client_rect.Height - hscrollbar_ctrl.Height
1012 - ThemeEngine.Current.DrawListBoxDecorationTop (BorderStyle));
1018 // Add an item in the Selection array and marks it visually as selected
1019 private void SelectItem (int index)
1024 Rectangle invalidate = GetItemDisplayRectangle (index, LBoxInfo.top_item);
1025 (Items.GetListBoxItem (index)).Selected = true;
1026 selected_indices.AddIndex (index);
1027 selected_items.AddObject (Items[index]);
1029 if (ClientRectangle.Contains (invalidate))
1030 Invalidate (invalidate);
1034 // Removes an item in the Selection array and marks it visually as unselected
1035 private void UnSelectItem (int index, bool remove)
1040 Rectangle invalidate = GetItemDisplayRectangle (index, LBoxInfo.top_item);
1041 (Items.GetListBoxItem (index)).Selected = false;
1044 selected_indices.RemoveIndex (index);
1045 selected_items.RemoveObject (Items[index]);
1049 if (ClientRectangle.Contains (invalidate))
1050 Invalidate (invalidate);
1053 private void UpdateFormatString ()
1055 if (RightToLeft == RightToLeft.No)
1056 string_format.Alignment = StringAlignment.Near;
1058 string_format.Alignment = StringAlignment.Far;
1061 string_format.SetTabStops (0, new float [] {(float)(Font.Height * 3.7)});
1064 // Updates the scrollbar's position with the new items and inside area
1065 internal void UpdateItemInfo (bool adding, int first, int last)
1067 if (!IsHandleCreated || suspend_ctrlupdate == true)
1070 UpdateShowVerticalScrollBar ();
1072 if (listbox_info.show_verticalsb && Items.Count > listbox_info.page_size)
1073 if (vscrollbar_ctrl.Enabled)
1074 vscrollbar_ctrl.Maximum = Items.Count - listbox_info.page_size;
1076 if (listbox_info.show_horizontalsb) {
1078 int fullpage = (listbox_info.page_size * (listbox_info.client_rect.Width / ColumnWidthInternal));
1080 if (hscrollbar_ctrl.Enabled && listbox_info.page_size > 0)
1081 hscrollbar_ctrl.Maximum = 1 + ((Items.Count - fullpage) / listbox_info.page_size);
1085 if (MultiColumn == false) {
1086 /* Calc the longest items for non multicolumn listboxes */
1087 if ((first == -1 && last == -1) || (adding == false)) {
1090 for (int i = 0; i < Items.Count; i++) {
1091 size = DeviceContext.MeasureString (Items[i].ToString(), Font);
1093 if ((int) size.Width > listbox_info.max_itemwidth)
1094 listbox_info.max_itemwidth = (int) size.Width;
1101 for (int i = first; i < last + 1; i++) {
1102 size = DeviceContext.MeasureString (Items[i].ToString(), Font);
1104 if ((int) size.Width > listbox_info.max_itemwidth)
1105 listbox_info.max_itemwidth = (int) size.Width;
1114 SelectedItems.ReCreate ();
1115 SelectedIndices.ReCreate ();
1117 UpdateShowHorizontalScrollBar ();
1121 private void UpdateInternalClientRect (Rectangle client_rectangle)
1123 listbox_info.client_rect = client_rectangle;
1124 UpdateShowHorizontalScrollBar ();
1125 UpdateShowVerticalScrollBar ();
1126 RellocateScrollBars ();
1127 UpdateItemInfo (false, -1, -1);
1130 /* Determines if the horizontal scrollbar has to be displyed */
1131 private void UpdateShowHorizontalScrollBar ()
1134 bool enabled = true;
1136 if (MultiColumn) { /* Horizontal scrollbar is always shown in Multicolum mode */
1138 /* Is it really need it */
1139 int page_size = listbox_info.client_rect.Height / listbox_info.item_height;
1140 int fullpage = (page_size * (listbox_info.client_rect.Width / ColumnWidthInternal));
1142 if (Items.Count > fullpage) {
1145 else { /* Acording to MS Documentation ScrollAlwaysVisible only affects Horizontal scrollbars but
1146 this is not true for MultiColumn listboxes */
1147 if (ScrollAlwaysVisible == true) {
1153 } else { /* If large item*/
1155 if (listbox_info.max_itemwidth > listbox_info.client_rect.Width && HorizontalScrollbar) {
1157 hscrollbar_ctrl.Maximum = listbox_info.max_itemwidth;
1161 if (hscrollbar_ctrl.Enabled != enabled)
1162 hscrollbar_ctrl.Enabled = enabled;
1164 if (listbox_info.show_horizontalsb == show)
1167 listbox_info.show_horizontalsb = show;
1168 hscrollbar_ctrl.Visible = show;
1171 RellocateScrollBars ();
1177 /* Determines if the vertical scrollbar has to be displyed */
1178 private void UpdateShowVerticalScrollBar ()
1181 bool enabled = true;
1183 if (!MultiColumn) { /* Vertical scrollbar is never shown in Multicolum mode */
1184 if (Items.Count > listbox_info.page_size) {
1188 if (ScrollAlwaysVisible) {
1194 if (vscrollbar_ctrl.Enabled != enabled)
1195 vscrollbar_ctrl.Enabled = enabled;
1197 if (listbox_info.show_verticalsb == show)
1200 listbox_info.show_verticalsb = show;
1201 vscrollbar_ctrl.Visible = show;
1204 if (vscrollbar_ctrl.Enabled)
1205 vscrollbar_ctrl.Maximum = Items.Count - listbox_info.page_size;
1207 RellocateScrollBars ();
1214 private void VerticalScrollEvent (object sender, EventArgs e)
1216 LBoxInfo.top_item = /*listbox_info.page_size + */ vscrollbar_ctrl.Value;
1217 LBoxInfo.last_item = LastVisibleItem ();
1222 #endregion Private Methods
1225 ListBox.ObjectCollection
1227 public class ObjectCollection : IList, ICollection, IEnumerable
1230 internal class ListObjectComparer : IComparer
\r
1232 private ListBox owner;
\r
1234 public ListObjectComparer (ListBox owner)
\r
1236 this.owner = owner;
\r
1239 public int Compare (object a, object b)
\r
1241 string str1 = a.ToString ();
1242 string str2 = b.ToString ();
\r
1243 return str1.CompareTo (str2);
\r
1248 internal class ListItemComparer : IComparer
\r
1250 private ListBox owner;
\r
1252 public ListItemComparer (ListBox owner)
\r
1254 this.owner = owner;
\r
1257 public int Compare (object a, object b)
\r
1259 int index1 = ((ListBox.ListBoxItem) (a)).Index;
1260 int index2 = ((ListBox.ListBoxItem) (b)).Index;
1261 string str1 = owner.Items[index1].ToString ();
1262 string str2 = owner.Items[index2].ToString ();
\r
1263 return str1.CompareTo (str2);
\r
1267 private ListBox owner;
1268 private ArrayList object_items = new ArrayList ();
1269 private ArrayList listbox_items = new ArrayList ();
1271 public ObjectCollection (ListBox owner)
1276 public ObjectCollection (ListBox owner, object[] obj)
1282 public ObjectCollection (ListBox owner, ObjectCollection obj)
1288 #region Public Properties
1289 public virtual int Count {
1290 get { return object_items.Count; }
1293 public virtual bool IsReadOnly {
1294 get { return false; }
1297 public virtual object this [int index] {
1299 if (index < 0 || index >= Count)
1300 throw new ArgumentOutOfRangeException ("Index of out range");
1302 return object_items[index];
1305 if (index < 0 || index >= Count)
1306 throw new ArgumentOutOfRangeException ("Index of out range");
1308 object_items[index] = value;
1312 bool ICollection.IsSynchronized {
1313 get { return false; }
1316 object ICollection.SyncRoot {
1317 get { return this; }
1320 bool IList.IsFixedSize {
1321 get { return false; }
1324 #endregion Public Properties
1326 #region Public Methods
1327 public int Add (object item)
1331 idx = AddItem (item);
1332 owner.UpdateItemInfo (true, idx, idx);
1336 public void AddRange (object[] items)
1340 foreach (object mi in items)
1343 owner.UpdateItemInfo (true, cnt, Count);
1346 public void AddRange (ObjectCollection col)
1350 foreach (object mi in col)
1353 owner.UpdateItemInfo (true, cnt, Count);
1356 public virtual void Clear ()
1358 object_items.Clear ();
1359 listbox_items.Clear ();
1360 owner.UpdateItemInfo (false, -1, -1);
1362 public virtual bool Contains (object obj)
1364 return object_items.Contains (obj);
1367 public void CopyTo (object[] dest, int arrayIndex)
1369 object_items.CopyTo (dest, arrayIndex);
1372 void ICollection.CopyTo (Array dest, int index)
1374 object_items.CopyTo (dest, index);
1377 public virtual IEnumerator GetEnumerator ()
1379 return object_items.GetEnumerator ();
1382 int IList.Add (object item)
1387 public virtual int IndexOf (object value)
1389 return object_items.IndexOf (value);
1392 public virtual void Insert (int index, object item)
1394 throw new NotImplementedException ();
1397 public virtual void Remove (object value)
1399 RemoveAt (IndexOf (value));
1400 owner.UpdateItemInfo (false, -1, -1);
1403 public virtual void RemoveAt (int index)
1405 if (index < 0 || index >= Count)
1406 throw new ArgumentOutOfRangeException ("Index of out range");
1408 object_items.RemoveAt (index);
1409 listbox_items.RemoveAt (index);
1410 owner.UpdateItemInfo (false, -1, -1);
1412 #endregion Public Methods
1414 #region Private Methods
1415 private int AddItem (object item)
1417 int cnt = object_items.Count;
1418 object_items.Add (item);
1419 listbox_items.Add (new ListBox.ListBoxItem (cnt));
1423 // TODO: object_items have to be sorted, look at ListBoxItem. Are we using object theere?
1424 internal ListBox.ListBoxItem GetListBoxItem (int index)
1426 if (index < 0 || index >= Count)
1427 throw new ArgumentOutOfRangeException ("Index of out range");
1429 return (ListBox.ListBoxItem) listbox_items[index];
1432 internal void SetListBoxItem (ListBox.ListBoxItem item, int index)
1434 if (index < 0 || index >= Count)
1435 throw new ArgumentOutOfRangeException ("Index of out range");
1437 listbox_items[index] = item;
1440 internal void Sort ()
1442 /* Keep this order */
1443 listbox_items.Sort (new ListItemComparer (owner));
1444 object_items.Sort (new ListObjectComparer (owner));
1446 for (int i = 0; i < listbox_items.Count; i++) {
1447 ListBox.ListBoxItem item = GetListBoxItem (i);
1452 #endregion Private Methods
1456 ListBox.SelectedIndexCollection
1458 public class SelectedIndexCollection : IList, ICollection, IEnumerable
1460 private ListBox owner;
1461 private ArrayList indices = new ArrayList ();
1463 public SelectedIndexCollection (ListBox owner)
1468 #region Public Properties
1469 public virtual int Count {
1470 get { return indices.Count; }
1473 public virtual bool IsReadOnly {
1474 get { return true; }
1477 public int this [int index] {
1479 if (index < 0 || index >= Count)
1480 throw new ArgumentOutOfRangeException ("Index of out range");
1482 return (int) indices[index];
1486 bool ICollection.IsSynchronized {
1487 get { return true; }
1490 bool IList.IsFixedSize{
1491 get { return true; }
1494 object ICollection.SyncRoot {
1495 get { return this; }
1498 #endregion Public Properties
1500 #region Public Methods
1501 public bool Contains (int selectedIndex)
1503 return indices.Contains (selectedIndex);
1506 public virtual void CopyTo (Array dest, int index)
1508 indices.CopyTo (dest, index);
1511 public virtual IEnumerator GetEnumerator ()
1513 return indices.GetEnumerator ();
1516 int IList.Add (object obj)
1518 throw new NotSupportedException ();
1523 throw new NotSupportedException ();
1526 bool IList.Contains (object selectedIndex)
1528 return Contains ((int)selectedIndex);
1531 int IList.IndexOf (object selectedIndex)
1533 return IndexOf ((int) selectedIndex);
1536 void IList.Insert (int index, object value)
1538 throw new NotSupportedException ();
1541 void IList.Remove (object value)
1543 throw new NotSupportedException ();
1546 void IList.RemoveAt (int index)
1548 throw new NotSupportedException ();
1551 object IList.this[int index]{
1552 get {return indices[index]; }
1553 set {throw new NotImplementedException (); }
1556 public int IndexOf (int selectedIndex)
1558 return indices.IndexOf (selectedIndex);
1560 #endregion Public Methods
1562 #region Private Methods
1564 internal void AddIndex (int index)
1566 indices.Add (index);
1569 internal void ClearIndices ()
1574 internal void RemoveIndex (int index)
1576 indices.Remove (index);
1579 internal void ReCreate ()
1583 for (int i = 0; i < owner.Items.Count; i++) {
1584 ListBox.ListBoxItem item = owner.Items.GetListBoxItem (i);
1587 indices.Add (item.Index);
1591 #endregion Private Methods
1595 SelectedObjectCollection
1597 public class SelectedObjectCollection : IList, ICollection, IEnumerable
1599 private ListBox owner;
1600 private ArrayList object_items = new ArrayList ();
1602 public SelectedObjectCollection (ListBox owner)
1607 #region Public Properties
1608 public virtual int Count {
1609 get { return object_items.Count; }
1612 public virtual bool IsReadOnly {
1613 get { return true; }
1616 public virtual object this [int index] {
1618 if (index < 0 || index >= Count)
1619 throw new ArgumentOutOfRangeException ("Index of out range");
1621 return object_items[index];
1623 set {throw new NotSupportedException ();}
1626 bool ICollection.IsSynchronized {
1627 get { return true; }
1630 object ICollection.SyncRoot {
1631 get { return this; }
1634 bool IList.IsFixedSize {
1635 get { return true; }
1638 object IList.this[int index] {
1639 get { return object_items[index]; }
1640 set { throw new NotSupportedException (); }
1643 #endregion Public Properties
1645 #region Public Methods
1646 public virtual bool Contains (object selectedObject)
1648 return object_items.Contains (selectedObject);
1651 public virtual void CopyTo (Array dest, int index)
1653 object_items.CopyTo (dest, index);
1656 int IList.Add (object value)
1658 throw new NotSupportedException ();
1663 throw new NotSupportedException ();
1666 bool IList.Contains (object selectedIndex)
1668 throw new NotImplementedException ();
1671 int IList.IndexOf (object selectedIndex)
1673 return IndexOf ((int) selectedIndex);
1676 void IList.Insert (int index, object value)
1678 throw new NotSupportedException ();
1681 void IList.Remove (object value)
1683 throw new NotSupportedException ();
1686 void IList.RemoveAt (int index)
1688 throw new NotSupportedException ();
1691 public int IndexOf (int selectedIndex)
1693 return object_items.IndexOf (selectedIndex);
1696 public virtual IEnumerator GetEnumerator ()
1698 return object_items.GetEnumerator ();
1701 #endregion Public Methods
1703 #region Private Methods
1704 internal void AddObject (object obj)
1706 object_items.Add (obj);
1709 internal void ClearObjects ()
1711 object_items.Clear ();
1714 internal void ReCreate ()
1716 object_items.Clear ();
1718 for (int i = 0; i < owner.Items.Count; i++) {
1719 ListBox.ListBoxItem item = owner.Items.GetListBoxItem (i);
1722 object_items.Add (owner.Items[item.Index]);
1726 internal void RemoveObject (object obj)
1728 object_items.Remove (obj);
1733 #endregion Private Methods