Home | History | Annotate | Download | only in front_end
      1 /*
      2  * Copyright (C) 2009 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 /**
     32  * @constructor
     33  * @extends {WebInspector.Object}
     34  * @param {!Element} element
     35  */
     36 WebInspector.StatusBarItem = function(element)
     37 {
     38     this.element = element;
     39     this._enabled = true;
     40 }
     41 
     42 WebInspector.StatusBarItem.prototype = {
     43     /**
     44      * @param {boolean} value
     45      */
     46     setEnabled: function(value)
     47     {
     48         if (this._enabled === value)
     49             return;
     50         this._enabled = value;
     51         this._applyEnabledState();
     52     },
     53 
     54     /**
     55      * @protected
     56      */
     57     _applyEnabledState: function()
     58     {
     59         this.element.disabled = !this._enabled;
     60     },
     61 
     62     __proto__: WebInspector.Object.prototype
     63 }
     64 
     65 /**
     66  * @constructor
     67  * @extends {WebInspector.StatusBarItem}
     68  * @param {string} text
     69  * @param {string=} className
     70  */
     71 WebInspector.StatusBarText = function(text, className)
     72 {
     73     WebInspector.StatusBarItem.call(this, document.createElement("span"));
     74     this.element.className = "status-bar-item status-bar-text";
     75     if (className)
     76         this.element.addStyleClass(className);
     77     this.element.textContent = text;
     78 }
     79 
     80 WebInspector.StatusBarText.prototype = {
     81     /**
     82      * @param {string} text
     83      */
     84     setText: function(text)
     85     {
     86         this.element.textContent = text;
     87     },
     88 
     89     __proto__: WebInspector.StatusBarItem.prototype
     90 }
     91 
     92 
     93 /**
     94  * @constructor
     95  * @extends {WebInspector.StatusBarItem}
     96  * @param {string} title
     97  * @param {string} className
     98  * @param {number=} states
     99  */
    100 WebInspector.StatusBarButton = function(title, className, states)
    101 {
    102     WebInspector.StatusBarItem.call(this, document.createElement("button"));
    103     this.element.className = className + " status-bar-item";
    104     this.element.addEventListener("click", this._clicked.bind(this), false);
    105 
    106     this.glyph = document.createElement("div");
    107     this.glyph.className = "glyph";
    108     this.element.appendChild(this.glyph);
    109 
    110     this.glyphShadow = document.createElement("div");
    111     this.glyphShadow.className = "glyph shadow";
    112     this.element.appendChild(this.glyphShadow);
    113 
    114     this.states = states;
    115     if (!states)
    116         this.states = 2;
    117 
    118     if (states == 2)
    119         this._state = false;
    120     else
    121         this._state = 0;
    122 
    123     this.title = title;
    124     this.className = className;
    125     this._visible = true;
    126 }
    127 
    128 WebInspector.StatusBarButton.prototype = {
    129     _clicked: function()
    130     {
    131         this.dispatchEventToListeners("click");
    132         if (this._longClickInterval)
    133             clearInterval(this._longClickInterval);
    134     },
    135 
    136     /**
    137      * @return {boolean}
    138      */
    139     enabled: function()
    140     {
    141         return this._enabled;
    142     },
    143 
    144     get title()
    145     {
    146         return this._title;
    147     },
    148 
    149     set title(x)
    150     {
    151         if (this._title === x)
    152             return;
    153         this._title = x;
    154         this.element.title = x;
    155     },
    156 
    157     get state()
    158     {
    159         return this._state;
    160     },
    161 
    162     set state(x)
    163     {
    164         if (this._state === x)
    165             return;
    166 
    167         if (this.states === 2)
    168             this.element.enableStyleClass("toggled-on", x);
    169         else {
    170             this.element.removeStyleClass("toggled-" + this._state);
    171             if (x !== 0)
    172                 this.element.addStyleClass("toggled-" + x);
    173         }
    174         this._state = x;
    175     },
    176 
    177     get toggled()
    178     {
    179         if (this.states !== 2)
    180             throw("Only used toggled when there are 2 states, otherwise, use state");
    181         return this.state;
    182     },
    183 
    184     set toggled(x)
    185     {
    186         if (this.states !== 2)
    187             throw("Only used toggled when there are 2 states, otherwise, use state");
    188         this.state = x;
    189     },
    190 
    191     get visible()
    192     {
    193         return this._visible;
    194     },
    195 
    196     set visible(x)
    197     {
    198         if (this._visible === x)
    199             return;
    200 
    201         this.element.enableStyleClass("hidden", !x);
    202         this._visible = x;
    203     },
    204 
    205     makeLongClickEnabled: function()
    206     {
    207         this.element.addEventListener("mousedown", mouseDown.bind(this), false);
    208         this.element.addEventListener("mouseout", mouseUp.bind(this), false);
    209         this.element.addEventListener("mouseup", mouseUp.bind(this), false);
    210 
    211         var longClicks = 0;
    212 
    213         function mouseDown(e)
    214         {
    215             if (e.which !== 1)
    216                 return;
    217             longClicks = 0;
    218             this._longClickInterval = setInterval(longClicked.bind(this), 200);
    219         }
    220 
    221         function mouseUp(e)
    222         {
    223             if (e.which !== 1)
    224                 return;
    225             if (this._longClickInterval)
    226                 clearInterval(this._longClickInterval);
    227         }
    228 
    229         function longClicked()
    230         {
    231             ++longClicks;
    232             this.dispatchEventToListeners(longClicks === 1 ? "longClickDown" : "longClickPress");
    233         }
    234     },
    235 
    236     /**
    237      * @param {function():Array.<WebInspector.StatusBarButton>} buttonsProvider
    238      */
    239     makeLongClickOptionsEnabled: function(buttonsProvider)
    240     {
    241         this.makeLongClickEnabled();
    242 
    243         this.longClickGlyph = document.createElement("div");
    244         this.longClickGlyph.className = "fill long-click-glyph";
    245         this.element.appendChild(this.longClickGlyph);
    246 
    247         this.longClickGlyphShadow = document.createElement("div");
    248         this.longClickGlyphShadow.className = "fill long-click-glyph shadow";
    249         this.element.appendChild(this.longClickGlyphShadow);
    250 
    251         this.addEventListener("longClickDown", this._showOptions.bind(this, buttonsProvider), this);
    252     },
    253 
    254     /**
    255      * @param {function():Array.<WebInspector.StatusBarButton>} buttonsProvider
    256      */
    257     _showOptions: function(buttonsProvider)
    258     {
    259         var buttons = buttonsProvider();
    260         var mainButtonClone = new WebInspector.StatusBarButton(this.title, this.className, this.states);
    261         mainButtonClone.addEventListener("click", this._clicked, this);
    262         mainButtonClone.state = this.state;
    263         buttons.push(mainButtonClone);
    264 
    265         var mouseUpListener = mouseUp.bind(this);
    266         document.documentElement.addEventListener("mouseup", mouseUpListener, false);
    267 
    268         var optionsGlassPane = new WebInspector.GlassPane();
    269         var optionsBarElement = optionsGlassPane.element.createChild("div", "alternate-status-bar-buttons-bar");
    270         const buttonHeight = 24;
    271         optionsBarElement.style.height = (buttonHeight * buttons.length) + "px";
    272         optionsBarElement.style.left = (this.element.offsetLeft + 1) + "px";
    273 
    274         var boundMouseOver = mouseOver.bind(this);
    275         var boundMouseOut = mouseOut.bind(this);
    276         for (var i = 0; i < buttons.length; ++i) {
    277             buttons[i].element.addEventListener("mousemove", boundMouseOver, false);
    278             buttons[i].element.addEventListener("mouseout", boundMouseOut, false);
    279             optionsBarElement.appendChild(buttons[i].element);
    280         }
    281         buttons[buttons.length - 1].element.addStyleClass("emulate-active");
    282 
    283         function mouseOver(e)
    284         {
    285             if (e.which !== 1)
    286                 return;
    287             var buttonElement = e.target.enclosingNodeOrSelfWithClass("status-bar-item");
    288             buttonElement.addStyleClass("emulate-active");
    289         }
    290 
    291         function mouseOut(e)
    292         {
    293             if (e.which !== 1)
    294                 return;
    295             var buttonElement = e.target.enclosingNodeOrSelfWithClass("status-bar-item");
    296             buttonElement.removeStyleClass("emulate-active");
    297         }
    298 
    299         function mouseUp(e)
    300         {
    301             if (e.which !== 1)
    302                 return;
    303             optionsGlassPane.dispose();
    304             document.documentElement.removeEventListener("mouseup", mouseUpListener, false);
    305 
    306             for (var i = 0; i < buttons.length; ++i) {
    307                 if (buttons[i].element.hasStyleClass("emulate-active")) {
    308                     buttons[i].element.removeStyleClass("emulate-active");
    309                     buttons[i]._clicked();
    310                     break;
    311                 }
    312             }
    313         }
    314     },
    315 
    316     __proto__: WebInspector.StatusBarItem.prototype
    317 }
    318 
    319 /**
    320  * @constructor
    321  * @extends {WebInspector.StatusBarItem}
    322  * @param {?function(Event)} changeHandler
    323  * @param {string=} className
    324  */
    325 WebInspector.StatusBarComboBox = function(changeHandler, className)
    326 {
    327     WebInspector.StatusBarItem.call(this, document.createElement("span"));
    328     this.element.className = "status-bar-select-container";
    329 
    330     this._selectElement = this.element.createChild("select", "status-bar-item");
    331     this.element.createChild("div", "status-bar-select-arrow");
    332     if (changeHandler)
    333         this._selectElement.addEventListener("change", changeHandler, false);
    334     if (className)
    335         this._selectElement.addStyleClass(className);
    336 }
    337 
    338 WebInspector.StatusBarComboBox.prototype = {
    339     /**
    340      * @return {number}
    341      */
    342     size: function()
    343     {
    344         return this._selectElement.childElementCount;
    345     },
    346 
    347     /**
    348      * @param {!Element} option
    349      */
    350     addOption: function(option)
    351     {
    352         this._selectElement.appendChild(option);
    353     },
    354 
    355     /**
    356      * @param {string} label
    357      * @param {string=} title
    358      * @param {string=} value
    359      * @return {!Element}
    360      */
    361     createOption: function(label, title, value)
    362     {
    363         var option = this._selectElement.createChild("option");
    364         option.text = label;
    365         if (title)
    366             option.title = title;
    367         if (typeof value !== "undefined")
    368             option.value = value;
    369         return option;
    370     },
    371 
    372     /**
    373      * @override
    374      */
    375     _applyEnabledState: function()
    376     {
    377         this._selectElement.disabled = !this._enabled;
    378     },
    379 
    380     /**
    381      * @param {!Element} option
    382      */
    383     removeOption: function(option)
    384     {
    385         this._selectElement.removeChild(option);
    386     },
    387 
    388     removeOptions: function()
    389     {
    390         this._selectElement.removeChildren();
    391     },
    392 
    393     /**
    394      * @return {?Element}
    395      */
    396     selectedOption: function()
    397     {
    398         if (this._selectElement.selectedIndex >= 0)
    399             return this._selectElement[this._selectElement.selectedIndex];
    400         return null;
    401     },
    402 
    403     /**
    404      * @param {Element} option
    405      */
    406     select: function(option)
    407     {
    408         this._selectElement.selectedIndex = Array.prototype.indexOf.call(this._selectElement, option);
    409     },
    410 
    411     /**
    412      * @param {number} index
    413      */
    414     setSelectedIndex: function(index)
    415     {
    416         this._selectElement.selectedIndex = index;
    417     },
    418 
    419     /**
    420      * @return {number}
    421      */
    422     selectedIndex: function()
    423     {
    424         return this._selectElement.selectedIndex;
    425     },
    426 
    427     __proto__: WebInspector.StatusBarItem.prototype
    428 }
    429