Rewrite AndroidSyncSettings to be significantly simpler.
[chromium-blink-merge.git] / remoting / webapp / app_remoting / js / keyboard_layouts_menu.js
blob3c82cdba82b9146284e1760ed7be63435de295d4
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 /**
6 * @fileoverview
7 * Class managing the host's available keyboard layouts, allowing the user to
8 * select one that matches the local layout, or auto-selecting based on the
9 * current locale.
12 'use strict';
14 /** @suppress {duplicate} */
15 var remoting = remoting || {};
17 /**
18 * @param {remoting.ContextMenuAdapter} adapter
19 * @constructor
21 remoting.KeyboardLayoutsMenu = function(adapter) {
22 /**
23 * @type {remoting.ContextMenuAdapter}
24 * @private
26 this.adapter_ = adapter;
27 /**
28 * @type {remoting.SubmenuManager}
29 * @private
31 this.submenuManager_ = new remoting.SubmenuManager(
32 adapter,
33 chrome.i18n.getMessage(/*i18n-content*/'KEYBOARD_LAYOUTS_SUBMENU_TITLE'),
34 true);
35 /**
36 * @type {string}
37 * @private
39 this.currentLayout_ = '';
41 adapter.addListener(this.onContextMenu_.bind(this));
44 /**
45 * @param {Array<string>} layouts The keyboard layouts available on the host,
46 * for example en-US, de-DE
47 * @param {string} currentLayout The layout currently active on the host.
49 remoting.KeyboardLayoutsMenu.prototype.setLayouts =
50 function(layouts, currentLayout) {
51 this.submenuManager_.removeAll();
52 this.currentLayout_ = '';
53 for (var i = 0; i < layouts.length; ++i) {
54 this.submenuManager_.add(this.makeMenuId_(layouts[i]), layouts[i]);
56 // Pick a suitable default layout.
57 this.getBestLayout_(layouts, currentLayout,
58 this.setLayout_.bind(this, false));
61 /**
62 * Notify the host that a new keyboard layout has been selected.
64 * @param {boolean} saveToLocalStorage If true, save the specified layout to
65 * local storage.
66 * @param {string} layout The new keyboard layout.
67 * @private
69 remoting.KeyboardLayoutsMenu.prototype.setLayout_ =
70 function(saveToLocalStorage, layout) {
71 if (this.currentLayout_ != '') {
72 this.adapter_.updateCheckState(
73 this.makeMenuId_(this.currentLayout_), false);
75 this.adapter_.updateCheckState(this.makeMenuId_(layout), true);
76 this.currentLayout_ = layout;
78 console.log("Setting the keyboard layout to '" + layout + "'");
79 remoting.clientSession.sendClientMessage(
80 'setKeyboardLayout',
81 JSON.stringify({layout: layout}));
82 if (saveToLocalStorage) {
83 var params = {};
84 params[remoting.KeyboardLayoutsMenu.KEY_] = layout;
85 chrome.storage.local.set(params);
89 /**
90 * Choose the best keyboard from the alternatives, based on the following
91 * algorithm:
92 * - Search local storage by for a preferred keyboard layout for the app;
93 * if it is found, prefer it over the current locale, falling back on the
94 * latter only if no match is found.
95 * - If the candidate layout matches one of the supported layouts, use it.
96 * - Otherwise, if the language portion of the candidate matches that of
97 * any of the supported layouts, use the first such layout (e.g, en-AU
98 * will match either en-US or en-GB, whichever appears first).
99 * - Otherwise, use the host's current layout.
101 * @param {Array<string>} layouts
102 * @param {string} currentHostLayout
103 * @param {function(string):void} onDone
104 * @private
106 remoting.KeyboardLayoutsMenu.prototype.getBestLayout_ =
107 function(layouts, currentHostLayout, onDone) {
109 * Extract the language id from a string that is either "language" (e.g.
110 * "de") or "language-region" (e.g. "en-US").
112 * @param {string} layout
113 * @return {string}
115 var getLanguage = function(layout) {
116 var languageAndRegion = layout.split('-');
117 switch (languageAndRegion.length) {
118 case 1:
119 case 2:
120 return languageAndRegion[0];
121 default:
122 return '';
126 /** @param {Object<string>} storage */
127 var chooseLayout = function(storage) {
128 var configuredLayout = storage[remoting.KeyboardLayoutsMenu.KEY_];
129 var tryLayouts = [ chrome.i18n.getUILanguage() ];
130 if (configuredLayout && typeof(configuredLayout) == 'string') {
131 tryLayouts.unshift(configuredLayout);
133 for (var i = 0; i < tryLayouts.length; ++i) {
134 if (layouts.indexOf(tryLayouts[i]) != -1) {
135 onDone(tryLayouts[i]);
136 return;
138 var language = getLanguage(tryLayouts[i]);
139 if (language) {
140 for (var j = 0; j < layouts.length; ++j) {
141 if (language == getLanguage(layouts[j])) {
142 onDone(layouts[j]);
143 return;
148 // Neither the stored layout nor UI locale was suitable.
149 onDone(currentHostLayout);
152 chrome.storage.local.get(remoting.KeyboardLayoutsMenu.KEY_, chooseLayout);
156 * Create a menu id from the given keyboard layout.
158 * @param {string} layout Keyboard layout
159 * @return {string}
160 * @private
162 remoting.KeyboardLayoutsMenu.prototype.makeMenuId_ = function(layout) {
163 return 'layout@' + layout;
167 * Handle a click on the application's context menu.
169 * @param {OnClickData=} info
170 * @private
172 remoting.KeyboardLayoutsMenu.prototype.onContextMenu_ = function(info) {
173 /** @type {Array<string>} */
174 var components = info.menuItemId.split('@');
175 if (components.length == 2 &&
176 this.makeMenuId_(components[1]) == info.menuItemId) {
177 this.setLayout_(true, components[1]);
182 * @type {string}
183 * @private
185 remoting.KeyboardLayoutsMenu.KEY_ = 'preferred-keyboard-layout';