1 // Copyright 2014 The ChromeOS IME Authors. All Rights Reserved.
2 // limitations under the License.
3 // See the License for the specific language governing permissions and
4 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
5 // distributed under the License is distributed on an "AS-IS" BASIS,
6 // Unless required by applicable law or agreed to in writing, software
8 // http://www.apache.org/licenses/LICENSE-2.0
10 // You may obtain a copy of the License at
11 // you may not use this file except in compliance with the License.
12 // Licensed under the Apache License, Version 2.0 (the "License");
14 goog.provide('i18n.input.chrome.inputview.KeyboardContainer');
16 goog.require('goog.dom.TagName');
17 goog.require('goog.dom.classlist');
18 goog.require('goog.i18n.bidi');
19 goog.require('i18n.input.chrome.inputview.Css');
20 goog.require('i18n.input.chrome.inputview.GlobalFlags');
21 goog.require('i18n.input.chrome.inputview.elements.Element');
22 goog.require('i18n.input.chrome.inputview.elements.ElementType');
23 goog.require('i18n.input.chrome.inputview.elements.content.AltDataView');
24 goog.require('i18n.input.chrome.inputview.elements.content.CandidateView');
25 goog.require('i18n.input.chrome.inputview.elements.content.EmojiView');
26 goog.require('i18n.input.chrome.inputview.elements.content.ExpandedCandidateView');
27 goog.require('i18n.input.chrome.inputview.elements.content.GestureCanvasView');
28 goog.require('i18n.input.chrome.inputview.elements.content.HandwritingView');
29 goog.require('i18n.input.chrome.inputview.elements.content.KeysetView');
30 goog.require('i18n.input.chrome.inputview.elements.content.MenuView');
31 goog.require('i18n.input.chrome.inputview.elements.content.SelectView');
32 goog.require('i18n.input.chrome.inputview.elements.content.SwipeView');
33 goog.require('i18n.input.chrome.inputview.elements.content.VoiceView');
37 goog.scope(function() {
38 var Css = i18n.input.chrome.inputview.Css;
39 var EmojiView = i18n.input.chrome.inputview.elements.content.EmojiView;
40 var HandwritingView = i18n.input.chrome.inputview.elements.content.
42 var KeysetView = i18n.input.chrome.inputview.elements.content.KeysetView;
43 var content = i18n.input.chrome.inputview.elements.content;
44 var ElementType = i18n.input.chrome.inputview.elements.ElementType;
49 * The keyboard container.
51 * @param {!i18n.input.chrome.inputview.Adapter} adapter .
52 * @param {!i18n.input.chrome.sounds.SoundController} soundController .
53 * @param {goog.events.EventTarget=} opt_eventTarget The parent event target.
55 * @extends {i18n.input.chrome.inputview.elements.Element}
57 // TODO(bshe): Move this file to elements/content
58 i18n.input.chrome.inputview.KeyboardContainer =
59 function(adapter, soundController, opt_eventTarget) {
60 goog.base(this, '', ElementType.KEYBOARD_CONTAINER_VIEW, opt_eventTarget);
62 /** @type {!content.CandidateView} */
63 this.candidateView = new content.CandidateView(
64 'candidateView', adapter, this);
66 /** @type {!content.AltDataView} */
67 this.altDataView = new content.AltDataView(this);
69 /** @type {!content.SwipeView} */
70 this.swipeView = new content.SwipeView(adapter, this);
72 /** @type {!content.SelectView} */
73 this.selectView = new content.SelectView(this);
75 if (adapter.isGestureTypingEnabled()) {
76 /** @type {!content.GestureCanvasView} */
77 this.gestureCanvasView = new content.GestureCanvasView(this);
80 /** @type {!content.MenuView} */
81 this.menuView = new content.MenuView(this);
83 /** @type {!content.VoiceView} */
84 this.voiceView = new content.VoiceView(this, adapter, soundController);
86 /** @type {!content.ExpandedCandidateView} */
87 this.expandedCandidateView = new content.ExpandedCandidateView(this);
90 * The map of the KeysetViews.
92 * Value: The view object.
94 * @type {!Object.<string, !KeysetView>}
96 this.keysetViewMap = {};
99 * The bus channel to communicate with background.
101 * @private {!i18n.input.chrome.inputview.Adapter}
103 this.adapter_ = adapter;
105 goog.inherits(i18n.input.chrome.inputview.KeyboardContainer,
106 i18n.input.chrome.inputview.elements.Element);
107 var KeyboardContainer = i18n.input.chrome.inputview.KeyboardContainer;
110 /** @type {!KeysetView} */
111 KeyboardContainer.prototype.currentKeysetView;
115 * The padding bottom of the whole keyboard.
119 KeyboardContainer.PADDING_BOTTOM_ = 7;
123 * The margin of the tab style keyset.
128 KeyboardContainer.TAB_MARGIN_ = 11;
132 * An div to wrapper candidate view and keyboard set view.
136 KeyboardContainer.prototype.wrapperDiv_ = null;
140 KeyboardContainer.prototype.createDom = function() {
141 goog.base(this, 'createDom');
143 var elem = this.getElement();
144 var dom = this.getDomHelper();
145 this.wrapperDiv_ = dom.createDom(goog.dom.TagName.DIV, Css.WRAPPER);
146 this.candidateView.render(this.wrapperDiv_);
147 dom.appendChild(elem, this.wrapperDiv_);
148 this.altDataView.render();
149 this.swipeView.render();
150 this.selectView.render();
151 this.menuView.render();
152 this.voiceView.render();
153 this.voiceView.setVisible(false);
154 this.expandedCandidateView.render(this.wrapperDiv_);
155 this.expandedCandidateView.setVisible(false);
156 if (this.adapter_.isGestureTypingEnabled()) {
157 this.gestureCanvasView.render(this.wrapperDiv_);
159 goog.dom.classlist.add(elem, Css.CONTAINER);
164 KeyboardContainer.prototype.update = function() {
165 this.currentKeysetView && this.currentKeysetView.update();
170 * Adds a keyset view.
172 * @param {!Object} keysetData .
173 * @param {!Object} layoutData .
174 * @param {string} keyset .
175 * @param {string} languageCode .
176 * @param {!i18n.input.chrome.inputview.Model} model .
177 * @param {string} inputToolName .
178 * @param {!Object.<string, boolean>} conditions .
180 KeyboardContainer.prototype.addKeysetView = function(keysetData, layoutData,
181 keyset, languageCode, model, inputToolName, conditions) {
183 if (keyset == 'emoji') {
184 view = new EmojiView(keysetData, layoutData, keyset, languageCode, model,
185 inputToolName, this, this.adapter_);
186 } else if (keyset == 'hwt') {
187 view = new HandwritingView(keysetData, layoutData, keyset, languageCode,
188 model, inputToolName, this, this.adapter_);
190 view = new KeysetView(keysetData, layoutData, keyset, languageCode, model,
191 inputToolName, this, this.adapter_);
193 view.render(this.wrapperDiv_);
194 view.applyConditions(conditions);
195 view.setVisible(false);
196 this.keysetViewMap[keyset] = view;
201 * Switches to a keyset.
203 * @param {string} keyset .
204 * @param {string} title .
205 * @param {boolean} isPasswordBox .
206 * @param {boolean} isA11yMode .
207 * @param {string} rawKeyset The raw keyset id will switch to.
208 * @param {string} lastRawkeyset .
209 * @param {string} languageCode .
210 * @return {boolean} True if switched successfully.
212 KeyboardContainer.prototype.switchToKeyset = function(keyset, title,
213 isPasswordBox, isA11yMode, rawKeyset, lastRawkeyset, languageCode) {
214 if (!this.keysetViewMap[keyset]) {
218 for (var name in this.keysetViewMap) {
219 var view = this.keysetViewMap[name];
220 if (name == keyset) {
221 this.candidateView.setVisible(!view.disableCandidateView);
222 // Before setting view visible, activate it first, since activation may
224 view.activate(rawKeyset);
225 view.setVisible(true);
228 view.spaceKey.updateTitle(title, !isPasswordBox &&
229 keyset != 'hwt' && keyset != 'emoji');
232 goog.dom.classlist.add(this.getElement(), Css.A11Y);
234 // If current raw keyset is changed, record it.
235 if (lastRawkeyset != rawKeyset) {
236 view.fromKeyset = lastRawkeyset;
238 if (view instanceof HandwritingView) {
239 view.setLanguagecode(languageCode);
241 // Deactivate the last keyset view instance.
242 if (this.currentKeysetView != view) {
243 if (this.currentKeysetView) {
244 this.currentKeysetView.deactivate(lastRawkeyset);
246 this.currentKeysetView = view;
248 this.candidateView.updateByKeyset(rawKeyset, isPasswordBox,
249 goog.i18n.bidi.isRtlLanguage(languageCode));
251 view.setVisible(false);
260 * Resizes the whole keyboard.
262 * @param {number} width .
263 * @param {number} height .
264 * @param {number} widthPercent .
265 * @param {number} candidateViewHeight .
267 KeyboardContainer.prototype.setContainerSize = function(width, height,
268 widthPercent, candidateViewHeight) {
269 if (!this.currentKeysetView) {
272 var elem = this.getElement();
275 var wrapperMargin = 0;
276 if (this.currentKeysetView.isTabStyle()) {
277 h = height - 2 * KeyboardContainer.TAB_MARGIN_;
278 wrapperMargin = KeyboardContainer.TAB_MARGIN_;
280 this.wrapperDiv_.style.marginTop = this.wrapperDiv_.style.marginBottom =
281 wrapperMargin + 'px';
282 h -= KeyboardContainer.PADDING_BOTTOM_;
283 elem.style.paddingBottom = KeyboardContainer.PADDING_BOTTOM_ + 'px';
285 var padding = Math.round((width - width * widthPercent) / 2);
286 var w = width - 2 * padding;
288 // Reduce height if candidate view is enabled
289 h = this.currentKeysetView.disableCandidateView ? h :
290 h - candidateViewHeight;
292 var backspaceWeight = this.currentKeysetView.backspaceKey ?
293 this.currentKeysetView.backspaceKey.getParent().getWidthInWeight() : 0;
294 this.candidateView.setWidthInWeight(
295 this.currentKeysetView.getWidthInWeight(), backspaceWeight);
296 this.candidateView.resize(w, candidateViewHeight);
297 this.expandedCandidateView.setWidthInWeight(
298 this.currentKeysetView.getWidthInWeight(), backspaceWeight);
299 this.expandedCandidateView.resize(w, h);
300 if (i18n.input.chrome.inputview.GlobalFlags.isQPInputView) {
301 var candidateElem = this.candidateView.getElement();
302 candidateElem.style.paddingLeft = candidateElem.style.paddingRight =
304 this.currentKeysetView.resize(width, h, widthPercent);
305 var expandViewElem = this.expandedCandidateView.getElement();
306 expandViewElem.style.marginLeft = expandViewElem.style.marginRight =
309 this.currentKeysetView.resize(w, h, 1);
310 elem.style.paddingLeft = elem.style.paddingRight = padding + 'px';
312 if (this.expandedCandidateView.isVisible()) {
313 // Closes the expanded candidate view if it's visible.
314 // This is to avoid mis-layout issue for the expanded candidate when screen
316 this.expandedCandidateView.state = content.ExpandedCandidateView.State.NONE;
317 this.candidateView.switchToIcon(
318 content.CandidateView.IconType.EXPAND_CANDIDATES, true);
319 this.expandedCandidateView.setVisible(false);
320 this.currentKeysetView.setVisible(true);
322 this.altDataView.resize(screen.width, height);
323 this.swipeView.resize(screen.width, height);
324 this.selectView.resize(screen.width, height);
325 this.menuView.resize(screen.width, height);
326 this.voiceView.resize(w + padding, height);
327 if (this.adapter_.isGestureTypingEnabled()) {
328 this.gestureCanvasView.resize(screen.width, height);
334 KeyboardContainer.prototype.disposeInternal = function() {
335 goog.dispose(this.candidateView);
336 goog.dispose(this.altDataView);
337 goog.dispose(this.swipeView);
338 goog.dispose(this.selectView);
339 goog.dispose(this.menuView);
340 goog.dispose(this.voiceView);
341 if (this.adapter_.isGestureTypingEnabled()) {
342 goog.dispose(this.gestureCanvasView);
344 for (var key in this.keysetViewMap) {
345 goog.dispose(this.keysetViewMap[key]);
348 goog.base(this, 'disposeInternal');
353 * Whether there are strokes on canvas.
355 * @return {boolean} Whether there are strokes on canvas.
357 KeyboardContainer.prototype.hasStrokesOnCanvas = function() {
358 if (this.currentKeysetView) {
359 return this.currentKeysetView.hasStrokesOnCanvas();
369 KeyboardContainer.prototype.cleanStroke = function() {
370 if (this.currentKeysetView) {
371 this.currentKeysetView.cleanStroke();