1 # ***** BEGIN LICENSE BLOCK *****
2 # Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 # The contents of this file are subject to the Mozilla Public License Version
5 # 1.1 (the "License"); you may not use this file except in compliance with
6 # the License. You may obtain a copy of the License at
7 # http://www.mozilla.org/MPL/
9 # Software distributed under the License is distributed on an "AS IS" basis,
10 # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 # for the specific language governing rights and limitations under the
14 # The Original Code is Mozilla Communicator client code, released
17 # The Initial Developer of the Original Code is
19 # Portions created by the Initial Developer are Copyright (C) 2002
20 # the Initial Developer. All Rights Reserved.
23 # David Hyatt (hyatt@apple.com)
24 # Blake Ross (blaker@netscape.com)
25 # Joe Hewitt (hewitt@netscape.com)
27 # Alternatively, the contents of this file may be used under the terms of
28 # either the GNU General Public License Version 2 or later (the "GPL"), or
29 # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 # in which case the provisions of the GPL or the LGPL are applicable instead
31 # of those above. If you wish to allow use of your version of this file only
32 # under the terms of either the GPL or the LGPL, and not to allow others to
33 # use your version of this file under the terms of the MPL, indicate your
34 # decision by deleting the provisions above and replace them with the notice
35 # and other provisions required by the GPL or the LGPL. If you do not delete
36 # the provisions above, a recipient may use your version of this file under
37 # the terms of any one of the MPL, the GPL or the LGPL.
39 # ***** END LICENSE BLOCK *****
43 var gToolboxDocument = null;
45 var gCurrentDragOverItem = null;
46 var gToolboxChanged = false;
47 var gToolboxSheet = false;
51 if ("arguments" in window && window.arguments[0]) {
52 InitWithToolbox(window.arguments[0]);
53 repositionDialog(window);
55 else if (window.frameElement &&
56 "toolbox" in window.frameElement) {
58 InitWithToolbox(window.frameElement.toolbox);
59 repositionDialog(window.frameElement.panel);
63 function InitWithToolbox(aToolbox)
66 dispatchCustomizationEvent("beforecustomization");
67 gToolboxDocument = gToolbox.ownerDocument;
68 gToolbox.customizing = true;
70 gToolbox.addEventListener("dragstart", onToolbarDragStart, true);
71 gToolbox.addEventListener("dragover", onToolbarDragOver, true);
72 gToolbox.addEventListener("dragleave", onToolbarDragLeave, true);
73 gToolbox.addEventListener("drop", onToolbarDrop, true);
83 finishToolbarCustomization();
89 finishToolbarCustomization();
92 function finishToolbarCustomization()
94 removeToolboxListeners();
97 gToolbox.customizing = false;
99 notifyParentComplete();
102 function initDialog()
104 var mode = gToolbox.getAttribute("mode");
105 document.getElementById("modelist").value = mode;
106 var smallIconsCheckbox = document.getElementById("smallicons");
107 smallIconsCheckbox.checked = gToolbox.getAttribute("iconsize") == "small";
109 smallIconsCheckbox.disabled = true;
111 // Build up the palette of other items.
114 // Wrap all the items on the toolbar in toolbarpaletteitems.
118 function repositionDialog(aWindow)
120 // Position the dialog touching the bottom of the toolbox and centered with
126 if (aWindow != window)
127 width = aWindow.getBoundingClientRect().width;
128 else if (document.documentElement.hasAttribute("width"))
129 width = document.documentElement.getAttribute("width");
131 width = parseInt(document.documentElement.style.width);
132 var screenX = gToolbox.boxObject.screenX
133 + ((gToolbox.boxObject.width - width) / 2);
134 var screenY = gToolbox.boxObject.screenY + gToolbox.boxObject.height;
136 aWindow.moveTo(screenX, screenY);
139 function removeToolboxListeners()
141 gToolbox.removeEventListener("dragstart", onToolbarDragStart, true);
142 gToolbox.removeEventListener("dragover", onToolbarDragOver, true);
143 gToolbox.removeEventListener("dragleave", onToolbarDragLeave, true);
144 gToolbox.removeEventListener("drop", onToolbarDrop, true);
148 * Invoke a callback on the toolbox to notify it that the dialog is done
151 function notifyParentComplete()
153 if ("customizeDone" in gToolbox)
154 gToolbox.customizeDone(gToolboxChanged);
155 dispatchCustomizationEvent("aftercustomization");
158 function toolboxChanged(aEvent)
160 gToolboxChanged = true;
161 if ("customizeChange" in gToolbox)
162 gToolbox.customizeChange(aEvent);
163 dispatchCustomizationEvent("customizationchange");
166 function dispatchCustomizationEvent(aEventName) {
167 var evt = document.createEvent("Events");
168 evt.initEvent(aEventName, true, true);
169 gToolbox.dispatchEvent(evt);
173 * Persist the current set of buttons in all customizable toolbars to
176 function persistCurrentSets()
178 if (!gToolboxChanged || gToolboxDocument.defaultView.closed)
182 forEachCustomizableToolbar(function (toolbar) {
183 // Calculate currentset and store it in the attribute.
184 var currentSet = toolbar.currentSet;
185 toolbar.setAttribute("currentset", currentSet);
187 var customIndex = toolbar.hasAttribute("customindex");
189 if (!toolbar.hasChildNodes()) {
190 // Remove custom toolbars whose contents have been removed.
191 gToolbox.removeChild(toolbar);
193 // Persist custom toolbar info on the <toolbarset/>
194 gToolbox.toolbarset.setAttribute("toolbar"+(++customCount),
195 toolbar.toolbarName + ":" + currentSet);
196 gToolboxDocument.persist(gToolbox.toolbarset.id, "toolbar"+customCount);
201 // Persist the currentset attribute directly on hardcoded toolbars.
202 gToolboxDocument.persist(toolbar.id, "currentset");
206 // Remove toolbarX attributes for removed toolbars.
207 while (gToolbox.toolbarset.hasAttribute("toolbar"+(++customCount))) {
208 gToolbox.toolbarset.removeAttribute("toolbar"+customCount);
209 gToolboxDocument.persist(gToolbox.toolbarset.id, "toolbar"+customCount);
214 * Wraps all items in all customizable toolbars in a toolbox.
216 function wrapToolbarItems()
218 forEachCustomizableToolbar(function (toolbar) {
219 Array.forEach(toolbar.childNodes, function (item) {
221 if (item.firstChild && item.firstChild.localName == "menubar")
225 if (isToolbarItem(item)) {
226 let wrapper = wrapToolbarItem(item);
227 cleanupItemForToolbar(item, wrapper);
234 * Unwraps all items in all customizable toolbars in a toolbox.
236 function unwrapToolbarItems()
238 var paletteItems = gToolbox.getElementsByTagName("toolbarpaletteitem");
240 while ((paletteItem = paletteItems.item(0)) != null) {
241 var toolbarItem = paletteItem.firstChild;
242 restoreItemForToolbar(toolbarItem, paletteItem);
243 paletteItem.parentNode.replaceChild(toolbarItem, paletteItem);
248 * Creates a wrapper that can be used to contain a toolbaritem and prevent
249 * it from receiving UI events.
251 function createWrapper(aId, aDocument)
253 var wrapper = aDocument.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
254 "toolbarpaletteitem");
256 wrapper.id = "wrapper-"+aId;
261 * Wraps an item that has been cloned from a template and adds
262 * it to the end of a row in the palette.
264 function wrapPaletteItem(aPaletteItem, aCurrentRow, aSpacer)
266 var wrapper = createWrapper(aPaletteItem.id, document);
268 wrapper.setAttribute("flex", 1);
269 wrapper.setAttribute("align", "center");
270 wrapper.setAttribute("pack", "center");
271 wrapper.setAttribute("minheight", "0");
272 wrapper.setAttribute("minwidth", "0");
274 wrapper.appendChild(aPaletteItem);
276 // XXX We need to call this AFTER the palette item has been appended
277 // to the wrapper or else we crash dropping certain buttons on the
278 // palette due to removal of the command and disabled attributes - JRH
279 cleanUpItemForPalette(aPaletteItem, wrapper);
282 aCurrentRow.insertBefore(wrapper, aSpacer);
284 aCurrentRow.appendChild(wrapper);
289 * Wraps an item that is currently on a toolbar and replaces the item
290 * with the wrapper. This is not used when dropping items from the palette,
291 * only when first starting the dialog and wrapping everything on the toolbars.
293 function wrapToolbarItem(aToolbarItem)
295 var wrapper = createWrapper(aToolbarItem.id, gToolboxDocument);
297 wrapper.flex = aToolbarItem.flex;
299 aToolbarItem.parentNode.replaceChild(wrapper, aToolbarItem);
301 wrapper.appendChild(aToolbarItem);
307 * Get the list of ids for the current set of items on each toolbar.
309 function getCurrentItemIds()
311 var currentItems = {};
312 forEachCustomizableToolbar(function (toolbar) {
313 var child = toolbar.firstChild;
315 if (isToolbarItem(child))
316 currentItems[child.id] = 1;
317 child = child.nextSibling;
324 * Builds the palette of draggable items that are not yet in a toolbar.
326 function buildPalette()
328 // Empty the palette first.
329 var paletteBox = document.getElementById("palette-box");
330 while (paletteBox.lastChild)
331 paletteBox.removeChild(paletteBox.lastChild);
333 var currentRow = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
335 currentRow.setAttribute("class", "paletteRow");
337 // Add the toolbar separator item.
338 var templateNode = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
340 templateNode.id = "separator";
341 wrapPaletteItem(templateNode, currentRow, null);
343 // Add the toolbar spring item.
344 templateNode = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
346 templateNode.id = "spring";
347 templateNode.flex = 1;
348 wrapPaletteItem(templateNode, currentRow, null);
350 // Add the toolbar spacer item.
351 templateNode = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
353 templateNode.id = "spacer";
354 templateNode.flex = 1;
355 wrapPaletteItem(templateNode, currentRow, null);
359 var currentItems = getCurrentItemIds();
360 templateNode = gToolbox.palette.firstChild;
361 while (templateNode) {
362 // Check if the item is already in a toolbar before adding it to the palette.
363 if (!(templateNode.id in currentItems)) {
364 var paletteItem = document.importNode(templateNode, true);
366 if (rowSlot == kRowMax) {
367 // Append the old row.
368 paletteBox.appendChild(currentRow);
371 currentRow = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
373 currentRow.setAttribute("class", "paletteRow");
378 wrapPaletteItem(paletteItem, currentRow, null);
381 templateNode = templateNode.nextSibling;
385 fillRowWithFlex(currentRow);
386 paletteBox.appendChild(currentRow);
391 * Creates a new palette item for a cloned template node and
392 * adds it to the last slot in the palette.
394 function appendPaletteItem(aItem)
396 var paletteBox = document.getElementById("palette-box");
397 var lastRow = paletteBox.lastChild;
398 var lastSpacer = lastRow.lastChild;
400 if (lastSpacer.localName != "spacer") {
401 // The current row is full, so we have to create a new row.
402 lastRow = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
404 lastRow.setAttribute("class", "paletteRow");
405 paletteBox.appendChild(lastRow);
407 wrapPaletteItem(aItem, lastRow, null);
409 fillRowWithFlex(lastRow);
411 // Decrement the flex of the last spacer or remove it entirely.
412 var flex = lastSpacer.getAttribute("flex");
414 lastRow.removeChild(lastSpacer);
417 lastSpacer.setAttribute("flex", --flex);
419 // Insert the wrapper where the last spacer was.
420 wrapPaletteItem(aItem, lastRow, lastSpacer);
424 function fillRowWithFlex(aRow)
426 var remainingFlex = kRowMax - aRow.childNodes.length;
427 if (remainingFlex > 0) {
428 var spacer = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
430 spacer.setAttribute("flex", remainingFlex);
431 aRow.appendChild(spacer);
436 * Makes sure that an item that has been cloned from a template
437 * is stripped of any attributes that may adversely affect its
438 * appearance in the palette.
440 function cleanUpItemForPalette(aItem, aWrapper)
442 aWrapper.setAttribute("place", "palette");
443 setWrapperType(aItem, aWrapper);
445 if (aItem.hasAttribute("title"))
446 aWrapper.setAttribute("title", aItem.getAttribute("title"));
447 else if (aItem.hasAttribute("label"))
448 aWrapper.setAttribute("title", aItem.getAttribute("label"));
449 else if (isSpecialItem(aItem)) {
450 var stringBundle = document.getElementById("stringBundle");
451 // Remove the common "toolbar" prefix to generate the string name.
452 var title = stringBundle.getString(aItem.localName.slice(7) + "Title");
453 aWrapper.setAttribute("title", title);
456 // Remove attributes that screw up our appearance.
457 aItem.removeAttribute("command");
458 aItem.removeAttribute("observes");
459 aItem.removeAttribute("type");
460 aItem.removeAttribute("width");
462 Array.forEach(aWrapper.querySelectorAll("[disabled]"), function(aNode) {
463 aNode.removeAttribute("disabled");
468 * Makes sure that an item that has been cloned from a template
469 * is stripped of all properties that may adversely affect its
470 * appearance in the toolbar. Store critical properties on the
471 * wrapper so they can be put back on the item when we're done.
473 function cleanupItemForToolbar(aItem, aWrapper)
475 setWrapperType(aItem, aWrapper);
476 aWrapper.setAttribute("place", "toolbar");
478 if (aItem.hasAttribute("command")) {
479 aWrapper.setAttribute("itemcommand", aItem.getAttribute("command"));
480 aItem.removeAttribute("command");
484 aWrapper.setAttribute("itemchecked", "true");
485 aItem.checked = false;
488 if (aItem.disabled) {
489 aWrapper.setAttribute("itemdisabled", "true");
490 aItem.disabled = false;
495 * Restore all the properties that we stripped off above.
497 function restoreItemForToolbar(aItem, aWrapper)
499 if (aWrapper.hasAttribute("itemdisabled"))
500 aItem.disabled = true;
502 if (aWrapper.hasAttribute("itemchecked"))
503 aItem.checked = true;
505 if (aWrapper.hasAttribute("itemcommand")) {
506 let commandID = aWrapper.getAttribute("itemcommand");
507 aItem.setAttribute("command", commandID);
509 //XXX Bug 309953 - toolbarbuttons aren't in sync with their commands after customizing
510 let command = gToolboxDocument.getElementById(commandID);
511 if (command && command.hasAttribute("disabled"))
512 aItem.setAttribute("disabled", command.getAttribute("disabled"));
516 function setWrapperType(aItem, aWrapper)
518 if (aItem.localName == "toolbarseparator") {
519 aWrapper.setAttribute("type", "separator");
520 } else if (aItem.localName == "toolbarspring") {
521 aWrapper.setAttribute("type", "spring");
522 } else if (aItem.localName == "toolbarspacer") {
523 aWrapper.setAttribute("type", "spacer");
524 } else if (aItem.localName == "toolbaritem" && aItem.firstChild) {
525 aWrapper.setAttribute("type", aItem.firstChild.localName);
529 function setDragActive(aItem, aValue)
532 var direction = window.getComputedStyle(aItem, null).direction;
533 var value = direction == "ltr"? "left" : "right";
534 if (aItem.localName == "toolbar") {
535 node = aItem.lastChild;
536 value = direction == "ltr"? "right" : "left";
543 if (!node.hasAttribute("dragover"))
544 node.setAttribute("dragover", value);
546 node.removeAttribute("dragover");
550 function addNewToolbar()
552 var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
553 .getService(Components.interfaces.nsIPromptService);
555 var stringBundle = document.getElementById("stringBundle");
556 var message = stringBundle.getString("enterToolbarName");
557 var title = stringBundle.getString("enterToolbarTitle");
561 // Quitting from the toolbar dialog while the new toolbar prompt is up
562 // can cause things to become unresponsive on the Mac. Until dialog modality
563 // is fixed (395465), disable the "Done" button explicitly.
564 var doneButton = document.getElementById("donebutton");
565 doneButton.disabled = true;
569 if (!promptService.prompt(window, title, message, name, null, {})) {
570 doneButton.disabled = false;
575 message = stringBundle.getFormattedString("enterToolbarBlank", [name.value]);
579 var dupeFound = false;
581 // Check for an existing toolbar with the same display name
582 for (let i = 0; i < gToolbox.childNodes.length; ++i) {
583 var toolbar = gToolbox.childNodes[i];
584 var toolbarName = toolbar.getAttribute("toolbarname");
586 if (toolbarName == name.value &&
587 toolbar.getAttribute("type") != "menubar" &&
588 toolbar.nodeName == 'toolbar') {
597 message = stringBundle.getFormattedString("enterToolbarDup", [name.value]);
600 gToolbox.appendCustomToolbar(name.value, "");
604 doneButton.disabled = false;
608 * Restore the default set of buttons to fixed toolbars,
609 * remove all custom toolbars, and rebuild the palette.
611 function restoreDefaultSet()
613 // Unwrap the items on the toolbar.
614 unwrapToolbarItems();
616 // Remove all of the customized toolbars.
617 var child = gToolbox.lastChild;
619 if (child.hasAttribute("customindex")) {
620 var thisChild = child;
621 child = child.previousSibling;
622 thisChild.currentSet = "__empty";
623 gToolbox.removeChild(thisChild);
625 child = child.previousSibling;
629 // Restore the defaultset for fixed toolbars.
630 forEachCustomizableToolbar(function (toolbar) {
631 var defaultSet = toolbar.getAttribute("defaultset");
633 toolbar.currentSet = defaultSet;
636 // Restore the default icon size and mode.
637 document.getElementById("smallicons").checked = (updateIconSize() == "small");
638 document.getElementById("modelist").value = updateToolbarMode();
640 // Now rebuild the palette.
643 // Now re-wrap the items on the toolbar.
646 toolboxChanged("reset");
649 function updateIconSize(aSize) {
650 return updateToolboxProperty("iconsize", aSize, "large");
653 function updateToolbarMode(aModeValue) {
654 var mode = updateToolboxProperty("mode", aModeValue, "icons");
656 var iconSizeCheckbox = document.getElementById("smallicons");
657 iconSizeCheckbox.disabled = mode == "text";
662 function updateToolboxProperty(aProp, aValue, aToolkitDefault) {
663 var toolboxDefault = gToolbox.getAttribute("default" + aProp) ||
666 gToolbox.setAttribute(aProp, aValue || toolboxDefault);
667 gToolboxDocument.persist(gToolbox.id, aProp);
669 forEachCustomizableToolbar(function (toolbar) {
670 var toolbarDefault = toolbar.getAttribute("default" + aProp) ||
672 if (toolbar.getAttribute("lock" + aProp) == "true" &&
673 toolbar.getAttribute(aProp) == toolbarDefault)
676 toolbar.setAttribute(aProp, aValue || toolbarDefault);
677 gToolboxDocument.persist(toolbar.id, aProp);
680 return aValue || toolboxDefault;
683 function forEachCustomizableToolbar(callback) {
684 Array.filter(gToolbox.childNodes, isCustomizableToolbar).forEach(callback);
687 function isCustomizableToolbar(aElt)
689 return aElt.localName == "toolbar" &&
690 aElt.getAttribute("customizable") == "true";
693 function isSpecialItem(aElt)
695 return aElt.localName == "toolbarseparator" ||
696 aElt.localName == "toolbarspring" ||
697 aElt.localName == "toolbarspacer";
700 function isToolbarItem(aElt)
702 return aElt.localName == "toolbarbutton" ||
703 aElt.localName == "toolbaritem" ||
704 aElt.localName == "toolbarseparator" ||
705 aElt.localName == "toolbarspring" ||
706 aElt.localName == "toolbarspacer";
709 ///////////////////////////////////////////////////////////////////////////
710 //// Drag and Drop observers
712 function onToolbarDragLeave(aEvent)
714 if (gCurrentDragOverItem)
715 setDragActive(gCurrentDragOverItem, false);
718 function onToolbarDragStart(aEvent)
720 var documentId = gToolboxDocument.documentElement.id;
722 var item = aEvent.target;
723 while (item && item.localName != "toolbarpaletteitem")
724 item = item.parentNode;
726 item.setAttribute("dragactive", "true");
728 var dt = aEvent.dataTransfer;
729 dt.setData("text/toolbarwrapper-id/" + documentId, item.firstChild.id);
730 dt.effectAllowed = "move";
733 function onToolbarDragOver(aEvent)
735 var documentId = gToolboxDocument.documentElement.id;
736 if (!aEvent.dataTransfer.types.contains("text/toolbarwrapper-id/" + documentId))
739 var toolbar = aEvent.target;
740 var dropTarget = aEvent.target;
741 while (toolbar && toolbar.localName != "toolbar") {
742 dropTarget = toolbar;
743 toolbar = toolbar.parentNode;
746 // Make sure we are dragging over a customizable toolbar.
747 if (!toolbar || !isCustomizableToolbar(toolbar)) {
748 gCurrentDragOverItem = null;
752 var previousDragItem = gCurrentDragOverItem;
754 if (dropTarget.localName == "toolbar") {
755 gCurrentDragOverItem = dropTarget;
757 gCurrentDragOverItem = null;
759 var direction = window.getComputedStyle(dropTarget.parentNode, null).direction;
760 var dropTargetCenter = dropTarget.boxObject.x + (dropTarget.boxObject.width / 2);
762 if (direction == "ltr")
763 dragAfter = aEvent.clientX > dropTargetCenter;
765 dragAfter = aEvent.clientX < dropTargetCenter;
768 gCurrentDragOverItem = dropTarget.nextSibling;
769 if (!gCurrentDragOverItem)
770 gCurrentDragOverItem = toolbar;
772 gCurrentDragOverItem = dropTarget;
775 if (previousDragItem && gCurrentDragOverItem != previousDragItem) {
776 setDragActive(previousDragItem, false);
779 setDragActive(gCurrentDragOverItem, true);
781 aEvent.preventDefault();
782 aEvent.stopPropagation();
785 function onToolbarDrop(aEvent)
787 if (!gCurrentDragOverItem)
790 setDragActive(gCurrentDragOverItem, false);
792 var documentId = gToolboxDocument.documentElement.id;
793 var draggedItemId = aEvent.dataTransfer.getData("text/toolbarwrapper-id/" + documentId);
794 if (gCurrentDragOverItem.id == draggedItemId)
797 var toolbar = aEvent.target;
798 while (toolbar.localName != "toolbar")
799 toolbar = toolbar.parentNode;
801 var draggedPaletteWrapper = document.getElementById("wrapper-"+draggedItemId);
802 if (!draggedPaletteWrapper) {
803 // The wrapper has been dragged from the toolbar.
804 // Get the wrapper from the toolbar document and make sure that
805 // it isn't being dropped on itself.
806 var wrapper = gToolboxDocument.getElementById("wrapper-"+draggedItemId);
807 if (wrapper == gCurrentDragOverItem)
810 // Don't allow non-removable kids (e.g., the menubar) to move.
811 if (wrapper.firstChild.getAttribute("removable") != "true")
814 // Remove the item from its place in the toolbar.
815 wrapper.parentNode.removeChild(wrapper);
817 // Determine which toolbar we are dropping on.
818 var dropToolbar = null;
819 if (gCurrentDragOverItem.localName == "toolbar")
820 dropToolbar = gCurrentDragOverItem;
822 dropToolbar = gCurrentDragOverItem.parentNode;
824 // Insert the item into the toolbar.
825 if (gCurrentDragOverItem != dropToolbar)
826 dropToolbar.insertBefore(wrapper, gCurrentDragOverItem);
828 dropToolbar.appendChild(wrapper);
830 // The item has been dragged from the palette
832 // Create a new wrapper for the item. We don't know the id yet.
833 var wrapper = createWrapper("", gToolboxDocument);
835 // Ask the toolbar to clone the item's template, place it inside the wrapper, and insert it in the toolbar.
836 var newItem = toolbar.insertItem(draggedItemId, gCurrentDragOverItem == toolbar ? null : gCurrentDragOverItem, wrapper);
838 // Prepare the item and wrapper to look good on the toolbar.
839 cleanupItemForToolbar(newItem, wrapper);
840 wrapper.id = "wrapper-"+newItem.id;
841 wrapper.flex = newItem.flex;
843 // Remove the wrapper from the palette.
844 var currentRow = draggedPaletteWrapper.parentNode;
845 if (draggedItemId != "separator" &&
846 draggedItemId != "spring" &&
847 draggedItemId != "spacer")
849 currentRow.removeChild(draggedPaletteWrapper);
852 // Pull the first child of the next row up
854 var nextRow = currentRow.nextSibling;
857 var last = currentRow.lastChild;
858 var first = currentRow.firstChild;
861 currentRow.parentNode.removeChild(currentRow);
865 if (last.localName == "spacer") {
866 var flex = last.getAttribute("flex");
867 last.setAttribute("flex", ++flex);
868 // Reflow doesn't happen for some reason. Trigger it with a hide/show. ICK! -dwh
873 // Make a spacer and give it a flex of 1.
874 var spacer = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
876 spacer.setAttribute("flex", "1");
877 currentRow.appendChild(spacer);
882 currentRow.appendChild(nextRow.firstChild);
883 currentRow = currentRow.nextSibling;
888 gCurrentDragOverItem = null;
893 function onPaletteDragOver(aEvent)
895 var documentId = gToolboxDocument.documentElement.id;
896 if (aEvent.dataTransfer.types.contains("text/toolbarwrapper-id/" + documentId))
897 aEvent.preventDefault();
900 function onPaletteDrop(aEvent)
902 var documentId = gToolboxDocument.documentElement.id;
903 var itemId = aEvent.dataTransfer.getData("text/toolbarwrapper-id/" + documentId);
905 var wrapper = gToolboxDocument.getElementById("wrapper-"+itemId);
907 // Don't allow non-removable kids (e.g., the menubar) to move.
908 if (wrapper.firstChild.getAttribute("removable") != "true")
911 var wrapperType = wrapper.getAttribute("type");
912 if (wrapperType != "separator" &&
913 wrapperType != "spacer" &&
914 wrapperType != "spring") {
915 restoreItemForToolbar(wrapper.firstChild, wrapper);
916 appendPaletteItem(document.importNode(wrapper.firstChild, true));
917 gToolbox.palette.appendChild(wrapper.firstChild);
920 // The item was dragged out of the toolbar.
921 wrapper.parentNode.removeChild(wrapper);