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 |