Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/mcs
diff options
context:
space:
mode:
authorMike Kestner <mkestner@gmail.com>2006-02-28 01:11:58 +0300
committerMike Kestner <mkestner@gmail.com>2006-02-28 01:11:58 +0300
commit385e817034a3625fbbe1f65bafe7d94359840269 (patch)
tree0e28beea22d87ca334fc8ba78a07ede1f5685a49 /mcs
parent57fbaa058bc5806970bc9b2c1fd06398008ba3d4 (diff)
2006-02-27 Mike Kestner <mkestner@novell.com>
* ListView.cs: - Restructure layout and invalidation model to remove a ton of flicker from the control and speed up performance in general. - Add manual column resize, flickers like crazy, but I already have some ideas on how I'll fix that. (#76822) - Merge the three Icon-based views into a single layout method. - Move item selection interaction logic from the item since interaction with the collections is more appropriate to the view. - Deselection on non-item clicks. * ListViewItem.cs: - Encapsulate most of the layout. Add some internal props to trigger layout. Move to a model where Items invalidate themselves instead of just invalidating the whole control every time something changes. - Invalidate on Text/Caption changes. - switch to an offset based layout model to avoid having to absolute position every element on item moves. - correct checkbox layout to conform to MS layout. * ThemeWin32Classic.cs: - refactor some column header drawing code. - fix string justification for column headers (#76821) - make SmallIcon labels top justified for compat with MS impl. * ThemeClearlooks.cs: - adjust to new ListViewItem internal checkbox bounds api. svn path=/trunk/mcs/; revision=57357
Diffstat (limited to 'mcs')
-rw-r--r--mcs/class/Managed.Windows.Forms/System.Windows.Forms/ChangeLog26
-rw-r--r--mcs/class/Managed.Windows.Forms/System.Windows.Forms/ListView.cs384
-rw-r--r--mcs/class/Managed.Windows.Forms/System.Windows.Forms/ListViewItem.cs255
-rw-r--r--mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeClearlooks.cs2
-rw-r--r--mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeWin32Classic.cs58
5 files changed, 357 insertions, 368 deletions
diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ChangeLog b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ChangeLog
index 3929d8802cf..08b274fdbfe 100644
--- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ChangeLog
+++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ChangeLog
@@ -1,3 +1,29 @@
+2006-02-27 Mike Kestner <mkestner@novell.com>
+
+ * ListView.cs:
+ - Restructure layout and invalidation model to remove a ton of
+ flicker from the control and speed up performance in general.
+ - Add manual column resize, flickers like crazy, but I already have
+ some ideas on how I'll fix that. (#76822)
+ - Merge the three Icon-based views into a single layout method.
+ - Move item selection interaction logic from the item since
+ interaction with the collections is more appropriate to the view.
+ - Deselection on non-item clicks.
+ * ListViewItem.cs:
+ - Encapsulate most of the layout. Add some internal props to trigger
+ layout. Move to a model where Items invalidate themselves instead
+ of just invalidating the whole control every time something changes.
+ - Invalidate on Text/Caption changes.
+ - switch to an offset based layout model to avoid having to absolute
+ position every element on item moves.
+ - correct checkbox layout to conform to MS layout.
+ * ThemeWin32Classic.cs:
+ - refactor some column header drawing code.
+ - fix string justification for column headers (#76821)
+ - make SmallIcon labels top justified for compat with MS impl.
+ * ThemeClearlooks.cs:
+ - adjust to new ListViewItem internal checkbox bounds api.
+
2006-02-27 Jackson Harper <jackson@ximian.com>
* Control.cs: Change where implicit controls fall in the zorder.
diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ListView.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ListView.cs
index 9066811f135..70ec71df299 100644
--- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ListView.cs
+++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ListView.cs
@@ -22,6 +22,7 @@
// Authors:
// Ravindra Kumar (rkumar@novell.com)
// Jordi Mas i Hernandez, jordi@ximian.com
+// Mike Kestner (mkestner@novell.com)
//
// TODO:
// - Item text editing
@@ -29,7 +30,6 @@
// - Feedback for item activation, change in cursor types as mouse moves.
// - HideSelection
// - LabelEdit
-// - Manual column resizing
// - Drag and drop
@@ -61,6 +61,8 @@ namespace System.Windows.Forms
private ListViewItem clicked_item;
private ListViewItem last_clicked_item;
private ColumnHeaderCollection columns;
+ private ColumnHeader resize_column;
+ private bool column_resize_active = false;
private bool ctrl_pressed;
private bool shift_pressed;
internal ListViewItem focused_item;
@@ -525,7 +527,7 @@ namespace System.Windows.Forms
// do a hit test for the scrolled position
else {
foreach (ListViewItem item in this.items) {
- if (item.EntireRect.X >= h_marker && item.EntireRect.Y >= v_marker)
+ if (item.Bounds.X >= 0 && item.Bounds.Y >= 0)
return item;
}
return null;
@@ -564,8 +566,7 @@ namespace System.Windows.Forms
return 0;
foreach (ListViewItem item in this.items) {
- if (item.EntireRect.X + item.EntireRect.Width >= h_marker
- && item.EntireRect.Y + item.EntireRect.Height >= v_marker)
+ if (item.Bounds.Right >= 0 && item.Bounds.Bottom >= 0)
return item.Index;
}
return 0;
@@ -574,10 +575,10 @@ namespace System.Windows.Forms
}
- internal int LastItemIndex {
+ internal int LastVisibleIndex {
get {
for (int i = FirstVisibleIndex; i < Items.Count; i++) {
- if (Items[i].EntireRect.Y > v_marker + ClientRectangle.Bottom)
+ if (Items[i].Bounds.Y > ClientRectangle.Bottom)
return i -1;
}
@@ -786,19 +787,72 @@ namespace System.Windows.Forms
}
}
-
+ Size LargeIconItemSize {
+ get {
+ int w = Math.Max (text_size.Width, 2 + CheckBoxSize.Width + LargeImageList.ImageSize.Width);
+ int h = text_size.Height + 2 + Math.Max (CheckBoxSize.Height, LargeImageList.ImageSize.Height);
+ return new Size (w, h);
+ }
+ }
+
+ Size SmallIconItemSize {
+ get {
+ int w = text_size.Width + 2 + CheckBoxSize.Width + SmallImageList.ImageSize.Width;
+ int h = Math.Max (text_size.Height, Math.Max (CheckBoxSize.Height, SmallImageList.ImageSize.Height));
+ return new Size (w, h);
+ }
+ }
+
+ void LayoutIcons (bool large_icons, bool left_aligned, int x_spacing, int y_spacing)
+ {
+ if (items.Count == 0)
+ return;
+
+ Size sz = large_icons ? LargeIconItemSize : SmallIconItemSize;
+
+ int rows, cols;
+
+ if (left_aligned) {
+ rows = (int) Math.Floor ((double)client_area.Height / (double)(sz.Height + y_spacing));
+ if (rows == 0)
+ rows = 1;
+ cols = (int) Math.Ceiling ((double)items.Count / (double)rows);
+ } else {
+ cols = (int) Math.Floor ((double)client_area.Width / (double)(sz.Width + x_spacing));
+ if (cols == 0)
+ cols = 1;
+ rows = (int) Math.Ceiling ((double)items.Count / (double)cols);
+ }
+
+ layout_ht = rows * (sz.Height + y_spacing) - y_spacing;
+ layout_wd = cols * (sz.Width + x_spacing) - x_spacing;
+ int row = 0;
+ int col = 0;
+ foreach (ListViewItem item in items) {
+ int x = col * (sz.Width + x_spacing);
+ int y = row * (sz.Height + y_spacing);
+ item.Location = new Point (x, y);
+ item.Layout ();
+ if (left_aligned) {
+ if (++row == rows) {
+ row = 0;
+ col++;
+ }
+ } else {
+ if (++col == cols) {
+ col = 0;
+ row++;
+ }
+ }
+ }
+ }
+
// Sets the location of every item on
// the ListView as per the view
private void CalculateListView (ListViewAlignment align)
{
int current_pos_x = 0; // our x-position marker
int current_pos_y = 0; // our y-position marker
- int item_ht;
- int item_wd;
- int max; // max x_pos or y_pos depending on the alignment
- int current = 0; // current row or column
- int vertical_spacing = ThemeEngine.Current.ListViewVerticalSpacing;
- int horizontal_spacing = ThemeEngine.Current.ListViewHorizontalSpacing;
CalcTextSize ();
@@ -806,8 +860,7 @@ namespace System.Windows.Forms
case View.Details:
// ColumnHeaders are not drawn if headerstyle is none
- int ht = (this.header_style == ColumnHeaderStyle.None) ?
- 0 : this.Font.Height + 3;
+ int ht = 0;
if (columns.Count > 0) {
foreach (ColumnHeader col in columns) {
@@ -816,149 +869,41 @@ namespace System.Windows.Forms
col.CalcColumnHeader ();
current_pos_x += col.Wd;
}
- this.layout_wd = current_pos_x;
+
+ if (header_style != ColumnHeaderStyle.None)
+ ht = columns [0].Ht;
+ layout_wd = current_pos_x;
}
// set the position marker for placing items
// vertically down
- current_pos_y = ht;
+ current_pos_y = ht + 2;
if (items.Count > 0) {
foreach (ListViewItem item in items) {
- item.location.X = 0;
- item.location.Y = current_pos_y;
- item.CalcListViewItem ();
- current_pos_y += item.EntireRect.Height;
+ item.Layout ();
+ item.Location = new Point (0, current_pos_y);
+ current_pos_y += item.Bounds.Height + 2;
}
- this.layout_ht = current_pos_y;
+ layout_ht = current_pos_y;
// some space for bottom gridline
- if (this.grid_lines)
- this.layout_ht += 2;
+ if (grid_lines)
+ layout_ht += 2;
}
break;
case View.SmallIcon:
- vertical_spacing = 0;
- horizontal_spacing = 0;
- goto case View.LargeIcon;
+ LayoutIcons (false, alignment == ListViewAlignment.Left, 4, 2);
+ break;
case View.LargeIcon:
- if (items.Count > 0) {
- items [0].CalcListViewItem ();
- item_ht = items [0].EntireRect.Height;
- item_wd = items [0].EntireRect.Width;
-
- // top (default) and snaptogrid alignments are handled same way
- if (align == ListViewAlignment.Left) {
- max = client_area.Height;
- foreach (ListViewItem item in items) {
- item.location.X = current_pos_x +
- horizontal_spacing;
- item.location.Y = 0;
- item.CalcListViewItem ();
- current_pos_y += item_ht;
-
- current ++; // just to know about the last element
- // we just did the last item
- if (current == items.Count) {
- if (max < current_pos_y)
- max = current_pos_y;
- current_pos_x = item.EntireRect.Right;
- break;
- }
- else {
- // is there enough space for another row ?
- if ((current_pos_y + vertical_spacing
- + item_ht) <= client_area.Height)
- current_pos_y += vertical_spacing;
- else {
- // start another column
- // make current_pos_y as the
- // max value and reset
- // current_pos_y value.
- max = current_pos_y;
- current_pos_x += item_wd;
- current_pos_y = 0;
- }
- }
- }
- // adjust the layout dimensions
- this.layout_ht = max;
- this.layout_wd = current_pos_x;
- }
- else { // other default/top alignment
- max = client_area.Width;
- foreach (ListViewItem item in items) {
- item.location.X = current_pos_x +
- horizontal_spacing;
-
- item.location.Y = current_pos_y;
- item.CalcListViewItem ();
- current_pos_x += item_wd;
-
- current ++; // just to know about the last element
- // we just did the last item
- if (current == items.Count) {
- if (max < current_pos_x)
- max = current_pos_x;
- current_pos_y = item.EntireRect.Bottom;
- break;
- }
- else {
- // is there enough space for another column?
- if ((current_pos_x + horizontal_spacing
- + item_wd) <= client_area.Width)
- continue;
- else {
- // start another row
- // make current_pos_x as the
- // max value and reset
- // current_pos_x value.
- max = current_pos_x;
- current_pos_y += (item_ht +
- vertical_spacing);
- current_pos_x = 0;
- }
- }
- }
- // adjust the layout dimensions
- this.layout_wd = max;
- this.layout_ht = current_pos_y;
- }
- }
+ LayoutIcons (true, alignment == ListViewAlignment.Left,
+ ThemeEngine.Current.ListViewHorizontalSpacing,
+ ThemeEngine.Current.ListViewVerticalSpacing);
break;
case View.List:
- if (items.Count > 0) {
- items [0].CalcListViewItem ();
- item_ht = items [0].EntireRect.Height;
- item_wd = items [0].EntireRect.Width;
-
- max = client_area.Height / item_ht;
- if (max == 0)
- max = 1; // we draw at least one row
-
- foreach (ListViewItem item in items) {
- item.location.X = current_pos_x;
- item.location.Y = current_pos_y;
- item.CalcListViewItem ();
- current ++;
- if (current == max) {
- current_pos_x += item_wd;
- current_pos_y = 0;
- current = 0;
- }
- else
- current_pos_y += item_ht;
- }
-
- // adjust the layout dimensions
- this.layout_ht = max * item_ht;
- if (current == 0) // we have fully filled layout
- this.layout_wd = current_pos_x;
- else
- this.layout_wd = current_pos_x + item_wd;
- }
+ LayoutIcons (false, true, 4, 2);
break;
}
@@ -966,6 +911,20 @@ namespace System.Windows.Forms
}
+ void SelectItem (ListViewItem item)
+ {
+ if (!CanMultiselect && SelectedItems.Count > 0) {
+ SelectedItems.Clear ();
+ SelectedIndices.list.Clear ();
+ }
+
+ if (!SelectedItems.Contains (item)) {
+ SelectedItems.list.Add (item);
+ SelectedIndices.list.Add (item.Index);
+ }
+ item.Selected = true;
+ }
+
private bool KeySearchString (KeyEventArgs ke)
{
int current_tickcnt = Environment.TickCount;
@@ -981,7 +940,7 @@ namespace System.Windows.Forms
if (CultureInfo.CurrentCulture.CompareInfo.IsPrefix (Items[i].Text, keysearch_text,
CompareOptions.IgnoreCase)) {
SetFocusedItem (Items [i]);
- items [i].Selected = true;
+ SelectItem (items [i]);
EnsureVisible (i);
break;
}
@@ -1081,7 +1040,7 @@ namespace System.Windows.Forms
}
if (index != -1) {
- items [index].Selected = true;
+ SelectItem (items [index]);
SetFocusedItem (items [index]);
EnsureVisible (index);
}
@@ -1111,6 +1070,12 @@ namespace System.Windows.Forms
// hit test on columns
if (this.view == View.Details && this.columns.Count > 0) {
+ if (resize_column != null) {
+ column_resize_active = true;
+ Capture = true;
+ return;
+ }
+
foreach (ColumnHeader col in this.columns) {
if (col.Rect.Contains (hit)) {
this.clicked_column = col;
@@ -1121,7 +1086,9 @@ namespace System.Windows.Forms
if (this.clicked_column != null) {
this.clicked_column.pressed = true;
- this.Redraw (false);
+ Rectangle bounds = clicked_column.Rect;
+ bounds.X -= h_marker;
+ Invalidate (bounds);
return;
}
}
@@ -1129,9 +1096,9 @@ namespace System.Windows.Forms
// hit test on items
// we need to take scrolling into account
- hit = new Point (me.X + h_marker, me.Y + v_marker);
+ hit = new Point (me.X, me.Y);
foreach (ListViewItem item in this.items) {
- if (item.CheckRect.Contains (hit)) {
+ if (item.CheckRectReal.Contains (hit)) {
CheckState curr_state = item.Checked ?
CheckState.Checked : CheckState.Unchecked;
if (item.Checked)
@@ -1141,7 +1108,6 @@ namespace System.Windows.Forms
CheckState new_state = item.Checked ?
CheckState.Checked : CheckState.Unchecked;
- this.Redraw (false);
// Raise the ItemCheck event
ItemCheckEventArgs ice = new ItemCheckEventArgs (item.Index,
@@ -1153,25 +1119,24 @@ namespace System.Windows.Forms
if (this.view == View.Details &&
this.FullRowSelect == false) {
- if (item.LabelRect.Contains (hit)) {
+ if (item.GetBounds (ItemBoundsPortion.Label).Contains (hit)) {
this.clicked_item = item;
break;
}
}
else {
- if (item.EntireRect.Contains (hit)) {
+ if (item.Bounds.Contains (hit)) {
this.clicked_item = item;
break;
}
}
}
- // set the FocusedItem to be the current clicked_item
SetFocusedItem (clicked_item);
if (clicked_item != null) {
bool changed = !clicked_item.Selected;
- clicked_item.Selected = true;
+ SelectItem (clicked_item);
// Only Raise the event if the selected item has changed
if (changed)
@@ -1183,16 +1148,12 @@ namespace System.Windows.Forms
OnDoubleClick (EventArgs.Empty);
else if (me.Clicks == 1 && clicked_item != null)
OnClick (EventArgs.Empty);
-
- this.Redraw (false);
} else if (selected_indices.Count > 0) {
- // NOTE: selected_indices isn't computed properly so
- // this doesn't actually work
-
// Raise the event if there was at least one item
// selected and the user click on a dead area (unselecting all)
+ SelectedItems.Clear ();
+ SelectedIndices.list.Clear ();
OnSelectedIndexChanged (EventArgs.Empty);
- Redraw (false);
}
}
@@ -1208,23 +1169,49 @@ namespace System.Windows.Forms
ListViewItem item = this.GetItemAt (hit.X, hit.Y);
if (item != null) {
- item.Selected = true;
+ SelectItem (item);
// Raise the event
this.OnSelectedIndexChanged (new EventArgs ());
-
- this.Redraw (false);
}
}
private void ListView_MouseMove (object sender, MouseEventArgs me)
{
+ if (View != View.Details || Columns.Count < 2)
+ return;
+
// Column header is always at the top. It can
// scroll only horizontally. So, we have to take
// only horizontal scrolling into account
Point hit = new Point (me.X + h_marker, me.Y);
+ if (column_resize_active) {
+ resize_column.Width = hit.X - resize_column.X;
+ if (resize_column.Width < 0)
+ resize_column.Width = 0;
+ return;
+ }
+
+ resize_column = null;
+
+ for (int i = 0; i < Columns.Count; i++) {
+ Rectangle zone = Columns [i].Rect;
+ zone.X = zone.Right - 5;
+ zone.Width = 10;
+ if (zone.Contains (hit)) {
+ resize_column = Columns [i];
+ break;
+ }
+ }
+
+ if (resize_column == null)
+ Cursor = Cursors.Default;
+ else
+ Cursor = Cursors.VSplit;
+
// non-null clicked_col means mouse down has happened
// on a column
+ // FIXME: this seems to be drag related
if (this.clicked_column != null) {
if (this.clicked_column.pressed == false &&
this.clicked_column.Rect.Contains (hit)) {
@@ -1245,12 +1232,22 @@ namespace System.Windows.Forms
if (items.Count == 0)
return;
+ if (column_resize_active) {
+ Capture = false;
+ column_resize_active = false;
+ resize_column = null;
+ Cursor = Cursors.Default;
+ return;
+ }
+
Point hit = new Point (me.X, me.Y);
if (this.clicked_column != null) {
if (this.clicked_column.pressed) {
this.clicked_column.pressed = false;
- this.Redraw (false);
+ Rectangle bounds = clicked_column.Rect;
+ bounds.X -= h_marker;
+ Invalidate (bounds);
// Raise the ColumnClick event
this.OnColumnClick (new ColumnClickEventArgs
@@ -1262,9 +1259,9 @@ namespace System.Windows.Forms
Rectangle rect = Rectangle.Empty;
if (this.clicked_item != null) {
if (this.view == View.Details && !this.full_row_select)
- rect = this.clicked_item.LabelRect;
+ rect = this.clicked_item.GetBounds (ItemBoundsPortion.Label);
else
- rect = this.clicked_item.EntireRect;
+ rect = this.clicked_item.Bounds;
// We handle double click in a separate handler
if (this.activation != ItemActivation.Standard &&
@@ -1290,8 +1287,7 @@ namespace System.Windows.Forms
private void ListView_Paint (object sender, PaintEventArgs pe)
{
- if (this.Width <= 0 || this.Height <= 0 ||
- this.Visible == false || this.updating == true)
+ if (Width <= 0 || Height <= 0 || !Visible || updating)
return;
CalculateScrollBars ();
@@ -1329,11 +1325,6 @@ namespace System.Windows.Forms
int pixels = h_marker - h_scroll.Value;
Rectangle area = client_area;
- if (View == View.Details && Columns.Count > 0) {
- area.Y += Columns[0].Ht;
- area.Height -= Columns[0].Ht;
- }
-
h_marker = h_scroll.Value;
XplatUI.ScrollWindow (Handle, area, pixels, 0, false);
}
@@ -1525,37 +1516,24 @@ namespace System.Windows.Forms
public void EnsureVisible (int index)
{
- if (index < 0 || index >= this.items.Count || this.scrollable == false)
+ if (index < 0 || index >= items.Count || scrollable == false)
return;
- // dimensions of visible area
- int view_wd = client_area.Width;
- int view_ht = client_area.Height;
- // visible area is decided by the h_marker and v_marker
- Rectangle view_rect = new Rectangle (h_marker, v_marker, view_wd, view_ht);
-
- // an item's bounding rect
- Rectangle rect = this.items [index].EntireRect;
+ Rectangle view_rect = new Rectangle (0, 0, client_area.Width, client_area.Height);
+ Rectangle bounds = items [index].Bounds;
- // we don't need to do anything if item is visible.
- // visible area is represented by (0,0,view_wd,view_ht)
- if (view_rect.Contains (rect))
+ if (view_rect.Contains (bounds))
return;
- // Scroll Left or Up
- if ((rect.Left < view_rect.Left) || (rect.Top < view_rect.Top)) {
- if (rect.Left < view_rect.Left)
- this.h_scroll.Value -= (view_rect.Left - rect.Left);
- if (rect.Top < view_rect.Top)
- this.v_scroll.Value -= (view_rect.Top - rect.Top);
- }
- // Scroll Right or Down
- else {
- if (rect.Right > view_rect.Right)
- this.h_scroll.Value += (rect.Right - view_rect.Right);
- if (rect.Bottom > view_rect.Bottom)
- this.v_scroll.Value += (rect.Bottom - view_rect.Bottom);
- }
+ if (bounds.Left < 0)
+ h_scroll.Value += bounds.Left;
+ else if (bounds.Right > view_rect.Right)
+ h_scroll.Value += (bounds.Right - view_rect.Right);
+
+ if (bounds.Top < 0)
+ v_scroll.Value += bounds.Top;
+ else if (bounds.Bottom > view_rect.Bottom)
+ v_scroll.Value += (bounds.Bottom - view_rect.Bottom);
}
public ListViewItem GetItemAt (int x, int y)
@@ -2043,7 +2021,7 @@ namespace System.Windows.Forms
if (list.Contains (value))
throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
- value.owner = this.owner;
+ value.Owner = owner;
list [displayIndex] = value;
owner.Redraw (true);
@@ -2079,7 +2057,7 @@ namespace System.Windows.Forms
if (list.Contains (value))
throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
- value.owner = this.owner;
+ value.Owner = owner;
list.Add (value);
if (owner.Sorting != SortOrder.None)
@@ -2111,7 +2089,7 @@ namespace System.Windows.Forms
owner.CheckedIndices.list.Clear ();
foreach (ListViewItem item in values) {
- item.owner = this.owner;
+ item.Owner = owner;
list.Add (item);
}
@@ -2161,7 +2139,7 @@ namespace System.Windows.Forms
else
li = new ListViewItem (item.ToString ());
- li.owner = this.owner;
+ li.Owner = owner;
result = list.Add (li);
owner.Redraw (true);
@@ -2206,7 +2184,7 @@ namespace System.Windows.Forms
if (list.Contains (item))
throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
- item.owner = this.owner;
+ item.Owner = owner;
list.Insert (index, item);
owner.Redraw (true);
return item;
@@ -2411,14 +2389,10 @@ namespace System.Windows.Forms
#region Public Methods
public virtual void Clear ()
{
- // mark the items as unselected before clearing the list
for (int i = 0; i < list.Count; i++)
- ((ListViewItem) list [i]).selected = false;
+ ((ListViewItem) list [i]).Selected = false;
list.Clear ();
-
- if (owner != null)
- owner.Invalidate ();
}
public bool Contains (ListViewItem item)
diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ListViewItem.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ListViewItem.cs
index dc223d13aef..6e5d38ef7fc 100644
--- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ListViewItem.cs
+++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ListViewItem.cs
@@ -53,15 +53,13 @@ namespace System.Windows.Forms
private object tag;
private bool use_item_style = true;
- // internal variables
- internal Rectangle checkbox_rect; // calculated by CalcListViewItem method
- internal Rectangle entire_rect;
- internal Rectangle icon_rect;
- internal Rectangle item_rect;
- internal Rectangle label_rect;
- internal Point location = Point.Empty; // set by the ListView control
- internal ListView owner;
- internal bool selected;
+ Rectangle bounds;
+ Rectangle checkbox_rect; // calculated by CalcListViewItem method
+ Rectangle icon_rect;
+ Rectangle item_rect;
+ Rectangle label_rect;
+ ListView owner;
+ bool selected;
#endregion Instance Variables
@@ -144,8 +142,9 @@ namespace System.Windows.Forms
if (is_checked == value)
return;
+ is_checked = value;
+
if (owner != null) {
- is_checked = value;
if (is_checked) {
if (owner.CheckedItems.Contains (this) == false) {
owner.CheckedItems.list.Add (this);
@@ -157,8 +156,9 @@ namespace System.Windows.Forms
owner.CheckedIndices.list.Remove (this.Index);
}
- owner.Invalidate (Bounds);
+ Layout ();
}
+ Invalidate ();
}
}
@@ -173,7 +173,8 @@ namespace System.Windows.Forms
is_focused = value;
if (owner != null)
- owner.Invalidate (Bounds);
+ Layout ();
+ Invalidate ();
}
}
@@ -196,7 +197,8 @@ namespace System.Windows.Forms
sub_items[0].Font = value;
if (owner != null)
- owner.Invalidate (Bounds);
+ Layout ();
+ Invalidate ();
}
}
@@ -229,7 +231,8 @@ namespace System.Windows.Forms
image_index = value;
if (owner != null)
- owner.Invalidate (Bounds);
+ Layout ();
+ Invalidate ();
}
}
@@ -265,27 +268,14 @@ namespace System.Windows.Forms
public bool Selected {
get { return selected; }
set {
- if (owner != null) {
- if (owner.CanMultiselect == false &&
- owner.SelectedItems.Count > 0) {
- owner.SelectedItems.Clear ();
- owner.SelectedIndices.list.Clear ();
- }
+ if (selected == value)
+ return;
- selected = value;
- if (selected) {
- if (owner.SelectedItems.Contains (this) == false) {
- owner.SelectedItems.list.Add (this);
- owner.SelectedIndices.list.Add (this.Index);
- }
- }
- else {
- owner.SelectedItems.list.Remove (this);
- owner.SelectedIndices.list.Remove (this.Index);
- }
-
- owner.Invalidate (Bounds);
- }
+ selected = value;
+
+ if (owner != null)
+ Layout ();
+ Invalidate ();
}
}
@@ -327,7 +317,16 @@ namespace System.Windows.Forms
else
return "";
}
- set { this.sub_items [0].Text = value; }
+ set {
+ if (sub_items [0].Text == value)
+ return;
+
+ sub_items [0].Text = value;
+
+ if (owner != null)
+ Layout ();
+ Invalidate ();
+ }
}
[DefaultValue (true)]
@@ -380,42 +379,34 @@ namespace System.Windows.Forms
if (owner == null)
return Rectangle.Empty;
- /* Original Ravi's design calculated all items in a virtual space
- We convert them real screen positions
- */
- switch (portion) {
+ Rectangle rect;
- case ItemBoundsPortion.Icon: {
- Rectangle rect = icon_rect;
- rect.X -= owner.h_marker;
- rect.Y -= owner.v_marker;
- return rect;
- }
+ switch (portion) {
+ case ItemBoundsPortion.Icon:
+ rect = icon_rect;
+ break;
- case ItemBoundsPortion.Label: {
- Rectangle rect = label_rect;
- rect.X -= owner.h_marker;
- rect.Y -= owner.v_marker;
- return rect;
- }
+ case ItemBoundsPortion.Label:
+ rect = label_rect;
+ break;
- case ItemBoundsPortion.ItemOnly: {
- Rectangle rect = item_rect;
- rect.X -= owner.h_marker;
- rect.Y -= owner.v_marker;
- return rect;
- }
+ case ItemBoundsPortion.ItemOnly:
+ rect = item_rect;
+ break;
- case ItemBoundsPortion.Entire: {
- Rectangle rect = entire_rect;
+ case ItemBoundsPortion.Entire:
+ rect = bounds;
rect.X -= owner.h_marker;
rect.Y -= owner.v_marker;
return rect;
- }
default:
throw new ArgumentException ("Invalid value for portion.");
}
+
+ rect.X += bounds.X - owner.h_marker;
+ rect.Y += bounds.Y - owner.v_marker;
+ return rect;
}
void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
@@ -452,42 +443,71 @@ namespace System.Windows.Forms
internal Rectangle CheckRectReal {
get {
Rectangle rect = checkbox_rect;
- rect.X -= owner.h_marker;
- rect.Y -= owner.v_marker;
+ rect.X += bounds.X - owner.h_marker;
+ rect.Y += bounds.Y - owner.v_marker;
return rect;
}
}
- internal Rectangle CheckRect {
+ Rectangle CheckRect {
get { return this.checkbox_rect; }
}
- internal Rectangle EntireRect {
- get { return this.entire_rect; }
- }
-
- internal Rectangle IconRect {
+ Rectangle IconRect {
get { return this.icon_rect; }
}
- internal Rectangle LabelRect {
+ Rectangle LabelRect {
get { return this.label_rect; }
}
- internal void CalcListViewItem ()
+ internal Point Location {
+ set {
+ if (bounds.X == value.X && bounds.Y == value.Y)
+ return;
+
+ Rectangle prev = Bounds;
+ bounds.X = value.X;
+ bounds.Y = value.Y;
+ if (owner != null) {
+ if (prev != Rectangle.Empty)
+ owner.Invalidate (prev);
+ owner.Invalidate (Bounds);
+ }
+ }
+ }
+
+ internal ListView Owner {
+ set {
+ if (owner == value)
+ return;
+
+ owner = value;
+ if (owner != null)
+ Layout ();
+ Invalidate ();
+ }
+ }
+
+ private void Invalidate ()
+ {
+ if (owner == null)
+ return;
+
+ owner.Invalidate (Bounds);
+ }
+
+ internal void Layout ()
{
int item_ht;
+ Rectangle total;
Size text_size = owner.text_size;
+ checkbox_rect = Rectangle.Empty;
if (owner.CheckBoxes)
checkbox_rect.Size = owner.CheckBoxSize;
- else
- checkbox_rect = Rectangle.Empty;
-
- checkbox_rect.Location = this.location;
switch (owner.View) {
-
case View.Details:
// LAMESPEC: MSDN says, "In all views except the details
// view of the ListView, this value specifies the same
@@ -495,104 +515,85 @@ namespace System.Windows.Forms
// returns same bounding rectangles for Item and Entire
// values in the case of Details view.
- icon_rect.X = checkbox_rect.X + checkbox_rect.Width + 2;
- icon_rect.Y = checkbox_rect.Y;
-
- item_ht = Math.Max (owner.CheckBoxSize.Height + 1,
- text_size.Height);
+ icon_rect = label_rect = Rectangle.Empty;
+ icon_rect.X = checkbox_rect.Width + 2;
+ item_ht = Math.Max (owner.CheckBoxSize.Height, text_size.Height);
if (owner.SmallImageList != null) {
- item_ht = Math.Max (item_ht,
- owner.SmallImageList.ImageSize.Height + 1);
+ item_ht = Math.Max (item_ht, owner.SmallImageList.ImageSize.Height);
icon_rect.Width = owner.SmallImageList.ImageSize.Width;
}
- else
- icon_rect.Width = 0;
- label_rect.Height = checkbox_rect.Height = icon_rect.Height = item_ht;
+ label_rect.Height = icon_rect.Height = item_ht;
+ checkbox_rect.Y = icon_rect.Height - checkbox_rect.Height - 1;
- label_rect.X = icon_rect.X + icon_rect.Width;
- label_rect.Y = icon_rect.Y;
+ label_rect.X = icon_rect.Right + 1;
if (owner.Columns.Count > 0)
label_rect.Width = Math.Max (text_size.Width, owner.Columns[0].Wd);
else
label_rect.Width = text_size.Width;
- item_rect = entire_rect = Rectangle.Union
+ item_rect = total = Rectangle.Union
(Rectangle.Union (checkbox_rect, icon_rect), label_rect);
+ bounds.Size = total.Size;
// Take into account the rest of columns. First column
// is already taken into account above.
for (int i = 1; i < owner.Columns.Count; i++) {
item_rect.Width += owner.Columns [i].Wd;
- entire_rect.Width += owner.Columns [i].Wd;
+ bounds.Width += owner.Columns [i].Wd;
}
break;
case View.LargeIcon:
+ label_rect = icon_rect = Rectangle.Empty;
+
if (owner.LargeImageList != null) {
- icon_rect.Width = owner.LargeImageList.ImageSize.Width + 16;
- icon_rect.Height = owner.LargeImageList.ImageSize.Height + 4;
- }
- else {
- icon_rect.Width = 16;
- icon_rect.Height = 4;
+ icon_rect.Width = owner.LargeImageList.ImageSize.Width;
+ icon_rect.Height = owner.LargeImageList.ImageSize.Height;
}
- if (text_size.Width <= (checkbox_rect.Width + icon_rect.Width)) {
- icon_rect.X = checkbox_rect.X + checkbox_rect.Width;
- icon_rect.Y = checkbox_rect.Y;
+ checkbox_rect.Y = icon_rect.Height - checkbox_rect.Height - 1;
- label_rect.X = icon_rect.X + (icon_rect.Width
- - text_size.Width) / 2;
- label_rect.Y = Math.Max (checkbox_rect.Bottom,
- icon_rect.Bottom) + 2;
+ if (text_size.Width <= (checkbox_rect.Width + icon_rect.Width)) {
+ icon_rect.X = checkbox_rect.Width + 1;
+ label_rect.X = icon_rect.X + (icon_rect.Width - text_size.Width) / 2;
+ label_rect.Y = Math.Max (checkbox_rect.Bottom, icon_rect.Bottom) + 2;
label_rect.Size = text_size;
- }
- else {
- label_rect.X = this.location.X;
-
- int centerX = label_rect.X + text_size.Width / 2;
+ } else {
+ int centerX = text_size.Width / 2;
icon_rect.X = centerX - icon_rect.Width / 2;
checkbox_rect.X = (icon_rect.X - checkbox_rect.Width);
-
- icon_rect.Y = checkbox_rect.Y;
-
- label_rect.Y = Math.Max (checkbox_rect.Bottom,
- icon_rect.Bottom) + 2;
+ label_rect.Y = Math.Max (checkbox_rect.Bottom, icon_rect.Bottom) + 2;
label_rect.Size = text_size;
}
item_rect = Rectangle.Union (icon_rect, label_rect);
- entire_rect = Rectangle.Union (item_rect, checkbox_rect);
+ total = Rectangle.Union (item_rect, checkbox_rect);
+ bounds.Size = total.Size;
break;
case View.List:
- goto case View.SmallIcon;
-
case View.SmallIcon:
- icon_rect.X = checkbox_rect.X + checkbox_rect.Width;
- icon_rect.Y = checkbox_rect.Y;
-
+ label_rect = icon_rect = Rectangle.Empty;
+ icon_rect.X = checkbox_rect.Width + 1;
item_ht = Math.Max (owner.CheckBoxSize.Height, text_size.Height);
if (owner.SmallImageList != null) {
- item_ht = Math.Max (item_ht,
- owner.SmallImageList.ImageSize.Height + 1);
+ item_ht = Math.Max (item_ht, owner.SmallImageList.ImageSize.Height);
icon_rect.Width = owner.SmallImageList.ImageSize.Width;
+ icon_rect.Height = owner.SmallImageList.ImageSize.Height;
}
- else
- icon_rect.Width = 0;
-
- label_rect.Height = checkbox_rect.Height = icon_rect.Height = item_ht;
- label_rect.X = icon_rect.X + icon_rect.Width;
- label_rect.Y = icon_rect.Y;
+ checkbox_rect.Y = icon_rect.Height - checkbox_rect.Height + 1;
+ label_rect.X = icon_rect.Right + 1;
label_rect.Width = text_size.Width;
+ label_rect.Height = icon_rect.Height = item_ht;
item_rect = Rectangle.Union (icon_rect, label_rect);
- entire_rect = Rectangle.Union (item_rect, checkbox_rect);
+ total = Rectangle.Union (item_rect, checkbox_rect);
+ bounds.Size = total.Size;
break;
}
diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeClearlooks.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeClearlooks.cs
index 08ded7e05d8..2697229e025 100644
--- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeClearlooks.cs
+++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeClearlooks.cs
@@ -2486,7 +2486,7 @@ namespace System.Windows.Forms {
if ( control.View == View.Details ) {
if ( control.FullRowSelect ) {
// fill the entire rect excluding the checkbox
- full_rect.Location = item.LabelRect.Location;
+ full_rect.Location = item.GetBounds (ItemBoundsPortion.Label).Location;
dc.FillRectangle( this.ResPool.GetSolidBrush
( this.ColorHighlight ), full_rect );
} else {
diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeWin32Classic.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeWin32Classic.cs
index f3a596777c7..1dcb7cceef2 100644
--- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeWin32Classic.cs
+++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ThemeWin32Classic.cs
@@ -1428,7 +1428,7 @@ namespace System.Windows.Forms
if (!details || control.Columns.Count > 0) {
int first = control.FirstVisibleIndex;
- for (int i = first; i <= control.LastItemIndex; i ++) {
+ for (int i = first; i <= control.LastVisibleIndex; i ++) {
if (clip.IntersectsWith (control.Items[i].GetBounds (ItemBoundsPortion.Entire)))
DrawListViewItem (dc, control, control.Items[i]);
}
@@ -1486,35 +1486,20 @@ namespace System.Windows.Forms
dc.FillRectangle (ResPool.GetSolidBrush (control.BackColor),
0, 0, control.TotalWidth, control.Font.Height + 5);
if (control.Columns.Count > 0) {
- if (control.HeaderStyle == ColumnHeaderStyle.Clickable) {
- foreach (ColumnHeader col in control.Columns) {
- Rectangle rect = col.Rect;
- rect.X -= control.h_marker;
- this.CPDrawButton (dc, rect,
- (col.Pressed ?
- ButtonState.Pushed :
- ButtonState.Normal));
- dc.DrawString (col.Text, DefaultFont,
- ResPool.GetSolidBrush
- (this.ColorControlText),
- rect.X + 3,
- rect.Y + rect.Height/2 + 1,
- col.Format);
- }
- }
- // Non-clickable columns
- else {
- foreach (ColumnHeader col in control.Columns) {
- Rectangle rect = col.Rect;
- rect.X -= control.h_marker;
- this.CPDrawButton (dc, rect, ButtonState.Flat);
- dc.DrawString (col.Text, DefaultFont,
- ResPool.GetSolidBrush
- (this.ColorControlText),
- rect.X + 3,
- rect.Y + rect.Height/2 + 1,
- col.Format);
- }
+ foreach (ColumnHeader col in control.Columns) {
+ Rectangle rect = col.Rect;
+ rect.X -= control.h_marker;
+ ButtonState state;
+ if (control.HeaderStyle == ColumnHeaderStyle.Clickable)
+ state = col.Pressed ? ButtonState.Pushed : ButtonState.Normal;
+ else
+ state = ButtonState.Flat;
+ this.CPDrawButton (dc, rect, state);
+ rect.X += 3;
+ rect.Width -= 8;
+ dc.DrawString (col.Text, DefaultFont,
+ ResPool.GetSolidBrush (ColorControlText),
+ rect, col.Format);
}
}
}
@@ -1593,7 +1578,10 @@ namespace System.Windows.Forms
// draw the item text
// format for the item text
StringFormat format = new StringFormat ();
- format.LineAlignment = StringAlignment.Center;
+ if (control.View == View.SmallIcon)
+ format.LineAlignment = StringAlignment.Near;
+ else
+ format.LineAlignment = StringAlignment.Center;
if (control.View == View.LargeIcon)
format.Alignment = StringAlignment.Center;
else
@@ -1606,7 +1594,7 @@ namespace System.Windows.Forms
if (control.View == View.Details) {
if (control.FullRowSelect) {
// fill the entire rect excluding the checkbox
- full_rect.Location = item.LabelRect.Location;
+ full_rect.Location = item.GetBounds (ItemBoundsPortion.Label).Location;
dc.FillRectangle (this.ResPool.GetSolidBrush
(this.ColorHighlight), full_rect);
}
@@ -1653,14 +1641,14 @@ namespace System.Windows.Forms
// set the format for subitems
format.FormatFlags = StringFormatFlags.NoWrap;
- format.Alignment = StringAlignment.Near;
// 0th subitem is the item already drawn
for (int index = 1; index < count; index++) {
subItem = subItems [index];
col = control.Columns [index];
- sub_item_rect.X = col.Rect.Left;
- sub_item_rect.Width = col.Wd;
+ format.Alignment = col.Format.Alignment;
+ sub_item_rect.X = col.Rect.Left + 3;
+ sub_item_rect.Width = col.Wd - 6;
sub_item_rect.X -= control.h_marker;
SolidBrush sub_item_back_br = null;