using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Reflection;
using System.Collections;

using Softelvdm.SftTreeNET;
using Softelvdm.Controls;

namespace WindowsApplication1 {
    public partial class PartsSample3 : Form {
        public PartsSample3() {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e) {
            // This sample demonstrates how sorting indicators could be used in column headers.
            // To prepare for this sample, create a new project with a blank form and add
            // a SftTree/NET control named sftTree1.
            // In addition, adjust the following FromFile method to use a (small) bitmap
            // that is located on your system.
            Image img = Bitmap.FromFile("..\\..\\test.gif");

            // Most of this initialization code could be eliminated by designing the control.
            sftTree1.Initializing = true;
            sftTree1.Columns.Count = 4;
            for (int c = 0 ; c < sftTree1.Columns.Count ; ++c) {
                CellClass cell = sftTree1.Headers[0, c]; // access each header cell
                cell.Text = "Column " + c.ToString(); // set the title
                if (c == 1)
                    cell.Image = img; // add an image to a random column header
                cell.SortIndicatorPosition = SortIndicatorPositionEnum.Default;
            }
            sftTree1.ItemClick += new SftTree.ItemClickEventHandler(sftTree1_ItemClick);
            sftTree1.ItemDoubleClick += new SftTree.ItemDoubleClickEventHandler(sftTree1_ItemDoubleClick);

            // Add a few items
            ItemClass item = sftTree1.ItemCollection.Add(new string [] { "Text 1", "Data 4", "44", "31" } );
            item.Cells[2].TagObject = (long) 44; // we use the actual number for sorting, not the string
            item.Cells[3].TagObject = (long) 31;
            item = sftTree1.ItemCollection.Add(new string[] { "Text 2", "Data 2", "22", "28" });
            item.Cells[2].TagObject = (long) 22; // we use the actual number for sorting, not the string
            item.Cells[3].TagObject = (long) 28;
            item.Cells[3].Image = img; // add an image to a random cell
            item = sftTree1.ItemCollection.Add(new string[] { "Text 3", "Data 43", "11", "233" });
            item.Cells[2].TagObject = (long) 11; // we use the actual number for sorting, not the string
            item.Cells[3].TagObject = (long) 233;
            item = sftTree1.ItemCollection.Add(new string[] { "Text 4", "Data 34", "144", "551" });
            item.Cells[2].TagObject = (long) 144; // we use the actual number for sorting, not the string
            item.Cells[3].TagObject = (long) 551;

            SetSorted(0); // remember that column 0 is (already) sorted

            sftTree1.Columns.MakeOptimal(0, false);
            sftTree1.RecalcHorizontalExtent();
            sftTree1.Initializing = false;
        }

        private int m_sortedColumn = -1; // remembers the sorted column

        private bool SetSorted(int column)
        {
            bool fAscending = true; // assume new column will be ascending
            if (m_sortedColumn == column && sftTree1.Headers[0, column].SortStatus == SortStatusEnum.Ascending)
                fAscending = false; // the current column is now descending

            // turn off sorting indicator in all column headers
            sftTree1.Headers.SetSortStatus(SortStatusEnum.NotSorted);

           // now set the new sorting indicator
            sftTree1.Headers[0, column].SortStatus = fAscending ? SortStatusEnum.Ascending : SortStatusEnum.Descending;
            m_sortedColumn = column;
            return fAscending;
        }

        private void SortData(ItemClickEventArgs e)
        {
            // sort the column last clicked
            if (e.Usage != UsageLocationEnum.header) // we are not interested if the click wasn't in the header
                return;
            if (e.Area != ItemClickAreaEnum.Cell)
                return;

            bool fAscending = SetSorted(e.Cell.ColumnIndex);

            switch (e.Cell.ColumnIndex) {
            default: // column 0 and 1 are sorted based on the Text property
                if (fAscending)
                    sftTree1.ItemCollection.Sort(new SortAscending(e.Cell.ColumnIndex));
                else
                    sftTree1.ItemCollection.Sort(new SortDescending(e.Cell.ColumnIndex));
                break;
            case 2: case 3: // column 2 and 3 are sorted based on the TagObject property, interpreted as a long
                if (fAscending)
                    sftTree1.ItemCollection.Sort(new SortTagObjectAsLongAscending(e.Cell.ColumnIndex));
                else
                    sftTree1.ItemCollection.Sort(new SortTagObjectAsLongDescending(e.Cell.ColumnIndex));
                break;
            }
        }

        public sealed class SortTagObjectAsLongAscending : IComparer {
            private int m_ColumnIndex;

            public SortTagObjectAsLongAscending(int ColumnIndex) {
                m_ColumnIndex = ColumnIndex;
            }
            public int Compare(object x, object y) {
                ItemClass i1 = (ItemClass)x;
                ItemClass i2 = (ItemClass)y;
                long l1 = (long) i1.Cells[m_ColumnIndex].TagObject;
                long l2 = (long) i2.Cells[m_ColumnIndex].TagObject;
                if (l1 > l2) return 1;
                if (l1 < l2) return -1;
                return 0;
            }
        }
        public sealed class SortTagObjectAsLongDescending : IComparer {
            private int m_ColumnIndex;

            public SortTagObjectAsLongDescending(int ColumnIndex) {
                m_ColumnIndex = ColumnIndex;
            }
            public int Compare(object x, object y) {
                ItemClass i1 = (ItemClass)x;
                ItemClass i2 = (ItemClass)y;
                long l1 = (long)i1.Cells[m_ColumnIndex].TagObject;
                long l2 = (long)i2.Cells[m_ColumnIndex].TagObject;
                if (l1 < l2) return 1;
                if (l1 > l2) return -1;
                return 0;
            }
        }

        // ItemClick event
        private void sftTree1_ItemClick(object sender, ItemClickEventArgs e) {
            Debug.Write("** ItemClick");
            DumpValues(e);

            SortData(e);
        }

        private void sftTree1_ItemDoubleClick(object sender, ItemClickEventArgs e) {
            Debug.Write("** ItemDoubleClick");
            DumpValues(e);

            SortData(e);
        }

        // This is a small helper routine to show all properties and fields of an object
        private void DumpValues(object o) {
            PropertyInfo[] api = o.GetType().GetProperties();
            foreach (PropertyInfo pi in api)
                Debug.Write(" " + pi.Name + " " + pi.GetValue(o, new object[] { }));
            FieldInfo[] afi = o.GetType().GetFields();
            foreach (FieldInfo fi in afi)
                Debug.Write(" " + fi.Name + " " + fi.GetValue(o));
            Debug.WriteLine("");
        }

    }
}