| OLD | NEW |
| 1 // Copyright 2014 The ChromeOS IME Authors. All Rights Reserved. | 1 // Copyright 2014 The ChromeOS IME Authors. All Rights Reserved. |
| 2 // limitations under the License. | 2 // limitations under the License. |
| 3 // See the License for the specific language governing permissions and | 3 // See the License for the specific language governing permissions and |
| 4 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 4 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 5 // distributed under the License is distributed on an "AS-IS" BASIS, | 5 // distributed under the License is distributed on an "AS-IS" BASIS, |
| 6 // Unless required by applicable law or agreed to in writing, software | 6 // Unless required by applicable law or agreed to in writing, software |
| 7 // | 7 // |
| 8 // http://www.apache.org/licenses/LICENSE-2.0 | 8 // http://www.apache.org/licenses/LICENSE-2.0 |
| 9 // | 9 // |
| 10 // You may obtain a copy of the License at | 10 // You may obtain a copy of the License at |
| 11 // you may not use this file except in compliance with the License. | 11 // you may not use this file except in compliance with the License. |
| 12 // Licensed under the Apache License, Version 2.0 (the "License"); | 12 // Licensed under the Apache License, Version 2.0 (the "License"); |
| 13 // | 13 // |
| 14 goog.provide('i18n.input.chrome.inputview.Accents'); | 14 goog.provide('i18n.input.chrome.inputview.Accents'); |
| 15 | 15 |
| 16 goog.require('goog.dom'); | |
| 17 goog.require('goog.dom.TagName'); | 16 goog.require('goog.dom.TagName'); |
| 18 goog.require('goog.dom.classlist'); | 17 goog.require('goog.dom.classlist'); |
| 19 goog.require('goog.style'); | 18 goog.require('goog.style'); |
| 19 goog.require('i18n.input.chrome.FloatingWindow'); |
| 20 goog.require('i18n.input.chrome.inputview.Css'); | 20 goog.require('i18n.input.chrome.inputview.Css'); |
| 21 goog.require('i18n.input.chrome.inputview.util'); | 21 goog.require('i18n.input.chrome.inputview.util'); |
| 22 | 22 |
| 23 | 23 |
| 24 goog.scope(function() { | 24 goog.scope(function() { |
| 25 var Accents = i18n.input.chrome.inputview.Accents; | |
| 26 var Css = i18n.input.chrome.inputview.Css; | 25 var Css = i18n.input.chrome.inputview.Css; |
| 26 var FloatingWindow = i18n.input.chrome.FloatingWindow; |
| 27 var TagName = goog.dom.TagName; |
| 28 |
| 27 | 29 |
| 28 | 30 |
| 29 /** | 31 /** |
| 32 * The accents floating windows. |
| 33 * |
| 34 * @param {!chrome.app.window.AppWindow} parentWindow The parent app window. |
| 35 * @constructor |
| 36 * @extends {i18n.input.chrome.FloatingWindow} |
| 37 */ |
| 38 i18n.input.chrome.inputview.Accents = function(parentWindow) { |
| 39 i18n.input.chrome.inputview.Accents.base(this, 'constructor', |
| 40 parentWindow, undefined, Accents.CSS_FILE); |
| 41 }; |
| 42 var Accents = i18n.input.chrome.inputview.Accents; |
| 43 goog.inherits(Accents, FloatingWindow); |
| 44 |
| 45 |
| 46 |
| 47 /** |
| 48 * @const {string} The css file name for accents component. |
| 49 */ |
| 50 Accents.CSS_FILE = 'accents_css.css' |
| 51 |
| 52 |
| 53 /** |
| 30 * The highlighted element. | 54 * The highlighted element. |
| 31 * | 55 * |
| 32 * @type {Element} | 56 * @type {Element} |
| 33 * @private | 57 * @private |
| 34 */ | 58 */ |
| 35 Accents.highlightedItem_ = null; | 59 Accents.prototype.highlightedItem_ = null; |
| 60 |
| 61 |
| 62 /** @override */ |
| 63 Accents.prototype.createDom = function() { |
| 64 Accents.base(this, 'createDom'); |
| 65 var container = this.getElement(); |
| 66 goog.dom.classlist.add(container, Css.ACCENT_CONTAINER); |
| 67 container.id = 'container'; |
| 68 }; |
| 36 | 69 |
| 37 | 70 |
| 38 /** | 71 /** |
| 39 * Gets the highlighted character. | 72 * Gets the highlighted character. |
| 40 * | 73 * |
| 41 * @return {string} The character. | 74 * @return {string} The character. |
| 42 * @private | |
| 43 */ | 75 */ |
| 44 Accents.getHighlightedAccent_ = function() { | 76 Accents.prototype.getHighlightedAccent = function() { |
| 45 return Accents.highlightedItem_ ? | 77 return this.highlightedItem_ ? |
| 46 Accents.highlightedItem_.textContent.trim() : ''; | 78 this.highlightedItem_.textContent.trim() : ''; |
| 47 }; | 79 }; |
| 48 | 80 |
| 49 | 81 |
| 50 /** | 82 /** |
| 51 * Highlights the item according to the current coordinate of the finger. | 83 * Highlights the item according to the current coordinate of the finger. |
| 52 * | 84 * |
| 53 * @param {number} x The x position of finger in screen coordinate system. | 85 * @param {number} x The x position of finger in client view. |
| 54 * @param {number} y The y position of finger in screen coordinate system. | 86 * @param {number} y The y position of finger in client view. |
| 55 * @param {number} offset The offset to cancel highlight. | 87 * @param {number} offset The offset to cancel highlight. |
| 56 * @private | |
| 57 */ | 88 */ |
| 58 Accents.highlightItem_ = function(x, y, offset) { | 89 Accents.prototype.highlightItem = function(x, y, offset) { |
| 59 var highlightedItem = Accents.getHighlightedItem_(x, y, offset); | 90 var highlightedItem = this.getHighlightedItem_(x, y, offset); |
| 60 if (Accents.highlightedItem_ != highlightedItem) { | 91 if (this.highlightedItem_ != highlightedItem) { |
| 61 if (Accents.highlightedItem_) { | 92 if (this.highlightedItem_) { |
| 62 goog.dom.classlist.remove(Accents.highlightedItem_, | 93 goog.dom.classlist.remove(this.highlightedItem_, Css.ELEMENT_HIGHLIGHT); |
| 63 i18n.input.chrome.inputview.Css.ELEMENT_HIGHLIGHT); | |
| 64 } | 94 } |
| 65 Accents.highlightedItem_ = highlightedItem; | 95 this.highlightedItem_ = highlightedItem; |
| 66 if (Accents.highlightedItem_ && | 96 if (this.highlightedItem_ && |
| 67 Accents.highlightedItem_.textContent.trim()) { | 97 this.highlightedItem_.textContent.trim()) { |
| 68 goog.dom.classlist.add(Accents.highlightedItem_, | 98 goog.dom.classlist.add(this.highlightedItem_, Css.ELEMENT_HIGHLIGHT); |
| 69 i18n.input.chrome.inputview.Css.ELEMENT_HIGHLIGHT); | |
| 70 } | 99 } |
| 71 } | 100 } |
| 72 }; | 101 }; |
| 73 | 102 |
| 74 | 103 |
| 75 /** | 104 /** |
| 76 * Gets the higlighted item from |x| and |y| position. | 105 * Gets the highlighted item from |x| and |y| position. |
| 77 * @param {number} x The x position of finger in screen coordinate system. | 106 * @param {number} x The x position of client View. |
| 78 * @param {number} y The y position of finger in screen coordinate system. | 107 * @param {number} y The y position of client View. |
| 79 * @param {number} offset The offset to cancel highlight. | 108 * @param {number} offset The offset to cancel highlight. |
| 80 * @return {Element} . | 109 * @return {Element} . |
| 81 * @private | 110 * @private |
| 82 */ | 111 */ |
| 83 Accents.getHighlightedItem_ = function(x, y, offset) { | 112 Accents.prototype.getHighlightedItem_ = function(x, y, offset) { |
| 84 var dom = goog.dom.getDomHelper(); | 113 var dom = this.getDomHelper(); |
| 85 var row = null; | 114 var row = null; |
| 86 var rows = dom.getElementsByClass(i18n.input.chrome.inputview.Css.ACCENT_ROW); | 115 var rows = dom.getElementsByClass(Css.ACCENT_ROW); |
| 87 for (var i = 0; i < rows.length; i++) { | 116 for (var i = 0; i < rows.length; i++) { |
| 88 var coordinate = goog.style.getClientPosition(rows[i]); | 117 var coordinate = goog.style.getClientPosition(rows[i]); |
| 89 var size = goog.style.getSize(rows[i]); | 118 var size = goog.style.getSize(rows[i]); |
| 90 var screenYStart = coordinate.y + window.screenY; | 119 var screenYStart = (i == 0 ? coordinate.y - offset : coordinate.y); |
| 91 screenYStart = i == 0 ? screenYStart - offset : screenYStart; | 120 var screenYEnd = coordinate.y + size.height; |
| 92 var screenYEnd = coordinate.y + window.screenY + size.height; | |
| 93 screenYEnd = i == rows.length - 1 ? screenYEnd + offset : screenYEnd; | 121 screenYEnd = i == rows.length - 1 ? screenYEnd + offset : screenYEnd; |
| 94 if (screenYStart < y && screenYEnd > y) { | 122 if (screenYStart < y && screenYEnd > y) { |
| 95 row = rows[i]; | 123 row = rows[i]; |
| 96 break; | 124 break; |
| 97 } | 125 } |
| 98 } | 126 } |
| 99 if (row) { | 127 if (row) { |
| 100 var children = dom.getChildren(row); | 128 var children = dom.getChildren(row); |
| 101 for (var i = 0; i < children.length; i++) { | 129 for (var i = 0; i < children.length; i++) { |
| 102 var coordinate = goog.style.getClientPosition(children[i]); | 130 var coordinate = goog.style.getClientPosition(children[i]); |
| 103 var size = goog.style.getSize(children[i]); | 131 var size = goog.style.getSize(children[i]); |
| 104 var screenXStart = coordinate.x + window.screenX; | 132 var screenXStart = (i == 0 ? coordinate.x - offset : coordinate.x); |
| 105 screenXStart = i == 0 ? screenXStart - offset : screenXStart; | 133 var screenXEnd = coordinate.x + size.width; |
| 106 var screenXEnd = coordinate.x + window.screenX + size.width; | |
| 107 screenXEnd = i == children.length - 1 ? screenXEnd + offset : screenXEnd; | 134 screenXEnd = i == children.length - 1 ? screenXEnd + offset : screenXEnd; |
| 108 if (screenXStart < x && screenXEnd > x) { | 135 if (screenXStart < x && screenXEnd > x) { |
| 109 return children[i]; | 136 return children[i]; |
| 110 } | 137 } |
| 111 } | 138 } |
| 112 } | 139 } |
| 113 return null; | 140 return null; |
| 114 }; | 141 }; |
| 115 | 142 |
| 116 | 143 |
| 117 /** | 144 /** |
| 118 * Sets the accents which this window should display. | 145 * Sets the accents which this window should display. |
| 119 * | 146 * |
| 120 * @param {!Array.<string>} accents The accents to display. | 147 * @param {!Array.<string>} accents The accents to display. |
| 121 * @param {!number} numOfColumns The number of colums of this accents window. | 148 * @param {!number} numOfColumns The number of colums of this accents window. |
| 122 * @param {!number} numOfRows The number of rows of this accents window. | 149 * @param {!number} numOfRows The number of rows of this accents window. |
| 123 * @param {number} width The width of accent key. | 150 * @param {number} width The width of accent key. |
| 124 * @param {number} height The height of accent key. | 151 * @param {number} height The height of accent key. |
| 125 * @param {number} startKeyIndex The index of the start key in bottom row. | 152 * @param {number} startKeyIndex The index of the start key in bottom row. |
| 126 * @param {boolean} isCompact True if this accents window is for compact | 153 * @param {boolean} isCompact True if this accents window is for compact |
| 127 * keyboard. | 154 * keyboard. |
| 128 * @private | |
| 129 */ | 155 */ |
| 130 Accents.setAccents_ = function(accents, numOfColumns, numOfRows, width, | 156 Accents.prototype.setAccents = function(accents, numOfColumns, numOfRows, width, |
| 131 height, startKeyIndex, isCompact) { | 157 height, startKeyIndex, isCompact) { |
| 132 var TagName = goog.dom.TagName; | 158 var dom = this.getDomHelper(); |
| 133 var dom = goog.dom.getDomHelper(); | 159 var container = this.getElement(); |
| 134 var container = dom.createDom(TagName.DIV, Css.ACCENT_CONTAINER); | 160 dom.removeChildren(container); |
| 135 container.id = 'container'; | 161 var orderedAccents = this.reorderAccents_(accents, numOfColumns, numOfRows, |
| 136 | |
| 137 var orderedAccents = Accents.reorderAccents_(accents, numOfColumns, numOfRows, | |
| 138 startKeyIndex); | 162 startKeyIndex); |
| 139 var row = null; | 163 var row = null; |
| 140 for (var i = 0; i < orderedAccents.length; i++) { | 164 for (var i = 0; i < orderedAccents.length; i++) { |
| 141 var keyElem = dom.createDom(TagName.DIV, Css.ACCENT_KEY); | 165 var keyElem = dom.createDom(TagName.DIV, Css.ACCENT_KEY); |
| 142 // Even if this is an empty key, we still need to add textDiv. Otherwise, | 166 // Even if this is an empty key, we still need to add textDiv. Otherwise, |
| 143 // the keys have layout issues. | 167 // the keys have layout issues. |
| 144 var textDiv = dom.createElement(TagName.DIV); | 168 var textDiv = dom.createElement(TagName.DIV); |
| 145 var text = i18n.input.chrome.inputview.util.getVisibleCharacter( | 169 var text = i18n.input.chrome.inputview.util.getVisibleCharacter( |
| 146 orderedAccents[i]); | 170 orderedAccents[i]); |
| 147 textDiv.textContent = text; | 171 textDiv.textContent = text; |
| 148 // If accent is a word use a smaller font size. | 172 // If accent is a word use a smaller font size. |
| 149 goog.dom.classlist.add(textDiv, text.length > 1 ? Css.FONT_SMALL : | 173 goog.dom.classlist.add(textDiv, text.length > 1 ? Css.FONT_SMALL : |
| 150 (isCompact ? Css.ACCENT_COMPACT_FONT : Css.ACCENT_FULL_FONT)); | 174 (isCompact ? Css.ACCENT_COMPACT_FONT : Css.ACCENT_FULL_FONT)); |
| 151 | 175 |
| 152 goog.style.setStyle(textDiv, 'lineHeight', height + 'px'); | 176 goog.style.setStyle(textDiv, 'lineHeight', height + 'px'); |
| 153 dom.appendChild(keyElem, textDiv); | 177 dom.appendChild(keyElem, textDiv); |
| 154 if (!orderedAccents[i]) { | 178 if (!orderedAccents[i]) { |
| 155 goog.dom.classlist.add(keyElem, Css.ACCENT_EMPTY_KEY); | 179 goog.dom.classlist.add(keyElem, Css.ACCENT_EMPTY_KEY); |
| 156 } | 180 } |
| 157 goog.style.setSize(keyElem, width, height); | 181 goog.style.setSize(keyElem, width, height); |
| 158 if (i % numOfColumns == 0) { | 182 if (i % numOfColumns == 0) { |
| 159 if (row) { | 183 if (row) { |
| 160 container.appendChild(row); | 184 container.appendChild(row); |
| 161 } | 185 } |
| 162 row = dom.createDom(TagName.DIV, Css.ACCENT_ROW); | 186 row = dom.createDom(TagName.DIV, Css.ACCENT_ROW); |
| 163 } | 187 } |
| 164 dom.appendChild(row, keyElem); | 188 dom.appendChild(row, keyElem); |
| 165 } | 189 } |
| 166 dom.appendChild(container, row); | 190 dom.appendChild(container, row); |
| 167 dom.appendChild(document.body, container); | |
| 168 }; | 191 }; |
| 169 | 192 |
| 170 | 193 |
| 171 /** | 194 /** |
| 172 * Generates the reordered accents which is optimized for creating accent key | 195 * Generates the reordered accents which is optimized for creating accent key |
| 173 * elements sequentially(from top to bottom, left to right). | 196 * elements sequentially(from top to bottom, left to right). |
| 174 * Accent in |accents| is ordered according to its frequency(more frequently | 197 * Accent in |accents| is ordered according to its frequency(more frequently |
| 175 * used appears first). Once reordered, the more frequently used accents will be | 198 * used appears first). Once reordered, the more frequently used accents will be |
| 176 * positioned closer to the parent key. See tests for example. | 199 * positioned closer to the parent key. See tests for example. |
| 177 * @param {!Array.<string>} accents The accents to display. | 200 * @param {!Array.<string>} accents The accents to display. |
| 178 * @param {!number} numOfColumns The number of colums of this accents window. | 201 * @param {!number} numOfColumns The number of colums of this accents window. |
| 179 * @param {!number} numOfRows The number of rows of this accents window. | 202 * @param {!number} numOfRows The number of rows of this accents window. |
| 180 * @param {number} startKeyIndex The index of the start key in bottom row. | 203 * @param {number} startKeyIndex The index of the start key in bottom row. |
| 181 * @return {!Array.<string>} . | 204 * @return {!Array.<string>} . |
| 182 * @private | 205 * @private |
| 183 */ | 206 */ |
| 184 Accents.reorderAccents_ = function(accents, numOfColumns, numOfRows, | 207 Accents.prototype.reorderAccents_ = function(accents, numOfColumns, numOfRows, |
| 185 startKeyIndex) { | 208 startKeyIndex) { |
| 186 var orderedAccents = new Array(numOfColumns * numOfRows); | 209 var orderedAccents = new Array(numOfColumns * numOfRows); |
| 187 | 210 |
| 188 var index = 0; | 211 var index = 0; |
| 189 // Generates the order to fill keys in a row. Start with startKeyIndex, we try | 212 // Generates the order to fill keys in a row. Start with startKeyIndex, we try |
| 190 // to fill keys on both side(right side first) of the start key. | 213 // to fill keys on both side(right side first) of the start key. |
| 191 var rowOrder = new Array(numOfColumns); | 214 var rowOrder = new Array(numOfColumns); |
| 192 rowOrder[startKeyIndex] = index; | 215 rowOrder[startKeyIndex] = index; |
| 193 for (var i = 1; | 216 for (var i = 1; |
| 194 startKeyIndex + i < numOfColumns || startKeyIndex - i >= 0; | 217 startKeyIndex + i < numOfColumns || startKeyIndex - i >= 0; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 207 if (index >= accents.length) { | 230 if (index >= accents.length) { |
| 208 orderedAccents[i * numOfColumns + j] = ''; | 231 orderedAccents[i * numOfColumns + j] = ''; |
| 209 } else { | 232 } else { |
| 210 orderedAccents[i * numOfColumns + j] = accents[index]; | 233 orderedAccents[i * numOfColumns + j] = accents[index]; |
| 211 } | 234 } |
| 212 } | 235 } |
| 213 } | 236 } |
| 214 | 237 |
| 215 return orderedAccents; | 238 return orderedAccents; |
| 216 }; | 239 }; |
| 217 | |
| 218 goog.exportSymbol('accents.highlightedAccent', Accents.getHighlightedAccent_); | |
| 219 goog.exportSymbol('accents.highlightItem', Accents.highlightItem_); | |
| 220 goog.exportSymbol('accents.setAccents', Accents.setAccents_); | |
| 221 | |
| 222 }); // goog.scope | 240 }); // goog.scope |
| OLD | NEW |