using System;
using System.Collections.Generic;
//using System.Drawing;
using System.Linq;
using System.Text.RegularExpressions;
using Gwen.Control.Layout;
namespace Gwen.Control
{
///
/// ListBox control.
///
public class ListBox : ScrollControl
{
private readonly Table m_Table;
private readonly List m_SelectedRows;
private bool m_MultiSelect;
private bool m_IsToggle;
private bool m_SizeToContents;
private Pos m_OldDock; // used while autosizing
///
/// Determines whether multiple rows can be selected at once.
///
public bool AllowMultiSelect
{
get { return m_MultiSelect; }
set
{
m_MultiSelect = value;
if (value)
IsToggle = true;
}
}
///
/// Determines whether rows can be unselected by clicking on them again.
///
public bool IsToggle { get { return m_IsToggle; } set { m_IsToggle = value; } }
///
/// Number of rows in the list box.
///
public int RowCount { get { return m_Table.RowCount; } }
///
/// Returns specific row of the ListBox.
///
/// Row index.
/// Row at the specified index.
public ListBoxRow this[int index] { get { return m_Table[index] as ListBoxRow; } }
///
/// List of selected rows.
///
public IEnumerable SelectedRows { get { return m_SelectedRows; } }
///
/// First selected row (and only if list is not multiselectable).
///
public TableRow SelectedRow
{
get
{
if (m_SelectedRows.Count == 0)
return null;
return m_SelectedRows[0];
}
}
///
/// Gets the selected row number.
///
public int SelectedRowIndex
{
get
{
var selected = SelectedRow;
if (selected == null)
return -1;
return m_Table.GetRowIndex(selected);
}
}
///
/// Column count of table rows.
///
public int ColumnCount { get { return m_Table.ColumnCount; } set { m_Table.ColumnCount = value; Invalidate(); } }
///
/// Invoked when a row has been selected.
///
public event GwenEventHandler RowSelected;
///
/// Invoked whan a row has beed unselected.
///
public event GwenEventHandler RowUnselected;
///
/// Initializes a new instance of the class.
///
/// Parent control.
public ListBox(Base parent)
: base(parent)
{
m_SelectedRows = new List();
EnableScroll(false, true);
AutoHideBars = true;
Margin = Margin.One;
m_Table = new Table(this);
m_Table.Dock = Pos.Fill;
m_Table.ColumnCount = 1;
m_Table.BoundsChanged += TableResized;
m_MultiSelect = false;
m_IsToggle = false;
}
///
/// Selects the specified row by index.
///
/// Row to select.
/// Determines whether to deselect previously selected rows.
public void SelectRow(int index, bool clearOthers = false)
{
if (index < 0 || index >= m_Table.RowCount)
return;
SelectRow(m_Table.Children[index], clearOthers);
}
///
/// Selects the specified row(s) by text.
///
/// Text to search for (exact match).
/// Determines whether to deselect previously selected rows.
public void SelectRows(String rowText, bool clearOthers = false)
{
var rows = m_Table.Children.OfType().Where(x => x.Text == rowText);
foreach (ListBoxRow row in rows)
{
SelectRow(row, clearOthers);
}
}
///
/// Selects the specified row(s) by regex text search.
///
/// Regex pattern to search for.
/// Regex options.
/// Determines whether to deselect previously selected rows.
public void SelectRowsByRegex(String pattern, RegexOptions regexOptions = RegexOptions.None, bool clearOthers = false)
{
var rows = m_Table.Children.OfType().Where(x => Regex.IsMatch(x.Text, pattern) );
foreach (ListBoxRow row in rows)
{
SelectRow(row, clearOthers);
}
}
///
/// Slelects the specified row.
///
/// Row to select.
/// Determines whether to deselect previously selected rows.
public void SelectRow(Base control, bool clearOthers = false)
{
if (!AllowMultiSelect || clearOthers)
UnselectAll();
ListBoxRow row = control as ListBoxRow;
if (row == null)
return;
// TODO: make sure this is one of our rows!
row.IsSelected = true;
m_SelectedRows.Add(row);
if (RowSelected != null)
RowSelected.Invoke(this);
}
///
/// Removes the specified row by index.
///
/// Row index.
public void RemoveRow(int idx)
{
m_Table.RemoveRow(idx); // this calls Dispose()
}
///
/// Adds a new row.
///
/// Row text.
/// Newly created control.
public TableRow AddRow(String label)
{
return AddRow(label, String.Empty);
}
///
/// Adds a new row.
///
/// Row text.
/// Internal control name.
/// Newly created control.
public TableRow AddRow(String label, String name)
{
ListBoxRow row = new ListBoxRow(this);
m_Table.AddRow(row);
row.SetCellText(0, label);
row.Name = name;
row.Selected += OnRowSelected;
m_Table.SizeToContents(Width);
return row;
}
///
/// Sets the column width (in pixels).
///
/// Column index.
/// Column width.
public void SetColumnWidth(int column, int width)
{
m_Table.SetColumnWidth(column, width);
Invalidate();
}
///
/// Renders the control using specified skin.
///
/// Skin to use.
protected override void Render(Skin.Base skin)
{
skin.DrawListBox(this);
}
///
/// Deselects all rows.
///
public virtual void UnselectAll()
{
foreach (ListBoxRow row in m_SelectedRows)
{
row.IsSelected = false;
if (RowUnselected != null)
RowUnselected.Invoke(this);
}
m_SelectedRows.Clear();
}
///
/// Unselects the specified row.
///
/// Row to unselect.
public void UnselectRow(ListBoxRow row)
{
row.IsSelected = false;
m_SelectedRows.Remove(row);
if (RowUnselected != null)
RowUnselected.Invoke(this);
}
///
/// Handler for the row selection event.
///
/// Event source.
protected virtual void OnRowSelected(Base control)
{
// [omeg] changed default behavior
bool clear = false;// !InputHandler.InputHandler.IsShiftDown;
ListBoxRow row = control as ListBoxRow;
if (row == null)
return;
if (row.IsSelected)
{
if (IsToggle)
UnselectRow(row);
}
else
{
SelectRow(control, clear);
}
}
///
/// Removes all rows.
///
public virtual void Clear()
{
UnselectAll();
m_Table.RemoveAll();
}
public void SizeToContents()
{
m_SizeToContents = true;
// docking interferes with autosizing so we disable it until sizing is done
m_OldDock = m_Table.Dock;
m_Table.Dock = Pos.None;
m_Table.SizeToContents(0); // autosize without constraints
}
private void TableResized(Base control)
{
if (m_SizeToContents)
{
SetSize(m_Table.Width, m_Table.Height);
m_SizeToContents = false;
m_Table.Dock = m_OldDock;
Invalidate();
}
}
}
}