Meet the UcompOS Portal Proxy Components

If you’ve read my previous postings, you should now have a basic understanding of some of the core mechanics of the UcompOS Rich Productivity Framework including Proxy Components and Services Dictionaries.

The concept of the UcompOS Continuum should also be somewhat clearer now as well as the roles of the UcompOS Portal and the UcompOS SDK in the context of the UcompOS Continuum.

Despite the obvious significance of the UcompOS Portal, in the context of the UcompOS Continuum, it is just another entity with the UcompOS SDK implemented that publishes a Services Dictionary of public API methods exposed for other entities.

To take advantage of this fact, the UcompOS SDK has a host of Proxy Components built into it that can be thought of as client interfaces to the public API methods exposed by the UcompOS Portal.

Understanding the mechanics of building your own UcompOS public API methods and Proxy Components to those public API methods is the key to unleashing the true power of the UcompOS RPF and creating the most compelling rich experiences for users of your Rich Portal Application.

But even a basic exploration of the SDK’s built-in UcompOS Portal Proxy Components is a fun way to explore and learn.

In this post, I’ll introduce you briefly to the UcompOS Portal Proxy Components.  I won’t spend a lot of time detailing them as you’ll likely see some dedicated blog postings from me covering the individual Proxy Components and their nuances in the coming weeks.

Each Proxy Component covered is built into all 3 UcompOS SDKs – AIR, Flex/Flash, and JavaScript.

The implementation details of using the AIR and Flash/Flex (ActionScript 3.0) Proxy Components versus the JavaScript Proxy Components are very subtle and of course full SDK documentation is online for the ActionScript 3.0 SDK as well as the JavaScript SDK.

Since the SDK documentation is online, I won’t spend a lot of time covering the methods, properties, and events of the Proxy Components (as you can get all this information in the docs), rather I’ll just give a first-person synopsis of what you can do with each of the Proxy Components.

UcompOSAIRProxy

The UcompOSAIRProxy class allows you to create a virtual representation of a UcompOS AIR application in an entity.  Once you create this virtual representation, you then use this class’s launchApplication(); and quitApplication(); method to control the start and stop of the AIR application.  Then any communication with the AIR application is handled via the traditional means of Proxy Components and public API methods.  The UcompOSAIRProxy class would be used when you wanted to launch a UcompOS AIR application as a sub-application.  If the UcompOS AIR application was to be a base application, you would just have the network URL to the air package in the application manifest and the AIR application would be launchable from the UcompOS application dock.  See my tutorial entitled A Simple HTML Digital Camera Browser for an example of this.

UcompOSArtifactContainerProxy

The UcompOSArtifactContainerProxy class lets you create a container for UcompOS Artifacts on the UcompOS Portal.  A UcompOS Artifact is essentially a “widget” that can be an image or SWF application that can have functionality attached to it (drag and drop, double click, click, rollover, context menu, etc.).

A UcompOS Artifact Container then is a visual layout container for these artifacts.  I gave an example of this in my tutorial entitled Building a UcompOS Weather Channel Widget.

An example may be a taskbar.  Suppose I want to layout a number of widgets each with its own specific functionality attached to it along the bottom right corner of my UcompOS Portal interface.

To do this I could create a UcompOS Artifact Container via the UcompOSArtifactContainerProxy class.  Then when I create my UcompOS Artifact, I would pass a reference to my UcompOSArtifactContainerProxy instance and the artifact would be placed into the relevant container.

There are 3 layout options at present with the UcompOS Artifact Container: HBox, VBox, and Tile

These are parallel to the classes of the same name in the mx.containers package from the Flex 3 framework (FYI the UcompOS Portal is built on Flex 4).

UcompOSArtifactProxy

The UcompOSArtifactProxy is a class used to create UcompOS Artifacts on the UcompOS Portal.

A UcompOS Artifact can be thought of as a widget.  The widget can be purely presentational, or it can have functionality attached to it as my Weather Channel Widget example demonstrated.

The visual content of a UcompOS Artifact can articulated as one of three forms:

  1. The network URL to an image (PNG, GIF, JPG)
  2. The network URL to a SWF appication
  3. A ByteArray representation of an image

You then attach functionality to a UcompOS Artifact by calling the UcompOSArtifactProxy‘s many public methods and attaching various event listeners to it to handle click, double click, rollover, rollout, drag and drop, and other various events.

If the visual content of your artifact is a SWF, this SWF can be a UcompOS sub-application for even more exciting interactive possibilities.

At this point, HTML-type applications cannot be used as artifacts

As described above in my discussion of the UcompOSArtifactContainerProxy class, you can add a UcompOS Artifact to a container so that groups of similar artifacts can be arranged together in a logical presentation.

One cool thing you can do, if you don’t add an artifact to a container and just position it at specified coordinates on the UcompOS Portal, you can make it draggable.  And because you can configure artifacts to accept drops, the ability to drag and drop one artifact to another to create some desired behavior or functionality exists.

I’ll likely devote a tutorial to this interesting capability in the near future.

UcompOSBrowserWindowProxy

The UcompOSBrowserWindowProxy class lets you launch a satellite browser window from the UcompOS Portal.  You can add generic content to the browser window, or you can load a UcompOS sub-application.

The ability to communicate with a UcompOS sub-application loaded in a satellite browser window is the exact same as if the sub-application was loaded in the UcompOS Portal run-time, in a UcompOS Window, or in a UcompOS Artifact.

UcompOSDockProxy

The UcompOSDockProxy class lets you exert control over the UcompOS Portal’s Application Dock.

You can do things such as set context menus to the application icon an entity is associated with.  You can also change the size of the icons on the dock as well as control the “genie” effect (the effect where the dock icons expand and then contract as the mouse passes over them).

You can also hide the dock completely using the showDock(visible:Boolean):void; method.

And one of the more important capabilities is you can set an alert for the icon on the dock an entity is associated with using the setAlert(); method.  This would be useful perhaps in e-mail or instant messaging applications to alert the user of receipt of a new e-mail or instant message.

UcompOSGlobalManagerProxy

The UcompOSGlobalManagerProxy class provides an interface to a number of important visual and data features  of the UcompOS Portal.

For instance, if you wanted the UcompOS Portal to throw a generic Flex-style Alert, you could use the createAlert(); method.

If you wanted to dispatch an event to all entities in the UcompOS Continuum, you could use the dispatchContinuumEvent(); method.

Suppose you wanted to launch another UcompOS application from within an entity.  You could call the launchApplication(); method and pass the manifest URL of the target application’s application manifest.

These are only a few of the important duties the UcompOSGlobalManagerProxy facilitates.

UcompOSHTMLProxy

The UcompOS Portal is a Flex 4 application embedded in an HTML wrapper.

The UcompOSHTMLProxy class lets you call JavaScript functions in the HTML wrapper.

The class provides the alert();, confirm(); and prompt(); methods which invoke the JavaScript functionality of the same name.

You can then add event listeners such as UcompOSHTMLProxy.CONFIRM_SUBMIT and UcompOSHTMLProxy.PROMPT_SUBMIT to capture user-input.

You can also use the javascript(); method to pass pure JavaScript code.

So one possibility here, in the ucompos/local/LocalLib.js JavaScript file in the UcompOS Developers Package that you customize to create your own authentication, you can implement your own JavaScript methods that perform specific tasks and then access these methods from the UcompOSHTMLProxy.

UcompOSMenuBarProxy

The UcompOSMenuBarProxy lets you set the dataProvider for the UcompOS Menu Bar and your particular menu bar implementation comes into view when the UcompOS application associated with the entity that set the menu bar model comes into focus.

You can even associated a menu bar model with an individual UcompOS Window instance.

You then attach event listeners to capture user menu selections.

Two cool random quick points is that you can pass a baseMenu=true value to the second parameter of the setMenuBar(); method and it will remove the default UcompOS menu bar item so you can 100% customize the menu.  Also, in your dataProvider to the menu you can attach an icon property with the network URL of images you want to use for the individual menu bar nodes.

UcompOSStyleProxy

The UcompOSStyleProxy class lets you take control over the portal’s visual presentation including the background image (wallpaper) that appears on the UcompOS portal.

With the setTheme(); method, you can set the MDI window theme to one of 3 different pre-existing window themes.  Right now, I just have the 3 that come packaged with the flexlib.mdi package implemented (Windows XP, Mac OS 9, and the default style) but it is my intention to expand this.

There is also a setEffects(); method that let you control the visual effects that occur when UcompOS Windows are closed or minimized/maximized.  The options are Default, Linear, and Vista which are the effects built into the flexlib.mdi package.

There is also a generic setStyle(); method that lets you set a generic CSS style property to the UcompOS Portal.

One important point about this method.  When you call setStyle();, the UcompOS Portal dispatches a UcompOS Continuum Event – meaning that all entities get notified about the style change.

So if you did something like this:

UcompOSStyleProxy.getInstance().setStyle("Button","color",0xFF0000);

Every entity would be notified that the Button selector’s color property was just given a red value on the UcompOS Portal.

You could then listen for this UcompOSStyleProxy.STYLE_CHANGE event and change the visual presentation of an entity’s internal controls accordingly.

UcompOSWindowProxy

The UcompOSWindowProxy class is used to create MDI window instances on the UcompOS Portal and then load generic web content or a UcompOS sub-application into them.

The class documentation is definitely worth a look as there are a lot of really cool features you can employ with UcompOS Window instances.

So that’s it.  A brief look at all the UcompOS Portal Proxy Components built into the UcompOS SDK.

I invite you to view the source code of the the JavaScript SDK and you can check the UcompOS Flash/Flex SDK written in ActionScript 3 out of the UcompOS SVN Repository.  Viewing this code will give you some better ideas of how to construct Proxy Components.

I have not yet made the source code of the UcompOS Portal publicly viewable and do not have a timeline for doing so but if you have questions about how I have built the public API methods on the UcompOS Portal, please bring questions to me in the UcompOS Forum and I’ll share relevant strategies and code examples.

A Simple HTML Digital Camera Browser

In this tutorial, we will look at a variety of core UcompOS Rich Productivity Framework concepts, and in particular we will explore the mechanics of adding a desktop component to your UcompOS Rich Portal Application.

It is recommended you download the source of the application we’ll build in this tutorial at the link below so you can follow along and there is also a video demonstration of the application we are going to build in this tutorial.

Download the Simple HTML Digital Camera Browser Source Code

This tutorial assumes you have at least a basic working knowledge of:

  • Adobe AIR 2.0
  • Adobe Flash Builder
  • ActionScript 3.0
  • HTML
  • JavaScript
  • You should have read my blog posts or watched my video tutorials about UcompOS Proxy Components and Services Dictionaries

The goals for our application are as follows:

We want to build a simple digital camera browser that lets the user browse through and view images from their digital camera in a Rich Portal Application implementation.

We are going to keep the application as deliberately simple as possible and we are not going to address its cosmetics or aesthetics so that we can focus on providing instruction on specific UcompOS concepts and principles.

To further define the specifications for our application, we want to build a UcompOS Application that prompts the user to connect their digital camera to their computer.  We want our application to be able to know when their digital camera has been connected.  Then when the digital camera has been connected, we want to display the contents of their camera to them.  The user should be able to easily browse through their camera’s contents and they should be able to click on a file on the camera to view it.  Also, the file should be opened in the native photo-viewing application on their computer versus simply displayed in the browser.

Again, we are going to focus on a very simple implementation and will not focus on aesthetics or presentation so that we can focus more on the core UcompOS mechanics we are leveraging to build our application.

Our UcompOS application is comprised of the following components:

  • An AIR 2.0 UcompOS Application built with Adobe Flash Builder 4
  • An HTML UcompOS Sub Application

We’ll walk through the process of setting up and building the different pieces of the application fairly linearly and then tie it all together at the end with a screenshot of our application.

Implementation Details

The way I want to design our program, I want a UcompOS Application to load on the UcompOS Application Dock entitled “My Camera”.  When this application is opened, we want it to launch our UcompOS AIR 2.0 application.  I want that application to prompt the user to connect their digital camera.

When the user connects their digital camera, I want to instantly launch a UcompOS Window instance in the UcompOS Portal that displays the contents of the camera to the end user and allows them to browse through any folder structures housed on the camera and then I want to allow them to select a file to be viewed in their default photo viewing application on their computer.

When the camera is disconnected, I want to shut down the application.

Setting up the AIR 2.0 Application

While I could use a number of different technologies to build our AIR application, I am going to use Adobe Flash Builder 4.   The minimum required version for a UcompOS AIR application is AIR 2.0.  You can learn more about AIR 2.0 and access its run-time and SDK at http://labs.adobe.com/technologies/air2/.

The first step is to set up a Flash Builder project for my AIR application.

My project is called Camera_Example.  Pictured at left is the fully expanded project in Flash Builder with all its files. flash_builder_project

Our main class in our AIR application is Camera_Example.mxml.

Notice in my libs folder is the file UcompOSAIRSDK.swc.  This is the UcompOS SDK file for AIR applications.  This file is found in the UcompOS Developers Package in the sdk/air folder that is created when you unzip the UcompOSSDK.zip file contained in the package.

Simply drag and drop that file into the libs folder of any Flash Builder (or Flex) based UcompOS AIR application.

You can also incorporate the UcompOS AIR SDK into Flash-based and HTML-based AIR applications (the SDK has no Flex dependencies) but the techniques for doing so are outside the scope of this tutorial.

Ideally, my goal is for the end user to not even have any knowledge that an AIR application is involved other than the initial install process.  I want the user to operate entirely within the web browser here and my rationale for this in this tutorial is with the goal in mind of showing how multiple technologies are fusing together to create a seamless rich experience.

Of course, AIR needs to be involved because AIR is what we use to do most of the heavy lifting in our application including detecting the camera attachment/detachment, browsing through the camera’s contents, and opening individual pictures on the desktop.

From an implementation point of view, an AIR application can only be launched from the web browser following a user-initiated event such as a mouse click.

When an AIR application is configured as the base source code for a UcompOS Application, and this application appears on the UcompOS Application Dock, when the user clicks the icon in the application dock, that user event is what triggers the launching of the AIR application.

I’ll add that it is possible to implement UcompOS AIR sub-applications and the best practice for doing this is to leverage the UcompOSArtifactProxy class.  This topic will be covered in a future tutorial in the near future.

Our AIR Application’s Descriptor File

Our Camera_Example-app.xml file needs a very crucial adjustment.

By default, you’ll see this XML element commented out:

<!-- <allowBrowserInvocation></allowBrowserInvocation> -->

This needs to be uncommented and issued a true value:

<allowBrowserInvocation>true</allowBrowserInvocation>

This tells the AIR runtime that your application is allowed to be launched from the web browser.

If you try to instantiate the UcompOS AIR SDK in an AIR application that does not have its descriptor set up in this manner, you’ll get a compile-time error and you won’t be able to package your application.

cameraEven though we do want our AIR application to be as innocuous as possible, if a user does stumble upon it on their main OS’ dock or in the folder on their computer where it’s been installed, I want them to see the custom icon at left and this icon and other varieties in different sizes are in the assets_embed/png folder.

Therefore in my app-descriptor file, I have implemented the following:

<icon>
 <image16x16>assets_embed/png/image16x16.png</image16x16>
 <image32x32>assets_embed/png/image32x32.png</image32x32>
 <image48x48>assets_embed/png/image48x48.png</image48x48>
 <image128x128>assets_embed/png/image128x128.png</image128x128>
 </icon>

AIR Application Code

Since I want the user to know as little as possible, if anything, about the presence of the AIR application, I want it to be invisible.  Therefore, I’ll give the visible property in the root WindowedApplication tag a value of false.  This will suppress any windows from being displayed.

Next, I want to instantiate the UcompOS SDK.

This should happen once the main application dispatches its applicationComplete event.

My root MXML tag looks like this:

<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
   xmlns:s="library://ns.adobe.com/flex/spark"
   xmlns:mx="library://ns.adobe.com/flex/halo"
   applicationComplete="start();"
 visible="false">

Now let’s take a look at the private variables I am declaring in my main class.  We’ll cover the purpose of each of these variables further in the tutorial:

private static var _cameraRoot:String;
private var _h:UcompOSHTMLProxy;
private var _d:UcompOSDockProxy;

Now let’s take a look at my start(); method:

private function start():void
{
 AIRSDKClient.getInstance(this,new ServicesDictionary());
 AIRSDKClient.getInstance().addEventListener(SDKClient.SDK_READY,ucompos_init);
 implementStorageVolumeListeners();
}

The instantiation of the UcompOS AIR SDK is very similar to the instantiation of the UcompOS Flex/Flash SDK that targets browser-based content with a few key exceptions:

  • The Singleton class AIRSDKClient is leveraged versus the SDKClient class
  • We pass this as the first parameter to the getInstance(); method and an optional Services Dictionary as the second parameter.  We’ll look at the Services Dictionary for this application below.
  • Internal to the AIRSDKClient class, the SDKClient class is instantiated.  Once it is instantiated, it dispatches an Event of type SDKClient.SDK_READY and only then can you safely instantiate and use any of the Proxy Components built into the SDK so you must listen for this event and implement any Proxy Component-related startup code in the event handler for this event

In our start(); method, we have a call to implementStorageVolumeListeners();

Let’s take a look at the implementStorageVolumeListeners(); method:

private function implementStorageVolumeListeners():void
{
 StorageVolumeInfo.storageVolumeInfo.addEventListener(StorageVolumeChangeEvent.STORAGE_VOLUME_MOUNT,mountHandler);
 StorageVolumeInfo.storageVolumeInfo.addEventListener(StorageVolumeChangeEvent.STORAGE_VOLUME_UNMOUNT,unmountHandler);
}

This method leverages AIR 2.0 capabilities.  StorageVolumeInfo is a Singleton class in AIR 2.0 that can have an event listener attached to it to handle StorageVolumeChangeEvent.STORAGE_VOLUME_MOUNT and StorageVolumeChangeEvent.STORAGE_VOLUME_UNMOUNT events.  These events are dispatched whenever a new mount point is introduced to the base Operating System or whenever a mount point is removed.  Our handlers for these events are mountHandler(); and unmountHandler(); respectively.

Before we take a look at mountHandler(); and unmountHandler();, let’s take a look at the ucompos_init(); method that is invoked once our UcompOS AIR SDK has been fully initialized and we are ready to interact with it fully:

private function ucompos_init(event:Event):void
 {
  _h = new UcompOSHTMLProxy();
  _h.alert("Please connect your digital camera to your computer");
  _d = UcompOSDockProxy.getInstance();
 }

In this method, we are creating an instance of UcompOSHTMLProxy.  This class has a number of methods that let us execute common JavaScript methods such as alert();, prompt();, and confirm(); in the UcompOS Portal’s HTML wrapper file.

I am choosing to use a regular JavaScript alert to prompt the user to connect their digital camera to their computer.

I am also going to create a reference to the UcompOSDockProxy Singleton and my reasons for doing this will become clear below.

Now, let’s take a look at the mountHandler(); method.

private function mountHandler(event:StorageVolumeChangeEvent):void
{
 _d.setAlert(true);
 _cameraRoot = event.rootDirectory.nativePath;
 w = new UcompOSWindowProxy();
 w.add("http://desktop.ucompass.com/Camera_Example/Camera_Browser.html",event.rootDirectory.name,400,400);
 var object:Object = API.getFiles({});
 }

This method is invoked when the user attaches a new storage volume to their computer.  It is worth mentioning at this time that the simple example being developed here could be used to browse any type of removable storage.  We just happen to be focusing on a scenario that would involve a digital camera.

The implementation details of mountHandler(); are straightforward.  First, we want to call the setAlert(); method of the UcompOSDockProxy instance and pass a value of true to it.  This makes the icon associated with this application on the UcompOS Portal Application Dock “Chirp” and glow drawing the user’s attention to it.

Then, we want to set the _cameraRoot property to event.rootDirectory.nativePath.  The StorageVolumeChangeEvent contains a rootDirectory property which is of type File and represents the file location on the file system where the base of the mount point is located.

Next we create an instance of UcompOSWindowProxy of 400 x 400 and load our HTML sub-application into it.  Our HTML sub-application will be the actual camera browser that the end user interacts with and we’ll review that later.

Our unmountHandler(); method is extremely simple:

private function unmountHandler(event:StorageVolumeChangeEvent):void
{
 w.close();
 UcompOSGlobalManagerProxy.getInstance().quitApplication();
}

This calls the close(); method on our UcompOSWindowProxy instance and then quits out of the application once the camera is removed.

Way back when we instantiated the UcompOS AIR SDK, we passed a new instance of ServicesDictionary to the instantiation method.

There are two public API methods we need our AIR application to sponsor and we are calling them Camera.getFiles and Camera.openFile.

Camera.getFiles will take the path to a given folder on the file system and return a list of the contents of that folder.

Camera.openFile will take the path to a given file on the file system and open it up with the application on the computer that the file is associated with.

First, let’s take a look at our ServicesDictionary:

package cameraexample
{
  import com.ucompass.ucompos.sdk.server.AbstractServicesDictionary;
  public class ServicesDictionary extends AbstractServicesDictionary
  {
    public function ServicesDictionary()
    {
      _map =
      {
        'Camera.getFiles':
        {
          static:true,
          classRef:API,
          method:'getFiles',
          description:'Lists files in a folder'
        },
 
        'Camera.openFile':
        {
          static:true,
          classRef:API,
          method:'openFile',
          description:'Opens a file in its native application'
        }
      }
    }
  }
}

As you can see, both of our public API methods are housed as static methods in an API class.

Here is the method that corresponds to the Camera.getFiles public API method:

public static function getFiles(data:Object):Object
{
  var folder:String = data.folder;
  if(!folder)
  {
    folder = Camera_Example.cameraRoot;
  }
 
  var file:File = new File(folder);
  var files:Array = [];
 
  for(var i:uint = 0;i<file.getDirectoryListing().length;i++)
  {
    var _file:File = file.getDirectoryListing()[i] as File;
    files.push({name:_file.name,isDirectory:_file.isDirectory});
  }
 
  return {eventType:"files",files:files,folder:folder};
 
}

The Camera.getFiles public API method expects a folder property to be on the Object parameter passed to the method.  If it’s not, it retrieves the contents at the base of the camera.

Back in our base application, we have a static getter function that retrieves the value of cameraRoot (which is why we established the value of _cameraRoot in the mountHandler(); method).

Our method simply builds an Array of Objects each having a name property and a Boolean to indicate if the item is a directory.

In our return Object, we return the eventType property set to files as well as our Array of files and a reference to the folder whose contents were retrieved.  We’ll learn more about the purpose of this eventType property when we look at our HTML sub-application.

Our public API method Camera.openFile is extremely simple:

public static function openFile(data:Object):Object
{
 var file:File = new File(data.file);
 file.openWithDefaultApplication();
 return {};
}

That’s it for our AIR application.  We are ready to package it with adt or the compiler built into Flash Builder.

I am packaging it into a file named Camera_Example.air and it will be reachable at a network URL of http://desktop.ucompass.com/Camera_Example/Camera_Example.air

Our HTML Sub-Application

Now we are ready to build our HTML sub-application which will be the interface the end-user actually interacts with.

The URL of our application will be at http://desktop.ucompass.com/Camera_Example/Camera_Browser.html.  This is the URL passed to the add(); method of our UcompOSWindowProxy instance of our mountHandler(); method in our AIR application.

We want this application to be extremely simple.

We just want it to list out the contents of our digital camera and present them as files or folders.

When the user clicks on a folder resource, we want to display the items in that folder.  When they click on a file resource, we want to open that file in the application that the file is associated with on their computer.

From an implementation point of view, when we click a folder, we are going to call our AIR application’s public API method Camera.getFiles and when we click a file we are going to call Camera.openFile.

The first thing we are going to do in our HTML sub-application is implement the UcompOS JavaScript SDK:

<script type="text/javascript" src="/UcompOSSDK.js"></script>

While it is not a requirement, best practice recommends you place the UcompOS JavaScript SDK and SWF files in the root directory of your webserver.

Here are two variables we initialize:

var camera;
var d;

When the UcompOS JavaScript SDK has initialized, it looks for a start(); method in the application its implemented into.

Our start(); method is as follows:

function start()
 {
   d = new UcompOSDockProxy();
   camera = new Camera();
   camera.addEventListener("files",filesHandler);
   camera.getFiles();
 }

We are creating an instance of UcompOSDockProxy which we’ll use to suspend the Dock alert we set in our AIR application.

More importantly, we are creating an instance of Camera, and adding an event listener to it and calling its getFiles(); method.

Camera is a Proxy Component we have built in our HTML sub-application.  A Proxy Component is an interface to the public API methods located in other entities.

In our case, the Proxy Component Camera in our sub-application is the interface to the Camera.getFiles and Camera.openFile public API methods sponsored by our AIR application.

Let’s take a look at our Proxy Component Camera and walk through it as the mechanics of Proxy Components are very important to understand:

function Camera()
{
  this.setDestination(parentConnectionId);
  this.getFiles = function(folder)
  {
    this.call("Camera.getFiles",{folder:folder});
  }
 
  this.openFile = function(file)
  {
    this.call("Camera.openFile",{file:file});
  }
}
 
Camera.prototype = new AbstractProxyComponent();
Camera.prototype.constructor = Camera;

The last two lines of the class would be analogous to saying Camera extends AbstractProxyComponent in ActionScript 3.0.  Any Proxy Component must extend AbstractProxyComponent (in ActionScript as well as JavaScript).

In our class implementation, we pass the parentConnectionId property to the setDestination method of our class (which is a method inherited from AbstractProxyComponent).

Since our sub-application was launched by our AIR application, in the context of the UcompOS Continuum, we know that our AIR application is the parent of the sub-application in scope and we can safely use the UcompOS JavaScript SDK global variable parentConnectionId (this is analogous to the public property SDKModel.getInstance().parent in the UcompOS AIR/Flash/Flex SDK).

Our Camera class also implements two methods: getFiles(); and openFile();.  As you can see by referring to the class code, both of these call the public API methods in our AIR application Camera.getFiles and Camera.openFile by using the call(); method in our class that is inherited from AbstractProxyComponent.

Another very important point, in our start(); method, refer again to this command:

camera.addEventListener("files",filesHandler);

This tells our instance of our Camera class to pass any SDKEvent’s of type “files” to the method filesHandler.

If you refer to our AIR application public API method Camera.getFiles, you’ll recall its return Object sets an eventType property to “files“.

The return Object of the public API method Camera.getFiles is passed to our filesHandler(); method.

Here is the code of our filesHandler(); method:

function filesHandler(data)
{
  var e = document.getElementById('files');
  e.innerHTML = '<p><a href="javascript:void(0);" onclick="getFiles();">Camera Root</a><p/><hr/><p/><u>Current folder: '+data.folder+'</u>';
  for(var i = 0;i<data.files.length;i++)
  {
    if(data.files[i].isDirectory)
    {
      e.innerHTML+='<p/><img src="icons/folder.gif"/> <a href="javascript:void(0);" onclick="getFiles(\''+data.folder+'/'+data.files[i].name+'\');">'+data.files[i].name+'</a>';
    }
    else
    {
      e.innerHTML+='<p/><img src="icons/file.gif"/> <a href="javascript:void(0);" onclick="openFile(\''+data.folder+'/'+data.files[i].name+'\');">'+data.files[i].name+'</a>';
    }
  }
}

Notice we are referencing the files and folder properties of the Object passed to filesHandler();.  We iterate on the files property which we know from our inspection of our AIR application’s public API method Camera.getFiles is an Array and we further know that each Object in this Array has a name:String and isDirectory:Boolean property.

We create simple HTML that displays the name of the files and folders with the appropriate icons and calls the methods getFiles(); for folders and openFile(); for files.

These methods appear below:

function getFiles(folder)
{
 d.setAlert(false);
 camera.getFiles(folder);
}
 
function openFile(file)
{
 camera.openFile(file);
}

In getFiles(); as well as openFile();, notice we are calling the setAlert(); method of the UcompOSDockProxy and passing it a value of false.  This is to cancel the Dock alert we set on the UcompOS Portal’s Application Dock that we set in the AIR application the first time the user clicks on a resource.

That’s all there is to our HTML sub-application.

Configuring Everything as a UcompOS Application

Now we need to set up our application manifest for our simple Digital Camera browser application.

This should be very straightforward if you’ve reviewed some of my other UcompOS tutorials but for AIR applications, there are some special configurations you need to make:

<application>
  <source>
    <base>http://desktop.ucompass.com/Camera_Example/Camera_Example.air</base>
    <params>
      <param>
        <name>appId</name>
        <value>Camera-Example</value>
      </param>
      <param>
        <name>publisherId</name>
        <value>0E5CA255707A7E3F70F12D38B16B8D2A4C17413C.1</value>
      </param>
    </params>
  </source>
  <titles>
    <title locale="en_US" default="true">My Camera</title>
  </titles>
  <icons>
    <icon locale="en_US" default="true">http://desktop.ucompass.com/Camera_Example/icons/camera.png</icon>
  </icons>
</application>

Notice the appId and publisherId parameters you must include in the <params/> element of the manifest.

IMPORTANT: At the time I am authoring this tutorial, the evening of December 27, 2009, the publisherId field faces an uncertain future in AIR 2.0 and may be deprecated.  At present, you can find your publisherId by looking in the $APP/Contents/Resources/META-INF/AIR/publisherid file in the application installation directory for your installed application.  The appId and publisherId parameters must be included otherwise, the UcompOS Portal will not be able to successfully launch your UcompOS AIR application.  Any changes to the AIR 2.0 implementation specifics for publisherId will be blogged about here and updates will immediately be made to the UcompOS RPF accordingly.

Next we’ll take a very quick peak at my Dock Manifest:

<applications>
  <application>
    http://desktop.ucompass.com/Camera_Example/manifest.xml
  </application>
</applications>

In this case, I obviously just have a single application I am loading into my UcompOS Portal implementation that is our simple Digital Camera browser example.

Screenshot of the Application

demo

Conclusion

In this tutorial, we created a deliberately simple application to demonstrate a number of core UcompOS RPF concepts and principles – particularly integrating the desktop into a UcompOS Rich Portal Application implementation.

Building a UcompOS Weather Channel Widget

In this tutorial posting we are going to look at several advanced features of the UcompOS Rich Productivity Framework.

You’ll want to download the source of the example application at the link below so you can follow along and there is also a video tutorial that goes along with this tutorial posting.

Download the Weather Widget Example Source Code

We will be building a small UcompOS application that attaches a Current Weather Conditions Widget to a UcompOS Portal implementation.  The source of the weather data will be The Weather Channel’s API Service.

We are going to look at a number of different UcompOS Rich Productivity Framework concepts in this tutorial including:

  • Working with both the UcompOS JavaScript and Flash SDK
  • Creating UcompOS background applications
  • Working with both UcompOS Artifacts and UcompOS Artifact Containers
  • Working with the UcompOS HTML Proxy

Let’s first start by looking at the application and exploring its functionality.  Then we’ll dissect the implementation carefully and explain exactly how everything was set up.

Below is a screen capture showing our simple implementation.

Demo

We can see a transparent bar on the bottom of the UcompOS Portal.  To the far right, we see a little weather icon with a temperature reading on top of it.

The transparent bar is actually a UcompOS Artifact Container and the weather widget is a UcompOS Artifact instance.

When I right click on the temperature reading, we see a context menu as shown below:

ContextMenu

We’ll look at how this weather widget was constructed as a UcompOS application.

First, let’s look at the Weather Widget itself which is a simple ActionScript 3 Flash CS5 application.

This tutorial assumes you have at least a basic command of the ActionScript 3 programming language so we will not study the construction of the weather widget itself in too much detail, but will rather focus on some of the key aspects of it as they pertain to creating a UcompOS Rich Productivity experience.

The main .fla file for our widget is named weather.fla.

As you can see below, its main document class is a class named Weather and the Flash movie itself is a small square of dimensions 25 pixels x 25 pixels.  Below is a look at the set up of our Flash movie:

FlashSetup

Next, let’s look in my Flash movie’s File > ActionScript Settings > Library Path location in my weather.fla file and we’ll see we have implemented our UcompOSSDK.swc file which is the UcompOS Flash SDK:

SWCSetup

Now let’s take a look at the main Weather class and see how it works.

Let’s first take a moment to reflect on what we want our Flash application to do.

We want our Flash movie to display an icon that displays the current weather conditions and then overlaid on top of that image we want the current temperature to display.

We also want our Flash movie to have a Context Menu associated with it that will let users access certain extended functionality like the ability to change to a new location to retrieve current weather conditions for.

First, in our constructor function for our Weather class, we are going to instantiate the UcompOS SDK by calling the static getInstance() method of the SDKClient class and passing it a self-reference:

SDKClient.getInstance(this);

Next, we’ll create the Loader that will house the image that will display the current weather conditions and add it to the stage:

_loader = new Loader();
 
addChild(_loader);

Now comes a key step.  We are going to create a UcompOSArtifactProxy instance and we will set its self property to true:

_artifact = new UcompOSArtifactProxy();
 
_artifact.self = true;

The Flash movie we are building here is going to be added to the UcompOS Portal as a UcompOS Artifact.  By setting the self property to true, we can manipulate the widget on the UcompOS Portal from within the widget itself.

Now, we are going to add an event listener to handle selections the user makes to items on the Context Menu that we’ll eventually add to the widget:

_artifact.addEventListener(UcompOSArtifactProxy.MENU_ITEM_SELECT,contextMenu_handler);

Next, I’ll create an instance of a TemperatureReport class.  Let’s see what the TemperatureReport class is.

Back in our weather.fla Flash movie, we have a movie clip in the Library named TemperatureReport that is associated with a class of the same name (TemperatureReport).  The movie clip has on its main timeline a simple TextField with the instance name of _textField.

In our TemperatureReport class, we have a public setter function, set temperature, that accepts a value of type String and sets the value as the text property on our _textField instance.

Now, back in our main Weather class, we’ll add the TemperatureReport instance to the stage and position it at (0,5):

_temperatureReport = new TemperatureReport();
addChild(_temperatureReport);
_temperatureReport.y = 5
_temperatureReport.x = 0;

Next we are going to create an instance of the UcompOSHTMLProxy class:

_html = new UcompOSHTMLProxy();

Finally, we will call our private getWeather(); method.

A full discussion of the Weather Channel API is well outside the scope of this tutorial.  In our application, we are using an API to a service called Enrich to access the Weather Channel API.  The API to Enrich is installed in the UcompOS SDK in a class called EnrichComm but again, the implementation details of how we are actually retrieving the weather data in use here is irrelevant.

The specifications for our application are we want to be able to pass a zip code to indicate our location.  The Weather Channel API has a public method that translates a zip code into a weather station identifier.

Once we have our weather station identifier, we can then call the Weather Channel API and request the current weather and pass our station identifier.

The Weather Channel API will return an XML representation of the current weather and our handler will pick out the key values we are interested in using E4X (EcmaScript for XML).

We are interested in the current temperature, the icon that represents the current weather, and the actual official city name that our zip code is associated with.

Now, we will call the load() method on our Loader instance and pass the URL of the current weather icon and we are going to set the temperature property on our TemperatureReport instance to display the current temperature.

Next, we are going to create an XML model for the Context Menu that we want to appear on our weather widget that will let the user change to a different location, open the detailed current weather conditions for the location, or see the 10-day forecast for the location.

We will then pass our XML model to the setContextMenu(); method of our UcompOS Artifact instance.  Since we set the self property of our UcompOSArtifactProxy instance to true, any methods we call on our artifact instance will be applied to the widget itself.

When the user selects an option on the context menu of the widget, the handler invoked is
the contextMenu_handler method.

Artifact context menu handlers are returned an SDKEvent by the UcompOSSDK.  The SDKEvent objects data property is an Object with a label property and this label property is the value of the label on the context menu item the user selected.

We are going to employ a simple switch / case block to handle 3 different scenarios.

Scenario 1 is a change of location where we will call the prompt method of our UcompOSHTMLProxy instance and attach an event listener for the PROMPT_SUBMIT event.

Scenario 2 is the 10-day forecast which we will open up in a UcompOS Window and load the web site on the Weather Channel of the current location in scope.

And Scenario 3, the default in our switch / case block is the detailed local weather conditions for our current location in scope which we will also display in a UcompOS Window.

Going back to Scenario 1 for a moment, the prompt method of the UcompOSHTMLProxy actually causes the UcompOS Portal’s HTML Wrapper to dispatch a call to the JavaScript prompt() command and displays the text passed to it.

The value the user enters into the Prompt dialogue is returned to our event handler which in our case is a private method named newLocation_handler and the value the user entered is contained in the response property of the SDKEvevt object’s data property.

So we now have finished building our widget.

We are now ready to set up the application that will attach the widget to the UcompOS Portal as
a UcompOS Artifact.

We are going to build a simple HTML UcompOS application to accomplish this.  Our HTML application is the file Weather_Widget.html in our example package’s html folder.

We will insert the the UcompOS JavaScript SDK into our application.

In any UcompOS HTML application, any method named start(); is used as the initialization code for the application.

In our start(); method, we are first going to create an instance of UcompOSArtifactContainerProxy and then call its add() method.

We will make it a container of type “HBox” meaning we want the artifacts placed in it to be laid out horizontally.  The second parameter of the add(); method is an Array of style objects where each object has a styleProp and a newValue property.

We want the container positioned along the entire bottom portion of my UcompOS Portal and to do this we’ll set the bottom, right, and left styles to the values you see here.
Container

We have an image that we want displayed as the background image for the container that is at the URL you see indicated above.

Then, we are going to create an instance of UcompOSArtifactProxy and call its add(); method.

var artifact = new UcompOSArtifactProxy();
artifact.add(null,"http://desktop.ucompass.com/Weather_Widget/flash/weather.swf",0,0,false,true,{},container,true);

The URL of our artifact will be the URL of the Weather Widget we created earlier which of course is a SWF file.

A couple key things to point out about our artifact.  First, the sandbox parameter is set to true.

We want the Flash content that constitutes our widget to be sandboxed as we don’t have any need for it to participate in drag and drop activity with other flash content loaded into our portal implementation.

Also, notice for the container parameter of the artifact we are passing a reference to our UcompOSArtifactContainer we created.  This tells the UcompOS Portal to load the artifact into the specified artifact container.

Now, we’re ready to create a simple application manifest for our application.

Here is our manifest and the source code for the application will be the HTML application we just created.

ApplicationManifest

Finally, we’ll create our Dock Manifest for our UcompOS Portal implementation.

The <application/> tag here points to the manifest of our UcompOS application.
Manifest


A very important point to make here is that we have the background=”true” attribute set on our application tag.  What this is saying is immediately launch the application as a background process.  This causes the application to execute as soon as the user logs into the UcompOS Portal but the application is not placed on the application dock.

The UcompOS Portal can launch as many background processes as you need it to.