diff --git a/xpfe/global/resources/content/MANIFEST b/xpfe/global/resources/content/MANIFEST index 57f4c650884..a8caac8bee0 100644 --- a/xpfe/global/resources/content/MANIFEST +++ b/xpfe/global/resources/content/MANIFEST @@ -40,4 +40,9 @@ tabBindings.xml treeBindings.xml xulBindings.xml xul.css +nsClipboard.js +nsDragAndDrop.js +nsJSSupportsUtils.js +nsTransferable.js +nsJSComponentManager.js diff --git a/xpfe/global/resources/content/Makefile.in b/xpfe/global/resources/content/Makefile.in index 26f2f69d177..fa39d5c194f 100644 --- a/xpfe/global/resources/content/Makefile.in +++ b/xpfe/global/resources/content/Makefile.in @@ -84,6 +84,11 @@ CHROME_CONTENT= \ tabBindings.xml \ treeBindings.xml \ xulBindings.xml \ + nsClipboard.js \ + nsDragAndDrop.js \ + nsJSSupportsUtils.js \ + nsTransferable.js \ + nsJSComponentManager.js\ xul.css \ $(NULL) diff --git a/xpfe/global/resources/content/makefile.win b/xpfe/global/resources/content/makefile.win index 7b3a8388491..2d8d2794dab 100644 --- a/xpfe/global/resources/content/makefile.win +++ b/xpfe/global/resources/content/makefile.win @@ -75,6 +75,11 @@ CHROME_CONTENT= \ .\radioBindings.xml \ .\tabBindings.xml \ .\treeBindings.xml \ + .\nsClipboard.js \ + .\nsDragAndDrop.js \ + .\nsJSSupportsUtils.js \ + .\nsTransferable.js \ + .\nsJSComponentManager.js \ .\xul.css \ $(NULL) diff --git a/xpfe/global/resources/content/nsClipboard.js b/xpfe/global/resources/content/nsClipboard.js new file mode 100644 index 00000000000..7b7ccaca4e5 --- /dev/null +++ b/xpfe/global/resources/content/nsClipboard.js @@ -0,0 +1,76 @@ +/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (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.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Original Author: + * Ben Matthew Goodger + * + * Contributor(s): + */ + +/** + * nsClipboard - wrapper around nsIClipboard and nsITransferable + * that simplifies access to the clipboard. + **/ +var nsClipboard = { + get mClipboard() + { + return nsJSComponentManager.getService("component://netscape/widget/clipboard", + "nsIClipboard"); + }, + + mCurrentClipboard: null, + /** + * Array/Object read (Object aFlavourList, long aClipboard, Bool aAnyFlag) ; + * + * returns the data in the clipboard + * + * @param Object aFlavourList + * formatted list of desired flavours + * @param long aClipboard + * the clipboard to read data from (kSelectionClipboard/kGlobalClipboard) + * @param Bool aAnyFlag + * should be false. + **/ + read: function (aFlavourList, aClipboard, aAnyFlag) + { + this.mCurrentClipboard = aClipboard; + var data = nsTransferable.get(aFlavourList, this.getClipboardTransferable, aAnyFlag); + return data; + }, + + /** + * nsISupportsArray getClipboardTransferable (Object aFlavourList) ; + * + * returns a nsISupportsArray of the item on the clipboard + * + * @param Object aFlavourList + * formatted list of desired flavours. + **/ + getClipboardTransferable: function (aFlavourList) + { + var supportsArray = nsJSSupportsUtils.createSupportsArray(); + var trans = nsTransferable.createTransferable(); + for (var flavour in aFlavourList) + trans.addDataFlavor(flavour); + nsClipboard.mClipboard.getData(trans, nsClipboard.mCurrentClipboard) + supportsArray.AppendElement(trans); + return supportsArray; + } +}; + diff --git a/xpfe/global/resources/content/nsDragAndDrop.js b/xpfe/global/resources/content/nsDragAndDrop.js new file mode 100644 index 00000000000..fc98d35ee31 --- /dev/null +++ b/xpfe/global/resources/content/nsDragAndDrop.js @@ -0,0 +1,168 @@ +/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (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.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Original Author: + * Ben Matthew Goodger + * + * Contributor(s): + */ + +/** + * nsDragAndDrop - a convenience wrapper for nsTransferable, nsITransferable + * and nsIDragService/nsIDragSession. + * + * Use: map the handler functions to the 'ondraggesture', 'ondragover' and + * 'ondragdrop' event handlers on your XML element, e.g. + * + * + * You need to create an observer js object with the following member + * functions: + * Object onDragStart (event) // called when drag initiated, + * // returns flavour list with data + * // to stuff into transferable + * void onDragOver (Object flavour) // called when element is dragged + * // over, so that it can perform + * // any drag-over feedback for provided + * // flavour + * void onDrop (Object data) // formatted data object dropped. + * Object getSupportedFlavours () // returns a flavour list so that + * // nsTransferable can determine whether + * // or not to accept drop. + **/ + +var nsDragAndDrop = { + + get mDragService() + { + return nsJSComponentManager.getService("component://netscape/widget/dragservice", + "nsIDragService"); + }, + + /** + * void startDrag (DOMEvent aEvent, Object aDragDropObserver) ; + * + * called when a drag on an element is started. + * + * @param DOMEvent aEvent + * the DOM event fired by the drag init + * @param Object aDragDropObserver + * javascript object of format described above that specifies + * the way in which the element responds to drag events. + **/ + startDrag: function (aEvent, aDragDropObserver) + { + if (aDragDropObserver.onDragStart) + flavourList = aDragDropObserver.onDragStart(aEvent); + + var trans = nsTransferable.set(flavourList); + trans = trans ? trans.QueryInterface(Components.interfaces.nsISupports) : trans; + var transArray = nsJSSupportsUtils.createSupportsArray(); + transArray.AppendElement(trans); + + var dragServiceIID = Components.interfaces.nsIDragService; + this.mDragService.invokeDragSession(aEvent.target, transArray, null, + dragServiceIID.DRAGDROP_ACTION_COPY + dragServiceIID.DRAGDROP_ACTION_MOVE); + aEvent.preventBubble(); + }, + + /** + * void dragOver (DOMEvent aEvent, Object aDragDropObserver) ; + * + * called when a drag passes over this element + * + * @param DOMEvent aEvent + * the DOM event fired by the drag init + * @param Object aDragDropObserver + * javascript object of format described above that specifies + * the way in which the element responds to drag events. + **/ + dragOver: function (aEvent, aDragDropObserver) + { + var dragSession = this.mDragService.getCurrentSession(); + if (dragSession) + { + var flavourList = aDragDropObserver.getSupportedFlavours(); + for (var flavour in flavourList) + { + if (dragSession.isDataFlavorSupported(flavour)) + { + dragSession.canDrop = true; + if (aDragDropObserver.onDragOver) + aDragDropObserver.onDragOver(flavour); + aEvent.preventBubble(); + break; + } + } + } + }, + + mDragSession: null, + + /** + * void drop (DOMEvent aEvent, Object aDragDropObserver) ; + * + * called when the user drops on the element + * + * @param DOMEvent aEvent + * the DOM event fired by the drag init + * @param Object aDragDropObserver + * javascript object of format described above that specifies + * the way in which the element responds to drag events. + **/ + drop: function (aEvent, aDragDropObserver) + { + this.mDragSession = this.mDragService.getCurrentSession(); + if (this.mDragSession) + { + var flavourList = aDragDropObserver.getSupportedFlavours(); + var dragData = nsTransferable.get(flavourList, this.getDragData, true); + aEvent.preventBubble(); + // hand over to the client to respond to dropped data + if (aDragDropObserver.onDrop) + aDragDropObserver.onDrop(dragData); + } + }, + + /** + * nsISupportsArray getDragData (Object aFlavourList) + * + * Creates a nsISupportsArray of all droppable items for the given + * set of supported flavours. + * + * @param Object aFlavourList + * formatted flavour list. + **/ + getDragData: function (aFlavourList) + { + var supportsArray = nsJSSupportsUtils.createSupportsArray(); + for (var i = 0; i < nsDragAndDrop.mDragSession.numDropItems; ++i) + { + var trans = nsTransferable.createTransferable(); + for (var flavour in aFlavourList) + trans.addDataFlavor(flavour); + nsDragAndDrop.mDragSession.getData(trans, i); + supportsArray.AppendElement(trans); + } + return supportsArray; + } + +}; + diff --git a/xpfe/global/resources/content/nsJSComponentManager.js b/xpfe/global/resources/content/nsJSComponentManager.js new file mode 100644 index 00000000000..7e826e95e7c --- /dev/null +++ b/xpfe/global/resources/content/nsJSComponentManager.js @@ -0,0 +1,74 @@ +/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (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.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Original Author: + * Ben Matthew Goodger + * + * Contributor(s): + */ + +var nsJSComponentManager = { + createInstance: function (aProgID, aIID) + { + try + { + var iid = Components.interfaces[aIID]; + return Components.classes[aProgID].createInstance(iid); + } + catch(e) + { + } + }, + + createInstanceByID: function (aID, aIID) + { + try + { + var iid = Components.interfaces[aIID]; + return Components.classesByID[aID].createInstance(iid); + } + catch(e) + { + } + }, + + getService: function (aProgID, aIID) + { + try + { + var iid = Components.interfaces[aIID]; + return Components.classes[aProgID].getService(iid); + } + catch(e) + { + } + }, + + getServiceByID: function (aID, aIID) + { + try + { + var iid = Components.interfaces[aIID]; + return Components.classes[aID].getService(iid); + } + catch(e) + { + } + } +}; \ No newline at end of file diff --git a/xpfe/global/resources/content/nsJSSupportsUtils.js b/xpfe/global/resources/content/nsJSSupportsUtils.js new file mode 100644 index 00000000000..4dbace8ad76 --- /dev/null +++ b/xpfe/global/resources/content/nsJSSupportsUtils.js @@ -0,0 +1,46 @@ +/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (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.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Original Author: + * Ben Matthew Goodger + * + * Contributor(s): + */ + +var nsJSSupportsUtils = { + + createSupportsArray: function () + { + return nsJSComponentManager.createInstance("component://netscape/supports-array", + "nsISupportsArray"); + }, + + createSupportsWString: function () + { + return nsJSComponentManager.createInstance("component://netscape/supports-wstring", + "nsISupportsWString"); + }, + + createSupportsString: function () + { + return nsJSComponentManager.createInstance("component://netscape/supports-string", + "nsISupportsString"); + } + +}; \ No newline at end of file diff --git a/xpfe/global/resources/content/nsTransferable.js b/xpfe/global/resources/content/nsTransferable.js new file mode 100644 index 00000000000..6713cb04d57 --- /dev/null +++ b/xpfe/global/resources/content/nsTransferable.js @@ -0,0 +1,192 @@ +/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (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.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Original Author: + * Ben Matthew Goodger + * + * Contributor(s): + */ + +/** + * nsTransferable - a wrapper for nsITransferable that simplifies + * javascript clipboard and drag&drop. for use in + * these situations you should use the nsClipboard + * and nsDragAndDrop wrappers for more convenience + **/ + +var nsTransferable = { + + /** + * Flavour List Format: + * flavourList["text/unicode"].width // width of data + * flavourList["text/unicode"].iid // iid of data type + * flavourList["text/unicode"].data // data to be stored (if any) + **/ + + /** + * nsITransferable set (Object aFlavourList) ; + * + * Creates a transferable with data for a list of supported types ("flavours") + * + * @param Object aFlavourList + * a javascript object in the format described above + **/ + set: function (aFlavourList) + { + var trans = this.createTransferable(); + for (var flavour in aFlavourList) + { + trans.addDataFlavor(flavour); + var width = aFlavourList[flavour].width; + var wrapper = this.createEmptyWrapper(width); + if (wrapper) + { + wrapper.data = aFlavourList[flavour].data; + trans.setTransferData(flavour, wrapper, wrapper.data.length * width); + } + } + return trans; + }, + + /** + * Array/Object get (Object aFlavourList, Function aRetrievalFunc, Boolean aAnyFlag) ; + * + * Retrieves data from the transferable provided in aRetrievalFunc, formatted + * for more convenient access. + * + * @param Object aFlavourList + * a javascript object in the format described above + * @param Function aRetrievalFunc + * a reference to a function that returns a nsISupportsArray of nsITransferables + * for each item from the specified source (clipboard/drag&drop etc) + * @param Boolean aAnyFlag + * a flag specifying whether or not a specific flavour is requested. If false, + * data of the type of the first flavour in the flavourlist parameter is returned, + * otherwise the best flavour supported will be returned. + **/ + get: function (aFlavourList, aRetrievalFunc, aAnyFlag) + { + var firstFlavour = null; + for (var flavour in aFlavourList) + { + firstFlavour = flavour; + break; + } + + if (aRetrievalFunc) + { + var supportsArray = aRetrievalFunc(aFlavourList); + var dataArray = []; + for (var i = 0; i < supportsArray.Count(); i++) + { + trans = supportsArray.GetElementAt(i); + if (trans) + trans = trans.QueryInterface(Components.interfaces.nsITransferable); + + var data = { }; + var flavour = { }; + var length = { }; + + if (aAnyFlag) + { + trans.getAnyTransferData(flavour, data, length); + if (data && flavour) + { + var selectedFlavour = aFlavourList[flavour.value]; + if (selectedFlavour) + { + data = data.value.QueryInterface(Components.interfaces[selectedFlavour.iid]); + var currData = + { + data: { data: data, length: length.value, width: selectedFlavour.width }, // this.wrapData(data.value, length.value, selectedFlavour.width), + flavour: flavour.value + }; + if (supportsArray.Count() == 1) + return currData; + else + dataArray[i] = currData; + } + } + dataArray[i] = null; + } + else + { + trans.getTransferData(firstFlavour, data, length); + var currData = data ? this.wrapData(data.value, length.value, aFlavourList[firstFlavour].width) : null; + if (supportsArray.Count() == 1) + return currData; + else + dataArray[i] = currData; + } + } + return dataArray; + } + else + throw "No data retrieval handler provided!"; + }, + + /** + * nsITransferable createTransferable (void) ; + * + * Creates and returns a transferable object. + **/ + createTransferable: function () + { + return nsJSComponentManager.createInstance("component://netscape/widget/transferable", + "nsITransferable"); + }, + + /** + * nsISupports createEmptyWrapper (int aWidth) ; + * + * Creates a wrapper for string data. XXX - this is bad, we're assuming the data we're + * dragging is string. + * + * @param int aWidth + * the width of the data (single or double byte) + **/ + createEmptyWrapper: function (aWidth) + { + return aWidth == 2 ? nsJSSupportsUtils.createSupportsWString() : + nsJSSupportsUtils.createSupportsString(); + + }, + + /** + * String wrapData (Object aDataObject, int aLength, int aWidth) + * + * Returns the actual string representation of nsISupports[W]String wrapped + * data. + * + * @param Object aDataObject + * the data to be unwrapped + * @param int aLength + * the integer length of the data + * @param int aWidth + * the unit size + **/ + wrapData: function (aDataObject, aLength, aWidth) + { + const IID = aWidth == 2 ? Components.interfaces.nsISupportsWString : + Components.interfaces.nsISupportsString; + var data = aDataObject.QueryInterface(IID); + if (data) + return data.data.substring(0, aLength / aWidth); + }, +};