1 /* 2 * Copyright (C) 2010 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 */ 34 WebInspector.ShortcutsScreen = function() 35 { 36 this._sections = /** @type {Object.<string, !WebInspector.ShortcutsSection>} */ ({}); 37 } 38 39 WebInspector.ShortcutsScreen.prototype = { 40 /** 41 * @param {string} name 42 * @return {!WebInspector.ShortcutsSection} 43 */ 44 section: function(name) 45 { 46 var section = this._sections[name]; 47 if (!section) 48 this._sections[name] = section = new WebInspector.ShortcutsSection(name); 49 return section; 50 }, 51 52 /** 53 * @return {!WebInspector.View} 54 */ 55 createShortcutsTabView: function() 56 { 57 var orderedSections = []; 58 for (var section in this._sections) 59 orderedSections.push(this._sections[section]); 60 function compareSections(a, b) 61 { 62 return a.order - b.order; 63 } 64 orderedSections.sort(compareSections); 65 66 var view = new WebInspector.View(); 67 68 view.element.className = "settings-tab-container"; 69 view.element.createChild("header").createChild("h3").appendChild(document.createTextNode(WebInspector.UIString("Shortcuts"))); 70 var scrollPane = view.element.createChild("div", "help-container-wrapper"); 71 var container = scrollPane.createChild("div"); 72 container.className = "help-content help-container"; 73 for (var i = 0; i < orderedSections.length; ++i) 74 orderedSections[i].renderSection(container); 75 76 var note = scrollPane.createChild("p", "help-footnote"); 77 var noteLink = note.createChild("a"); 78 noteLink.href = "https://developers.google.com/chrome-developer-tools/docs/shortcuts"; 79 noteLink.target = "_blank"; 80 noteLink.createTextChild(WebInspector.UIString("Full list of keyboard shortcuts and gestures")); 81 82 return view; 83 } 84 } 85 86 /** 87 * We cannot initialize it here as localized strings are not loaded yet. 88 * @type {?WebInspector.ShortcutsScreen} 89 */ 90 WebInspector.shortcutsScreen = null; 91 92 /** 93 * @constructor 94 * @param {string} name 95 */ 96 WebInspector.ShortcutsSection = function(name) 97 { 98 this.name = name; 99 this._lines = /** @type {!Array.<{key: !Node, text: string}>} */ ([]); 100 this.order = ++WebInspector.ShortcutsSection._sequenceNumber; 101 }; 102 103 WebInspector.ShortcutsSection._sequenceNumber = 0; 104 105 WebInspector.ShortcutsSection.prototype = { 106 /** 107 * @param {!WebInspector.KeyboardShortcut.Descriptor} key 108 * @param {string} description 109 */ 110 addKey: function(key, description) 111 { 112 this._addLine(this._renderKey(key), description); 113 }, 114 115 /** 116 * @param {!Array.<!WebInspector.KeyboardShortcut.Descriptor>} keys 117 * @param {string} description 118 */ 119 addRelatedKeys: function(keys, description) 120 { 121 this._addLine(this._renderSequence(keys, "/"), description); 122 }, 123 124 /** 125 * @param {!Array.<!WebInspector.KeyboardShortcut.Descriptor>} keys 126 * @param {string} description 127 */ 128 addAlternateKeys: function(keys, description) 129 { 130 this._addLine(this._renderSequence(keys, WebInspector.UIString("or")), description); 131 }, 132 133 /** 134 * @param {!Node} keyElement 135 * @param {string} description 136 */ 137 _addLine: function(keyElement, description) 138 { 139 this._lines.push({ key: keyElement, text: description }) 140 }, 141 142 /** 143 * @param {!Element} container 144 */ 145 renderSection: function(container) 146 { 147 var parent = container.createChild("div", "help-block"); 148 149 var headLine = parent.createChild("div", "help-line"); 150 headLine.createChild("div", "help-key-cell"); 151 headLine.createChild("div", "help-section-title help-cell").textContent = this.name; 152 153 for (var i = 0; i < this._lines.length; ++i) { 154 var line = parent.createChild("div", "help-line"); 155 var keyCell = line.createChild("div", "help-key-cell"); 156 keyCell.appendChild(this._lines[i].key); 157 keyCell.appendChild(this._createSpan("help-key-delimiter", ":")); 158 line.createChild("div", "help-cell").textContent = this._lines[i].text; 159 } 160 }, 161 162 /** 163 * @param {!Array.<!WebInspector.KeyboardShortcut.Descriptor>} sequence 164 * @param {string} delimiter 165 * @return {!Node} 166 */ 167 _renderSequence: function(sequence, delimiter) 168 { 169 var delimiterSpan = this._createSpan("help-key-delimiter", delimiter); 170 return this._joinNodes(sequence.map(this._renderKey.bind(this)), delimiterSpan); 171 }, 172 173 /** 174 * @param {!WebInspector.KeyboardShortcut.Descriptor} key 175 * @return {!Node} 176 */ 177 _renderKey: function(key) 178 { 179 var keyName = key.name; 180 var plus = this._createSpan("help-combine-keys", "+"); 181 return this._joinNodes(keyName.split(" + ").map(this._createSpan.bind(this, "help-key")), plus); 182 }, 183 184 /** 185 * @param {string} className 186 * @param {string} textContent 187 * @return {!Element} 188 */ 189 _createSpan: function(className, textContent) 190 { 191 var node = document.createElement("span"); 192 node.className = className; 193 node.textContent = textContent; 194 return node; 195 }, 196 197 /** 198 * @param {!Array.<!Element>} nodes 199 * @param {!Element} delimiter 200 * @return {!Node} 201 */ 202 _joinNodes: function(nodes, delimiter) 203 { 204 var result = document.createDocumentFragment(); 205 for (var i = 0; i < nodes.length; ++i) { 206 if (i > 0) 207 result.appendChild(delimiter.cloneNode(true)); 208 result.appendChild(nodes[i]); 209 } 210 return result; 211 } 212 } 213