2010-12-06 07:04:52 -05:00
|
|
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
|
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
|
|
|
*
|
|
|
|
|
* The contents of this file are subject to the Mozilla 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/MPL/
|
|
|
|
|
*
|
|
|
|
|
* 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 the Tree Style Tab.
|
|
|
|
|
*
|
|
|
|
|
* The Initial Developer of the Original Code is SHIMODA Hiroshi.
|
2011-01-23 19:13:23 -05:00
|
|
|
|
* Portions created by the Initial Developer are Copyright (C) 2010-2011
|
2010-12-06 07:04:52 -05:00
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
|
*
|
|
|
|
|
* Contributor(s): SHIMODA Hiroshi <piro@p.club.ne.jp>
|
|
|
|
|
*
|
|
|
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
|
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
|
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
|
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
|
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
|
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
|
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
|
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
|
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
|
|
|
* the provisions above, a recipient may use your version of this file under
|
|
|
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
|
|
|
*
|
|
|
|
|
* ***** END LICENSE BLOCK ******/
|
|
|
|
|
|
2011-01-22 09:43:55 -05:00
|
|
|
|
const EXPORTED_SYMBOLS = ['TabbarDNDObserver'];
|
2010-12-06 07:04:52 -05:00
|
|
|
|
|
|
|
|
|
const Cc = Components.classes;
|
|
|
|
|
const Ci = Components.interfaces;
|
|
|
|
|
|
|
|
|
|
const TAB_DROP_TYPE = 'application/x-moz-tabbrowser-tab';
|
|
|
|
|
|
|
|
|
|
const SSS = Cc['@mozilla.org/content/style-sheet-service;1']
|
|
|
|
|
.getService(Ci.nsIStyleSheetService);
|
|
|
|
|
const SecMan = Cc['@mozilla.org/scriptsecuritymanager;1']
|
|
|
|
|
.getService(Ci.nsIScriptSecurityManager);
|
|
|
|
|
const IOService = Cc['@mozilla.org/network/io-service;1']
|
|
|
|
|
.getService(Ci.nsIIOService);
|
|
|
|
|
|
2010-12-06 08:31:58 -05:00
|
|
|
|
function TabbarDNDObserver(aTabBrowser)
|
2009-09-02 21:26:38 -04:00
|
|
|
|
{
|
2010-12-06 08:31:58 -05:00
|
|
|
|
this.init(aTabBrowser);
|
2009-09-02 21:26:38 -04:00
|
|
|
|
}
|
|
|
|
|
|
2010-12-06 07:04:52 -05:00
|
|
|
|
TabbarDNDObserver.prototype = {
|
2009-09-03 02:20:45 -04:00
|
|
|
|
|
2010-12-06 07:04:52 -05:00
|
|
|
|
readyToStartTabbarDrag : function TabbarDND_readyToStartTabbarDrag()
|
2009-09-02 21:26:38 -04:00
|
|
|
|
{
|
2010-12-06 07:04:52 -05:00
|
|
|
|
var sheet = this.treeStyleTab.makeURIFromSpec('chrome://treestyletab/content/hide-embed.css');
|
|
|
|
|
if (!SSS.sheetRegistered(sheet, SSS.AGENT_SHEET))
|
|
|
|
|
SSS.loadAndRegisterSheet(sheet, SSS.AGENT_SHEET);
|
2010-12-01 10:15:40 -05:00
|
|
|
|
},
|
|
|
|
|
|
2010-12-06 07:04:52 -05:00
|
|
|
|
readyToEndTabbarDrag : function TabbarDND_readyToEndTabbarDrag()
|
2010-12-01 10:15:40 -05:00
|
|
|
|
{
|
2010-12-06 07:04:52 -05:00
|
|
|
|
var sheet = this.treeStyleTab.makeURIFromSpec('chrome://treestyletab/content/hide-embed.css');
|
|
|
|
|
if (SSS.sheetRegistered(sheet, SSS.AGENT_SHEET))
|
|
|
|
|
SSS.unregisterSheet(sheet, SSS.AGENT_SHEET);
|
2010-12-01 10:15:40 -05:00
|
|
|
|
},
|
|
|
|
|
|
2010-12-06 07:04:52 -05:00
|
|
|
|
canDragTabbar : function TabbarDND_canDragTabbar(aEvent)
|
2010-12-01 10:15:40 -05:00
|
|
|
|
{
|
2010-12-06 07:04:52 -05:00
|
|
|
|
var sv = this.treeStyleTab;
|
2009-09-03 04:24:22 -04:00
|
|
|
|
|
2010-04-21 07:03:05 -04:00
|
|
|
|
if (
|
|
|
|
|
sv.evaluateXPath(
|
2009-09-03 14:06:23 -04:00
|
|
|
|
'ancestor-or-self::*[contains(" scrollbar popup menupopup panel tooltip ", concat(" ", local-name(), " "))]',
|
2009-09-03 04:24:22 -04:00
|
|
|
|
aEvent.originalTarget,
|
2010-12-06 07:04:52 -05:00
|
|
|
|
Ci.nsIDOMXPathResult.BOOLEAN_TYPE
|
2010-04-21 07:03:05 -04:00
|
|
|
|
).booleanValue ||
|
2010-04-21 07:43:13 -04:00
|
|
|
|
sv.isToolbarCustomizing
|
2010-04-21 07:03:05 -04:00
|
|
|
|
)
|
2009-09-03 04:24:22 -04:00
|
|
|
|
return false;
|
|
|
|
|
|
2009-09-02 21:26:38 -04:00
|
|
|
|
var tab = sv.getTabFromEvent(aEvent);
|
|
|
|
|
var tabbar = sv.getTabbarFromEvent(aEvent);
|
2009-09-03 21:42:32 -04:00
|
|
|
|
var canDrag = (
|
2009-09-02 21:26:38 -04:00
|
|
|
|
(tab ? aEvent.shiftKey : tabbar ) &&
|
|
|
|
|
(
|
|
|
|
|
aEvent.shiftKey ||
|
2010-12-06 07:04:52 -05:00
|
|
|
|
sv.browser.getAttribute(sv.kFIXED) != 'true'
|
2009-09-02 21:26:38 -04:00
|
|
|
|
)
|
|
|
|
|
);
|
2009-09-03 21:42:32 -04:00
|
|
|
|
|
|
|
|
|
if (canDrag && !aEvent.shiftKey) {
|
|
|
|
|
let insensitiveArea = sv.getTreePref('tabbar.fixed.insensitiveArea');
|
|
|
|
|
let box = tabbar.boxObject;
|
2011-01-22 10:46:29 -05:00
|
|
|
|
switch (sv.position)
|
2009-09-03 21:42:32 -04:00
|
|
|
|
{
|
|
|
|
|
case 'right':
|
|
|
|
|
if (aEvent.screenX < box.screenX + insensitiveArea)
|
|
|
|
|
canDrag = false;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'left':
|
|
|
|
|
if (aEvent.screenX > box.screenX + box.width - insensitiveArea)
|
|
|
|
|
canDrag = false;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
case 'top':
|
|
|
|
|
if (aEvent.screenY > box.screenY + box.height - insensitiveArea)
|
|
|
|
|
canDrag = false;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'bottom':
|
|
|
|
|
if (aEvent.screenY < box.screenY + insensitiveArea)
|
|
|
|
|
canDrag = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return canDrag;
|
2009-09-02 21:26:38 -04:00
|
|
|
|
},
|
|
|
|
|
|
2010-12-06 07:04:52 -05:00
|
|
|
|
canDrop : function TabbarDND_canDrop(aEvent)
|
2009-11-23 13:04:40 -05:00
|
|
|
|
{
|
2010-12-06 07:04:52 -05:00
|
|
|
|
var sv = this.treeStyleTab;
|
2010-12-01 10:15:40 -05:00
|
|
|
|
var tooltip = sv.tabStrip.firstChild;
|
|
|
|
|
if (tooltip &&
|
|
|
|
|
tooltip.localName == 'tooltip' &&
|
|
|
|
|
tooltip.popupBoxObject.popupState != 'closed')
|
|
|
|
|
tooltip.hidePopup();
|
|
|
|
|
|
2010-12-01 19:00:39 -05:00
|
|
|
|
var dropAction = this.getDropAction(aEvent);
|
2010-12-01 10:15:40 -05:00
|
|
|
|
if ('dataTransfer' in aEvent) {
|
|
|
|
|
var dt = aEvent.dataTransfer;
|
2010-12-01 19:00:39 -05:00
|
|
|
|
if (dropAction.action & sv.kACTION_NEWTAB) {
|
2010-12-01 10:15:40 -05:00
|
|
|
|
dt.effectAllowed = dt.dropEffect = (
|
|
|
|
|
!dropAction.source ? 'link' :
|
|
|
|
|
sv.isCopyAction(aEvent) ? 'copy' :
|
|
|
|
|
'move'
|
|
|
|
|
);
|
2009-11-23 13:04:40 -05:00
|
|
|
|
}
|
|
|
|
|
}
|
2010-12-01 10:15:40 -05:00
|
|
|
|
return dropAction.canDrop;
|
2009-11-23 13:04:40 -05:00
|
|
|
|
},
|
2010-12-01 10:15:40 -05:00
|
|
|
|
|
2010-12-06 07:04:52 -05:00
|
|
|
|
canDropTab : function TabbarDND_canDropTab(aEvent)
|
2009-11-23 13:04:40 -05:00
|
|
|
|
{
|
2010-12-01 10:15:40 -05:00
|
|
|
|
try{
|
2010-12-06 07:04:52 -05:00
|
|
|
|
var sv = this.treeStyleTab;
|
|
|
|
|
var b = this.browser;
|
2010-12-01 10:15:40 -05:00
|
|
|
|
|
2010-12-01 19:02:27 -05:00
|
|
|
|
var session = sv.currentDragSession;
|
2010-12-01 10:15:40 -05:00
|
|
|
|
var node = session.sourceNode;
|
|
|
|
|
var tab = sv.getTabFromChild(node);
|
|
|
|
|
if (!node ||
|
|
|
|
|
!tab ||
|
|
|
|
|
tab.parentNode != b.mTabContainer)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
tab = sv.getTabFromEvent(aEvent);
|
|
|
|
|
if (sv.isCollapsed(tab))
|
|
|
|
|
return false;
|
|
|
|
|
|
2010-12-01 19:00:39 -05:00
|
|
|
|
var info = this.getDropAction(aEvent, session);
|
2010-12-01 10:15:40 -05:00
|
|
|
|
return info.canDrop;
|
|
|
|
|
}
|
|
|
|
|
catch(e) {
|
2010-12-06 07:04:52 -05:00
|
|
|
|
dump('TabbarDND::canDrop\n'+e+'\n');
|
2010-12-01 10:15:40 -05:00
|
|
|
|
return false;
|
|
|
|
|
}
|
2009-11-23 13:04:40 -05:00
|
|
|
|
},
|
2010-12-01 10:15:40 -05:00
|
|
|
|
|
2010-12-06 07:04:52 -05:00
|
|
|
|
getDropAction : function TabbarDND_getDropAction(aEvent, aDragSession)
|
2010-12-01 19:00:39 -05:00
|
|
|
|
{
|
2010-12-06 07:04:52 -05:00
|
|
|
|
var sv = this.treeStyleTab;
|
|
|
|
|
var b = this.browser;
|
2010-12-01 19:00:39 -05:00
|
|
|
|
|
|
|
|
|
if (!aDragSession)
|
2010-12-01 19:02:27 -05:00
|
|
|
|
aDragSession = sv.currentDragSession;
|
2010-12-01 19:00:39 -05:00
|
|
|
|
|
|
|
|
|
var tab = aDragSession ? sv.getTabFromChild(aDragSession.sourceNode) : null ;
|
|
|
|
|
sv.ensureTabInitialized(tab);
|
|
|
|
|
|
|
|
|
|
var info = this.getDropActionInternal(aEvent, tab);
|
|
|
|
|
info.canDrop = true;
|
|
|
|
|
info.source = tab;
|
|
|
|
|
if (tab) {
|
|
|
|
|
var isCopy = sv.isCopyAction(aEvent);
|
|
|
|
|
if (isCopy && 'duplicateTab' in b) {
|
|
|
|
|
info.action |= sv.kACTION_DUPLICATE;
|
|
|
|
|
}
|
|
|
|
|
if (
|
|
|
|
|
!isCopy &&
|
|
|
|
|
sv.getTabBrowserFromChild(tab) != b &&
|
|
|
|
|
(
|
2011-01-19 11:31:22 -05:00
|
|
|
|
('duplicateTab' in b)
|
2010-12-01 19:00:39 -05:00
|
|
|
|
)
|
|
|
|
|
) {
|
|
|
|
|
info.action |= sv.kACTION_IMPORT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (info.action & sv.kACTIONS_FOR_DESTINATION) {
|
|
|
|
|
if (info.action & sv.kACTION_MOVE) info.action ^= sv.kACTION_MOVE;
|
|
|
|
|
if (info.action & sv.kACTION_STAY) info.action ^= sv.kACTION_STAY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (info.action & sv.kACTION_ATTACH) {
|
|
|
|
|
if (info.parent == tab) {
|
|
|
|
|
info.canDrop = false;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
var orig = tab;
|
|
|
|
|
tab = info.target;
|
|
|
|
|
while (tab = sv.getParentTab(tab))
|
|
|
|
|
{
|
|
|
|
|
if (tab != orig) continue;
|
|
|
|
|
info.canDrop = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-03-23 14:30:01 -04:00
|
|
|
|
|
2011-05-16 13:23:38 -04:00
|
|
|
|
var isInverted = sv.isVertical ? false : b.ownerDocument.defaultView.getComputedStyle(b.parentNode, null).direction == 'rtl';
|
2011-03-23 14:30:01 -04:00
|
|
|
|
if (
|
|
|
|
|
info.target &&
|
|
|
|
|
(
|
|
|
|
|
info.target.hidden ||
|
2011-05-16 13:23:38 -04:00
|
|
|
|
(
|
|
|
|
|
sv.isCollapsed(info.target) &&
|
|
|
|
|
info.position != (isInverted ? sv.kDROP_BEFORE : sv.kDROP_AFTER )
|
|
|
|
|
)
|
2011-03-23 14:30:01 -04:00
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
info.canDrop = false;
|
|
|
|
|
|
2010-12-01 19:00:39 -05:00
|
|
|
|
return info;
|
|
|
|
|
},
|
|
|
|
|
|
2010-12-06 07:04:52 -05:00
|
|
|
|
getDropActionInternal : function TabbarDND_getDropActionInternal(aEvent, aSourceTab)
|
2010-12-01 19:00:39 -05:00
|
|
|
|
{
|
2010-12-06 07:04:52 -05:00
|
|
|
|
var sv = this.treeStyleTab;
|
|
|
|
|
var b = this.browser;
|
|
|
|
|
var d = this.document;
|
2010-12-01 19:00:39 -05:00
|
|
|
|
|
|
|
|
|
var tab = aEvent.target;
|
|
|
|
|
var tabs = sv.getTabsArray(b);
|
2010-12-06 22:40:41 -05:00
|
|
|
|
var firstTab = sv.getFirstNormalTab(b) || tabs[0];
|
2011-05-16 13:23:38 -04:00
|
|
|
|
var lastTabIndex = tabs.length - 1;
|
2010-12-06 07:04:52 -05:00
|
|
|
|
var isInverted = sv.isVertical ? false : b.ownerDocument.defaultView.getComputedStyle(b.parentNode, null).direction == 'rtl';
|
2010-12-01 19:00:39 -05:00
|
|
|
|
var info = {
|
|
|
|
|
target : null,
|
|
|
|
|
position : null,
|
|
|
|
|
action : null,
|
|
|
|
|
parent : null,
|
|
|
|
|
insertBefore : null,
|
|
|
|
|
event : aEvent
|
|
|
|
|
};
|
|
|
|
|
|
2010-12-06 07:04:52 -05:00
|
|
|
|
var isTabMoveFromOtherWindow = aSourceTab && aSourceTab.ownerDocument != d;
|
|
|
|
|
var isNewTabAction = !aSourceTab || aSourceTab.ownerDocument != d;
|
2010-12-01 19:00:39 -05:00
|
|
|
|
|
|
|
|
|
if (tab.localName != 'tab') {
|
2011-05-16 13:23:38 -04:00
|
|
|
|
let action = isTabMoveFromOtherWindow ? sv.kACTION_STAY : (sv.kACTION_MOVE | sv.kACTION_PART) ;
|
2010-12-01 19:00:39 -05:00
|
|
|
|
if (isNewTabAction) action |= sv.kACTION_NEWTAB;
|
|
|
|
|
if (aEvent[sv.positionProp] < firstTab.boxObject[sv.positionProp]) {
|
|
|
|
|
info.target = info.parent = info.insertBefore = firstTab;
|
|
|
|
|
info.position = isInverted ? sv.kDROP_AFTER : sv.kDROP_BEFORE ;
|
|
|
|
|
info.action = action;
|
|
|
|
|
return info;
|
|
|
|
|
}
|
|
|
|
|
else if (aEvent[sv.positionProp] > tabs[lastTabIndex].boxObject[sv.positionProp] + tabs[lastTabIndex].boxObject[sv.sizeProp]) {
|
|
|
|
|
info.target = info.parent = tabs[lastTabIndex];
|
|
|
|
|
info.position = isInverted ? sv.kDROP_BEFORE : sv.kDROP_AFTER ;
|
|
|
|
|
info.action = action;
|
|
|
|
|
return info;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
let index = b.getNewIndex ?
|
|
|
|
|
b.getNewIndex(aEvent) :
|
|
|
|
|
b.tabContainer._getDropIndex(aEvent) ;
|
|
|
|
|
info.target = tabs[Math.min(index, lastTabIndex)];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
sv.ensureTabInitialized(tab);
|
|
|
|
|
info.target = tab;
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-18 16:14:17 -04:00
|
|
|
|
/**
|
|
|
|
|
* Basically, tabs should have three areas for dropping of items:
|
|
|
|
|
* [start][center][end], but, pinned tabs couldn't have its tree.
|
|
|
|
|
* So, if a tab is dragged and the target tab is pinned, then, we
|
|
|
|
|
* have to ignore the [center] area.
|
|
|
|
|
*/
|
|
|
|
|
var pinned = tab.getAttribute('pinned') == 'true';
|
|
|
|
|
var dropAreasCount = (aSourceTab && pinned) ? 2 : 3 ;
|
|
|
|
|
var positionProp = sv.isVertical && pinned ? sv.invertedPositionProp : sv.positionProp ;
|
|
|
|
|
var sizeProp = sv.isVertical && pinned ? sv.invertedSizeProp : sv.sizeProp ;
|
2010-12-01 19:00:39 -05:00
|
|
|
|
var boxPos = tab.boxObject[positionProp];
|
2011-03-18 16:14:17 -04:00
|
|
|
|
var boxUnit = Math.round(tab.boxObject[sizeProp] / dropAreasCount);
|
2010-12-01 19:00:39 -05:00
|
|
|
|
if (aEvent[positionProp] < boxPos + boxUnit) {
|
|
|
|
|
info.position = isInverted ? sv.kDROP_AFTER : sv.kDROP_BEFORE ;
|
|
|
|
|
}
|
2011-03-18 16:14:17 -04:00
|
|
|
|
else if (dropAreasCount == 2 || aEvent[positionProp] > boxPos + boxUnit + boxUnit) {
|
2010-12-01 19:00:39 -05:00
|
|
|
|
info.position = isInverted ? sv.kDROP_BEFORE : sv.kDROP_AFTER ;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
info.position = sv.kDROP_ON;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (info.position)
|
|
|
|
|
{
|
|
|
|
|
case sv.kDROP_ON:
|
2011-03-18 16:14:17 -04:00
|
|
|
|
var visible = sv.getNextVisibleTab(tab);
|
2010-12-01 19:00:39 -05:00
|
|
|
|
info.action = sv.kACTION_STAY | sv.kACTION_ATTACH;
|
|
|
|
|
info.parent = tab;
|
|
|
|
|
info.insertBefore = sv.getTreePref('insertNewChildAt') == sv.kINSERT_FISRT ?
|
|
|
|
|
(sv.getFirstChildTab(tab) || visible) :
|
|
|
|
|
(sv.getNextSiblingTab(tab) || sv.getNextTab(sv.getLastDescendantTab(tab)) || visible);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case sv.kDROP_BEFORE:
|
|
|
|
|
/*
|
|
|
|
|
[TARGET ] <EFBFBD><EFBFBD>part from parent, and move
|
|
|
|
|
|
|
|
|
|
[ ]
|
|
|
|
|
[TARGET ] <EFBFBD><EFBFBD>attach to the parent of the target, and move
|
|
|
|
|
|
|
|
|
|
[ ]
|
|
|
|
|
[TARGET ] <EFBFBD><EFBFBD>attach to the parent of the target, and move
|
|
|
|
|
|
|
|
|
|
[ ]
|
|
|
|
|
[TARGET] <EFBFBD><EFBFBD>attach to the parent of the target (previous tab), and move
|
|
|
|
|
*/
|
|
|
|
|
var prevTab = sv.getPreviousVisibleTab(tab);
|
|
|
|
|
if (!prevTab) {
|
|
|
|
|
info.action = sv.kACTION_MOVE | sv.kACTION_PART;
|
|
|
|
|
info.insertBefore = firstTab;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
var prevLevel = Number(prevTab.getAttribute(sv.kNEST));
|
|
|
|
|
var targetNest = Number(tab.getAttribute(sv.kNEST));
|
|
|
|
|
info.parent = (prevLevel < targetNest) ? prevTab : sv.getParentTab(tab) ;
|
|
|
|
|
info.action = sv.kACTION_MOVE | (info.parent ? sv.kACTION_ATTACH : sv.kACTION_PART );
|
|
|
|
|
info.insertBefore = tab;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case sv.kDROP_AFTER:
|
|
|
|
|
/*
|
|
|
|
|
[TARGET ] <EFBFBD><EFBFBD>if the target has a parent, attach to it and and move
|
|
|
|
|
|
|
|
|
|
[TARGET] <EFBFBD><EFBFBD>attach to the parent of the target, and move
|
|
|
|
|
[ ]
|
|
|
|
|
|
|
|
|
|
[TARGET ] <EFBFBD><EFBFBD>attach to the parent of the target, and move
|
|
|
|
|
[ ]
|
|
|
|
|
|
|
|
|
|
[TARGET ] <EFBFBD><EFBFBD>attach to the target, and move
|
|
|
|
|
[ ]
|
|
|
|
|
*/
|
|
|
|
|
var nextTab = sv.getNextVisibleTab(tab);
|
|
|
|
|
if (!nextTab) {
|
|
|
|
|
info.action = sv.kACTION_MOVE | sv.kACTION_ATTACH;
|
|
|
|
|
info.parent = sv.getParentTab(tab);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
var targetNest = Number(tab.getAttribute(sv.kNEST));
|
|
|
|
|
var nextLevel = Number(nextTab.getAttribute(sv.kNEST));
|
|
|
|
|
info.parent = (targetNest < nextLevel) ? tab : sv.getParentTab(tab) ;
|
|
|
|
|
info.action = sv.kACTION_MOVE | (info.parent ? sv.kACTION_ATTACH : sv.kACTION_PART );
|
|
|
|
|
info.insertBefore = nextTab;
|
|
|
|
|
/*
|
|
|
|
|
[TARGET ] <EFBFBD><EFBFBD>attach dragged tab to the parent of the target as its next sibling
|
|
|
|
|
[DRAGGED]
|
|
|
|
|
*/
|
|
|
|
|
if (aSourceTab == nextTab && sv.getDescendantTabs(info.parent).length == 1) {
|
|
|
|
|
info.action = sv.kACTION_MOVE | sv.kACTION_ATTACH;
|
|
|
|
|
info.parent = sv.getParentTab(tab);
|
|
|
|
|
info.insertBefore = sv.getNextTab(nextTab);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-25 23:17:48 -04:00
|
|
|
|
if (isNewTabAction) info.action |= sv.kACTION_NEWTAB;
|
2010-12-01 19:00:39 -05:00
|
|
|
|
|
|
|
|
|
return info;
|
|
|
|
|
},
|
|
|
|
|
|
2010-12-06 07:04:52 -05:00
|
|
|
|
performDrop : function TabbarDND_performDrop(aInfo, aDraggedTab)
|
2010-12-01 19:00:39 -05:00
|
|
|
|
{
|
2010-12-06 07:04:52 -05:00
|
|
|
|
var sv = this.treeStyleTab;
|
|
|
|
|
var b = this.browser;
|
|
|
|
|
var w = this.window;
|
2010-12-01 19:00:39 -05:00
|
|
|
|
|
|
|
|
|
var tabsInfo = this.getDraggedTabsInfoFromOneTab(aInfo, aDraggedTab);
|
|
|
|
|
if (!tabsInfo.draggedTab) return false;
|
|
|
|
|
|
|
|
|
|
aDraggedTab = tabsInfo.draggedTab;
|
|
|
|
|
var draggedTabs = tabsInfo.draggedTabs;
|
|
|
|
|
var draggedRoots = tabsInfo.draggedRoots;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var targetBrowser = b;
|
|
|
|
|
var tabs = sv.getTabsArray(targetBrowser);
|
|
|
|
|
|
|
|
|
|
var sourceWindow = aDraggedTab.ownerDocument.defaultView;
|
|
|
|
|
var sourceBrowser = sv.getTabBrowserFromChild(aDraggedTab);
|
|
|
|
|
|
|
|
|
|
var draggedWholeTree = [].concat(draggedRoots);
|
2011-05-16 20:24:19 -04:00
|
|
|
|
for each (let root in draggedRoots)
|
|
|
|
|
{
|
|
|
|
|
let tabs = sv.getDescendantTabs(root);
|
|
|
|
|
for each (let tab in tabs)
|
|
|
|
|
{
|
|
|
|
|
if (draggedWholeTree.indexOf(tab) < 0)
|
|
|
|
|
draggedWholeTree.push(tab);
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-04-07 23:15:42 -04:00
|
|
|
|
|
|
|
|
|
var selectedTabs = draggedTabs.filter(function(aTab) {
|
|
|
|
|
return aTab.getAttribute('multiselected') == 'true';
|
|
|
|
|
});
|
|
|
|
|
if (draggedWholeTree.length != selectedTabs.length &&
|
|
|
|
|
selectedTabs.length) {
|
|
|
|
|
draggedTabs = draggedRoots = selectedTabs;
|
2011-05-16 20:24:19 -04:00
|
|
|
|
if (aInfo.action & sv.kACTIONS_FOR_SOURCE) {
|
|
|
|
|
for each (let tab in Array.slice(selectedTabs))
|
|
|
|
|
{
|
|
|
|
|
if (selectedTabs.indexOf(sv.getParentTab(tab)) > -1)
|
|
|
|
|
continue;
|
|
|
|
|
sv.partAllChildren(tab, {
|
2011-04-07 23:15:42 -04:00
|
|
|
|
behavior : sv.getCloseParentBehaviorForTab(
|
2011-05-16 20:24:19 -04:00
|
|
|
|
tab,
|
2011-04-07 23:15:42 -04:00
|
|
|
|
sv.kCLOSE_PARENT_BEHAVIOR_PROMOTE_FIRST_CHILD
|
|
|
|
|
)
|
|
|
|
|
});
|
2011-05-16 20:24:19 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
2011-04-07 23:15:42 -04:00
|
|
|
|
}
|
|
|
|
|
|
2010-12-01 19:00:39 -05:00
|
|
|
|
while (aInfo.insertBefore && draggedWholeTree.indexOf(aInfo.insertBefore) > -1)
|
|
|
|
|
{
|
|
|
|
|
aInfo.insertBefore = sv.getNextTab(aInfo.insertBefore);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (aInfo.action & sv.kACTIONS_FOR_SOURCE) {
|
|
|
|
|
if (aInfo.action & sv.kACTION_PART) {
|
|
|
|
|
this.partTabsOnDrop(draggedRoots);
|
|
|
|
|
}
|
|
|
|
|
else if (aInfo.action & sv.kACTION_ATTACH) {
|
|
|
|
|
this.attachTabsOnDrop(draggedRoots, aInfo.parent);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( // if this move will cause no change...
|
|
|
|
|
sourceBrowser == targetBrowser &&
|
|
|
|
|
sourceBrowser.treeStyleTab.getNextVisibleTab(draggedTabs[draggedTabs.length-1]) == aInfo.insertBefore
|
|
|
|
|
) {
|
|
|
|
|
// then, do nothing
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// prevent Multiple Tab Handler feature
|
|
|
|
|
targetBrowser.duplicatingSelectedTabs = true;
|
|
|
|
|
targetBrowser.movingSelectedTabs = true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var newRoots = [];
|
|
|
|
|
var shouldClose = (
|
|
|
|
|
aInfo.action & sv.kACTION_IMPORT &&
|
|
|
|
|
sv.getAllTabsArray(sourceBrowser).length == draggedTabs.length
|
|
|
|
|
);
|
|
|
|
|
var oldTabs = [];
|
|
|
|
|
var newTabs = [];
|
|
|
|
|
var treeStructure = draggedTabs.map(function(aTab) {
|
|
|
|
|
var parent = sourceBrowser.treeStyleTab.getParentTab(aTab);
|
|
|
|
|
return parent ? draggedTabs.indexOf(parent) : -1 ;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
var parentTabsArray = draggedTabs.map(function(aTab) {
|
|
|
|
|
return (aInfo.action & sv.kACTIONS_FOR_DESTINATION) ?
|
|
|
|
|
sourceBrowser.treeStyleTab.getParentTab(aTab) : null ;
|
|
|
|
|
}, this);
|
|
|
|
|
|
|
|
|
|
// Firefox fails to "move" collapsed tabs. So, expand them first
|
|
|
|
|
// and collapse them after they are moved.
|
|
|
|
|
var collapseExpandState = [];
|
2011-01-23 23:27:41 -05:00
|
|
|
|
if (aInfo.action & sv.kACTION_MOVE || aInfo.action & sv.kACTION_IMPORT) {
|
2011-05-16 20:24:19 -04:00
|
|
|
|
for each (let tab in draggedWholeTree)
|
|
|
|
|
{
|
|
|
|
|
collapseExpandState.push(sv.getTabValue(tab, sv.kSUBTREE_COLLAPSED) == 'true');
|
|
|
|
|
sv.collapseExpandSubtree(tab, false, true);
|
|
|
|
|
sv.collapseExpandTab(tab, false, true);
|
|
|
|
|
}
|
2010-12-01 19:00:39 -05:00
|
|
|
|
}
|
|
|
|
|
|
2011-05-16 13:23:38 -04:00
|
|
|
|
var lastTabIndex = tabs[tabs.length -1]._tPos;
|
2011-05-16 20:24:19 -04:00
|
|
|
|
for (let i in draggedTabs)
|
|
|
|
|
{
|
|
|
|
|
let tab = draggedTabs[i];
|
2010-12-01 19:00:39 -05:00
|
|
|
|
if (aInfo.action & sv.kACTIONS_FOR_DESTINATION) {
|
2011-05-16 20:24:19 -04:00
|
|
|
|
let parent = parentTabsArray[i];
|
2010-12-01 19:00:39 -05:00
|
|
|
|
if (tabsInfo.isMultipleMove && 'MultipleTabService' in sourceWindow)
|
|
|
|
|
sourceWindow.MultipleTabService.setSelection(aTab, false);
|
2011-01-19 11:31:22 -05:00
|
|
|
|
if (aInfo.action & sv.kACTION_IMPORT) {
|
2010-12-01 19:00:39 -05:00
|
|
|
|
tab = targetBrowser.addTab();
|
|
|
|
|
tab.linkedBrowser.stop();
|
|
|
|
|
tab.linkedBrowser.docShell;
|
|
|
|
|
targetBrowser.swapBrowsersAndCloseOther(tab, aTab);
|
|
|
|
|
targetBrowser.setTabTitle(tab);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
tab = targetBrowser.duplicateTab(aTab);
|
|
|
|
|
sv.deleteTabValue(tab, sv.kCHILDREN);
|
|
|
|
|
sv.deleteTabValue(tab, sv.kPARENT);
|
|
|
|
|
if (aInfo.action & sv.kACTION_IMPORT)
|
|
|
|
|
oldTabs.push(aTab);
|
|
|
|
|
}
|
|
|
|
|
newTabs.push(tab);
|
2010-12-06 07:04:52 -05:00
|
|
|
|
if (tabsInfo.isMultipleMove && 'MultipleTabService' in w)
|
2011-02-06 22:09:12 -05:00
|
|
|
|
w.MultipleTabService.setSelection(tab, true);
|
2010-12-01 19:00:39 -05:00
|
|
|
|
if (!parent || draggedTabs.indexOf(parent) < 0)
|
|
|
|
|
newRoots.push(tab);
|
|
|
|
|
lastTabIndex++;
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-16 20:24:19 -04:00
|
|
|
|
let newIndex = aInfo.insertBefore ? aInfo.insertBefore._tPos : lastTabIndex ;
|
2010-12-01 19:00:39 -05:00
|
|
|
|
if (aInfo.insertBefore && newIndex > tab._tPos) newIndex--;
|
|
|
|
|
|
|
|
|
|
sv.internallyTabMovingCount++;
|
|
|
|
|
targetBrowser.moveTabTo(tab, newIndex);
|
|
|
|
|
sv.collapseExpandTab(tab, false, true);
|
|
|
|
|
sv.internallyTabMovingCount--;
|
2011-05-16 20:24:19 -04:00
|
|
|
|
}
|
2010-12-01 19:00:39 -05:00
|
|
|
|
|
|
|
|
|
// close imported tabs from the source browser
|
2011-05-16 20:24:19 -04:00
|
|
|
|
for each (let tab in oldTabs)
|
|
|
|
|
{
|
2010-12-01 19:00:39 -05:00
|
|
|
|
sourceBrowser.removeTab(aTab, { animate : true });
|
2011-05-16 20:24:19 -04:00
|
|
|
|
}
|
2010-12-01 19:00:39 -05:00
|
|
|
|
if (shouldClose)
|
|
|
|
|
this.closeOwner(sourceBrowser);
|
|
|
|
|
|
|
|
|
|
// restore tree structure for newly opened tabs
|
2011-05-16 20:24:19 -04:00
|
|
|
|
for (let i in newTabs)
|
|
|
|
|
{
|
|
|
|
|
let index = treeStructure[i];
|
|
|
|
|
if (index < 0) continue;
|
|
|
|
|
sv.attachTabTo(newTabs[i], newTabs[index]);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (newTabs.length || aInfo.action & sv.kACTION_MOVE || aInfo.action & sv.kACTION_IMPORT) {
|
|
|
|
|
for (let i = collapseExpandState.length - 1; i > -1; i--)
|
|
|
|
|
{
|
|
|
|
|
let collapsed = collapseExpandState[i];
|
|
|
|
|
sv.collapseExpandSubtree(draggedWholeTree[i], collapsed, true);
|
|
|
|
|
if (newTabs.length)
|
|
|
|
|
sv.collapseExpandSubtree(newTabs[i], collapsed, true);
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-12-01 19:00:39 -05:00
|
|
|
|
|
|
|
|
|
if (aInfo.action & sv.kACTIONS_FOR_DESTINATION &&
|
|
|
|
|
aInfo.action & sv.kACTION_ATTACH)
|
|
|
|
|
this.attachTabsOnDrop(newRoots, aInfo.parent);
|
|
|
|
|
|
|
|
|
|
// Multiple Tab Handler
|
|
|
|
|
targetBrowser.movingSelectedTabs = false;
|
|
|
|
|
targetBrowser.duplicatingSelectedTabs = false;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
},
|
|
|
|
|
|
2010-12-06 07:04:52 -05:00
|
|
|
|
getDraggedTabsInfoFromOneTab : function TabbarDND_getDraggedTabsInfoFromOneTab(aInfo, aTab)
|
2010-12-01 19:00:39 -05:00
|
|
|
|
{
|
2010-12-06 07:04:52 -05:00
|
|
|
|
var sv = this.treeStyleTab;
|
|
|
|
|
var b = this.browser;
|
|
|
|
|
var w = this.window;
|
2010-12-01 19:00:39 -05:00
|
|
|
|
|
|
|
|
|
aTab = sv.getTabFromChild(aTab);
|
2011-02-09 18:58:28 -05:00
|
|
|
|
if (!aTab || !aTab.parentNode) // ignore removed tabs!
|
2010-12-01 19:00:39 -05:00
|
|
|
|
return {
|
|
|
|
|
draggedTab : null,
|
|
|
|
|
draggedTabs : [],
|
|
|
|
|
draggedRoots : [],
|
|
|
|
|
isMultipleMove : false
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var targetBrowser = b;
|
|
|
|
|
var tabs = sv.getTabsArray(targetBrowser);
|
|
|
|
|
|
|
|
|
|
var sourceWindow = aTab.ownerDocument.defaultView;
|
|
|
|
|
var sourceBrowser = sv.getTabBrowserFromChild(aTab);
|
|
|
|
|
|
2011-05-24 05:41:18 -04:00
|
|
|
|
var draggedTabs = w['piro.sakura.ne.jp'].tabsDragUtils.getSelectedTabs(aTab || sourceBrowser || aInfo.event);
|
2010-12-01 19:00:39 -05:00
|
|
|
|
var draggedRoots = [aTab];
|
|
|
|
|
var isMultipleMove = false;
|
|
|
|
|
|
|
|
|
|
if (draggedTabs.length > 1) {
|
|
|
|
|
isMultipleMove = true;
|
|
|
|
|
if (!(aInfo.action & sv.kACTIONS_FOR_DESTINATION)) {
|
|
|
|
|
draggedRoots = [];
|
|
|
|
|
draggedTabs.forEach(function(aTab) {
|
|
|
|
|
var parent = aTab,
|
|
|
|
|
current;
|
|
|
|
|
do {
|
|
|
|
|
current = parent;
|
|
|
|
|
parent = sourceBrowser.treeStyleTab.getParentTab(parent)
|
|
|
|
|
if (parent && draggedTabs.indexOf(parent) > -1) continue;
|
2011-04-07 23:15:42 -04:00
|
|
|
|
if (draggedRoots.indexOf(current) < 0)
|
|
|
|
|
draggedRoots.push(current);
|
2010-12-01 19:00:39 -05:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
while (parent);
|
|
|
|
|
}, this);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (aInfo.action & sv.kACTIONS_FOR_DESTINATION) {
|
|
|
|
|
draggedTabs = [aTab].concat(sourceBrowser.treeStyleTab.getDescendantTabs(aTab));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
draggedTab : aTab,
|
|
|
|
|
draggedTabs : draggedTabs,
|
|
|
|
|
draggedRoots : draggedRoots,
|
|
|
|
|
isMultipleMove : isMultipleMove
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
|
2010-12-06 07:04:52 -05:00
|
|
|
|
attachTabsOnDrop : function TabbarDND_attachTabsOnDrop(aTabs, aParent)
|
2010-12-01 19:00:39 -05:00
|
|
|
|
{
|
2010-12-06 07:04:52 -05:00
|
|
|
|
var sv = this.treeStyleTab;
|
|
|
|
|
var b = this.browser;
|
2010-12-01 19:00:39 -05:00
|
|
|
|
|
|
|
|
|
b.movingSelectedTabs = true; // Multiple Tab Handler
|
|
|
|
|
aTabs.forEach(function(aTab) {
|
|
|
|
|
if (!aTab.parentNode) return; // ignore removed tabs
|
|
|
|
|
if (aParent)
|
|
|
|
|
sv.attachTabTo(aTab, aParent);
|
|
|
|
|
else
|
|
|
|
|
sv.partTab(aTab);
|
|
|
|
|
sv.collapseExpandTab(aTab, false);
|
|
|
|
|
}, sv);
|
|
|
|
|
b.movingSelectedTabs = false; // Multiple Tab Handler
|
|
|
|
|
},
|
|
|
|
|
|
2010-12-06 07:04:52 -05:00
|
|
|
|
partTabsOnDrop : function TabbarDND_partTabsOnDrop(aTabs)
|
2010-12-01 19:00:39 -05:00
|
|
|
|
{
|
2010-12-06 07:04:52 -05:00
|
|
|
|
var sv = this.treeStyleTab;
|
|
|
|
|
var b = this.browser;
|
2010-12-01 19:00:39 -05:00
|
|
|
|
|
|
|
|
|
b.movingSelectedTabs = true; // Multiple Tab Handler
|
|
|
|
|
aTabs.forEach(function(aTab) {
|
|
|
|
|
if (!aTab.parentNode) return; // ignore removed tabs
|
|
|
|
|
sv.partTab(aTab);
|
|
|
|
|
sv.collapseExpandTab(aTab, false);
|
|
|
|
|
}, sv);
|
|
|
|
|
b.movingSelectedTabs = false; // Multiple Tab Handler
|
|
|
|
|
},
|
|
|
|
|
|
2010-12-06 07:04:52 -05:00
|
|
|
|
closeOwner : function TabbarDND_closeOwner(aTabOwner)
|
2010-12-01 19:00:39 -05:00
|
|
|
|
{
|
|
|
|
|
var w = aTabOwner.ownerDocument.defaultView;
|
|
|
|
|
if (!w) return;
|
|
|
|
|
if ('SplitBrowser' in w) {
|
|
|
|
|
if ('getSubBrowserFromChild' in w.SplitBrowser) {
|
|
|
|
|
var subbrowser = w.SplitBrowser.getSubBrowserFromChild(aTabOwner);
|
|
|
|
|
if (subbrowser) {
|
|
|
|
|
subbrowser.close();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (w.SplitBrowser.browsers.length) return;
|
|
|
|
|
}
|
|
|
|
|
w.close();
|
|
|
|
|
},
|
|
|
|
|
|
2010-12-06 07:04:52 -05:00
|
|
|
|
clearDropPosition : function TabbarDND_clearDropPosition()
|
2010-12-01 19:00:39 -05:00
|
|
|
|
{
|
2010-12-06 07:04:52 -05:00
|
|
|
|
var sv = this.treeStyleTab;
|
|
|
|
|
var b = this.browser;
|
2010-12-01 19:00:39 -05:00
|
|
|
|
var xpathResult = sv.evaluateXPath(
|
|
|
|
|
'child::xul:tab[@'+sv.kDROP_POSITION+']',
|
|
|
|
|
b.mTabContainer
|
|
|
|
|
);
|
|
|
|
|
for (var i = 0, maxi = xpathResult.snapshotLength; i < maxi; i++)
|
|
|
|
|
{
|
|
|
|
|
xpathResult.snapshotItem(i).removeAttribute(sv.kDROP_POSITION);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
2010-12-06 07:04:52 -05:00
|
|
|
|
isDraggingAllTabs : function TabbarDND_isDraggingAllTabs(aTab, aTabs)
|
2010-12-01 19:00:39 -05:00
|
|
|
|
{
|
2010-12-06 07:04:52 -05:00
|
|
|
|
var sv = this.treeStyleTab;
|
|
|
|
|
var b = this.browser;
|
2010-12-01 19:00:39 -05:00
|
|
|
|
|
|
|
|
|
var actionInfo = {
|
|
|
|
|
action : sv.kACTIONS_FOR_DESTINATION | sv.kACTION_IMPORT
|
|
|
|
|
};
|
|
|
|
|
var tabsInfo = this.getDraggedTabsInfoFromOneTab(actionInfo, aTab);
|
|
|
|
|
return tabsInfo.draggedTabs.length == (aTabs || sv.getAllTabsArray(b)).length;
|
|
|
|
|
},
|
|
|
|
|
|
2010-12-06 07:04:52 -05:00
|
|
|
|
isDraggingAllCurrentTabs : function TabbarDND_isDraggingAllCurrentTabs(aTab)
|
2010-12-01 19:00:39 -05:00
|
|
|
|
{
|
2011-02-06 22:09:12 -05:00
|
|
|
|
return this.isDraggingAllTabs(aTab, this.treeStyleTab.getTabsArray(this.treeStyleTab.browser));
|
2010-12-01 19:00:39 -05:00
|
|
|
|
},
|
|
|
|
|
|
2010-12-06 07:04:52 -05:00
|
|
|
|
handleEvent : function TabbarDND_handleEvent(aEvent)
|
2010-12-01 18:12:57 -05:00
|
|
|
|
{
|
2011-02-19 06:27:30 -05:00
|
|
|
|
// ignore drag and drop while toolbar customization (for Firefox 3.6)
|
|
|
|
|
if (this.treeStyleTab.isToolbarCustomizing)
|
|
|
|
|
return;
|
|
|
|
|
|
2010-12-01 18:12:57 -05:00
|
|
|
|
switch (aEvent.type)
|
|
|
|
|
{
|
|
|
|
|
case 'dragstart': return this.onDragStart(aEvent);
|
|
|
|
|
case 'dragenter': return this.onDragEnter(aEvent);
|
|
|
|
|
case 'dragleave': return this.onDragLeave(aEvent);
|
|
|
|
|
case 'dragend': return this.onDragEnd(aEvent);
|
|
|
|
|
case 'dragover': return this.onDragOver(aEvent);
|
|
|
|
|
case 'drop': return this.onDrop(aEvent);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
2010-12-06 07:04:52 -05:00
|
|
|
|
onDragStart : function TabbarDND_onDragStart(aEvent)
|
2009-11-23 13:04:40 -05:00
|
|
|
|
{
|
2010-12-01 10:15:40 -05:00
|
|
|
|
if (this.canDragTabbar(aEvent))
|
|
|
|
|
return this.onTabbarDragStart(aEvent);
|
|
|
|
|
|
2010-12-06 07:04:52 -05:00
|
|
|
|
var tab = this.treeStyleTab.getTabFromEvent(aEvent);
|
2010-12-01 10:15:40 -05:00
|
|
|
|
if (tab)
|
|
|
|
|
return this.onTabDragStart(aEvent, tab);
|
|
|
|
|
},
|
|
|
|
|
|
2010-12-06 07:04:52 -05:00
|
|
|
|
onTabDragStart : function TabbarDND_onTabDragStart(aEvent, aTab)
|
2010-12-01 10:15:40 -05:00
|
|
|
|
{
|
2010-12-06 07:04:52 -05:00
|
|
|
|
var sv = this.treeStyleTab;
|
|
|
|
|
var w = this.window;
|
2010-12-01 10:15:40 -05:00
|
|
|
|
var actionInfo = {
|
|
|
|
|
action : sv.kACTIONS_FOR_DESTINATION | sv.kACTION_MOVE,
|
|
|
|
|
event : aEvent
|
|
|
|
|
};
|
2010-12-01 19:00:39 -05:00
|
|
|
|
var tabsInfo = this.getDraggedTabsInfoFromOneTab(actionInfo, aTab);
|
2010-12-20 01:46:38 -05:00
|
|
|
|
if (
|
2011-04-26 13:44:19 -04:00
|
|
|
|
tabsInfo.draggedTabs.length <= 1 ||
|
|
|
|
|
Array.some(tabsInfo.draggedTabs, function(aTab) {
|
|
|
|
|
return aTab.getAttribute('multiselected') == 'true';
|
|
|
|
|
})
|
2010-12-20 02:24:47 -05:00
|
|
|
|
)
|
2011-04-26 13:44:19 -04:00
|
|
|
|
return;
|
2010-12-20 01:46:38 -05:00
|
|
|
|
|
|
|
|
|
w['piro.sakura.ne.jp'].tabsDragUtils.startTabsDrag(aEvent, tabsInfo.draggedTabs);
|
2009-11-23 13:04:40 -05:00
|
|
|
|
},
|
|
|
|
|
|
2010-12-06 07:04:52 -05:00
|
|
|
|
onTabbarDragStart : function TabbarDND_onTabbarDragStart(aEvent)
|
2010-12-01 10:15:40 -05:00
|
|
|
|
{
|
2010-12-06 07:04:52 -05:00
|
|
|
|
var sv = this.treeStyleTab;
|
2010-12-01 10:15:40 -05:00
|
|
|
|
var dt = aEvent.dataTransfer;
|
|
|
|
|
dt.mozSetDataAt(
|
|
|
|
|
sv.kDRAG_TYPE_TABBAR,
|
|
|
|
|
aEvent.shiftKey ?
|
|
|
|
|
sv.kTABBAR_MOVE_FORCE :
|
|
|
|
|
sv.kTABBAR_MOVE_NORMAL,
|
|
|
|
|
0
|
|
|
|
|
);
|
|
|
|
|
dt.mozCursor = 'move';
|
2010-12-06 07:04:52 -05:00
|
|
|
|
// var tabbar = sv.browser.mTabContainer;
|
2010-12-01 10:15:40 -05:00
|
|
|
|
// var box = tabbar.boxObject;
|
|
|
|
|
// dt.setDragImage(
|
|
|
|
|
// tabbar,
|
|
|
|
|
// aEvent.screenX - box.screenX,
|
|
|
|
|
// aEvent.screenY - box.screenY
|
|
|
|
|
// );
|
|
|
|
|
// no feedback image, because it's annoying...
|
2010-12-06 07:04:52 -05:00
|
|
|
|
dt.setDragImage(new this.window.Image(), 0, 0);
|
2010-12-01 10:15:40 -05:00
|
|
|
|
aEvent.stopPropagation();
|
|
|
|
|
this.readyToStartTabbarDrag();
|
|
|
|
|
},
|
|
|
|
|
|
2010-12-06 07:04:52 -05:00
|
|
|
|
onDragEnter : function TabbarDND_onDragEnter(aEvent)
|
2009-09-02 21:26:38 -04:00
|
|
|
|
{
|
2010-12-06 07:04:52 -05:00
|
|
|
|
var sv = this.treeStyleTab;
|
|
|
|
|
var w = this.window;
|
2010-12-01 10:15:40 -05:00
|
|
|
|
|
2010-06-13 08:21:49 -04:00
|
|
|
|
var dt = aEvent.dataTransfer;
|
2010-12-01 10:15:40 -05:00
|
|
|
|
if (!this.canDrop(aEvent)) {
|
|
|
|
|
dt.effectAllowed = dt.dropEffect = 'none';
|
|
|
|
|
return;
|
2011-05-24 05:41:18 -04:00
|
|
|
|
|
2011-05-25 23:17:48 -04:00
|
|
|
|
|
2010-12-01 10:15:40 -05:00
|
|
|
|
}
|
2010-06-13 08:21:49 -04:00
|
|
|
|
|
2009-09-02 21:26:38 -04:00
|
|
|
|
var tab = aEvent.target;
|
|
|
|
|
if (tab.localName != 'tab' ||
|
|
|
|
|
!sv.getTreePref('autoExpand.enabled'))
|
|
|
|
|
return;
|
|
|
|
|
|
2010-12-06 07:04:52 -05:00
|
|
|
|
w.clearTimeout(this.mAutoExpandTimer);
|
2011-03-23 14:30:01 -04:00
|
|
|
|
w.clearTimeout(this.mAutoExpandTimerNext);
|
2010-06-13 08:21:49 -04:00
|
|
|
|
|
|
|
|
|
var sourceNode = dt.getData(sv.kDRAG_TYPE_TABBAR+'-node');
|
2010-12-01 10:15:40 -05:00
|
|
|
|
if (aEvent.target == sourceNode)
|
|
|
|
|
return;
|
2010-06-13 08:21:49 -04:00
|
|
|
|
|
2011-03-23 14:30:01 -04:00
|
|
|
|
this.mAutoExpandTimerNext = w.setTimeout(function(aSelf, aTarget) {
|
|
|
|
|
aSelf.mAutoExpandTimerNext = null;
|
|
|
|
|
aSelf.mAutoExpandTimer = w.setTimeout(
|
|
|
|
|
function() {
|
|
|
|
|
let tab = sv.getTabById(aTarget);
|
|
|
|
|
if (tab &&
|
|
|
|
|
sv.shouldTabAutoExpanded(tab) &&
|
|
|
|
|
tab.getAttribute(sv.kDROP_POSITION) == 'self') {
|
|
|
|
|
if (sv.getTreePref('autoExpand.intelligently')) {
|
|
|
|
|
sv.collapseExpandTreesIntelligentlyFor(tab);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
this.mAutoExpandedTabs.push(aTarget);
|
|
|
|
|
sv.collapseExpandSubtree(tab, false);
|
|
|
|
|
}
|
2009-09-02 21:26:38 -04:00
|
|
|
|
}
|
2011-03-23 14:30:01 -04:00
|
|
|
|
},
|
|
|
|
|
sv.getTreePref('autoExpand.delay')
|
|
|
|
|
);
|
|
|
|
|
}, 0, this, tab.getAttribute(sv.kID));
|
2009-09-02 21:26:38 -04:00
|
|
|
|
|
|
|
|
|
tab = null;
|
|
|
|
|
},
|
|
|
|
|
|
2010-12-06 07:04:52 -05:00
|
|
|
|
onDragLeave : function TabbarDND_onDragLeave(aEvent)
|
2009-09-02 21:26:38 -04:00
|
|
|
|
{
|
2010-12-06 07:04:52 -05:00
|
|
|
|
var sv = this.treeStyleTab;
|
|
|
|
|
var b = this.browser;
|
|
|
|
|
var w = this.window;
|
2010-12-01 10:15:40 -05:00
|
|
|
|
|
|
|
|
|
var tabbarFromEvent = sv.getTabbarFromChild(aEvent.relatedTarget);
|
|
|
|
|
if (!tabbarFromEvent)
|
2010-12-01 19:00:39 -05:00
|
|
|
|
this.clearDropPosition();
|
2010-06-13 08:21:49 -04:00
|
|
|
|
|
2010-12-06 07:04:52 -05:00
|
|
|
|
w.clearTimeout(this.mAutoExpandTimer);
|
2009-09-02 21:26:38 -04:00
|
|
|
|
this.mAutoExpandTimer = null;
|
|
|
|
|
},
|
|
|
|
|
|
2010-12-06 07:04:52 -05:00
|
|
|
|
onDragEnd : function TabbarDND_onDragEnd(aEvent)
|
2009-09-02 21:26:38 -04:00
|
|
|
|
{
|
2010-12-06 07:04:52 -05:00
|
|
|
|
var sv = this.treeStyleTab;
|
2010-06-13 08:21:49 -04:00
|
|
|
|
var dt = aEvent.dataTransfer;
|
2010-12-01 10:15:40 -05:00
|
|
|
|
if (dt.getData(sv.kDRAG_TYPE_TABBAR))
|
|
|
|
|
this.onTabbarDragEnd(aEvent);
|
|
|
|
|
else
|
|
|
|
|
this.onTabDragEnd(aEvent);
|
|
|
|
|
},
|
|
|
|
|
|
2010-12-06 07:04:52 -05:00
|
|
|
|
onTabDragEnd : function TabbarDND_onTabDragEnd(aEvent)
|
2010-12-01 10:15:40 -05:00
|
|
|
|
{
|
2010-12-06 07:04:52 -05:00
|
|
|
|
var sv = this.treeStyleTab;
|
|
|
|
|
var b = this.browser;
|
|
|
|
|
var d = this.document;
|
|
|
|
|
var w = this.window;
|
2010-12-01 10:15:40 -05:00
|
|
|
|
|
|
|
|
|
var tabbar = b.mTabContainer;
|
|
|
|
|
var strip = sv.tabStrip;
|
|
|
|
|
var dt = aEvent.dataTransfer;
|
|
|
|
|
|
2010-12-01 19:00:39 -05:00
|
|
|
|
this.clearDropPosition();
|
2010-12-01 10:15:40 -05:00
|
|
|
|
|
|
|
|
|
if (dt.mozUserCancelled || dt.dropEffect != 'none')
|
|
|
|
|
return;
|
2010-06-13 08:21:49 -04:00
|
|
|
|
|
2010-12-01 10:15:40 -05:00
|
|
|
|
// prevent handling of this event by the default handler
|
|
|
|
|
aEvent.stopPropagation();
|
2011-02-08 12:56:33 -05:00
|
|
|
|
aEvent.preventDefault();
|
2010-12-01 10:15:40 -05:00
|
|
|
|
|
|
|
|
|
var eX = aEvent.screenX;
|
|
|
|
|
var eY = aEvent.screenY;
|
|
|
|
|
var x, y, w, h;
|
|
|
|
|
|
|
|
|
|
// ignore drop on the toolbox
|
2010-12-06 07:04:52 -05:00
|
|
|
|
x = w.screenX;
|
|
|
|
|
y = w.screenY;
|
|
|
|
|
w = w.outerWidth;
|
|
|
|
|
h = d.getElementById('navigator-toolbox').boxObject.height;
|
2010-12-01 10:15:40 -05:00
|
|
|
|
if (eX > x && eX < x + w && eY > y && eY < y + h)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// ignore drop near the tab bar
|
|
|
|
|
var box = strip.boxObject;
|
|
|
|
|
var ignoreArea = Math.max(16, parseInt(sv.getFirstNormalTab(b).boxObject.height / 2));
|
|
|
|
|
x = box.screenX - (sv.isVertical ? ignoreArea : 0 );
|
|
|
|
|
y = box.screenY - ignoreArea;
|
|
|
|
|
w = box.width + (sv.isVertical ? ignoreArea + ignoreArea : 0 );
|
|
|
|
|
h = box.height + ignoreArea + ignoreArea;
|
|
|
|
|
if (eX > x && eX < x + w && eY > y && eY < y + h)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
var draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
|
2010-12-01 19:00:39 -05:00
|
|
|
|
if (this.isDraggingAllCurrentTabs(draggedTab))
|
2010-12-01 10:15:40 -05:00
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
b.replaceTabWithWindow(draggedTab);
|
|
|
|
|
},
|
|
|
|
|
|
2010-12-06 07:04:52 -05:00
|
|
|
|
onTabbarDragEnd : function TabbarDND_onTabbarDragEnd(aEvent)
|
2010-12-01 10:15:40 -05:00
|
|
|
|
{
|
2010-12-06 07:04:52 -05:00
|
|
|
|
var w = this.window;
|
|
|
|
|
w.setTimeout(function(aSelf) {
|
2010-12-01 10:15:40 -05:00
|
|
|
|
aSelf.readyToEndTabbarDrag();
|
2010-12-06 07:04:52 -05:00
|
|
|
|
aSelf.treeStyleTab.removeTabbrowserAttribute(aSelf.treeStyleTab.kDROP_POSITION);
|
2009-11-23 13:04:40 -05:00
|
|
|
|
}, 10, this);
|
2009-09-02 21:26:38 -04:00
|
|
|
|
aEvent.stopPropagation();
|
2010-06-13 08:21:49 -04:00
|
|
|
|
aEvent.preventDefault();
|
2009-09-02 21:26:38 -04:00
|
|
|
|
},
|
2010-12-01 10:15:40 -05:00
|
|
|
|
|
2010-12-06 07:04:52 -05:00
|
|
|
|
onDragOver : function TabbarDND_onDragOver(aEvent)
|
2009-09-02 21:26:38 -04:00
|
|
|
|
{
|
2010-12-01 10:15:40 -05:00
|
|
|
|
if (this.onTabDragOver(aEvent)) {
|
|
|
|
|
aEvent.stopPropagation();
|
|
|
|
|
aEvent.preventDefault(); // this is required to override default dragover actions!
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
2010-12-06 07:04:52 -05:00
|
|
|
|
onTabDragOver : function TabbarDND_onTabDragOver(aEvent)
|
2010-12-01 10:15:40 -05:00
|
|
|
|
{
|
|
|
|
|
try{
|
2010-12-06 07:04:52 -05:00
|
|
|
|
var sv = this.treeStyleTab;
|
|
|
|
|
var b = this.browser;
|
2010-06-13 08:21:49 -04:00
|
|
|
|
|
2010-12-01 19:02:27 -05:00
|
|
|
|
var session = sv.currentDragSession;
|
2010-12-02 12:38:15 -05:00
|
|
|
|
if (sv.isToolbarCustomizing)
|
2010-12-01 10:15:40 -05:00
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
sv.autoScroll.processAutoScroll(aEvent);
|
|
|
|
|
|
2010-12-01 19:00:39 -05:00
|
|
|
|
var info = this.getDropAction(aEvent, session);
|
2010-12-01 10:15:40 -05:00
|
|
|
|
|
|
|
|
|
var observer = b;
|
|
|
|
|
if (b.tabContainer && b.tabContainer._setEffectAllowedForDataTransfer) // for Firefox 4.0
|
|
|
|
|
observer = b.tabContainer;
|
|
|
|
|
|
|
|
|
|
// auto-switch for staying on tabs (Firefox 3.5 or later)
|
|
|
|
|
if (
|
|
|
|
|
info.position == sv.kDROP_ON &&
|
|
|
|
|
info.target &&
|
|
|
|
|
!info.target.selected &&
|
|
|
|
|
(
|
|
|
|
|
('mDragTime' in observer && 'mDragOverDelay' in observer) || // Firefox 3.6
|
|
|
|
|
('_dragTime' in observer && '_dragOverDelay' in observer) // Firefox 4.0 or later
|
|
|
|
|
)
|
|
|
|
|
) {
|
|
|
|
|
let time = observer.mDragTime || observer._dragTime || 0;
|
|
|
|
|
let delay = observer.mDragOverDelay || observer._dragOverDelay || 0;
|
|
|
|
|
let effects = observer._setEffectAllowedForDataTransfer(aEvent);
|
|
|
|
|
if (effects == 'link') {
|
|
|
|
|
let now = Date.now();
|
|
|
|
|
if (!time) {
|
|
|
|
|
time = now;
|
|
|
|
|
if ('mDragTime' in observer)
|
|
|
|
|
observer.mDragTime = time;
|
|
|
|
|
else
|
|
|
|
|
observer._dragTime = time;
|
|
|
|
|
}
|
|
|
|
|
if (now >= time + delay)
|
2010-12-02 12:38:15 -05:00
|
|
|
|
b.selectedTab = info.target;
|
2010-12-01 10:15:40 -05:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!info.target || info.target != sv.evaluateXPath(
|
|
|
|
|
'child::xul:tab[@'+sv.kDROP_POSITION+']',
|
|
|
|
|
b.mTabContainer,
|
2010-12-06 07:04:52 -05:00
|
|
|
|
Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE
|
2010-12-01 10:15:40 -05:00
|
|
|
|
).singleNodeValue)
|
2010-12-01 19:00:39 -05:00
|
|
|
|
this.clearDropPosition();
|
2010-12-01 10:15:40 -05:00
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
!info.canDrop ||
|
|
|
|
|
observer._setEffectAllowedForDataTransfer(aEvent) == 'none'
|
|
|
|
|
) {
|
|
|
|
|
aEvent.dataTransfer.effectAllowed = "none";
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-16 13:23:38 -04:00
|
|
|
|
let indicatorTab = info.target;
|
|
|
|
|
if (sv.isCollapsed(info.target)) {
|
|
|
|
|
let tab = indicatorTab;
|
|
|
|
|
while ((tab = sv.getPreviousTab(tab)) && sv.isCollapsed(tab)) {}
|
|
|
|
|
if (tab) indicatorTab = tab;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
indicatorTab.setAttribute(
|
2010-12-01 10:15:40 -05:00
|
|
|
|
sv.kDROP_POSITION,
|
|
|
|
|
info.position == sv.kDROP_BEFORE ? 'before' :
|
|
|
|
|
info.position == sv.kDROP_AFTER ? 'after' :
|
|
|
|
|
'self'
|
|
|
|
|
);
|
2011-01-19 05:03:40 -05:00
|
|
|
|
|
2010-12-01 10:15:40 -05:00
|
|
|
|
var indicator = b.mTabDropIndicatorBar || b.tabContainer._tabDropIndicator;
|
2011-03-30 03:18:23 -04:00
|
|
|
|
indicator.setAttribute('dragging', (info.position == sv.kDROP_ON || sv.isVertical) ? 'false' : 'true' );
|
2011-01-19 05:03:40 -05:00
|
|
|
|
if (sv.isVertical)
|
|
|
|
|
indicator.collapsed = true;
|
|
|
|
|
|
2011-01-22 10:46:29 -05:00
|
|
|
|
return (info.position == sv.kDROP_ON || sv.position != 'top')
|
2010-12-01 10:15:40 -05:00
|
|
|
|
}
|
|
|
|
|
catch(e) {
|
2010-12-06 07:04:52 -05:00
|
|
|
|
dump('TabbarDND::onDragOver\n'+e+'\n');
|
2010-12-01 10:15:40 -05:00
|
|
|
|
}
|
2009-09-02 21:26:38 -04:00
|
|
|
|
},
|
2010-12-01 10:15:40 -05:00
|
|
|
|
|
2010-12-06 07:04:52 -05:00
|
|
|
|
onDrop : function TabbarDND_onDrop(aEvent)
|
2009-09-02 21:26:38 -04:00
|
|
|
|
{
|
2010-12-01 10:15:40 -05:00
|
|
|
|
this.onTabDrop(aEvent);
|
|
|
|
|
|
2010-12-06 07:04:52 -05:00
|
|
|
|
var sv = this.treeStyleTab;
|
2010-12-01 10:15:40 -05:00
|
|
|
|
if (this.mAutoExpandedTabs.length) {
|
|
|
|
|
if (sv.getTreePref('autoExpand.collapseFinally')) {
|
|
|
|
|
this.mAutoExpandedTabs.forEach(function(aTarget) {
|
|
|
|
|
this.collapseExpandSubtree(this.getTabById(aTarget), true, true);
|
|
|
|
|
}, sv);
|
|
|
|
|
}
|
|
|
|
|
this.mAutoExpandedTabs = [];
|
2009-09-02 21:26:38 -04:00
|
|
|
|
}
|
|
|
|
|
},
|
2010-12-01 10:15:40 -05:00
|
|
|
|
|
|
|
|
|
onTabDrop : function TSTService_onTabDrop(aEvent)
|
2009-09-02 21:26:38 -04:00
|
|
|
|
{
|
2010-12-06 07:04:52 -05:00
|
|
|
|
var sv = this.treeStyleTab;
|
|
|
|
|
var b = this.browser;
|
|
|
|
|
var w = this.window;
|
2009-09-02 21:26:38 -04:00
|
|
|
|
|
2010-12-01 10:15:40 -05:00
|
|
|
|
var tabbar = b.mTabContainer;
|
|
|
|
|
var dt = aEvent.dataTransfer;
|
|
|
|
|
|
2010-12-01 19:00:39 -05:00
|
|
|
|
this.clearDropPosition();
|
2010-12-01 10:15:40 -05:00
|
|
|
|
|
|
|
|
|
if (tabbar._tabDropIndicator) // for Firefox 4 or later
|
|
|
|
|
tabbar._tabDropIndicator.collapsed = true;
|
|
|
|
|
|
2010-12-01 19:02:27 -05:00
|
|
|
|
var session = sv.currentDragSession;
|
2010-12-01 19:00:39 -05:00
|
|
|
|
var dropActionInfo = this.getDropAction(aEvent, session);
|
2010-12-01 10:15:40 -05:00
|
|
|
|
|
|
|
|
|
var draggedTab;
|
|
|
|
|
if (dt.dropEffect != 'link') {
|
|
|
|
|
draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
|
|
|
|
|
if (!draggedTab) {
|
|
|
|
|
aEvent.stopPropagation();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-01 19:00:39 -05:00
|
|
|
|
if (draggedTab && this.performDrop(dropActionInfo, draggedTab)) {
|
2010-12-01 10:15:40 -05:00
|
|
|
|
aEvent.stopPropagation();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// duplicating of tabs
|
|
|
|
|
if (
|
|
|
|
|
draggedTab &&
|
|
|
|
|
(
|
|
|
|
|
dt.dropEffect == 'copy' ||
|
|
|
|
|
sv.getTabBrowserFromChild(draggedTab) != b
|
|
|
|
|
) &&
|
|
|
|
|
dropActionInfo.position == sv.kDROP_ON
|
|
|
|
|
) {
|
|
|
|
|
var beforeTabs = Array.slice(b.mTabContainer.childNodes);
|
2010-12-06 07:04:52 -05:00
|
|
|
|
w.setTimeout(function() {
|
2010-12-01 10:15:40 -05:00
|
|
|
|
var newTabs = Array.slice(b.mTabContainer.childNodes).filter(function(aTab) {
|
|
|
|
|
return beforeTabs.indexOf(aTab) < 0;
|
|
|
|
|
});
|
|
|
|
|
if (newTabs.length)
|
|
|
|
|
sv.attachTabTo(newTabs[0], dropActionInfo.target);
|
|
|
|
|
}, 0);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// dropping of urls
|
|
|
|
|
if (!draggedTab) {
|
|
|
|
|
aEvent.stopPropagation();
|
|
|
|
|
|
|
|
|
|
let url = this.retrieveURLFromDataTransfer(dt);
|
|
|
|
|
|
|
|
|
|
if (!url || !url.length || url.indexOf(' ', 0) != -1 || /^\s*(javascript|data):/.test(url))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
let (sourceDoc = session ? session.sourceDocument : null) {
|
2011-02-06 20:45:59 -05:00
|
|
|
|
let sourceURI = sourceDoc ? sourceDoc.documentURI : 'file:///' ;
|
|
|
|
|
let normalizedURI = sv.makeURIFromSpec(url);
|
|
|
|
|
if (normalizedURI && sourceURI.indexOf('chrome://') < 0) {
|
2010-12-01 10:15:40 -05:00
|
|
|
|
try {
|
2011-02-06 20:45:59 -05:00
|
|
|
|
SecMan.checkLoadURIStr(sourceURI, normalizedURI.spec, Ci.nsIScriptSecurityManager.STANDARD);
|
2010-12-01 10:15:40 -05:00
|
|
|
|
}
|
|
|
|
|
catch(e) {
|
|
|
|
|
aEvent.stopPropagation();
|
|
|
|
|
throw 'Drop of ' + url + ' denied.';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let bgLoad = sv.getPref('browser.tabs.loadInBackground');
|
|
|
|
|
if (aEvent.shiftKey) bgLoad = !bgLoad;
|
|
|
|
|
|
|
|
|
|
let tab = sv.getTabFromEvent(aEvent);
|
|
|
|
|
if (!tab || dt.dropEffect == 'copy') {
|
2010-12-06 07:04:52 -05:00
|
|
|
|
this.performDrop(dropActionInfo, b.loadOneTab(w.getShortcutOrURI(url), { inBackground: bgLoad }));
|
2010-12-01 10:15:40 -05:00
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
let locked = (
|
|
|
|
|
tab.getAttribute('locked') == 'true' || // Tab Mix Plus and others
|
|
|
|
|
tab.getAttribute('isPageLocked') == 'true' // Super Tab Mode
|
|
|
|
|
);
|
|
|
|
|
let loadDroppedLinkToNewChildTab = dropActionInfo.position != sv.kDROP_ON || locked;
|
|
|
|
|
if (!loadDroppedLinkToNewChildTab &&
|
|
|
|
|
dropActionInfo.position == sv.kDROP_ON)
|
|
|
|
|
loadDroppedLinkToNewChildTab = sv.dropLinksOnTabBehavior() == sv.kDROPLINK_NEWTAB;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
if (loadDroppedLinkToNewChildTab || locked) {
|
2010-12-06 07:04:52 -05:00
|
|
|
|
this.performDrop(dropActionInfo, b.loadOneTab(w.getShortcutOrURI(url), { inBackground: bgLoad }));
|
2010-12-01 10:15:40 -05:00
|
|
|
|
}
|
|
|
|
|
else {
|
2010-12-06 07:04:52 -05:00
|
|
|
|
tab.linkedBrowser.loadURI(w.getShortcutOrURI(url));
|
2010-12-01 10:15:40 -05:00
|
|
|
|
if (!bgLoad)
|
|
|
|
|
b.selectedTab = tab;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch(e) {
|
|
|
|
|
}
|
2009-09-02 21:26:38 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
2010-12-01 10:15:40 -05:00
|
|
|
|
|
|
|
|
|
retrieveURLFromDataTransfer : function TSTService_retrieveURLFromDataTransfer(aDataTransfer)
|
|
|
|
|
{
|
|
|
|
|
let url;
|
|
|
|
|
let types = ['text/x-moz-url', 'text/uri-list', 'text/plain', 'application/x-moz-file'];
|
|
|
|
|
for (let i = 0; i < types.length; i++) {
|
|
|
|
|
let dataType = types[i];
|
|
|
|
|
let isURLList = dataType == 'text/uri-list';
|
|
|
|
|
let urlData = aDataTransfer.mozGetDataAt(isURLList ? 'URL' : dataType , 0);
|
|
|
|
|
if (urlData) {
|
|
|
|
|
url = this.retrieveURLFromData(urlData, isURLList ? 'text/plain' : dataType);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return url;
|
|
|
|
|
},
|
|
|
|
|
retrieveURLFromData : function TSTService_retrieveURLFromData(aData, aType)
|
|
|
|
|
{
|
|
|
|
|
switch (aType)
|
|
|
|
|
{
|
|
|
|
|
case 'text/unicode':
|
|
|
|
|
case 'text/plain':
|
|
|
|
|
case 'text/x-moz-text-internal':
|
|
|
|
|
return aData.replace(/^\s+|\s+$/g, '');
|
|
|
|
|
|
|
|
|
|
case 'text/x-moz-url':
|
2010-12-06 07:04:52 -05:00
|
|
|
|
return ((aData instanceof Ci.nsISupportsString) ? aData.toString() : aData)
|
2010-12-01 10:15:40 -05:00
|
|
|
|
.split('\n')[0];
|
|
|
|
|
|
|
|
|
|
case 'application/x-moz-file':
|
2010-12-06 07:04:52 -05:00
|
|
|
|
let fileHandler = IOService.getProtocolHandler('file')
|
|
|
|
|
.QueryInterface(Ci.nsIFileProtocolHandler);
|
2010-12-01 10:15:40 -05:00
|
|
|
|
return fileHandler.getURLSpecFromFile(aData);
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
},
|
2010-12-01 18:12:57 -05:00
|
|
|
|
|
2010-12-06 08:31:58 -05:00
|
|
|
|
init : function TabbarDND_init(aTabBrowser)
|
2010-12-01 18:12:57 -05:00
|
|
|
|
{
|
2010-12-06 08:31:58 -05:00
|
|
|
|
this.browser = aTabBrowser;
|
|
|
|
|
this.document = aTabBrowser.ownerDocument;
|
2010-12-06 07:04:52 -05:00
|
|
|
|
this.window = this.document.defaultView;
|
2010-12-06 08:31:58 -05:00
|
|
|
|
this.treeStyleTab = aTabBrowser.treeStyleTab;
|
2010-12-06 07:04:52 -05:00
|
|
|
|
|
2010-12-01 18:12:57 -05:00
|
|
|
|
this.mAutoExpandTimer = null;
|
2011-03-23 14:30:01 -04:00
|
|
|
|
this.mAutoExpandTimerNext = null;
|
2010-12-01 18:12:57 -05:00
|
|
|
|
this.mAutoExpandedTabs = [];
|
2011-01-22 09:43:55 -05:00
|
|
|
|
this.startListenEvents();
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
startListenEvents : function TabbarDND_startListenEvents()
|
|
|
|
|
{
|
2010-12-06 07:04:52 -05:00
|
|
|
|
var strip = this.treeStyleTab.tabStrip;
|
2010-12-01 18:12:57 -05:00
|
|
|
|
strip.addEventListener('dragstart', this, true);
|
|
|
|
|
strip.addEventListener('dragover', this, true);
|
|
|
|
|
strip.addEventListener('dragenter', this, false);
|
|
|
|
|
strip.addEventListener('dragleave', this, false);
|
2011-02-08 12:56:33 -05:00
|
|
|
|
strip.addEventListener('dragend', this, true);
|
2010-12-01 18:12:57 -05:00
|
|
|
|
strip.addEventListener('drop', this, true);
|
|
|
|
|
},
|
2011-01-22 09:43:55 -05:00
|
|
|
|
|
2010-12-06 07:04:52 -05:00
|
|
|
|
destroy : function TabbarDND_destroy()
|
2011-01-22 09:43:55 -05:00
|
|
|
|
{
|
|
|
|
|
this.endListenEvents();
|
|
|
|
|
|
|
|
|
|
delete this.treeStyleTab;
|
|
|
|
|
delete this.browser;
|
|
|
|
|
delete this.document;
|
|
|
|
|
delete this.window;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
endListenEvents : function TabbarDND_endListenEvents()
|
2009-09-02 21:42:04 -04:00
|
|
|
|
{
|
2010-12-06 07:04:52 -05:00
|
|
|
|
var strip = this.treeStyleTab.tabStrip;
|
2010-12-01 18:12:57 -05:00
|
|
|
|
strip.removeEventListener('dragstart', this, true);
|
|
|
|
|
strip.removeEventListener('dragover', this, true);
|
|
|
|
|
strip.removeEventListener('dragenter', this, false);
|
|
|
|
|
strip.removeEventListener('dragleave', this, false);
|
2011-02-08 12:56:33 -05:00
|
|
|
|
strip.removeEventListener('dragend', this, true);
|
2010-12-01 18:12:57 -05:00
|
|
|
|
strip.removeEventListener('drop', this, true);
|
2009-09-02 21:26:38 -04:00
|
|
|
|
}
|
2011-01-22 09:43:55 -05:00
|
|
|
|
|
2009-09-02 21:26:38 -04:00
|
|
|
|
};
|
|
|
|
|
|