//============================================================================
//DataSourcePointList Class
//Copyright ?2006  John Champion, Jerry Vos
//
//This library is free software; you can redistribute it and/or
//modify it under the terms of the GNU Lesser General Public
//License as published by the Free Software Foundation; either
//version 2.1 of the License, or (at your option) any later version.
//
//This library 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
//Lesser General Public License for more details.
//
//You should have received a copy of the GNU Lesser General Public
//License along with this library; if not, write to the Free Software
//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//=============================================================================
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Reflection;
using System.Windows.Forms;
using System.Data;
namespace DrawGraph
{
	/// 
	/// 
	/// 
	/// 
	/// 
	/// 
	/// John Champion
	///  $Revision: 3.3 $ $Date: 2007/02/18 05:51:53 $ 
	[Serializable]
	public class DataSourcePointList : IPointList
	{
		private BindingSource _bindingSource;
		//private object _dataSource = null;
		private string _xDataMember = null;
		private string _yDataMember = null;
		private string _zDataMember = null;
		private string _tagDataMember = null;
	#region Properties
		/// 
		/// Indexer to access the specified  object by
		/// its ordinal position in the list.
		/// 
		/// The ordinal position (zero-based) of the
		///  object to be accessed.
		/// A  object reference.
		public PointPair this[int index]
		{
			get
			{
				if ( index < 0 || index >= _bindingSource.Count )
					throw new System.ArgumentOutOfRangeException( "Error: Index out of range" );
				object row = _bindingSource[index];
				double x = GetDouble( row, _xDataMember );
				double y = GetDouble( row, _yDataMember );
				double z = GetDouble( row, _zDataMember );
				object tag = GetObject( row, _tagDataMember );
				
				PointPair pt = new PointPair( x, y, z );
				pt.Tag = tag;
				return pt;
			}
		}
		/// 
		/// gets the number of points available in the list
		/// 
		public int Count
		{
			get
			{
				if ( _bindingSource != null )
					return _bindingSource.Count;
				else
					return 0;
			}
		}
		/// 
		/// The  object from which to get the bound data
		/// 
		/// 
		/// Typically, you set the 
		/// property to a reference to your database, table or list object.  The
		///  property would be set
		/// to the name of the datatable within the
		/// ,
		/// if applicable.
		public object BindingSource
		{
			get { return _bindingSource; }
		}
		/// 
		/// The table or list object from which to extract the data values.
		/// 
		/// 
		/// This property is just an alias for
		/// .
		/// 
		public object DataSource
		{
			get { return _bindingSource.DataSource; }
			set { _bindingSource.DataSource = value; }
		}
		/// 
		/// The  name of the property or column from which to obtain the
		/// X data values for the chart.
		/// 
		/// Set this to null leave the X data values set to 
		/// 
		public string XDataMember
		{
			get { return _xDataMember; }
			set { _xDataMember = value; }
		}
		/// 
		/// The  name of the property or column from which to obtain the
		/// Y data values for the chart.
		/// 
		/// Set this to null leave the Y data values set to 
		/// 
		public string YDataMember
		{
			get { return _yDataMember; }
			set { _yDataMember = value; }
		}
		/// 
		/// The  name of the property or column from which to obtain the
		/// Z data values for the chart.
		/// 
		/// Set this to null leave the Z data values set to 
		/// 
		public string ZDataMember
		{
			get { return _zDataMember; }
			set { _zDataMember = value; }
		}
		/// 
		/// The  name of the property or column from which to obtain the
		/// tag values for the chart.
		/// 
		/// Set this to null leave the tag values set to null.  If this references string
		/// data, then the tags may be used as tooltips using the
		///  option.
		/// 
		public string TagDataMember
		{
			get { return _tagDataMember; }
			set { _tagDataMember = value; }
		}
	#endregion
	#region Constructors
		/// 
		/// Default Constructor
		/// 
		public DataSourcePointList()
		{
			_bindingSource = new BindingSource();
			_xDataMember = string.Empty;
			_yDataMember = string.Empty;
			_zDataMember = string.Empty;
			_tagDataMember = string.Empty;
		}
		/// 
		/// Constructor to initialize the DataSourcePointList from an
		/// existing 
		/// 
		public DataSourcePointList( DataSourcePointList rhs ) : this()
		{
			_bindingSource.DataSource = rhs._bindingSource.DataSource;
			if ( rhs._xDataMember != null )
				_xDataMember = (string) rhs._xDataMember.Clone();
			if ( rhs._yDataMember != null )
				_yDataMember = (string)rhs._yDataMember.Clone();
			if ( rhs._zDataMember != null )
				_zDataMember = (string)rhs._zDataMember.Clone();
			if ( rhs._tagDataMember != null )
				_tagDataMember = (string)rhs._tagDataMember.Clone();
		}
		/// 
		/// Implement the  interface in a typesafe manner by just
		/// calling the typed version of 
		/// 
		/// A deep copy of this object
		object ICloneable.Clone()
		{
			return this.Clone();
		}
		/// 
		/// Typesafe, deep-copy clone method.
		/// 
		/// A new, independent copy of this class
		public DataSourcePointList Clone()
		{
			return new DataSourcePointList( this );
		}
	#endregion
	#region Methods
		/// 
		/// Extract a double value from the specified table row or data object with the
		/// specified column name.
		/// 
		/// The data object from which to extract the value
		/// The property name or column name of the value
		/// to be extracted
		private double GetDouble( object row, string dataMember )
		{
			if ( dataMember == null || dataMember == string.Empty )
				return PointPair.Missing;
			PropertyInfo pInfo = row.GetType().GetProperty( dataMember );
			DataRowView drv = row as DataRowView;
			object val = null;
			if ( pInfo != null )
				val = pInfo.GetValue( row, null );
			else if ( drv != null )
				val = drv[dataMember];
			else if ( pInfo == null )
				throw new System.Exception( "Can't find DataMember '" + dataMember + "' in DataSource" );
			//			if ( val == null )
			//				throw new System.Exception( "Can't find DataMember '" + dataMember + "' in DataSource" );
			double x;
			if ( val == null )
				x = PointPair.Missing;
			else if ( val.GetType() == typeof( DateTime ) )
				x = ( (DateTime)val ).ToOADate();
			else
				x = Convert.ToDouble( val );
			return x;
		}
		/// 
		/// Extract an object from the specified table row or data object with the
		/// specified column name.
		/// 
		/// The data object from which to extract the object
		/// The property name or column name of the object
		/// to be extracted
		private object GetObject( object row, string dataMember )
		{
			if ( dataMember == null || dataMember == string.Empty )
				return null;
			PropertyInfo pInfo = row.GetType().GetProperty( dataMember );
			DataRowView drv = row as DataRowView;
			object val = null;
			if ( pInfo != null )
				val = pInfo.GetValue( row, null );
			else if ( drv != null )
				val = drv[dataMember];
			if ( val == null )
				throw new System.Exception( "Can't find DataMember '" + dataMember + "' in DataSource" );
			return val;
		}
	#endregion
	}
}