commit a82371fa935811286f4303768ec1631cab8b812d Author: Markus Ewald Date: Fri Mar 30 19:52:40 2007 +0000 Initial import of Nuclex.Windows.Forms, containing a special ListView control that can contain embedded controls in its cells git-svn-id: file:///srv/devel/repo-conversion/nuwi@1 d2e56fa2-650e-0410-a79f-9358c0239efd diff --git a/Nuclex.Windows.Forms.csproj b/Nuclex.Windows.Forms.csproj new file mode 100644 index 0000000..503589a --- /dev/null +++ b/Nuclex.Windows.Forms.csproj @@ -0,0 +1,95 @@ + + + {BDC43D2A-7638-412E-976A-E7E115803A27} + {9F340DF3-2AED-4330-AC16-78AC2D9B4738};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Debug + x86 + Library + Properties + Nuclex.Windows.Forms + Nuclex.Windows.Forms + v1.0 + Windows + Microsoft.Xna.Framework.Content.Pipeline.EffectImporter.dll;Microsoft.Xna.Framework.Content.Pipeline.FBXImporter.dll;Microsoft.Xna.Framework.Content.Pipeline.TextureImporter.dll;Microsoft.Xna.Framework.Content.Pipeline.XImporter.dll + + + + + true + full + false + bin\x86\Debug + DEBUG;TRACE + prompt + 4 + true + false + x86 + Documentation\Nuclex.Windows.Forms.xml + + + pdbonly + true + bin\x86\Release + TRACE + prompt + 4 + true + false + x86 + Documentation\Nuclex.Windows.Forms.xml + + + + False + + + False + + + False + + + False + + + + + + + + + + Component + false + ContainerListView + + + ContainerListView.cs + false + ContainerListView.Designer + + + false + ListViewEmbeddedControl + + + false + ListViewEmbeddedControlCollection + + + false + EmbeddedControlCollection + + + + + + + \ No newline at end of file diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..6311ec0 --- /dev/null +++ b/Properties/AssemblyInfo.cs @@ -0,0 +1,31 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Nuclex.Windows.Forms")] +[assembly: AssemblyProduct("Nuclex.Windows.Forms")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyCompany("Nuclex Development Labs")] +[assembly: AssemblyCopyright("Copyright © Nuclex Development Labs 2007")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("08254ad9-394e-4638-8412-098c8c4a4c39")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +[assembly: AssemblyVersion("1.0.0.0")] diff --git a/Source/ContainerListView/ContainerListView.Designer.cs b/Source/ContainerListView/ContainerListView.Designer.cs new file mode 100644 index 0000000..5355903 --- /dev/null +++ b/Source/ContainerListView/ContainerListView.Designer.cs @@ -0,0 +1,33 @@ +namespace Nuclex.Windows.Forms { + + partial class ContainerListView { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) { + if(disposing && (components != null)) { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() { + components = new System.ComponentModel.Container(); + } + + #endregion + } + +} // namespace Nuclex.Windows.Forms diff --git a/Source/ContainerListView/ContainerListView.cs b/Source/ContainerListView/ContainerListView.cs new file mode 100644 index 0000000..098b926 --- /dev/null +++ b/Source/ContainerListView/ContainerListView.cs @@ -0,0 +1,156 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Text; +using System.Windows.Forms; +using System.Runtime.InteropServices; + +namespace Nuclex.Windows.Forms { + + /// ListView allowing for other controls to be embedded in its cells + /// + /// There basically were two possible design choices: Provide a specialized + /// ListViewSubItem that carries a Control instead of a string or manage the + /// embedded controls in seperation of the ListView's items. The first option + /// would require a complete rewrite of the ListViewItem class and its related + /// support classes, all of which are surprisingly large and complex. Thus, + /// the less clean but more doable latter option has been chosen. + /// + public partial class ContainerListView : System.Windows.Forms.ListView { + + #region struct EmbeddedControl + + /// Informationen über ein ins ListView eingebettetes Steuerelement + private struct EmbeddedControl { + /// Steuerelement das im ListView eingebetttr ist + public Control Control; + /// Spalte in der das Control eingebettet ist + public int Column; + /// Zeile in der das Control eingebettet ist + public int Row; + /// Wie das Control in der ListView-Zelle angedockt ist + public DockStyle Dock; + /// Das ListView-Element in dem sich das Control befindet + public ListViewItem Item; + } + + #endregion // struct EmbeddedControl + + /// Initialisiert ein neues ListView-Steuerelement + public ContainerListView() { + this.embeddedControlClickedHandler = new EventHandler(embeddedControlClicked); + + this.embeddedControls = new ListViewEmbeddedControlCollection(); + this.embeddedControls.EmbeddedControlAdded += + new EventHandler( + embeddedControlAdded + ); + this.embeddedControls.EmbeddedControlRemoved += + new EventHandler( + embeddedControlRemoved + ); + + InitializeComponent(); + + base.View = View.Details; + base.AllowColumnReorder = false; + } + + /// Called when a control gets removed from the embedded controls list + /// List from which the control has been removed + /// Event arguments providing a reference to the removed control + private void embeddedControlAdded( + object sender, ListViewEmbeddedControlCollection.ListViewEmbeddedControlEventArgs e + ) { + e.EmbeddedControl.Control.Click += this.embeddedControlClickedHandler; + this.Controls.Add(e.EmbeddedControl.Control); + } + + /// Called when a control gets added to the embedded controls list + /// List to which the control has been added + /// Event arguments providing a reference to the added control + private void embeddedControlRemoved( + object sender, ListViewEmbeddedControlCollection.ListViewEmbeddedControlEventArgs e + ) { + if(this.Controls.Contains(e.EmbeddedControl.Control)) { + e.EmbeddedControl.Control.Click -= this.embeddedControlClickedHandler; + this.Controls.Remove(e.EmbeddedControl.Control); + } + } + + /// Called when an embedded control has been clicked on + /// Embedded control that has been clicked + /// Not used + private void embeddedControlClicked(object sender, EventArgs e) { + this.BeginUpdate(); + + try { + SelectedItems.Clear(); + + foreach(ListViewEmbeddedControl embeddedControl in this.embeddedControls) { + if(ReferenceEquals(embeddedControl.Control, sender)) { + if((embeddedControl.Row > 0) && (embeddedControl.Row < Items.Count)) + Items[embeddedControl.Row].Selected = true; + } + } + } + finally { + this.EndUpdate(); + } + } + + private int[] GetColumnOrder() { + int[] order = new int[this.Columns.Count]; + + for(int i = 0; i < this.Columns.Count; ++i) + order[this.Columns[i].DisplayIndex] = i; + + return order; + } + + /// Calculates the boundaries of a cell in the list view + /// Item in the list view from which to calculate the cell + /// Index der cell whose boundaries to calculate + /// The boundaries of the specified list view cell + protected Rectangle GetSubItemBounds(ListViewItem item, int subItem) { + + int[] order = GetColumnOrder(); + if (order == null) // No Columns + return Rectangle.Empty; + + if (subItem >= order.Length) + throw new IndexOutOfRangeException("SubItem " + subItem + " out of range"); + + // Rahmen des gesamten ListViewItems ermitteln, inklusive aller SubItems + Rectangle itemBounds = item.GetBounds(ItemBoundsPortion.Entire); + int subItemX = itemBounds.Left; + + // Horizontale Position des SubItems berechnen + // Da die Spaltenreihenfolge geändert werden kann müssen wir + // Columns[order[i]] statt Columns[i] verwenden! + ColumnHeader columnHeader; + int i; + for (i = 0; i < order.Length; ++i) { + columnHeader = this.Columns[order[i]]; + if (columnHeader.Index == subItem) + break; + + subItemX += columnHeader.Width; + } + + return new Rectangle( + subItemX, itemBounds.Top, this.Columns[order[i]].Width, itemBounds.Height + ); + + } + + /// Event handler for when embedded controls are clicked on + private EventHandler embeddedControlClickedHandler; + /// Controls being embedded in this ListView + private ListViewEmbeddedControlCollection embeddedControls; + + } + +} // namespace Nuclex.Windows.Forms diff --git a/Source/ContainerListView/ListViewEmbeddedControl.cs b/Source/ContainerListView/ListViewEmbeddedControl.cs new file mode 100644 index 0000000..8d947da --- /dev/null +++ b/Source/ContainerListView/ListViewEmbeddedControl.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Windows.Forms; + +namespace Nuclex.Windows.Forms { + + /// Stores informations about an embedded control + public class ListViewEmbeddedControl { + + /// Initializes a new embedded control holder + /// Control being embedded in a list view + /// List row at which the control will be embedded + /// List column at which the control will be embedded + public ListViewEmbeddedControl(Control control, int row, int column) { + this.control = control; + this.row = row; + this.column = column; + } + + /// Control that has been embedded in a ListView + public Control Control { + get { return this.control; } + } + + /// Row in the ListView the control has been embedded in + public int Row { + get { return this.row; } + } + + /// Column in the ListView the control has been embedded in + public int Column { + get { return this.column; } + } + + /// Embedded control + private Control control; + /// Row where the control is embedded + private int row; + /// Column where the control is embedded + private int column; + } + +} // namespace Nuclex.Windows.Forms diff --git a/Source/ContainerListView/ListViewEmbeddedControlCollection.cs b/Source/ContainerListView/ListViewEmbeddedControlCollection.cs new file mode 100644 index 0000000..cb9e31a --- /dev/null +++ b/Source/ContainerListView/ListViewEmbeddedControlCollection.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; + +namespace Nuclex.Windows.Forms { + + /// Collection of controls embedded in a ListView + public class ListViewEmbeddedControlCollection : Collection { + + #region class ListViewEmbeddedControlEventArgs + + /// Arguments class for events that need to pass a control + public class ListViewEmbeddedControlEventArgs : EventArgs { + + /// Initializes a new event arguments supplier + /// Control to be supplied to the event handler + public ListViewEmbeddedControlEventArgs(ListViewEmbeddedControl embeddedControl) { + this.embeddedControl = embeddedControl; + } + + /// Obtains the control the event arguments are carrying + public ListViewEmbeddedControl EmbeddedControl { + get { return this.embeddedControl; } + } + + /// Control that's passed to the event handler + private ListViewEmbeddedControl embeddedControl; + + } + + #endregion // class ListViewEmbeddedControlEventArgs + + /// Raised when a control has been added to the collection + public event EventHandler EmbeddedControlAdded; + /// Raised when a control is removed from the collection + public event EventHandler EmbeddedControlRemoved; + + /// Removes all elements from the ListViewEmbeddedControlCollection + protected override void ClearItems() { + base.ClearItems(); + } + + /// + /// Inserts an element into the ListViewEmbeddedControlCollection at the specified index + /// + /// + /// The object to insert. The value can be null for reference types + /// + /// The zero-based index at which item should be inserted + protected override void InsertItem(int index, ListViewEmbeddedControl item) { + base.InsertItem(index, item); + } + + /// + /// Removes the element at the specified index of the ListViewEmbeddedControlCollection + /// + /// The zero-based index of the element to remove + protected override void RemoveItem(int index) { + base.RemoveItem(index); + } + + /// Replaces the element at the specified index + /// + /// The new value for the element at the specified index. The value can be null + /// for reference types + /// + /// The zero-based index of the element to replace + protected override void SetItem(int index, ListViewEmbeddedControl item) { + base.SetItem(index, item); + } + + /// Fires the EmbeddedControlAdded event + /// + /// Embedded control that has been added to the collection + /// + protected virtual void OnEmbeddedControlAdded(ListViewEmbeddedControl embeddedControl) { + if(EmbeddedControlAdded != null) + EmbeddedControlAdded(this, new ListViewEmbeddedControlEventArgs(embeddedControl)); + } + + /// Fires the EmbeddedControlRemoved event + /// + /// Embedded control that has been removed from the collection + /// + protected virtual void OnEmbeddedControlRemoved(ListViewEmbeddedControl embeddedControl) { + if(EmbeddedControlRemoved != null) + EmbeddedControlRemoved(this, new ListViewEmbeddedControlEventArgs(embeddedControl)); + } + + } + +} // namespace Nuclex.Windows.Forms diff --git a/Source/EmbeddedControlCollection.cs b/Source/EmbeddedControlCollection.cs new file mode 100644 index 0000000..b05e2e5 --- /dev/null +++ b/Source/EmbeddedControlCollection.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.Windows.Forms; + +namespace Nuclex.Windows.Forms { + + /// Collection of controls embedded in another control + public class EmbeddedControlCollection : Control.ControlCollection { + + #region class ControlEventArgs + + /// Arguments class for events that need to pass a control + public class ControlEventArgs : EventArgs { + + /// Initializes a new event arguments provider + /// Control to be supplied to the event handler + public ControlEventArgs(Control control) { + this.control = control; + } + + /// Obtains the control the event arguments are carrying + public Control Control { get { return this.control; } } + + /// Control that's passed to the event handler + private Control control; + + } + + #endregion // class ControlEventArgs + + /// Raised when a control has been added to the collection + public event EventHandler ControlAdded; + /// Raised when a control is removed from the collection + public event EventHandler ControlRemoved; + + /// Initializes a new instance of the EmbeddedControlCollection class + /// + /// A System.Windows.Forms.Control representing the control + /// that owns the control collection + /// + EmbeddedControlCollection(Control owner) : base(owner) { } + + /// Adds the specified control to the control collection + /// + /// The System.Windows.Forms.Control to add to the control collection + /// + public override void Add(Control value) { + base.Add(value); + + OnControlAdded(value); + } + + /// Removes the specified control from the control collection + /// + /// The System.Windows.Forms.Control to remove from the EmbeddedControlCollection + /// + public override void Remove(Control value) { + base.Remove(value); + + OnControlRemoved(value); + } + + /* + /// Adds an array of control objects to the collection + /// + /// An array of System.Windows.Forms.Control objects to add to the collection + /// + public override void AddRange(Control[] controls) { + base.AddRange(controls); + } + + /// Removes all controls from the collection + public override void Clear() { + base.Clear(); + } + + /// Removes the child control with the specified key + /// The name of the child control to remove + public override void RemoveByKey(string key) { + base.RemoveByKey(key); + } + */ + + /// + /// Called when a control has been added to the collection, + /// fires the ControlAdded event + /// + /// Control that has been added to the collection + protected virtual void OnControlAdded(Control control) { + if(ControlAdded != null) + ControlAdded(this, new ControlEventArgs(control)); + } + + /// + /// Called when a control has been removed to the collection, + /// fires the ControlRemoved event + /// + /// Control that has been removed from the collection + protected virtual void OnControlRemoved(Control control) { + if(ControlRemoved != null) + ControlRemoved(this, new ControlEventArgs(control)); + } + + } + +} // namespace Nuclex.Windows.Forms