3 <!-- ***** BEGIN LICENSE BLOCK *****
4 - Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 - The contents of this file are subject to the Mozilla Public License Version
7 - 1.1 (the "License"); you may not use this file except in compliance with
8 - the License. You may obtain a copy of the License at
9 - http://www.mozilla.org/MPL/
11 - Software distributed under the License is distributed on an "AS IS" basis,
12 - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 - for the specific language governing rights and limitations under the
16 - The Original Code is BlueGriffon.
18 - The Initial Developer of the Original Code is
19 - Disruptive Innovations SARL.
20 - Portions created by the Initial Developer are Copyright (C) 2006
21 - the Initial Developer. All Rights Reserved.
24 - Daniel Glazman (daniel.glazman@disruptive-innovations.com), Original Author
26 - Alternatively, the contents of this file may be used under the terms of
27 - either the GNU General Public License Version 2 or later (the "GPL"), or
28 - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 - in which case the provisions of the GPL or the LGPL are applicable instead
30 - of those above. If you wish to allow use of your version of this file only
31 - under the terms of either the GPL or the LGPL, and not to allow others to
32 - use your version of this file under the terms of the MPL, indicate your
33 - decision by deleting the provisions above and replace them with the notice
34 - and other provisions required by the LGPL or the GPL. If you do not delete
35 - the provisions above, a recipient may use your version of this file under
36 - the terms of any one of the MPL, the GPL or the LGPL.
38 - ***** END LICENSE BLOCK ***** -->
41 <!ENTITY % sidebarDTD SYSTEM "chrome://bluegriffon/locale/sidebar.dtd" >
45 <bindings id="sidebarBindings"
46 xmlns="http://www.mozilla.org/xbl"
47 xmlns:html="http://www.w3.org/1999/xhtml"
48 xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
49 xmlns:xbl="http://www.mozilla.org/xbl">
51 <binding id="sidebaritems">
54 <stylesheet src="chrome://bluegriffon/skin/sidebar.css"/>
61 // let's find all sidebaritems living in their own window
62 var items = this.getElementsByAttribute("standalone", "true");
63 for (var i = 0; i < items.length; i++)
66 // retrieve all the data it carries
67 var name = item.getAttribute("name");
68 var properties = item.getAttribute("properties");
69 var src = item.getAttribute("src");
70 // let's see if we have a localized string for that
72 var label = item.getAttribute("title");
75 window.openDialog("chrome://bluegriffon/content/dialogs/standaloneSidebar.xul","_blank",
76 "all,dialog=no", name,
77 label ? label : name, src, item);
83 <property name="mItems"
85 onget="return this.getElementsByTagName('sidebaritem');" />
87 <method name="_getItemsFromName">
88 <parameter name="aName"/>
91 return this.getElementsByAttribute("name", aName);
100 <binding id="sidebar">
103 <stylesheet src="chrome://bluegriffon/skin/sidebar.css"/>
107 <xul:hbox align="center" class="titlebox"
108 ondragover="this.parentNode.onDragOver(event, this)"
109 ondragleave="this.parentNode.onDragLeave(this)"
110 ondrop="this.parentNode.onDrop(event)">
111 <xul:toolbarbutton label="&addSidebarContent.label;" class="sidebar-morebutton" type="menu"
112 tooltiptext="&addSidebarContent.tooltip;">
113 <xul:menupopup onpopupshowing="this.parentNode.parentNode.parentNode._updateMissingSidebarItems(this)"/>
115 <xul:spacer flex="1"/>
116 <xul:toolbarbutton class="sidebar-closebutton"
117 tooltiptext="&closeSidebar.tooltip;"
118 oncommand="this.parentNode.parentNode._close()"/>
120 <xul:vbox flex="1" anonid="content">
127 <field name="mXUL_NS">"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"</field>
129 <field name="mSidebarItems">null</field>
130 <field name="mOtherSidebar">null</field>
131 <field name="mSplitter">null</field>
133 <property name="mContents"
135 onget="return this.getElementsByTagName('sidebarcontent');" />
136 <property name="mSplitters"
138 onget="return this.getElementsByTagName('splitter');" />
141 <parameter name="aSidebarItems"/>
142 <parameter name="aOtherSidebar"/>
143 <parameter name="aSplitter"/>
150 this.mSidebarItems = aSidebarItems;
151 this.mOtherSidebar = aOtherSidebar;
152 this.mSplitter = aSplitter;
154 // get the list of sidebaritems shown in this sidebar
155 var itemsAttr = this.getAttribute("sidebaritems");
156 var itemsArray = itemsAttr.split(",");
157 var ordinalIndex = 1;
158 for (var i = 0; i < itemsArray.length; i++)
163 // now, find the corresponding sidebaritem
164 var item = aSidebarItems._getItemsFromName(itemsArray[i]).item(0);
167 // retrieve all the data it carries
168 var properties = item.getAttribute("properties");
169 var src = item.getAttribute("src");
170 // the height on the sidebaritem is persistent, and is updated
171 // each time a splitter between sidebarcontent elements is moved
172 var height = item.getAttribute("height");
174 // let's see if we have a localized string for that
176 var label = item.getAttribute("title");
178 // create a sidebarcontent
179 var sidebarcontent = document.createElementNS(this.mXUL_NS, "sidebarcontent");
180 // set the name and the height
181 sidebarcontent.setAttribute("name", itemsArray[i]);
182 sidebarcontent.setAttribute("height", height);
183 // append it to the sidebar
184 this.appendChild(sidebarcontent);
186 sidebarcontent._setLabel(label ? label : itemsArray[i]);
187 // now create the iframe
188 var iframe = document.createElementNS(this.mXUL_NS, "iframe");
189 iframe.setAttribute("flex", "1");
190 iframe.setAttribute("src", src);
191 sidebarcontent.appendChild(iframe);
193 sidebarcontent.setAttribute("ordinal", ordinalIndex++);
195 // and this is not the last sidebaritem for this sidebar,
196 // let's add a splitter
197 if (i < itemsArray.length - 1)
199 var splitter = document.createElementNS(this.mXUL_NS, "splitter");
200 // we need to know when the splitter is moved.
201 splitter.setAttribute("oncommand",
202 "this.parentNode._setPersistentHeights()");
203 // append the splitter to the sidebar
204 splitter.setAttribute("ordinal", ordinalIndex++);
205 this.appendChild(splitter);
215 <method name="_setPersistentHeights">
219 // early way out if no sidebaritems
220 if (!this.mSidebarItems)
223 // browse all sidebarcontent elements in this sidebar
224 var contents = this.mContents;
225 for (var i = 0; i < contents.length; i++)
227 var child = contents[i];
228 // find their unique identifier
229 var name = child.getAttribute("name");
232 // find the corresponding sidebaritem
233 var items = this.mSidebarItems._getItemsFromName(name);
234 if (items && items.length)
237 // get the sidebarcontent's height and store it in the
239 item.setAttribute("height", child.getAttribute("height"));
240 // make it persist so we get it back next session
241 document.persist(item.getAttribute("id"), "height");
250 <method name="_updatePersistentItemsList">
254 function compare(a, b) {
255 return a.ordinal - b.ordinal;
258 // early way out if no sidebaritems
259 if (!this.mSidebarItems)
262 // find all sidebarcontents in the current sidebar
263 var contents = this.mContents;
264 if (!contents || !contents.length)
266 // none, zilch, nada... Make that persist and leave
267 this.setAttribute("sidebaritems", "");
268 document.persist(this, "sidebaritems");
272 // make an array storing all sidebarcontents
274 for (var i = 0; i < contents.length; i++)
275 itemsArray.push( contents[i] );
277 // sort it by ordinal
278 itemsArray.sort(compare);
280 // now rebuild the sidebaritems attribute on the sidebar
282 for (var i = 0; i < itemsArray.length; i++)
284 var item = itemsArray[i];
285 item.setAttribute("ordinal", i * 2 + 1);
288 newList += item.getAttribute("name");
292 this.setAttribute("sidebaritems", newList);
293 document.persist(this, "sidebaritems");
295 // don't forget to update splitters' ordinal !
296 var splitters = this.mSplitters;
297 for (var i = 0; i < splitters.length; i++)
299 splitters[i].setAttribute("ordinal", i * 2 + 2);
306 <method name="_addToOtherSidebar">
307 <parameter name="aName"/>
308 <parameter name="aTitle"/>
309 <parameter name="aURL"/>
312 this.mOtherSidebar.addContent(aName, aTitle, aURL);
317 <method name="addContent">
318 <parameter name="aName"/>
319 <parameter name="aTitle"/>
320 <parameter name="aURL"/>
323 // what should be the default original for this new content ?
324 var ordinalIndex = this.childNodes.length;
327 var splitter = document.createElementNS(this.mXUL_NS, "splitter");
328 // we need to know when the splitter is moved.
329 splitter.setAttribute("oncommand",
330 "this.parentNode._setPersistentHeights()");
331 // append the splitter to the sidebar
332 splitter.setAttribute("ordinal", ++ordinalIndex);
333 this.appendChild(splitter);
336 // create a sidebarcontent
337 var sidebarcontent = document.createElementNS(this.mXUL_NS, "sidebarcontent");
338 // set the name and the height
339 sidebarcontent.setAttribute("name", aName);
340 // append it to the sidebar
341 this.appendChild(sidebarcontent);
343 sidebarcontent._setLabel(aTitle);
344 // now create the iframe
345 var iframe = document.createElementNS(this.mXUL_NS, "iframe");
346 iframe.setAttribute("flex", "1");
347 iframe.setAttribute("src", aURL);
348 sidebarcontent.appendChild(iframe);
350 sidebarcontent.setAttribute("ordinal", ordinalIndex++);
352 this._updatePersistentItemsList();
357 <method name="_addSidebarItem">
358 <parameter name="aMenuitem"/>
361 this.addContent( aMenuitem.getAttribute("name"),
362 aMenuitem.getAttribute("label"),
363 aMenuitem.getAttribute("src") );
368 <method name="_updateMissingSidebarItems">
369 <parameter name="aPopup"/>
372 // early way out if no sidebaritems
373 if (!this.mSidebarItems)
376 // find all sidebaritems
377 var items = this.mSidebarItems.mItems;
378 var missingItems = {};
379 for (var i = 0; i < items.length; i++)
382 var name = item.getAttribute("name");
383 var title = item.getAttribute("title");
384 var src = item.getAttribute("src");
386 // don't offer to them to a sidebar if they are
387 // already shown in standalone windows
388 if (item.getAttribute("standalone") != "true")
389 missingItems[name] = [ title, src ]
392 // remove from list the ones already in the current sidebar
393 var contents = this.mContents;
394 for (var i = 0; i < contents.length; i++)
396 var content = contents[i];
397 name = content.getAttribute("name");
398 delete missingItems[name];
400 // and remove from list the ones already in the other sidebar
402 if (this.mOtherSidebar)
404 contents = this.mOtherSidebar.mContents;
405 for (var i = 0; i < contents.length; i++)
407 content = contents[i];
408 name = content.getAttribute("name");
409 delete missingItems[name];
414 while (aPopup.hasChildNodes())
415 aPopup.removeChild(aPopup.lastChild);
418 for (i in missingItems)
421 var menuitem = document.createElementNS(this.mXUL_NS, "menuitem");
422 var label = missingItems[i][0];
423 menuitem.setAttribute("label", label ? label : i);
424 menuitem.setAttribute("tooltiptext", label ? label : i);
425 menuitem.setAttribute("name", i);
426 menuitem.setAttribute("src", missingItems[i][1]);
427 menuitem.setAttribute("oncommand", "this.parentNode.parentNode.parentNode.parentNode._addSidebarItem(this)");
428 aPopup.appendChild(menuitem);
432 var menuitem = document.createElementNS(this.mXUL_NS, "menuitem");
433 menuitem.setAttribute("label", " -- ");
434 menuitem.setAttribute("disabled", "true");
435 aPopup.appendChild(menuitem);
441 <method name="_close">
446 this.mSplitter.setAttribute("state", "collapsed");
447 document.persist(this.mSplitter.getAttribute("id"), "state");
450 this.setAttribute("collapsed", "true");
455 <method name="onDragOver">
456 <parameter name="aEvent"/>
457 <parameter name="aDropTarget"/>
460 var sidebar = aDropTarget.parentNode;
462 var dt = aEvent.dataTransfer;
463 var hasNode = dt.types.contains("application/x-moz-node");
466 var node = dt.mozGetDataAt("application/x-moz-node", 0);
467 if (node.nodeName.toLowerCase() != "sidebarcontent")
471 if (node.parentNode != sidebar)
473 aDropTarget.setAttribute("style", "background-color: orange");
474 aEvent.preventDefault();
482 <method name="onDragLeave">
483 <parameter name="aDropTarget"/>
486 aDropTarget.removeAttribute("style");
491 <method name="onDrop">
492 <parameter name="aEvent"/>
496 var dt = aEvent.dataTransfer;
497 var e = aEvent.target;
498 while (e && (e.localName.toLowerCase() != "hbox" ||
499 e.className != "titlebox"))
503 var dragSource = dt.mozGetDataAt("application/x-moz-node", 0);
505 dragSource._moveToOtherSidebar();
513 <binding id="sidebarcontent">
516 <stylesheet src="chrome://bluegriffon/skin/sidebarcontent.css"/>
520 <xul:hbox align="center" class="titlebox" anonid="titlebox"
521 ondragover="this.parentNode.onDragOver(event, this)"
522 ondragleave="this.parentNode.onDragLeave(this)"
523 ondrop="this.parentNode.onDrop(event)">
524 <xul:label ondragstart="this.parentNode.parentNode.onDragStart(event, this.parentNode.parentNode)"
525 ondragend="this.parentNode.parentNode.onDragEnd(event, this.parentNode.parentNode)"
526 anonid="name" class="sidebarcontent-name"/>
527 <xul:spacer flex="1"/>
528 <xul:toolbarbutton label="&actions.label;" class="sidebar-arrowbutton" type="menu">
529 <xul:menupopup onpopupshowing="this.parentNode.parentNode.parentNode._updateActionsPopup(this)">
530 <xul:menuitem anonid="detachmenu"
531 label="&detachMenu.label;"
532 accesskey="&detachMenu.accesskey;"
533 oncommand="this.parentNode.parentNode.parentNode.parentNode._detach()" />
535 <xul:menuitem anonid="closemenu"
536 label="&closeMenu.label;"
537 accesskey="&closeMenu.accesskey;"
538 oncommand="this.parentNode.parentNode.parentNode.parentNode._close()"/>
546 <property name="mTitleBox">
549 return document.getAnonymousElementByAttribute(this, "anonid", "titlebox");
554 <property name="mLabel">
557 return this.mTitleBox.firstChild;
562 <property name="mTitle">
565 return this.mLabel.value;
570 <property name="mContent">
573 return this.getElementsByTagName("iframe").item(0);
578 <method name="_updateActionsPopup">
579 <parameter name="aPopup"/>
582 var isFirst = (this.getAttribute("ordinal") == "1");
583 var isLast = (this.getAttribute("ordinal") == this.parentNode.childNodes.length);
584 var moveupmenu = aPopup.getElementsByAttribute("anonid", "moveupmenu")[0];
585 var movedownmenu = aPopup.getElementsByAttribute("anonid", "movedownmenu")[0];
586 moveupmenu.setAttribute("disabled", isFirst);
587 movedownmenu.setAttribute("disabled", isLast);
588 var moveothermenu = aPopup.getElementsByAttribute("anonid", "moveothermenu")[0];
589 if (this.parentNode.mOtherSidebar)
590 moveothermenu.removeAttribute("disabled");
592 moveothermenu.setAttribute("disabled", "true");
597 <method name="_setLabel">
598 <parameter name="aLabel"/>
601 this.mLabel.value = aLabel;
606 <method name="_close">
609 var currentOrdinal = parseInt(this.getAttribute("ordinal"));
610 var sidebar = this.parentNode;
611 if (currentOrdinal == 1)
613 // we have a splitter after the current item and we have
615 var splitterOrdinal = currentOrdinal + 1;
616 var splitters = this.parentNode.getElementsByAttribute("ordinal", splitterOrdinal);
617 if (splitters && splitters.length)
618 sidebar.removeChild(splitters[0]);
622 // we have a splitter before the current item and we have
624 var splitterOrdinal = currentOrdinal - 1;
625 var splitters = this.parentNode.getElementsByAttribute("ordinal", splitterOrdinal);
626 if (splitters && splitters.length)
627 sidebar.removeChild(splitters[0]);
629 sidebar.removeChild(this);
631 sidebar._updatePersistentItemsList();
636 <method name="_move">
637 <parameter name="aOffset"/>
640 // we always have a splitter before the current element
641 // as we always have another sidebarcontent before the splitter
642 var currentOrdinal = this.getAttribute("ordinal");
643 var otherOrdinal = parseInt(currentOrdinal) + aOffset;
644 var otherContent = this.parentNode.getElementsByAttribute("ordinal", otherOrdinal).item(0);
645 otherContent.setAttribute("ordinal", currentOrdinal);
646 this.setAttribute("ordinal", otherOrdinal);
648 this.parentNode._updatePersistentItemsList();
653 <method name="_moveToOtherSidebar">
656 var sidebar = this.parentNode;
657 var title = this.mTitle;
658 var src = this.mContent.getAttribute("src");
659 var name = this.getAttribute("name");
661 // we cannot really move a sidebarcontent from one
662 // sidebar to the other because the iframe's context is
664 //sidebar._addToOtherSidebar(name, title, src);
669 var ordinalIndex = sidebar.mOtherSidebar.childNodes.length;
673 var splitter = document.createElementNS(sidebar.mXUL_NS, "splitter");
674 // we need to know when the splitter is moved.
675 splitter.setAttribute("oncommand",
676 "this.parentNode._setPersistentHeights()");
677 // append the splitter to the sidebar
678 splitter.setAttribute("ordinal", ++ordinalIndex);
679 sidebar.mOtherSidebar.appendChild(splitter);
681 this.setAttribute("ordinal", ++ordinalIndex);
683 if (this.previousSibling &&
684 this.previousSibling.nodeName.toLowerCase() == "splitter")
685 sidebar.removeChild(this.previousSibling);
687 sidebar.mOtherSidebar.appendChild(this);
688 this.setAttribute("name", name);
689 this.mLabel.value = title;
691 sidebar._updatePersistentItemsList()
692 sidebar.mOtherSidebar._updatePersistentItemsList();
697 <method name="_detach">
700 var label = this.mTitle;
701 var name = this.getAttribute("name");
702 // find the corresponding sidebaritem
703 var sidebar = this.parentNode;
704 var items = sidebar.mSidebarItems._getItemsFromName(name);
705 if (items && items.length)
708 // remember that we want this sidebaritem to be floating alone
709 item.setAttribute("standalone", "true");
710 document.persist(item.getAttribute("id"), "standalone");
712 var src = item.getAttribute("src");
713 // make it float, make it float
714 window.openDialog("chrome://bluegriffon/content/dialogs/standaloneSidebar.xul","_blank",
715 "chrome,modal=no,titlebar,scrollbars=yes,resizable", name, label, src, item);
724 <method name="onDragOver">
725 <parameter name="aEvent"/>
726 <parameter name="aDropTarget"/>
729 var sidebarContent = aDropTarget.parentNode;
730 var dt = aEvent.dataTransfer;
731 var hasNode = dt.types.contains("application/x-moz-node");
734 var node = dt.mozGetDataAt("application/x-moz-node", 0);
735 if (node.nodeName.toLowerCase() != "sidebarcontent")
737 if (node.getAttribute("name") != aDropTarget.parentNode.getAttribute("name"))
739 aDropTarget.setAttribute("style", "background-color: orange");
740 aEvent.preventDefault();
747 <method name="onDragLeave">
748 <parameter name="aDropTarget"/>
751 aDropTarget.removeAttribute("style");
756 <method name="onDragStart">
757 <parameter name="aEvent"/>
758 <parameter name="aDragSource"/>
762 var dt = aEvent.dataTransfer;
763 dt.setData("text/plain", aDragSource.mTitle);
764 dt.mozSetDataAt("application/x-moz-node", aDragSource, 0);
765 dt.effectAllowed = "all";
770 <method name="onDragEnd">
771 <parameter name="aEvent"/>
772 <parameter name="aDragSource"/>
776 var dt = aEvent.dataTransfer;
781 <method name="onDrop">
782 <parameter name="aEvent"/>
786 var dt = aEvent.dataTransfer;
787 var e = aEvent.target;
788 while (e && e.nodeName.toLowerCase() != "sidebarcontent")
792 var dragSource = dt.mozGetDataAt("application/x-moz-node", 0);
794 var sameSidebar = (e.parentNode == dragSource.parentNode);
796 dragSource._moveToOtherSidebar();
798 var offset = ( parseInt(dragSource.getAttribute("ordinal")) <
799 parseInt(e.getAttribute("ordinal")) ) ?
802 while (parseInt(e.getAttribute("ordinal")) -
803 parseInt(dragSource.getAttribute("ordinal")) +
805 dragSource._move(offset);