org.symbian.wrttools.doc.WRTKit/html/WRTKit_Travel_Companion_user_interface-GUID-989d17cc-f019-46bb-b6f5-49166e258aca.html
changeset 230 7848c135d915
parent 229 716254ccbcc0
child 231 611be8d22832
--- a/org.symbian.wrttools.doc.WRTKit/html/WRTKit_Travel_Companion_user_interface-GUID-989d17cc-f019-46bb-b6f5-49166e258aca.html	Fri Mar 05 19:11:15 2010 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,698 +0,0 @@
-<?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">
-<html lang="en" xml:lang="en">
-<head>
-<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
-<meta name="copyright" content="(C) Copyright 2005" />
-<meta name="DC.rights.owner" content="(C) Copyright 2005" />
-<meta content="concept" name="DC.Type" />
-<meta name="DC.Title" content="Travel Companion user interface" />
-<meta scheme="URI" name="DC.Relation" content="WRTKit_Travel_Companion_Tutorial-GUID-be79ba64-fa03-4968-964e-d7dcc42d7053.html" />
-<meta content="XHTML" name="DC.Format" />
-<meta content="GUID-989D17CC-F019-46BB-B6F5-49166E258ACA" name="DC.Identifier" />
-<meta content="en" name="DC.Language" />
-<link href="commonltr.css" type="text/css" rel="stylesheet" />
-<title>
-Travel Companion user interface</title>
-</head>
-<body id="GUID-989D17CC-F019-46BB-B6F5-49166E258ACA"><a name="GUID-989D17CC-F019-46BB-B6F5-49166E258ACA"><!-- --></a>
-
-
-
-    <h1 class="topictitle1">
-Travel Companion user interface</h1>
-
-    <div>
-
-        <div class="section"><h2 class="sectiontitle">
-Handling multiple views</h2>
-
-            
-            <p>
-
-                The Travel Companion widget will follow many of the same patterns that the Hello World
-                and RSS Reader widgets have followed. The entry point to the widget is the init() function
-                that we call from the onload event handler in the main HTML file TravelCompanion.html.
-                We will implement the init() function along with the rest of the widget and user interface
-                in the TravelCompanion.js file. Let's start with the init() function so that we get the
-                widget up and running.
-            </p>
-
-            <p>
-
-                From previous widgets we already know a lot of things about the WRTKit and about what
-                we will need. For example we know that we will have a user interface manager and that
-                we'll need a reference to each of the views that our widget uses. And since we have
-                designed the Travel Companion widget we know what views we will have. Before we write the
-                init() function we can go ahead and declare the variables that we will use to refer to
-                the views and the user interface manager. And while we're at it we can also declare the
-                variable that we'll use to refer to the Travel Companion engine. All of these variables
-                are globals and thus go outside the init() function:
-            </p>
-
-<pre>
-
-// Reference to travel companion engine that implements the business logic.
-var engine;
-
-// Reference to the WRTKit user interface manager.
-var uiManager;
-
-// References to views.
-var mainView;
-var infoView;
-var converterView;
-var weatherView;
-var settingsView;
-</pre>
-
-            <p>
-
-                Previously we've written the init() function so that it creates the entire user interface
-                but because the Travel Companion widget has a much larger user interface than anything
-                we've done before, it's probably a good idea to split things up into smaller functions
-                so we don't end up with a huge init() function that will be hard to read and maintain.
-                Let's create a function for the creation of each view, and then one function that will
-                call these view creation functions and setup all other things that we need for the user
-                interface, such as the Options menu. We'll just create stub functions for now but we
-                will soon get to implement the functions:
-            </p>
-
-<pre>
-
-// Creates the user interface.
-function createUI() {
-}
-
-// Creates the main view.
-function createMainView() {
-}
-
-// Creates the info view.
-function createInfoView() {
-}
-
-// Creates the converter view.
-function createConverterView() {
-}
-
-// Creates the weather view.
-function createWeatherView() {
-}
-
-// Creates the settings view.
-function createSettingsView() {
-}
-</pre>
-
-            <p>
-
-                In the RSS Reader widget we used functions called showMainView() and showSettings() to
-                move between views. That allowed us to implement all the logic that was required when
-                moving between views in one place regardless of what action triggered the change of
-                views. We'll do the same thing in the Travel Companion widget but this time we'll need
-                five functions since we have five views. Let's create stubs for these too at this stage
-                so that the functions exist if we need to refer to them.
-            </p>
-
-<pre>
-
-// Displays the main view.
-function showMainView() {
-}
-
-// Displays the info view.
-function showInfoView() {
-}
-
-// Displays the converter view.
-function showConverterView() {
-}
-
-// Displays the weather view.
-function showWeatherView() {
-}
-
-// Displays the settings view.
-function showSettingsView() {
-}
-</pre>
-
-            <p>
-
-                Since we will create each user interface view in its own function our init() function
-                will be much simpler than in previous widgets. We will create the business logic engine,
-                create the user interface by calling createUI() and then display the main view.
-            </p>
-
-<pre>
-
-// Called from the onload event handler to initialize the widget.
-function init() {
-    // initialize the business logic engine
-    engine = new Engine();
-    
-    // create the user interface
-    createUI();
-    
-    // display the main view
-    showMainView();
-}
-</pre>
-
-            <p>
-
-                Let's get started with creating the user interface by returning to the createUI()
-                function. We'll want to widget to show the softkey bar and we'll want it to be in
-                tab navigation mode instead of the default pointer navigation mode. We then need
-                to create the user interface manager and the five views that this widget has. Of 
-                course those five views are actually created by the five create-functions that we
-                just wrote stubs for so we just need to call those functions from createUI().
-            </p>
-
-<pre>
-
-// Creates the user interface.
-function createUI() {
-    if (window.widget) {
-        // set tab-navigation mode and show softkeys
-        widget.setNavigationEnabled(false);
-        menu.showSoftkeys();
-    }
-    
-    // create UI manager
-    uiManager = new UIManager();
-    
-    // create views
-    createMainView();
-    createInfoView();
-    createConverterView();
-    createWeatherView();
-    createSettingsView();
-}
-</pre>
-
-            <p>
-
-                Because we created the stub functions for moving between views, we can also create
-                the Options menu now. We'll only add one item to the menu in addition to the default
-                "Exit" menu item. The item we'll add is one that will take the user to the settings
-                view. We'll first need to create a global menu item identifier:
-            </p>
-
-<pre>
-
-// Constants for menu item identifiers.
-var MENU_ITEM_SETTINGS = 0;
-</pre>
-
-            <p>
-
-                Now that we have the menu item identifier we can actually create the menu item. Because
-                the Options menu functionality is only available in the S60 Web Runtime and not in PC
-                browsers we'll add that code in the same if-clause where we set the navigation mode and
-                show the softkey bar.
-            </p>
-
-<pre>
-
-// create menu
-var settingsMenuItem = new MenuItem("Settings", MENU_ITEM_SETTINGS);
-settingsMenuItem.onSelect = menuItemSelected;
-menu.append(settingsMenuItem);
-</pre>
-
-            <p>
-
-                When the menu item is selected it calls a function called menuItemSelected(). Let's
-                create that function and handle the case when the settings menu item is selected.
-                When it is, we want to call showSettingsView() so that the user ends up in the settings
-                view as expected:
-            </p>
-
-<pre>
-
-// Callback for when menu items are selected.
-function menuItemSelected(id) {
-    switch (id) {
-        case MENU_ITEM_SETTINGS:
-            showSettingsView();
-            break;
-    }
-}
-</pre>
-
-            <p>
-
-                The framework that we'll need when implementing the actual views is now nearly complete.
-                But before we move on let's talk about how we'll be using softkeys in the Travel
-                Companion widget.
-            </p>
-
-            <p>
-
-                In the main view we want the right softkey to be the default "Exit". But in the
-                four functional views we don't want it to exit the widget but rather to return to
-                the main view. We'll thus use "Back" as the title in the functional views, except
-                in the settings view where we'll use "Cancel".
-            </p>
-
-            <p>
-
-                Let's create three functions that will handle setting the widget right softkey to
-                these configurations. The functions will check if we're actually in the S60 Web
-                Runtime before attempting to change the right softkey in order to make the widget
-                also work in a PC browser for testing purposes.
-            </p>
-
-<pre>
-
-// Sets the softkeys for the main view.
-function setMainViewSoftkeys() {
-    if (window.widget) {
-        // set right softkey to "exit"
-        menu.setRightSoftkeyLabel("", null);
-    }
-}
-
-// Sets the softkeys for sub views.
-function setSubViewSoftkeys() {
-    if (window.widget) {
-        // set right softkey to "back" (to main view)
-        menu.setRightSoftkeyLabel("Back", showMainView);
-    }
-}
-
-// Sets the softkeys for settings view.
-function setSettingsViewSoftkeys() {
-    if (window.widget) {
-        // set right softkey to "cancel" (returns to main view)
-        menu.setRightSoftkeyLabel("Cancel", showMainView);
-    }
-}
-</pre>
-
-        </div>
-
-        <div class="section"><h2 class="sectiontitle">
-Main view</h2>
-
-            
-            <p>
-
-                Let's create our main view now so that we get something visible. The main view is
-                of course created in the function createMainView() for which we already created a
-                stub function. The main view will have four WRTKit NavigationButton controls in it,
-                one for each of the views (not counting the main view itself) in the widget. Using
-                the NavigationButton control is just like using a FormButton, with the difference
-                that it looks different and can have an icon image in addition to just text. Earlier
-                when we looked at the files that were in the Examples/TravelCompanion directory we
-                noticed that there were four icons there. Now it's time to use them as icons in the
-                navigation buttons.
-            </p>
-
-            <p>
-
-                We will add event listerners to the buttons so that when they are clicked (when they
-                emit an ActionPerformed event) they will call the functions we have created for
-                moving between views. At this point the functions are just stubs, but we will of
-                course fix that later.
-            </p>
-
-            <p>
-
-                We've had captions for the views that we've created so far in the Hello World and
-                RSS Reader widgets and the Travel Companion will also have view captions. However
-                for the Travel Companion we'll use an image as our view caption. We will set the
-                view caption to an empty string because if it's undefined or null then the view
-                caption area will be hidden. Then we will create a CSS rule for the ListViewCaptionText
-                class that is used by the area where the caption text goes in a list view. Because
-                our CSS rule is defined after the default WRTKit CSS rule for ListViewCaptionText,
-                our rule will be override the default one. Let's open up TravelCompanion.css and
-                create this rule:
-            </p>
-
-<pre>
-
-/* Place logo in list view caption */
-.ListViewCaptionText {
-    background: url("ListViewCaptionLogo.png") no-repeat;
-    height: 35px;
-}
-</pre>
-
-            <p>
-
-                We specified a height in addition to the background image. The height is needed
-                so that the caption text area won't collapse to zero height since it won't contain
-                any text. We're now ready to implement the createMainView() function:
-            </p>
-
-<pre>
-
-// Creates the main view.
-function createMainView() {
-    // empty caption text to display the caption bar - custom background using CSS
-    mainView = new ListView(null, "");
-    
-    // info
-    var navToInfoButton = new NavigationButton(null, "NavInfoIcon.png", "Information");
-    navToInfoButton.addEventListener("ActionPerformed", showInfoView);
-    mainView.addControl(navToInfoButton);
-    
-    // converter
-    var navToConverterButton = new NavigationButton(null, "NavConverterIcon.png", "Currency Converter");
-    navToConverterButton.addEventListener("ActionPerformed", showConverterView);
-    mainView.addControl(navToConverterButton);
-    
-    // weather
-    var navToWeatherButton = new NavigationButton(null, "NavWeatherIcon.png", "Weather Forecast");
-    navToWeatherButton.addEventListener("ActionPerformed", showWeatherView);
-    mainView.addControl(navToWeatherButton);
-    
-    // settings
-    var navToSettingsButton = new NavigationButton(null, "NavSettingsIcon.png", "Settings");
-    navToSettingsButton.addEventListener("ActionPerformed", showSettingsView);
-    mainView.addControl(navToSettingsButton);
-}
-</pre>
-
-            <p>
-
-                We now have a main view and our widget even calls showMainView() when it starts
-                but nothing will actually show up yet because we haven't implemented the showMainView()
-                function yet. Let's do that now:
-            </p>
-
-<pre>
-
-// Displays the main view.
-function showMainView() {
-    setMainViewSoftkeys();
-    uiManager.setView(mainView);
-}
-</pre>
-
-            <p>
-
-                The function calls the setMainViewSoftkeys() function to put the right softkey
-                in the proper state and then asks the user interface manager to show the main
-                view. Remember that we're already calling the showMainView() function from the
-                init() function so we can go ahead and test this now in a PC browser, emulator
-                or handset. Notice the custom list view caption image and the navigation button
-                icons. Clicking the navigation buttons doesn't do anything yet because we don't
-                have any other views yet and the functions to show other views except the main
-                view aren't implemented. But then again, because we wrote stub functions we are
-                also not getting any error messages.
-            </p>
-
-            <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. 
-Travel Companion main view</span>
-
-                
-                <br /><img src="Travel_Companion_Main_Screenshot_1.png" /><br />
-            </div>
-
-        </div>
-
-        <div class="section"><h2 class="sectiontitle">
-Settings view</h2>
-
-            
-            <p>
-
-                It's a good idea to implement the settings view as early as possible because
-                that allows you to test the rest of the widget more easily. In order to get
-                the settings view up and running we'll need to do three things. First of all
-                we'll need to implement the createSettingsView() function so that the widget
-                actually has a settings view. Second, we'll need to implement the actions
-                that can be performed in that view. There are two actions: "Save" and "Cancel".
-                Of these, save is the tricker one and we'll implement it in a function that
-                we will call saveSettingsClicked(). The cancel action will simply take us back
-                to the main view and will be handled by the showMainView() function that we
-                have already implemented. And third, we need to implement the showSettingsView()
-                function so that clicking on the settings navigation button in the main view
-                takes us to the settings view and sets it up correctly so that the view
-                reflects the current preferences.
-            </p>
-
-            <p>
-
-                The settings view will have four sections that we will separate using a WRTKit
-                Separator control. The first section lets the user select the home city and the
-                whether the home city is in daylight saving time. Here we'll use a SelectionMenu
-                control for the city selection and a SelectionList control with a single option
-                for the daylight saving time option. We could have used a SelectionList with
-                two options "Daylight saving time" and "Normal time". Since the selection would
-                have been a single selection this would have resulted in two radio buttons. But
-                partly for the sake of usability and partly to show how to do it, we'll implement
-                it so that it's a single checkbox instead. Thus, we'll use a SelectionList with
-                a single option but we'll get the checkboxes instead of radio buttons by putting
-                the SelectionList in multiple selection mode. Because there's only one option
-                there will only be one checkbox.
-            </p>
-
-            <p>
-
-                The second section is just like the first one but for the local city. The third
-                section is for the temperature unit selection (Celsius or Fahrenheit) and we'll
-                implement it as a single selection SelectionList control. And finally the fourth
-                section is for the Save and Cancel FormButton controls.
-            </p>
-
-            <p>
-
-                The options for the selection controls will be created just before we create
-                the controls themselves. The daylight saving time and temperature unit options
-                are just static JSON defined option lists since we know what the options are.
-                But for the city selection we'll create it dynamically by asking the business
-                logic engine for a list of all the supported cities. We'll then create one option
-                for each city.
-            </p>
-
-            <p>
-
-                Because we'll need to access the controls in the settings view from outside the
-                creation function we'll need to create global references to them:
-            </p>
-
-<pre>
-
-// Settings view controls.
-var homeCitySelection;
-var homeCityDSTSelection;
-var localCitySelection;
-var localCityDSTSelection;
-var temperatureUnitSelection;
-</pre>
-
-            <p>
-
-                We can now implement the settings view creation function:
-            </p>
-
-<pre>
-
-// Creates the settings view.
-function createSettingsView() {
-    // empty caption text to display the caption bar - custom background using CSS
-    settingsView = new ListView(null, "");
-    
-    // create city options from cities array
-    var cityOptions = [];
-    var cities = engine.getCities();
-    for (var i = 0; i &lt; cities.length; i++) {
-        cityOptions.push({ value: cities[i], text: cities[i].name });
-    }
-    
-    // create DST option
-    dstOptions = [ { value: true, text: "DST (+1h)" } ];
-    
-    // home city
-    homeCitySelection = new SelectionMenu(null, "Home City", cityOptions);
-    settingsView.addControl(homeCitySelection);
-    
-    // home city DST (using a multiple selection but only one option to get a single checkbox)
-    homeCityDSTSelection = new SelectionList(null, "Daylight Saving Time (home)", dstOptions, true);
-    settingsView.addControl(homeCityDSTSelection);
-    
-    // separator
-    settingsView.addControl(new Separator());
-    
-    // local city
-    localCitySelection = new SelectionMenu(null, "Local City", cityOptions);
-    settingsView.addControl(localCitySelection);
-    
-    // local city DST (using a multiple selection but only one option to get a single checkbox)
-    localCityDSTSelection = new SelectionList(null, "Daylight Saving Time (local)", dstOptions, true);
-    settingsView.addControl(localCityDSTSelection);
-    
-    // separator
-    settingsView.addControl(new Separator());
-    
-    // temperature unit
-    var temperatureUnitOptions = [ { value: "c", text: "Celsius" }, { value: "f", text: "Fahrenheit" } ];
-    temperatureUnitSelection = new SelectionList(null, "Temperature Unit", temperatureUnitOptions);
-    settingsView.addControl(temperatureUnitSelection);
-    
-    // separator
-    settingsView.addControl(new Separator());
-    
-    // save button
-    var saveSettingsButton = new FormButton(null, "Save");
-    saveSettingsButton.addEventListener("ActionPerformed", saveSettingsClicked);
-    settingsView.addControl(saveSettingsButton);
-    
-    // cancel button
-    var cancelSettingsButton = new FormButton(null, "Cancel");
-    cancelSettingsButton.addEventListener("ActionPerformed", showMainView);
-    settingsView.addControl(cancelSettingsButton);
-}
-</pre>
-
-            <p>
-
-                Note that we used the actual city as the value for the city options. You can
-                use anything you want for the value property for a selection control option
-                and in this case we used the actual city object because it will come in handy
-                later when we want to set the home and local cities that the user has selected
-                to the engine.
-            </p>
-
-            <p>
-
-                Our save button calls the saveSettingsClicked() function we talked about earlier
-                but we haven't created that function yet. We'll continue implementing the user
-                interface by writing this function.
-            </p>
-
-            <p>
-
-                You'll recall that the business logic engine actually stores all the preferences
-                so all we really need to do is read what values have been selected in the settings
-                view, telling these values to the engine, calling the savePreferences() method in
-                the engine to persist the settings, and then return to the main view.
-            </p>
-
-<pre>
-
-// Called when the user clicks on the "save" button in the settings view.
-function saveSettingsClicked() {
-    // update the selected home city
-    var selectedHomeCityOption = homeCitySelection.getSelected();
-    if (selectedHomeCityOption != null) {
-        engine.setHomeCity(selectedHomeCityOption.value);
-    }
-    
-    // update the selected local city
-    var selectedLocalCityOption = localCitySelection.getSelected();
-    if (selectedLocalCityOption != null) {
-        engine.setLocalCity(selectedLocalCityOption.value);
-    }
-    
-    // update home and local city DST
-    // there's only one checkbox but we are using a multiple-selection menu.
-    // if the selected array has one element then the checkbox is checked.
-    engine.setHomeCityDST(homeCityDSTSelection.getSelected().length == 1);
-    engine.setLocalCityDST(localCityDSTSelection.getSelected().length == 1);
-    
-    // update temperature unit
-    var selectedTemperatureUnitOption = temperatureUnitSelection.getSelected();
-    if (selectedTemperatureUnitOption != null) {
-        engine.setTemperatureUnit(selectedTemperatureUnitOption.value);
-    }
-    
-    // save settings
-    engine.savePreferences();
-    
-    // go back to the main view
-    showMainView();
-}
-</pre>
-
-            <p>
-
-                We're writing defensive code here and making sure that the selection controls
-                actually have anything selected at all. This should never be possible with
-                single selection control if they have one option already selected, but we'll
-                use the principle of "better safe than sorry".
-            </p>
-
-            <p>
-
-                Notice that the daylight saving time selection is checked by asking for the
-                selected options array (we're using a multiple selection control) and checking
-                if there is exactly one selected option. We don't care about the actual selected
-                option because we know that there's only one. Either it's selected or it's not.
-            </p>
-
-            <p>
-
-                We have now implemented two of the three steps we said were necessary to get the
-                settings view fully functional. Let's implement the final step: showing the view.
-                Showing the settings view is done by first updating the settings view controls
-                to reflect the current configuration, setting the right softkey to the state that
-                it should be in for the settings view and then asking the user interface manager
-                to show the settings view.
-            </p>
-
-<pre>
-
-// Displays the settings view.
-function showSettingsView() {
-    // update settings view controls to match current configuration
-    // the DST selected sets are either the options array with its single option or an empty array
-    
-    // home city and DST setting
-    homeCitySelection.setSelected(homeCitySelection.getOptionForValue(engine.getHomeCity()));
-    homeCityDSTSelection.setSelected(engine.getHomeCityDST() ? homeCityDSTSelection.getOptions() : []);
-    
-    // local city and DST setting
-    localCitySelection.setSelected(localCitySelection.getOptionForValue(engine.getLocalCity()));
-    localCityDSTSelection.setSelected(engine.getLocalCityDST() ? localCityDSTSelection.getOptions() : []);
-    
-    // temperature unit
-    temperatureUnitSelection.setSelected(temperatureUnitSelection.getOptionForValue(engine.getTemperatureUnit()));
-    
-    setSettingsViewSoftkeys();
-    uiManager.setView(settingsView);
-}
-</pre>
-
-            <p>
-
-                We're using the convenient getOptionForValue() function that all selection controls
-                have to retrieve the right option to select for each of the selection controls. The
-                way we handle the daylight saving time selection controls may seem a little strange
-                at first but remember that we only have a single option and thus if that option should
-                be selected then the selected options array is identical with the options array - both
-                are arrays containing the one and same option. Selection controls always copy the options
-                and selected options arrays when the setOptions() and setSelected() methods are called
-                so there is no problem in passing the options array as the selected options array.
-            </p>
-
-            <p>
-
-                The settings view is now completed. You can try it out and play with it, change the
-                settings, open it up again, change some more settings, cancel the changes, etc. to
-                verify that it's working as it should.
-            </p>
-
-            <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. 
-Travel Companion settings view</span>
-
-                
-                <br /><img src="Travel_Companion_Settings_Screenshot_1.png" /><br />
-            </div>
-
-        </div>
-
-    </div>
-
-<div>
-<div class="familylinks">
-<div class="parentlink"><strong>Parent topic:</strong> <a href="WRTKit_Travel_Companion_Tutorial-GUID-be79ba64-fa03-4968-964e-d7dcc42d7053.html">Travel Companion</a></div>
-</div>
-</div>
-
-</body>
-</html>
\ No newline at end of file