Symbian developer community

 
wiki

Create a WRTKit control

From Symbian Developer Community

Jump to: navigation, search

WRTKit does not contain a control that you need.

Recipe
Amount of time required: 20 minutes
Required libraries: N/A
Required header files: N/A
PlatSec Capabilities: N/A
Compatibility: S60 3rd Edition FP2, S60 5th Edition v1.0
Comes with Code: Symbian.org WRT Widget

Solution

Use control libraries or create a control.

WRTKit is a small but powerful framework for writing WRT widgets. However, the number of controls available is limited and larger applications could require additional components.

There are two ways to overcome this:

  1. Using third party control libraries (e.g. [ YUI])
  2. Writing our own controls

Using control libraries is a good option - any control library is ok as long as it is easily skinnable for small screens via CSS. This step could be forbidding if CSS theme is excessively complex or large.

Often, however, we need to add only few simple controls. Luckily, controls are very easy to create with WRTKit. Let us first consider a simple case of non-focusable control. WRTKit includes a Label control which can show text but not an image. We'll create the ImageLabel control that will show an image instead of text.

When using WRTkit, all controls must subclass the Control class. Here is the code to declare the class subclassing control along with field declarations and construction:

 
// Constructor.
function ImageLabel(id, caption, image) {
if (id != UI_NO_INIT_ID) {
this.init(id, caption, image);
}
}
 
// Label inherits from Control.
ImageLabel.prototype = new Control(UI_NO_INIT_ID);
 
// Content element for the ImageLabel
ImageLabel.prototype.contentElement = null;
 
// DOM element for image
ImageLabel.prototype.imageElement = null;
 

First, we have declared the constructor. We are following WRTKit's pattern for class initialisation which allows for clean templating via UI_NO_INIT_ID. Next, the prototype is set to Control establishing inheritance relationship. Finally we declare two DOM elements (DIV as we'll see later) to hold our component and the image.

The init function calls the superclass constructor, creates the main control DOM element and invokes setImage to create the imageElement. Our contentElement is added to the controlElement inherited from Control.

 
// Initializer - called from constructor.
ImageLabel.prototype.init = function(id, caption, image) {
// call superclass initializer
Control.prototype.init.call(this, id, caption);
 
// create content element
this.contentElement = document.createElement("div");
this.controlElement.appendChild(this.contentElement);
 
// set the image
this.setImage(image);
}
 

The image is set via relative URI string. For example, if the image file is "test.png" in the widget root directory, we can just pass "test.png" as parameter during construction. If null is passed as parameter, the image is removed.

 
// Returns the button image (URL); null if none.
ImageLabel.prototype.getImage = function() {
return (this.imageElement != null) ? this.imageElement.src : null;
}
 
// Sets the button image (URL); null if none.
ImageLabel.prototype.setImage = function(image) {
if (image == null) {
// remove image - if any
if (this.imageElement != null) {
this.contentElement.removeChild(this.imageElement);
}
} else {
// default to not append image element
var append = false;
 
// create image element if one doesn't exist
if (this.imageElement == null) {
this.imageElement = document.createElement("img");
this.imageElement.setAttribute("alt", "");
append = true;
}
 
// set image source URL
this.imageElement.src = image;
 
// append the image element to the left cell?
if (append) {
this.contentElement.appendChild(this.imageElement);
}
}
}
 

The setImage code creates or modifies the imageElement and adds/removes the element from the contentElement.

Our ImageLabel should not be focusable - gaining focus on a component that is not editable could obstruct normal focus traversal. Further, we don't want the Control to be disabled as this may affect it's appearance.

 
// Returns the enabled state for the control.
ImageLabel.prototype.isEnabled = function() {
return true;
}
 
// Returns the focusable state for the control.
ImageLabel.prototype.isFocusable = function() {
return false;
}
 

Finally, this sets up standard Control styles appropriate for our ImageLabel. Note that this is a trivial case - editable / focusable control would require a bit more work. NavigationButton in WRTKit is an excellent example of how this can be done.

 
// Updates the style of the control to reflects the state of the control.
ImageLabel.prototype.updateStyleFromState = function() {
// set element class names
this.setClassName(this.rootElement, "Control");
this.setClassName(this.assemblyElement, "ControlAssembly ControlAssemblyNormal");
this.setClassName(this.captionElement, "ControlCaption ControlCaptionNormal");
this.setClassName(this.controlElement, "ControlElement");
this.setClassName(this.contentElement, "LabelText");
}
 

That's it. Place this file in your project and you can use it as any other WRTKit control.

 
// ////////////////////////////////////////////////////////////////////////////
// Symbian Foundation Example Code
//
// This software is in the public domain. No copyright is claimed, and you
// may use it for any purpose without license from the Symbian Foundation.
// No warranty for any purpose is expressed or implied by the authors or
// the Symbian Foundation.
// ////////////////////////////////////////////////////////////////////////////
 
///////////////////////////////////////////////////////////////////////////////
// The ImageLabel class implements a control that displays an image
 
// Constructor.
function ImageLabel(id, caption, image) {
if (id != UI_NO_INIT_ID) {
this.init(id, caption, image);
}
}
 
// Label inherits from Control.
ImageLabel.prototype = new Control(UI_NO_INIT_ID);
 
// Content element for the ImageLabel
ImageLabel.prototype.contentElement = null;
 
// DOM element for image
ImageLabel.prototype.imageElement = null;
 
// Initializer - called from constructor.
ImageLabel.prototype.init = function(id, caption, image) {
// call superclass initializer
Control.prototype.init.call(this, id, caption);
 
// create content element
this.contentElement = document.createElement("div");
this.controlElement.appendChild(this.contentElement);
 
// set the image
this.setImage(image);
}
 
// Returns the enabled state for the control.
ImageLabel.prototype.isEnabled = function() {
return true;
}
 
// Returns the focusable state for the control.
ImageLabel.prototype.isFocusable = function() {
return false;
}
 
// Returns the button image (URL); null if none.
ImageLabel.prototype.getImage = function() {
return (this.imageElement != null) ? this.imageElement.src : null;
}
 
// Sets the button image (URL); null if none.
ImageLabel.prototype.setImage = function(image) {
if (image == null) {
// remove image - if any
if (this.imageElement != null) {
this.contentElement.removeChild(this.imageElement);
}
} else {
// default to not append image element
var append = false;
 
// create image element if one doesn't exist
if (this.imageElement == null) {
this.imageElement = document.createElement("img");
this.imageElement.setAttribute("alt", "");
append = true;
}
 
// set image source URL
this.imageElement.src = image;
 
// append the image element to the left cell?
if (append) {
this.contentElement.appendChild(this.imageElement);
}
}
}
 
 
// Updates the style of the control to reflects the state of the control.
ImageLabel.prototype.updateStyleFromState = function() {
// set element class names
this.setClassName(this.rootElement, "Control");
this.setClassName(this.assemblyElement, "ControlAssembly ControlAssemblyNormal");
this.setClassName(this.captionElement, "ControlCaption ControlCaptionNormal");
this.setClassName(this.controlElement, "ControlElement");
this.setClassName(this.contentElement, "LabelText");
}
 

Summary

This recipe shows how to create a new control for use with WRTKit.

Sign in to comment…