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.elements.Element');
21 goog.require('i18n.input.chrome.inputview.elements.ElementType');
22 goog.require('i18n.input.chrome.inputview.elements.content.AltDataView');
23 goog.require('i18n.input.chrome.inputview.elements.content.CandidateView');
24 goog.require('i18n.input.chrome.inputview.elements.content.EmojiView');
25 goog.require('i18n.input.chrome.inputview.elements.content.ExpandedCandidateView');
26 goog.require('i18n.input.chrome.inputview.elements.content.FloatingView');
27 goog.require('i18n.input.chrome.inputview.elements.content.GestureCanvasView');
28 goog.require('i18n.input.chrome.inputview.elements.content.GesturePreviewView');
29 goog.require('i18n.input.chrome.inputview.elements.content.HandwritingView');
30 goog.require('i18n.input.chrome.inputview.elements.content.KeysetView');
31 goog.require('i18n.input.chrome.inputview.elements.content.MenuView');
32 goog.require('i18n.input.chrome.inputview.elements.content.SelectView');
33 goog.require('i18n.input.chrome.inputview.elements.content.SwipeView');
34 goog.require('i18n.input.chrome.inputview.elements.content.VoiceView');
38 goog.scope(function() {
39 var Css = i18n.input.chrome.inputview.Css;
40 var EmojiView = i18n.input.chrome.inputview.elements.content.EmojiView;
41 var HandwritingView = i18n.input.chrome.inputview.elements.content.
43 var KeysetView = i18n.input.chrome.inputview.elements.content.KeysetView;
44 var content = i18n.input.chrome.inputview.elements.content;
45 var ElementType = i18n.input.chrome.inputview.elements.ElementType;
50 * The keyboard container.
52 * @param {!i18n.input.chrome.inputview.Adapter} adapter .
53 * @param {!i18n.input.chrome.sounds.SoundController} soundController .
54 * @param {goog.events.EventTarget=} opt_eventTarget The parent event target.
56 * @extends {i18n.input.chrome.inputview.elements.Element}
58 // TODO(bshe): Move this file to elements/content
59 i18n.input.chrome.inputview.KeyboardContainer =
60 function(adapter, soundController, opt_eventTarget) {
61 goog.base(this, '', ElementType.KEYBOARD_CONTAINER_VIEW, opt_eventTarget);
63 /** @type {!content.CandidateView} */
64 this.candidateView = new content.CandidateView(
65 'candidateView', adapter, this);
67 /** @type {!content.AltDataView} */
68 this.altDataView = new content.AltDataView(this);
70 /** @type {!content.GesturePreviewView} */
71 this.gesturePreviewView = new content.GesturePreviewView(this);
73 /** @type {!content.SwipeView} */
74 this.swipeView = new content.SwipeView(adapter, this.candidateView, this);
76 /** @type {!content.SelectView} */
77 this.selectView = new content.SelectView(this);
79 /** @type {!content.MenuView} */
80 this.menuView = new content.MenuView(this);
82 /** @type {!content.VoiceView} */
83 this.voiceView = new content.VoiceView(this, adapter, soundController);
85 /** @type {!content.ExpandedCandidateView} */
86 this.expandedCandidateView = new content.ExpandedCandidateView(this);
89 * The map of the KeysetViews.
91 * Value: The view object.
93 * @type {!Object.<string, !KeysetView>}
95 this.keysetViewMap = {};
98 * The bus channel to communicate with background.
100 * @private {!i18n.input.chrome.inputview.Adapter}
102 this.adapter_ = adapter;
104 goog.inherits(i18n.input.chrome.inputview.KeyboardContainer,
105 i18n.input.chrome.inputview.elements.Element);
106 var KeyboardContainer = i18n.input.chrome.inputview.KeyboardContainer;
109 /** @type {!KeysetView} */
110 KeyboardContainer.prototype.currentKeysetView;
114 * The padding bottom of the whole keyboard.
118 KeyboardContainer.PADDING_BOTTOM_ = 7;
122 * The margin of the tab style keyset.
127 KeyboardContainer.TAB_MARGIN_ = 11;
131 * An div to wrapper candidate view and keyboard set view.
135 KeyboardContainer.prototype.wrapperDiv_ = null;
139 * The gesture canvas view.
141 * @type {content.GestureCanvasView}
143 KeyboardContainer.prototype.gestureCanvasView = null;
147 * The gesture canvas view.
149 * @type {content.FloatingView}
151 KeyboardContainer.prototype.floatingView = null;
155 KeyboardContainer.prototype.createDom = function() {
156 goog.base(this, 'createDom');
158 var elem = this.getElement();
159 var dom = this.getDomHelper();
160 this.wrapperDiv_ = dom.createDom(goog.dom.TagName.DIV, Css.WRAPPER);
161 this.candidateView.render(this.wrapperDiv_);
162 dom.appendChild(elem, this.wrapperDiv_);
163 this.altDataView.render();
164 this.gesturePreviewView.render();
165 this.swipeView.render();
166 this.selectView.render();
167 this.menuView.render();
168 this.voiceView.render();
169 this.voiceView.setVisible(false);
170 this.expandedCandidateView.render(this.wrapperDiv_);
171 this.expandedCandidateView.setVisible(false);
172 if (this.adapter_.isFloatingVirtualKeyboardEnabled()) {
173 this.floatingView = new content.FloatingView(this);
174 this.floatingView.render();
176 this.gestureCanvasView = new content.GestureCanvasView(this);
177 this.gestureCanvasView.render(this.wrapperDiv_);
178 goog.dom.classlist.add(elem, Css.CONTAINER);
183 KeyboardContainer.prototype.update = function() {
184 this.currentKeysetView && this.currentKeysetView.update();
189 * Adds a keyset view.
191 * @param {!Object} keysetData .
192 * @param {!Object} layoutData .
193 * @param {string} keyset .
194 * @param {string} languageCode .
195 * @param {!i18n.input.chrome.inputview.Model} model .
196 * @param {string} inputToolName .
197 * @param {!Object.<string, boolean>} conditions .
199 KeyboardContainer.prototype.addKeysetView = function(keysetData, layoutData,
200 keyset, languageCode, model, inputToolName, conditions) {
202 if (keyset == 'emoji') {
203 view = new EmojiView(keysetData, layoutData, keyset, languageCode, model,
204 inputToolName, this, this.adapter_);
205 } else if (keyset == 'hwt') {
206 view = new HandwritingView(keysetData, layoutData, keyset, languageCode,
207 model, inputToolName, this, this.adapter_);
209 view = new KeysetView(keysetData, layoutData, keyset, languageCode, model,
210 inputToolName, this, this.adapter_);
212 view.render(this.wrapperDiv_);
213 view.applyConditions(conditions);
214 view.setVisible(false);
215 this.keysetViewMap[keyset] = view;
220 * Switches to a keyset.
222 * @param {string} keyset .
223 * @param {string} title .
224 * @param {boolean} isPasswordBox .
225 * @param {boolean} isA11yMode .
226 * @param {string} rawKeyset The raw keyset id will switch to.
227 * @param {string} lastRawkeyset .
228 * @param {string} languageCode .
229 * @return {boolean} True if switched successfully.
231 KeyboardContainer.prototype.switchToKeyset = function(keyset, title,
232 isPasswordBox, isA11yMode, rawKeyset, lastRawkeyset, languageCode) {
233 if (!this.keysetViewMap[keyset]) {
237 for (var name in this.keysetViewMap) {
238 var view = this.keysetViewMap[name];
239 if (name == keyset) {
240 this.candidateView.setVisible(!view.disableCandidateView);
241 // Before setting view visible, activate it first, since activation may
243 view.activate(rawKeyset);
244 view.setVisible(true);
247 view.spaceKey.updateTitle(title, !isPasswordBox &&
248 keyset != 'hwt' && keyset != 'emoji');
251 goog.dom.classlist.add(this.getElement(), Css.A11Y);
253 // If current raw keyset is changed, record it.
254 if (lastRawkeyset != rawKeyset) {
255 view.fromKeyset = lastRawkeyset;
257 if (view instanceof HandwritingView) {
258 view.setLanguagecode(languageCode);
260 // Deactivate the last keyset view instance.
261 if (this.currentKeysetView != view) {
262 if (this.currentKeysetView) {
263 this.currentKeysetView.deactivate(lastRawkeyset);
265 this.currentKeysetView = view;
267 this.candidateView.updateByKeyset(rawKeyset, isPasswordBox,
268 goog.i18n.bidi.isRtlLanguage(languageCode));
270 view.setVisible(false);
273 var isCompact = keyset.indexOf('compact') >= 0;
274 this.selectView.setKeysetSupported(isCompact);
275 this.swipeView.setKeysetSupported(isCompact);
281 * Resizes the whole keyboard.
283 * @param {number} width .
284 * @param {number} height .
285 * @param {number} widthPercent .
286 * @param {number} candidateViewHeight .
288 KeyboardContainer.prototype.setContainerSize = function(width, height,
289 widthPercent, candidateViewHeight) {
290 if (!this.currentKeysetView) {
293 var elem = this.getElement();
296 var wrapperMargin = 0;
297 this.wrapperDiv_.style.marginTop = this.wrapperDiv_.style.marginBottom =
298 wrapperMargin + 'px';
299 h -= KeyboardContainer.PADDING_BOTTOM_;
300 elem.style.paddingBottom = KeyboardContainer.PADDING_BOTTOM_ + 'px';
302 var padding = Math.round((width - width * widthPercent) / 2);
303 var w = width - 2 * padding;
305 // Reduce height if candidate view is enabled
306 h = this.currentKeysetView.disableCandidateView ? h :
307 h - candidateViewHeight;
309 var backspaceWeight = this.currentKeysetView.backspaceKey ?
310 this.currentKeysetView.backspaceKey.getParent().getWidthInWeight() : 0;
311 this.candidateView.setWidthInWeight(
312 this.currentKeysetView.getWidthInWeight(), backspaceWeight);
313 this.candidateView.resize(w, candidateViewHeight);
314 this.expandedCandidateView.setWidthInWeight(
315 this.currentKeysetView.getWidthInWeight(), backspaceWeight);
316 this.expandedCandidateView.resize(w, h);
317 var candidateElem = this.candidateView.getElement();
318 candidateElem.style.paddingLeft = candidateElem.style.paddingRight =
320 this.currentKeysetView.resize(width, h, widthPercent);
321 var expandViewElem = this.expandedCandidateView.getElement();
322 expandViewElem.style.marginLeft = expandViewElem.style.marginRight =
324 if (this.expandedCandidateView.isVisible()) {
325 // Closes the expanded candidate view if it's visible.
326 // This is to avoid mis-layout issue for the expanded candidate when screen
328 this.expandedCandidateView.state = content.ExpandedCandidateView.State.NONE;
329 this.candidateView.switchToIcon(
330 content.CandidateView.IconType.EXPAND_CANDIDATES, true);
331 this.expandedCandidateView.setVisible(false);
332 this.currentKeysetView.setVisible(true);
334 this.altDataView.resize(width, height);
335 this.gesturePreviewView.resize(width, height);
336 this.swipeView.resize(width, height);
337 this.selectView.resize(width, height);
338 this.menuView.resize(width, height);
339 this.voiceView.resize(w + padding, height);
340 if (this.floatingView) {
341 this.floatingView.resize(width, height);
343 this.gestureCanvasView.resize(width, height);
348 KeyboardContainer.prototype.disposeInternal = function() {
349 goog.dispose(this.candidateView);
350 goog.dispose(this.altDataView);
351 goog.dispose(this.gesturePreviewView);
352 goog.dispose(this.swipeView);
353 goog.dispose(this.selectView);
354 goog.dispose(this.menuView);
355 goog.dispose(this.voiceView);
356 if (this.floatingView) {
357 goog.dispose(this.floatingView);
359 goog.dispose(this.gestureCanvasView);
360 for (var key in this.keysetViewMap) {
361 goog.dispose(this.keysetViewMap[key]);
364 goog.base(this, 'disposeInternal');
369 * Whether there are strokes on canvas.
371 * @return {boolean} Whether there are strokes on canvas.
373 KeyboardContainer.prototype.hasStrokesOnCanvas = function() {
374 if (this.currentKeysetView) {
375 return this.currentKeysetView.hasStrokesOnCanvas();
385 KeyboardContainer.prototype.cleanStroke = function() {
386 if (this.currentKeysetView) {
387 this.currentKeysetView.cleanStroke();