| developer.brewmp.com developer.brewmp.com

Developer

Creating a Custom Touch Controller

Base version:

Brew® MP 1.0.2

Tested version:

Brew MP 1.0.2

Phone tested:

No

This document describes how to create a custom touch controller to use in widget-based applications. Modifying the Brew MP UI Widgets code is strongly discouraged. Instead, it is recommended that your own touch controllers be implemented outside of Brew MP UI Widgets in their own extension.

Objective

This document explains how custom touch controllers can be created by using touch controllers from the Brew MP UI Widgets platform. This document references an implementation of a custom touch controller similar to the CheckTC (Touch Controller), which is provided in the Brew MP platform. The difference is that this touch controller selects the widget (like CheckWidget) on a pointer down event as oposed to on a pointer up event. This custom touch controller uses GenericTC as a base. This takes advantage of its provision-like click notifications.

Requirements

A simple way to create a custom touch controller is to create an extension using an existing Brew MP UI Touch Controller. The following steps provide an overview of what needs to be done to achieve this. Each step is described in more detail in the example. For more information on Brew MP extensions, see the C Extension Visual Studio Primer.

To create a custom touch controller

  1. Define the internal structure of the touch controller.
  2. Define the constructor of a custom touch controller.
  3. Set the widget.
  4. Customize event handling.
  5. Free memory.

Sample code location

ZIP filename

Location

Run app

c_customtouchcontroller_app

Brew MP Resources

  • Download and extract the ZIP file.

  • Compile the app.

  • Run it on the Brew MP Simulator.

Example: Define the internal structure of the touch controller.

The following structure is used by the custom touch controller provided in the sample code. It includes an IController virtual table. It also includes a pointer to IEnv, which provides system services like class instantiation. The IController pointer holds a reference to the base widget, which in this case is a GenericTC. It is used to override the event handling of the base controller, GenericTC.

typedef struct {   
   AEEVTBL(IController) *  pvt;   
   IController    *picBase;      //Base controller   
   IEnv           *piEnv;   
   IWidget        *piw;          //Controlled widget   
} CustomTouchController;

Example: Define the constructor of a custom touch controller.

The following code snippet shows how to create a custom touch controller with an existing touch controller. First, you need to create an instance of IEnv, which exists throughout the life of the widget. Then, IEnv is used to allocate the custom touch controller's main data structure. Finally, the base touch controller, GenericTC, is created.

static int CustomTouchController_New(IController **ppOut, IShell *piShell)   
{   
   CustomTouchController* me = NULL;   
   IEnv* piEnv = NULL;   
   int nErr = AEE_SUCCESS;   
   ERR_TRY( ISHELL_CreateInstance(piShell, AEECLSID_Env, (void **) &piEnv) );   
   
   //Create the our base structure wih an IController vtable   
   ERR_TRY( IENV_ERRMALLOCRECEX(piEnv,   
                                CustomTouchController,    
                                sizeof(AEEVTBL(IController)),   
                                (void**)&me) );   
   me->piEnv = piEnv;   
   IEnv_AddRef(piEnv);   
   
   
  nErr = IEnv_CreateInstance(piEnv,   
                             AEECLSID_GenericTC,   
                             (void **) &me->picBase);   
   
   if (nErr != AEE_SUCCESS || NULL == me->picBase) {   
      CustomTouchController_Dtor(me);   
      return nErr;   
   }

Next, IController vtable is created. All IController entries are forwarded to the base IController (GenericTC) except for two: SetWidget and HandleEvent. In SetWidget the controlled widget is captured for use later before sending it to the base controller. The event handler is explained below.

   me->pvt = GETVTBL(me,IController);   
   me->pvt->AddRef = CustomTouchController_AddRef;   
   me->pvt->Release = CustomTouchController_Release;   
   me->pvt->HandleEvent = CustomTouchController_HandleEvent;   
   me->pvt->SetHandler = CustomTouchController_SetHandler;   
   me->pvt->SetWidget = CustomTouchController_SetWidget;   
   me->pvt->QueryInterface = CustomTouchController_QueryInterface;   
   
   *ppOut = CAST(IController*, me);   
   
ERR_CATCH:      
   RELEASEIF(piEnv);   
   return nErr;   
}

Example: Set the widget.

Here the controller widget is captured before it is sent to the base controller. This is needed to control the widget from the custom touch controller's event handler.

static int CustomTouchController_SetWidget(IController *po, IWidget *piw)   
{   
   CustomTouchController* me = ICONTROLLER_TO_CUSTOMTOUCHCONTROLLER(po);   
   me->piw = piw; //no add ref. it will be ref'ed by the base   
   return IController_SetWidget(me->picBase, piw);   
}

Example: Customize event handling.

The behaviour of the base touch controller can be changed by modifying the way certain events are handled, or even ignoring certain events altogether. This is where property behaviour is customized to select the widget on pointer down.

Also, this shows how multi-touch support is added to a touch controller. By handling the property, PROPEX_TOUCH_SUPPORT, the touch controller will receive multi-touch events as long as the widget forwards its events to the controller.

static boolean CustomTouchController_HandleEvent(IController* po, 
            AEEEvent evt, uint16 wParam, uint32 dwParam)   
{   
   CustomTouchController* me = ICONTROLLER_TO_CUSTOMTOUCHCONTROLLER(po);   
   int nErr = AEE_SUCCESS;   
   boolean bHandled = FALSE;   
   //toggle selection on pointer down   
   if (EVT_POINTER_DOWN == evt) {   
      IValueModel *pivm;   
      boolean bPressed;   
      ERR_TRY( IWidget_GetModel(me->piw, AEEIID_IValueModel, CAST(IModel**,&pivm)) );   
      //toggle selected state   
      bPressed = !IValueModel_GetBool(pivm);   
      IValueModel_SetBool(pivm, bPressed);   
      bHandled = TRUE;   
      RELEASEIF(pivm);   
   }   
   //support multi-touch   
   if (EVT_WDG_GETPROPERTY == evt) {   
      if (PROP_EX == wParam) {   
         WidgetPropEx *pPropEx = (WidgetPropEx*) dwParam;   
         if (PROPEX_TOUCH_SUPPORT == pPropEx->nPropId) {   
            *((int*) pPropEx->pUser) = AEEWIDGET_TOUCH_SUPPORT_MULTIPLE_POINTERS;   
            return TRUE;   
         }    
      }   
   }   
   if (!bHandled) {   
      bHandled = IController_HandleEvent(me->picBase, evt, wParam, dwParam);   
   }   
ERR_CATCH:   
   if (AEE_SUCCESS != nErr) {   
      bHandled = FALSE;   
   }   
   return bHandled;   
}

Example: Free memory.

The destructor releases only the IEnv not IController or IWidget. The base IController is the first one to destructed as it is the one doing the reference counting. IWidget is only referenced by the base IController so it does not need to be released.

static void CustomTouchController_Dtor(CustomTouchController *me)   
{   
   IEnv *piEnv = me->piEnv;   
   me->piEnv = NULL;   
   (void) IEnv_Free(piEnv, me);   
   IEnv_Release(piEnv);   
}

Related information

  • See the Widgets Touch Technology Guide
  • See the C Extension Visual Studio Primer

Using a Camera in a Brew MP Application

Base version:

Brew MP SDK 1.0 rev 5.3.977535

Tested version:

Brew MP SDK 1.0 rev 5.3.977535

Phone tested:

Yes

Objective

This document describes how to create and set up an ICamera object, preview a snapshot or movie, and save a snapshot or movie within a Brew® Mobile Platform (Brew MP) application.

The example code included is from the c_samplecamera application, which you can download from the How To section of the Brew Mobile Library. You can extract the contents of the .zip file, compile the application, and run it on the Brew MP Simulator.

Note: Brew MP devices do not display camera preview frames on screen sizes 176x144, 128x96, and 96x80. This is a problem in the platform code. This capability will be added in a future release.

Requirements

To use the ICamera interface, you must have:

  • A Brew MP enabled device with camera hardware and support.
  • If testing on the Simulator, a direct-show compliant web cam attached to the computer.
  • Brew MP 1.0 SDK rev 1.0 or greater.
  • A MIF file with privileges for AEEPRIVID_PLFILE and AEECLSID_CAMERA. If your device has multiple cameras, then AEECLSID_CAMERA2, AEECLSID_CAMERA3, and AEECLSID_CAMERA4 might be necessary.

This document assumes that you are familiar with the Brew MP C Application Primer.

ICamera Modes

ICamera has four modes: Ready, Preview, Snapshot and Movie. These modes are a state machine. You can find the current mode by calling the ICAMERA_GetMode() function.

ICamera starts in the Ready mode, and can transition to the other modes. The Preview, Snapshot, and Movie modes can only transition to the Ready mode. To transition from the Preview mode to the Movie mode, you must transition to the Ready mode, and then from the Ready mode to the Movie mode.

State transitions are not complete until the callback function is called. For transitions to the Ready mode, the callback function has the status CAM_STATUS_DONE in nStatus. For transitions to the other modes, the callback function has the status CAM_STATUS_START in nStatus.

Return Values

ICamera has both synchronous and asynchronous functions. A return value of SUCCESS for a synchronous function means the operation was successfully completed.

An asynchronous function initiates an action and returns control to the application. A return value of SUCCESS for an asynchronous function means the command was accepted. You find out about the result of the action from the callback function.

If a function returns CAM_PENDING, the operation is asynchronous and the success of the operation will be in the AEECameraNotify structure in the callback function. An asynchronous operation is complete when the callback function nStatus is equal to CAM_STATUS_DONE.

Refer to the Brew MP API Reference for information on specific ICamera functions, their use, and return values.

Sample code location

ZIP filename

Location

Run app

c_samplecamera

Brew MP Library

  • Download and extract the ZIP file.

  • Compile the app.

  • Run it on the Brew MP Simulator.

Creating a custom widget

Base version:

Brew MP 1.0

Tested version:

Brew MP 1.0

Phone tested:

No

This document describes how to create a custom widget to use in widget-based applications. Modifying the Brew® MP UI Widgets code is strongly discouraged. Instead, it is recommended that your own widgets be implemented outside of Brew MP UI Widgets in their own extension.

Objective

This document explains how custom widgets can be created by using widgets from the Brew MP UI Widgets platform. The custom widget implemented is a CheckBoxStatic Widget, consisting of both a text label and a radio button. Prop container is used as a base widget to implement this widget. Prop container has a checkbox and static Widget inserted in it. This creates the basic look and feel of the CheckBoxStatic widget. This example overrides the event handler for custom event handling.

A model is needed to store the data associated with this widget. The CheckBoxStatic widget has a value model attached to it that uses the CheckBoxStaticWidget_ModelData as the model. CheckBoxStaticWidget_ModelData has two members, the text that can be used by the label, and checkState to denote whether checkbox is enabled or not.

Requirements

To create a CheckBoxStatic Widget, you need to create an extension using existing Brew MP UI Widgets. The following steps provide an overview of what needs to be done. Each step is described in more details in the examples. For more information on Brew MP extensions, see the C Extension Visual Studio Primer.

  1. Create a public header file for CheckBoxStatic Widget.
  2. Define the internal structure of the widget.
  3. Update a CheckBoxStatic_New function.
  4. Property handling.
  5. Freeing memory.

Sample code location

ZIP filename

Location

Run app

c_checkboxstaticwidget_app

Brew MP Resources

  • Download and extract the ZIP file.

  • Compile the app.

  • Run it on the Brew MP Simulator.

c_checkboxstaticwidget_extension

Brew MP Resources

  • Download and extract the ZIP file.

  • Compile the app.

  • Run it on the Brew MP Simulator.

Example: create a public header file for CheckBoxStatic widget

The header file defines the model data associated with CheckBoxStatic widget. It also defines a property to configure this widget to use radio buttons instead of a check box. It defines two other properties, PROPEX_CHECKBOXSTATICWIDGET_CHECKWIDGET and PROPEX_CHECKBOXSTATICWIDGET_STATICWIDGET, to retrieve check box and static widgets from CheckBoxStatic Widget. CheckBoxStatic widget is implementing the IWidget interface, so CheckBoxStatic widget does not have an interface definition in the public header file.

typedef struct CheckBoxStaticWidget_ModelData          
{          
   const AECHAR*  pwszLabel;   // Label for the check box          
   boolean        bCheckState; // Whether its checked or not.          
} CheckBoxStaticWidget_ModelData;               
           
// Property to use the radio button instead of a check box.          
#define  PROPEX_CHECKBOXSTATICWIDGET_RADIOBUTTON       0x0108bfa8          
           
// Property to get the radio button/check box widget form CheckBoxStatic Widget.          
#define  PROPEX_CHECKBOXSTATICWIDGET_CHECKWIDGET       0x0108d1c7          
           
// Property to get the static widget form CheckBoxStatic Widget.          
#define  PROPEX_CHECKBOXSTATICWIDGET_STATICWIDGET      0x0108d1c8          
           
static __inline int IWidget_GetCheckBoxStaticCheckBoxWidget(IWidget *pif,           
                                               IWidget **ppiwCheckBox) {          
   return IWidget_GetPropertyEx(pif, PROPEX_CHECKBOXSTATICWIDGET_CHECKWIDGET,           
                        (int)sizeof(*ppiwCheckBox), (void*)ppiwCheckBox);          
}          
           
static __inline int IWidget_GetCheckBoxStaticStaticWidget(IWidget *pif,           
                                               IWidget **ppiwCheckBox) {          
   return IWidget_GetPropertyEx(pif, PROPEX_CHECKBOXSTATICWIDGET_STATICWIDGET,           
                        (int)sizeof(*ppiwCheckBox), (void*)ppiwCheckBox);          
}

Example: define the internal structure of the widget

The following structure is used by CheckBoxStatic Widget. It creates a prop container and uses it as the base widget. It has two additional widgets to store the check box and static widget. It provides extra property handling by overriding the handler of prop container. It also has a model listener for the view and value model of the widget.

typedef struct {          
   IModule        *piModule;          
   IEnv           *piEnv;          
   IWidget        *piwBase;        // Widget of prop container          
   IPropContainer *picBase;        // Propcontainer ref          
   IWidget        *piwCheckBox;    // Checkbox          
   IWidget        *piwLabel;       // Label          
   HandlerDesc    hdWidget;        // Handler for prop container             
            
   // Model Listeners          
   ModelListener  mlValueModel; // Value model Listener          
   ModelListener  mlViewModel;  // View model listener so we know if the widget          
                                // changes its value model.          
} CheckBoxStaticWidget;

Example: update a CheckBoxStatic_New function

The following code snippet shows how to create CheckboxStatic Widget with existing widgets. It first creates an instance of prop container, then creates checkbox and static widget, and inserts those widgets in prop container. It creates a value model and attaches a listener and the view model to the value model. It overrides the prop container's event handler for handling properties for this widget.

int CheckBoxStaticWidget_New(IWidget **ppOut, IShell *piShell, IModule *piModule)          
{          
   c_checkboxstaticwidget_extension *me = NULL;          
   IPropContainer       *piPropContainer = NULL;          
   IWidget              *piWidget = NULL;          
   IModel               *pim = NULL;          
   IEnv                 *piEnv = NULL;          
   int                  nErr = AEE_EFAILED;          
            
   ERR_TRY( ISHELL_CreateInstance(piShell, AEECLSID_Env, (void **) &piEnv) );          
   ERR_TRY( IENV_ERRMALLOCREC(piEnv, c_checkboxstaticwidget_extension,           
                                                            (void **) &me) );          
   me->piEnv = piEnv;          
   IEnv_AddRef(piEnv);          
   me->piModule = piModule;          
   IMODULE_AddRef(piModule);          
            
   // Create a prop container and insert StaticWidget and Checkbox                
   nErr = IEnv_CreateInstance(piEnv, AEECLSID_PropContainer, (void **)           
                                                           &piPropContainer);          
   if (nErr != AEE_SUCCESS) {          
      CheckBoxStaticWidget_Dtor(me);          
      return nErr;          
   }          
   ERR_TRY( IPropContainer_QueryInterface(piPropContainer, AEEIID_IWidget,           
                                                      (void **) &piWidget) );

Note that the first picBase and piwBase are stored with a 'weak' reference (no increment of the reference count). This is because the CheckBoxStatic widget is overriding the event handler and attaching a value model to the base container. PicBase and piwBase will be destroyed and freed whenever the container is destroyed. Since it is essentially a self reference, that's why there is no need to count it in the reference counting.

   me->picBase = piPropContainer;          
   me->piwBase = piWidget;            // No addref                
   // Set layout style to horizontal          
   ERR_TRY(  IWidget_SetLayoutStyle(piWidget, AEEWIDGET_LAYOUT_HORZ) );          
   // Set border properties          
   ERR_TRY(  IWidget_SetBorderWidth(piWidget, 0) );          
   ERR_TRY(  CheckBoxStaticWidget_AddStaticWidget(me) );          
   ERR_TRY(  CheckBoxStaticWidget_AddCheckBox(me, TRUE) );   

Attach model listeners to the base widget.

    // View Model Listener          
   ModelListener_InitEx(&me->mlViewModel,           
                    (PFNLISTENER)CheckBoxStaticWidget_ViewModelListener, me);          
   ERR_TRY( IWidget_GetViewModel(piWidget, &pim) );          
   ERR_TRY( IModel_AddListener(pim, &me->mlViewModel) );          
   RELEASEIF(pim);          
             
   // Value Model Listener            
   // This listener will be automatically attached by the View Model Listener          
   // Callback when the value model is attached           
   // Create the value model to attach to the base widget          
   ERR_TRY( IEnv_CreateInstance(piEnv, AEECLSID_ValueModel, (void**) &pim) );          
   ModelListener_InitEx(&me->mlValueModel,           
                   (PFNLISTENER)CheckBoxStaticWidget_ValueModelListener, me);          
   ERR_TRY( IWidget_SetModel(piWidget, pim) );

Set the custom handler for this widget, because this widget does custom property handling.

   HANDLERDESC_INIT(&me->hdWidget, CheckBoxStaticWidget_HandleEvent, me,           
                                                  CheckBoxStaticWidget_Dtor);          
   IWidget_SetHandler(piWidget, &me->hdWidget);          
            
   *ppOut = (void *)me->piwBase;          
          
   ERR_CATCH:             
      RELEASEIF(piPropContainer);    // Release the prop container          
                                     // it has only a weak reference           
      RELEASEIF(pim);          
      RELEASEIF(piEnv);          
   return nErr;          
}

Example: property handling

In the handle event function, this widget handles PROPEX_CHECKBOXSTATICWDGT_RADIOBUTTON property to toggle between radio button and checkbox. It passes all the other events to prop container's event handler.

c_checkboxstaticwidget_extension *me = (c_checkboxstaticwidget_extension *) pCxt;          
boolean handled;          
            
switch (eCode) {          
   case EVT_WDG_SETPROPERTY:          
      if (PROP_EX == wParam) {          
         WidgetPropEx *pPropEx = (WidgetPropEx*) dwParam;          
         if (pPropEx->nPropId == PROPEX_CHECKBOXSTATICWIDGET_RADIOBUTTON) {          
            int nErr = 0;          
            nErr = CheckBoxStaticWidget_AddCheckBox(me,
                        (uint32) pPropEx->pUser ? TRUE : FALSE);          
            return (SUCCESS == nErr);          
         }          
      }           
      break;          
   case EVT_WDG_GETPROPERTY:          
      if (PROP_EX == wParam) {          
         WidgetPropEx *pPropEx = (WidgetPropEx*) dwParam;          
         if (pPropEx->nPropId == PROPEX_CHECKBOXSTATICWIDGET_CHECKWIDGET) {          
            *((IWidget**) pPropEx->pUser) = me->piwCheckBox;          
            ADDREFIF(me->piwCheckBox);          
            return TRUE;          
         }           
         else if (pPropEx->nPropId == PROPEX_CHECKBOXSTATICWIDGET_STATICWIDGET) {          
            *((IWidget**) pPropEx->pUser) = me->piwLabel;          
            ADDREFIF(me->piwLabel);          
            return TRUE;          
         }          
      }            
      break;                                                                                                                                                                                                                   
   default:          
   break;          
}          
handled =  HANDLERDESC_CALL(&me->hdWidget, eCode, wParam, dwParam);

Example: freeing memory

The following code cancels the listeners, frees the handler and releases the widgets.:

c_checkboxstaticwidget_extension *me = (c_checkboxstaticwidget_extension *) pCxt;          
            
// Cancel Listeners          
LISTENER_Cancel(&me->mlValueModel);          
LISTENER_Cancel(&me->mlViewModel);          
            
// Free handler          
HANDLERDESC_FREE(&me->hdWidget);          
            
// Release Widgets          
RELEASEIF(me->piwCheckBox);          
RELEASEIF(me->piwLabel);          
{          
   IEnv *piEnv = me->piEnv;          
   me->piEnv = NULL;          
   IMODULE_Release(me->piModule);          
   (void) IEnv_Free(piEnv, me);          
   IEnv_Release(piEnv);          
}

Related information

  • See the Widgets Technology Guide
  • See the C Extension Visual Studio Primer

Attaching to a Model and Handling Model Events

Base version:

Brew MP 1.0

Tested version:

Brew MP 1.0

Phone tested:

Yes

Attaching to a model and handling the events that model sends is one of the core components of the Widgets user interface system. It allows for many powerful things, ranging from defining actions to be taken on state changes, to creating a custom widget without even creating a single actual widget of your own.

Models generally come in two categories for widgets: View Models and Value models. View models are read-only models used to pass state change information the user. This can be used to create custom actions based on state change, such as loading a file when the user clicks a button or updating the contents of an email pane when a new message is selected in a list. Value models are mutable models used by widgets to represent core values that affect the look of the widget. Examples of these are the boolean state of a Check widget or the list of items that will be displayed by a List widget.

In general, View Model notifications are be used by application-level logic to provide for links between different components of the user interface. Value model notifications are be used to implement custom widgets that display based on more complicated value information.

Objective

This document explains the process for attaching to a model, determining whether the event sent out by the model was desired, and taking actions based on those events. It provides the steps necessary to detach yourself from a model when you no longer need the notifications.

Requirements

To attach to the View Model of a widget, an application needs to do the following. Each item is described in greater detail in the example sections found below.

  1. Create a listener function.
  2. Create the widget to which you wish to attach.
  3. Create a model listener and initialize it with the listener function and user data.
  4. Get the view model using IWidget_GetViewModel().
  5. Attach your model listener to the model.

To attach to the value model of a widget, an application follows a similar process. Each item is described in greater detail in the example sections found below.

  1. Create a listener function.
  2. Create the widget to which you wish to attach.
  3. Create a model listener and initialize it with the listener function and user data.
  4. Get the value model using IWidget_GetModel().
  5. Attach your model listener to the model.

To remove yourself from a model, an application calls LISTENER_Cancel() on their model listener. This is described in greater detail in the example sections found below.

Sample code location

ZIP filename

Location

Run app

c_touchtransparency_app

Brew® MP Resources

  • Download and extract the ZIP file.

  • Compile the app.

  • Run it on the Brew MP Simulator.

c_listwidgettouch_app Brew MP Resources
  • Download and extract the ZIP file.

  • Compile the app.

  • Run it on the Brew MP Simulator.

View model example: create a listener function

A listener callback is a function that takes the form specified below. The first parameter is user-specified data, specified when the listener is created. The second parameter is the model event that caused the callback to occur.

static void c_listwidgettouch_app_ListListen(char* listType, ModelEvent* pEvt)       
{       
   if (pEvt->evCode == EVT_MDL_SCROLL_CHANGE) {       
      ScrollEvent* pse = CAST(ScrollEvent*, pEvt);       
      ...       
   }       
   else if (pEvt->evCode == EVT_MDL_FOCUS_CHANGE) {       
      FocusEvent* pfe = (FocusEvent*)pEvt;       
      ...       
   }       
   else if (pEvt->evCode == EVT_MDL_FOCUS_WRAP) {       
      FocusEvent* pfe = (FocusEvent*)pEvt;       
      ...       
   }       
   else if (pEvt->evCode == EVT_MDL_WIDGETELEM_STATE) {       
      WidgetElemStateEvent* pwese = (WidgetElemStateEvent*)pwese;       
      ...       
   }       
}

View model example: create the host widget

Create a widget as normal using ISHELL_CreateInstance() or other suitable function.

...       
ERR_TRY( ISHELL_CreateInstance(piShell, AEECLSID_ListWidget, (void**) &pidList) );       
ERR_TRY( IDecorator_QueryInterface(pidList, AEEIID_IWidget, (void**) &piwList) );       
...

View model example: create a model listener and initialize it with the listener function and user data

Tell the model listener what callback function and user data it should use. The first parameter is the model listener, the second is the callback function, and the third is the user data that will be sent to your function when the callback occurs.

...       
LISTENER_Init(pml, c_listwidgettouch_app_ListListen, (void*)pszListenerData);       
...

View model example: get the View model using IWidget_GetViewModel

...       
ERR_TRY( IWidget_GetViewModel(piwList, &piViewModel) );       
...

View model example: attach your model listener to the model

...       
(void)IModel_AddListener(piViewModel, pml);       
...

Value model example: create a listener function

A listener callback is a function that takes the form specified below. The first parameter is user specified data, specified when the listener is created. The second parameter is the model event that caused the callback to occur.

static void c_touchtransparency_app_TouchModeListener       
                       (TouchModeData* pData, ModelEvent* pEvt)       
{       
   AEEResult nErr;       
   IValueModel *piValueModel = NULL;       
   boolean isEnabled;       
       
   // Get the state of the radio button.       
   ERR_TRY( IModel_QueryInterface(pEvt->pModel, AEEIID_IValueModel,        
                                          (void**)&piValueModel) );       
   isEnabled = IValueModel_GetBool(piValueModel);       
   // If the radio button is now enabled, set our touch mode on the target        
   // (the top widget)       
   if (isEnabled) {       
      (void)IWidget_SetTouchMode(pData->piwTarget, pData->nTouchMode);       
   }       
       
ERR_CATCH:       
   RELEASEIF(piValueModel);       
}       

Value model example: create the host widget

Create a widget as normal using ISHELL_CreateInstance() or other suitable function.

...       
ERR_TRY( ISHELL_CreateInstance(me->pIShell, AEECLSID_RadioWidget,        
                                           (void**)&piwButton) );       
...       

Value model example: Create a model listener and initialize it with the listener function and user data

Tell the model listener what callback function and user data it should use. The first parameter is the model listener, the second is the callback function, and the third is the user data that will be sent to your function when the callback occurs.

...       
LISTENER_Init(&me->radioButtonChanged[i], c_touchtransparency_app_TouchModeListener,       
                                               &me->listenerData[i]);       
...       

Get the Value model using IWidget_GetViewModel().

...       
ERR_TRY( IWidget_GetModel(piwButton, AEEIID_IValueModel, &piValueModel) );       
...       

Attach your model listener to the model.

...       
(void) IModel_AddListener(piValueModel, &me->radioButtonChanged[i]);       
...       

Value model example: cancel a model listener

...       
LISTENER_Cancel(&me->mlAlways);       
...       

Error handling

Make sure that all of the executed APIs have returned AEE_SUCCESS in order to proceed with the next step and for correct execution.

Related information

  • See the Widgets Technology Guide
  • See the C/C++ API Reference

Connecting a Brew MP application to a PC through USB/IPort

Base version:

Brew MP 1.0

Tested version:

Brew MP 1.0

Phone tested:

No

Objective

This topic describes how to

  • Connect a Brew® MP application to a PC via USB/IPort

  • Send Attention (AT) commands to the Attention Command Processor (ATCOP)

Requirements

The application needs to use the correct COM port and the correct commands.

Example - Determining which COM port to use

To determine which COM port to use:

  1. Open Device Manager.

    Under Modems, you should see a modem corresponding to the device.

  2. Right-click on the modem and select Properties.

  3. In the Properties dialog box for the modem, click the Modem tab.

    At the top of the Modem tab, the Port value indicates the COM port to use.

Example - Sending AT commands to the ATCOP

After the application successfully sends an AT$BREW command, the application communicates with the Brew MP Serial Command Processor (BSCOP). The BSCOP commands have numbers prepended to them, such as 01ver or 02app.

If the application opens AEESIO_PORT_INCOMING, the application gains control of the port that enters (or is already in BSCOP). The port also only opens when the transition into BSCOP occurs.

Note: If you're writing an internal tool for the device, you may want to consider using Connect. It handles the serial port/connectivity issues, provides reliability, and has other features such as the ability to copy files, send events, and start applets.

The following sample code is from a file called siousage.c. SIO is a protected class. To create it, you must declare a dependency on AEECLSID_SERIAL in your MIF.

// Our applet's structure
typedef struct SIOUsage
{
   AEEApplet      a;
   IPort         *piPort;
   AEECallback    cbReadable;
   AEECallback    cbWriteable;
} SIOUsage;

static int SIOUsage_Init(SIOUsage *pme)
{
   int nErr;

   nErr = ISHELL_CreateInstance(pme->a.m_pIShell, AEECLSID_SERIAL,
                                (void**)&pSioPort->piPort);

   if (nErr != SUCCESS)
   {
      return EFAILED;
   }

   // The following line opens the USB serial port.  To open the RS-232
   // serial port, use AEESIO_PORT_SIO1
   nErr = IPORT_Open(pme->piPort, AEESIO_PORT_USB1);
   if (nErr != SUCCESS && nErr != AEEPORT_WAIT)
   {
   // There was some unknown error opening the port
      DBGPRINTF("Error opening port");
      return EFAILED;
   }

   // Setup our callbacks.  These are called when there is *probably* data
   // to be written or read.
   CALLBACK_Init(&pme->cbReadable, SIOUsage_TryRead, (void*)pme);
   CALLBACK_Init(&pme->cbWriteable, SIOUsage_TryWrite, (void*)pme);
   IPORT_Readable(pme->piPort, &pme->cbReadable);
   IPORT_Writeable(pme->piPort, &pme->cbWriteable);

   // At this point, if nErr is AEEPORT_WAIT, the serial port is opening.
   // We'll know this is complete when our cbWriteable callback fires.
   // Normally, we'll receive AEEPORT_WAIT instead of SUCCESS.
}

static void SIOUsage_TryRead(void *po)
{
   SIOUsage *pme = (SIOUsage*)po;
   int32 dwRead;
   char buf[100];

   // We can *probably* read data here
   dwRead = IPORT_Read(pme->piPort, buf, sizeof(buf));

   // Log a message if we did read data
   if (dwRead > 0)
   {
      DBGPRINTF("Read %ld bytes of data", dwRead);
   }

   // Remember that we need to reset our readable callback
   IPORT_Readable(pme->piPort, &pme->cbReadable);
}

static void SIOUsage_TryWrite(void *po)
{
   SIOUsage *pme = (SIOUsage*)po&
   int32 dwWrite&
   char *pBuf = "Hello World!";

   // If you want to know if the port successfully got opened, do it here.
   //   what you want to do is nErr = IPORT_Open(pme->piPort, NULL);

   // We can *probably* write data here
   dwWrite = IPORT_Write(pme->piPort, pBuf, STRLEN(pBuf));

   // Log a message if we did read data
   if (dwWrite > 0)
   {
      DBGPRINTF("We wrote %ld bytes of data", dwWrite);
   }

   // Remember that we need to reset our writeable callback
   IPORT_Writeable(pme->piPort, &pme->cbWriteable);
}

Programming for Devices with Extended Keyboard Functionality

Base version:

Brew MP 1.0

Tested version:

Brew MP 1.0

Phone tested:

No

Objective

This topic describes how to create an application for handsets with extended keyboards. The interfaces described were implemented with full support in Brew® 3.1.5 SP01 unless otherwise noted in a handset's device pack. Handsets with earlier Brew versions may have partial or modified support of the interfaces described. Always consult a handset's device pack specification listing to determine handset capabilities.

Requirements

Use the IKeysMapping and IKeysConfig interfaces in applications to decode the key event information. Key events contain extra information to communicate the meaning of key presses to an application.

For handsets with extended keyboards, such as QWERTY, a single key can have multiple input values. For example, an [A] key may also be capable of giving an input of 'a' or a symbol such as '@'. In addition, a combination such as [Function] + [A] can mean an input of '#' on one handset while it means '@' on another.

Device pack requirements

To support IKeysMapping, the device pack must include a map.csv file that provides [key] + [modifier] = [character] mappings. The device pack field IDS_DD_EXTENDED_KEYPAD_SUPPORT indicates whether the device supports an extended keypad using the standard Brew MP behavior described in this topic.

If the device pack contains a map.csv file, IKeysMapping is supported on the Brew MP Simulator, which provides the correct key events as described in this document. When using the Simulator, you can use the PC keyboard to press key combinations, such as [Shift] + [A]. In the Properties tab of the Simulator, a device pack that provides support for IKeysMapping will have a value of Yes for the Extended keypad support field, as shown below.

Event handling

Key events contain the following information:

Primary key The main character that is mapped to a specific hardware key.
Secondary key Additional characters that are mapped to a specific hardware key. A secondary key may be an upper or lower case version of the primary key or a symbol.
Modifiers Flags that communicate to the application which secondary key, if any, has been input from the keypad.
Sticky keys Modifier keys whose state stays constant between key presses, such as a Num Lock or Caps Lock.
Unicode The character encoding specification as described in UCS-2.

There are two types of key events:

  • Primary key events

    • All pressed keys generate the standard key events: EVT_KEY_PRESS, EVT_KEY, and EVT_KEY_RELEASE.
    • For primary keys mapped to a character with a Unicode value, the wParam for the event contains the Unicode value for the character.
    • For primary keys that are alphabetical (A - Z), wParam contains the lower case Unicode value for the letter.
    • The AVK codes, AVK_A through AVK_Z are defined in AEEVCodes.h for convenience, and are equal to the lower case Unicode values for the key press. For example, pressing the [A] key will generate EVT_KEY events with wParam = 97 (the value of AVK_A and the Unicode value for 'a').
  • Secondary key events

    • Secondary key events include one or more modifiers in addition to the primary key information.
    • The combination of the primary key and the modifiers identifies the secondary key.
    • When secondary key events occur, the wParam (primary key code) of an event is the same as it would be for a primary key event and the dwParam value contains the modifiers for the event.
    • The value reported in dwParam is a bitwise OR combination of all currently active modifiers.
    • All keypad event modifiers are defined in AEEVCodes.h. For example, with the [Left Shift] modifier set, pressing [A] will generate an event with the following parameters:
    eCode = EVT_KEY_PRESS (EVT_KEY and EVT_KEY_RELEASE events will
    be received in a similar fashion)
    wParam = AVK_A
    dwParam = KB_LSHIFT

    In the above example, dwParam may be replaced by any combination of modifiers that are valid on the handset, such as KB_SYMBOL, KB_CAPSLOCK, etc., and communicates to the application the modifier(s) that are active when the key is pressed. The possible combinations of modifiers are handset specific. The IKeysMapping interface provides methods to decode overloaded key values. The device pack field IDS_DD_EXTENDED_KEYPAD_SUPPORT specifies the support (YES/NO) of this feature for each specific handset.

Sample code location

ZIP filename

Location

Run app

c_qwertysampleapp

Brew MP Library

  • Download and extract the ZIP file.
  • Compile the app.
  • Run it on the Brew MP Simulator.

Note: To use IKeysMapping on the Simulator, you must copy the map.csv file to the tools\simulation directory in the Brew MP SDK. Make sure to turn off Numlock, Capslock, and Scrolllock on the PC keyboard to avoid interference with keys mapping.

Example - IKeysMapping

Note: This sample code requires the AEEIKeysMapping.h and AEEIKeysConfig.h header files, located in the platform\hardware\inc directory of the Brew MP SDK.

In the following example, IKeysMapping_GetMapping() is called to get the AVK code and modifier for the character, then TextEntry_FindModifier() determines which key was pressed.

   
      if(dwParam) {
         nRetval = IKeysMapping_GetMapping(pMe->m_pIKeysMapping,
                  wParam, dwParam, &mapping);
         TextEntry_FindModifier(pMe, dwParam);
      }
      else {
         mapping = wParam;
      }      

Example - IKeysConfig

Note: Changing sticky key states is a global operation that can affect other applications that are executing concurrently or execute after the change has occurred. It is recommended that applications refrain from modifying sticky key states when they are operating as either a background or a non-top-visible application.

The IKeysConfig interface allows an application to control sticky modifier keys. An application can use the IKeysConfig_GetStickyKeys() interface to determine which sticky keys are present on the handset. An application can also read and modify sticky key states using IKeysConfig_GetKeyState() and IKeysConfig_SetKeyState(), respectively. The IKeysConfig API is available as a QueryInterface on IKeysMapping.

//Exercise IKeysConfig interface
   IKeysConfig_GetStickyKeys(pMe->m_pIKeysConfig, &dwStickyKeys);
   switch(wParam)
   {
      case IDC_CAPS:
         {
            if (pMe->m_dwStickyKeys & KB_CAPSLOCK)
            {
               //If caps lock is present, read its state
               IKeysConfig_GetKeyState(pMe->m_pIKeysConfig, KB_CAPSLOCK,
                        &bKeystate);
               /* Logic to handle Caps Lock state */
               IKeysConfig_SetKeyState(pMe->m_pIKeysConfig, KB_CAPSLOCK,
                        !bKeystate);
	
            }
         }
         break;

      case IDC_NUMLOCK:
         {
            if (pMe->m_dwStickyKeys & KB_NUMLOCK)
            {
               //If caps lock is present, read its state
               IKeysConfig_GetKeyState(pMe->m_pIKeysConfig, KB_NUMLOCK,
                        &bKeystate);
               /* Logic to handle Caps Lock state */
               IKeysConfig_SetKeyState(pMe->m_pIKeysConfig, KB_NUMLOCK,
                        !bKeystate);
            }
         }
      break; 
  
   default:
      break;
   }

It is recommended that applications that are impacted by sticky keys use the IKeysConfig_GetStickyKeys() and IKeysConfig_GetKeyState() interfaces to ascertain sticky key states upon startup and resume instead of assuming a default launching condition. This will prevent incorrect performance caused by differences between handset input state and an application's operational state.

ITextCtl Support for extended keyboard functionality

If your application is using ITextCtl to receive text input from the the user, a new input mode, AEE_TM_EXTENDED_KEYS, was added to the ITextCtl interface in Brew 3.1.5 SP01. (Earlier Brew versions that use extended keypads may have partial support or no support for ITextCtl and may require application support to operate correctly.)

In the AEE_TM_EXTENDED_KEYS mode, ITextCtl automatically decodes key events by internally calling IKeysMapping and displays the correct character in the text box for the current sticky key state. For handsets supporting this input mode, an application should make the following call at the beginning of execution:

ITEXTCTL_SetInputMode(pMe->pITextCtl, AEE_TM_EXTENDED_KEYS);

Applications do not need to modify further the input mode of ITextCtl to properly display key events that are passed using the ITEXTCTL_HandleEvent() interface. Because ITextCtl is internally calling IKeysMapping on events it receives, the application should only pass in the raw key event values sent to the application by Brew MP, without any modification to these values.

Flash Technology Guide

Flash Technology Guide for Manufacturers for Developers

Base version:

Brew MP 1.0

Document number:

HT80-VT500-225

HT80-VT500-226

Date published:

February 9, 2012

Note: The Brew MP Flash interfaces and the AMC Flash Player are deprecated.

The Flash Technology Guide provides information on using the Flash authoring language with Brew ® Mobile Platform (Brew MP™). Particular attention is given to features of this language, APIs, and device configuration information that help OEMs and developers use their unique capabilities with Brew MP. An overview of developing a Flash application, the architecture of how a Flash application runs in Brew MP, and how using Adobe ActionScript allows you to use Flash content in Brew MP applications is also provided. Use cases and tests are shown as examples of how to use the API functionality and how to test it.

The Brew MP Flash interfaces provide extended control of the Flash player and its content and allow player-client interaction to provide advanced features, such as custom text input behavior and full-screen support. In addition, when the client is implemented as a web browser plugin, these interfaces enable close interaction between the HTML/JavaScript content in a web browser and the Flash content in the player.

Brew MP has partnered with Adobe, integrating Adobe Flash and the Adobe Mobile Client (AMC) Flash Player into Brew MP. The Brew MP IFlashPlayer interface allows Brew MP applications to use the AMC Flash Player. The following are potential workflows for application development with Flash and Brew MP:

  • Developing Flash-based applications to run with the Brew MP environment
  • Creating a Brew MP ActionScript extension to package with a Flash application
  • Creating a C-based Brew MP application with embedded Flash content

Developing Flash applications to run in the Brew MP environment

The following are the basic steps for creating a Flash application to run in the Brew MP environment:

Note: In addition to the technology guides, see other Language documentation in http://developer.brewmp.com/resources on the Brew MP website.

  1. Author the application in the Flash environment, creating a Flash (FLA) file.
  2. Publish the application, producing a Shockwave Flash (SWF) file that is exported to the Brew MP Simulator.
  3. Run the SWF file on the Brew MP Simulator to test its functionality.
  4. Edit the application FLA file as necessary.
  5. Export the application files for a Brew MP device.

For more information, see Using Flash in Brew MP.

Creating a Brew MP ActionScript Extension to package with a Flash Application

Brew MP ActionScript extensions are installable modules of C/C++ code that extend the ActionScript language to provide additional capabilities and services. Each extension represents a single ActionScript object that has properties and methods like any other ActionScript object.

A Brew MP ActionScript extension is a Brew MP class, written in C, that implements the IASExtension interface and provides the implementation for a single ActionScript class object. ActionScript extensions extend the ActionScript language by providing new objects for the ActionScript author to instantiate and use.

For information on creating a Brew MP ActionScript extension, see Creating and using ActionScript extensions.

Creating a Brew MP C application with embedded Flash content

To create a C-based Brew MP application, see the C Eclipse Application/Extension Development and C Visual Studio Application/Extension Development sections in the Brew MP Application Developer Primer in http://developer.brewmp.com/resources on the Brew MP website.

To embed Flash content in Brew MP by calling an ActionScript extension, see the Creating and using ActionScript extensions.

Wallpaper Technology Guide

Wallpaper Technology Guide for Manufacturers for Developers

Base version:

Brew MP 1.0

Document number:

HT80-VT500-223 Rev. A

HT80-VT500-224 Rev. A

Date published:

December 13, 2011

The Brew ® Mobile Platform (Brew MP™) IWallpaper interface allows applications to query for information about device support for wallpapers and manage the wallpaper settings. This technology guide describes how to use the IWallpaper interface.

The Brew ® Mobile Platform (Brew MP™) IWallpaper interface allows applications to query for information about device support for wallpapers and manage the wallpaper settings. This technology guide describes how to use the IWallpaper interface and how to properly implement wallpaper support in the device.

Debugging Technology Guide

Debugging Technology Guide for Manufacturers for Developers

Base version:

Brew MP 1.0.2

Tested version:

Brew MP 1.0.2

Document number:

HT80-VT500-221 Rev B

HT80-VT500-222 Rev B

Date published:

May 23, 2012

The Debugging Technology Guide provides information on the following:

  • Heap debugging tools available in Brew MP
  • Memory debugging with Trace32
  • Debugging using Heap1Wrapper
  • Debugging random memory corruption
  • Resolving memory leaks
  • Resolving interface leaks

Sample code

The memtests sample code is available on the Brew MP website with this guide and provides a way to produce the following types of memory errors:

  • Buffer overrun or underrun
  • Freeing a memory node more than once
  • Writing to freed memory
  • Large malloc
  • Malloc memory leak
  • Interface leak

ZIP filename

Location

Run app

memtests.zip

Brew MP Resources

  • Download and extract the ZIP file.

  • Compile the extension.

  • Compile the app.

  • Run it on the Simulator.

Smartcard Technology Guide

Smartcard Technology Guide for Manufacturers for Developers

Base version:

Brew MP 1.0.3

Document number:

HT80-VT500-217 Rev. A

HT80-VT500-190 Rev. A

Date published:

September 9, 2011

From version 1.0.3 and higher, Brew® Mobile Platform (Brew MP) provides a standardized and non-privileged smartcard interface to interact with SIM, CSIM, RUIM, USIM and ISIM types of smartcards. The Smartcard Technology Guide details information needed by the developers to work with this smartcard interface.

For device manufacturers, this document also describes device integration steps for the smartcard interface.

Note: CSIM is a CDMA application that runs on a UICC card and USIM is a UMTS application that runs on UICC cards. ISIM support is limited.

Pages

Subscribe to developer.brewmp.com RSS