Some Important Processing
List of Products and the Factory Function
A list of products is declared as the following:
SFXArray<AWSProductPtr> _productarray;
_productarray is an array of pointers to objects of AWSProduct class. In fact, what we need is an array of objects such as Book or DVD. This is done by making AWSProduct an abstract class and Book and DVD are its derived classess.
In the application, we add the pointers to Book objects or to DVD objects to the _productarray as follows.
// item is pointer to AWSProduct abtract class AWSProductPtr item; // assign a pointer to Book object or DVD object to item item = AWSProduct::Factory(producttype); // then add the item to the array _productarray.Append(item);
Below are the declaration and implementation of the Factory function. They are straightforward.
// declaration of the factory function static AWSProductPtr Factory(SFXAnsiString producttype);
// implementation of the factory function AWSProductPtr AWSProduct::Factory(SFXAnsiString producttype) { if(producttype == BOOK_SEARCH) return ::new AWSBook(); if(producttype == DVD_SEARCH) return ::new AWSDvd(); return null; }
Suspend and Resume
Suspend
BREW is a single thread environment, when other applications (such as an incomming call) boot up, the current running application will be suspended.
If there is an opened socket and we are getting data, we must close the socket and free the received buffer when we are sent a suspend message. In the application with REST API, the OnSuspend handler is registered to the "Connecting..." dialog and is implemented as shown in the source code below.
HANDLER_IMPLEMENT_VOIDSUSPEND(SGRNetworkDialogSet, OnSuspend, reason, info) { unused(reason); unused(info); if (IsConnecting()) { _http.Close(); ClearData(); } return; }
Similarly, if there is a running timer, the timer must be cancelled before suspending. In the application, a timer is running when the list of products window opens. The OnSuspend handler is registered to the SGRListboxControl class and is implemented as follows.
HANDLER_IMPLEMENT_VOIDSUSPEND(SGRListboxControl, OnSuspend, reason, info) { unused(reason); unused(info); StopTimer(); // stop timer return; }
Resume
When the application resumes, we reopen the socket and continue getting data. In the application with REST API, the OnResume handler is registered to the "Connecting..." dialog and is implemented as shown in the source code below.
HANDLER_IMPLEMENT_VOIDRESUME(SGRNetworkDialogSet, OnResume, environment) { unused(environment); if (IsConnecting()) { DBGPRINTF("Network start again..."); Connect(); } return; }
The timer which was canceled when being suspended needs to be restarted.
HANDLER_IMPLEMENT_VOIDRESUME(SGRListboxControl, OnResume, environment) { unused(environment); StartTimer(); return; }
Search Input Window Event Handlers
1. The OnKey Event Handler
The OnKey event handler handles the "Left" (AVK_LEFT), "Right" (AVK_RIGHT), "Up" (AVK_UP), and "Down" (AVK_DOWN) directional keys.
If the "Left" or the "Right" key is pressed, the left pane or the right pane of the current pane will be selected regardless of what the focused component is. The source code for handling "Left" key and "Righ" key is shown below.
SearchPanePtr tmp; case AVK_LEFT: tmp= static_cast<SearchPanePtr>(GetLeft(TYPE_WILDCARD,ATTRIBUTE_SFRTABPANE)); if (tmp) tmp->Select(); ret = true; break; case AVK_RIGHT: tmp= static_cast<SearchPanePtr>(GetRight(TYPE_WILDCARD,ATTRIBUTE_SFRTABPANE)); if (tmp) tmp->Select(); ret = true; break;
If the "Up" or the "Down" key is pressed, the focus will be moved up or down. However, there is a slight difference between the handling of the "Up" key and the "Down" key as shown in the source code below.
SFRResponderPtr responder(null); case AVK_UP: if (GetFocus()) responder = GetFocus()->GetPrevious(TYPE_WILDCARD, ATTRIBUTE_WILDCARD, STATUS_VISIBLE | STATUS_ENABLE, false); if (responder) { FocusPrevious(); ret = true; } break; case AVK_DOWN: FocusDown(); ret= true; break;
For the "Up" key, the focus should be moved to the tab pane if the current focused component is the top one (the combo box).
When moving by the directional key, the label of the third softkey also change accordingly. This is shown in the source code below.
// change the label of the third soft key accoding to the selected component SGRSoftkeyWindowPtr softkey; if (event.GetP16() == AVK_LEFT || event.GetP16() == AVK_RIGHT) { if ((softkey = SGRSoftkeyWindow::GetInstance()) != null) { static_throw(softkey->Register(this, SGRSoftkeyWindow::SOFTKEY_3, "Select")); if (static_try()) SetReference(softkey->Bind(this)); } } else if (event.GetP16() == AVK_UP || event.GetP16() == AVK_DOWN) { if ((softkey = SGRSoftkeyWindow::GetInstance()) != null) { SFRResponderPtr responder; if ((responder = GetFocus()) != null) { // if the combo box is selected if (responder->GetAttribute() == ATTRIBUTE_SFRCOMBOBOXCONTROL) softkey->Register(this, SGRSoftkeyWindow::SOFTKEY_3, "Select"); // if the edit box is selected else if (responder->GetAttribute() == ATTRIBUTE_SFREDITBOXCONTROL) softkey->Register(this, SGRSoftkeyWindow::SOFTKEY_3, "Input"); // if the button is selected else if (responder->GetAttribute() == ATTRIBUTE_SFRBUTTONCONTROL) softkey->Register(this, SGRSoftkeyWindow::SOFTKEY_3, "Search"); } SetReference(softkey->Bind(this)); } }
2. The OnSoftKey Event Handler
If the "soft key 1" is pressed, the application is terminated. If the "soft key 2" is pressed, a window of favorite products is displayed. If the "soft key 3" is pressed, the default handling assigned to the focused component is called. Therefore, in the following source code, only "soft key 1" and "soft key 2" need to be handled.
// softkey handler HANDLER_IMPLEMENT_VOIDEVENT(SearchPane, OnSoftkey, event) { switch (event.GetP16()) { case SGRSoftkeyWindow::SOFTKEY_1: // terminate application SFRApplication::Terminate(); break; case SGRSoftkeyWindow::SOFTKEY_2: // display list of favorite products SFXAnsiString filename; SFCError error; /* load the favorite product and display the favorite window */ break; } return; }
3. The OnButtonControl Event Handler
HANDLER_IMPLEMENT_VOIDCONTROL(SearchPane, OnButtonControl, result, control) { SFRMultiDialog::ParamRec param; SFXWideString utf16str; SFXAnsiString _browsenode; SFXAnsiString _string, _keyword; // get browsenodes SInt16 ind = _combobox->GetValue(); _browsenode = BrowseNodesValue[ind]; _string = _textcontrol->GetText().Trim(); // trim spaces _string = _string.TrimRight("\r").TrimRight("\n"); // trim cariage return and linefeed // Convert to UTF8 SFXTextEncoding::ShiftJISToUTF16LE(_string, &utf16str); SFXTextEncoding::UTF16LEToUTF8(utf16str, &_keyword); // if no brosenode is selected, keyword must be supplied if(_keyword.IsEmptyCString() && _browsenode =="All") _errorDialog.Open("Keyword Error", "Please input keyword", DIALOG_OK, this); // connect to AWS to get information using REST request else _networkDialog.Open(AWSProduct::GetUrlForKeyWordSearch(_searchindex, _browsenode, _keyword), true, OnNetworkEntry, this, "Confirm", "Connect to the Internet?", "Yes", "No" ); }
Favorite Facility
A product can be saved so that the user can view this product later without the need to connect to the internet again.
Saved products are called favorites.
Favorite data are kept in "data" folder. For each favorite, there is a corresponding XML file that keep the product information, and an entry in a ".dat" file that holds the filename and title of all products of same type.
In the application the favorite window and the list of product window share the same class as shown below.
class ListProductsWindow : public SFRPlainWindow { SFMSEALCOPY(ListProductsWindow) private: // 0: search result, 1: favorite list SInt16 _windowtype; // product type such as Books or DVD SFXAnsiString _searchindex; // List of products AWSListProductsPtr _products; // List control to display produc SGRListboxControlPtr _list; ... }
The ListProductsWindow class displays the products in the _products variable in a SGRListboxControl list box.
The only difference between the favorite window and the list of product window is the handling of the sofkey window. In case of the favorite window, if the "soft key 2" is pressed, a menu for managing the favorite list will be displayed.
softkey->Register(this, SGRSoftkeyWindow::SOFTKEY_1, "End"); softkey->Register(this, SGRSoftkeyWindow::SOFTKEY_2, (_windowtype == 0)? "Back" : "Menu"); softkey->Register(this, SGRSoftkeyWindow::SOFTKEY_3, "Detail");
The source code below shows how to create the menu (error handling is obmitted).
SFRTextMenuPtr menu; // create menu menu = ::new SFRTextMenu(SGRSoftkeyToolbox::GetMenuPosition(OPERATION_LIMIT), "Menu", null, 0) ; menu->AppendItem("Delete", AVK_1, 0xFBF6); menu->AppendItem("Delete All", AVK_2, 0xFCF6); menu->AppendItem("Back", AVK_3, 0x40F7); SGRSoftkeyToolbox::OpenStandardMenu(menu, HANDLER_FUNCTION(FromSoftkey));
Searching in Different Locales
Every REST request to ECS begins with a base URL that is specific to the locale in which you want to make the request.
For Amazon.com (US), the base URL is:
http://ecs.amazonaws.com/onca/xml?Service=AWSECommerceService
For Amazon.co.jp (JP), the base URL is:
http://ecs.amazonaws.jp/onca/xml?Service=AWSECommerceService
The browsenodes for each product type vary according to the locale. In this sample application, the locale base URL and the browsenodes are stored in an XML file. If you want to search on a different locale, just edit this file. Below is the structure of that XML file for the US locale.
<?xml version="1.0" encoding="UTF-8"?> <Locale>http://webservices.amazon.com</Locale> <Books> <Size>31</Size> <Title id="All">Amazon.com</Title> <Title id="1">Arts & Photography</Title> <Title id="2">Biographies & Memoirs</Title> <Title id="3">Business & Investing</Title> <Title id="4">Children's Books</Title> <Title id="4366">Comics & Graphic Novels</Title> <Title id="5">Computers & Internet</Title> <Title id="6">Cooking, Food & Wine</Title> <Title id="13643">Engineering</Title> <Title id="86">Entertainment</Title> <Title id="301889">Gay & Lesbian</Title> <Title id="10">Health, Mind & Body</Title> <Title id="9">History</Title> <Title id="48">Home & Garden</Title> <Title id="49">Horror</Title> <Title id="10777">Law</Title> <Title id="17">Literature & Fiction</Title> <Title id="13996">Medicine</Title> <Title id="18">Mystery & Thrillers</Title> <Title id="53">Nonfiction</Title> <Title id="290060">Outdoors & Nature</Title> <Title id="20">Parenting & Families</Title> <Title id="173507">Professional & Technical</Title> <Title id="21">Reference</Title> <Title id="22">Religion & Spirituality</Title> <Title id="23">Romance</Title> <Title id="75">Science</Title> <Title id="25">Science Fiction & Fantasy</Title> <Title id="26">Sports</Title> <Title id="28">Teens</Title> <Title id="27">Travel</Title> </Books> <DVD> <Size>25</Size> <Title id="All">Amazon.com</Title> <Title id="163296">Action & Adventure</Title> <Title id="538708">African American Cinema</Title> <Title id="712256">Animation</Title> <Title id="517956">Anime & Manga</Title> <Title id="163313">Art House & International</Title> <Title id="163345">Classics</Title> <Title id="163357">Comedy</Title> <Title id="466674">Cult Movies</Title> <Title id="508532">Documentary</Title> <Title id="163379">Drama</Title> <Title id="290738">Educational</Title> <Title id="578324">Fitness & Yoga</Title> <Title id="301667">Gay & Lesbian</Title> <Title id="163396">Horror</Title> <Title id="163414">Kids & Family</Title> <Title id="586156">Military & War</Title> <Title id="163420">Music Video & Concerts</Title> <Title id="508528">Musicals & Performing Arts</Title> <Title id="512030">Mystery & Suspense</Title> <Title id="163431">Science Fiction & Fantasy</Title> <Title id="163448">Special Interests</Title> <Title id="467970">Sports</Title> <Title id="163450">Television</Title> <Title id="163312">Westerns</Title> </DVD>