/// /// Copyright © 2003-2008 JetBrains s.r.o. /// You may distribute under the terms of the GNU General Public License, as published by the Free Software Foundation, version 2 (see License.txt in the repository root folder). /// using System.IO; using System.Text; using System.Windows.Forms; using JetBrains.Omea.Base; using JetBrains.Omea.Containers; using JetBrains.Omea.OpenAPI; namespace JetBrains.Omea.RSSPlugin { /// /// Drag and drop handler for RSS items. /// internal class RSSDragDropHandler: IResourceDragDropHandler { private const string CLIPBOARD_FORMAT_URL = "UniformResourceLocator"; private const string CLIPBOARD_FORMAT_URL_W = "UniformResourceLocatorW"; public void AddResourceDragData( IResourceList dragResources, IDataObject dataObject ) { if ( dragResources.Count == 1 ) { IResource dragResource = dragResources [0]; if ( dragResource.Type == "RSSFeed" && dragResource.HasProp( Props.URL ) ) { dataObject.SetData( DataFormats.Text, dragResource.GetStringProp( Props.URL ) ); } } } public DragDropEffects DragOver( IResource targetResource, IDataObject data, DragDropEffects allowedEffect, int keyState ) { if( data.GetDataPresent( typeof(IResourceList) ) ) { // The resources we're dragging IResourceList dragResources = (IResourceList)data.GetData( typeof(IResourceList) ); // Check the droptarget, it must be either a folder or a tree root if(!((targetResource.Type == "RSSFeedGroup") || (targetResource == Core.ResourceTreeManager.GetRootForType( "RSSFeed" )))) return DragDropEffects.None; // Collect all the direct and indirect parents of the droptarget; then we'll check to avoid dropping parent on its children IntArrayList parentList = new IntArrayList(); IResource parent = targetResource; while( parent != null ) { parentList.Add( parent.Id ); parent = parent.GetLinkProp( Core.Props.Parent ); } bool bAllDroppable = true; // Feeds or groups are being dragged foreach( IResource res in dragResources ) { // Dropping parent over its child? if( parentList.IndexOf( res.Id ) >= 0 ) return DragDropEffects.None; // Constraint the resource types of the resources being dropped bAllDroppable = bAllDroppable && ( (res.Type == "RSSFeed") || (res.Type == "RSSFeedGroup") ); } return bAllDroppable ? DragDropEffects.Move : DragDropEffects.None; } else if ( data.GetDataPresent( CLIPBOARD_FORMAT_URL ) || data.GetDataPresent( CLIPBOARD_FORMAT_URL_W ) ) { return DragDropEffects.Copy; } return DragDropEffects.None; } public void Drop( IResource targetResource, IDataObject data, DragDropEffects allowedEffect, int keyState ) { if ( targetResource == null ) return; if ( data.GetDataPresent( typeof(IResourceList) ) ) { IResourceList droppedResources = (IResourceList) data.GetData( typeof(IResourceList) ); foreach( IResource res in droppedResources ) { // Drop only feeds and newsgroups, and don't drop on self if ( (res.Id != targetResource.Id) && ( (res.Type == "RSSFeed") || (res.Type == "RSSFeedGroup") ) ) { Core.ResourceAP.QueueJob( JobPriority.Immediate, new SetParentDelegate( SetFeedParent ), res, targetResource ); } } } else if ( data.GetDataPresent( CLIPBOARD_FORMAT_URL_W ) ) { ProcessUrlDrop( targetResource, data, CLIPBOARD_FORMAT_URL_W, Encoding.Unicode ); } else if ( data.GetDataPresent( CLIPBOARD_FORMAT_URL ) ) { ProcessUrlDrop( targetResource, data, CLIPBOARD_FORMAT_URL, Encoding.Default ); } } private void SetFeedParent( IResource res, IResource parent ) { res.SetProp( Core.Props.Parent, parent ); Core.WorkspaceManager.AddToActiveWorkspace( res ); Core.WorkspaceManager.CleanWorkspaceLinks( res ); } private delegate void SetParentDelegate( IResource res, IResource parent ); private void ProcessUrlDrop( IResource targetResource, IDataObject data, string format, Encoding encoding ) { Stream dataStream = (Stream) data.GetData( format ); if ( dataStream != null ) { string url = Utils.StreamToString( dataStream, encoding ); RSSPlugin.GetInstance().ShowAddFeedWizard( url, targetResource ); } } } }