private bool allow_column_reorder = false;
private bool auto_arrange = true;
private bool check_boxes = false;
- private CheckedIndexCollection checked_indices;
- private CheckedListViewItemCollection checked_items;
- private ColumnHeaderCollection columns;
+ private readonly CheckedIndexCollection checked_indices;
+ private readonly CheckedListViewItemCollection checked_items;
+ private readonly ColumnHeaderCollection columns;
internal ListViewItem focused_item;
private bool full_row_select = false;
private bool grid_lines = false;
private bool hide_selection = true;
private bool hover_selection = false;
private IComparer item_sorter;
- private ListViewItemCollection items;
+ private readonly ListViewItemCollection items;
private bool label_edit = false;
private bool label_wrap = true;
private bool multiselect = true;
private bool scrollable = true;
- private SelectedIndexCollection selected_indices;
- private SelectedListViewItemCollection selected_items;
+ private readonly SelectedIndexCollection selected_indices;
+ private readonly SelectedListViewItemCollection selected_items;
private SortOrder sort_order = SortOrder.None;
private ImageList state_image_list;
private bool updating = false;
public ListView ()
{
background_color = ThemeEngine.Current.ColorWindow;
+ items = new ListViewItemCollection (this);
checked_indices = new CheckedIndexCollection (this);
checked_items = new CheckedListViewItemCollection (this);
columns = new ColumnHeaderCollection (this);
foreground_color = SystemColors.WindowText;
- items = new ListViewItemCollection (this);
selected_indices = new SelectedIndexCollection (this);
selected_items = new SelectedListViewItemCollection (this);
item_control = new ItemControl (this);
Controls.AddImplicit (item_control);
- h_scroll = new HScrollBar ();
+ h_scroll = new ImplicitHScrollBar ();
Controls.AddImplicit (this.h_scroll);
- v_scroll = new VScrollBar ();
+ v_scroll = new ImplicitVScrollBar ();
Controls.AddImplicit (this.v_scroll);
h_marker = v_marker = 0;
}
}
+ internal void OnSelectedIndexChanged ()
+ {
+ if (IsHandleCreated)
+ OnSelectedIndexChanged (EventArgs.Empty);
+ }
+
internal int TotalWidth {
get { return Math.Max (this.Width, this.layout_wd); }
}
}
}
- internal void UpdateSelection (ListViewItem item)
- {
- if (item.Selected) {
- if (!MultiSelect && SelectedItems.Count > 0)
- SelectedItems.Clear ();
-
- if (!SelectedItems.list.Contains (item))
- SelectedItems.list.Add (item);
- } else {
- SelectedItems.list.Remove (item);
- }
- }
-
private bool KeySearchString (KeyEventArgs ke)
{
int current_tickcnt = Environment.TickCount;
private bool SelectItems (ArrayList sel_items)
{
bool changed = false;
- ArrayList curr_items = (ArrayList) SelectedItems.list.Clone ();
+ ArrayList curr_items = SelectedItems.List;
foreach (ListViewItem item in curr_items)
if (!sel_items.Contains (item)) {
item.Selected = false;
ListViewItem last_clicked_item;
bool hover_processed = false;
bool checking = false;
+
+ ListViewLabelEditTextBox edit_text_box;
+ internal ListViewItem edit_item;
+ LabelEditEventArgs edit_args;
public ItemControl (ListView owner)
{
owner.OnDoubleClick (EventArgs.Empty);
if (owner.CheckBoxes)
ToggleCheckState (clicked_item);
- } else if (me.Clicks == 1)
+ } else if (me.Clicks == 1) {
owner.OnClick (EventArgs.Empty);
+ if (owner.LabelEdit && !changed)
+ BeginEdit (clicked_item); // this is probably not the correct place to execute BeginEdit
+ }
} else {
if (owner.MultiSelect) {
Keys mods = XplatUI.State.ModifierKeys;
else
box_select_mode = BoxSelect.Normal;
box_select_start = pt;
- prev_selection = (ArrayList) owner.SelectedItems.list.Clone ();
- } else if (owner.selected_indices.Count > 0) {
+ prev_selection = owner.SelectedItems.List;
+ } else if (owner.SelectedItems.Count > 0) {
owner.SelectedItems.Clear ();
owner.OnSelectedIndexChanged (EventArgs.Empty);
}
box_select_mode = BoxSelect.None;
checking = false;
}
+
+ internal void LabelEditFinished (object sender, EventArgs e)
+ {
+ EndEdit (edit_item);
+ }
+
+ internal void BeginEdit (ListViewItem item)
+ {
+ if (edit_item != null)
+ EndEdit (edit_item);
+
+ if (edit_text_box == null) {
+ edit_text_box = new ListViewLabelEditTextBox ();
+ edit_text_box.BorderStyle = BorderStyle.FixedSingle;
+ edit_text_box.EditingFinished += new EventHandler (LabelEditFinished);
+ edit_text_box.Visible = false;
+ Controls.Add (edit_text_box);
+ }
+
+ item.EnsureVisible();
+
+ edit_text_box.Reset ();
+
+ switch (owner.view) {
+ case View.List:
+ case View.SmallIcon:
+ case View.Details:
+ edit_text_box.TextAlign = HorizontalAlignment.Left;
+ edit_text_box.Bounds = item.GetBounds (ItemBoundsPortion.Label);
+ SizeF sizef = DeviceContext.MeasureString (item.Text, item.Font);
+ edit_text_box.Width = (int)sizef.Width + 4;
+ edit_text_box.MaxWidth = owner.ClientRectangle.Width - edit_text_box.Bounds.X;
+ edit_text_box.WordWrap = false;
+ edit_text_box.Multiline = false;
+ break;
+ case View.LargeIcon:
+ edit_text_box.TextAlign = HorizontalAlignment.Center;
+ edit_text_box.Bounds = item.GetBounds (ItemBoundsPortion.Label);
+ sizef = DeviceContext.MeasureString (item.Text, item.Font);
+ edit_text_box.Width = (int)sizef.Width + 4;
+ edit_text_box.MaxWidth = item.GetBounds(ItemBoundsPortion.Entire).Width;
+ edit_text_box.MaxHeight = owner.ClientRectangle.Height - edit_text_box.Bounds.Y;
+ edit_text_box.WordWrap = true;
+ edit_text_box.Multiline = true;
+ break;
+ }
+
+ edit_text_box.Text = item.Text;
+ edit_text_box.Font = item.Font;
+ edit_text_box.Visible = true;
+ edit_text_box.Focus ();
+ edit_text_box.SelectAll ();
+
+ edit_args = new LabelEditEventArgs (owner.Items.IndexOf(edit_item));
+ owner.OnBeforeLabelEdit (edit_args);
+
+ if (edit_args.CancelEdit)
+ EndEdit (item);
+
+ edit_item = item;
+ }
+
+ internal void EndEdit (ListViewItem item)
+ {
+ if (edit_text_box != null && edit_text_box.Visible) {
+ edit_text_box.Visible = false;
+ }
+
+ if (edit_item != null && edit_item == item) {
+ owner.OnAfterLabelEdit (edit_args);
+
+ if (!edit_args.CancelEdit) {
+ if (edit_args.Label != null)
+ edit_item.Text = edit_args.Label;
+ else
+ edit_item.Text = edit_text_box.Text;
+ }
+
+ }
+
+
+ edit_item = null;
+ }
internal override void OnPaintInternal (PaintEventArgs pe)
{
owner.Focus ();
}
}
+
+ internal class ListViewLabelEditTextBox : TextBox
+ {
+ int max_width = -1;
+ int min_width = -1;
+
+ int max_height = -1;
+ int min_height = -1;
+
+ int old_number_lines = 1;
+
+ SizeF text_size_one_char;
+
+ public ListViewLabelEditTextBox ()
+ {
+ min_height = DefaultSize.Height;
+ text_size_one_char = DeviceContext.MeasureString ("B", Font);
+ }
+
+ public int MaxWidth {
+ set {
+ if (value < min_width)
+ max_width = min_width;
+ else
+ max_width = value;
+ }
+ }
+
+ public int MaxHeight {
+ set {
+ if (value < min_height)
+ max_height = min_height;
+ else
+ max_height = value;
+ }
+ }
+
+ public new int Width {
+ get {
+ return base.Width;
+ }
+ set {
+ min_width = value;
+ base.Width = value;
+ }
+ }
+
+ public override Font Font {
+ get {
+ return base.Font;
+ }
+ set {
+ base.Font = value;
+ text_size_one_char = DeviceContext.MeasureString ("B", Font);
+ }
+ }
+
+ protected override void OnTextChanged (EventArgs e)
+ {
+ SizeF text_size = DeviceContext.MeasureString (Text, Font);
+
+ int new_width = (int)text_size.Width + 8;
+
+ if (!Multiline)
+ ResizeTextBoxWidth (new_width);
+ else {
+ if (Width != max_width)
+ ResizeTextBoxWidth (new_width);
+
+ int number_lines = Lines.Length;
+
+ if (number_lines != old_number_lines) {
+ int new_height = number_lines * (int)text_size_one_char.Height + 4;
+ old_number_lines = number_lines;
+
+ ResizeTextBoxHeight (new_height);
+ }
+ }
+
+ base.OnTextChanged (e);
+ }
+
+ protected override bool IsInputKey (Keys key_data)
+ {
+ if ((key_data & Keys.Alt) == 0) {
+ switch (key_data & Keys.KeyCode) {
+ case Keys.Enter:
+ return true;
+ }
+ }
+ return base.IsInputKey (key_data);
+ }
+
+ protected override void OnKeyDown (KeyEventArgs e)
+ {
+ if (e.KeyCode == Keys.Return && Visible) {
+ this.Visible = false;
+ OnEditingFinished (e);
+ }
+ }
+
+ protected override void OnLostFocus (EventArgs e)
+ {
+ if (Visible) {
+ OnEditingFinished (e);
+ }
+ }
+
+ protected void OnEditingFinished (EventArgs e)
+ {
+ if (EditingFinished != null)
+ EditingFinished (this, EventArgs.Empty);
+ }
+
+ private void ResizeTextBoxWidth (int new_width)
+ {
+ if (new_width > max_width)
+ base.Width = max_width;
+ else
+ if (new_width >= min_width)
+ base.Width = new_width;
+ else
+ base.Width = min_width;
+ }
+
+ private void ResizeTextBoxHeight (int new_height)
+ {
+ if (new_height > max_height)
+ base.Height = max_height;
+ else
+ if (new_height >= min_height)
+ base.Height = new_height;
+ else
+ base.Height = min_height;
+ }
+
+ public void Reset ()
+ {
+ max_width = -1;
+ min_width = -1;
+
+ max_height = -1;
+
+ old_number_lines = 1;
+
+ Text = String.Empty;
+
+ Size = DefaultSize;
+ }
+
+ public event EventHandler EditingFinished;
+ }
internal override void OnPaintInternal (PaintEventArgs pe)
{
private void HorizontalScroller (object sender, EventArgs e)
{
+ item_control.EndEdit (item_control.edit_item);
+
// Avoid unnecessary flickering, when button is
// kept pressed at the end
if (h_marker != h_scroll.Value) {
private void VerticalScroller (object sender, EventArgs e)
{
+ item_control.EndEdit (item_control.edit_item);
+
// Avoid unnecessary flickering, when button is
// kept pressed at the end
if (v_marker != v_scroll.Value) {
protected override void CreateHandle ()
{
base.CreateHandle ();
+ for (int i = 0; i < SelectedItems.Count; i++)
+ OnSelectedIndexChanged (EventArgs.Empty);
}
protected override void Dispose (bool disposing)
return;
}
- items.list.Sort (item_sorter);
+ items.Sort (item_sorter);
if (redraw)
this.Redraw (true);
}
private int [] GetIndices ()
{
- int [] indices = new int [Count];
- for (int i = 0; i < owner.CheckedItems.Count; i++) {
- ListViewItem item = owner.CheckedItems [i];
+ ArrayList checked_items = owner.CheckedItems.List;
+ int [] indices = new int [checked_items.Count];
+ for (int i = 0; i < checked_items.Count; i++) {
+ ListViewItem item = (ListViewItem) checked_items [i];
indices [i] = item.Index;
}
return indices;
public class CheckedListViewItemCollection : IList, ICollection, IEnumerable
{
- internal readonly ArrayList list;
private readonly ListView owner;
+ private ArrayList list;
#region Public Constructor
public CheckedListViewItemCollection (ListView owner)
{
- list = new ArrayList ();
this.owner = owner;
+ this.owner.Items.Changed += new CollectionChangedHandler (
+ ItemsCollection_Changed);
}
#endregion // Public Constructor
get {
if (!owner.CheckBoxes)
return 0;
- return list.Count;
+ return List.Count;
}
}
public ListViewItem this [int index] {
get {
- if (index < 0 || index >= Count)
+ ArrayList checked_items = List;
+ if (index < 0 || index >= checked_items.Count)
throw new ArgumentOutOfRangeException ("index");
- return (ListViewItem) list [index];
+ return (ListViewItem) checked_items [index];
}
}
bool ICollection.IsSynchronized {
- get { return list.IsSynchronized; }
+ get { return false; }
}
object ICollection.SyncRoot {
{
if (!owner.CheckBoxes)
return false;
- return list.Contains (item);
+ return List.Contains (item);
}
public void CopyTo (Array dest, int index)
{
if (!owner.CheckBoxes)
return;
- list.CopyTo (dest, index);
+ List.CopyTo (dest, index);
}
public IEnumerator GetEnumerator ()
{
if (!owner.CheckBoxes)
return (new ListViewItem [0]).GetEnumerator ();
- return list.GetEnumerator ();
+ return List.GetEnumerator ();
}
int IList.Add (object value)
{
if (!owner.CheckBoxes)
return -1;
- return list.IndexOf (item);
+ return List.IndexOf (item);
}
#endregion // Public Methods
+
+ internal ArrayList List {
+ get {
+ if (list == null) {
+ list = new ArrayList ();
+ foreach (ListViewItem item in owner.Items) {
+ if (item.Checked)
+ list.Add (item);
+ }
+ }
+ return list;
+ }
+ }
+
+ internal void Reset ()
+ {
+ // force re-population of list
+ list = null;
+ }
+
+ private void ItemsCollection_Changed ()
+ {
+ Reset ();
+ }
} // CheckedListViewItemCollection
public class ColumnHeaderCollection : IList, ICollection, IEnumerable
public class ListViewItemCollection : IList, ICollection, IEnumerable
{
- internal ArrayList list;
+ private readonly ArrayList list;
private readonly ListView owner;
#region Public Constructor
value.Owner = owner;
list [displayIndex] = value;
+ OnChange ();
owner.Redraw (true);
}
this [index] = (ListViewItem) value;
else
this [index] = new ListViewItem (value.ToString ());
+ OnChange ();
}
}
#endregion // Public Properties
list.Add (value);
owner.Sort (false);
+ OnChange ();
owner.Redraw (true);
return value;
}
public void AddRange (ListViewItem [] values)
{
list.Clear ();
- owner.SelectedItems.list.Clear ();
- owner.CheckedItems.list.Clear ();
foreach (ListViewItem item in values) {
item.Owner = owner;
}
owner.Sort (false);
+ OnChange ();
owner.Redraw (true);
}
owner.SetFocusedItem (null);
owner.h_scroll.Value = owner.v_scroll.Value = 0;
list.Clear ();
- owner.SelectedItems.list.Clear ();
- owner.CheckedItems.list.Clear ();
+ OnChange ();
owner.Redraw (true);
}
li.Owner = owner;
result = list.Add (li);
+ OnChange ();
owner.Redraw (true);
return result;
item.Owner = owner;
list.Insert (index, item);
+ OnChange ();
owner.Redraw (true);
return item;
}
if (!list.Contains (item))
return;
- owner.SelectedItems.list.Remove (item);
- owner.CheckedItems.list.Remove (item);
+ bool selection_changed = owner.SelectedItems.Contains (item);
list.Remove (item);
+ OnChange ();
owner.Redraw (true);
+ if (selection_changed)
+ owner.OnSelectedIndexChanged (EventArgs.Empty);
}
public virtual void RemoveAt (int index)
{
- ListViewItem item = this [index];
+ if (index < 0 || index >= Count)
+ throw new ArgumentOutOfRangeException ("index");
+ bool selection_changed = owner.SelectedIndices.Contains (index);
list.RemoveAt (index);
- owner.SelectedItems.list.Remove (item);
- owner.CheckedItems.list.Remove (item);
+ OnChange ();
owner.Redraw (false);
+ if (selection_changed)
+ owner.OnSelectedIndexChanged (EventArgs.Empty);
}
#endregion // Public Methods
+ internal event CollectionChangedHandler Changed;
+
+ internal void Sort (IComparer comparer)
+ {
+ list.Sort (comparer);
+ OnChange ();
+ }
+
+ internal void OnChange ()
+ {
+ if (Changed != null)
+ Changed ();
+ }
} // ListViewItemCollection
public class SelectedIndexCollection : IList, ICollection, IEnumerable
private int [] GetIndices ()
{
- int [] indices = new int [Count];
- for (int i = 0; i < owner.SelectedItems.Count; i++) {
- ListViewItem item = owner.SelectedItems [i];
+ ArrayList selected_items = owner.SelectedItems.List;
+ int [] indices = new int [selected_items.Count];
+ for (int i = 0; i < selected_items.Count; i++) {
+ ListViewItem item = (ListViewItem) selected_items [i];
indices [i] = item.Index;
}
return indices;
}
-
} // SelectedIndexCollection
public class SelectedListViewItemCollection : IList, ICollection, IEnumerable
{
- internal ArrayList list;
private readonly ListView owner;
+ private ArrayList list;
#region Public Constructor
public SelectedListViewItemCollection (ListView owner)
{
- list = new ArrayList ();
this.owner = owner;
+ this.owner.Items.Changed += new CollectionChangedHandler (
+ ItemsCollection_Changed);
}
#endregion // Public Constructor
get {
if (!owner.IsHandleCreated)
return 0;
- return list.Count;
+ return List.Count;
}
}
public ListViewItem this [int index] {
get {
- if (index < 0 || index >= Count)
+ ArrayList selected_items = List;
+ if (!owner.IsHandleCreated || index < 0 || index >= selected_items.Count)
throw new ArgumentOutOfRangeException ("index");
- return (ListViewItem) list [index];
+ return (ListViewItem) selected_items [index];
}
}
bool ICollection.IsSynchronized {
- get { return list.IsSynchronized; }
+ get { return false; }
}
object ICollection.SyncRoot {
if (!owner.IsHandleCreated)
return;
- ArrayList copy = (ArrayList) list.Clone ();
- for (int i = 0; i < copy.Count; i++)
- ((ListViewItem) copy [i]).Selected = false;
-
- list.Clear ();
+ foreach (ListViewItem item in List)
+ item.Selected = false;
}
public bool Contains (ListViewItem item)
{
if (!owner.IsHandleCreated)
return false;
- return list.Contains (item);
+ return List.Contains (item);
}
public void CopyTo (Array dest, int index)
{
if (!owner.IsHandleCreated)
return;
- list.CopyTo (dest, index);
+ List.CopyTo (dest, index);
}
public IEnumerator GetEnumerator ()
{
if (!owner.IsHandleCreated)
return (new ListViewItem [0]).GetEnumerator ();
- return list.GetEnumerator ();
+ return List.GetEnumerator ();
}
int IList.Add (object value)
{
if (!owner.IsHandleCreated)
return -1;
- return list.IndexOf (item);
+ return List.IndexOf (item);
}
#endregion // Public Methods
+ internal ArrayList List {
+ get {
+ if (list == null) {
+ list = new ArrayList ();
+ foreach (ListViewItem item in owner.Items) {
+ if (item.Selected)
+ list.Add (item);
+ }
+ }
+ return list;
+ }
+ }
+
+ internal void Reset ()
+ {
+ // force re-population of list
+ list = null;
+ }
+
+ private void ItemsCollection_Changed ()
+ {
+ Reset ();
+ }
} // SelectedListViewItemCollection
+ internal delegate void CollectionChangedHandler ();
+
#endregion // Subclasses
}
}