1 <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
|
2 <html lang="en" xml:lang="en"> |
|
3 <head> |
|
4 <meta content="text/html; charset=utf-8" http-equiv="Content-Type" /> |
|
5 <meta name="copyright" content="(C) Copyright 2005" /> |
|
6 <meta name="DC.rights.owner" content="(C) Copyright 2005" /> |
|
7 <meta content="concept" name="DC.Type" /> |
|
8 <meta name="DC.Title" content="Travel Companion user interface" /> |
|
9 <meta scheme="URI" name="DC.Relation" content="WRTKit_Travel_Companion_Tutorial-GUID-be79ba64-fa03-4968-964e-d7dcc42d7053.html" /> |
|
10 <meta content="XHTML" name="DC.Format" /> |
|
11 <meta content="GUID-989D17CC-F019-46BB-B6F5-49166E258ACA" name="DC.Identifier" /> |
|
12 <meta content="en" name="DC.Language" /> |
|
13 <link href="commonltr.css" type="text/css" rel="stylesheet" /> |
|
14 <title> |
|
15 Travel Companion user interface</title> |
|
16 </head> |
|
17 <body id="GUID-989D17CC-F019-46BB-B6F5-49166E258ACA"><a name="GUID-989D17CC-F019-46BB-B6F5-49166E258ACA"><!-- --></a> |
|
18 |
|
19 |
|
20 |
|
21 <h1 class="topictitle1"> |
|
22 Travel Companion user interface</h1> |
|
23 |
|
24 <div> |
|
25 |
|
26 <div class="section"><h2 class="sectiontitle"> |
|
27 Handling multiple views</h2> |
|
28 |
|
29 |
|
30 <p> |
|
31 |
|
32 The Travel Companion widget will follow many of the same patterns that the Hello World |
|
33 and RSS Reader widgets have followed. The entry point to the widget is the init() function |
|
34 that we call from the onload event handler in the main HTML file TravelCompanion.html. |
|
35 We will implement the init() function along with the rest of the widget and user interface |
|
36 in the TravelCompanion.js file. Let's start with the init() function so that we get the |
|
37 widget up and running. |
|
38 </p> |
|
39 |
|
40 <p> |
|
41 |
|
42 From previous widgets we already know a lot of things about the WRTKit and about what |
|
43 we will need. For example we know that we will have a user interface manager and that |
|
44 we'll need a reference to each of the views that our widget uses. And since we have |
|
45 designed the Travel Companion widget we know what views we will have. Before we write the |
|
46 init() function we can go ahead and declare the variables that we will use to refer to |
|
47 the views and the user interface manager. And while we're at it we can also declare the |
|
48 variable that we'll use to refer to the Travel Companion engine. All of these variables |
|
49 are globals and thus go outside the init() function: |
|
50 </p> |
|
51 |
|
52 <pre> |
|
53 |
|
54 // Reference to travel companion engine that implements the business logic. |
|
55 var engine; |
|
56 |
|
57 // Reference to the WRTKit user interface manager. |
|
58 var uiManager; |
|
59 |
|
60 // References to views. |
|
61 var mainView; |
|
62 var infoView; |
|
63 var converterView; |
|
64 var weatherView; |
|
65 var settingsView; |
|
66 </pre> |
|
67 |
|
68 <p> |
|
69 |
|
70 Previously we've written the init() function so that it creates the entire user interface |
|
71 but because the Travel Companion widget has a much larger user interface than anything |
|
72 we've done before, it's probably a good idea to split things up into smaller functions |
|
73 so we don't end up with a huge init() function that will be hard to read and maintain. |
|
74 Let's create a function for the creation of each view, and then one function that will |
|
75 call these view creation functions and setup all other things that we need for the user |
|
76 interface, such as the Options menu. We'll just create stub functions for now but we |
|
77 will soon get to implement the functions: |
|
78 </p> |
|
79 |
|
80 <pre> |
|
81 |
|
82 // Creates the user interface. |
|
83 function createUI() { |
|
84 } |
|
85 |
|
86 // Creates the main view. |
|
87 function createMainView() { |
|
88 } |
|
89 |
|
90 // Creates the info view. |
|
91 function createInfoView() { |
|
92 } |
|
93 |
|
94 // Creates the converter view. |
|
95 function createConverterView() { |
|
96 } |
|
97 |
|
98 // Creates the weather view. |
|
99 function createWeatherView() { |
|
100 } |
|
101 |
|
102 // Creates the settings view. |
|
103 function createSettingsView() { |
|
104 } |
|
105 </pre> |
|
106 |
|
107 <p> |
|
108 |
|
109 In the RSS Reader widget we used functions called showMainView() and showSettings() to |
|
110 move between views. That allowed us to implement all the logic that was required when |
|
111 moving between views in one place regardless of what action triggered the change of |
|
112 views. We'll do the same thing in the Travel Companion widget but this time we'll need |
|
113 five functions since we have five views. Let's create stubs for these too at this stage |
|
114 so that the functions exist if we need to refer to them. |
|
115 </p> |
|
116 |
|
117 <pre> |
|
118 |
|
119 // Displays the main view. |
|
120 function showMainView() { |
|
121 } |
|
122 |
|
123 // Displays the info view. |
|
124 function showInfoView() { |
|
125 } |
|
126 |
|
127 // Displays the converter view. |
|
128 function showConverterView() { |
|
129 } |
|
130 |
|
131 // Displays the weather view. |
|
132 function showWeatherView() { |
|
133 } |
|
134 |
|
135 // Displays the settings view. |
|
136 function showSettingsView() { |
|
137 } |
|
138 </pre> |
|
139 |
|
140 <p> |
|
141 |
|
142 Since we will create each user interface view in its own function our init() function |
|
143 will be much simpler than in previous widgets. We will create the business logic engine, |
|
144 create the user interface by calling createUI() and then display the main view. |
|
145 </p> |
|
146 |
|
147 <pre> |
|
148 |
|
149 // Called from the onload event handler to initialize the widget. |
|
150 function init() { |
|
151 // initialize the business logic engine |
|
152 engine = new Engine(); |
|
153 |
|
154 // create the user interface |
|
155 createUI(); |
|
156 |
|
157 // display the main view |
|
158 showMainView(); |
|
159 } |
|
160 </pre> |
|
161 |
|
162 <p> |
|
163 |
|
164 Let's get started with creating the user interface by returning to the createUI() |
|
165 function. We'll want to widget to show the softkey bar and we'll want it to be in |
|
166 tab navigation mode instead of the default pointer navigation mode. We then need |
|
167 to create the user interface manager and the five views that this widget has. Of |
|
168 course those five views are actually created by the five create-functions that we |
|
169 just wrote stubs for so we just need to call those functions from createUI(). |
|
170 </p> |
|
171 |
|
172 <pre> |
|
173 |
|
174 // Creates the user interface. |
|
175 function createUI() { |
|
176 if (window.widget) { |
|
177 // set tab-navigation mode and show softkeys |
|
178 widget.setNavigationEnabled(false); |
|
179 menu.showSoftkeys(); |
|
180 } |
|
181 |
|
182 // create UI manager |
|
183 uiManager = new UIManager(); |
|
184 |
|
185 // create views |
|
186 createMainView(); |
|
187 createInfoView(); |
|
188 createConverterView(); |
|
189 createWeatherView(); |
|
190 createSettingsView(); |
|
191 } |
|
192 </pre> |
|
193 |
|
194 <p> |
|
195 |
|
196 Because we created the stub functions for moving between views, we can also create |
|
197 the Options menu now. We'll only add one item to the menu in addition to the default |
|
198 "Exit" menu item. The item we'll add is one that will take the user to the settings |
|
199 view. We'll first need to create a global menu item identifier: |
|
200 </p> |
|
201 |
|
202 <pre> |
|
203 |
|
204 // Constants for menu item identifiers. |
|
205 var MENU_ITEM_SETTINGS = 0; |
|
206 </pre> |
|
207 |
|
208 <p> |
|
209 |
|
210 Now that we have the menu item identifier we can actually create the menu item. Because |
|
211 the Options menu functionality is only available in the S60 Web Runtime and not in PC |
|
212 browsers we'll add that code in the same if-clause where we set the navigation mode and |
|
213 show the softkey bar. |
|
214 </p> |
|
215 |
|
216 <pre> |
|
217 |
|
218 // create menu |
|
219 var settingsMenuItem = new MenuItem("Settings", MENU_ITEM_SETTINGS); |
|
220 settingsMenuItem.onSelect = menuItemSelected; |
|
221 menu.append(settingsMenuItem); |
|
222 </pre> |
|
223 |
|
224 <p> |
|
225 |
|
226 When the menu item is selected it calls a function called menuItemSelected(). Let's |
|
227 create that function and handle the case when the settings menu item is selected. |
|
228 When it is, we want to call showSettingsView() so that the user ends up in the settings |
|
229 view as expected: |
|
230 </p> |
|
231 |
|
232 <pre> |
|
233 |
|
234 // Callback for when menu items are selected. |
|
235 function menuItemSelected(id) { |
|
236 switch (id) { |
|
237 case MENU_ITEM_SETTINGS: |
|
238 showSettingsView(); |
|
239 break; |
|
240 } |
|
241 } |
|
242 </pre> |
|
243 |
|
244 <p> |
|
245 |
|
246 The framework that we'll need when implementing the actual views is now nearly complete. |
|
247 But before we move on let's talk about how we'll be using softkeys in the Travel |
|
248 Companion widget. |
|
249 </p> |
|
250 |
|
251 <p> |
|
252 |
|
253 In the main view we want the right softkey to be the default "Exit". But in the |
|
254 four functional views we don't want it to exit the widget but rather to return to |
|
255 the main view. We'll thus use "Back" as the title in the functional views, except |
|
256 in the settings view where we'll use "Cancel". |
|
257 </p> |
|
258 |
|
259 <p> |
|
260 |
|
261 Let's create three functions that will handle setting the widget right softkey to |
|
262 these configurations. The functions will check if we're actually in the S60 Web |
|
263 Runtime before attempting to change the right softkey in order to make the widget |
|
264 also work in a PC browser for testing purposes. |
|
265 </p> |
|
266 |
|
267 <pre> |
|
268 |
|
269 // Sets the softkeys for the main view. |
|
270 function setMainViewSoftkeys() { |
|
271 if (window.widget) { |
|
272 // set right softkey to "exit" |
|
273 menu.setRightSoftkeyLabel("", null); |
|
274 } |
|
275 } |
|
276 |
|
277 // Sets the softkeys for sub views. |
|
278 function setSubViewSoftkeys() { |
|
279 if (window.widget) { |
|
280 // set right softkey to "back" (to main view) |
|
281 menu.setRightSoftkeyLabel("Back", showMainView); |
|
282 } |
|
283 } |
|
284 |
|
285 // Sets the softkeys for settings view. |
|
286 function setSettingsViewSoftkeys() { |
|
287 if (window.widget) { |
|
288 // set right softkey to "cancel" (returns to main view) |
|
289 menu.setRightSoftkeyLabel("Cancel", showMainView); |
|
290 } |
|
291 } |
|
292 </pre> |
|
293 |
|
294 </div> |
|
295 |
|
296 <div class="section"><h2 class="sectiontitle"> |
|
297 Main view</h2> |
|
298 |
|
299 |
|
300 <p> |
|
301 |
|
302 Let's create our main view now so that we get something visible. The main view is |
|
303 of course created in the function createMainView() for which we already created a |
|
304 stub function. The main view will have four WRTKit NavigationButton controls in it, |
|
305 one for each of the views (not counting the main view itself) in the widget. Using |
|
306 the NavigationButton control is just like using a FormButton, with the difference |
|
307 that it looks different and can have an icon image in addition to just text. Earlier |
|
308 when we looked at the files that were in the Examples/TravelCompanion directory we |
|
309 noticed that there were four icons there. Now it's time to use them as icons in the |
|
310 navigation buttons. |
|
311 </p> |
|
312 |
|
313 <p> |
|
314 |
|
315 We will add event listerners to the buttons so that when they are clicked (when they |
|
316 emit an ActionPerformed event) they will call the functions we have created for |
|
317 moving between views. At this point the functions are just stubs, but we will of |
|
318 course fix that later. |
|
319 </p> |
|
320 |
|
321 <p> |
|
322 |
|
323 We've had captions for the views that we've created so far in the Hello World and |
|
324 RSS Reader widgets and the Travel Companion will also have view captions. However |
|
325 for the Travel Companion we'll use an image as our view caption. We will set the |
|
326 view caption to an empty string because if it's undefined or null then the view |
|
327 caption area will be hidden. Then we will create a CSS rule for the ListViewCaptionText |
|
328 class that is used by the area where the caption text goes in a list view. Because |
|
329 our CSS rule is defined after the default WRTKit CSS rule for ListViewCaptionText, |
|
330 our rule will be override the default one. Let's open up TravelCompanion.css and |
|
331 create this rule: |
|
332 </p> |
|
333 |
|
334 <pre> |
|
335 |
|
336 /* Place logo in list view caption */ |
|
337 .ListViewCaptionText { |
|
338 background: url("ListViewCaptionLogo.png") no-repeat; |
|
339 height: 35px; |
|
340 } |
|
341 </pre> |
|
342 |
|
343 <p> |
|
344 |
|
345 We specified a height in addition to the background image. The height is needed |
|
346 so that the caption text area won't collapse to zero height since it won't contain |
|
347 any text. We're now ready to implement the createMainView() function: |
|
348 </p> |
|
349 |
|
350 <pre> |
|
351 |
|
352 // Creates the main view. |
|
353 function createMainView() { |
|
354 // empty caption text to display the caption bar - custom background using CSS |
|
355 mainView = new ListView(null, ""); |
|
356 |
|
357 // info |
|
358 var navToInfoButton = new NavigationButton(null, "NavInfoIcon.png", "Information"); |
|
359 navToInfoButton.addEventListener("ActionPerformed", showInfoView); |
|
360 mainView.addControl(navToInfoButton); |
|
361 |
|
362 // converter |
|
363 var navToConverterButton = new NavigationButton(null, "NavConverterIcon.png", "Currency Converter"); |
|
364 navToConverterButton.addEventListener("ActionPerformed", showConverterView); |
|
365 mainView.addControl(navToConverterButton); |
|
366 |
|
367 // weather |
|
368 var navToWeatherButton = new NavigationButton(null, "NavWeatherIcon.png", "Weather Forecast"); |
|
369 navToWeatherButton.addEventListener("ActionPerformed", showWeatherView); |
|
370 mainView.addControl(navToWeatherButton); |
|
371 |
|
372 // settings |
|
373 var navToSettingsButton = new NavigationButton(null, "NavSettingsIcon.png", "Settings"); |
|
374 navToSettingsButton.addEventListener("ActionPerformed", showSettingsView); |
|
375 mainView.addControl(navToSettingsButton); |
|
376 } |
|
377 </pre> |
|
378 |
|
379 <p> |
|
380 |
|
381 We now have a main view and our widget even calls showMainView() when it starts |
|
382 but nothing will actually show up yet because we haven't implemented the showMainView() |
|
383 function yet. Let's do that now: |
|
384 </p> |
|
385 |
|
386 <pre> |
|
387 |
|
388 // Displays the main view. |
|
389 function showMainView() { |
|
390 setMainViewSoftkeys(); |
|
391 uiManager.setView(mainView); |
|
392 } |
|
393 </pre> |
|
394 |
|
395 <p> |
|
396 |
|
397 The function calls the setMainViewSoftkeys() function to put the right softkey |
|
398 in the proper state and then asks the user interface manager to show the main |
|
399 view. Remember that we're already calling the showMainView() function from the |
|
400 init() function so we can go ahead and test this now in a PC browser, emulator |
|
401 or handset. Notice the custom list view caption image and the navigation button |
|
402 icons. Clicking the navigation buttons doesn't do anything yet because we don't |
|
403 have any other views yet and the functions to show other views except the main |
|
404 view aren't implemented. But then again, because we wrote stub functions we are |
|
405 also not getting any error messages. |
|
406 </p> |
|
407 |
|
408 <div class="fignone" id="GUID-989D17CC-F019-46BB-B6F5-49166E258ACA__GUID-B006B086-0D8B-4EA4-8A71-179507B7595A"><a name="GUID-989D17CC-F019-46BB-B6F5-49166E258ACA__GUID-B006B086-0D8B-4EA4-8A71-179507B7595A"><!-- --></a><span class="figcap">Figure 1. |
|
409 Travel Companion main view</span> |
|
410 |
|
411 |
|
412 <br /><img src="Travel_Companion_Main_Screenshot_1.png" /><br /> |
|
413 </div> |
|
414 |
|
415 </div> |
|
416 |
|
417 <div class="section"><h2 class="sectiontitle"> |
|
418 Settings view</h2> |
|
419 |
|
420 |
|
421 <p> |
|
422 |
|
423 It's a good idea to implement the settings view as early as possible because |
|
424 that allows you to test the rest of the widget more easily. In order to get |
|
425 the settings view up and running we'll need to do three things. First of all |
|
426 we'll need to implement the createSettingsView() function so that the widget |
|
427 actually has a settings view. Second, we'll need to implement the actions |
|
428 that can be performed in that view. There are two actions: "Save" and "Cancel". |
|
429 Of these, save is the tricker one and we'll implement it in a function that |
|
430 we will call saveSettingsClicked(). The cancel action will simply take us back |
|
431 to the main view and will be handled by the showMainView() function that we |
|
432 have already implemented. And third, we need to implement the showSettingsView() |
|
433 function so that clicking on the settings navigation button in the main view |
|
434 takes us to the settings view and sets it up correctly so that the view |
|
435 reflects the current preferences. |
|
436 </p> |
|
437 |
|
438 <p> |
|
439 |
|
440 The settings view will have four sections that we will separate using a WRTKit |
|
441 Separator control. The first section lets the user select the home city and the |
|
442 whether the home city is in daylight saving time. Here we'll use a SelectionMenu |
|
443 control for the city selection and a SelectionList control with a single option |
|
444 for the daylight saving time option. We could have used a SelectionList with |
|
445 two options "Daylight saving time" and "Normal time". Since the selection would |
|
446 have been a single selection this would have resulted in two radio buttons. But |
|
447 partly for the sake of usability and partly to show how to do it, we'll implement |
|
448 it so that it's a single checkbox instead. Thus, we'll use a SelectionList with |
|
449 a single option but we'll get the checkboxes instead of radio buttons by putting |
|
450 the SelectionList in multiple selection mode. Because there's only one option |
|
451 there will only be one checkbox. |
|
452 </p> |
|
453 |
|
454 <p> |
|
455 |
|
456 The second section is just like the first one but for the local city. The third |
|
457 section is for the temperature unit selection (Celsius or Fahrenheit) and we'll |
|
458 implement it as a single selection SelectionList control. And finally the fourth |
|
459 section is for the Save and Cancel FormButton controls. |
|
460 </p> |
|
461 |
|
462 <p> |
|
463 |
|
464 The options for the selection controls will be created just before we create |
|
465 the controls themselves. The daylight saving time and temperature unit options |
|
466 are just static JSON defined option lists since we know what the options are. |
|
467 But for the city selection we'll create it dynamically by asking the business |
|
468 logic engine for a list of all the supported cities. We'll then create one option |
|
469 for each city. |
|
470 </p> |
|
471 |
|
472 <p> |
|
473 |
|
474 Because we'll need to access the controls in the settings view from outside the |
|
475 creation function we'll need to create global references to them: |
|
476 </p> |
|
477 |
|
478 <pre> |
|
479 |
|
480 // Settings view controls. |
|
481 var homeCitySelection; |
|
482 var homeCityDSTSelection; |
|
483 var localCitySelection; |
|
484 var localCityDSTSelection; |
|
485 var temperatureUnitSelection; |
|
486 </pre> |
|
487 |
|
488 <p> |
|
489 |
|
490 We can now implement the settings view creation function: |
|
491 </p> |
|
492 |
|
493 <pre> |
|
494 |
|
495 // Creates the settings view. |
|
496 function createSettingsView() { |
|
497 // empty caption text to display the caption bar - custom background using CSS |
|
498 settingsView = new ListView(null, ""); |
|
499 |
|
500 // create city options from cities array |
|
501 var cityOptions = []; |
|
502 var cities = engine.getCities(); |
|
503 for (var i = 0; i < cities.length; i++) { |
|
504 cityOptions.push({ value: cities[i], text: cities[i].name }); |
|
505 } |
|
506 |
|
507 // create DST option |
|
508 dstOptions = [ { value: true, text: "DST (+1h)" } ]; |
|
509 |
|
510 // home city |
|
511 homeCitySelection = new SelectionMenu(null, "Home City", cityOptions); |
|
512 settingsView.addControl(homeCitySelection); |
|
513 |
|
514 // home city DST (using a multiple selection but only one option to get a single checkbox) |
|
515 homeCityDSTSelection = new SelectionList(null, "Daylight Saving Time (home)", dstOptions, true); |
|
516 settingsView.addControl(homeCityDSTSelection); |
|
517 |
|
518 // separator |
|
519 settingsView.addControl(new Separator()); |
|
520 |
|
521 // local city |
|
522 localCitySelection = new SelectionMenu(null, "Local City", cityOptions); |
|
523 settingsView.addControl(localCitySelection); |
|
524 |
|
525 // local city DST (using a multiple selection but only one option to get a single checkbox) |
|
526 localCityDSTSelection = new SelectionList(null, "Daylight Saving Time (local)", dstOptions, true); |
|
527 settingsView.addControl(localCityDSTSelection); |
|
528 |
|
529 // separator |
|
530 settingsView.addControl(new Separator()); |
|
531 |
|
532 // temperature unit |
|
533 var temperatureUnitOptions = [ { value: "c", text: "Celsius" }, { value: "f", text: "Fahrenheit" } ]; |
|
534 temperatureUnitSelection = new SelectionList(null, "Temperature Unit", temperatureUnitOptions); |
|
535 settingsView.addControl(temperatureUnitSelection); |
|
536 |
|
537 // separator |
|
538 settingsView.addControl(new Separator()); |
|
539 |
|
540 // save button |
|
541 var saveSettingsButton = new FormButton(null, "Save"); |
|
542 saveSettingsButton.addEventListener("ActionPerformed", saveSettingsClicked); |
|
543 settingsView.addControl(saveSettingsButton); |
|
544 |
|
545 // cancel button |
|
546 var cancelSettingsButton = new FormButton(null, "Cancel"); |
|
547 cancelSettingsButton.addEventListener("ActionPerformed", showMainView); |
|
548 settingsView.addControl(cancelSettingsButton); |
|
549 } |
|
550 </pre> |
|
551 |
|
552 <p> |
|
553 |
|
554 Note that we used the actual city as the value for the city options. You can |
|
555 use anything you want for the value property for a selection control option |
|
556 and in this case we used the actual city object because it will come in handy |
|
557 later when we want to set the home and local cities that the user has selected |
|
558 to the engine. |
|
559 </p> |
|
560 |
|
561 <p> |
|
562 |
|
563 Our save button calls the saveSettingsClicked() function we talked about earlier |
|
564 but we haven't created that function yet. We'll continue implementing the user |
|
565 interface by writing this function. |
|
566 </p> |
|
567 |
|
568 <p> |
|
569 |
|
570 You'll recall that the business logic engine actually stores all the preferences |
|
571 so all we really need to do is read what values have been selected in the settings |
|
572 view, telling these values to the engine, calling the savePreferences() method in |
|
573 the engine to persist the settings, and then return to the main view. |
|
574 </p> |
|
575 |
|
576 <pre> |
|
577 |
|
578 // Called when the user clicks on the "save" button in the settings view. |
|
579 function saveSettingsClicked() { |
|
580 // update the selected home city |
|
581 var selectedHomeCityOption = homeCitySelection.getSelected(); |
|
582 if (selectedHomeCityOption != null) { |
|
583 engine.setHomeCity(selectedHomeCityOption.value); |
|
584 } |
|
585 |
|
586 // update the selected local city |
|
587 var selectedLocalCityOption = localCitySelection.getSelected(); |
|
588 if (selectedLocalCityOption != null) { |
|
589 engine.setLocalCity(selectedLocalCityOption.value); |
|
590 } |
|
591 |
|
592 // update home and local city DST |
|
593 // there's only one checkbox but we are using a multiple-selection menu. |
|
594 // if the selected array has one element then the checkbox is checked. |
|
595 engine.setHomeCityDST(homeCityDSTSelection.getSelected().length == 1); |
|
596 engine.setLocalCityDST(localCityDSTSelection.getSelected().length == 1); |
|
597 |
|
598 // update temperature unit |
|
599 var selectedTemperatureUnitOption = temperatureUnitSelection.getSelected(); |
|
600 if (selectedTemperatureUnitOption != null) { |
|
601 engine.setTemperatureUnit(selectedTemperatureUnitOption.value); |
|
602 } |
|
603 |
|
604 // save settings |
|
605 engine.savePreferences(); |
|
606 |
|
607 // go back to the main view |
|
608 showMainView(); |
|
609 } |
|
610 </pre> |
|
611 |
|
612 <p> |
|
613 |
|
614 We're writing defensive code here and making sure that the selection controls |
|
615 actually have anything selected at all. This should never be possible with |
|
616 single selection control if they have one option already selected, but we'll |
|
617 use the principle of "better safe than sorry". |
|
618 </p> |
|
619 |
|
620 <p> |
|
621 |
|
622 Notice that the daylight saving time selection is checked by asking for the |
|
623 selected options array (we're using a multiple selection control) and checking |
|
624 if there is exactly one selected option. We don't care about the actual selected |
|
625 option because we know that there's only one. Either it's selected or it's not. |
|
626 </p> |
|
627 |
|
628 <p> |
|
629 |
|
630 We have now implemented two of the three steps we said were necessary to get the |
|
631 settings view fully functional. Let's implement the final step: showing the view. |
|
632 Showing the settings view is done by first updating the settings view controls |
|
633 to reflect the current configuration, setting the right softkey to the state that |
|
634 it should be in for the settings view and then asking the user interface manager |
|
635 to show the settings view. |
|
636 </p> |
|
637 |
|
638 <pre> |
|
639 |
|
640 // Displays the settings view. |
|
641 function showSettingsView() { |
|
642 // update settings view controls to match current configuration |
|
643 // the DST selected sets are either the options array with its single option or an empty array |
|
644 |
|
645 // home city and DST setting |
|
646 homeCitySelection.setSelected(homeCitySelection.getOptionForValue(engine.getHomeCity())); |
|
647 homeCityDSTSelection.setSelected(engine.getHomeCityDST() ? homeCityDSTSelection.getOptions() : []); |
|
648 |
|
649 // local city and DST setting |
|
650 localCitySelection.setSelected(localCitySelection.getOptionForValue(engine.getLocalCity())); |
|
651 localCityDSTSelection.setSelected(engine.getLocalCityDST() ? localCityDSTSelection.getOptions() : []); |
|
652 |
|
653 // temperature unit |
|
654 temperatureUnitSelection.setSelected(temperatureUnitSelection.getOptionForValue(engine.getTemperatureUnit())); |
|
655 |
|
656 setSettingsViewSoftkeys(); |
|
657 uiManager.setView(settingsView); |
|
658 } |
|
659 </pre> |
|
660 |
|
661 <p> |
|
662 |
|
663 We're using the convenient getOptionForValue() function that all selection controls |
|
664 have to retrieve the right option to select for each of the selection controls. The |
|
665 way we handle the daylight saving time selection controls may seem a little strange |
|
666 at first but remember that we only have a single option and thus if that option should |
|
667 be selected then the selected options array is identical with the options array - both |
|
668 are arrays containing the one and same option. Selection controls always copy the options |
|
669 and selected options arrays when the setOptions() and setSelected() methods are called |
|
670 so there is no problem in passing the options array as the selected options array. |
|
671 </p> |
|
672 |
|
673 <p> |
|
674 |
|
675 The settings view is now completed. You can try it out and play with it, change the |
|
676 settings, open it up again, change some more settings, cancel the changes, etc. to |
|
677 verify that it's working as it should. |
|
678 </p> |
|
679 |
|
680 <div class="fignone" id="GUID-989D17CC-F019-46BB-B6F5-49166E258ACA__GUID-66154A40-DD96-45B3-BF53-01594426BA71"><a name="GUID-989D17CC-F019-46BB-B6F5-49166E258ACA__GUID-66154A40-DD96-45B3-BF53-01594426BA71"><!-- --></a><span class="figcap">Figure 2. |
|
681 Travel Companion settings view</span> |
|
682 |
|
683 |
|
684 <br /><img src="Travel_Companion_Settings_Screenshot_1.png" /><br /> |
|
685 </div> |
|
686 |
|
687 </div> |
|
688 |
|
689 </div> |
|
690 |
|
691 <div> |
|
692 <div class="familylinks"> |
|
693 <div class="parentlink"><strong>Parent topic:</strong> <a href="WRTKit_Travel_Companion_Tutorial-GUID-be79ba64-fa03-4968-964e-d7dcc42d7053.html">Travel Companion</a></div> |
|
694 </div> |
|
695 </div> |
|
696 |
|
697 </body> |
|
698 </html> |
|