using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
namespace BizHawk.Client.EmuHawk
{
///
/// A performant VirtualListView implementation that doesn't rely on native Win32 API calls
/// (and in fact does not inherit the ListView class at all)
/// It is an enhanced version of the work done with GDI+ rendering in InputRoll.cs
/// -------------------------
/// *** Public Properties ***
/// -------------------------
///
public partial class PlatformAgnosticVirtualListView
{
#region ListView Compatibility Properties
///
/// This VirtualListView implementation doesn't really need this, but it is here for compatibility
///
[Category("Behavior")]
public int VirtualListSize
{
get
{
return _itemCount;
}
set
{
_itemCount = value;
RecalculateScrollBars();
}
}
///
/// ListView compatibility property
/// THIS DOES NOT WORK PROPERLY - AVOID!
///
[System.ComponentModel.Browsable(false)]
public System.Windows.Forms.ListView.SelectedIndexCollection SelectedIndices
{
// !!! does not work properly, avoid using this in the calling implementation !!!
get
{
var tmpListView = new System.Windows.Forms.ListView();
//tmpListView.VirtualMode = true;
//var selectedIndexCollection = new System.Windows.Forms.ListView.SelectedIndexCollection(tmpListView);
//tmpListView.VirtualListSize = ItemCount;
for (int i = 0; i < ItemCount; i++)
{
tmpListView.Items.Add(i.ToString());
}
//tmpListView.Refresh();
if (AnyRowsSelected)
{
var indices = SelectedRows.ToList();
foreach (var i in indices)
{
tmpListView.SelectedIndices.Add(i);
//selectedIndexCollection.Add(i);
}
}
return tmpListView.SelectedIndices; // selectedIndexCollection;
}
}
///
/// Compatibility property
/// With a standard ListView you can add columns in the Designer
/// We will ignore this (but leave it here for compatibility)
/// Columns must be added through the AddColumns() public method
///
public System.Windows.Forms.ListView.ColumnHeaderCollection Columns = new System.Windows.Forms.ListView.ColumnHeaderCollection(new System.Windows.Forms.ListView());
///
/// Compatibility with ListView class
/// This is not used in this implementation
///
[Category("Behavior")]
public bool VirtualMode { get; set; }
///
/// Gets or sets a value indicating whether the selected item in the control remains highlighted when the control loses focus
///
[Category("Behavior")]
public bool HideSelection { get; set; }
///
/// Gets or sets a value indicating whether the ListView uses state image behavior that is compatible with the .NET Framework 1.1 or the .NET Framework 2.0.
/// Here for ListView api compatibility (we dont care about this)
///
[System.ComponentModel.Browsable(false)]
public bool UseCompatibleStateImageBehavior { get; set; }
///
/// Gets or sets how items are displayed in the control.
/// Here for ListView api compatibility (we dont care about this)
///
public System.Windows.Forms.View View { get; set; }
#endregion
#region VirtualListView Compatibility Properties
///
/// Informs user that a select all event is in place, can be used in change events to wait until this is false
/// Not used in this implementation (yet)
///
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool SelectAllInProgress { get; set; }
///
/// Gets/Sets the selected item
/// Here for compatibility with VirtualListView.cs
///
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int selectedItem
{
get
{
if (SelectedRows.Count() == 0)
{
return -1;
}
else
{
return SelectedRows.First();
}
}
set
{
SelectItem(value, true);
}
}
[Category("Behavior")]
public bool BlazingFast { get; set; }
#endregion
#region Behavior
///
/// Gets or sets the amount of left and right padding on the text inside a cell
///
[DefaultValue(3)]
[Category("Behavior")]
public int CellWidthPadding { get; set; }
///
/// Gets or sets the amount of top and bottom padding on the text inside a cell
///
[DefaultValue(1)]
[Category("Behavior")]
public int CellHeightPadding { get; set; }
///
/// Gets or sets the scrolling speed
///
[Category("Behavior")]
public int ScrollSpeed
{
get
{
if (CellHeight == 0)
CellHeight++;
return _vBar.SmallChange / CellHeight;
}
set
{
_vBar.SmallChange = value * CellHeight;
}
}
///
/// Gets or sets a value indicating whether columns can be resized
///
[Category("Behavior")]
[DefaultValue(true)]
public bool AllowColumnResize { get; set; }
///
/// Gets or sets a value indicating whether columns can be reordered
///
[Category("Behavior")]
[DefaultValue(true)]
public bool AllowColumnReorder { get; set; }
///
/// Gets or sets a value indicating whether multiple items can to be selected
///
[Category("Behavior")]
[DefaultValue(true)]
public bool MultiSelect { get; set; }
///
/// Gets or sets a value indicating whether the control is in input painting mode
///
[Category("Behavior")]
[DefaultValue(false)]
public bool InputPaintingMode { get; set; }
///
/// Gets or sets how the InputRoll scrolls when calling ScrollToIndex.
///
[DefaultValue("near")]
[Category("Behavior")]
public string ScrollMethod { get; set; }
///
/// Gets or sets a value indicating how the Intever for the hover event
///
[DefaultValue(false)]
[Category("Behavior")]
public bool AlwaysScroll { get; set; }
///
/// Gets or sets the lowest seek interval to activate the progress bar
///
[Category("Behavior")]
public int SeekingCutoffInterval { get; set; }
[DefaultValue(750)]
[Category("Behavior")]
public int HoverInterval
{
get { return _hoverTimer.Interval; }
set { _hoverTimer.Interval = value; }
}
///
/// Gets or sets whether you can use right click to select things
///
[Category("Behavior")]
public bool AllowRightClickSelecton { get; set; }
///
/// Gets or sets whether keys can modify selection
///
[Category("Behavior")]
public bool LetKeysModifySelection { get; set; }
///
/// Gets or sets whether hot keys are suspended
///
[Category("Behavior")]
public bool SuspendHotkeys { get; set; }
#endregion
#region Appearance
///
/// Gets or sets a value indicating whether grid lines are displayed around cells
///
[Category("Appearance")]
[DefaultValue(true)]
public bool GridLines { get; set; }
///
/// Gets or sets a value indicating whether the entire row will always be selected
///
[Category("Appearance")]
[DefaultValue(false)]
public bool FullRowSelect { get; set; }
///
/// Gets or sets the font used for the column header text
/// Also forces a cell size re-evaluation
///
[Category("Appearance")]
public Font ColumnHeaderFont
{
get
{
if (_columnHeaderFont == null)
{
ColumnHeaderFont = new Font("Arial", 8, FontStyle.Bold);
}
return _columnHeaderFont;
}
set
{
_columnHeaderFont = value;
SetCharSize();
}
}
private Font _columnHeaderFont;
///
/// Gets or sets the color of the column header text
///
[Category("Appearance")]
public Color ColumnHeaderFontColor
{
get
{
if (_columnHeaderFontColor == null)
_columnHeaderFontColor = Color.Black;
return _columnHeaderFontColor;
}
set { _columnHeaderFontColor = value; }
}
private Color _columnHeaderFontColor;
///
/// Gets or sets the background color of the column header cells
///
[Category("Appearance")]
public Color ColumnHeaderBackgroundColor
{
get
{
if (_columnHeaderBackgroundColor == null)
_columnHeaderBackgroundColor = Color.LightGray;
return _columnHeaderBackgroundColor;
}
set { _columnHeaderBackgroundColor = value; }
}
private Color _columnHeaderBackgroundColor;
///
/// Gets or sets the background color of the column header cells when they are highlighted
///
[Category("Appearance")]
public Color ColumnHeaderBackgroundHighlightColor
{
get
{
if (_columnHeaderBackgroundHighlightColor == null)
_columnHeaderBackgroundHighlightColor = SystemColors.HighlightText;
return _columnHeaderBackgroundHighlightColor;
}
set { _columnHeaderBackgroundHighlightColor = value; }
}
private Color _columnHeaderBackgroundHighlightColor;
///
/// Gets or sets the color of the column header outline
///
[Category("Appearance")]
public Color ColumnHeaderOutlineColor
{
get
{
if (_columnHeaderOutlineColor == null)
_columnHeaderOutlineColor = Color.Black;
return _columnHeaderOutlineColor;
}
set
{
_columnHeaderOutlineColor = value;
}
}
private Color _columnHeaderOutlineColor;
///
/// Gets or sets the font used for every row cell
/// Also forces a cell size re-evaluation
///
[Category("Appearance")]
public Font CellFont
{
get
{
if (_cellFont == null)
{
CellFont = new Font("Arial", 8, FontStyle.Regular);
}
return _cellFont;
}
set
{
_cellFont = value;
SetCharSize();
}
}
private Font _cellFont;
///
/// Gets or sets the color of the font used for every row cell
///
[Category("Appearance")]
public Color CellFontColor
{
get
{
if (_cellFontColor == null)
_cellFontColor = Color.Black;
return _cellFontColor;
}
set { _cellFontColor = value; }
}
private Color _cellFontColor;
///
/// Gets or sets the background color for every row cell
///
[Category("Appearance")]
public Color CellBackgroundColor
{
get
{
if (_cellBackgroundColor == null)
_cellBackgroundColor = Color.White;
return _cellBackgroundColor;
}
set { _cellBackgroundColor = value; }
}
private Color _cellBackgroundColor;
///
/// Gets or sets the background color for every row cell that is highlighted
///
[Category("Appearance")]
public Color CellBackgroundHighlightColor
{
get
{
if (_cellBackgroundHighlightColor == null)
_cellBackgroundHighlightColor = Color.Blue;
return _cellBackgroundHighlightColor;
}
set { _cellBackgroundHighlightColor = value; }
}
private Color _cellBackgroundHighlightColor;
///
/// Gets or sets the color used to draw the ListView gridlines
///
[Category("Appearance")]
public Color GridLineColor
{
get
{
if (_gridLineColor == null)
_gridLineColor = SystemColors.ControlLight;
return _gridLineColor;
}
set { _gridLineColor = value; }
}
private Color _gridLineColor;
///
/// Gets or sets the size of control's border
/// Note: this is drawn directly onto the parent control, so large values will probably look terrible
///
[Category("Appearance")]
public int BorderSize { get; set; }
///
/// Defines the absolute minimum column size (used when manually resizing columns)
///
[DefaultValue(50)]
[Category("Appearance")]
public int MinimumColumnSize { get; set; }
///
/// The padding property is disabled for this control (as this is handled internally)
///
[Category("Appearance")]
public new System.Windows.Forms.Padding Padding
{
get { return new System.Windows.Forms.Padding(0); }
set { }
}
///
/// Gets or sets the color of the control's border
///
[Category("Appearance")]
public Color BorderColor
{
get
{
if (_borderColor == null)
_borderColor = SystemColors.InactiveBorder;
return _borderColor;
}
set { _borderColor = value; }
}
private Color _borderColor;
#endregion
#region API
///
/// All visible columns
///
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public IEnumerable VisibleColumns => _columns.VisibleColumns;
///
/// Gets or sets the sets the virtual number of rows to be displayed. Does not include the column header row.
///
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int ItemCount
{
get { return _itemCount; }
set
{
_itemCount = value;
RecalculateScrollBars();
}
}
///
/// Returns all columns including those that are not visible
///
///
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public ListColumns AllColumns => _columns;
///
/// Gets whether the mouse is currently over a column cell
///
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool IsPointingAtColumnHeader => IsHoveringOnColumnCell;
///
/// Returns the index of the first selected row (null if no selection)
///
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int? FirstSelectedIndex
{
get
{
if (AnyRowsSelected)
{
return SelectedRows.Min();
}
return null;
}
}
///
/// Returns the index of the last selected row (null if no selection)
///
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int? LastSelectedIndex
{
get
{
if (AnyRowsSelected)
{
return SelectedRows.Max();
}
return null;
}
}
///
/// Gets or sets the first visible row index, if scrolling is needed
///
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int FirstVisibleRow
{
get // SuuperW: This was checking if the scroll bars were needed, which is useless because their Value is 0 if they aren't needed.
{
if (CellHeight == 0) CellHeight++;
return _vBar.Value / CellHeight;
}
set
{
if (NeedsVScrollbar)
{
_programmaticallyUpdatingScrollBarValues = true;
if (value * CellHeight <= _vBar.Maximum)
{
_vBar.Value = value * CellHeight;
}
else
{
_vBar.Value = _vBar.Maximum;
}
_programmaticallyUpdatingScrollBarValues = false;
}
}
}
///
/// Gets the last row that is fully visible
///
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
private int LastFullyVisibleRow
{
get
{
int halfRow = 0;
if ((DrawHeight - ColumnHeight - 3) % CellHeight < CellHeight / 2)
{
halfRow = 1;
}
return FirstVisibleRow + VisibleRows - halfRow; // + CountLagFramesDisplay(VisibleRows - halfRow);
}
}
///
/// Gets or sets the last visible row
///
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int LastVisibleRow
{
get
{
return FirstVisibleRow + VisibleRows; // + CountLagFramesDisplay(VisibleRows);
}
set
{
int halfRow = 0;
if ((DrawHeight - ColumnHeight - 3) % CellHeight < CellHeight / 2)
{
halfRow = 1;
}
FirstVisibleRow = Math.Max(value - (VisibleRows - halfRow), 0);
}
}
///
/// Gets the number of rows currently visible including partially visible rows.
///
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int VisibleRows
{
get
{
if (CellHeight == 0) CellHeight++;
return (DrawHeight - ColumnHeight - 3) / CellHeight; // Minus three makes it work
}
}
///
/// Gets the first visible column index, if scrolling is needed
///
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int FirstVisibleColumn
{
get
{
if (CellHeight == 0) CellHeight++;
var columnList = VisibleColumns.ToList();
return columnList.FindIndex(c => c.Right > _hBar.Value);
}
}
///
/// Gets the last visible column index, if scrolling is needed
///
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int LastVisibleColumnIndex
{
get
{
if (CellHeight == 0) CellHeight++;
List columnList = VisibleColumns.ToList();
int ret;
ret = columnList.FindLastIndex(c => c.Left <= DrawWidth + _hBar.Value);
return ret;
}
}
///
/// Gets or sets the current Cell that the mouse was in.
///
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public Cell CurrentCell { get; set; }
///
/// Returns whether the current cell is a data cell or not
///
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool CurrentCellIsDataCell => CurrentCell?.RowIndex != null && CurrentCell.Column != null;
///
/// Gets a list of selected row indexes
///
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public IEnumerable SelectedRows
{
get
{
return _selectedItems
.Where(cell => cell.RowIndex.HasValue)
.Select(cell => cell.RowIndex.Value)
.Distinct();
}
}
///
/// Returns whether any rows are selected
///
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool AnyRowsSelected
{
get
{
return _selectedItems.Any(cell => cell.RowIndex.HasValue);
}
}
///
/// Gets or sets the previous Cell that the mouse was in.
///
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public Cell LastCell { get; private set; }
///
/// Gets or sets whether paint down is happening
///
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool IsPaintDown { get; private set; }
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool UseCustomBackground { get; set; }
///
/// Gets or sets the current draw height
///
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int DrawHeight { get; private set; }
///
/// Gets or sets the current draw width
///
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int DrawWidth { get; private set; }
///
/// Gets or sets whether the right mouse button is held down
///
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool RightButtonHeld { get; private set; }
#endregion
}
}