Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(443)

Side by Side Diff: chrome/browser/resources/settings/languages_page/languages_model.js

Issue 1351623008: MD Settings: Languages model for language pages (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@SingletonPrefs
Patch Set: move iron-list to dependency patchset Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 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.
4
5 /**
6 * @fileoverview 'cr-settings-languages-model' provides convenient access to
7 * Chrome's language and input method settings.
8 *
9 * @group Chrome Settings Elements
10 * @element cr-settings-languages-model
11 */
12
13 /**
14 * @typedef {{spellCheckEnabled: boolean}}
15 */
16 var LanguageState;
17
18 /**
19 * @typedef {{language: !chrome.languageSettingsPrivate.Language,
20 * state: !LanguageState}}
21 */
22 var LanguageInfo;
23
24 /**
25 * The model includes:
26 * supportedLanguages: an array of languages, ordered alphabetically.
27 * enabledLanguages: an array of enabled language info and state, ordered by
28 * preference.
29 * @typedef {{
30 * supportedLanguages: !Array<!chrome.languageSettingsPrivate.Language>,
31 * enabledLanguages: !Array<!LanguageInfo>
32 * }}
33 */
34 var LanguagesModel;
35
36 (function() {
37 'use strict';
38
39 /** Exposes the singleton model to hosts. */
40 Polymer({
41 is: 'cr-settings-languages-model',
42
43 properties: {
44 /**
45 * Shared languages model.
46 * @type {(LanguagesModel|undefined)}
47 */
48 model: {
49 type: Object,
50 notify: true,
51 readOnly: true,
52 },
53
54 /**
55 * Shared private state.
stevenjb 2015/09/22 01:45:15 nit: This only kind of makes sense to me because w
michaelpg 2015/09/22 04:03:15 I've added documentation in the file overview and
56 * @type {!Element}
57 */
58 privateModel_: {
59 type: Object,
60 value: document.createElement('cr-settings-languages-model-private'),
61 },
62 },
63
64 ready: function() {
65 this.squelching_(function() {
66 // This notifies the host via Polymer.
67 this._setModel(this.privateModel_.model);
68 });
69 this.listen(this.privateModel_, 'model-changed', 'privateModelChanged_');
70 },
71
72 /**
73 * On supported systems, sets the prospective UI language to the chosen
74 * language. This dosen't affect the actual UI language until a restart.
stevenjb 2015/09/22 01:45:15 Rather than duplicating these comments, I would ei
michaelpg 2015/09/22 04:03:15 Done.
75 * @param {string} languageCode
76 */
77 setUILanguage: function(languageCode) {
78 this.privateModel_.setUILanguage(languageCode);
79 },
80
81 /**
82 * Enables the language, making it available for spell check and input.
83 * @param {string} languageCode
84 * */
85 enableLanguage: function(languageCode) {
86 this.privateModel_.enableLanguage(languageCode);
87 },
88
89 /**
90 * Disables the language.
91 * @param {string} languageCode
92 */
93 disableLanguage: function(languageCode) {
94 this.privateModel_.disableLanguage(languageCode);
95 },
96
97 /**
98 * @param {string} languageCode
99 * @return {boolean} True if the language is enabled.
100 */
101 isEnabled: function(languageCode) {
102 return this.privateModel_.isEnabled(languageCode);
103 },
104
105 /**
106 * Enables or disables spell check for the given language.
107 * @param {string} languageCode
108 * @param {boolean} enable
109 */
110 toggleSpellCheck: function(languageCode, enable) {
111 this.privateModel_.toggleSpellCheck(languageCode, enable);
112 },
113
114 /**
115 * Forwards changes reported by privateModel_ to the host.
116 * @private
117 */
118 privateModelChanged_: function(e) {
119 // Squelch because we've defeated Polymer's internal dirty-checking.
120 this.squelching_(function() {
121 // Forward notification to host.
122 this.fire(e.type, e.detail, {bubbles: false});
123 });
124 },
125
126 /**
127 * Sets a "squelch" switch before calling the function, so functions can
128 * return early when the switch is active.
129 * @param {!function()} fn
130 * @private
131 */
132 squelching_: function(fn) {
133 this.squelch_ = true;
stevenjb 2015/09/22 01:45:15 I don't see anywhere that we check |squelch_| ?
michaelpg 2015/09/22 04:03:15 You're right, we don't need to because model is re
134 fn.call(this);
135 // We can unset squelch_ now because change notifications are synchronous.
136 this.squelch_ = false;
137 },
138 });
139
140 var preferredLanguagesPath;
141 if (cr.isChromeOS)
142 preferredLanguagesPath = 'prefs.settings.language.preferred_languages.value';
143 else
144 preferredLanguagesPath = 'prefs.intl.accept_languages.value';
145
146 /**
147 * Privately used element that contains, listens to and updates the shared
148 * languages model.
149 */
150 Polymer({
151 is: 'cr-settings-languages-model-private',
152
153 properties: {
154 /**
155 * @type {(LanguagesModel|undefined)}
156 */
157 model: {
158 type: Object,
159 notify: true,
160 },
161
162 /**
163 * Object containing all preferences, for use by Polymer controls.
164 */
165 prefs: {
166 type: Object,
167 notify: true,
168 },
169 },
170
171 /**
172 * Hash map of model.supportedLanguages for fast lookup. Not data bound.
stevenjb 2015/09/22 01:45:16 nit: describe what the key is for this map and the
michaelpg 2015/09/22 04:03:15 Done.
173 * @private {!Object<!chrome.languageSettingsPrivate.Language>}
174 */
175 supportedLanguageMap_: {},
176
177 /**
178 * Hash maps of model.enabledLanguages for fast lookup. Not data bound.
179 * @private {!Object<!LanguageInfo>}
180 */
181 enabledLanguageMap_: {},
182
183 observers: [
184 'preferredLanguagesPrefChanged_(' + preferredLanguagesPath + ')',
185 'spellCheckDictionariesPrefChanged_(prefs.spellcheck.dictionaries.value.*)',
186 ],
187
188 /** @override */
189 created: function() {
190 chrome.languageSettingsPrivate.getLanguageList(function(languageList) {
191 // Wait until prefs are initialized before creating the model, so we can
192 // include information about enabled languages.
193 CrSettingsPrefs.initialized.then(function() {
194 this.createModel_(languageList);
195 this.initialized_ = true;
196 }.bind(this));
197 }.bind(this));
198 },
199
200 /**
201 * Constructs the model with the given language list.
202 * @param {!Array<!chrome.languageSettingsPrivate.Language>}
203 * supportedLanguages
204 */
205 createModel_: function(supportedLanguages) {
206 // Populate the hash map of supported languages.
207 for (var i = 0; i < supportedLanguages.length; i++) {
208 this.supportedLanguageMap_[supportedLanguages[i].code] =
209 supportedLanguages[i];
210 }
211
212 // Create a list of enabled language info from the supported languages.
213 var enabledLanguages = this.getEnabledLanguages_();
214 // Populate the hash map of enabled languages.
215 for (var i = 0; i < enabledLanguages.length; i++) {
216 var languageInfo = enabledLanguages[i];
217 this.enabledLanguageMap_[languageInfo.language.code] = languageInfo;
218 }
219
220 // Initialize the Polymer model.
221 this.model = {
222 supportedLanguages: supportedLanguages,
223 enabledLanguages: enabledLanguages,
224 };
225 },
226
227 /**
228 * Returns a list of LanguageInfos for each enabled language in the supported
229 * languages list.
230 * @private
231 * @return {!Array<!LanguageInfo>}
232 */
233 getEnabledLanguages_: function() {
234 var languageCodes = this.get(preferredLanguagesPath).split(',');
stevenjb 2015/09/22 01:45:15 Could this.preferredLanguagesPath be undefined if
michaelpg 2015/09/22 04:03:15 Once prefs are initialized, I believe every pref s
stevenjb 2015/09/22 16:47:33 Hmm. I'm not super excited about a typo in C++ cod
235 var enabledLanguages = [];
236 var spellCheckMap = this.getSpellCheckMap_();
237 for (var i = 0; i < languageCodes.length; i++) {
238 var code = languageCodes[i];
239 var language = this.supportedLanguageMap_[code];
240 if (!language)
241 continue;
242 var state = {spellCheckEnabled: !!spellCheckMap[code]};
243 enabledLanguages.push({language: language, state: state});
244 }
245 return enabledLanguages;
246 },
247
248 /**
249 * Creates a map whose keys are languages enabled for spell check.
250 * @return {!Object<boolean>}
251 */
252 getSpellCheckMap_: function() {
253 var spellCheckPref = /** @type {chrome.settingsPrivate.PrefObject} */(
254 this.get('prefs.spellcheck.dictionaries'));
stevenjb 2015/09/22 01:45:16 Here too, maybe handle spellCheckPref == undefined
255 var spellCheckCodes = spellCheckPref.value;
256 var spellCheckMap = {};
257 for (var i = 0; i < spellCheckCodes.length; i++)
258 spellCheckMap[spellCheckCodes[i]] = true;
259 return spellCheckMap;
260 },
261
262 /** @private */
263 preferredLanguagesPrefChanged_: function() {
264 if (!this.initialized_)
265 return;
266
267 var enabledLanguages = this.getEnabledLanguages_();
268 // Reset the enabled language map. Do this before notifying of the change
269 // via model.enabledLanguages.
270 this.enabledLanguageMap_ = {};
271 for (var i = 0; i < enabledLanguages.length; i++) {
272 var languageInfo = enabledLanguages[i];
273 this.enabledLanguageMap_[languageInfo.language.code] = languageInfo;
274 }
275 this.set('model.enabledLanguages', enabledLanguages);
276 },
277
278 /**
279 * Updates the spellCheckEnabled state of each enabled language.
280 * @private
281 */
282 spellCheckDictionariesPrefChanged_: function() {
283 if (!this.initialized_)
284 return;
285
286 var spellCheckMap = this.getSpellCheckMap_();
287 for (var i = 0; i < this.model.enabledLanguages.length; i++) {
288 this.set('model.enabledLanguages.' + i + '.state.spellCheckEnabled',
289 !!spellCheckMap[this.model.enabledLanguages[i].language.code]);
290 }
291 },
292
293 /**
294 * On supported systems, sets the prospective UI language to the chosen
295 * language. This dosen't affect the actual UI language until a restart.
296 * @param {string} languageCode
297 */
298 setUILanguage: function(languageCode) {
299 // Set the prospective UI language. This won't take effect until a restart.
300 if (cr.isWindows)
301 this.set('prefs.intl.app_locale.value', languageCode);
302 else if (cr.isChromeOS)
303 chrome.send('setUILanguage', [languageCode]);
stevenjb 2015/09/22 01:45:15 FWIW: Since we're using a chrome.send call here an
michaelpg 2015/09/22 04:03:15 Good call -- we should be setting the LocalState p
304 },
305
306 /**
307 * Enables the language, making it available for spell check and input.
308 * @param {string} languageCode
309 */
310 enableLanguage: function(languageCode) {
311 var languageCodes = this.get(preferredLanguagesPath);
stevenjb 2015/09/22 01:45:16 Handle undefined?
312 var index = languageCodes.split(',').indexOf(languageCode);
313 if (index > -1)
314 return;
315 this.set(preferredLanguagesPath, languageCodes + ',' + languageCode);
316 },
317
318 /**
319 * Disables the language.
320 * @param {string} languageCode
321 */
322 disableLanguage: function(languageCode) {
323 // Don't disable the UI language.
324 var appLocale = this.get('prefs.intl.app_locale.value') ||
325 navigator.language;
stevenjb 2015/09/22 01:45:15 Handle undefined?
326 if (languageCode == appLocale)
327 return;
328
329 var languageCodes = this.get(preferredLanguagesPath).split(',');
stevenjb 2015/09/22 01:45:15 Handle undefined?
330 // Don't disable the only enabled language.
331 if (languageCodes.length == 1)
332 return;
333
334 // Remove the language from spell check.
335 var spellCheckIndex =
336 this.get('prefs.spellcheck.dictionaries.value').indexOf(languageCode);
337 if (spellCheckIndex != -1)
338 this.splice('prefs.spellcheck.dictionaries.value', spellCheckIndex, 1);
stevenjb 2015/09/22 01:45:15 Handle undefined?
339
340 var languageIndex = languageCodes.indexOf(languageCode);
341 if (languageIndex == -1)
342 return;
343 languageCodes.splice(languageIndex, 1);
344 this.set(preferredLanguagesPath, languageCodes.join(','));
345 },
346
347 /**
348 * @param {string} languageCode
349 * @return {boolean} True if the language is enabled.
350 */
351 isEnabled: function(languageCode) {
352 return !!this.enabledLanguageMap_[languageCode];
353 },
354
355 /**
356 * Enables or disables spell check for the given language.
357 * @param {string} languageCode
358 * @param {boolean} enable
359 */
360 toggleSpellCheck: function(languageCode, enable) {
361 var spellCheckPref = /** @type {chrome.settingsPrivate.PrefObject} */(
362 this.get('prefs.spellcheck.dictionaries'));
stevenjb 2015/09/22 01:45:15 Handle undefined?
363 if (enable) {
364 if (spellCheckPref.value.indexOf(languageCode) == -1)
365 this.push('prefs.spellcheck.dictionaries.value', languageCode);
366 } else {
367 // TODO: need update externs before committing
368 this.arrayDelete('prefs.spellcheck.dictionaries.value', languageCode);
369 }
370 },
371 });
372 })();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698