Click here to Skip to main content
15,886,518 members
Articles / Programming Languages / C#

Linux Todolist

Rate me:
Please Sign up or sign in to vote.
4.59/5 (15 votes)
28 Jan 2008GPL35 min read 73.9K   2.3K   53  
A simple todolist designed for an Asus Eee Pc
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using System.Drawing.Drawing2D;

namespace uk.org.aspellclark.todolist
{
	/// <summary>
	/// Summary description for TreeList.
	/// </summary>
	public class TreeList : System.Windows.Forms.UserControl
	{
		private System.Windows.Forms.DataGrid _treeGrid;
		private const int __TREE_COLUMN_SIZE__ = 200;
		public TreeListNodeSelected NodeSelectedEvent;

		/// <summary> 
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;

		public class TreeListNode
		{
			private object[] _columns;
			private ArrayList _childs;
			private TreeListNode _parent;
			
			public TreeListNode(int cols)
			{
				_columns = new object[cols];
			}

			public TreeListNode(object[] cols)
			{
				_columns = cols;
			}

			public void AddChild(TreeListNode child)
			{
				if (_childs == null)
					_childs = new ArrayList();

				_childs.Add(child);
			}

			public object[] Columns
			{
				get { return _columns; }
				set { _columns = value; }
			}

			public ArrayList ChildNodes
			{
				get { return _childs; }
				set { _childs = value; }
			}

			public TreeListNode Parent
			{
				get { return _parent; }
				set { _parent = value; }
			}
		}//class()

		private class TreeListColumnStyle : DataGridTextBoxColumn
		{
			private const int __BOX_SIZE__ = 8;
			private const int __BOX_MARGIN__ = 2;
			private int _col;

			public TreeListColumnStyle(int col)
			{
				_col = col;
			}

			protected override void Paint(System.Drawing.Graphics g, Rectangle bounds, CurrencyManager source, int rowNum, Brush backBrush, Brush foreBrush, bool alignToRight)
			{
				if (_col == 0)
				{
					g.FillRectangle(backBrush, bounds);

					DataRow row = ((DataRowView)source.List[rowNum]).Row;
					bounds.X += GetXOffset(row);

					object expanded = row["__IS_EXPANDED__"];
					if (!Convert.IsDBNull(expanded))
					{
						Pen pen = new Pen(foreBrush);
						int x = bounds.Left + __BOX_MARGIN__;
						int y = bounds.Top + __BOX_MARGIN__ * 2;
						g.DrawRectangle(pen, x, y, __BOX_SIZE__, __BOX_SIZE__);
						g.DrawLine(pen, x + __BOX_MARGIN__, y + __BOX_SIZE__ / 2, x + __BOX_SIZE__ - __BOX_MARGIN__, y + __BOX_SIZE__ / 2);
						if (!Convert.ToBoolean(expanded))
							g.DrawLine(pen, x + __BOX_SIZE__ / 2, y + __BOX_MARGIN__, x + __BOX_SIZE__ / 2, y + __BOX_SIZE__ - __BOX_MARGIN__);

						bounds.X += __BOX_SIZE__;
					}

					bounds.X += (__BOX_MARGIN__ * 3);
				}

				base.Paint(g, bounds, source, rowNum, backBrush, foreBrush, alignToRight);
			}

			private int GetXOffset(DataRow row)
			{
				object parent = row["__PARENT_ROW__"];
				if (Convert.IsDBNull(parent))
					return 0;
				else
					return __BOX_SIZE__ * 2 + GetXOffset((DataRow)parent);
			}
		
			protected override void Edit(System.Windows.Forms.CurrencyManager source, int rowNum, System.Drawing.Rectangle bounds, bool readOnly, string instantText, bool cellIsVisible) 
			{ 
				// don't call the baseclass so no editing done...
				//	base.Edit(source, rowNum, bounds, readOnly, instantText, cellIsVisible); 
			}
		}//class()

		public TreeList()
		{
			// This call is required by the Windows.Forms Form Designer.
			InitializeComponent();
		}

		/// <summary> 
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}

				Clear();
			}
			base.Dispose( disposing );
		}

		#region Component Designer generated code
		/// <summary> 
		/// Required method for Designer support - do not modify 
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this._treeGrid = new System.Windows.Forms.DataGrid();
			((System.ComponentModel.ISupportInitialize)(this._treeGrid)).BeginInit();
			this.SuspendLayout();
			// 
			// _treeGrid
			// 
			this._treeGrid.CaptionVisible = false;
			this._treeGrid.DataMember = "";
			this._treeGrid.Dock = System.Windows.Forms.DockStyle.Fill;
			this._treeGrid.GridLineStyle = System.Windows.Forms.DataGridLineStyle.None;
			this._treeGrid.HeaderForeColor = System.Drawing.SystemColors.ControlText;
			this._treeGrid.Location = new System.Drawing.Point(0, 0);
			this._treeGrid.Name = "_treeGrid";
			this._treeGrid.ReadOnly = true;
			this._treeGrid.Size = new System.Drawing.Size(320, 256);
			this._treeGrid.TabIndex = 0;
			this._treeGrid.TabStop = false;
			this._treeGrid.MouseDown += new System.Windows.Forms.MouseEventHandler(this.OnMouseDown);
			this._treeGrid.MouseUp += new System.Windows.Forms.MouseEventHandler(this.OnMouseUp);
			// 
			// TreeList
			// 
			this.Controls.Add(this._treeGrid);
			this.Name = "TreeList";
			this.Size = new System.Drawing.Size(320, 256);
			((System.ComponentModel.ISupportInitialize)(this._treeGrid)).EndInit();
			this.ResumeLayout(false);

		}
		#endregion

		private void SetColumnStyles()
		{
			CurrencyManager cm = (CurrencyManager)this.BindingContext[_treeGrid.DataSource];
			((DataView)cm.List).AllowNew = false;
			((DataView)cm.List).AllowEdit = false;
			((DataView)cm.List).AllowDelete = false;
			_treeGrid.ReadOnly = false;
		
			DataTable dt = (DataTable)_treeGrid.DataSource;
			DataGridTableStyle styles = new DataGridTableStyle(cm);
			styles.GridColumnStyles.Clear();
			styles.ReadOnly = true;
			styles.AllowSorting = false;
			styles.RowHeadersVisible = false;
			styles.GridLineStyle = DataGridLineStyle.None;

			for (int i = 0; i < dt.Columns.Count - 3; i++)
			{
				TreeListColumnStyle style = new TreeListColumnStyle(i);
				style.ReadOnly = true;
				style.Width = __TREE_COLUMN_SIZE__;
				style.MappingName = dt.Columns[i].ColumnName;
				style.HeaderText = dt.Columns[i].ColumnName;
				style.TextBox.Visible = false;
				style.NullText = "";
				styles.GridColumnStyles.Add(style);
			}

			DataGridTextBoxColumn hstyle1 = new DataGridTextBoxColumn();
			hstyle1.Width = 0;
			styles.GridColumnStyles.Add(hstyle1);

			DataGridBoolColumn hstyle2 = new DataGridBoolColumn();
			hstyle2.Width = 0;
			styles.GridColumnStyles.Add(hstyle2);

			DataGridBoolColumn hstyle3 = new DataGridBoolColumn();
			hstyle3.Width = 0;
			styles.GridColumnStyles.Add(hstyle3);

			_treeGrid.TableStyles.Add(styles);
		}

		public void SetColumns(string[] names)
		{
			_treeGrid.BeginInit();

			DataTable dt = new DataTable();
			for (int i = 0; i < names.Length; i++)
				dt.Columns.Add(names[i]);

			//add some hidden columns
			DataColumn hcol1 = new DataColumn("__PARENT_ROW__", typeof(object));
			hcol1.ColumnMapping = MappingType.Hidden;
			dt.Columns.Add(hcol1);
			DataColumn hcol2 = new DataColumn("__IS_EXPANDED__", typeof(bool));
			hcol2.ColumnMapping = MappingType.Hidden;
			dt.Columns.Add(hcol2);
			DataColumn hcol3 = new DataColumn("__IS_VISIBLE__", typeof(bool));
			hcol3.ColumnMapping = MappingType.Hidden;
			dt.Columns.Add(hcol3);

			_treeGrid.DataSource = dt;

			SetColumnStyles();

			_treeGrid.EndInit();
		}

		static private void AddNode(DataTable dt, TreeListNode node, DataRow parentRow)
		{
			if (node.Columns.Length != dt.Columns.Count - 3)
				throw new Exception("Node values don't match expected columns.");

			DataRow row = dt.NewRow();
			for (int i = 0; i < node.Columns.Length; i++)
				row[i] = node.Columns[i];
				
			if (parentRow != null)
			{
				row["__PARENT_ROW__"] = parentRow;
				node.Parent = (TreeList.TreeListNode)dt.ExtendedProperties[parentRow];
			}

			if (node.ChildNodes != null)
				row["__IS_EXPANDED__"] = true;

			row["__IS_VISIBLE__"] = true;

			dt.Rows.Add(row);

			dt.ExtendedProperties.Add(row, node);

			if (node.ChildNodes != null)
			{
				foreach (TreeListNode child in node.ChildNodes)
					AddNode(dt, child, row);
			}
		}

		private void UpdateChildrenVisibility(DataTable dt, int startIdx, DataRow parentRow, bool visible)
		{
			for (int i = startIdx; i < dt.Rows.Count; i++)
			{
				DataRow row = dt.Rows[i];
				object parent = row["__PARENT_ROW__"];
				if (Convert.IsDBNull(parent))
					continue;

				if (!parentRow.Equals(parent))
					continue;
					
				row["__IS_VISIBLE__"] = visible;
				if (!Convert.IsDBNull(row["__IS_EXPANDED__"]) && Convert.ToBoolean(row["__IS_EXPANDED__"]))
					UpdateChildrenVisibility(dt, i + 1, row, visible);
			}
		}

		private void OnMouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
		{
			if (e.Button != MouseButtons.Left)
				return;

			DataGrid.HitTestInfo hi = _treeGrid.HitTest(e.X, e.Y);
			if (hi.Type != DataGrid.HitTestType.Cell)
				return;

			CurrencyManager source = (CurrencyManager)_treeGrid.BindingContext[_treeGrid.DataSource];
			if (hi.Row >= 0 && hi.Row < source.List.Count)
			{
				_treeGrid.CurrentRowIndex = hi.Row;
				DataRow parentRow = ((DataRowView)source.List[hi.Row]).Row;

				object expanded = parentRow["__IS_EXPANDED__"];
				if (Convert.IsDBNull(expanded))
					return;

				//this.dataGrid1.TableStyles[0].GridColumnStyles[0];
				bool visibility = Convert.ToBoolean(expanded);
				parentRow["__IS_EXPANDED__"] = !visibility;
				
				UpdateChildrenVisibility((DataTable)_treeGrid.DataSource, hi.Row + 1, parentRow, !visibility);
			}
		}

		private void OnMouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
		{
			_treeGrid.Select(_treeGrid.CurrentRowIndex);
			if (NodeSelectedEvent != null)
				NodeSelectedEvent(this.SelectedNode);
		}

		public void AddNode(TreeListNode node)
		{
			_treeGrid.SuspendLayout();
			_treeGrid.BeginInit();

			DataTable dt = (DataTable)_treeGrid.DataSource;
			AddNode(dt, node, null);

			_treeGrid.EndInit();

			dt.DefaultView.RowFilter = "__IS_VISIBLE__=true";
			_treeGrid.Select(0);
			_treeGrid.ResumeLayout(false);
		}

		public void Clear()
		{
			if (_treeGrid.DataSource != null)
			{
				((DataTable)_treeGrid.DataSource).Dispose();
				_treeGrid.DataSource = null;
				_treeGrid.TableStyles.Clear();
			}
		}

		public TreeList.TreeListNode SelectedNode
		{
			get
			{
				CurrencyManager cm = (CurrencyManager)_treeGrid.BindingContext[_treeGrid.DataSource];
				DataRowView rv = (DataRowView)cm.List[_treeGrid.CurrentRowIndex];
				return (TreeList.TreeListNode)((DataTable)_treeGrid.DataSource).ExtendedProperties[rv.Row];
			}
		}
	}

	public delegate void TreeListNodeSelected(TreeList.TreeListNode node);

}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Software Developer (Senior) Airbus Defense and Space
United Kingdom United Kingdom
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions