| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // Licensed to the Apache Software Foundation (ASF) under one or more |
| // contributor license agreements. See the NOTICE file distributed with |
| // this work for additional information regarding copyright ownership. |
| // The ASF licenses this file to You under the Apache License, Version 2.0 |
| // (the "License"); you may not use this file except in compliance with |
| // the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| package mx.managers |
| { |
| |
| import flash.desktop.Clipboard; |
| import flash.desktop.NativeDragManager; |
| import flash.desktop.NativeDragOptions; |
| import flash.display.BitmapData; |
| import flash.display.DisplayObject; |
| import flash.display.InteractiveObject; |
| import flash.events.Event; |
| import flash.events.IEventDispatcher; |
| import flash.events.MouseEvent; |
| import flash.events.NativeDragEvent; |
| import flash.geom.ColorTransform; |
| import flash.geom.Matrix; |
| import flash.geom.Point; |
| import flash.system.Capabilities; |
| import flash.utils.getDefinitionByName; |
| |
| import mx.core.DragSource; |
| import mx.core.IFlexDisplayObject; |
| import mx.core.IFlexModule; |
| import mx.core.IFlexModuleFactory; |
| import mx.core.IUIComponent; |
| import mx.core.UIComponentGlobals; |
| import mx.core.mx_internal; |
| import mx.events.DragEvent; |
| import mx.events.FlexEvent; |
| import mx.events.InterDragManagerEvent; |
| import mx.events.InterManagerRequest; |
| import mx.managers.dragClasses.DragProxy; |
| import mx.styles.CSSStyleDeclaration; |
| import mx.styles.IStyleManager2; |
| import mx.styles.StyleManager; |
| import mx.utils.Platform; |
| |
| use namespace mx_internal; |
| |
| [ExcludeClass] |
| |
| /** |
| * @private |
| * |
| * @playerversion AIR 1.1 |
| */ |
| public class NativeDragManagerImpl implements IDragManager |
| { |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Class variables |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| */ |
| private static var sm:ISystemManager; |
| |
| /** |
| * @private |
| */ |
| private static var instance:IDragManager; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Class methods |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| */ |
| public static function getInstance():IDragManager |
| { |
| if (!instance) |
| { |
| sm = SystemManagerGlobals.topLevelSystemManagers[0]; |
| instance = new NativeDragManagerImpl(); |
| } |
| |
| return instance; |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Constructor |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| */ |
| public function NativeDragManagerImpl() |
| { |
| super(); |
| |
| if (instance) |
| throw new Error("Instance already exists."); |
| |
| registerSystemManager(sm); |
| sandboxRoot = sm.getSandboxRoot(); |
| sandboxRoot.addEventListener(InterDragManagerEvent.DISPATCH_DRAG_EVENT, marshalDispatchEventHandler, false, 0, true); |
| |
| // trace("creating DragManagerImpl", sm); |
| sandboxRoot.addEventListener(InterManagerRequest.DRAG_MANAGER_REQUEST, marshalDragManagerHandler, false, 0, true); |
| var me:InterManagerRequest = new InterManagerRequest(InterManagerRequest.DRAG_MANAGER_REQUEST); |
| me.name = "update"; |
| // trace("--->update request for DragManagerImpl", sm); |
| sandboxRoot.dispatchEvent(me); |
| // trace("<---update request for DragManagerImpl", sm); |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Variables |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| * Object being dragged around. |
| */ |
| public var dragProxy:DragProxy; |
| |
| /** |
| * @private |
| */ |
| private var mouseIsDown:Boolean = false; |
| |
| private var _action:String; |
| |
| /** |
| * @private |
| */ |
| private var _dragInitiator:IUIComponent; |
| |
| /** |
| * @private |
| */ |
| private var _clipboard:Clipboard; |
| |
| /** |
| * @private |
| */ |
| private var _dragImage:IFlexDisplayObject; |
| |
| private var _offset:Point; |
| |
| private var _allowedActions:NativeDragOptions; |
| |
| private var _allowMove:Boolean; |
| |
| private var _relatedObject:InteractiveObject; |
| |
| private var _imageAlpha:Number; |
| |
| /** |
| * @private |
| * The highest place we can listen for events in our DOM |
| */ |
| private var sandboxRoot:IEventDispatcher; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Properties |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * Read-only property that returns <code>true</code> |
| * if a drag is in progress. |
| * |
| * @langversion 3.0 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function get isDragging():Boolean |
| { |
| return flash.desktop.NativeDragManager.isDragging;// || bDoingDrag; |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Methods |
| // |
| //-------------------------------------------------------------------------- |
| |
| |
| /** |
| * Initiates a drag and drop operation. |
| * |
| * @param dragInitiator IUIComponent that specifies the component initiating |
| * the drag. |
| * |
| * @param dragSource DragSource object that contains the data |
| * being dragged. |
| * |
| * @param mouseEvent The MouseEvent that contains the mouse information |
| * for the start of the drag. |
| * |
| * @param dragImage The image to drag. This argument is optional. |
| * If omitted, a standard drag rectangle is used during the drag and |
| * drop operation. If you specify an image, you must explicitly set a |
| * height and width of the image or else it will not appear. |
| * |
| * @param xOffset Number that specifies the x offset, in pixels, for the |
| * <code>dragImage</code>. This argument is optional. If omitted, the drag proxy |
| * is shown at the upper-left corner of the drag initiator. The offset is expressed |
| * in pixels from the left edge of the drag proxy to the left edge of the drag |
| * initiator, and is usually a negative number. |
| * |
| * @param yOffset Number that specifies the y offset, in pixels, for the |
| * <code>dragImage</code>. This argument is optional. If omitted, the drag proxy |
| * is shown at the upper-left corner of the drag initiator. The offset is expressed |
| * in pixels from the top edge of the drag proxy to the top edge of the drag |
| * initiator, and is usually a negative number. |
| * |
| * @param imageAlpha Number that specifies the alpha value used for the |
| * drag image. This argument is optional. If omitted, the default alpha |
| * value is 0.5. A value of 0.0 indicates that the image is transparent; |
| * a value of 1.0 indicates it is fully opaque. |
| * |
| * @langversion 3.0 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function doDrag( |
| dragInitiator:IUIComponent, |
| dragSource:DragSource, |
| mouseEvent:MouseEvent, |
| dragImage:IFlexDisplayObject = null, // instance of dragged item(s) |
| xOffset:Number = 0, |
| yOffset:Number = 0, |
| imageAlpha:Number = 0.5, |
| allowMove:Boolean = true):void |
| { |
| if (dragAutomationHandlerClass) |
| { |
| dragAutomationHandlerClass["storeAIRDragSourceDetails"](dragSource); |
| } |
| |
| var proxyWidth:Number; |
| var proxyHeight:Number; |
| |
| // Can't start a new drag if we're already in the middle of one... |
| if (isDragging) |
| return; |
| |
| // Can't do a drag if the mouse isn't down |
| if (!(mouseEvent.type == MouseEvent.MOUSE_DOWN || |
| mouseEvent.type == MouseEvent.CLICK || |
| mouseIsDown || |
| mouseEvent.buttonDown)) |
| { |
| return; |
| } |
| |
| var me:InterManagerRequest = new InterManagerRequest(InterManagerRequest.DRAG_MANAGER_REQUEST); |
| me.name = "isDragging"; |
| me.value = true; |
| // trace("-->dispatch isDragging for DragManagerImpl", sm, true); |
| sandboxRoot.dispatchEvent(me); |
| // trace("<--dispatch isDragging for DragManagerImpl", sm, true); |
| |
| me = new InterManagerRequest(InterManagerRequest.DRAG_MANAGER_REQUEST); |
| me.name = "mouseShield"; |
| me.value = true; |
| // trace("-->dispatch add mouseShield.for DragManagerImpl", sm); |
| sandboxRoot.dispatchEvent(me); |
| |
| _clipboard = new Clipboard(); |
| _dragInitiator = dragInitiator; |
| _offset = new Point(xOffset, yOffset); |
| _allowMove = allowMove; |
| _imageAlpha = imageAlpha; |
| |
| //adjust offsets for imagePlacement. |
| _offset.y -= InteractiveObject(dragInitiator).mouseY; |
| _offset.x -= InteractiveObject(dragInitiator).mouseX; |
| |
| // TODO!!! We need to pass in these values as a function parameter |
| _allowedActions = new NativeDragOptions(); |
| _allowedActions.allowCopy = true; |
| _allowedActions.allowLink = true; |
| _allowedActions.allowMove = allowMove; |
| |
| // Transfer the dragSource into a Clipboard |
| for (var i:int = 0; i < dragSource.formats.length; i++) |
| { |
| var format:String = dragSource.formats[i] as String; |
| |
| // Create an object to store a reference to the format and dragSource. |
| // This delays copying over the drag data until it is needed |
| var dataFetcher:DragDataFormatFetcher = new DragDataFormatFetcher(); |
| dataFetcher.dragSource = dragSource; |
| dataFetcher.format = format; |
| |
| _clipboard.setDataHandler(format, dataFetcher.getDragSourceData, false); |
| } |
| |
| if (!dragImage) |
| { |
| // No drag image specified, use default |
| var dragManagerStyleDeclaration:CSSStyleDeclaration = |
| getStyleManager(dragInitiator).getStyleDeclaration("mx.managers.DragManager"); |
| var dragImageClass:Class = |
| dragManagerStyleDeclaration.getStyle("defaultDragImageSkin"); |
| dragImage = new dragImageClass(); |
| proxyWidth = dragInitiator ? dragInitiator.width : 0; |
| proxyHeight = dragInitiator ? dragInitiator.height : 0; |
| if (dragImage is IFlexDisplayObject) |
| IFlexDisplayObject(dragImage).setActualSize(proxyWidth, proxyHeight); |
| } |
| else |
| { |
| proxyWidth = dragImage.width; |
| proxyHeight = dragImage.height; |
| } |
| |
| _dragImage = dragImage; |
| |
| if (dragAutomationHandlerClass) |
| { |
| dragAutomationHandlerClass["recordAutomatableDragStart1"](dragInitiator as IUIComponent, mouseEvent); |
| } |
| |
| if (dragImage is IUIComponent && dragImage is ILayoutManagerClient && |
| !ILayoutManagerClient(dragImage).initialized && dragInitiator) |
| { |
| dragImage.addEventListener(FlexEvent.UPDATE_COMPLETE,initiateDrag); |
| dragInitiator.systemManager.popUpChildren.addChild(DisplayObject(dragImage)); |
| |
| if (dragImage is ILayoutManagerClient ) |
| { |
| UIComponentGlobals.layoutManager.validateClient(ILayoutManagerClient(dragImage), true); |
| } |
| |
| if(dragImage is IUIComponent) |
| { |
| dragImage.setActualSize(proxyWidth, proxyHeight); |
| proxyWidth = (dragImage as IUIComponent).getExplicitOrMeasuredWidth(); |
| proxyHeight = (dragImage as IUIComponent).getExplicitOrMeasuredHeight(); |
| } |
| else |
| { |
| proxyWidth = dragImage.measuredWidth; |
| proxyHeight = dragImage.measuredHeight; |
| } |
| |
| if (dragImage is ILayoutManagerClient ) |
| { |
| UIComponentGlobals.layoutManager.validateClient(ILayoutManagerClient(dragImage)); |
| } |
| } |
| else |
| { |
| initiateDrag(null, false); |
| return; |
| } |
| } |
| |
| /** |
| * Finish up the doDrag once the dragImage has been drawn |
| * |
| * @langversion 3.0 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| private function initiateDrag(event:FlexEvent, removeImage:Boolean = true):void |
| { |
| if (removeImage) |
| _dragImage.removeEventListener(FlexEvent.UPDATE_COMPLETE, initiateDrag); |
| var dragBitmap:BitmapData; |
| if (_dragImage.width && _dragImage.height) |
| dragBitmap = new BitmapData(_dragImage.width, _dragImage.height, true, 0x000000); |
| else |
| dragBitmap = new BitmapData(1, 1, true, 0x000000); |
| |
| // Adjust the alpha while copying the image into the dragBitmap. |
| var colorTransform:ColorTransform = new ColorTransform(); |
| colorTransform.alphaMultiplier = _imageAlpha; |
| |
| dragBitmap.draw(_dragImage, new Matrix(), colorTransform); |
| |
| if (removeImage && _dragImage is IUIComponent && _dragInitiator) |
| { |
| _dragInitiator.systemManager.popUpChildren.removeChild(DisplayObject(_dragImage)); |
| } |
| |
| // TODO!!! include _dragActions as the last param |
| flash.desktop.NativeDragManager.doDrag(InteractiveObject(_dragInitiator), _clipboard, dragBitmap, _offset, _allowedActions); |
| //NativeDragManager.dropAction = _allowMove ? DragManager.MOVE : DragManager.COPY; |
| } |
| |
| /** |
| * Call this method from your <code>dragEnter</code> event handler if you accept |
| * the drag/drop data. |
| * For example: |
| * |
| * <pre>DragManager.acceptDragDrop(event.target);</pre> |
| * |
| * @param target The drop target accepting the drag. |
| * |
| * @langversion 3.0 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function acceptDragDrop(target:IUIComponent):void |
| { |
| if (isDragging) |
| { |
| // trace("NativeDragMgr.acceptDragDrop targ",target); |
| var dispObj:InteractiveObject = target as InteractiveObject; |
| if (dispObj) |
| flash.desktop.NativeDragManager.acceptDragDrop(dispObj); |
| } |
| else |
| { |
| var me:InterManagerRequest = new InterManagerRequest(InterManagerRequest.DRAG_MANAGER_REQUEST); |
| me.name = "acceptDragDrop"; |
| me.value = target; |
| // trace("-->dispatch acceptDragDrop for DragManagerImpl", sm, target); |
| sandboxRoot.dispatchEvent(me); |
| // trace("<--dispatch acceptDragDrop for DragManagerImpl", sm, target); |
| } |
| } |
| |
| /** |
| * Sets the feedback indicator for the drag and drop operation. |
| * Possible values are <code>DragManager.COPY</code>, <code>DragManager.MOVE</code>, |
| * <code>DragManager.LINK</code>, or <code>DragManager.NONE</code>. |
| * |
| * @param feedback The type of feedback indicator to display. |
| * |
| * @langversion 3.0 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function showFeedback(feedback:String):void |
| { |
| if (isDragging) |
| { |
| if (feedback == DragManager.MOVE && !_allowedActions.allowMove) |
| return; |
| else if (feedback == DragManager.COPY && !_allowedActions.allowCopy) |
| return; |
| else if (feedback == DragManager.LINK && !_allowedActions.allowLink) |
| return; |
| flash.desktop.NativeDragManager.dropAction = feedback; |
| } |
| else |
| { |
| var me:InterManagerRequest = new InterManagerRequest(InterManagerRequest.DRAG_MANAGER_REQUEST); |
| me.name = "showFeedback"; |
| me.value = feedback; |
| // trace("-->dispatch showFeedback for DragManagerImpl", sm, feedback); |
| sandboxRoot.dispatchEvent(me); |
| // trace("<--dispatch showFeedback for DragManagerImpl", sm, feedback); |
| } |
| } |
| |
| /** |
| * Returns the current drag and drop feedback. |
| * |
| * @return Possible return values are <code>DragManager.COPY</code>, |
| * <code>DragManager.MOVE</code>, |
| * <code>DragManager.LINK</code>, or <code>DragManager.NONE</code>. |
| * |
| * @langversion 3.0 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function getFeedback():String |
| { |
| if (!isDragging) |
| { |
| var me:InterManagerRequest = new InterManagerRequest(InterManagerRequest.DRAG_MANAGER_REQUEST); |
| me.name = "getFeedback"; |
| // trace("-->dispatch getFeedback for DragManagerImpl", sm); |
| sandboxRoot.dispatchEvent(me); |
| // trace("<--dispatch getFeedback for DragManagerImpl", sm); |
| return me.value as String; |
| } |
| |
| return flash.desktop.NativeDragManager.dropAction; |
| } |
| |
| /** |
| * @Review |
| * Not Supported by NativeDragManagerImpl |
| * |
| * @langversion 3.0 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function endDrag():void |
| { |
| var me:InterManagerRequest; |
| |
| me = new InterManagerRequest(InterManagerRequest.DRAG_MANAGER_REQUEST); |
| me.name = "mouseShield"; |
| me.value = false; |
| // trace("-->dispatch remove mouseShield.for DragManagerImpl", sm); |
| sandboxRoot.dispatchEvent(me); |
| |
| me = new InterManagerRequest(InterManagerRequest.DRAG_MANAGER_REQUEST); |
| me.name = "isDragging"; |
| me.value = false; |
| // trace("-->dispatch isDragging for DragManagerImpl", sm, false); |
| sandboxRoot.dispatchEvent(me); |
| // trace("<--dispatch isDragging for DragManagerImpl", sm, false); |
| // trace("<--endDrag for DragManagerImpl", sm); |
| |
| } |
| |
| /** |
| * @private |
| * register ISystemManagers that will listen for events |
| * (such as those for additional windows) |
| */ |
| mx_internal function registerSystemManager(sm:ISystemManager):void |
| { |
| if (sm.isTopLevel()) |
| { |
| sm.addEventListener(MouseEvent.MOUSE_DOWN, sm_mouseDownHandler); |
| sm.addEventListener(MouseEvent.MOUSE_UP, sm_mouseUpHandler); |
| } |
| |
| sm.stage.addEventListener(NativeDragEvent.NATIVE_DRAG_ENTER, nativeDragEventHandler, true); |
| sm.stage.addEventListener(NativeDragEvent.NATIVE_DRAG_COMPLETE, nativeDragEventHandler, true); |
| sm.stage.addEventListener(NativeDragEvent.NATIVE_DRAG_DROP, nativeDragEventHandler, true); |
| sm.stage.addEventListener(NativeDragEvent.NATIVE_DRAG_EXIT, nativeDragEventHandler, true); |
| sm.stage.addEventListener(NativeDragEvent.NATIVE_DRAG_OVER, nativeDragEventHandler, true); |
| sm.stage.addEventListener(NativeDragEvent.NATIVE_DRAG_START, nativeDragEventHandler, true); |
| |
| } |
| |
| /** |
| * @private |
| * unregister ISystemManagers that will listen for events |
| * (such as those for additional windows) |
| */ |
| mx_internal function unregisterSystemManager(sm:ISystemManager):void |
| { |
| if (sm.isTopLevel()) |
| { |
| sm.removeEventListener(MouseEvent.MOUSE_DOWN, sm_mouseDownHandler); |
| sm.removeEventListener(MouseEvent.MOUSE_UP, sm_mouseUpHandler); |
| } |
| |
| sm.stage.removeEventListener(NativeDragEvent.NATIVE_DRAG_ENTER, nativeDragEventHandler, true); |
| sm.stage.removeEventListener(NativeDragEvent.NATIVE_DRAG_COMPLETE, nativeDragEventHandler, true); |
| sm.stage.removeEventListener(NativeDragEvent.NATIVE_DRAG_DROP, nativeDragEventHandler, true); |
| sm.stage.removeEventListener(NativeDragEvent.NATIVE_DRAG_EXIT, nativeDragEventHandler, true); |
| sm.stage.removeEventListener(NativeDragEvent.NATIVE_DRAG_OVER, nativeDragEventHandler, true); |
| sm.stage.removeEventListener(NativeDragEvent.NATIVE_DRAG_START, nativeDragEventHandler, true); |
| |
| } |
| |
| /** |
| * @private |
| */ |
| static private function getStyleManager(dragInitiator:IUIComponent):IStyleManager2 |
| { |
| // If the dragInitiator has a styleManager, use that one. |
| // In a situation where a main application that loads a module with drag initiator, |
| // the main application may not link in the DragManager and appropriate styles. |
| // We want to use the styles of the module of the dragInitiator. See SDK-24324. |
| if (dragInitiator is IFlexModule) |
| return StyleManager.getStyleManager(IFlexModule(dragInitiator).moduleFactory); |
| |
| return StyleManager.getStyleManager(sm as IFlexModuleFactory); |
| } |
| |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Automation |
| // |
| //-------------------------------------------------------------------------- |
| /** |
| * @private |
| * This function gets the class which is responsible for getting the |
| * drag automation handler class. |
| */ |
| |
| private var _dragAutomationHandlerClass:Class; |
| |
| /** |
| * @private |
| */ |
| private function get dragAutomationHandlerClass():Class |
| { |
| if (!_dragAutomationHandlerClass) |
| { |
| try |
| { |
| if (sm) |
| { |
| _dragAutomationHandlerClass = |
| Class(sm.getDefinitionByName("mx.automation.delegates.DragManagerAutomationImpl")); |
| } |
| else |
| { |
| _dragAutomationHandlerClass = |
| Class(getDefinitionByName("mx.automation.delegates.DragManagerAutomationImpl")); |
| } |
| } |
| catch (e:Error) |
| { |
| trace(e.message); |
| } |
| } |
| return _dragAutomationHandlerClass; |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Event handlers |
| // |
| //-------------------------------------------------------------------------- |
| private function sm_mouseDownHandler(event:MouseEvent):void |
| { |
| mouseIsDown = true; |
| } |
| |
| private function sm_mouseUpHandler(event:MouseEvent):void |
| { |
| mouseIsDown = false; |
| } |
| |
| /** |
| * Listens for all NativeDragEvents and then redispatches them as DragEvents |
| * |
| * @langversion 3.0 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| private function nativeDragEventHandler(event:NativeDragEvent):void |
| { |
| var newType:String = event.type.charAt(6).toLowerCase() + event.type.substr(7); |
| var dragSource:DragSource = new DragSource(); |
| var target:DisplayObject = event.target as DisplayObject; |
| var clipboard:Clipboard = event.clipboard; |
| var origFormats:Array = clipboard.formats; |
| var len:int = origFormats.length; |
| var format:String; |
| var data:Object; |
| var me:InterManagerRequest; |
| |
| _allowedActions = event.allowedActions; |
| |
| //translate either commandKey or controlKey to old-style ctrlKey |
| var ctrlKey:Boolean = false; |
| if (Platform.isMac) |
| ctrlKey = event.commandKey; |
| else |
| ctrlKey = event.controlKey; |
| |
| //default to move if drag is from same app |
| if (NativeDragManager.dragInitiator && event.type == NativeDragEvent.NATIVE_DRAG_START) |
| { |
| flash.desktop.NativeDragManager.dropAction = |
| (ctrlKey || !_allowMove) ? DragManager.COPY : DragManager.MOVE; |
| } |
| |
| // Transfer clipboard data to dragSource |
| if (event.type != NativeDragEvent.NATIVE_DRAG_EXIT) |
| { |
| for (var i:int = 0; i < len; i++) |
| { |
| format = origFormats[i]; |
| if (clipboard.hasFormat(format)) |
| { |
| // Create an object to store a reference to the format and clipboard. |
| // This delays copying over the drag data until it is needed |
| var dataFetcher:DragDataFormatFetcher = new DragDataFormatFetcher(); |
| dataFetcher.clipboard = clipboard; |
| dataFetcher.format = format; |
| |
| dragSource.addHandler(dataFetcher.getClipboardData, format); |
| } |
| } |
| } |
| if (event.type == NativeDragEvent.NATIVE_DRAG_DROP) |
| _relatedObject = event.target as InteractiveObject; |
| |
| |
| |
| // Need a dragInitiator in NativeDragEvent |
| var dragEvent:DragEvent |
| = new DragEvent(newType, false, event.cancelable, |
| NativeDragManager.dragInitiator as IUIComponent, |
| dragSource, event.dropAction, ctrlKey, |
| event.altKey, event.shiftKey); |
| dragEvent.buttonDown = event.buttonDown; |
| dragEvent.delta = event.delta; |
| dragEvent.localX = event.localX; |
| dragEvent.localY = event.localY; |
| if (newType == DragEvent.DRAG_COMPLETE) |
| dragEvent.relatedObject = _relatedObject; |
| else |
| dragEvent.relatedObject = event.relatedObject; |
| |
| if (dragAutomationHandlerClass) |
| { |
| if (newType == DragEvent.DRAG_DROP) |
| { |
| dragAutomationHandlerClass["recordAutomatableDragDrop1"](target,dragEvent); |
| } |
| else if (newType == DragEvent.DRAG_COMPLETE) |
| { |
| dragAutomationHandlerClass["recordAutomatableDragCancel1"] |
| (NativeDragManager.dragInitiator as IUIComponent, dragEvent); |
| } |
| } |
| |
| // Resend the event as a DragEvent. |
| _dispatchDragEvent(target, dragEvent); |
| |
| if (newType == DragEvent.DRAG_COMPLETE) |
| { |
| if (sm == sandboxRoot) |
| endDrag(); |
| else |
| { |
| me = new InterManagerRequest(InterManagerRequest.DRAG_MANAGER_REQUEST); |
| me.name = "endDrag"; |
| // trace("-->dispatch endDrag for DragManagerImpl", sm); |
| sandboxRoot.dispatchEvent(me); |
| // trace("<--dispatch endDrag for DragManagerImpl", sm); |
| } |
| } |
| } |
| |
| /** |
| * @private |
| */ |
| private function _dispatchDragEvent(target:DisplayObject, event:DragEvent):void |
| { |
| // in trusted mode, the target could be in another application domain |
| // in untrusted mode, the mouse events shouldn't work so we shouldn't be here |
| |
| // same domain |
| if (isSameOrChildApplicationDomain(target)) |
| target.dispatchEvent(event); |
| else |
| { |
| // wake up all the other DragManagers |
| var me:InterManagerRequest = new InterManagerRequest(InterManagerRequest.INIT_MANAGER_REQUEST); |
| me.name = "mx.managers.IDragManagerImpl"; |
| sandboxRoot.dispatchEvent(me); |
| // bounce this message off the sandbox root and hope |
| // another DragManager picks it up |
| var mde:InterDragManagerEvent = new InterDragManagerEvent(InterDragManagerEvent.DISPATCH_DRAG_EVENT, false, false, |
| event.localX, |
| event.localY, |
| event.relatedObject, |
| event.ctrlKey, |
| event.altKey, |
| event.shiftKey, |
| event.buttonDown, |
| event.delta, |
| target, |
| event.type, |
| event.dragInitiator, |
| event.dragSource, |
| event.action, |
| event.draggedItem |
| ); |
| sandboxRoot.dispatchEvent(mde); |
| } |
| } |
| |
| private function isSameOrChildApplicationDomain(target:Object):Boolean |
| { |
| var swfRoot:DisplayObject = SystemManager.getSWFRoot(target); |
| if (swfRoot) |
| return true; |
| |
| var me:InterManagerRequest = new InterManagerRequest(InterManagerRequest.SYSTEM_MANAGER_REQUEST); |
| me.name = "hasSWFBridges"; |
| sandboxRoot.dispatchEvent(me); |
| |
| // if no bridges, it might be a private/internal class so return true and hope we're right |
| if (!me.value) return true; |
| |
| return false; |
| } |
| |
| /** |
| * Marshal dispatchEvents |
| * |
| * @langversion 3.0 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| private function marshalDispatchEventHandler(event:Event):void |
| { |
| if (event is InterDragManagerEvent) |
| return; |
| |
| var marshalEvent:Object = event; |
| |
| var swfRoot:DisplayObject = SystemManager.getSWFRoot(marshalEvent.dropTarget); |
| if (!swfRoot) |
| return; // doesn't belong to this appdomain |
| |
| var dragEvent:DragEvent = new DragEvent(marshalEvent.dragEventType, marshalEvent.bubbles, marshalEvent.cancelable); |
| dragEvent.localX = marshalEvent.localX; |
| dragEvent.localY = marshalEvent.localY; |
| dragEvent.action = marshalEvent.action; |
| dragEvent.ctrlKey = marshalEvent.ctrlKey; |
| dragEvent.altKey = marshalEvent.altKey; |
| dragEvent.shiftKey = marshalEvent.shiftKey; |
| dragEvent.draggedItem = marshalEvent.draggedItem; |
| dragEvent.dragSource = new DragSource(); |
| var formats:Array = marshalEvent.dragSource.formats; |
| var n:int = formats.length; |
| for (var i:int = 0; i < n; i++) |
| { |
| // this will call handlers right away, so deferred clipboard will be costly |
| dragEvent.dragSource.addData(marshalEvent.dragSource.dataForFormat(formats[i]), formats[i]); |
| } |
| if (!marshalEvent.dropTarget.dispatchEvent(dragEvent)) |
| { |
| event.preventDefault(); |
| } |
| } |
| |
| /** |
| * Marshal dragManager |
| * |
| * @langversion 3.0 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| private function marshalDragManagerHandler(event:Event):void |
| { |
| if (event is InterManagerRequest) |
| return; |
| |
| var marshalEvent:Object = event; |
| switch (marshalEvent.name) |
| { |
| case "isDragging": |
| // trace("--marshaled isDragging for DragManagerImpl", sm, marshalEvent.value); |
| // bDoingDrag = marshalEvent.value; // not supported in AIR right now, we'd need more info |
| break; |
| case "acceptDragDrop": |
| if (isDragging) |
| { |
| // trace("NativeDragMgr.acceptDragDrop targ",target); |
| var dispObj:InteractiveObject = marshalEvent.value as InteractiveObject; |
| if (dispObj) |
| flash.desktop.NativeDragManager.acceptDragDrop(dispObj); |
| } |
| break; |
| case "showFeedback": |
| if (isDragging) // it is our drag |
| { |
| // trace("--marshaled showFeedback for DragManagerImpl", sm, marshalEvent.value); |
| showFeedback(marshalEvent.value); |
| } |
| break; |
| case "getFeedback": |
| if (isDragging) // it is our drag |
| { |
| marshalEvent.value = getFeedback(); |
| // trace("--marshaled getFeedback for DragManagerImpl", sm, marshalEvent.value); |
| } |
| break; |
| case "endDrag": |
| // trace("--marshaled endDrag for DragManagerImpl", sm, marshalEvent.value); |
| endDrag(); |
| break; |
| case "update": |
| // if we own the drag, then redispatch to tell the new guy |
| if (isDragging) |
| { |
| // trace("-->marshaled update for DragManagerImpl", sm); |
| var me:InterManagerRequest = new InterManagerRequest(InterManagerRequest.DRAG_MANAGER_REQUEST); |
| me.name = "isDragging"; |
| me.value = true; |
| // trace("-->dispatched isDragging for DragManagerImpl", sm, true); |
| sandboxRoot.dispatchEvent(me); |
| // trace("<--dispatched isDragging for DragManagerImpl", sm, true); |
| // trace("<--marshaled update for DragManagerImpl", sm); |
| } |
| } |
| } |
| } |
| |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // Helper class: DragDataFormatFetcher |
| // |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| import flash.desktop.Clipboard; |
| import mx.core.DragSource; |
| |
| |
| /** |
| * @private |
| * Helper class used to provide a way to access the clipboard or dragSource data |
| * at a later time. |
| */ |
| class DragDataFormatFetcher |
| { |
| |
| include "../core/Version.as"; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Constructor |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * Constructor. |
| */ |
| public function DragDataFormatFetcher() |
| { |
| super(); |
| } |
| |
| /** |
| * @private |
| */ |
| public var clipboard:Clipboard; |
| |
| /** |
| * @private |
| */ |
| public var dragSource:DragSource; |
| |
| /** |
| * @private |
| */ |
| public var format:String; |
| |
| /** |
| * @private |
| */ |
| public function getClipboardData():Object |
| { |
| if (clipboard) |
| return clipboard.getData(format); |
| else |
| return null; |
| } |
| |
| /** |
| * @private |
| */ |
| public function getDragSourceData():Object |
| { |
| if (dragSource) |
| return dragSource.dataForFormat(format); |
| else |
| return null; |
| } |
| } |
| |