Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Using MXML with QNX UI Components for the PlayBook

0.00/5 (No votes)
15 Apr 2011 1  
How to use MXML with QNX UI components for PlayBook
One of the less known facts about the Flex SDK and all its various parts is that MXML != Flex. MXML is a markup language that gets turned into ActionScript by mxmlc. With a little bit of knowledge of some metadata and willingness to build a bit of plumbing into a container class, you can use MXML and QNX UI Components for the PlayBook.

So What I Am Trying to Do Here?

I am trying to take a ActionScript 3 UI library and use MXML to describe its layout. More specifically, I wanted to use the PlayBook's native OS UI component library from the BlackBerry Tablet OS SDK, called the QNX UI components. Let's take a look at some code to show you what I am talking about.

Here is a MXML based app using a new class called QApplication that extends QNX Container, which then contains a QNX UI Button:

<?xml version="1.0" encoding="utf-8"?>
<r:QApplication xmlns:r="http://ns.renaun.com/mxml/2010" 

                xmlns:fx="http://ns.adobe.com/mxml/2009"

                xmlns:buttons="qnx.ui.buttons.*">
    <buttons:Button />
</r:QApplication>

Doing this in ActionScript would look like this:

package
{
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;

import qnx.ui.buttons.Button;
import qnx.ui.core.Container;

public class DisplayButtonAS3 extends Sprite
{
  public function DisplayButtonAS3()
  {
    stage.scaleMode = StageScaleMode.NO_SCALE;
    stage.align = StageAlign.TOP_LEFT;
    var container:Container = new Container();
    var but:Button = new Button();
    container.addChild(but);
    addChild(container);
    container.setSize(stage.stageWidth, stage.stageHeight);
  }
}
}

All to create the same application seen here:

MXML-Playbook/display-example.png

DisplayButton Example

What Does This Mean?

This means you can create a PlayBook application all in MXML with no Flex. This also means you can use Flex 4 (including Flex Hero the latest SDK with mobile support) and mix in some QNX UI components. All you need is to add the QMXML.swc (compiled against Tablet OS SDK 0.9.2) and namespace xmlns:r="http://ns.renaun.com/mxml/2010" to your project/application.

Now that sounds like the bomb! Well it's still another UI library. So its not like the QNX UI Component library all of the sudden works just like the Flex Spark architecture. No, the QNX UI lib walks its own path and you will have to remember that when using it. Doesn't mean its bad, just be aware it's not the same as Flex.

If you want to continue and play with the examples, make sure to get the BlackBerry Tablet OS SDK from the BlackBerry developer site: http://us.blackberry.com/developers/tablet/devresources.jsp

NOTE: I am using BlackBerry Tablet OS SDK 0.9.1 as of writing this.

Ok I Get It, Let Me See Some Code!

First! All the code is available on github, go get it. The repository has a few Flash Builder projects in it. The main library project is called QMXML. All you need to create your own project is the QMXML.swc (compiled against Tablet OS SDK 0.9.2) found in the bin folder or you can download it from here.

The other projects are sample projects called: NonFlexMXMLUsingQNX and FlexAndQNX. The NonFlexMXMLUsingQNX project contains the DisplayButton applications shown above, as well as another project showing a few more QNX UI classes nested in containers using QNX flow/containment properties.

The FlexAndQNX application is a standard Flex 4 spark (non-mobile) application that uses a QNX Button and List along side a Flex LineSeries data chart. Which made some sense as QNX UI library lacks charting at this point. Here is a view of the application running in the simulator:

MXML-Playbook/FlexAndQNX-in-Simulator.png

FlexAndQNX in Simulator

Here is the source code for the FlexAndQNX application which allows you mix QNX UI components directly in Flex.

<?xml version="1.0" encoding="utf-8"?>
			<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 

       xmlns:r="http://ns.renaun.com/mxml/2010"

       xmlns:s="library://ns.adobe.com/flex/spark" 

       xmlns:mx="library://ns.adobe.com/flex/mx"

       xmlns:buttons="qnx.ui.buttons.*" xmlns:listClasses="qnx.ui.listClasses.*"

       width="1024" height="600"

       backgroundColor="0xcccccc" 

      >
  <s:layout>
    <s:HorizontalLayout />
  </s:layout>
  <fx:Script>
    <![CDATA[
      import mx.collections.ArrayCollection;
      
      import qnx.ui.core.ContainerFlow;
      import qnx.ui.core.SizeUnit;
      import qnx.ui.data.DataProvider;
      import qnx.ui.events.ListEvent;
      private var data:Array = [];
      [Bindable]
      private var chartData:ArrayCollection;
      private function createData():void
      {
        data = [];
        for (var i:int = 0; i <50; i++)
          data.push({label: "Point " + i, data: i+(Math.random()*30),
            data2: i+60+(Math.random()*60),
            data3: i+80+(Math.random()*120)});
        lstData.dataProvider = new DataProvider(data);
        chartData = new ArrayCollection(data);
      }
      protected function lstData_listItemClickedHandler(event:ListEvent):void
      {
        trace(event.data.data + " - " + event.row);
      }
    ]]>
  </fx:Script>
  <fx:Declarations>  
    <!-- Define custom colors for use as fills in the AreaChart control. -->
    <mx:SolidColor id="sc1" color="0x336699" alpha=".3"/>
    <mx:SolidColor id="sc2" color="0x993333" alpha=".3"/>
    <mx:SolidColor id="sc3" color="0x339933" alpha=".3"/>
    <!-- Define custom Strokes. -->
    <mx:SolidColorStroke id = "s1" color="0x336699" weight="2"/>
    <mx:SolidColorStroke id = "s2" color="0x993333" weight="2"/>
    <mx:SolidColorStroke id = "s3" color="0x339933" weight="2"/>
    
    <mx:SeriesInterpolate id="seriesInterpolate" duration="500" />
  </fx:Declarations>
  <s:Group height="100%" width="20%">
    <r:QContainer id="c" align="near">
      <buttons:LabelButton label="Create Data" click="createData()" />
      <listClasses:List id="lstData" size="100" sizeUnit="percent"

              listItemClicked="lstData_listItemClickedHandler(event)" />
    </r:QContainer>
  </s:Group>
  <s:HGroup width="80%" height="100%">
    <mx:AreaChart id="Areachart" height="100%" width="80%"

          paddingLeft="5" paddingRight="5"

          showDataTips="true" dataProvider="{chartData}">
      
      <mx:horizontalAxis>
        <mx:CategoryAxis categoryField="label"/>
      </mx:horizontalAxis>
      
      <mx:series>
        <mx:AreaSeries yField="data" form="curve" 

               displayName="Plot 1" showDataEffect="{seriesInterpolate}"

               areaStroke="{s1}" areaFill="{sc1}"/>
        <mx:AreaSeries yField="data2" form="curve" displayName="Plot 2" 

               showDataEffect="{seriesInterpolate}"

               areaStroke="{s2}" areaFill="{sc2}"/>
        <mx:AreaSeries yField="data3" form="curve" displayName="Plot 3" 

               showDataEffect="{seriesInterpolate}"

               areaStroke="{s3}" areaFill="{sc3}"/>
      </mx:series>
    </mx:AreaChart>
    
    <mx:Legend dataProvider="{Areachart}"/>
  </s:HGroup>
</s:Application>

There is probably more integration on the QContainer class that I can do to make it work with Flex better but for now follow these loose rules. When mixing QNX UI components in a Flex app always start with a QContainer, think of that as your little mini QNX app space. You will want to wrap this in a Flex Spark Group or SkinnableContainer with the notion of the QContainer filling up all of its parents width and height. The QContainer listens for its parents RESIZE event and then invalidates its layout. Then based on the new width and height of its parent, it remeasures itself and its children. There is some leaway for setting different QNX properties like size and sizeUnit, but for the safest bet start with:

<s:Group height="100%" width="20%">
  <r:QContainer />
				</s:Group>

Any changes to the dimensions of the Group will automatically be detected by the QContainer and it will fill up the whole space of its parent.

NOTE: BlackBerry Tablet OS SDK does not provide a manifest file and namespace for their classes, which means your apps will have a lot of namespaces that look like qnx.ui.buttons.*. Also some QNX classes might cause problems with Flex's SystemManager control the stage, let me know if you come across something.

Project Types, SDKs, and Plugins

There are various projects types across Flash Builder 4 and Flash Builder Burrito. Also the BlackBerry Tablet OS SDK installs plugins for both Flash Builder versions. Typically, all you will need is to create a AIR project and modify your application descriptor file for mobile devices (meaning typically non-WindowedApplication and set visible=true). The QMXML classes will work in Flex 4 spark desktop apps as well as the newer Flex Hero mobile app and theme. This assumes your projects are created and point to the BlackBerry Tablet OS SDK 0.9.1.

Be aware the classes have had limited testing and would love you to take them for a ride. Have fun!

Geek Tidbits from My Journey

With MXML, you get Binding. Which is one of the great benefits of MXML. But this also means I had to take a UI framework that didn't take that into consideration and tweak it to work. Some of the QNX UI framework choices made this not so straightforward. I had to work in a bunch of hooks to properties that might change the layout and create my own layout invalidation/refresh. Luckily, the Container class is the only Container in QNX UI library and it only had a half dozen layout related properties. That made it easy to make this a viable solution.

There is still probably some issues with using width/height instead of the QNX's size, sizeUnit and sizeMode for flow layouts. But if you are using explicit width/height, you probably are not invalidating the layout a bunch.

Also, there were a few properties that didn't implement getter/setters so I had to watch for changes on them differently to invalidate the layout on changes. Overall, it wasn't too complicated but could be improved. Having said all that, I have to put a disclaimer that BlackBerry Tablet OS SDK is in beta and will improve, as well as my understanding how it works will change over time.

History

  • 15th April, 2011: Initial version

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here