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 Softelvdm.SftTreeNET;
using Softelvdm.Controls;

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

        private void Form1_Load(object sender, EventArgs e) {
            // This sample demonstrates drag & drop using one textbox control.
            // To prepare for this sample, create a new project with a blank form and add
            // a SftTree/NET control named sftTree1.
            // In addition, a textbox named textbox1 is needed. Try dragging data from the
            // tree control to the text box.
            // It is also possible to drag files from Windows Explorer to the tree control. 
            // No files are moved/copied, merely their names are added to the tree control.
            sftTree1.Initializing = true;
            sftTree1.Columns.Count = 1;
            for (int i = 0 ; i < 10 ; ++i) {
                ItemClass item = sftTree1.ItemCollection.Add("Item " + i.ToString());
                for (int ic = 0 ; ic < 10 ; ++ic) {
                    ItemClass child = item.Add("Child item " + ic.ToString());
                }
            }
            sftTree1.ItemCollection.Collapse(CollapseStyleEnum.All);
            sftTree1.Columns.MakeOptimal(0, false);
            sftTree1.RecalcHorizontalExtent();

            // We need to set up the tree control as a drop target
            sftTree1.AllowDrop = true;
            sftTree1.AutoExpandDragDrop = true;
            sftTree1.AutoExpandArea = AutoExpandAreaEnum.AllColumns;
            sftTree1.Initializing = false;

            // We also need to set up the text box so we can drop data
            textBox1.AllowDrop = true;
        }

        private void sftTree1_DragDetected(object sender, DragDetectedEventArgs e) {
            Debug.Print("We're starting to drag something");
            DumpValues(e);

            // based on what we are dragging, make up a string
            string s = "";
            s = e.Area.ToString() + " in ";
            s += e.Item.UsageLocation.ToString() + ": ";
            if (e.Cell != null) {
                if (e.Cell.Text == "") s += "(empty cell) ";
                else s += e.Cell.Text + " ";
            } else if (e.RowHeader != null) {
                if (e.RowHeader.Text == "") s += "(empty row header) ";
                else s += e.RowHeader.Text + " ";
            } else if (e.Item != null) {
                s += " an item ";
            }
            e.Handled = true;
            sftTree1.DoDragDrop(s, DragDropEffects.Copy);
        }

        // The textbox just copies data in this example
        private void textBox1_DragEnter(object sender, DragEventArgs e) {
            Debug.Write("*** textBox1 DragEnter ");
            DumpValues(e);
            if (e.Data.GetDataPresent(DataFormats.UnicodeText))
                e.Effect = DragDropEffects.Copy;
        }
        private void textBox1_DragDrop(object sender, DragEventArgs e) {
            Debug.Write("*** textBox1 DragDrop ");
            DumpValues(e);
            if (e.Data.GetDataPresent(DataFormats.UnicodeText))
                textBox1.Text = (string)e.Data.GetData("System.String");
        }

        // The tree control also just copies the data
        private void sftTree1_DragEnter(object sender, DragEventArgs e) {
            Debug.Write("*** sftTree1 DragEnter ");
            DumpValues(e);
            if (e.Data.GetDataPresent(DataFormats.UnicodeText))
                e.Effect = DragDropEffects.Copy;
            else if (e.Data.GetDataPresent(DataFormats.FileDrop))
                e.Effect = DragDropEffects.Copy;
            else
                e.Effect = DragDropEffects.None;
        }

        private void sftTree1_DragOver(object sender, DragEventArgs e) {
            // in this example, if we don't have a valid drop target, 
            // we STILL allow drops
            if (sftTree1.DropTarget == null)
                e.Effect = DragDropEffects.Copy;
        }

        private void sftTree1_DragDrop(object sender, DragEventArgs e) {
            Debug.Write("*** sftTree1 DragDrop ");
            DumpValues(e);

            ItemClass item = sftTree1.DropTarget as ItemClass;

            string s = "";
            Array a = null;
            if (e.Data.GetDataPresent(DataFormats.UnicodeText))
                s = (string)e.Data.GetData("System.String");
            else if (e.Data.GetDataPresent(DataFormats.FileDrop))
                a = (Array)e.Data.GetData(DataFormats.FileDrop);
            else
                return;

            ItemClass newItem = null;

            sftTree1.Initializing = true;
            if (s.Length > 0) {
                if (item != null) {
                    newItem = item.Add(s);
                    item.Expand(ExpandStyleEnum.DirectOnly);
                } else
                    newItem = sftTree1.ItemCollection.Add(s);
            } else {
                foreach (object o in a) {
                    s = (string) o;
                    if (item != null) {
                        newItem = item.Add(s);
                        item.Expand(ExpandStyleEnum.DirectOnly);
                    } else
                        newItem = sftTree1.ItemCollection.Add(s);
                }
            }
            sftTree1.Columns.MakeOptimal(0, false);
            sftTree1.RecalcHorizontalExtent();
            newItem.ScrollIntoView();
            sftTree1.FocusObject = newItem;
            newItem.Selected = true;
            sftTree1.Initializing = false;
        }

        // 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("");
        }
    }
}