//////////////////////////////////////////////////////////////////////////////// // // 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.automation.air { import flash.desktop.Clipboard; import flash.desktop.NativeDragOptions; import flash.display.DisplayObject; import flash.events.EventDispatcher; import flash.events.IEventDispatcher; import flash.events.NativeDragEvent; import mx.automation.IAutomationObject; import mx.automation.events.AutomationDragEvent; import mx.core.DragSource; import mx.managers.ISystemManager; [Mixin] /** * Helper class that provides methods required for automation of drag and drop in AIR applications * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 2 * @productversion Flex 4.1 */ public class AirDragManagerAutomationHandler { private static var sm:ISystemManager; private static var dragStartHappened:Boolean = false; private static var _lastClipBoardObject:Clipboard; private static var dragOptions:NativeDragOptions; private static var lastDragStartObj:IAutomationObject ; private static var _lastDragSource:DragSource; /** * Constructor * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 2 * @productversion Flex 4.1 */ public function AirDragManagerAutomationHandler() { } /** * @private * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 2 * @productversion Flex 4.1 */ public static function init(root:DisplayObject):void { sm = root as ISystemManager; } /** * Returns the target of last drag start event * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 2 * @productversion Flex 4.1 */ public static function getlastDragStartObj():IAutomationObject { return lastDragStartObj; } /** * Stores the details of current drag source * @param dragSource DragSource object * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 2 * @productversion Flex 4.1 */ public static function storeAIRDragSourceDetails(dragSource:DragSource):void { dragOptions = new NativeDragOptions(); dragOptions.allowCopy = true; dragOptions.allowMove = true; dragOptions.allowLink = false; _lastClipBoardObject = null; dragStartHappened = true; _lastDragSource = dragSource; } /** * @private * Builds clipboard object from the passed dragSource object * */ private static function formClipboard(dragSource:DragSource):Clipboard { var clipboardObj:Clipboard = new Clipboard(); var formatsArr:Array = dragSource.formats; if (formatsArr) { //var dataArray:Array = new Array(); var count: int = formatsArr.length; var index:int = 0; while (index < count) { // get the data object //var currentDataObject:Object = dragSource.dataForFormat(formatsArr[index]); //clipboardObj.setData(formatsArr[index],currentDataObject,false); // The above commented part was throwing an RTE if currentDataObject is null. // http://bugs.adobe.com/jira/browse/FLEXENT-1069 // So we are using setDataHandler() method of ClipBoard instead of setData() // in the same way how NativeDragManager constructs a clipboard object in doDrag() var dataFetcher:DragDataFormatFetcher = new DragDataFormatFetcher(); dataFetcher.dragSource = dragSource; dataFetcher.format = formatsArr[index]; clipboardObj.setDataHandler(formatsArr[index],dataFetcher.getDragSourceData,false); index++; } } return clipboardObj; } /** * Replays drag start event * @param realTarget Object on which the event is to be dispatched * @param dragEvent AutomationDragEvent object that holds information required to build a drag start event * @param draggedItems Object which is dragged * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 2 * @productversion Flex 4.1 */ public static function replayAIRDragStartEvent(realTarget:EventDispatcher , dragEvent:AutomationDragEvent, draggedItems:IAutomationObject):void { lastDragStartObj = realTarget as IAutomationObject; //dragStartHappened = false; if (dragStartHappened == false) { _lastClipBoardObject = new Clipboard(); _lastClipBoardObject.setData("items",new Object(),false); if (!dragOptions) dragOptions = new NativeDragOptions(); dragOptions.allowCopy = true; dragOptions.allowMove = true; dragOptions.allowLink = false; // we need to crete a native drag enter event and then a drag drop event and dispatch on our component. var dragStartEvent:NativeDragEvent = new NativeDragEvent(NativeDragEvent.NATIVE_DRAG_START); dragStartEvent.clipboard = _lastClipBoardObject; dragStartEvent.allowedActions = dragOptions; dragStartEvent.dropAction = dragEvent.action; dragStartEvent.localX = dragEvent.localX; dragStartEvent.localY = dragEvent.localY; dragStartEvent.buttonDown = true; if (dragStartEvent.isDefaultPrevented()) trace ('here-x'); realTarget.dispatchEvent(dragStartEvent); } } /** * Replays drag drop event * @param realTarget Object on which event is to be dispatched * @param dragEvent AutomationDragEvent object that holds information required to build a drag drop event * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 2 * @productversion Flex 4.1 */ public static function replayAIRDragDropEvent(realTarget:EventDispatcher , dragEvent:AutomationDragEvent/*,dragSource:DragSource*/):void { // we should have dragStartHappened as true,_lastClipBoardObject and dragOptions as non null values. // in the case marhshalled application drag start and drag drop can be in different application domain. if (!dragStartHappened) { // we need to get the details from the application where the current dragStart happened. } else { _lastClipBoardObject = formClipboard(_lastDragSource); if (_lastClipBoardObject && dragOptions) { // we need to crete a native drag enter event and then a drag drop event and dispatch on our component. var dragEnterEvent:NativeDragEvent = new NativeDragEvent(NativeDragEvent.NATIVE_DRAG_ENTER); dragEnterEvent.clipboard = _lastClipBoardObject; dragEnterEvent.allowedActions = dragOptions; dragEnterEvent.dropAction = dragEvent.action; dragEnterEvent.localX = dragEvent.localX; dragEnterEvent.localY = dragEvent.localY; dragEnterEvent.buttonDown = true; realTarget.dispatchEvent(dragEnterEvent); var dragDropEvent:NativeDragEvent = new NativeDragEvent(NativeDragEvent.NATIVE_DRAG_DROP); dragDropEvent.clipboard = _lastClipBoardObject; dragDropEvent.allowedActions = dragOptions; dragDropEvent.dropAction = dragEvent.action; dragDropEvent.localX = dragEvent.localX; dragDropEvent.localY = dragEvent.localY; realTarget.dispatchEvent(dragDropEvent); // we need to dispatch the dragComplete on the dragStart object. if (lastDragStartObj as IEventDispatcher) { var dragCompleteEvent:NativeDragEvent = new NativeDragEvent(NativeDragEvent.NATIVE_DRAG_COMPLETE); dragCompleteEvent.clipboard = _lastClipBoardObject; dragCompleteEvent.allowedActions = dragOptions; dragCompleteEvent.dropAction = dragEvent.action; dragCompleteEvent.localX = dragEvent.localX; dragCompleteEvent.localY = dragEvent.localY; (lastDragStartObj as IEventDispatcher).dispatchEvent(dragCompleteEvent); } } } dragStartHappened = false; _lastDragSource = null; } /** * Replays drag drop event in marshalled applications * @param realTarget Object on which event is to be dispatched * @param dragEvent AutomationDragEvent object that holds information required to build a drag drop event * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 2 * @productversion Flex 4.1 */ public static function replayAIRDragDropMarshalledEvent(realTarget:Object , dragEvent:Object/*,dragSource:DragSource*/):void { // we should have dragStartHappened as true,_lastClipBoardObject and dragOptions as non null values. // in the case marhshalled application drag start and drag drop can be in different application domain. if (dragStartHappened == false) { // we need to get the details from the application where the current dragStart happened. } else { _lastClipBoardObject = formClipboard(_lastDragSource); if (_lastClipBoardObject && dragOptions) { // we need to crete a native drag enter event and then a drag drop event and dispatch on our component. var dragEnterEvent:NativeDragEvent = new NativeDragEvent(NativeDragEvent.NATIVE_DRAG_ENTER); dragEnterEvent.clipboard = _lastClipBoardObject; dragEnterEvent.allowedActions = dragOptions; dragEnterEvent.dropAction = dragEvent["action"]; dragEnterEvent.localX = dragEvent["localX"]; dragEnterEvent.localY = dragEvent["localY"]; dragEnterEvent.buttonDown = true; realTarget.dispatchEvent(dragEnterEvent); var dragDropEvent:NativeDragEvent = new NativeDragEvent(NativeDragEvent.NATIVE_DRAG_DROP); dragDropEvent.clipboard = _lastClipBoardObject; dragDropEvent.allowedActions = dragOptions; dragDropEvent.dropAction = dragEvent["action"]; dragDropEvent.localX = dragEvent["localX"]; dragDropEvent.localY = dragEvent["localY"]; realTarget.dispatchEvent(dragDropEvent); // we need to dispatch the dragComplete on the dragStart object. if (lastDragStartObj as IEventDispatcher) { var dragCompleteEvent:NativeDragEvent = new NativeDragEvent(NativeDragEvent.NATIVE_DRAG_COMPLETE); dragCompleteEvent.clipboard = _lastClipBoardObject; dragCompleteEvent.allowedActions = dragOptions; dragCompleteEvent.dropAction = dragEvent["action"]; dragCompleteEvent.localX = dragEvent["localX"]; dragCompleteEvent.localY = dragEvent["localY"]; (lastDragStartObj as IEventDispatcher).dispatchEvent(dragCompleteEvent); } } } dragStartHappened = false; _lastDragSource = null; } /** * Replays drag cancel event * @param realTarget Object on which event is to be dispatched * @param dragEvent AutomationDragEvent object that holds information required to build a drag cancel event * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 2 * @productversion Flex 4.1 */ public static function replayAIRDragCancelEvent(realTarget:EventDispatcher,dragEvent:AutomationDragEvent ):void { _lastClipBoardObject = formClipboard(_lastDragSource); var dragCancelEvent:NativeDragEvent = new NativeDragEvent(NativeDragEvent.NATIVE_DRAG_COMPLETE); dragCancelEvent.clipboard = _lastClipBoardObject; dragCancelEvent.allowedActions = dragOptions; dragCancelEvent.dropAction = dragEvent.action; dragCancelEvent.localX = dragEvent.localX; dragCancelEvent.localY = dragEvent.localY; (lastDragStartObj as IEventDispatcher).dispatchEvent(dragCancelEvent); dragStartHappened = false; _lastDragSource = null; } /** * Returns the clipboard instance of last drag event * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 2 * @productversion Flex 4.1 */ public static function get lastClipBoardObject():Clipboard { return lastClipBoardObject; } } } import mx.core.DragSource; class DragDataFormatFetcher { include "../../core/Version.as"; //-------------------------------------------------------------------------- // // Constructor // //-------------------------------------------------------------------------- /** * Constructor. */ public function DragDataFormatFetcher() { super(); } /** * @private */ public var dragSource:DragSource; /** * @private */ public var format:String; /** * @private */ public function getDragSourceData():Object { if (dragSource) return dragSource.dataForFormat(format); else return null; } }