PageRenderTime 18ms CodeModel.GetById 10ms app.highlight 3ms RepoModel.GetById 1ms app.codeStats 1ms

/toolkit/content/widgets/popup.xml

http://github.com/zpao/v8monkey
XML | 552 lines | 496 code | 53 blank | 3 comment | 0 complexity | b74c3a2054b6d8987bda064125610dce MD5 | raw file
  1<?xml version="1.0"?>
  2
  3<bindings id="popupBindings"
  4   xmlns="http://www.mozilla.org/xbl"
  5   xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
  6   xmlns:xbl="http://www.mozilla.org/xbl">
  7
  8  <binding id="popup-base">
  9    <resources>
 10      <stylesheet src="chrome://global/skin/popup.css"/>
 11    </resources>
 12
 13    <implementation implements="nsIDOMXULPopupElement">
 14      <property name="label" onget="return this.getAttribute('label');"
 15                             onset="this.setAttribute('label', val); return val;"/>
 16      <property name="position" onget="return this.getAttribute('position');"
 17                                onset="this.setAttribute('position', val); return val;"/>
 18      <property name="popupBoxObject">
 19        <getter>
 20          return this.boxObject.QueryInterface(Components.interfaces.nsIPopupBoxObject);
 21        </getter>
 22      </property>
 23
 24      <property name="state" readonly="true"
 25                onget="return this.popupBoxObject.popupState"/>
 26
 27      <property name="triggerNode" readonly="true"
 28                onget="return this.popupBoxObject.triggerNode"/>
 29
 30      <property name="anchorNode" readonly="true"
 31                onget="return this.popupBoxObject.anchorNode"/>
 32
 33      <method name="openPopup">
 34        <parameter name="aAnchorElement"/>
 35        <parameter name="aPosition"/>
 36        <parameter name="aX"/>
 37        <parameter name="aY"/>
 38        <parameter name="aIsContextMenu"/>
 39        <parameter name="aAttributesOverride"/>
 40        <parameter name="aTriggerEvent"/>
 41        <body>
 42        <![CDATA[
 43          try {
 44            var popupBox = this.popupBoxObject;
 45            if (popupBox)
 46              popupBox.openPopup(aAnchorElement, aPosition, aX, aY,
 47                                 aIsContextMenu, aAttributesOverride, aTriggerEvent);
 48          } catch(e) {}
 49        ]]>
 50        </body>
 51      </method>
 52
 53      <method name="openPopupAtScreen">
 54        <parameter name="aX"/>
 55        <parameter name="aY"/>
 56        <parameter name="aIsContextMenu"/>
 57        <parameter name="aTriggerEvent"/>
 58        <body>
 59        <![CDATA[
 60          try {
 61            var popupBox = this.popupBoxObject;
 62            if (popupBox)
 63              popupBox.openPopupAtScreen(aX, aY, aIsContextMenu, aTriggerEvent);
 64          } catch(e) {}
 65        ]]>
 66        </body>
 67      </method>
 68      
 69      <method name="showPopup">
 70        <parameter name="element"/>
 71        <parameter name="xpos"/>
 72        <parameter name="ypos"/>
 73        <parameter name="popuptype"/>
 74        <parameter name="anchoralignment"/>
 75        <parameter name="popupalignment"/>
 76        <body>
 77        <![CDATA[
 78          var popupBox = null;
 79          var menuBox = null;
 80          try {
 81            popupBox = this.popupBoxObject;
 82          } catch(e) {}
 83          try {
 84            menuBox = this.parentNode.boxObject;
 85          } catch(e) {}
 86          if (menuBox instanceof Components.interfaces.nsIMenuBoxObject)
 87            menuBox.openMenu(true);
 88          else if (popupBox)
 89            popupBox.showPopup(element, this, xpos, ypos, popuptype, anchoralignment, popupalignment);
 90        ]]>
 91        </body>
 92      </method>
 93      
 94      <method name="hidePopup">
 95        <body>
 96        <![CDATA[
 97          var popupBox = null;
 98          var menuBox = null;
 99          try {
100            popupBox = this.boxObject.QueryInterface(Components.interfaces.nsIPopupBoxObject);
101          } catch(e) {}
102          try {
103            menuBox = this.parentNode.boxObject;
104          } catch(e) {}
105          if (menuBox instanceof Components.interfaces.nsIMenuBoxObject)
106            menuBox.openMenu(false);
107          else if (popupBox)
108            popupBox.hidePopup();
109        ]]>
110        </body>
111      </method>
112
113      <property name="autoPosition">
114        <getter>
115        <![CDATA[
116          return this.popupBoxObject.autoPosition;
117        ]]>
118        </getter>
119        <setter>
120        <![CDATA[
121          return this.popupBoxObject.autoPosition = val;
122        ]]>
123        </setter>
124      </property>
125      
126      <method name="enableKeyboardNavigator">
127        <parameter name="aEnableKeyboardNavigator"/>
128        <body>
129        <![CDATA[
130          this.popupBoxObject.enableKeyboardNavigator(aEnableKeyboardNavigator);
131        ]]>
132        </body>
133      </method>
134      
135      <method name="enableRollup">
136        <parameter name="aEnableRollup"/>
137        <body>
138        <![CDATA[
139          this.popupBoxObject.enableRollup(aEnableRollup);
140        ]]>
141        </body>
142      </method>
143      
144      <method name="sizeTo">
145        <parameter name="aWidth"/>
146        <parameter name="aHeight"/>
147        <body>
148        <![CDATA[
149          this.popupBoxObject.sizeTo(aWidth, aHeight);
150        ]]>
151        </body>
152      </method>
153      
154      <method name="moveTo">
155        <parameter name="aLeft"/>
156        <parameter name="aTop"/>
157        <body>
158        <![CDATA[
159          this.popupBoxObject.moveTo(aLeft, aTop);
160        ]]>
161        </body>
162      </method>
163
164      <method name="getOuterScreenRect">
165        <body>
166        <![CDATA[
167          return this.popupBoxObject.getOuterScreenRect();
168        ]]>
169        </body>
170      </method>
171    </implementation>     
172
173  </binding>
174
175  <binding id="popup"
176           extends="chrome://global/content/bindings/popup.xml#popup-base">
177    
178    <content>
179      <xul:arrowscrollbox class="popup-internal-box" flex="1" orient="vertical"
180                          smoothscroll="false">
181        <children/>
182      </xul:arrowscrollbox>
183    </content>
184
185    <implementation implements="nsIAccessibleProvider">
186      <property name="accessibleType" readonly="true">
187        <getter>
188          <![CDATA[
189              return Components.interfaces.nsIAccessibleProvider.XULMenupopup;
190            ]]>
191        </getter>
192      </property>
193    </implementation>
194
195    <handlers>
196      <handler event="popupshowing" phase="target">
197        <![CDATA[
198          var array = [];
199          var width = 0;
200          for (var menuitem = this.firstChild; menuitem; menuitem = menuitem.nextSibling) {
201            if (menuitem.localName == "menuitem" && menuitem.hasAttribute("acceltext")) {
202              var accel = document.getAnonymousElementByAttribute(menuitem, "anonid", "accel");
203              if (accel && accel.boxObject) {
204                array.push(accel);
205                if (accel.boxObject.width > width)
206                  width = accel.boxObject.width;
207              }
208            }
209          }
210          for (var i = 0; i < array.length; i++)
211            array[i].width = width;
212        ]]>
213      </handler>
214    </handlers>
215  </binding>
216
217  <binding id="panel"
218           extends="chrome://global/content/bindings/popup.xml#popup-base">
219    <!-- This separate binding for dialog-like panels - not menu, list or autocomplete popups
220         exposes the popup as an alert or a pane, depending on whether it is always intended
221         to get keyboard navigation when it opens -->
222    <implementation implements="nsIDOMXULPopupElement, nsIAccessibleProvider">
223      <property name="accessibleType" readonly="true">
224        <getter>
225          <![CDATA[
226          return (this.getAttribute("noautofocus") == "true") ?
227                       Components.interfaces.nsIAccessibleProvider.XULAlert :
228                       Components.interfaces.nsIAccessibleProvider.XULPane;
229        ]]></getter>
230      </property>
231      <field name="_prevFocus">0</field>
232      <field name="_dragBindingAlive">true</field>
233      <constructor>
234      <![CDATA[
235        if (this.getAttribute("backdrag") == "true" && !this._draggableStarted) {
236          this._draggableStarted = true;
237          try {
238            let tmp = {};
239            Components.utils.import("resource://gre/modules/WindowDraggingUtils.jsm", tmp);
240            let draghandle = new tmp.WindowDraggingElement(this);
241            draghandle.mouseDownCheck = function () this._dragBindingAlive;
242          } catch (e) {}
243        }
244      ]]>
245      </constructor>
246    </implementation>
247    
248    <handlers>
249      <handler event="popupshowing"><![CDATA[
250        // Capture the previous focus before has a chance to get set inside the panel
251        try {
252          this._prevFocus = document.commandDispatcher.focusedElement;
253          if (!this._prevFocus)  // Content window has focus
254            this._prevFocus = document.commandDispatcher.focusedWindow;
255        } catch (ex) {
256          this._prevFocus = document.activeElement;
257        }
258      ]]></handler>
259      <handler event="popupshown"><![CDATA[
260        // Fire event for accessibility APIs
261        var alertEvent = document.createEvent("Events");
262        alertEvent.initEvent("AlertActive", true, true);
263        this.dispatchEvent(alertEvent);
264       ]]></handler>
265      <handler event="popuphiding"><![CDATA[
266        try {
267          this._currentFocus = document.commandDispatcher.focusedElement;
268        } catch (e) {
269          this._currentFocus = document.activeElement;
270        }
271      ]]></handler>
272      <handler event="popuphidden"><![CDATA[
273        var currentFocus = this._currentFocus;
274        var prevFocus = this._prevFocus;
275        this._currentFocus = null;
276        this._prevFocus = null;
277        if (prevFocus && currentFocus && this.getAttribute("norestorefocus") != "true") {
278          // Try to restore focus
279          try {
280            if (document.commandDispatcher.focusedWindow != window)
281              return; // Focus has already been set to a window outside of this panel
282          } catch(ex) {}
283          while (currentFocus) {
284            if (currentFocus == this) {
285              // Focus was set on an element inside this panel,
286              // so we need to move it back to where it was previously
287              try {
288                let fm = Components.classes["@mozilla.org/focus-manager;1"]
289                                   .getService(Components.interfaces.nsIFocusManager);
290                fm.setFocus(prevFocus, fm.FLAG_NOSCROLL);
291              } catch(e) {
292                prevFocus.focus();
293              }
294              return;
295            }
296            currentFocus = currentFocus.parentNode;
297          }
298        }
299      ]]></handler>
300    </handlers>
301  </binding>
302
303  <binding id="arrowpanel" extends="chrome://global/content/bindings/popup.xml#panel">
304    <content flip="both" side="top" position="bottomcenter topleft">
305      <xul:box anonid="container" class="panel-arrowcontainer" flex="1">
306        <xul:box anonid="arrowbox" class="panel-arrowbox">
307          <xul:image anonid="arrow" class="panel-arrow"/>
308        </xul:box>
309        <xul:box class="panel-arrowcontent" flex="1">
310          <xul:box class="panel-inner-arrowcontent" xbl:inherits="align,dir,orient,pack" flex="1">
311            <children/>
312            <xul:box class="panel-inner-arrowcontentfooter" xbl:inherits="footertype" hidden="true"/>
313          </xul:box>
314        </xul:box>
315      </xul:box>
316    </content>
317    <implementation>
318      <field name="_fadeTimer">null</field>
319    </implementation>
320    <handlers>
321      <handler event="popupshowing">
322      <![CDATA[
323        var container = document.getAnonymousElementByAttribute(this, "anonid", "container");
324        var arrowbox = document.getAnonymousElementByAttribute(this, "anonid", "arrowbox");
325        var arrow = document.getAnonymousElementByAttribute(this, "anonid", "arrow");
326
327        var anchor = this.anchorNode;
328        if (!anchor) {
329          arrow.hidden = true;
330          return;
331        }
332
333        // Returns whether the first float is smaller than the second float or
334        // equals to it in a range of epsilon.
335        function smallerTo(aFloat1, aFloat2, aEpsilon)
336        {
337          return aFloat1 <= (aFloat2 + aEpsilon);
338        }
339
340        let popupRect = this.getBoundingClientRect();
341        let popupLeft = window.mozInnerScreenX + popupRect.left;
342        let popupTop = window.mozInnerScreenY + popupRect.top;
343        let popupRight = popupLeft + popupRect.width;
344        let popupBottom = popupTop + popupRect.height;
345
346        let anchorRect = anchor.getBoundingClientRect();
347        let anchorLeft = anchor.ownerDocument.defaultView.mozInnerScreenX + anchorRect.left;
348        let anchorTop = anchor.ownerDocument.defaultView.mozInnerScreenY + anchorRect.top;
349        let anchorRight = anchorLeft + anchorRect.width;
350        let anchorBottom = anchorTop + anchorRect.height;
351
352        try {
353          let anchorWindow = anchor.ownerDocument.defaultView;
354          if (anchorWindow != window) {
355            let utils = anchorWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
356                                     getInterface(Components.interfaces.nsIDOMWindowUtils);
357            let spp = utils.screenPixelsPerCSSPixel;
358            anchorLeft *= spp;
359            anchorRight *= spp;
360            anchorTop *= spp;
361            anchorBottom *= spp;
362          }
363        } catch(ex) { }
364
365        const epsilon = 0.2;
366
367        var horizPos = smallerTo(popupRight, anchorLeft, epsilon) ? -1 : smallerTo(anchorRight, popupLeft, epsilon) ? 1 : 0;
368        var vertPos = smallerTo(popupBottom, anchorTop, epsilon) ? -1 : smallerTo(anchorBottom, popupTop, epsilon) ? 1 : 0;
369
370        var anchorClass = "";
371        var hideAnchor = false;
372        if (horizPos == 0) {
373          container.orient = "vertical";
374          arrowbox.orient = "";
375          if (vertPos == 0) {
376            hideAnchor = true;
377          }
378          else {
379            let pack = "";
380
381            // We have to guess where to position the arrow given that we don't
382            // have access to the parameters passed to |openPopup|.
383
384            // If the popup is on the left of the anchor.
385            if (smallerTo(popupLeft, anchorLeft, epsilon) && smallerTo(popupRight, anchorRight, epsilon)) {
386              pack = "end";
387            // If the popup is on the right of the anchor.
388            } else if (smallerTo(anchorLeft, popupLeft, epsilon) && smallerTo(anchorRight, popupRight, epsilon)) {
389              pack = "start"; //(popupLeft + popupRect.width / 2 > anchorRight) ? "start" : "end";
390            // If the popup is not on the right nor on the left.
391            // Basically, that means one is above the other and one is bigger
392            // than the other.
393            // In that case, we can't easily choose a position for the arrow so
394            // we have to guess depending on which side the popup is more close to.
395            } else {
396              pack = (Math.abs(popupLeft - anchorLeft) < Math.abs(popupRight - anchorRight)) ? "start" : "end";
397            }
398
399            // In RTL, everything should be inverted.
400            if (window.getComputedStyle(this).direction == "rtl") {
401              pack = (pack == "start") ? "end" : "start";
402            }
403
404            arrowbox.pack = pack;
405
406            if (vertPos == 1) {
407              container.dir = "";
408              anchorClass = "top";
409            }
410            else if (vertPos == -1) {
411              container.dir = "reverse"; 
412              anchorClass = "bottom";
413            }
414          }
415        }
416        else if (vertPos == 0) {
417          container.orient = "";
418          arrowbox.orient = "vertical";
419          if (horizPos == 0) {
420            hideAnchor = true;
421          }
422          else {
423            arrowbox.pack = popupTop + popupRect.height / 2 < anchorTop ? "end" : "start";
424            if (horizPos == 1) {
425              container.dir = "";
426              anchorClass = "left";
427            }
428            else if (horizPos == -1) {
429              container.dir = "reverse";
430              anchorClass = "right";
431            }
432          }
433        }
434        else {
435          hideAnchor = true;
436        }
437        arrow.hidden = hideAnchor;
438        arrow.setAttribute("side", anchorClass);
439        this.setAttribute("side", anchorClass);
440
441        // set fading
442        var fade = this.getAttribute("fade");
443        var fadeDelay = (fade == "fast") ? 1 : fade == "slow" ? 4000 : 0;
444        if (fadeDelay) {
445          this._fadeTimer = setTimeout(function (self) {
446            self.style.opacity = 0.2;
447          }, fadeDelay, this);
448        }
449      ]]>
450      </handler>
451      <handler event="popuphiding" phase="target">
452        clearTimeout(this._fadeTimer);
453        this.style.removeProperty("opacity");
454      </handler>
455      <handler event="transitionend" phase="target">
456      <![CDATA[
457        if (event.propertyName == "opacity") {
458          this.hidePopup();
459          this.style.removeProperty("opacity");
460        }
461      ]]>
462      </handler>
463    </handlers>
464  </binding>
465
466  <binding id="tooltip" extends="chrome://global/content/bindings/popup.xml#popup-base">
467    <content>
468      <children>
469        <xul:label class="tooltip-label" xbl:inherits="xbl:text=label" flex="1"/>
470      </children>
471    </content>
472    
473    <implementation implements="nsIAccessibleProvider">
474      <property name="accessibleType" readonly="true">
475        <getter>
476          return Components.interfaces.nsIAccessibleProvider.XULTooltip;
477        </getter>
478      </property>
479
480      <field name="_mouseOutCount">0</field>
481      <field name="_isMouseOver">false</field>
482      
483      <property name="label"
484                onget="return this.getAttribute('label');"
485                onset="this.setAttribute('label', val); return val;"/>
486    </implementation>
487
488    <handlers>
489      <handler event="mouseover"><![CDATA[
490        var rel = event.relatedTarget;
491        //dump("ENTERING " + (rel ? rel.localName : "null") + "\n");
492        if (!rel)
493          return;
494          
495        // find out if the node we entered from is one of our anonymous children
496        while (rel) {
497          if (rel == this)
498            break;
499          rel = rel.parentNode;
500        }
501
502        // if the exited node is not a descendant of ours, we are entering for the first time
503        if (rel != this)
504          this._isMouseOver = true;
505      ]]></handler>
506
507      <handler event="mouseout"><![CDATA[
508        var rel = event.relatedTarget;
509        //dump("LEAVING " + (rel ? rel.localName : "null") + "\n");
510
511        // relatedTarget is null when the titletip is first shown: a mouseout event fires
512        // because the mouse is exiting the main window and entering the titletip "window".
513        // relatedTarget is also null when the mouse exits the main window completely,
514        // so count how many times relatedTarget was null after titletip is first shown 
515        // and hide popup the 2nd time
516        if (!rel) {
517          ++this._mouseOutCount;
518          if (this._mouseOutCount > 1)
519            this.hidePopup();
520          return;
521        }
522          
523        // find out if the node we are entering is one of our anonymous children
524        while (rel) {
525          if (rel == this)
526            break;
527          rel = rel.parentNode;
528        }
529        
530        // if the entered node is not a descendant of ours, hide the tooltip
531        if (rel != this && this._isMouseOver) {
532          this.hidePopup();
533        }        
534      ]]></handler>
535
536      <handler event="popuphiding"><![CDATA[
537        this._isMouseOver = false;
538        this._mouseOutCount = 0;
539      ]]></handler>
540    </handlers>
541  </binding>
542
543  <binding id="popup-scrollbars" extends="chrome://global/content/bindings/popup.xml#popup">
544    <content>
545      <xul:hbox class="popup-internal-box" flex="1" orient="vertical" style="overflow: auto;">
546        <children/>
547      </xul:hbox>
548    </content>
549  </binding>
550
551</bindings>
552