/*
* OLVListItem - A row in an ObjectListView
*
* Author: Phillip Piper
* Date: 31-March-2011 5:53 pm
*
* Change log:
* v2.8
* 2014-09-27 JPP - Remove faulty caching of CheckState
* 2014-05-06 JPP - Added OLVListItem.Enabled flag
* vOld
* 2011-03-31 JPP - Split into its own file
*
* Copyright (C) 2011-2014 Phillip Piper
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* If you wish to use this code in a closed source application, please contact phillip_piper@bigfoot.com.
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
namespace BrightIdeasSoftware {
///
/// OLVListItems are specialized ListViewItems that know which row object they came from,
/// and the row index at which they are displayed, even when in group view mode. They
/// also know the image they should draw against themselves
///
public class OLVListItem : ListViewItem {
#region Constructors
///
/// Create a OLVListItem for the given row object
///
public OLVListItem(object rowObject) {
this.rowObject = rowObject;
}
///
/// Create a OLVListItem for the given row object, represented by the given string and image
///
public OLVListItem(object rowObject, string text, Object image)
: base(text, -1) {
this.rowObject = rowObject;
this.imageSelector = image;
}
#endregion
#region Properties
///
/// Gets the bounding rectangle of the item, including all subitems
///
new public Rectangle Bounds {
get {
try {
return base.Bounds;
}
catch (System.ArgumentException) {
// If the item is part of a collapsed group, Bounds will throw an exception
return Rectangle.Empty;
}
}
}
///
/// Gets or sets how many pixels will be left blank around each cell of this item
///
/// This setting only takes effect when the control is owner drawn.
public Rectangle? CellPadding {
get { return this.cellPadding; }
set { this.cellPadding = value; }
}
private Rectangle? cellPadding;
///
/// Gets or sets how the cells of this item will be vertically aligned
///
/// This setting only takes effect when the control is owner drawn.
public StringAlignment? CellVerticalAlignment {
get { return this.cellVerticalAlignment; }
set { this.cellVerticalAlignment = value; }
}
private StringAlignment? cellVerticalAlignment;
///
/// Gets or sets the checkedness of this item.
///
///
/// Virtual lists don't handle checkboxes well, so we have to intercept attempts to change them
/// through the items, and change them into something that will work.
/// Unfortuneately, this won't work if this property is set through the base class, since
/// the property is not declared as virtual.
///
new public bool Checked {
get {
return base.Checked;
}
set {
if (this.Checked != value) {
if (value)
((ObjectListView)this.ListView).CheckObject(this.RowObject);
else
((ObjectListView)this.ListView).UncheckObject(this.RowObject);
}
}
}
///
/// Enable tri-state checkbox.
///
/// .NET's Checked property was not built to handle tri-state checkboxes,
/// and will return True for both Checked and Indeterminate states.
public CheckState CheckState {
get {
switch (this.StateImageIndex) {
case 0:
return System.Windows.Forms.CheckState.Unchecked;
case 1:
return System.Windows.Forms.CheckState.Checked;
case 2:
return System.Windows.Forms.CheckState.Indeterminate;
default:
return System.Windows.Forms.CheckState.Unchecked;
}
}
set {
switch (value) {
case System.Windows.Forms.CheckState.Unchecked:
this.StateImageIndex = 0;
break;
case System.Windows.Forms.CheckState.Checked:
this.StateImageIndex = 1;
break;
case System.Windows.Forms.CheckState.Indeterminate:
this.StateImageIndex = 2;
break;
}
}
}
///
/// Gets if this item has any decorations set for it.
///
public bool HasDecoration {
get {
return this.decorations != null && this.decorations.Count > 0;
}
}
///
/// Gets or sets the decoration that will be drawn over this item
///
/// Setting this replaces all other decorations
public IDecoration Decoration {
get {
if (this.HasDecoration)
return this.Decorations[0];
else
return null;
}
set {
this.Decorations.Clear();
if (value != null)
this.Decorations.Add(value);
}
}
///
/// Gets the collection of decorations that will be drawn over this item
///
public IList Decorations {
get {
if (this.decorations == null)
this.decorations = new List();
return this.decorations;
}
}
private IList decorations;
///
/// Gets whether or not this row can be selected and activated
///
public bool Enabled
{
get { return this.enabled; }
internal set { this.enabled = value; }
}
private bool enabled;
///
/// Get or set the image that should be shown against this item
///
/// This can be an Image, a string or an int. A string or an int will
/// be used as an index into the small image list.
public Object ImageSelector {
get { return imageSelector; }
set {
imageSelector = value;
if (value is Int32)
this.ImageIndex = (Int32)value;
else if (value is String)
this.ImageKey = (String)value;
else
this.ImageIndex = -1;
}
}
private Object imageSelector;
///
/// Gets or sets the the model object that is source of the data for this list item.
///
public object RowObject {
get { return rowObject; }
set { rowObject = value; }
}
private object rowObject;
#endregion
#region Accessing
///
/// Return the sub item at the given index
///
/// Index of the subitem to be returned
/// An OLVListSubItem
public virtual OLVListSubItem GetSubItem(int index) {
if (index >= 0 && index < this.SubItems.Count)
return (OLVListSubItem)this.SubItems[index];
return null;
}
///
/// Return bounds of the given subitem
///
/// This correctly calculates the bounds even for column 0.
public virtual Rectangle GetSubItemBounds(int subItemIndex) {
if (subItemIndex == 0) {
Rectangle r = this.Bounds;
Point sides = NativeMethods.GetScrolledColumnSides(this.ListView, subItemIndex);
r.X = sides.X + 1;
r.Width = sides.Y - sides.X;
return r;
}
OLVListSubItem subItem = this.GetSubItem(subItemIndex);
return subItem == null ? new Rectangle() : subItem.Bounds;
}
#endregion
}
}