view Chronosv2/source/DragAndDrop/DropHelper.cs @ 12:6a0449185449

SCC changed from TFS to HG
author stevenh7776 stevenhollidge@hotmail.com
date Tue, 21 Feb 2012 17:47:35 +0700
parents 443821e55f06
children
line wrap: on
line source

using System;
using System.Collections;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using Chronos.Presentation.Core.VirtualDesktops;
using Chronos.Presentation.Core.Widgets;
using Chronos.Presentation.ViewModel;
using Chronos.Presentation.Windows.Controls;
using nRoute.Services;
using nRoute.SiteMaps;

namespace Chronos.Presentation.DragAndDrop
{
    public sealed class DropHelper
    {
        #region · Consts ·

        const string UrlDataFormat = "text/x-moz-url";

        #endregion

        #region · Fields ·

        private UIElement       dropTarget = null;
        private string[]        datatypes  = { typeof(UIElement).ToString(), "Text" };        
        private DragDropEffects allowedEffects;

        #endregion

        #region · Properties ·

        public string[] AllowedDataTypes
        {
            get { return this.datatypes; }
            set
            {
                this.datatypes = value;

                for (int x = 0; x < this.datatypes.Length; x++)
                {
                    this.datatypes[x] = this.datatypes[x].ToLower();
                }
            }
        }

        public DragDropEffects AllowedEffects
        {
            get { return this.allowedEffects; }
            set { this.allowedEffects = value; }
        }

        #endregion

        #region · Constructors ·

        public DropHelper(UIElement wrapper)
        {
            this.dropTarget = wrapper;

            this.dropTarget.AllowDrop  = true;
            this.dropTarget.DragOver   += new DragEventHandler(DropTarget_DragOver);
            this.dropTarget.Drop       += new DragEventHandler(DropTarget_Drop);
        }

        #endregion

        #region · DropTarget Event Handlers ·

        private void DropTarget_Drop(object sender, DragEventArgs e)
        {
            IDataObject     data            = e.Data;
            DragDataWrapper dw              = null;
            bool            isDataOperation = false;
           
            Debug.Assert(data != null);

            if (data.GetDataPresent(typeof(DragDataWrapper).ToString()))
            {
                dw = data.GetData(typeof(DragDataWrapper).ToString()) as DragDataWrapper;

                Debug.Assert(dw.Shim != null);

                if ((dw.Shim.SupportedActions & DragDropProviderActions.Data) != 0)
                {
                    isDataOperation = true;
                }
            }

            // Try a BRUTE FORCE APPROACH on UIElement just to show how it could be done
            // BUT NOT ENDORSING IT!!! 
            if (!isDataOperation)
            {
                if (this.dropTarget is Canvas)
                {
                    if (e.Data.GetDataPresent(DataFormats.FileDrop))
                    {
                        this.DropFileLink(e);
                    }
                    else if (e.Data.GetDataPresent(UrlDataFormat))
                    {
                        this.DropUrl(e);
                    }
                }
            }
            else
            {
                Debug.Assert(dw != null);
                Debug.Assert(dw.Shim != null);

                object rawdata = dw.Data;

                if (this.dropTarget is ItemsControl)
                {
                    this.DropItemsControlHandler(e, rawdata);
                }
                else if (dropTarget is Canvas)
                {
                    if (rawdata is IWidget)
                    {
                        this.DropCanvasWidget(e, rawdata as IWidget);
                    }
                    else if (rawdata is SiteMapNode)
                    {
                        this.DropCanvasInternalLink(e, rawdata as NavigationNode);
                    }
                }
            }

            e.Handled = true;
        }
      
        private void DropTarget_DragOver(object sender, DragEventArgs e)
        {
            string[]    types = e.Data.GetFormats();
            bool        match = false;

            if (datatypes == null || types == null)
            {
                //TODO: ??? Should we set for DragDropEffects.None? 
                return;
            }

            foreach (string s in types)
            {
                foreach (string type in datatypes)
                {
                    match = (s.ToLower() == type);

                    if (match)
                    {
                        break;
                    }
                }
            
                if (match)
                {
                    break;
                }
            }

            if (match)
            {
                e.Effects = AllowedEffects;
                e.Handled = true;
            }
        }

        #endregion

        #region · Drop Handlers Methods ·

        private void DropCanvasWidget(DragEventArgs e, IWidget dropObject)
        {
            ServiceLocator.GetService<IVirtualDesktopManager>()
                          .Show
            (
                dropObject.CreateView() as WidgetElement, 
                e.GetPosition(this.dropTarget)
            );
        }

        private void DropItemsControlHandler(DragEventArgs e, object rawdata)
        {
            ItemsControl    ic      = this.dropTarget as ItemsControl;
            IList           list    = ic.ItemsSource as IList;

            if (list == null)
            {
                list = ic.Items as System.Collections.IList;
            }

            if (list != null)
            {
                if (!list.Contains(rawdata))
                {
                    // Here we do not check for Move | Copy ... because this is a DATA operation .. No parent relationshop at all ... 
                    list.Add(rawdata);
                }
                else
                {
                    // nothing was done ... 
                    e.Effects = DragDropEffects.None;
                }
            }
            else
            {
                e.Effects = DragDropEffects.None;
            }
        }

        private void DropFileLink(DragEventArgs e)
        {
            // External link drop
            Point       position    = e.GetPosition(this.dropTarget);
            string[]    filenames   = e.Data.GetData(DataFormats.FileDrop, true) as string[];

            e.Effects = DragDropEffects.Link;

            foreach (string filename in filenames)
            {
                ServiceLocator.GetService<IVirtualDesktopManager>()
                              .CreateShortcut<ExternalShortcutViewModel>
                (
                    Path.GetFileNameWithoutExtension(filename), filename, position
                );
            }
        }

        private void DropUrl(DragEventArgs e)
        {
            // External link drop
            Point   position    = e.GetPosition(this.dropTarget);
            String  data        = null;

            using (MemoryStream stream = e.Data.GetData(UrlDataFormat, true) as MemoryStream)
            {
                using (StreamReader reader = new StreamReader(stream, Encoding.Unicode))
                {
                    data = reader.ReadToEnd().Replace("\0", "");
                }
            }

            if (!String.IsNullOrEmpty(data))
            {
                string[] elements = data.Split('\n');

                e.Effects = DragDropEffects.Link;

                if (!String.IsNullOrWhiteSpace(elements[0]) &&
                    !String.IsNullOrWhiteSpace(elements[1]))
                {
                    ServiceLocator.GetService<IVirtualDesktopManager>()
                                  .CreateShortcut<ExternalShortcutViewModel>
                    (
                        elements[1], 
                        elements[0], 
                        position
                    );
                }
            }
        }

        private void DropCanvasInternalLink(DragEventArgs e, NavigationNode siteMapNode)
        {
            Point position = e.GetPosition(this.dropTarget);

            ServiceLocator.GetService<IVirtualDesktopManager>()
                          .CreateShortcut<InternalShortcutViewModel>
            (
                siteMapNode.Title, 
                siteMapNode.Url, 
                position
            );
        }
        
        #endregion

        #region · Private Methods ·

        private bool Unparent(DragDataWrapper dw, UIElement uie)
        {
            bool success = false;

            if (dw != null)
            {
                if (dw.AllowChildrenRemove)
                {
                    dw.Shim.UnParent();
                }
            }

            if (!success) // BRUTE FORCE 
            {
                if (uie is FrameworkElement)
                {
                    FrameworkElement fe = uie as FrameworkElement;

                    if (fe.Parent != null)
                    {
                        if (fe.Parent is Panel)
                        {
                            try
                            {
                                ((Panel)(fe.Parent)).Children.Remove(uie);
                                success = true;
                            }
                            catch (Exception)
                            {
#if DEBUG
                                System.Diagnostics.Debug.Assert(false);
#endif
                            }
                        }
                    }
                    else if (fe.Parent is ContentControl)
                    {
                        ContentControl cc = fe.Parent as ContentControl;

                        cc.Content  = null;
                        success     = true;
                    }
                }
            }

            return success;
        }

        #endregion
    }
}