/// /// 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; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using JetBrains.Omea.OpenAPI; namespace JetBrains.Omea.ResourceTools { #region DragDropLinkAdapter Class — adds default Link functionality to the drag-drop handlers /// /// Wrapper around a drag/drop handler which provides "Add Link" functionality when the /// drop cannot be handled by the base handler. /// public class DragDropLinkAdapter : IResourceDragDropHandler { /// /// The handler being wrapped. /// private IResourceDragDropHandler _baseHandler; /// /// The handler that implements link-by-dnd behavior, which is invoked /// when the refuses to handle the operation. /// protected static ResourceDragDropLinkHandler _linkhandler; /// /// Wraps the handler. /// public DragDropLinkAdapter( IResourceDragDropHandler baseHandler ) { _baseHandler = baseHandler; if( _linkhandler == null ) // Lazy-instantiate _linkhandler = new ResourceDragDropLinkHandler(); } public void AddResourceDragData( IResourceList dragResources, IDataObject dataObject ) { _baseHandler.AddResourceDragData( dragResources, dataObject ); _linkhandler.AddResourceDragData( dragResources, dataObject ); } public DragDropEffects DragOver( IResource targetResource, IDataObject data, DragDropEffects allowedEffect, int keyState ) { // Get the wrapped handler's opinion on the operation DragDropEffects baseEffects = _baseHandler.DragOver( targetResource, data, allowedEffect, keyState ); // If base can handle, let it; otherwise, query the link-adapter return baseEffects != DragDropEffects.None ? baseEffects : _linkhandler.DragOver( targetResource, data, allowedEffect, keyState ); } public void Drop( IResource targetResource, IDataObject data, DragDropEffects allowedEffect, int keyState ) { // If the base handler can handle the dragover, let it do the drop if(_baseHandler.DragOver(targetResource, data, allowedEffect, keyState) != DragDropEffects.None) { _baseHandler.Drop(targetResource, data, allowedEffect, keyState); return; } // Now give the link-handler a try if(_linkhandler.DragOver(targetResource, data, allowedEffect, keyState) != DragDropEffects.None) { _linkhandler.Drop(targetResource, data, allowedEffect, keyState); return; } } } #endregion #region ResourceDragDropLinkHandler Clas — Implements the drag'n'drop handler that establishes a link between two arbitary resources public class ResourceDragDropLinkHandler : IResourceDragDropHandler { #region IResourceDragDropHandler Members public void Drop( IResource targetResource, IDataObject data, DragDropEffects allowedEffect, int keyState ) { if( (data.GetDataPresent( typeof(IResourceList) )) && (targetResource != null) && (!Core.ResourceStore.ResourceTypes[ targetResource.Type ].HasFlag( ResourceTypeFlags.Internal )) ) { IResourceList dropList = (IResourceList)data.GetData( typeof(IResourceList) ); Core.UIManager.ShowAddLinkDialog( dropList, targetResource ); } } public DragDropEffects DragOver( IResource targetResource, IDataObject data, DragDropEffects allowedEffect, int keyState ) { return ((data.GetDataPresent( typeof(IResourceList) )) && (targetResource != null) && (!Core.ResourceStore.ResourceTypes[ targetResource.Type ].HasFlag( ResourceTypeFlags.Internal ))) ? DragDropEffects.Link : DragDropEffects.None; } public void AddResourceDragData( IResourceList dragResources, IDataObject dataObject ) { // This handler has nothing to add return; } #endregion } #endregion #region ResourceDragDropCompositeHandler Class — Implements a drag-drop handler that encapsulates a number of other handlers public class ResourceDragDropCompositeHandler : IResourceDragDropHandler { #region Data /// /// A list of handlers this composite invokes. /// protected ArrayList _handlers = new ArrayList(); /// /// Specifies whether the "Add Link" drop handler is suggested when none of the composed handlers fits. /// protected bool _bAddLink = true; /// /// The default link handler to fallback to if none of the composed handlers works out. /// protected static IResourceDragDropHandler _linkhandler = null; #endregion #region Construction /// /// Creates a composite handler with no contained handlers, just with the default link handler. /// public ResourceDragDropCompositeHandler() { if( _linkhandler == null ) _linkhandler = new ResourceDragDropLinkHandler(); } /// /// Creates a composite handler wrapping one raw handler, plus the default link handler. /// for more details. /// public ResourceDragDropCompositeHandler( IResourceDragDropHandler handlerBase ) { if( _linkhandler == null ) _linkhandler = new ResourceDragDropLinkHandler(); AddHandler( handlerBase ); } /// /// Creates a composite handler wrapping an arbitiary number of handlers, plus the default link handler. /// for more details. /// public ResourceDragDropCompositeHandler( params object[] args ) { if( _linkhandler == null ) _linkhandler = new ResourceDragDropLinkHandler(); foreach(object oHandler in args) { IResourceDragDropHandler handler = oHandler as IResourceDragDropHandler; if(handler == null) throw new ArgumentException("All the arguments must implement the IResourceDragDropHandler interface."); AddHandler( handler ); } } #endregion #region Attributes /// /// Gets a collection of the handlers wrapped by this composite handler; the default link hanlder is not included. /// [Browsable( false )] public ICollection Handlers { get { return _handlers; } } /// /// Gets the default link hanlder that is invoked when none of the wrapped handlers fits, /// and is set to True. /// [Browsable( false )] public IResourceDragDropHandler LinkHandler { get { return _linkhandler; } } /// /// Gets or sets whether the default link handler (as provided by ) gets executed when /// none of the wrapped handlers fits. /// [DefaultValue( true )] public bool AddLink { get { return _bAddLink; } set { _bAddLink = value; } } #endregion #region Operations /// /// Adds a new handler to the wrapped handlers list, as the last one in the list. /// The handlers will be executed in the same order as they were added. /// If the is a composite handler of the same type as this, /// its members are added one by one instead of adding the composite handler itself. /// public void AddHandler( IResourceDragDropHandler handler ) { // For a composite, add all of its members ResourceDragDropCompositeHandler composite = handler as ResourceDragDropCompositeHandler; if( composite != null ) { foreach( IResourceDragDropHandler handlerInner in composite.Handlers ) AddHandler( handlerInner ); } else _handlers.Add( handler ); } #endregion #region IResourceDragDropHandler Members public void Drop( IResource targetResource, IDataObject data, DragDropEffects allowedEffect, int keyState ) { // Find who can handle the drop (including the link handler, if allowed) IResourceDragDropHandler handlerFit; GetDragOverHandler( targetResource, data, allowedEffect, keyState, out handlerFit ); // Drop! if( handlerFit != null ) handlerFit.Drop( targetResource, data, allowedEffect, keyState ); } public DragDropEffects DragOver( IResource targetResource, IDataObject data, DragDropEffects allowedEffect, int keyState ) { IResourceDragDropHandler handlerFit; return GetDragOverHandler( targetResource, data, allowedEffect, keyState, out handlerFit ); } public void AddResourceDragData( IResourceList dragResources, IDataObject dataObject ) { // Call all the handlers so that they added their data foreach( IResourceDragDropHandler handler in _handlers ) handler.AddResourceDragData( dragResources, dataObject ); } #endregion #region Implementation /// /// Looks for a handler within the composed ones and the link-handler, if enabled, and picks the first one that /// confirms it can handle the situation in response to the dragover event. /// That handler is then returned. /// Note that the drag-over operation is thus already executed for that handler. /// protected DragDropEffects GetDragOverHandler( IResource targetResource, IDataObject data, DragDropEffects allowedEffect, int keyState, out IResourceDragDropHandler handlerFit ) { DragDropEffects effect; // Try the composed handlers foreach( IResourceDragDropHandler handler in _handlers ) { handlerFit = handler; if( (effect = handlerFit.DragOver( targetResource, data, allowedEffect, keyState )) != DragDropEffects.None ) return effect; } // Try the link-handler if( _bAddLink ) { handlerFit = _linkhandler; if( (effect = handlerFit.DragOver( targetResource, data, allowedEffect, keyState )) != DragDropEffects.None ) return effect; } // None has fit handlerFit = null; return DragDropEffects.None; } #endregion } #endregion }