1638 lines
40 KiB
C#
1638 lines
40 KiB
C#
|
// Permission is hereby granted, free of charge, to any person obtaining
|
||
|
// a copy of this software and associated documentation files (the
|
||
|
// "Software"), to deal in the Software without restriction, including
|
||
|
// without limitation the rights to use, copy, modify, merge, publish,
|
||
|
// distribute, sublicense, and/or sell copies of the Software, and to
|
||
|
// permit persons to whom the Software is furnished to do so, subject to
|
||
|
// the following conditions:
|
||
|
//
|
||
|
// The above copyright notice and this permission notice shall be
|
||
|
// included in all copies or substantial portions of the Software.
|
||
|
//
|
||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||
|
//
|
||
|
// Copyright (c) 2004 Novell, Inc. (http://www.novell.com)
|
||
|
//
|
||
|
// Author:
|
||
|
// Ravindra (rkumar@novell.com)
|
||
|
// Mike Kestner <mkestner@novell.com>
|
||
|
// Daniel Nauck (dna(at)mono-project(dot)de)
|
||
|
|
||
|
using System.Collections;
|
||
|
using System.ComponentModel;
|
||
|
using System.Drawing;
|
||
|
using System.Runtime.Serialization;
|
||
|
|
||
|
namespace System.Windows.Forms
|
||
|
{
|
||
|
[DefaultProperty ("Text")]
|
||
|
[DesignTimeVisible (false)]
|
||
|
[Serializable]
|
||
|
[ToolboxItem (false)]
|
||
|
[TypeConverter (typeof (ListViewItemConverter))]
|
||
|
public class ListViewItem : ICloneable, ISerializable
|
||
|
{
|
||
|
#region Instance Variables
|
||
|
private int image_index = -1;
|
||
|
private bool is_checked = false;
|
||
|
private int state_image_index = -1;
|
||
|
private ListViewSubItemCollection sub_items;
|
||
|
private object tag;
|
||
|
private bool use_item_style = true;
|
||
|
int display_index = -1; // actual position in ListView
|
||
|
private ListViewGroup group = null;
|
||
|
private string name = String.Empty;
|
||
|
private string image_key = String.Empty;
|
||
|
string tooltip_text = String.Empty;
|
||
|
int indent_count;
|
||
|
Point position = new Point (-1, -1); // cached to mimic .Net behaviour
|
||
|
Rectangle bounds = Rectangle.Empty;
|
||
|
Rectangle checkbox_rect; // calculated by CalcListViewItem method
|
||
|
Rectangle icon_rect;
|
||
|
Rectangle item_rect;
|
||
|
Rectangle label_rect;
|
||
|
ListView owner;
|
||
|
Font font;
|
||
|
Font hot_font; // cached font for hot tracking
|
||
|
bool selected;
|
||
|
|
||
|
internal int row;
|
||
|
internal int col;
|
||
|
|
||
|
|
||
|
#region UIA Framework: Methods, Properties and Events
|
||
|
|
||
|
internal event EventHandler UIATextChanged;
|
||
|
|
||
|
internal event LabelEditEventHandler UIASubItemTextChanged;
|
||
|
|
||
|
internal void OnUIATextChanged ()
|
||
|
{
|
||
|
if (UIATextChanged != null)
|
||
|
UIATextChanged (this, EventArgs.Empty);
|
||
|
}
|
||
|
|
||
|
internal void OnUIASubItemTextChanged (LabelEditEventArgs args)
|
||
|
{
|
||
|
//If our index is 0 we also generate TextChanged for the ListViewItem
|
||
|
//because ListViewItem.Text is the same as ListViewItem.SubItems [0].Text
|
||
|
if (args.Item == 0)
|
||
|
OnUIATextChanged ();
|
||
|
|
||
|
if (UIASubItemTextChanged != null)
|
||
|
UIASubItemTextChanged (this, args);
|
||
|
}
|
||
|
|
||
|
#endregion // UIA Framework: Methods, Properties and Events
|
||
|
|
||
|
|
||
|
#endregion Instance Variables
|
||
|
|
||
|
#region Public Constructors
|
||
|
public ListViewItem () : this (string.Empty)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public ListViewItem (string text) : this (text, -1)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public ListViewItem (string [] items) : this (items, -1)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public ListViewItem (ListViewItem.ListViewSubItem [] subItems, int imageIndex)
|
||
|
{
|
||
|
this.sub_items = new ListViewSubItemCollection (this, null);
|
||
|
for (int i = 0; i < subItems.Length; i++)
|
||
|
sub_items.Add (subItems [i]);
|
||
|
this.image_index = imageIndex;
|
||
|
}
|
||
|
|
||
|
public ListViewItem (string text, int imageIndex)
|
||
|
{
|
||
|
this.image_index = imageIndex;
|
||
|
this.sub_items = new ListViewSubItemCollection (this, text);
|
||
|
}
|
||
|
|
||
|
public ListViewItem (string [] items, int imageIndex)
|
||
|
{
|
||
|
this.sub_items = new ListViewSubItemCollection (this, null);
|
||
|
if (items != null) {
|
||
|
for (int i = 0; i < items.Length; i++)
|
||
|
sub_items.Add (new ListViewSubItem (this, items [i]));
|
||
|
}
|
||
|
this.image_index = imageIndex;
|
||
|
}
|
||
|
|
||
|
public ListViewItem (string [] items, int imageIndex, Color foreColor,
|
||
|
Color backColor, Font font) : this (items, imageIndex)
|
||
|
{
|
||
|
ForeColor = foreColor;
|
||
|
BackColor = backColor;
|
||
|
this.font = font;
|
||
|
}
|
||
|
|
||
|
public ListViewItem(string[] items, string imageKey) : this(items)
|
||
|
{
|
||
|
this.ImageKey = imageKey;
|
||
|
}
|
||
|
|
||
|
public ListViewItem(string text, string imageKey) : this(text)
|
||
|
{
|
||
|
this.ImageKey = imageKey;
|
||
|
}
|
||
|
|
||
|
public ListViewItem(ListViewSubItem[] subItems, string imageKey)
|
||
|
{
|
||
|
this.sub_items = new ListViewSubItemCollection (this, null);
|
||
|
for (int i = 0; i < subItems.Length; i++)
|
||
|
this.sub_items.Add (subItems [i]);
|
||
|
this.ImageKey = imageKey;
|
||
|
}
|
||
|
|
||
|
public ListViewItem(string[] items, string imageKey, Color foreColor,
|
||
|
Color backColor, Font font) : this(items, imageKey)
|
||
|
{
|
||
|
ForeColor = foreColor;
|
||
|
BackColor = backColor;
|
||
|
this.font = font;
|
||
|
}
|
||
|
|
||
|
public ListViewItem(ListViewGroup group) : this()
|
||
|
{
|
||
|
Group = group;
|
||
|
}
|
||
|
|
||
|
public ListViewItem(string text, ListViewGroup group) : this(text)
|
||
|
{
|
||
|
Group = group;
|
||
|
}
|
||
|
|
||
|
public ListViewItem(string[] items, ListViewGroup group) : this(items)
|
||
|
{
|
||
|
Group = group;
|
||
|
}
|
||
|
|
||
|
public ListViewItem(ListViewSubItem[] subItems, int imageIndex, ListViewGroup group)
|
||
|
: this(subItems, imageIndex)
|
||
|
{
|
||
|
Group = group;
|
||
|
}
|
||
|
|
||
|
public ListViewItem(ListViewSubItem[] subItems, string imageKey, ListViewGroup group)
|
||
|
: this(subItems, imageKey)
|
||
|
{
|
||
|
Group = group;
|
||
|
}
|
||
|
|
||
|
public ListViewItem(string text, int imageIndex, ListViewGroup group)
|
||
|
: this(text, imageIndex)
|
||
|
{
|
||
|
Group = group;
|
||
|
}
|
||
|
|
||
|
public ListViewItem(string text, string imageKey, ListViewGroup group)
|
||
|
: this(text, imageKey)
|
||
|
{
|
||
|
Group = group;
|
||
|
}
|
||
|
|
||
|
public ListViewItem(string[] items, int imageIndex, ListViewGroup group)
|
||
|
: this(items, imageIndex)
|
||
|
{
|
||
|
Group = group;
|
||
|
}
|
||
|
|
||
|
public ListViewItem(string[] items, string imageKey, ListViewGroup group)
|
||
|
: this(items, imageKey)
|
||
|
{
|
||
|
Group = group;
|
||
|
}
|
||
|
|
||
|
public ListViewItem(string[] items, int imageIndex, Color foreColor, Color backColor,
|
||
|
Font font, ListViewGroup group)
|
||
|
: this(items, imageIndex, foreColor, backColor, font)
|
||
|
{
|
||
|
Group = group;
|
||
|
}
|
||
|
|
||
|
public ListViewItem(string[] items, string imageKey, Color foreColor, Color backColor,
|
||
|
Font font, ListViewGroup group)
|
||
|
: this(items, imageKey, foreColor, backColor, font)
|
||
|
{
|
||
|
Group = group;
|
||
|
}
|
||
|
#endregion // Public Constructors
|
||
|
|
||
|
protected ListViewItem (SerializationInfo info, StreamingContext context)
|
||
|
{
|
||
|
Deserialize (info, context);
|
||
|
}
|
||
|
|
||
|
#region Public Instance Properties
|
||
|
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
|
||
|
public Color BackColor {
|
||
|
get {
|
||
|
if (sub_items.Count > 0)
|
||
|
return sub_items[0].BackColor;
|
||
|
|
||
|
if (owner != null)
|
||
|
return owner.BackColor;
|
||
|
|
||
|
return ThemeEngine.Current.ColorWindow;
|
||
|
}
|
||
|
set { SubItems [0].BackColor = value; }
|
||
|
}
|
||
|
|
||
|
[Browsable (false)]
|
||
|
public Rectangle Bounds {
|
||
|
get {
|
||
|
return GetBounds (ItemBoundsPortion.Entire);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[DefaultValue (false)]
|
||
|
[RefreshProperties (RefreshProperties.Repaint)]
|
||
|
public bool Checked {
|
||
|
get { return is_checked; }
|
||
|
set {
|
||
|
if (is_checked == value)
|
||
|
return;
|
||
|
|
||
|
if (owner != null) {
|
||
|
CheckState current_value = is_checked ? CheckState.Checked : CheckState.Unchecked;
|
||
|
CheckState new_value = value ? CheckState.Checked : CheckState.Unchecked;
|
||
|
|
||
|
ItemCheckEventArgs icea = new ItemCheckEventArgs (Index,
|
||
|
new_value, current_value);
|
||
|
owner.OnItemCheck (icea);
|
||
|
|
||
|
if (new_value != current_value) {
|
||
|
// force re-population of list
|
||
|
owner.CheckedItems.Reset ();
|
||
|
is_checked = new_value == CheckState.Checked;
|
||
|
Invalidate ();
|
||
|
|
||
|
ItemCheckedEventArgs args = new ItemCheckedEventArgs (this);
|
||
|
owner.OnItemChecked (args);
|
||
|
}
|
||
|
} else
|
||
|
is_checked = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[Browsable (false)]
|
||
|
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
|
||
|
public bool Focused {
|
||
|
get {
|
||
|
if (owner == null)
|
||
|
return false;
|
||
|
|
||
|
// In virtual mode the checks are always done using indexes
|
||
|
if (owner.VirtualMode)
|
||
|
return Index == owner.focused_item_index;
|
||
|
|
||
|
// Light check
|
||
|
return owner.FocusedItem == this;
|
||
|
|
||
|
}
|
||
|
set {
|
||
|
if (owner == null)
|
||
|
return;
|
||
|
|
||
|
if (Focused == value)
|
||
|
return;
|
||
|
|
||
|
ListViewItem prev_focused_item = owner.FocusedItem;
|
||
|
if (prev_focused_item != null)
|
||
|
prev_focused_item.UpdateFocusedState ();
|
||
|
|
||
|
owner.focused_item_index = value ? Index : -1;
|
||
|
if (value)
|
||
|
owner.OnUIAFocusedItemChanged ();
|
||
|
|
||
|
UpdateFocusedState ();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[Localizable (true)]
|
||
|
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
|
||
|
public Font Font {
|
||
|
get {
|
||
|
if (font != null)
|
||
|
return font;
|
||
|
else if (owner != null)
|
||
|
return owner.Font;
|
||
|
|
||
|
return ThemeEngine.Current.DefaultFont;
|
||
|
}
|
||
|
set {
|
||
|
if (font == value)
|
||
|
return;
|
||
|
|
||
|
font = value;
|
||
|
hot_font = null;
|
||
|
|
||
|
if (owner != null)
|
||
|
Layout ();
|
||
|
Invalidate ();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
|
||
|
public Color ForeColor {
|
||
|
get {
|
||
|
if (sub_items.Count > 0)
|
||
|
return sub_items[0].ForeColor;
|
||
|
|
||
|
if (owner != null)
|
||
|
return owner.ForeColor;
|
||
|
|
||
|
return ThemeEngine.Current.ColorWindowText;
|
||
|
}
|
||
|
set { SubItems [0].ForeColor = value; }
|
||
|
}
|
||
|
|
||
|
[DefaultValue (-1)]
|
||
|
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
|
||
|
[Editor ("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design,
|
||
|
typeof (System.Drawing.Design.UITypeEditor))]
|
||
|
[Localizable (true)]
|
||
|
[RefreshProperties (RefreshProperties.Repaint)]
|
||
|
[TypeConverter (typeof (NoneExcludedImageIndexConverter))]
|
||
|
public int ImageIndex {
|
||
|
get { return image_index; }
|
||
|
set {
|
||
|
if (value < -1)
|
||
|
throw new ArgumentException ("Invalid ImageIndex. It must be greater than or equal to -1.");
|
||
|
|
||
|
image_index = value;
|
||
|
image_key = String.Empty;
|
||
|
|
||
|
if (owner != null)
|
||
|
Layout ();
|
||
|
Invalidate ();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[DefaultValue ("")]
|
||
|
[LocalizableAttribute (true)]
|
||
|
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
|
||
|
[Editor ("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design,
|
||
|
typeof (System.Drawing.Design.UITypeEditor))]
|
||
|
[RefreshProperties (RefreshProperties.Repaint)]
|
||
|
[TypeConverter (typeof (ImageKeyConverter))]
|
||
|
public string ImageKey {
|
||
|
get {
|
||
|
return image_key;
|
||
|
}
|
||
|
set {
|
||
|
image_key = value == null ? String.Empty : value;
|
||
|
image_index = -1;
|
||
|
|
||
|
if (owner != null)
|
||
|
Layout ();
|
||
|
Invalidate ();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[Browsable (false)]
|
||
|
public ImageList ImageList {
|
||
|
get {
|
||
|
if (owner == null)
|
||
|
return null;
|
||
|
else if (owner.View == View.LargeIcon)
|
||
|
return owner.large_image_list;
|
||
|
else
|
||
|
return owner.small_image_list;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[DefaultValue (0)]
|
||
|
public int IndentCount {
|
||
|
get {
|
||
|
return indent_count;
|
||
|
}
|
||
|
set {
|
||
|
if (value < 0)
|
||
|
throw new ArgumentOutOfRangeException ("value");
|
||
|
|
||
|
if (value == indent_count)
|
||
|
return;
|
||
|
|
||
|
indent_count = value;
|
||
|
Invalidate ();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[Browsable (false)]
|
||
|
public int Index {
|
||
|
get {
|
||
|
if (owner == null)
|
||
|
return -1;
|
||
|
if (owner.VirtualMode)
|
||
|
return display_index;
|
||
|
|
||
|
if (display_index == -1)
|
||
|
return owner.Items.IndexOf (this);
|
||
|
|
||
|
return owner.GetItemIndex (display_index);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[Browsable (false)]
|
||
|
public ListView ListView {
|
||
|
get { return owner; }
|
||
|
}
|
||
|
|
||
|
[Browsable (false)]
|
||
|
[Localizable (true)]
|
||
|
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
|
||
|
public string Name {
|
||
|
get {
|
||
|
return name;
|
||
|
}
|
||
|
set {
|
||
|
name = value == null ? String.Empty : value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
|
||
|
[Browsable (false)]
|
||
|
public Point Position {
|
||
|
get {
|
||
|
if (owner != null && owner.VirtualMode)
|
||
|
return owner.GetItemLocation (display_index);
|
||
|
|
||
|
if (owner != null && !owner.IsHandleCreated)
|
||
|
return new Point (-1, -1);
|
||
|
|
||
|
return position;
|
||
|
}
|
||
|
set {
|
||
|
if (owner == null || owner.View == View.Details || owner.View == View.List)
|
||
|
return;
|
||
|
|
||
|
if (owner.VirtualMode)
|
||
|
throw new InvalidOperationException ();
|
||
|
|
||
|
owner.ChangeItemLocation (display_index, value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// When ListView uses VirtualMode, selection state info
|
||
|
// lives in the ListView, not in the item
|
||
|
// Also, in VirtualMode we can't Reset() the selection
|
||
|
[Browsable (false)]
|
||
|
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
|
||
|
public bool Selected {
|
||
|
get {
|
||
|
if (owner != null && owner.VirtualMode)
|
||
|
return owner.SelectedIndices.Contains (Index);
|
||
|
|
||
|
return selected;
|
||
|
}
|
||
|
set {
|
||
|
if (selected == value && owner != null && !owner.VirtualMode)
|
||
|
return;
|
||
|
|
||
|
SetSelectedCore (value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Expose this method as internal so we can force an update in the selection.
|
||
|
internal void SetSelectedCore (bool value)
|
||
|
{
|
||
|
if (owner != null) {
|
||
|
if (value && !owner.MultiSelect)
|
||
|
owner.SelectedIndices.Clear ();
|
||
|
if (owner.VirtualMode) {
|
||
|
if (value)
|
||
|
owner.SelectedIndices.InsertIndex (Index);
|
||
|
else
|
||
|
owner.SelectedIndices.RemoveIndex (Index);
|
||
|
} else {
|
||
|
selected = value;
|
||
|
owner.SelectedIndices.Reset (); // force re-population of list
|
||
|
}
|
||
|
|
||
|
owner.OnItemSelectionChanged (new ListViewItemSelectionChangedEventArgs (this, Index, value));
|
||
|
owner.OnSelectedIndexChanged ();
|
||
|
Invalidate ();
|
||
|
} else
|
||
|
selected = value;
|
||
|
}
|
||
|
|
||
|
[DefaultValue (-1)]
|
||
|
[Editor ("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design,
|
||
|
typeof (System.Drawing.Design.UITypeEditor))]
|
||
|
[Localizable (true)]
|
||
|
[RefreshProperties (RefreshProperties.Repaint)]
|
||
|
[RelatedImageListAttribute ("ListView.StateImageList")]
|
||
|
[TypeConverter (typeof (NoneExcludedImageIndexConverter))]
|
||
|
public int StateImageIndex {
|
||
|
get { return state_image_index; }
|
||
|
set {
|
||
|
if (value < -1 || value > 14)
|
||
|
throw new ArgumentOutOfRangeException ("Invalid StateImageIndex. It must be in the range of [-1, 14].");
|
||
|
|
||
|
state_image_index = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
|
||
|
[Editor ("System.Windows.Forms.Design.ListViewSubItemCollectionEditor, " + Consts.AssemblySystem_Design,
|
||
|
typeof (System.Drawing.Design.UITypeEditor))]
|
||
|
public ListViewSubItemCollection SubItems {
|
||
|
get {
|
||
|
if (sub_items.Count == 0)
|
||
|
this.sub_items.Add (string.Empty);
|
||
|
return sub_items;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[Bindable (true)]
|
||
|
[DefaultValue (null)]
|
||
|
[Localizable (false)]
|
||
|
[TypeConverter (typeof (StringConverter))]
|
||
|
public object Tag {
|
||
|
get { return tag; }
|
||
|
set { tag = value; }
|
||
|
}
|
||
|
|
||
|
[Localizable (true)]
|
||
|
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
|
||
|
public string Text {
|
||
|
get {
|
||
|
if (this.sub_items.Count > 0)
|
||
|
return this.sub_items [0].Text;
|
||
|
else
|
||
|
return string.Empty;
|
||
|
}
|
||
|
set {
|
||
|
if (SubItems [0].Text == value)
|
||
|
return;
|
||
|
|
||
|
sub_items [0].Text = value;
|
||
|
|
||
|
if (owner != null)
|
||
|
Layout ();
|
||
|
Invalidate ();
|
||
|
|
||
|
//UIA Framework: Generates Text changed
|
||
|
OnUIATextChanged ();
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[DefaultValue (true)]
|
||
|
public bool UseItemStyleForSubItems {
|
||
|
get { return use_item_style; }
|
||
|
set { use_item_style = value; }
|
||
|
}
|
||
|
|
||
|
[LocalizableAttribute(true)]
|
||
|
[DefaultValue (null)]
|
||
|
public ListViewGroup Group {
|
||
|
get { return this.group; }
|
||
|
set {
|
||
|
if (group != value) {
|
||
|
if (value == null)
|
||
|
group.Items.Remove (this);
|
||
|
else
|
||
|
value.Items.Add (this);
|
||
|
|
||
|
group = value;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[DefaultValue ("")]
|
||
|
public string ToolTipText {
|
||
|
get {
|
||
|
return tooltip_text;
|
||
|
}
|
||
|
set {
|
||
|
if (value == null)
|
||
|
value = String.Empty;
|
||
|
|
||
|
tooltip_text = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endregion // Public Instance Properties
|
||
|
|
||
|
#region Public Instance Methods
|
||
|
public void BeginEdit ()
|
||
|
{
|
||
|
if (owner != null && owner.LabelEdit) {
|
||
|
owner.item_control.BeginEdit (this);
|
||
|
}
|
||
|
// FIXME: TODO
|
||
|
// if (owner != null && owner.LabelEdit
|
||
|
// && owner.Activation == ItemActivation.Standard)
|
||
|
// allow editing
|
||
|
// else
|
||
|
// throw new InvalidOperationException ();
|
||
|
}
|
||
|
|
||
|
public virtual object Clone ()
|
||
|
{
|
||
|
ListViewItem clone = new ListViewItem ();
|
||
|
clone.image_index = this.image_index;
|
||
|
clone.is_checked = this.is_checked;
|
||
|
clone.selected = this.selected;
|
||
|
clone.font = this.font;
|
||
|
clone.state_image_index = this.state_image_index;
|
||
|
clone.sub_items = new ListViewSubItemCollection (this, null);
|
||
|
|
||
|
foreach (ListViewSubItem subItem in this.sub_items)
|
||
|
clone.sub_items.Add (subItem.Text, subItem.ForeColor,
|
||
|
subItem.BackColor, subItem.Font);
|
||
|
clone.tag = this.tag;
|
||
|
clone.use_item_style = this.use_item_style;
|
||
|
clone.owner = null;
|
||
|
clone.name = name;
|
||
|
clone.tooltip_text = tooltip_text;
|
||
|
|
||
|
return clone;
|
||
|
}
|
||
|
|
||
|
public virtual void EnsureVisible ()
|
||
|
{
|
||
|
if (this.owner != null) {
|
||
|
owner.EnsureVisible (owner.Items.IndexOf (this));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public ListViewItem FindNearestItem (SearchDirectionHint searchDirection)
|
||
|
{
|
||
|
if (owner == null)
|
||
|
return null;
|
||
|
|
||
|
Point loc = owner.GetItemLocation (display_index);
|
||
|
return owner.FindNearestItem (searchDirection, loc);
|
||
|
}
|
||
|
|
||
|
public Rectangle GetBounds (ItemBoundsPortion portion)
|
||
|
{
|
||
|
if (owner == null)
|
||
|
return Rectangle.Empty;
|
||
|
|
||
|
Rectangle rect;
|
||
|
|
||
|
switch (portion) {
|
||
|
case ItemBoundsPortion.Icon:
|
||
|
rect = icon_rect;
|
||
|
break;
|
||
|
|
||
|
case ItemBoundsPortion.Label:
|
||
|
rect = label_rect;
|
||
|
break;
|
||
|
|
||
|
case ItemBoundsPortion.ItemOnly:
|
||
|
rect = item_rect;
|
||
|
break;
|
||
|
|
||
|
case ItemBoundsPortion.Entire:
|
||
|
rect = bounds;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
throw new ArgumentException ("Invalid value for portion.");
|
||
|
}
|
||
|
|
||
|
Point item_loc = owner.GetItemLocation (DisplayIndex);
|
||
|
rect.X += item_loc.X;
|
||
|
rect.Y += item_loc.Y;
|
||
|
return rect;
|
||
|
}
|
||
|
|
||
|
void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
|
||
|
{
|
||
|
Serialize (info, context);
|
||
|
}
|
||
|
|
||
|
public ListViewSubItem GetSubItemAt (int x, int y)
|
||
|
{
|
||
|
if (owner != null && owner.View != View.Details)
|
||
|
return null;
|
||
|
|
||
|
foreach (ListViewSubItem sub_item in sub_items)
|
||
|
if (sub_item.Bounds.Contains (x, y))
|
||
|
return sub_item;
|
||
|
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public virtual void Remove ()
|
||
|
{
|
||
|
if (owner == null)
|
||
|
return;
|
||
|
|
||
|
owner.item_control.CancelEdit (this);
|
||
|
owner.Items.Remove (this);
|
||
|
owner = null;
|
||
|
}
|
||
|
|
||
|
public override string ToString ()
|
||
|
{
|
||
|
return string.Format ("ListViewItem: {0}", this.Text);
|
||
|
}
|
||
|
#endregion // Public Instance Methods
|
||
|
|
||
|
#region Protected Methods
|
||
|
protected virtual void Deserialize (SerializationInfo info, StreamingContext context)
|
||
|
{
|
||
|
sub_items = new ListViewSubItemCollection (this, null);
|
||
|
int sub_items_count = 0;
|
||
|
|
||
|
foreach (SerializationEntry entry in info) {
|
||
|
switch (entry.Name) {
|
||
|
case "Text":
|
||
|
sub_items.Add ((string)entry.Value);
|
||
|
break;
|
||
|
case "Font":
|
||
|
font = (Font)entry.Value;
|
||
|
break;
|
||
|
case "Checked":
|
||
|
is_checked = (bool)entry.Value;
|
||
|
break;
|
||
|
case "ImageIndex":
|
||
|
image_index = (int)entry.Value;
|
||
|
break;
|
||
|
case "StateImageIndex":
|
||
|
state_image_index = (int)entry.Value;
|
||
|
break;
|
||
|
case "UseItemStyleForSubItems":
|
||
|
use_item_style = (bool)entry.Value;
|
||
|
break;
|
||
|
case "SubItemCount":
|
||
|
sub_items_count = (int)entry.Value;
|
||
|
break;
|
||
|
case "Group":
|
||
|
group = (ListViewGroup)entry.Value;
|
||
|
break;
|
||
|
case "ImageKey":
|
||
|
if (image_index == -1)
|
||
|
image_key = (string)entry.Value;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Type subitem_type = typeof (ListViewSubItem);
|
||
|
if (sub_items_count > 0) {
|
||
|
sub_items.Clear (); // .net fixup
|
||
|
Text = info.GetString ("Text");
|
||
|
for (int i = 0; i < sub_items_count - 1; i++)
|
||
|
sub_items.Add ((ListViewSubItem)info.GetValue ("SubItem" + (i + 1), subitem_type));
|
||
|
}
|
||
|
|
||
|
// After any sub item has been added.
|
||
|
ForeColor = (Color)info.GetValue ("ForeColor", typeof (Color));
|
||
|
BackColor = (Color)info.GetValue ("BackColor", typeof (Color));
|
||
|
}
|
||
|
|
||
|
protected virtual void Serialize (SerializationInfo info, StreamingContext context)
|
||
|
{
|
||
|
info.AddValue ("Text", Text);
|
||
|
info.AddValue ("Font", Font);
|
||
|
info.AddValue ("ImageIndex", image_index);
|
||
|
info.AddValue ("Checked", is_checked);
|
||
|
info.AddValue ("StateImageIndex", state_image_index);
|
||
|
info.AddValue ("UseItemStyleForSubItems", use_item_style);
|
||
|
info.AddValue ("BackColor", BackColor);
|
||
|
info.AddValue ("ForeColor", ForeColor);
|
||
|
info.AddValue ("ImageKey", image_key);
|
||
|
if (group != null)
|
||
|
info.AddValue ("Group", group);
|
||
|
if (sub_items.Count > 1) {
|
||
|
info.AddValue ("SubItemCount", sub_items.Count);
|
||
|
for (int i = 1; i < sub_items.Count; i++) {
|
||
|
info.AddValue ("SubItem" + i, sub_items [i]);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#endregion // Protected Methods
|
||
|
|
||
|
#region Private Internal Methods
|
||
|
internal Rectangle CheckRectReal {
|
||
|
get {
|
||
|
Rectangle rect = checkbox_rect;
|
||
|
Point item_loc = owner.GetItemLocation (DisplayIndex);
|
||
|
rect.X += item_loc.X;
|
||
|
rect.Y += item_loc.Y;
|
||
|
return rect;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Rectangle text_bounds;
|
||
|
internal Rectangle TextBounds {
|
||
|
get {
|
||
|
// Call Layout() if it hasn't been called before.
|
||
|
if (owner.VirtualMode && bounds == new Rectangle (-1, -1, -1, -1))
|
||
|
Layout ();
|
||
|
Rectangle result = text_bounds;
|
||
|
Point loc = owner.GetItemLocation (DisplayIndex);
|
||
|
result.X += loc.X;
|
||
|
result.Y += loc.Y;
|
||
|
return result;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal int DisplayIndex {
|
||
|
get {
|
||
|
// Special case for Details view
|
||
|
// and no columns (which means no Layout at all)
|
||
|
if (display_index == -1)
|
||
|
return owner.Items.IndexOf (this);
|
||
|
|
||
|
return display_index;
|
||
|
}
|
||
|
set {
|
||
|
display_index = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal bool Hot {
|
||
|
get {
|
||
|
return Index == owner.HotItemIndex;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal Font HotFont {
|
||
|
get {
|
||
|
if (hot_font == null)
|
||
|
hot_font = new Font (Font, Font.Style | FontStyle.Underline);
|
||
|
|
||
|
return hot_font;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal ListView Owner {
|
||
|
set {
|
||
|
if (owner == value)
|
||
|
return;
|
||
|
|
||
|
owner = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal void SetGroup (ListViewGroup group)
|
||
|
{
|
||
|
this.group = group;
|
||
|
}
|
||
|
|
||
|
internal void SetPosition (Point position)
|
||
|
{
|
||
|
this.position = position;
|
||
|
}
|
||
|
|
||
|
// When focus changed, we need to invalidate area
|
||
|
// with previous layout and with the new one
|
||
|
void UpdateFocusedState ()
|
||
|
{
|
||
|
if (owner != null) {
|
||
|
Invalidate ();
|
||
|
Layout ();
|
||
|
Invalidate ();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal void Invalidate ()
|
||
|
{
|
||
|
if (owner == null || owner.item_control == null || owner.updating)
|
||
|
return;
|
||
|
|
||
|
// Add some padding to bounds (focused extra space, selection)
|
||
|
Rectangle rect = Bounds;
|
||
|
rect.Inflate (1, 1);
|
||
|
owner.item_control.Invalidate (rect);
|
||
|
}
|
||
|
|
||
|
internal void Layout ()
|
||
|
{
|
||
|
if (owner == null)
|
||
|
return;
|
||
|
int item_ht;
|
||
|
Rectangle total;
|
||
|
Size text_size = owner.text_size;
|
||
|
|
||
|
checkbox_rect = Rectangle.Empty;
|
||
|
if (owner.CheckBoxes)
|
||
|
checkbox_rect.Size = owner.CheckBoxSize;
|
||
|
switch (owner.View) {
|
||
|
case View.Details:
|
||
|
// LAMESPEC: MSDN says, "In all views except the details
|
||
|
// view of the ListView, this value specifies the same
|
||
|
// bounding rectangle as the Entire value." Actually, it
|
||
|
// returns same bounding rectangles for Item and Entire
|
||
|
// values in the case of Details view.
|
||
|
|
||
|
int x_offset = 0;
|
||
|
if (owner.SmallImageList != null)
|
||
|
x_offset = indent_count * owner.SmallImageList.ImageSize.Width;
|
||
|
|
||
|
// Handle reordered column
|
||
|
if (owner.Columns.Count > 0)
|
||
|
checkbox_rect.X = owner.Columns[0].Rect.X + x_offset;
|
||
|
|
||
|
icon_rect = label_rect = Rectangle.Empty;
|
||
|
icon_rect.X = checkbox_rect.Right + 2;
|
||
|
item_ht = owner.ItemSize.Height;
|
||
|
|
||
|
if (owner.SmallImageList != null)
|
||
|
icon_rect.Width = owner.SmallImageList.ImageSize.Width;
|
||
|
|
||
|
label_rect.Height = icon_rect.Height = item_ht;
|
||
|
checkbox_rect.Y = item_ht - checkbox_rect.Height;
|
||
|
|
||
|
label_rect.X = icon_rect.Width > 0 ? icon_rect.Right + 1 : icon_rect.Right;
|
||
|
|
||
|
if (owner.Columns.Count > 0)
|
||
|
label_rect.Width = owner.Columns[0].Wd - label_rect.X + checkbox_rect.X;
|
||
|
else
|
||
|
label_rect.Width = text_size.Width;
|
||
|
|
||
|
SizeF text_sz = TextRenderer.MeasureString (Text, Font);
|
||
|
text_bounds = label_rect;
|
||
|
text_bounds.Width = (int) text_sz.Width;
|
||
|
|
||
|
item_rect = total = Rectangle.Union
|
||
|
(Rectangle.Union (checkbox_rect, icon_rect), label_rect);
|
||
|
bounds.Size = total.Size;
|
||
|
|
||
|
item_rect.Width = 0;
|
||
|
bounds.Width = 0;
|
||
|
for (int i = 0; i < owner.Columns.Count; i++) {
|
||
|
item_rect.Width += owner.Columns [i].Wd;
|
||
|
bounds.Width += owner.Columns [i].Wd;
|
||
|
}
|
||
|
|
||
|
// Bounds for sub items
|
||
|
int n = Math.Min (owner.Columns.Count, sub_items.Count);
|
||
|
for (int i = 0; i < n; i++) {
|
||
|
Rectangle col_rect = owner.Columns [i].Rect;
|
||
|
sub_items [i].SetBounds (col_rect.X, 0, col_rect.Width, item_ht);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case View.LargeIcon:
|
||
|
label_rect = icon_rect = Rectangle.Empty;
|
||
|
|
||
|
SizeF sz = TextRenderer.MeasureString (Text, Font);
|
||
|
if ((int) sz.Width > text_size.Width) {
|
||
|
if (Focused && owner.InternalContainsFocus) {
|
||
|
int text_width = text_size.Width;
|
||
|
StringFormat format = new StringFormat ();
|
||
|
format.Alignment = StringAlignment.Center;
|
||
|
sz = TextRenderer.MeasureString (Text, Font, text_width, format);
|
||
|
text_size.Height = (int) sz.Height;
|
||
|
} else
|
||
|
text_size.Height = 2 * (int) sz.Height;
|
||
|
}
|
||
|
|
||
|
if (owner.LargeImageList != null) {
|
||
|
icon_rect.Width = owner.LargeImageList.ImageSize.Width;
|
||
|
icon_rect.Height = owner.LargeImageList.ImageSize.Height;
|
||
|
}
|
||
|
|
||
|
if (checkbox_rect.Height > icon_rect.Height)
|
||
|
icon_rect.Y = checkbox_rect.Height - icon_rect.Height;
|
||
|
else
|
||
|
checkbox_rect.Y = icon_rect.Height - checkbox_rect.Height;
|
||
|
|
||
|
if (text_size.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 = icon_rect.Bottom + 2;
|
||
|
label_rect.Size = text_size;
|
||
|
} else {
|
||
|
int centerX = text_size.Width / 2;
|
||
|
icon_rect.X = checkbox_rect.Width + 1 + centerX - icon_rect.Width / 2;
|
||
|
label_rect.X = checkbox_rect.Width + 1;
|
||
|
label_rect.Y = icon_rect.Bottom + 2;
|
||
|
label_rect.Size = text_size;
|
||
|
}
|
||
|
|
||
|
item_rect = Rectangle.Union (icon_rect, label_rect);
|
||
|
total = Rectangle.Union (item_rect, checkbox_rect);
|
||
|
bounds.Size = total.Size;
|
||
|
break;
|
||
|
|
||
|
case View.List:
|
||
|
case View.SmallIcon:
|
||
|
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);
|
||
|
icon_rect.Width = owner.SmallImageList.ImageSize.Width;
|
||
|
icon_rect.Height = owner.SmallImageList.ImageSize.Height;
|
||
|
}
|
||
|
|
||
|
checkbox_rect.Y = item_ht - checkbox_rect.Height;
|
||
|
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);
|
||
|
total = Rectangle.Union (item_rect, checkbox_rect);
|
||
|
bounds.Size = total.Size;
|
||
|
break;
|
||
|
case View.Tile:
|
||
|
if (!Application.VisualStylesEnabled)
|
||
|
goto case View.LargeIcon;
|
||
|
|
||
|
label_rect = icon_rect = Rectangle.Empty;
|
||
|
|
||
|
if (owner.LargeImageList != null) {
|
||
|
icon_rect.Width = owner.LargeImageList.ImageSize.Width;
|
||
|
icon_rect.Height = owner.LargeImageList.ImageSize.Height;
|
||
|
}
|
||
|
|
||
|
int separation = 2;
|
||
|
SizeF tsize = TextRenderer.MeasureString (Text, Font);
|
||
|
int main_item_height = (int) Math.Ceiling (tsize.Height);
|
||
|
int main_item_width = (int) Math.Ceiling (tsize.Width);
|
||
|
sub_items [0].bounds.Height = main_item_height;
|
||
|
|
||
|
// Set initial values for subitem's layout
|
||
|
int total_height = main_item_height;
|
||
|
int max_subitem_width = main_item_width;
|
||
|
|
||
|
int count = Math.Min (owner.Columns.Count, sub_items.Count);
|
||
|
for (int i = 1; i < count; i++) { // Ignore first column and first subitem
|
||
|
ListViewSubItem sub_item = sub_items [i];
|
||
|
if (sub_item.Text == null || sub_item.Text.Length == 0)
|
||
|
continue;
|
||
|
|
||
|
tsize = TextRenderer.MeasureString (sub_item.Text, sub_item.Font);
|
||
|
|
||
|
int width = (int)Math.Ceiling (tsize.Width);
|
||
|
if (width > max_subitem_width)
|
||
|
max_subitem_width = width;
|
||
|
|
||
|
int height = (int)Math.Ceiling (tsize.Height);
|
||
|
total_height += height + separation;
|
||
|
|
||
|
sub_item.bounds.Height = height;
|
||
|
}
|
||
|
|
||
|
max_subitem_width = Math.Min (max_subitem_width, owner.TileSize.Width - (icon_rect.Width + 4));
|
||
|
label_rect.X = icon_rect.Right + 4;
|
||
|
label_rect.Y = owner.TileSize.Height / 2 - total_height / 2;
|
||
|
label_rect.Width = max_subitem_width;
|
||
|
label_rect.Height = total_height;
|
||
|
|
||
|
// Main item - always set bounds for it
|
||
|
sub_items [0].SetBounds (label_rect.X, label_rect.Y, max_subitem_width, sub_items [0].bounds.Height);
|
||
|
|
||
|
// Second pass to assign bounds for every sub item
|
||
|
int current_y = sub_items [0].bounds.Bottom + separation;
|
||
|
for (int j = 1; j < count; j++) {
|
||
|
ListViewSubItem sub_item = sub_items [j];
|
||
|
if (sub_item.Text == null || sub_item.Text.Length == 0)
|
||
|
continue;
|
||
|
|
||
|
sub_item.SetBounds (label_rect.X, current_y, max_subitem_width, sub_item.bounds.Height);
|
||
|
current_y += sub_item.Bounds.Height + separation;
|
||
|
}
|
||
|
|
||
|
item_rect = Rectangle.Union (icon_rect, label_rect);
|
||
|
bounds.Size = item_rect.Size;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
#endregion // Private Internal Methods
|
||
|
|
||
|
#region Subclasses
|
||
|
|
||
|
[DefaultProperty ("Text")]
|
||
|
[DesignTimeVisible (false)]
|
||
|
[Serializable]
|
||
|
[ToolboxItem (false)]
|
||
|
[TypeConverter (typeof(ListViewSubItemConverter))]
|
||
|
public class ListViewSubItem
|
||
|
{
|
||
|
[NonSerialized]
|
||
|
internal ListViewItem owner;
|
||
|
private string text = string.Empty;
|
||
|
private string name;
|
||
|
private object userData;
|
||
|
private SubItemStyle style;
|
||
|
[NonSerialized]
|
||
|
internal Rectangle bounds;
|
||
|
|
||
|
|
||
|
#region UIA Framework: Methods, Properties and Events
|
||
|
|
||
|
[field:NonSerialized]
|
||
|
internal event EventHandler UIATextChanged;
|
||
|
|
||
|
private void OnUIATextChanged ()
|
||
|
{
|
||
|
if (UIATextChanged != null)
|
||
|
UIATextChanged (this, EventArgs.Empty);
|
||
|
}
|
||
|
|
||
|
#endregion // UIA Framework: Methods, Properties and Events
|
||
|
|
||
|
|
||
|
#region Public Constructors
|
||
|
public ListViewSubItem ()
|
||
|
: this (null, string.Empty, Color.Empty,
|
||
|
Color.Empty, null)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public ListViewSubItem (ListViewItem owner, string text)
|
||
|
: this (owner, text, Color.Empty,
|
||
|
Color.Empty, null)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public ListViewSubItem (ListViewItem owner, string text, Color foreColor,
|
||
|
Color backColor, Font font)
|
||
|
{
|
||
|
this.owner = owner;
|
||
|
Text = text;
|
||
|
this.style = new SubItemStyle (foreColor,
|
||
|
backColor, font);
|
||
|
}
|
||
|
#endregion // Public Constructors
|
||
|
|
||
|
#region Public Instance Properties
|
||
|
public Color BackColor {
|
||
|
get {
|
||
|
if (style.backColor != Color.Empty)
|
||
|
return style.backColor;
|
||
|
if (this.owner != null && this.owner.ListView != null)
|
||
|
return this.owner.ListView.BackColor;
|
||
|
return ThemeEngine.Current.ColorWindow;
|
||
|
}
|
||
|
set {
|
||
|
style.backColor = value;
|
||
|
Invalidate ();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[Browsable (false)]
|
||
|
public Rectangle Bounds {
|
||
|
get {
|
||
|
Rectangle retval = bounds;
|
||
|
if (owner != null) {
|
||
|
retval.X += owner.Bounds.X;
|
||
|
retval.Y += owner.Bounds.Y;
|
||
|
}
|
||
|
|
||
|
return retval;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[Localizable (true)]
|
||
|
public Font Font {
|
||
|
get {
|
||
|
if (style.font != null)
|
||
|
return style.font;
|
||
|
else if (owner != null)
|
||
|
return owner.Font;
|
||
|
return ThemeEngine.Current.DefaultFont;
|
||
|
}
|
||
|
set {
|
||
|
if (style.font == value)
|
||
|
return;
|
||
|
style.font = value;
|
||
|
Invalidate ();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public Color ForeColor {
|
||
|
get {
|
||
|
if (style.foreColor != Color.Empty)
|
||
|
return style.foreColor;
|
||
|
if (this.owner != null && this.owner.ListView != null)
|
||
|
return this.owner.ListView.ForeColor;
|
||
|
return ThemeEngine.Current.ColorWindowText;
|
||
|
}
|
||
|
set {
|
||
|
style.foreColor = value;
|
||
|
Invalidate ();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[Localizable (true)]
|
||
|
public string Name {
|
||
|
get {
|
||
|
if (name == null)
|
||
|
return string.Empty;
|
||
|
return name;
|
||
|
}
|
||
|
set {
|
||
|
name = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[TypeConverter (typeof (StringConverter))]
|
||
|
[BindableAttribute (true)]
|
||
|
[DefaultValue (null)]
|
||
|
[Localizable (false)]
|
||
|
public object Tag {
|
||
|
get {
|
||
|
return userData;
|
||
|
}
|
||
|
set {
|
||
|
userData = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[Localizable (true)]
|
||
|
public string Text {
|
||
|
get { return text; }
|
||
|
set {
|
||
|
if(text == value)
|
||
|
return;
|
||
|
|
||
|
if(value == null)
|
||
|
text = string.Empty;
|
||
|
else
|
||
|
text = value;
|
||
|
|
||
|
Invalidate ();
|
||
|
|
||
|
// UIA Framework: Generates SubItem TextChanged
|
||
|
OnUIATextChanged ();
|
||
|
}
|
||
|
}
|
||
|
#endregion // Public Instance Properties
|
||
|
|
||
|
#region Public Methods
|
||
|
public void ResetStyle ()
|
||
|
{
|
||
|
style.Reset ();
|
||
|
Invalidate ();
|
||
|
}
|
||
|
|
||
|
public override string ToString ()
|
||
|
{
|
||
|
return string.Format ("ListViewSubItem {{0}}", text);
|
||
|
}
|
||
|
#endregion // Public Methods
|
||
|
|
||
|
#region Private Methods
|
||
|
private void Invalidate ()
|
||
|
{
|
||
|
if (owner == null || owner.owner == null)
|
||
|
return;
|
||
|
|
||
|
owner.Invalidate ();
|
||
|
}
|
||
|
|
||
|
[OnDeserialized]
|
||
|
void OnDeserialized (StreamingContext context)
|
||
|
{
|
||
|
name = null;
|
||
|
userData = null;
|
||
|
}
|
||
|
|
||
|
internal int Height {
|
||
|
get {
|
||
|
return bounds.Height;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal void SetBounds (int x, int y, int width, int height)
|
||
|
{
|
||
|
bounds = new Rectangle (x, y, width, height);
|
||
|
}
|
||
|
|
||
|
#endregion // Private Methods
|
||
|
|
||
|
[Serializable]
|
||
|
class SubItemStyle
|
||
|
{
|
||
|
public SubItemStyle ()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public SubItemStyle (Color foreColor, Color backColor, Font font)
|
||
|
{
|
||
|
this.foreColor = foreColor;
|
||
|
this.backColor = backColor;
|
||
|
this.font = font;
|
||
|
}
|
||
|
|
||
|
public void Reset ()
|
||
|
{
|
||
|
foreColor = Color.Empty;
|
||
|
backColor = Color.Empty;
|
||
|
font = null;
|
||
|
}
|
||
|
|
||
|
public Color backColor;
|
||
|
public Color foreColor;
|
||
|
public Font font;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public class ListViewSubItemCollection : IList, ICollection, IEnumerable
|
||
|
{
|
||
|
private ArrayList list;
|
||
|
internal ListViewItem owner;
|
||
|
|
||
|
#region Public Constructors
|
||
|
public ListViewSubItemCollection (ListViewItem owner) : this (owner, owner.Text)
|
||
|
{
|
||
|
}
|
||
|
#endregion // Public Constructors
|
||
|
|
||
|
internal ListViewSubItemCollection (ListViewItem owner, string text)
|
||
|
{
|
||
|
this.owner = owner;
|
||
|
this.list = new ArrayList ();
|
||
|
if (text != null)
|
||
|
Add (text);
|
||
|
}
|
||
|
#region Public Properties
|
||
|
[Browsable (false)]
|
||
|
public int Count {
|
||
|
get { return list.Count; }
|
||
|
}
|
||
|
|
||
|
public bool IsReadOnly {
|
||
|
get { return false; }
|
||
|
}
|
||
|
|
||
|
public ListViewSubItem this [int index] {
|
||
|
get { return (ListViewSubItem) list [index]; }
|
||
|
set {
|
||
|
value.owner = owner;
|
||
|
list [index] = value;
|
||
|
owner.Layout ();
|
||
|
owner.Invalidate ();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public virtual ListViewSubItem this [string key] {
|
||
|
get {
|
||
|
int idx = IndexOfKey (key);
|
||
|
if (idx == -1)
|
||
|
return null;
|
||
|
|
||
|
return (ListViewSubItem) list [idx];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool ICollection.IsSynchronized {
|
||
|
get { return list.IsSynchronized; }
|
||
|
}
|
||
|
|
||
|
object ICollection.SyncRoot {
|
||
|
get { return list.SyncRoot; }
|
||
|
}
|
||
|
|
||
|
bool IList.IsFixedSize {
|
||
|
get { return list.IsFixedSize; }
|
||
|
}
|
||
|
|
||
|
object IList.this [int index] {
|
||
|
get { return this [index]; }
|
||
|
set {
|
||
|
if (! (value is ListViewSubItem))
|
||
|
throw new ArgumentException ("Not of type ListViewSubItem", "value");
|
||
|
this [index] = (ListViewSubItem) value;
|
||
|
}
|
||
|
}
|
||
|
#endregion // Public Properties
|
||
|
|
||
|
#region Public Methods
|
||
|
public ListViewSubItem Add (ListViewSubItem item)
|
||
|
{
|
||
|
AddSubItem (item);
|
||
|
owner.Layout ();
|
||
|
owner.Invalidate ();
|
||
|
return item;
|
||
|
}
|
||
|
|
||
|
public ListViewSubItem Add (string text)
|
||
|
{
|
||
|
ListViewSubItem item = new ListViewSubItem (owner, text);
|
||
|
return Add (item);
|
||
|
}
|
||
|
|
||
|
public ListViewSubItem Add (string text, Color foreColor,
|
||
|
Color backColor, Font font)
|
||
|
{
|
||
|
ListViewSubItem item = new ListViewSubItem (owner, text,
|
||
|
foreColor, backColor, font);
|
||
|
return Add (item);
|
||
|
}
|
||
|
|
||
|
public void AddRange (ListViewSubItem [] items)
|
||
|
{
|
||
|
if (items == null)
|
||
|
throw new ArgumentNullException ("items");
|
||
|
|
||
|
foreach (ListViewSubItem item in items) {
|
||
|
if (item == null)
|
||
|
continue;
|
||
|
AddSubItem (item);
|
||
|
}
|
||
|
owner.Layout ();
|
||
|
owner.Invalidate ();
|
||
|
}
|
||
|
|
||
|
public void AddRange (string [] items)
|
||
|
{
|
||
|
if (items == null)
|
||
|
throw new ArgumentNullException ("items");
|
||
|
|
||
|
foreach (string item in items) {
|
||
|
if (item == null)
|
||
|
continue;
|
||
|
AddSubItem (new ListViewSubItem (owner, item));
|
||
|
}
|
||
|
owner.Layout ();
|
||
|
owner.Invalidate ();
|
||
|
}
|
||
|
|
||
|
public void AddRange (string [] items, Color foreColor,
|
||
|
Color backColor, Font font)
|
||
|
{
|
||
|
if (items == null)
|
||
|
throw new ArgumentNullException ("items");
|
||
|
|
||
|
foreach (string item in items) {
|
||
|
if (item == null)
|
||
|
continue;
|
||
|
|
||
|
AddSubItem (new ListViewSubItem (owner, item, foreColor, backColor, font));
|
||
|
}
|
||
|
owner.Layout ();
|
||
|
owner.Invalidate ();
|
||
|
}
|
||
|
|
||
|
void AddSubItem (ListViewSubItem subItem)
|
||
|
{
|
||
|
subItem.owner = owner;
|
||
|
list.Add (subItem);
|
||
|
|
||
|
//UIA Framework
|
||
|
subItem.UIATextChanged += OnUIASubItemTextChanged;
|
||
|
}
|
||
|
|
||
|
public void Clear ()
|
||
|
{
|
||
|
list.Clear ();
|
||
|
}
|
||
|
|
||
|
public bool Contains (ListViewSubItem subItem)
|
||
|
{
|
||
|
return list.Contains (subItem);
|
||
|
}
|
||
|
|
||
|
public virtual bool ContainsKey (string key)
|
||
|
{
|
||
|
return IndexOfKey (key) != -1;
|
||
|
}
|
||
|
|
||
|
public IEnumerator GetEnumerator ()
|
||
|
{
|
||
|
return list.GetEnumerator ();
|
||
|
}
|
||
|
|
||
|
void ICollection.CopyTo (Array dest, int index)
|
||
|
{
|
||
|
list.CopyTo (dest, index);
|
||
|
}
|
||
|
|
||
|
int IList.Add (object item)
|
||
|
{
|
||
|
if (! (item is ListViewSubItem)) {
|
||
|
throw new ArgumentException ("Not of type ListViewSubItem", "item");
|
||
|
}
|
||
|
|
||
|
ListViewSubItem sub_item = (ListViewSubItem) item;
|
||
|
sub_item.owner = this.owner;
|
||
|
//UIA Framework
|
||
|
sub_item.UIATextChanged += OnUIASubItemTextChanged;
|
||
|
return list.Add (sub_item);
|
||
|
}
|
||
|
|
||
|
bool IList.Contains (object subItem)
|
||
|
{
|
||
|
if (! (subItem is ListViewSubItem)) {
|
||
|
throw new ArgumentException ("Not of type ListViewSubItem", "subItem");
|
||
|
}
|
||
|
|
||
|
return this.Contains ((ListViewSubItem) subItem);
|
||
|
}
|
||
|
|
||
|
int IList.IndexOf (object subItem)
|
||
|
{
|
||
|
if (! (subItem is ListViewSubItem)) {
|
||
|
throw new ArgumentException ("Not of type ListViewSubItem", "subItem");
|
||
|
}
|
||
|
|
||
|
return this.IndexOf ((ListViewSubItem) subItem);
|
||
|
}
|
||
|
|
||
|
void IList.Insert (int index, object item)
|
||
|
{
|
||
|
if (! (item is ListViewSubItem)) {
|
||
|
throw new ArgumentException ("Not of type ListViewSubItem", "item");
|
||
|
}
|
||
|
|
||
|
this.Insert (index, (ListViewSubItem) item);
|
||
|
}
|
||
|
|
||
|
void IList.Remove (object item)
|
||
|
{
|
||
|
if (! (item is ListViewSubItem)) {
|
||
|
throw new ArgumentException ("Not of type ListViewSubItem", "item");
|
||
|
}
|
||
|
|
||
|
this.Remove ((ListViewSubItem) item);
|
||
|
}
|
||
|
|
||
|
public int IndexOf (ListViewSubItem subItem)
|
||
|
{
|
||
|
return list.IndexOf (subItem);
|
||
|
}
|
||
|
|
||
|
public virtual int IndexOfKey (string key)
|
||
|
{
|
||
|
if (key == null || key.Length == 0)
|
||
|
return -1;
|
||
|
|
||
|
for (int i = 0; i < list.Count; i++) {
|
||
|
ListViewSubItem l = (ListViewSubItem) list [i];
|
||
|
if (String.Compare (l.Name, key, true) == 0)
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
public void Insert (int index, ListViewSubItem item)
|
||
|
{
|
||
|
item.owner = this.owner;
|
||
|
list.Insert (index, item);
|
||
|
owner.Layout ();
|
||
|
owner.Invalidate ();
|
||
|
|
||
|
//UIA Framework
|
||
|
item.UIATextChanged += OnUIASubItemTextChanged;
|
||
|
}
|
||
|
|
||
|
public void Remove (ListViewSubItem item)
|
||
|
{
|
||
|
list.Remove (item);
|
||
|
owner.Layout ();
|
||
|
owner.Invalidate ();
|
||
|
|
||
|
//UIA Framework
|
||
|
item.UIATextChanged -= OnUIASubItemTextChanged;
|
||
|
}
|
||
|
|
||
|
public virtual void RemoveByKey (string key)
|
||
|
{
|
||
|
int idx = IndexOfKey (key);
|
||
|
if (idx != -1)
|
||
|
RemoveAt (idx);
|
||
|
}
|
||
|
|
||
|
public void RemoveAt (int index)
|
||
|
{
|
||
|
//UIA Framework
|
||
|
if (index >= 0 && index < list.Count)
|
||
|
((ListViewSubItem) list [index]).UIATextChanged -= OnUIASubItemTextChanged;
|
||
|
|
||
|
list.RemoveAt (index);
|
||
|
|
||
|
}
|
||
|
#endregion // Public Methods
|
||
|
#region UIA Event Handler
|
||
|
|
||
|
private void OnUIASubItemTextChanged (object sender, EventArgs args)
|
||
|
{
|
||
|
owner.OnUIASubItemTextChanged (new LabelEditEventArgs (list.IndexOf (sender)));
|
||
|
}
|
||
|
|
||
|
#endregion
|
||
|
|
||
|
|
||
|
}
|
||
|
#endregion // Subclasses
|
||
|
}
|
||
|
}
|