/*
 * FastDataListView - A data bindable listview that has the speed of a virtual list
 *
 * Author: Phillip Piper
 * Date: 22/09/2010 8:11 AM
 *
 * Change log:
 * 2015-02-02   JPP  - Made Unfreezing more efficient by removing a redundant BuildList() call
 * v2.6
 * 2010-09-22   JPP  - Initial version
 *
 * Copyright (C) 2006-2015 Phillip Piper
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * If you wish to use this code in a closed source application, please contact phillip.piper@gmail.com.
 */

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.ComponentModel;
using System.Windows.Forms;
using System.Drawing.Design;

namespace BrightIdeasSoftware
{
    /// <summary>
    /// A FastDataListView virtualizes the display of data from a DataSource. It operates on
    /// DataSets and DataTables in the same way as a DataListView, but does so much more efficiently.
    /// </summary>
    /// <remarks>
    /// <para>
    /// A FastDataListView still has to load all its data from the DataSource. If you have SQL statement
    /// that returns 1 million rows, all 1 million rows will still need to read from the database.
    /// However, once the rows are loaded, the FastDataListView will only build rows as they are displayed.
    /// </para>
    /// </remarks>
    public class FastDataListView : FastObjectListView
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="disposing"></param>
        protected override void Dispose(bool disposing)
        {
            if (this.adapter != null) {
                this.adapter.Dispose();
                this.adapter = null;
            }

            base.Dispose(disposing);
        }

        #region Public Properties

        /// <summary>
        /// 获取或设置在设置DataSource时是否自动生成列以显示列。
        /// </summary>
        /// <remarks>必须在设置DataSource之前设置此设置。之后就没有效果了。</remarks>
        [Category("数据"),
         Description("获取或设置在设置DataSource时是否自动生成列以显示列"),
         DefaultValue(true)]
        public bool AutoGenerateColumns
        {
            get { return this.Adapter.AutoGenerateColumns; }
            set { this.Adapter.AutoGenerateColumns = value; }
        }

        /// <summary>
        /// 获取或设置将在此列表视图中显示的VirtualListDataSource。
        /// </summary>
        /// <remarks>VirtualListDataSource应实现 <see cref="IList"/>, <see cref="IBindingList"/>,
        /// 或 <see cref="IListSource"/>. 以下是一些常见的对象类型
        /// <list type="unordered">
        /// <item><description><see cref="DataView"/></description></item>
        /// <item><description><see cref="DataTable"/></description></item>
        /// <item><description><see cref="DataSet"/></description></item>
        /// <item><description><see cref="DataViewManager"/></description></item>
        /// <item><description><see cref="BindingSource"/></description></item>
        /// </list>
        /// <para>绑定到列表容器时 (即，实现 <see cref="IListSource"/> 接口, 比如 <see cref="DataSet"/>)
        /// 您还必须实现 <see cref="DataMember"/> 属性，以便标识要显示的特定列表。您也可以设置 <see cref="DataMember"/> 属性，
        /// 即使当VirtualListDataSource引用列表时也是如此, 因为 <see cref="DataMember"/> 还可以用于导航列表之间的关系.</para>
        ///</remarks>
        [Category("数据"),
        TypeConverter("System.Windows.Forms.Design.DataSourceConverter, System.Design")]
        public virtual Object DataSource {
            get { return this.Adapter.DataSource; }
            set { this.Adapter.DataSource = value; }
        }

        /// <summary>
        /// Gets or sets the name of the list or table in the data source for which the DataListView is displaying data.
        /// </summary>
        /// <remarks>If the data source is not a DataSet or DataViewManager, this property has no effect</remarks>
        [Category("数据"),
         Editor("System.Windows.Forms.Design.DataMemberListEditor, System.Design", typeof(UITypeEditor)),
         DefaultValue("")]
        public virtual string DataMember {
            get { return this.Adapter.DataMember; }
            set { this.Adapter.DataMember = value; }
        }

        #endregion

        #region Implementation properties

        /// <summary>
        /// Gets or sets the DataSourceAdaptor that does the bulk of the work needed
        /// for data binding.
        /// </summary>
        protected DataSourceAdapter Adapter {
            get {
                if (adapter == null)
                    adapter = this.CreateDataSourceAdapter();
                return adapter;
            }
            set { adapter = value; }
        }
        private DataSourceAdapter adapter;

        #endregion

        #region Implementation 

        /// <summary>
        /// Create the DataSourceAdapter that this control will use.
        /// </summary>
        /// <returns>A DataSourceAdapter configured for this list</returns>
        /// <remarks>Subclasses should override this to create their
        /// own specialized adapters</remarks>
        protected virtual DataSourceAdapter CreateDataSourceAdapter() {
            return new DataSourceAdapter(this);
        }

        /// <summary>
        /// Change the Unfreeze behaviour 
        /// </summary>
        protected override void DoUnfreeze()
        {

            // Copied from base method, but we don't need to BuildList() since we know that our
            // data adaptor is going to do that immediately after this method exits.
            this.EndUpdate();
            this.ResizeFreeSpaceFillingColumns();
            // this.BuildList();
        }

        #endregion
    }
}
