Preparing to Use an Htmlwidget
As with all interfaces Brew, before you can use something, you need to create it:
// html widget creation process
nErr = ISHELL_CreateInstance(me->pIShell, AEECLSID_HTMLWIDGET,
(void**)&(me->piwHtml));
if (SUCCESS != nErr) {
return FALSE;
}
IWIDGET_SetBGColor(me->piwHtml, MAKE_RGBA(255,255,255,255));
we.width = (me->rcRoot).dx;
we.height = (me->rcRoot).dy;
IWIDGET_SetExtent(me->piwHtml,&we);
IWIDGET_SetIWeb(me->piwHtml, me->piWeb);
nErr = IWIDGET_GetModel(me->piwHtml, AEEIID_DOCMODEL, (IModel**)&(me->piDocModel));
if (SUCCESS != nErr) {
return FALSE;
}
nErr = IWIDGET_GetViewModel(me->piwHtml, (IModel**)&piModel);
if (SUCCESS != nErr) {
IMODEL_Release(piModel);
return FALSE;
}
nErr = IMODEL_QueryInterface(piModel, AEEIID_HTMLVIEWMODEL,
(void**)&me->piViewModel);
if (SUCCESS != nErr) {
IMODEL_Release(piModel);
return FALSE;
}
After creating an instance of the HTML widget, the code sets its background color to white, and its bounds to the bounds of the application itself. Next, using
IWIDGET_SetIWeb, it links the
htmlwidget with a pre-allocated
IWeb instance. The
htmlwidget will use this
IWeb instance to load any embedded content it requires, such as inline images. (By decoupling the htmlwidget from the IWeb instance, you're better able to configure the IWeb instance on your own, setting options such as custom headers or other HTTP options.) Next, the code gets two models: the
docmodel and the
htmlviewmodel. The application uses the former to load text into the widget, while the application uses the latter to handle things such as user navigation within the HTML pages that the application presents. To do this, the code must also attach listeners to each of these models:
LISTENER_Init(&(me->mlHtmlView), samplehtmlwidgetapp_htmlviewlistener, me);
LISTENER_Init(&(me->mlHtmlDoc), samplehtmlwidgetapp_htmldoclistener, me);
IDOCMODEL_AddListener(me->piDocModel, &(me->mlHtmlDoc));
IHTMLVIEWMODEL_AddListener(me->piViewModel, &(me->mlHtmlView));
(Of course, all of this will only work if you've included the
htmlwidget module in your development environment; be sure to have the
DLL and
MIF file installed in your simulation environment, and if necessary, pre-load the
MOD and
MIF files to your handset under test before you begin. If you find your code fails to instantiate an
htmlwidget, check your environment to be sure you have the appropriate
MOD or
DLL installed correctly!)
Once this is done, the htmlwidget can be inserted into a container or form just like any other widget.
Loading HTML into the Widget
The htmlwidget is pretty boring unless it has something to display. While with a regular text widget you can simply invoke IWIDGET_SetText and you're good to go, the htmlwidget is more flexible: it can load its content directly from an ISource. This is important because both the file and Web interfaces can provide sources to content. (Brew's file interface actually implements the IAStream interface, but you can convert from a stream to a source using the ISourceUtil interface, as you soon see here.) Loading content is handled through the docmodel, which may seem weird if you're used to simpler widgets and how they load their content directly through the widget interface, until you consider that it's really the model's responsibility to store and manage the information used by the widget anyway! In fact, under the hood, methods like IWIDGET_SetText manipulate a widget's model anyway; they're just more convenient for simple widgets.
So, with the docmodel in hand, here's how to load an HTML document from a file:
piFile = IFILEMGR_OpenFile(me->piFileM, pszFilename,_OFM_READ);
nErr = IFILEMGR_GetLastError(me->piFileM);
nErr = ISOURCEUTIL_SourceFromAStream(me->piSourceUtil,
(IAStream*)piFile, &piSource);
if (NULL != piFile) {
nErr = IDOCMODEL_LoadSource(me->piDocModel, piSource);
}
// release handles
RELEASEIF(piFile);
RELEASEIF(piSource);
Pretty simple, isn't it? After opening the destination file, the code converts the stream interface provided by the file to a source interface, and then just hands the source off to the
docmodel. In turn, the
docmodel now owns the source (which owns the file), so to prevent memory leaks, the code releases both the file and the source.