Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / google_input_tools / src / chrome / os / inputview / keyboardcontainer.js
blob71fb0495052fcd14d3b0acd017ba680877f0f4a5
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
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
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.
42     HandwritingView;
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;
49 /**
50  * The keyboard container.
51  *
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.
55  * @constructor
56  * @extends {i18n.input.chrome.inputview.elements.Element}
57  */
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);
88   /**
89    * The map of the KeysetViews.
90    * Key: keyboard code.
91    * Value: The view object.
92    *
93    * @type {!Object.<string, !KeysetView>}
94    */
95   this.keysetViewMap = {};
97   /**
98    * The bus channel to communicate with background.
99    *
100    * @private {!i18n.input.chrome.inputview.Adapter}
101    */
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.
116  * @private {number}
117  */
118 KeyboardContainer.PADDING_BOTTOM_ = 7;
122  * The margin of the tab style keyset.
124  * @type {number}
125  * @private
126  */
127 KeyboardContainer.TAB_MARGIN_ = 11;
131  * An div to wrapper candidate view and keyboard set view.
133  * @private {Element}
134  */
135 KeyboardContainer.prototype.wrapperDiv_ = null;
139  * The gesture canvas view.
141  * @type {content.GestureCanvasView}
142  */
143 KeyboardContainer.prototype.gestureCanvasView = null;
147  * The gesture canvas view.
149  * @type {content.FloatingView}
150  */
151 KeyboardContainer.prototype.floatingView = null;
154 /** @override */
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();
175   }
176   this.gestureCanvasView = new content.GestureCanvasView(this);
177   this.gestureCanvasView.render(this.wrapperDiv_);
178   goog.dom.classlist.add(elem, Css.CONTAINER);
182 /** @override */
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 .
198  */
199 KeyboardContainer.prototype.addKeysetView = function(keysetData, layoutData,
200     keyset, languageCode, model, inputToolName, conditions) {
201   var view;
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_);
208   } else {
209     view = new KeysetView(keysetData, layoutData, keyset, languageCode, model,
210         inputToolName, this, this.adapter_);
211   }
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.
230  */
231 KeyboardContainer.prototype.switchToKeyset = function(keyset, title,
232     isPasswordBox, isA11yMode, rawKeyset, lastRawkeyset, languageCode) {
233   if (!this.keysetViewMap[keyset]) {
234     return false;
235   }
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
242       // change view keys.
243       view.activate(rawKeyset);
244       view.setVisible(true);
245       view.update();
246       if (view.spaceKey) {
247         view.spaceKey.updateTitle(title, !isPasswordBox &&
248             keyset != 'hwt' && keyset != 'emoji');
249       }
250       if (isA11yMode) {
251         goog.dom.classlist.add(this.getElement(), Css.A11Y);
252       }
253       // If current raw keyset is changed, record it.
254       if (lastRawkeyset != rawKeyset) {
255         view.fromKeyset = lastRawkeyset;
256       }
257       if (view instanceof HandwritingView) {
258         view.setLanguagecode(languageCode);
259       }
260       // Deactivate the last keyset view instance.
261       if (this.currentKeysetView != view) {
262         if (this.currentKeysetView) {
263           this.currentKeysetView.deactivate(lastRawkeyset);
264         }
265         this.currentKeysetView = view;
266       }
267       this.candidateView.updateByKeyset(rawKeyset, isPasswordBox,
268           goog.i18n.bidi.isRtlLanguage(languageCode));
269     } else {
270       view.setVisible(false);
271     }
272   }
273   var isCompact = keyset.indexOf('compact') >= 0;
274   this.selectView.setKeysetSupported(isCompact);
275   this.swipeView.setKeysetSupported(isCompact);
276   return true;
281  * Resizes the whole keyboard.
283  * @param {number} width .
284  * @param {number} height .
285  * @param {number} widthPercent .
286  * @param {number} candidateViewHeight .
287  */
288 KeyboardContainer.prototype.setContainerSize = function(width, height,
289     widthPercent, candidateViewHeight) {
290   if (!this.currentKeysetView) {
291     return;
292   }
293   var elem = this.getElement();
295   var h = height;
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 =
319       padding + 'px';
320   this.currentKeysetView.resize(width, h, widthPercent);
321   var expandViewElem = this.expandedCandidateView.getElement();
322   expandViewElem.style.marginLeft = expandViewElem.style.marginRight =
323       padding + 'px';
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
327     // is rotated.
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);
333   }
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);
342   }
343   this.gestureCanvasView.resize(width, height);
347 /** @override */
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);
358   }
359   goog.dispose(this.gestureCanvasView);
360   for (var key in this.keysetViewMap) {
361     goog.dispose(this.keysetViewMap[key]);
362   }
364   goog.base(this, 'disposeInternal');
369  * Whether there are strokes on canvas.
371  * @return {boolean} Whether there are strokes on canvas.
372  */
373 KeyboardContainer.prototype.hasStrokesOnCanvas = function() {
374   if (this.currentKeysetView) {
375     return this.currentKeysetView.hasStrokesOnCanvas();
376   } else {
377     return false;
378   }
383  * Cleans the stokes.
384  */
385 KeyboardContainer.prototype.cleanStroke = function() {
386   if (this.currentKeysetView) {
387     this.currentKeysetView.cleanStroke();
388   }
391 });  // goog.scope