Some UcompOSStyleProxy Basics

If you are a regular reader of this blog, you know that a lot of blogs have been dedicated to talking about the UcompOS Proxy components.  However, one component that hasn’t received a lot of attention so far is the UcompOSStyleProxy.

The UcompOSStyleProxy provides a means to manage the style properties of the UcompOS Main Container.  For instance, you can use the UcompOSStyleProxy to override the default background image on the UcompOS Main Container or set fade in\out duration effects on UcompOSWindowProxy instances.

To demonstrate the two behaviors above, let’s take a look at a simple UcompOSStyleProxy code example.  First, in my UcompOS instance, I have created a simple HTML application called styler.html that is loaded as a background application by my dockManifest.xml file.  The code in my styler.html application is fairly simple and easy to follow as evidenced by the following sample code:

<HTML>
<HEAD>
<SCRIPT TYPE=”text/javascript” SRC=”/UcompOSSDK.js”></SCRIPT>
<SCRIPT TYPE=”text/javascript”>

//instantiate the UCompOSSDK
function start()
{

//instantiate a UcompOSStyleProxy instance that we can apply styles to
var styler = new UcompOSStyleProxy();

//set the default background image to Picture1.jpg at the correct file path on the server
styler.setBackgroundImage(“/applications/Picture1.jpg”);

//now, set the UcompOSWindowProxy instances to fade in\out 3 seconds
styler.setWindowFadeInDuration(3000);
styler.setWindowFadeOutDuration(3000);

}

</SCRIPT>
</HEAD>
</HTML>

Hopefully, this example is simple enough to follow along with fairly easily; the mechanics involved are designed to be as straightforward as possible. However, one could easily envision scenarios where a user’s preferences are saved in a database and loaded at run-time by turning styler.html into a scripted application using PHP, PERL, or the language of your choice.  Or, perhaps you may look at setting and instantiating style properties at startup using your dockManifest. The choice is up to you!

Note also that it is also possible, for example, to change the color of text on the menu bar by using some code like (using our example above):

styler.setStyle(“.MenuBar”,”color”,0x0000FF);

You will want to keep in mind, though, that it is likely that the UcompOSStyleProxy class will continue to evolve in such a way that setting styles in this manner may not work in the future. Therefore, this practice is not recommended at this time. However, you will want to stay tuned to the updates that are made to this class as the UcompOS SDK continues to mature over the coming months.

Embedding Application Manifests Inside the Dock Manifest

As of UcompOS RPF build 0.4.3, you can now embed Application Manifests inside of your Dock Manifest.

The element of a Dock Manifest houses child elements, each of which point to the unique URL of a UcompOS Application Manifest file as shown in the following example:

<applications>
     <application>http://applications.ucompass.com/myApplication.xml</applications>
</applications>

Now, you can embed a element inside of an element in the dock manifest and include the full application manifest inside the element as shown in the following simple example:

<applications>
     <manifestURL>http://applications.ucompass.com/myApplication.xml</manifestURL>
     <manifest>
             <source>
                  <base>http://applications.ucompass.com/mySource.swf</base>
             </source>
     <manifest>
</applications>

Notice you also need to articulate a unique URL for the manifest file in a element – even if there is nothing at the indicated URL.

Also, the UcompOSGlobalManagerProxy‘s launchApplication() method now accepts an optional third manifest parameter of type XML that can be a dynamically generated application manifest.

Therefore, the possibility to generate UcompOS applications on the fly exists.

Building Drag and Drop Experiences in the UcompOS RPF

The UcompOS RPF couldn’t rightfully be called a “Rich Productivity Framework” if it didn’t have a model to support drag and drop interactivity.  Drag and Drop behavior could perhaps be considered one of the key characteristics of an application that helped to define the term “Rich Internet Application” in the early 2000s.

This discussion doesn’t focus on building drag and drop interactivity within a single UcompOS application.  Obviously, you can implement whatever sort of drag and drop interactivity within a singular UcompOS HTML, Flash, Flex, or AIR application without restriction or consideration of UcompOS mechanics.

The real power in a UcompOS Rich Portal Application is in implementing inter-application drag and drop interactivity.

Dragging names from an address book application to an e-mail application, dragging images from a file manager to a text editor, highlighting multiple resources and dragging them to a widget to perform some operation on the items simultaneously – these are some of the experiences that can be created.

The mechanics of drag and drop UcompOS implementations are worthy of discussion.  There are some important considerations that need to be made in order for the UcompOS Portal to enable your applications to be configured appropriately for inter-application dragging and dropping.

Sandboxing in the UcompOS RPF

The philosophy of the UcompOS RPF is to achieve the highest degree of sandboxing possible while still achieving our interaction objectives.

Our sandboxing is less for security purposes and more to create an isolated, self-contained environment for a UcompOS entity that is free from unintentional disruption by other UcompOS entities.

Communication between applications in the UcompOS RPF should exclusively occur using the classes built into the SDK.

In no way should you plan to, or should you need to, attempt to directly access classes, properties, or methods of other UcompOS entities within an individual UcompOS entity. You should exclusively rely on the powerful implementation of a UcompOS entity’s public API methods, Services Dictionary, and Proxy Components.

The one exception to this is the implementation of dragging and dropping across two different UcompOS entities.  But the UcompOS Portal handles all the logic for you so that you don’t need to worry about anything other than what should be dragged and what should be allowed to be a drop target and how it should behave when receiving a drop.

The topic of sandboxing in the Flash Player and loading SWF content into other SWF content is a necessarily thorough and rigorous conversation.

In the UcompOS RPF, any SWF content – be it a UcompOS application or sub-application – is loaded into the UcompOS Portal with an implementation of the SWFLoader class.

The SWFLoader has some very important properties that essentially articulate the permissions the child SWF content has in terms of accessing information (classes, properties, methods) of the parent SWF content it was loaded into.

One of the chief goals of the UcompOS RPF is complete disaggregation.  The framework wants you to be able to place resources at any network address without consequence.

Therefore, all SWF content is loaded into the UcompOS Portal with the trustContent property set with a true value.

There are three different ways SWF content is loaded into the UcompOS Portal as listed below:

  • SWF-based UcompOS application loaded invisibly into the UcompOS run-time
  • SWF-based sub-application loaded into a UcompOS Window
  • SWF-based sub-application loaded into a UcompOS Artifact

When you load SWF content into the UcompOS Portal, you can articulate how tightly it is to be sandboxed.

As far as SWF-based UcompOS applications loading invisibly into the UcompOS run-time, you can set a sandbox=”true” or sandbox=”false” attribute to the root tag in that application’s manifest file.  The default condition is sandbox=”true”.

Also, if you look at the signatures of the add(); methods of both UcompOSWindowProxy and UcompOSArtifactProxy, you’ll see they both have sandbox parameters that default to a true value.

By default, a SWF loaded into a UcompOS Window or UcompOS Artifact will take on the sandbox configuration of its root UcompOS Application.

From an implementation point of view, the only difference between the two configurations is SWF content loaded with the sandbox=”true” configuration has the following property set to the SWFLoader used to load the content:

swfLoader.loadForCompatibility = true;

According to the Adobe’s ActionScript 3 documentation:

“Set this property to
true

to indicate that the loaded application might be compiled with a different version of the Flex framework and you want your application to be able to interact with it. Setting the value of the
loadForCompatibility

property to
true

also causes the LoaderContext of the Loader to load the sub-application into a sibling application domain of the main application, rather than a child application domain.”

A full discussion of the LoaderContext and ApplicationDomain classes is outside the scope of this blog posting, but essentially, setting the loadForCompatibility property to true is a form of sandboxing in that you are able to load Flex content created with a different version of the SDK than the parent SWF content.

Unless you have very specific reasons, in most all cases you’ll leave the sandbox property in its default configuration (sandbox=true).

Our plan is that we will always keep the UcompOS Portal running on the latest public release of Flex 4 so leaving sandbox=true will insure you won’t have to continue to update your Flex-based UcompOS content.

Scenarios for when you would want to set sandbox=false are complex and sophisticated and will be covered in an upcoming posting.

The Marshall Plan

The implications laid out above are somewhat important to elaborate upon.

We want to be able to load SWF content created with any version of the Flex SDK into the UcompOS Portal, and then we still want to be able to enable it to participate in drag and drop interactivity with other SWF content, that may have been produced with still other versions of the Flex SDK.

How is this possible?  After all, classes such as the DragManager are involved and certainly it seems we’ll run into compatibility issues.

The answer is taking advantage of a concept the people at Adobe have created that they call the Marshall Plan.  I recommend you explore this important topic.  It deals with how data is marshalled across the boundaries between two different SWFs.

As of the Beta 2 release of Flex 4, the classes that enable this marshalling to automatically occur are no longer automatically compiled into the SWF.  You have to explicitly add them at compilation time.

This must be added as an argument to the Flex compiler for your application:

-includes=mx.managers.systemClasses.MarshallingSupport

Failure to add this to a Flex 4 Beta 2 UcompOS application that is set up for dragging and dropping will yield unpredictable results, and even run-time errors.

Building a Simple Drag and Drop Example

If you have two different UcompOS entities – one the drag source, the other the drag destination – you would set each of them up as if they were both in the same overall application.

You’d set up the drag source to specify the behavior of the drag initiation, and your drag destination to implement your desired behavior of when items are dragged and dropped onto the target.

There is another scenario however and it involves dragging and dropping to a UcompOS Artifact.

In our example, we want to build a very simple example that shows a UcompOS Flex application that employs a DataGrid.  We then want to implement an artifact and enable the user to drag and drop an item from the DataGrid to the artifact.

When the item is dropped, we want to throw a simple HTML alert that outputs some information about the item that was just dropped.

Here are the three resources used to accomplish this task:

The Dock Manifest

<applications>
 <application background="true" default="true">
   http://applications.ucompass.com/SampleApps/UcompOSExamples/assets/manifests/DragAndDropExample.xml
 </application>
</applications>

The Application Manifest

<application selfLoading=”true” width=”206″ height=”250″ preloaderTitle=”Drag and Drop Example”>
 
 <source>
  <base>http://applications.ucompass.com/SampleApps/UcompOSExamples/bin-debug/DragAndDropExample.swf</base>
 </source>
 
 <titles>
  <title default=”true” locale=”en_US”>UcompOS Drag and Drop Example</title>
 </titles>
 
 <icons>
  <icon default=”true” locale=”en_US”>
   http://applications.ucompass.com/SampleApps/UcompOSExamples/assets/png/nature/Cloud-48×48.png
  </icon>
 </icons>
 
</application>

The Application Code

<?xml version="1.0" encoding="utf-8"?>
<s:Application 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();" height="200" width="200">
 <fx:Script>
 <![CDATA[
 import com.ucompass.ucompos.sdk.SDKClient;
 import com.ucompass.ucompos.sdk.events.SDKEvent;
 import com.ucompass.ucompos.sdk.proxycomponents.UcompOSArtifactProxy;
 import com.ucompass.ucompos.sdk.proxycomponents.UcompOSHTMLProxy;
 
 import mx.collections.ArrayCollection;
 [Bindable]
 private var _people:ArrayCollection = new ArrayCollection([
 {Name:"Ed",Age:36},
 {Name:"Max",Age:2},
 {Name:"Mason",Age:1},
 {Name:"Abigail",Age:1}]);
 
 private function start():void
 {
 SDKClient.getInstance(this);
 var artifact:UcompOSArtifactProxy = new UcompOSArtifactProxy();
 artifact.add("Drag Here!",null,
 "http://applications.ucompass.com/SampleApps/UcompOSExamples/assets/png/nature/Cloud-48x48.png",
 300,300);
 artifact.dragDropManager(true,"items",["Name","Age"]);
 artifact.addEventListener(UcompOSArtifactProxy.DRAG_DROP,dragDropHandler);
 }
 
 private function dragDropHandler(event:SDKEvent):void
 {
 var droppedItems:Array = event.data.dragDropData;
 var droppedItem:Object = event.data.dragDropData[0];
 var h:UcompOSHTMLProxy = new UcompOSHTMLProxy();
 h.alert("Your name is "+droppedItem.Name+" and you are "+droppedItem.Age+".");
 }
 
 ]]>
 </fx:Script>
 <mx:DataGrid width="200" height="200" dataProvider="{_people}" dragEnabled="true">
 <mx:columns>
 <mx:DataGridColumn dataField="Name"/>
 <mx:DataGridColumn dataField="Age"/>
 </mx:columns>
 </mx:DataGrid>
</s:Application>

Video Demo

Drag and Drop Example

The Mechanics of UcompOS Desktop (AIR 2.0) Applications

One of the more important and high-impact features of the UcompOS Rich Productivity Framework is the ability for UcompOS Rich Portal Applications to extend to the desktop.

The technology leveraged to accomplish this is Adobe AIR 2.0.

When you consider the presence of AIR 2.0′s new NativeProcess class, which enables an AIR application to target the native Operating System’s base functionality, the prospect of building industrial-strength applications that place very few limits on the developer and allow their imaginations to extend to new heights becomes very attainable.

In this post I want to talk a bit about the mechanics of AIR applications in the UcompOS RPF.  Understanding these mechanics can help you conceptualize and then deploy the most compelling rich experiences for your UcompOS Rich Portal Application.

The first thing to understand is that in the context of the UcompOS RPF, any AIR application will simply be another UcompOS entity.

A UcompOS entity represents any application or sub-application running in a UcompOS implementation.  The UcompOS Portal itself is a UcompOS entity.  All the UcompOS entities running at one time in the UcompOS RPF comprise what I refer to as the UcompOS Continuum as you know if you’ve been reading my blog postings.

There are a few different ways to launch a UcompOS AIR entity – as an application from the UcompOS Application Dock, using the UcompOSAIRProxy class, or by creating a UcompOS Artifact the user can click on to launch the AIR application.

First, let’s understand the mechanics at work here.  The UcompOS Portal is obviously a Flash-based browser entity.  In order for a browser-based Flash application to launch an AIR application, a couple things need to happen.

First, the author of the AIR application has to articulate that the application is allowed to be launched by the browser.

This is very easy to accomplish.

You simply need to have the following element as a direct child of the root element in the application’s manifest descriptor file.

<allowBrowserInvocation>true</allowBrowserInvocation>

The manifest descriptor file is NOT the UcompOS application manifest for the application.  It is the XML file that articulates the base-level behaviors and properties of an AIR application.

If you try to compile an AIR application that instantiates the UcompOS AIR SDK that does not have the above provision made, you’ll get a compilation error.

Does this mean that the only way your UcompOS AIR applications should be launched is by the browser via the UcompOS Portal?

Not necessarily.  There are ways you can set it up so that when your UcompOS AIR application is launched directly by the end-user, it opens the UcompOS Portal to a precise configuration.

It can even be configured so that your AIR application can save custom file types on the user’s desktop that when double-clicked upon can launch the AIR application which in turn launches the UcompOS Portal and then feeds one or more applications with the data contained in the desktop file.

These are a bit more advanced topics that I’ll definitely devote coverage to these capabilities sometime in the next month or so.

The next thing we need to understand is that the browser can only launch an AIR application following a user-triggered mouse click event.

When you configure an AIR application as the base source for a UcompOS Application in that application’s UcompOS Application Manifest and have the application show up on the UcompOS Application Dock, the UcompOS Portal is configured such that the clicking of the application icon on the dock is the click that is used to immediately launch the AIR application.

When you configure the Application manifest that will use an AIR application as its base source code, there are some parameters you need to incorporate into the manifest.

Below is a sample application manifest from a UcompOS AIR application that provides an example of this:

 
<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>

Note that you must at least include the appId and publisherId parameters.

There are a couple other ways to launch a UcompOS AIR application as a sub-application.

The first is with the UcompOSAIRProxy class which is built into the UcompOS SDK.

The UcompOSAIRProxy Class

The UcompOSAIRProxy class deserves some attention in this posting.  It is a Proxy Component that is used to create a virtual representation of a UcompOS AIR application in a UcompOS entity.  Inspecting the class is a good way to learn more about the mechanics of UcompOS AIR Applications.

Let’s look at the signature of the UcompOSAIRProxy‘s constructor:

public function UcompOSAIRProxy(appSource:String, appId:String,
      publisherId:String, airVersion:String, host:String="127.0.0.1", 
      operationPort:uint=0, validationPort:uint=0)

Let me touch on each of the parameters of the UcompOSAIRProxy‘s constructor:

  • appSource: This is the URL of the .air package file associated with the AIR application
  • appId: This is the application id of the AIR file as it exists in the AIR application’s descriptor file
  • publisherId: This is the value of the publisherid that is found in the file at $APP_INSTALL_DIR/Contents/Resources/META-INF/AIR/publisherid - WARNING: the publisherid will be deprecated in AIR 2.0 soon and I will then remove it as a required parameter in the UcompOSAIRProxy’s constructor at that time
  • airVersion: This is the minimum version of AIR to run the application.  AIR 2.0 is the UcompOS minimum requirement.
  • host: UcompOS AIR Applications rely on the ServerSocket class to communicate with other UcompOS entities.  By default, the UcompOS AIR application binds to 127.0.0.1 on the local machine and other UcompOS entities target that destination in socket transmissions.  However, you can override this and bind to some public facing IP address.  (NOTE: The implications here are remotely deployed UcompOS AIR Applications)
  • operationPort and validationPort: UcompOS AIR Applications bind to two ports – one for validation purposes and the other for actual UcompOS data transmissions.  By default, the UcompOS SDK will start with port number 1024, and climb upward using the first two openly available ports for operation and validation.  These port numbers can be explicitly articulated.

A UcompOSAIRProxy class has three specific types of SDKEvent instances associated with it:

  • UcompOSAIRProxy.AIR_APPLICATION_LAUNCHED: Dispatched when the AIR application has launched
  • UcompOSAIRProxy.AIR_APPLICATION_QUIT: Dispatched when the AIR application has quit
  • UcompOSAIRProxy.AIR_APPLICATION_STATUS: Dispatched following a call to the UcompOSAIRProxy instance’s getStatus(); method

An instance of UcompOSAIRProxy also has a getter/setter on the Boolean property status which returns true when the AIR application is running.

The UcompOSAIRProxy class has two methods key to our discussion: launchApplication(); and quitApplication();

You could use launchApplication(); to launch a UcompOS AIR Application as a sub-application.

When you do, however, the UcompOS Portal must find a way to meet the compulsory user-triggered mouse-click requirement mentioned above.

It does this by throwing an Alert onto the interface of the UcompOS Portal asking the user if they agree to allow the AIR application to launch and then by clicking “OK”, the user is providing the necessary mouse-click.

The full signature of the launchApplication(); method is as follows:

public function launchApplication(message:String=null):void

The message parameter allows you to display a custom message on the Alert used in this scenario.

There is an alternative way to launch a UcompOS AIR sub-application that I’ll cover next.

Using a UcompOS Artifact to launch an AIR Application

By now, you know that the UcompOSArtifactProxy class in the UcompOS SDK provides a way to implement the equivalent of “desktop widgets” on the UcompOS Portal interface.  I prefer the term “Artifact” over “Widget” however as I feel widget has functionality implied, whereas a UcompOS Artifact can be functional and can be a full-fledged UcompOS sub-application or it can be strictly presentational.

As is the case with all Proxy Components (i.e. any class that extends AbstractProxyComponent), UcompOSArtifactProxy instances have a data property.

When you set the data property of a UcompOSArtifactProxy instance, this data property is housed on the actual artifact itself on the UcompOS Portal.

There are two special properties that can be added to this data Object: launchAIRApplication and quitAIRApplication

The values of these properties would be the uuid property of the UcompOSAIRProxy instance that was to be launched upon a mouse click of the artifact involved.

So the following code may be something you’d see in practical operation:

var myAIRAppProxy:UcompOSAIRProxy = new UcompOSAIRProxy("http://apps.mysite.com/myApp.air","My-App","My-Publisher-Id","2.0");
var myArtifactProxy:UcompOSArtifactProxy = new UcompOSArtifactProxy();
myArtifactProxy.add("Label for my Artifact",imageContent);
myArtifactProxy.data = {launchAIRApplication:myAIRAppProxy.uuid};

In the above example, as soon as the artifact is clicked on, the AIR application will launch.

You could also do something like the following too:

private function launchHandler(event:SDKEvent):void
{
 switch(event.type)
 {
 case UcompOSAIRProxy.AIR_APPLICATION_LAUNCHED:
  myArtifactProxy.setImage(imageContentAppOn);
  myArtifactProxy.data = {quitAIRApplication:myAIRAppProxy.uuid};
 break;
 case UcompOSAIRProxy.AIR_APPLICATION_QUIT:
  myArtifactProxy.setImage(imageContentAppOff);
  myArtifactProxy.data = {quitAIRApplication:myAIRAppProxy.uuid};
 break;
 }
}

In the above example, we are listening to see when the AIR application is launched as well as when it quits.  We then replace the artifact image with a status indicator using the UcompOSArtifactProxy‘s setImage(); method so it easily shows the user if the associated AIR application is running or not.

As an example of how I am using this concept myself, in the Educator 2 Rich Portal Application I am building entirely on top of the UcompOS RPF, on the taskbar (an artifact container with a number of artifacts housed in it), there is an icon to launch the “Educator 2 Desktop”, which is obviously an AIR application.

When they click this icon, the Educator 2 Desktop immediately launches and the icon turns green indicating the feature is connected.  When they click it again, the Educator 2 Desktop quits and the icon turns red indicating the feature is disconnected.

Building a Multilingual UcompOS Implementation

The UcompOS Rich Productivity Framework is designed to make it easy to serve localized Rich Portal Application implementations.

In this tutorial, we are going to explore the localization capabilities of the UcompOS RPF and look at some strategies for leveraging these capabilities.

I have created a Video that I encourage you to view that shows the implementation we are going to build in this tutorial in action, and you should also Download the source code that we build in this application so you can better follow along with it.

As is the case with most of our UcompOS tutorials, we are going to focus much less on aesthetics and presentation and more on the highlighting of core UcompOS fundamentals and mechanics.

In addition to highlighting the localization capabilities of the UcompOS RPF, we are also going to touch on a number of other useful and important topics including some advanced capabilities of UcompOS Application Manifest files as well as working with the UcompOSStyleProxy class which manages the aesthetic presentation of the UcompOS Portal.

In addition, we are going to learn more about the UcompOS Menu Bar, and also about the concept of declaring default UcompOS Background Applications.

Our Target Implementation

The implementation we want to build will involve a UcompOS application that opens some simple content in a UcompOS Window.  The content will internally be configured to display some simple text that can be automatically translated on the fly to another language using Yahoo’s BabelFish free translation API.

We will set up the application such that the user can switch the operating language using a “language chooser” we’ll build into the UcompOS Menu Bar.

We will also create graphical artifacts that provide a customized experience to the end user when they switch between languages.

The languages we’ll allow users to choose from will be:

  • English
  • Spanish
  • German
  • French
  • Italian

Two UcompOS Applications Involved

Our implementation will involve the construction of two UcompOS Applications.  One we will consider the Controller for our implementation, and another we will consider the View.

Both our applications will be UcompOS HTML applications that will leverage the UcompOS JavaScript SDK.

We are going to put all assets and code related to our implementation in a single folder named Multilingual.  Inside the Multilingual folder are controller and view subfolders with the pertinent assets and code in each folder.

Implementation Specifics

Let’s talk a little bit more about exactly how we want our implementation to behave.

We want to place a language chooser on the UcompOS Menu Bar that lets the user switch between languages.

We want this Menu Bar to be perpetually on the UcompOS Menu Bar even when our View application is in focus.

Our Dock Manifest

Let’s take a look at our Dock Manifest and discuss some of its more important aspects:

<applications>
<application background="true" default="true">

http://desktop.ucompass.com/Multilingual/controller/manifest.xml

</application>
<application>

http://desktop.ucompass.com/Multilingual/view/manifest.xml

</application>
</applications>

Obviously, the first UcompOS Application listed in our Dock Manifest is our Controller application and the second is our View application.

A very important point to discuss are the two attributes set for our Controller application, specifically background=”true” and default=”true”.

When you declare a UcompOS Application as a background application, that means it is to be launched immediately upon authentication to the UcompOS Portal and it is to not be presented on the UcompOS Application Dock.

The code is simply loaded in the UcompOS run-time immediately and remains available for interaction throughout the session.

Setting an application as the default has implications on the UcompOS Menu Bar – the Menu Bar of the application declared as the default application is the Menu Bar that shows when no application is in focus.

The best analogy to this is to consider the Finder application in Mac OS X.  The Finder’s Menu Bar shows up in Mac OS X when no other application is open.  Also, if you click the Mac OS X desktop on the wallpaper (not on an artifact from a running application), the Menu Bar of the Finder is what is displayed.

This is paralleled in the UcompOS RPF by designating an application with the default=”true” attribute in the Dock Manifest.

If no application is configured with the default=”true” attribute, then the base, default UcompOS Menu Bar is displayed when no application is in focus.

Also, if you try to configure a Dock Manifest with more than one application specified as the default, you’ll encounter a run-time error from the UcompOS Portal.

Also, in an individual application’s Application Manifest, you can instruct the UcompOS Portal to use the default Menu Bar.  We’ll look at this shortly as this will be how we configure our View application.

The Controller Application Manifest

Let’s take a look at the Application Manifest for our Controller:

<application>

 <source>
 <base>http://desktop.ucompass.com/Multilingual/controller/Controller.html</base>
 </source>

 <menu>
 <menuitem label="Language">
 <menuitem label="English" icon="http://desktop.ucompass.com/Multilingual/view/images/icons/en_US_menubar.png" data="en_US"/>
 <menuitem label="Spanish" icon="http://desktop.ucompass.com/Multilingual/view/images/icons/es_ES_menubar.png" data="es_ES"/>
 <menuitem label="German" icon="http://desktop.ucompass.com/Multilingual/view/images/icons/de_DE_menubar.png" data="de_DE"/>
 <menuitem label="French" icon="http://desktop.ucompass.com/Multilingual/view/images/icons/fr_FR_menubar.png" data="fr_FR"/>
 <menuitem label="Italian" icon="http://desktop.ucompass.com/Multilingual/view/images/icons/it_IT_menubar.png" data="it_IT"/>
 </menuitem>
 </menu>

</application>

As you can see our Controller Application Manifest is very simple but its chief critical responsibility is to furnish a Menu Bar implementation for the UcompOS Portal.

Since our Controller Application is configured as the default application in our Dock Manifest, its Menu Bar will be what displays when no other application is in focus.

The XML structure for the Menu Bar is very simple and straightforward.  Notice the icon property points to the network URL of an icon image to be displayed on the Menu Bar.  Also, a data property must be present in a Menu Bar node for an event to be dispatched to the applications and sub-applications the Menu Bar is associated with when the user chooses a Menu Bar option on the UcompOS Portal.

Our Menu Bar configures a Language Chooser on the UcompOS Menu Bar and lets the end-user choose between one of five different languages.

The View Application Manifest

Now let’s take a look at the View application’s Application Manifest:

<application selfLoading="true" width="500" height="500" x="100" y="100">

 <source>
 <base>http://desktop.ucompass.com/Multilingual/view/View.html</base>
 </source>

 <titles>
 <title locale="en_US">A Multilingual Application</title>
 <title locale="es_ES">Un uso multilingue</title>
 <title locale="de_DE">Eine mehrsprachige Anwendung</title>
 <title locale="fr_FR">Une application multilingue</title>
 <title locale="it_IT">Un'applicazione multilingue</title>
 </titles>

 <icons>
 <icon locale="en_US">http://desktop.ucompass.com/Multilingual/view/images/icons/en_US_dock.png</icon>
 <icon locale="es_ES">http://desktop.ucompass.com/Multilingual/view/images/icons/es_ES_dock.png</icon>
 <icon locale="de_DE">http://desktop.ucompass.com/Multilingual/view/images/icons/de_DE_dock.png</icon>
 <icon locale="fr_FR">http://desktop.ucompass.com/Multilingual/view/images/icons/fr_FR_dock.png</icon>
 <icon locale="it_IT">http://desktop.ucompass.com/Multilingual/view/images/icons/it_IT_dock.png</icon>
 </icons>

 <toolTips>
 <toolTip locale="en_US">See a UcompOS Application translate text into English</toolTip>
 <toolTip locale="es_ES">Vea un uso de UcompOS traducir el texto a inglés</toolTip>
 <toolTip locale="de_DE">Sehen Sie eine UcompOS Anwendung, Text ins Englische zu übersetzen</toolTip>
 <toolTip locale="fr_FR">Voir l'application d'UcompOS traduire le texte en anglais</toolTip>
 <toolTip locale="it_IT">Vedi un'applicazione di UcompOS tradurre il testo in inglese</toolTip>
 </toolTips>

 <menu default="true"/>

</application>

The first thing to notice about the Application Manifest above is the strategy employed for localizing Application titles, icons, and tool tips.

The Application Title shows up on the UcompOS Application Dock for a particular application as well as any UcompOS Windows that are spawned by the application.  The same applies to Application Icons.

Tool tips show up when the user mouses over an application icon on the UcompOS Application Dock and the mouse hovers for a second.

Notice how the locale attributes in this manifest match up to the data attributes for the menu bar model in our Controller manifest.

Another important thing to take note of is the <menu default=”true”/> element in the manifest.

This tells the UcompOS Portal that when this application is in focus, still use the UcompOS Portal’s default Menu Bar which will be the Menu Bar of our Controller Application.

Also, note the selfLoading=”true” attribute as well as the width, height, x, and y attributes in our manifest’s root <application/> element.

This tells the UcompOS Portal to launch the application into a UcompOS Window instance versus simply loading it into the UcompOS run-time.

Preparing the Graphics

The next task in building our implementation will be to prepare the graphic assets we’ll use.

In this implementation, I want our application icon to automatically update on the UcompOS Dock and UcompOS Window instances spawned by our application to reflect the most recently selected language.  So I’ll need five different application dock icons – one for each language.

Then on the UcompOS Menu Bar, we will add a “language chooser” utility.  I want each node in the language chooser, which will represent a different language, to have an icon representative of the given language.  So I’ll need five different menu bar icons – one for each language.

Finally, each time a new language is selected, I want the background wallpaper for my UcompOS Portal implementation to display an image representative of the chosen language.

I have created a folder named images in my Multilingual project’s view folder and in the images folder I’ve created two more folders:  icons and backgrounds.  I am placing the dock and menu bar icons in the icons folder and the background images in the backgrounds folder.

The Controller Source Code

As you can see in our Controller‘s Application Manifest, it points to the following network URL as the location for the application’s source code:

http://desktop.ucompass.com/Multilingual/controller/Controller.html

Let’s take a look at this application’s source code below and discuss it:

<html>
<head>
<title>Multilingual Controller</title>

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

<script type="text/javascript">

 var m;
 var g;
 var s;

 function start()
 {
 m = new UcompOSMenuBarProxy();
 g = new UcompOSGlobalManagerProxy();
 s = new UcompOSStyleProxy();

 m.addEventListener(m.CHANGE,menuChangeHandler);
 }

 function menuChangeHandler(menuData)
 {
 g.changeLanguage(menuData.data);
 s.setBackgroundImage("http://desktop.ucompass.com/Multilingual/view/images/backgrounds/"+menuData.data+".jpg");
 }

</script>

</head>
</html>

The first thing to notice is since this is an HTML application, we have the UcompOS JavaScript SDK installed.

Our start(); method employs a class we haven’t looked at yet in any of our tutorials, UcompOSMenuBarProxy, which manages and handles events dispatched by the Menu Bar on the UcompOS Portal.

In this case, we are added an event handler to handle CHANGE events.

In addition to the UcompOSMenuBarProxy, we are also working with the UcompOSGlobalManagerProxy and UcompOSStyleProxy classes in this application.

In this application, when we receive notification that the user has selected a new option on the Menu Bar, we access the newly selected language as the data property of the menuData Object passed to the event handler by the UcompOS SDK.

We then take that value and pass it to the changeLanguage(); method of the UcompOSGlobalManagerProxy.  This method configures the operating language on the UcompOS Portal with the newly chosen language string.  Whenever the UcompOS Portal’s operating language changes, a UcompOS Continuum Event is dispatched meaning that every running application and sub-application in the UcompOS Continuum is notified instantly.  This detail will be important to us when we look at our View application.

We also call the setBackgroundImage(); of the UcompOSStyleProxy and pass it the URL of a background image that is representative of the newly selected language.  This method sets the wallpaper image for the UcompOS Portal.

The View Source Code

As we saw in our View application’s Application Manifest, the source code of our View application is reachable at a network URL of:

http://desktop.ucompass.com/Multilingual/view/View.html

In the View application, we are starting with a string of text embedded in an HTML DIV element that is in the English language.

In our start(); method, we are creating an instance of the UcompOSGlobalManagerProxy class and calling its getSessionInfo(); method.  We are also attaching an event listener for events of type UcompOSGlobalManagerProxy.SESSION_INFO.

The getSessionInfo(); method the UcompOS Global Manager Proxy is extremely important.  It returns an Object with a number of important properties including the unique user Id that the current user is authenticated into the UcompOS Portal with.

Also, it returns the current language the UcompOS Portal is operating in in a property called language.

The exact implementation details regarding doing the actual language translation are outside the scope of the UcompOS RPF but I’ll explain them briefly.

We are using a web-based service called Enrich which provides an API to the Yahoo BabelFish free online language translation service to convert our content from one language to another.

One other UcompOS-related detail in our implementation is we are creating a UcompOSWindowProxy instance and setting its self property to true.

This lets us access the methods and properties of the UcompOS Window that the application we are operating in has been loaded into.

Once the user changes to a new language, we are then calling the UcompOSWindowProxy‘s setTitle(); method to update the title on the UcompOS Window in real-time.

Let’s take a look at the full source code of our View application below:

<html>
<head
<title>Multilngual Application</title>

<style type="text/css">

 body
 {
 font-family: Helvetica, Arial;
 font-size: 12px;
 }

 #title
 {
 font-size: 24px;
 background-color: #2677B6;
 color: #FFFFFF;
 font-weight: bold;
 text-align: center;
 padding: 2px;
 }

</style>

<script type="text/javascript" src="http://pilotfish.ucompass.com/gofish"></script>
<script type="text/javascript" src="/UcompOSSDK.js"></script>

<script type="text/javascript">

 var currentLanguage = 'en_US';
 var g;
 var thisWindow;
 var languageReference = {en_US:'English',es_ES:'Spanish',fr_FR:'French',de_DE:'German',it_IT:'Italian'};

 function start()
 {
 thisWindow = new UcompOSWindowProxy();
 thisWindow.self = true;
 g = new UcompOSGlobalManagerProxy();
 g.addEventListener(g.LANGUAGE_CHANGE,changeLanguage);
 g.addEventListener(g.SESSION_INFO,init);
 g.getSessionInfo();
 }

 function init(sdkData)
 {
 var c = setInterval(function () { if(callWebService) { clearInterval(c); changeLanguage(sdkData); } },100);
 }

 function changeLanguage(sdkData)
 {
 var query = new Object();
 query['feature'] = 'Search';
 query['module'] = 'Translate';
 query['sourceLanguage'] = currentLanguage;
 query['targetLanguage'] = sdkData.language;
 query['selectedText'] = document.getElementById('content').innerHTML;
 query['handler'] = 'changeLanguage_handler';
 callWebService(query);
 currentLanguage = sdkData.language;
 }

 function changeLanguage_handler(xmlObject)
 {
 document.getElementById('content').style.visibility = 'visible';
 document.getElementById('content').innerHTML = getTextNode(getXPath(xmlObject,"//translation")[0]);
 document.getElementById('title').innerHTML = languageReference[currentLanguage];
 thisWindow.setTitle(languageReference[currentLanguage]+" Window Title");
 }

</script>

</head>

<div id="title"></div>

<p/>

<div id="content" style="visibility: hidden;">
 As the name implies, an air mass is a mass of air that has
 relatively uniform characteristics with respect to temperature,
 and moisture. Air masses are often characterized by both their
 temperatures and their humidities. Air masses can basically be
 classified as warm or cold with respect to temperature and moist
 or dry with respect to humidity. The characteristics of an air
 mass are determined by the region over which it formed. For
 instance, during the winter, when the nights are long and frigid
 over the Polar regions, the air tends to become relatively
 uniform. A very cold and dry air mass develops. Occasionally,
 pieces of these air masses will break free and be transported by
 the jet stream.
</div>

<body>
</body>
</html>

Big Picture Conclusions

By isolating the language chooser into its own application, we are able to take advantage of the concept of UcompOS Continuum Events.  In our implementation, when the user changes their operating language, the UcompOSGlobalManagerProxy‘s changeLanguage(); method is invoked, which causes a UcompOS Continuum Event to be dispatched.

Therefore, we could have an unlimited number of UcompOS applications or sub-applications running, all of which employed their own custom logic and behavior when encountering a single language change event that originated in our Controller application.

Screen Capture

Below is a look at our implementation in operation:

Demo

How UcompOS Flash/Flex Applications are Sandboxed in the UcompOS Portal

There are numerous paradigms for launching UcompOS Applications in the UcompOS Portal.

In many instances, the UcompOS Application itself will be a non-visual entity thought of as perhaps the Model and Controller in an MVC style implementation and then the UcompOS Application would launch individual sub-applications in UcompOS Window, UcompOS Browser Window, or UcompOS Artifact instances which could be considered the View in the MVC implementation.

A UcompOS Application can also be an AIR application running on the desktop launched by the UcompOS Portal and also, a UcompOS Application can be launched immediately into a UcompOS Window or UcompOS Browser Window instance by implementing specific attributes in the root of the UcompOS Application’s application manifest.

The specific implementation details of SWF-based UcompOS content being loaded as a UcompOS application or sub-application into the UcompOS Portal warrants discussion.

If you’re an experienced Flash/Flex developer, you may come to the UcompOS RPF with a pre-conceived idea about how things are implemented and how you would go about building rich experiences.

There are 3 different scenarios where SWF content will be loaded directly into the UcompOS Portal:

  1. The SWF content represents a UcompOS Application that is loaded into the UcompOS Portal run-time.  In this case the SWF content is a non-visual entity.  It gets loaded into a SWFLoader with its visible property set to false that is attached directly to the UcompOS Portal as a child.  This application then likely is involved with launching sub-applications into UcompOS Window, UcompOS Browser Window, or UcompOS Artifact instances.
  2. The SWF content represents a UcompOS sub-application that is loaded into a UcompOS Window instance.  In this case, the SWF content is a visual entity.  It gets loaded into a SWFLoader and the SWFLoader is attached as a child to a UcompOS Window instance.  A UcompOS Window instance is derived from a class that extends the MDIWindow class from the mdi package in the FlexLib project.  And of course MDIWindow extends Panel.
  3. The SWF content represents a UcompOS sub-application that is loaded into a UcompOS Artifact instance.  In this case, the SWF content is a visual entity.  A UcompOS Artifact is actually a VBox implementation that gets attached to the UcompOS Portal and then the SWFLoader is attached as a child to the VBox instance.  The UcompOS Portal is a Flex 4 application with the Halo theme compiled so that is how I am using VBox here.

Here’s the important thing to understand about the SWFLoader instances implemented in all 3 of the above scenarios.  They are implemented in one of two “sandboxed” configurations.

If you are creating a Rich Portal Application and your intentions are to load two separate UcompOS Applications into the UcompOS Portal and then do some sort of coding where your accessing something like FlexGlobals.topLevelApplication, this will not work.

All communication with other entities in the UcompOS RPF should be accomplished exclusively via the communication protocols in the UcompOS SDK using implementations such as Proxy Components and public API methods exposed in Services Dictionaries.

The goal is to keep the UcompOS Portal as “dumb” as possible and enable it to focus exclusively on being really good at its base core objectives which are:

  • An MDI (Multiple Document Interface)
  • Style and aesthetic presentation management
  • Artifact model for widget-like implementation
  • UcompOS Application run-time
  • Event Dispatchment architecture

The classes UcompOSArtifactProxy and UcompOSWindowProxy each have Boolean sandbox parameters.  Also, the root <application/> element in an application manifest has a sandbox attribute which accepts values of true or false.

The default condition if you don’t set the sandbox parameter is true.

From an implementation point of view, all SWFLoader instances attached to the UcompOS Portal have the trustContent set to true.  This may be something I rethink when moving the UcompOS RPF project to Beta but at least in my main UcompOS RPF application I am building, the domain that I serve the UcompOS Portal from will be the exclusive thing I serve from that domain as I am interested in creating the a strong degree of disaggregation. (Of course you should have a solid understanding of policy files (such as crossdomain.xml)).

In the case where the sandbox property is set to true (the default condition), the SWFLoader‘s loadForCompatibility property is also set to true.

This creates a situation where the loaded SWF application is loaded into a sibling ApplicationDomain relative to the UcompOS Portal SWF application.

The loadForCompatibility property addresses the need for a SWF to be able to load child SWFs created with different versions of Flex.

For instance, if you tried to load a Flex 3 UcompOS application or sub-application into the UcompOS Portal with its sandbox set to false, you’ll get run-time errors.

So then when or why would you want to load a UcompOS SWF application or sub-application with its sandbox property set to false?

Primarily only in instances when you wanted to implement drag and drop functionality across the boundaries of a UcompOS sub-application.

If all the drag and drop functionality is within the boundaries of the SWF, then the sandbox setting is irrelevant.

However, suppose you have two UcompOS SWF sub-applications loaded into UcompOS Window instances and you want to enable items to be dragged and dropped back and forth between them.  This would require you to set the sandbox property to false.  Also, this would require you to build your applications with Flex 4 (although I admittedly have yet to try implementing drag and drop across two different non-sandboxed Flash CS5-created applications).

In an upcoming tutorial, I’ll show a demo of building a UcompOS-based file management system like the one I have built for Educator 2 that enables drag and drop between multiple UcompOS Window instances as well as drag and drop from a UcompOS Window instance to a UcompOS Artifact instance.

The key fact to ascertain here is that strong command of the UcompOS SDK and how it is utilized to send information back and forth between entities in the UcompOS Continuum is compulsory to your developing the most powerful and effective Rich Experiences.

A Framework for Easily Managing UcompOS Applications

As I’ve worked with the UcompOS platform since its Public Alpha release, I have come to be impressed with its flexibility in bringing a lot of different applications together into one portal system.  However, as I built and tested various applications, it became very apparent that I needed to take a few steps back and think about a framework for deploying applications or risk becoming engaged in a never-ending battle with the following tasks:

  • Editing static dock manifest files
  • Keeping application manifest files between applications straight
  • As the number of applications increases, easily finding the files I need to change without worrying about breaking another application becomes a challenge
  • Deploying updated versions of the UcompOS runtime without accidentally deleting or overwriting application content
  • Managing permissions to applications for different users

These issues were tackled in a fairly systematic manner.  My first logical step was to get rid of the static dock manifest and move that to some application code that generates the dock manifest from a database.  For my UcompOS implementation, information for applications that go on the dock menu is pulled from a very simple table that looks like this:

database_table

The Application_ID field is just a numerical value indicating the identifier of the application.  It is the primary key for the database and auto increments as new applications are installed.  The Application_Descriptor field is very simple, in function to the “title” attribute in your application manifest.  The Background and Default_State fields contain the values each application should have when they are added to the dock manifest file dynamically.  The Directory_Path field requires a bit of explanation.  What I’ve done is create a folder called “applications” in my UcompOS implementation where all applications reside:

project

The Directory_Path field is the name of the folder where each of my UcompOS applications is launched from.  The final field, Is_Global, is a field that indicates whether or not the application should be globally accessible to all users of my UcompOS Portal or not.  Note that if this field is set to false, I have another database table that contains the list of users who have access to the application.

This database is managed through a front-end that grants/denies access to applications based on the selection of a checkbox (Checking a box calls an AJAX function that automatically adds/removes permissions to various applications) like in the screenshot below:

roles

With all this in mind, the script that generates the UcompOS dock manifest file performs the following actions:

  1. Add all of the global applications in my applications table to the dock manifest
  2. Retrieve the list of which applications the user has access to, and add those applications to the dock manifest
  3. Return the entire dock manifest file to the UcompOS main container

You will notice above that I did not provide a filename for each application’s manifest file (just a directory path).  This was an intentional decision, as I chose to have a convention where the name of the application manifest file would be in a sub-folder called “manifest” under each application’s folder, and that the application manifest filename would be the same for each application.  This makes it very easy for me to easily identify the application manifest for each application, and helps maintain consistency across my UcompOS applications.

manifest

In my case, this application manifest for each of my UcompOS applications is named “getAppManifest.php”, and it is a simple script that returns the XML application manifest for the application.  In it, the file does a security check to make sure that the user is logged in and that they have permission to access the application (if the application isn’t global).  If everything checks out, then gatAppManifest.php spits out the application manifest for the application.

I should note that, for very practical reasons, I chose not to place the information for each application manifest file into a database table.  While this was certainly a consideration, the realization I came to was that this was going to be just too cumbersome, especially if you factor in the possibility of multiple languages.  Also, I considered the fact that this file is fairly static in nature, and wouldn’t need to be managed all that often.  Ultimately, I felt that there wasn’t going to be much of a difference time-wise between managing this manually or through a database interface.  For my framework that stresses ease of use, managing the application manifest via straight XML presented a far more straightforward path.

Before I close, I wanted to briefly touch on the file structure I have in place for my implementation.  By having each application compartmentalized in its own subfolder, it is much easier to troubleshoot and find issues with each application without worrying about breaking anything else.  Further, it allows me to do a simple drag and drop operation to deploy new applications in my UcompOS framework (I have a simple function in my application manifest file that adds the new application to the Application database if it doesn’t exist, and sets up any auxiliary tables needed for the application.  I also have been able to create several reusable templates I can leverage or when I begin work on a new UcompOS application).  Ultimately, the framework I’ve put into place solves all of the issues I mentioned above and greatly simplifies the application deployment  process, allowing me to focus on application functionality instead of the mechanics of application deployment, which for me, is what it’s all about.

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.

The Mechanics of HTML Applications in the UcompOS RPF

When I set out to build the application (the Educator 2 E-Learning Enterprise Management System) that led me to build the UcompOS RPF, I was operating under some very simple premises.

One such premise is, to the maximum extent possible, I didn’t want to be handcuffed exclusively to any one particular technology.

While I did make the decision to make the UcompOS Portal (i.e. the “Main Container”) a Flex 4 application (and I am very comfortable with this decision), as far as the sub-applications that would be launched inside or alongside the UcompOS Portal, I simply felt I absolutely needed to be able to work with as wide of a canvas as possible and for me this includes Flex, Flash, HTML/JavaScript/CSS, Adobe AIR for desktop UcompOS applications and even Microsoft Silverlight.

But any of these technologies need be able to interact with each other seamlessly such that what particular technology a UcompOS application or sub-application was constructed with was irrelevant in the context of the overall UcompOS Continuum.

In a full-fledged UcompOS implementation that has multiple UcompOS Applications all working in conjunction with each other, each application, sub application, and the UcompOS Portal itself is a player I refer to as an entity.

For an entity to be able to talk to other entities or execute API commands on other entities, it must have the UcompOS SDK installed.  The download for the UcompOS SDK contains 3 resources for Flash/Flex, AIR, and JavaScript developers.

The Flash/Flex SDK is a SWC that has no Flex dependencies so you can use it interchangeably in Flash as well as Flex applications, however, the Flash/Flex SDK is based on ActionScript 3 and at this point I don’t yet have any intention to release an ActionScript 2 SDK (though there still are ways to involve ActionScript 2 applications in UcompOS implementations and that will be covered in a future posting).

The AIR SDK is a SWC file that has some AIR 2.0 dependencies so that will only compile in an application that has the AIR 2.0 SDK at its disposal.

The JavaScript SDK is comprised of 2 files: UcompOSSDK.js and UcompOSSDK.swfUcompOSSDK.js needs to be included in a UcompOS HTML Application <SCRIPT/> element and the file can be placed on any webserver – even on a domain different than the domain hosting the UcompOS Application.

However, the UcompOSSDK.swf file MUST be served on the SAME domain as the domain that is serving the UcompOS HTML Application.

By default, the UcompOS SDK will look for the UcompOSSDK.swf file in the root of the webserver – i.e. at an absolute path of /UcompOSSDK.swf.  This however can be changed by setting the basePath variable in your HTML Application’s JavaScript code to a relative or absolute path – for instance:

basePath = ‘./’;

would tell the UcompOS SDK that the UcompOSSDK.swf file can be found in the same directory as the HTML Application.

In my post yesterday I discussed the fact that for browser based content, UcompOS applications use the LocalConnection infrastructure of the Flash Player as their communication medium (UcompOS AIR Applications use the new AIR 2.0 ServerSocket implementation).

So if the UcompOS Continuum is based on the LocalConnection which is a Flash Player implementation, how then do UcompOS HTML Applications participate in UcompOS transactions?

The answer is using the UcompOSSDK.swf as a Proxy to the UcompOS Continuum.

When the UcompOSSDK.js file is implemented into a UcompOS HTML Application, the UcompOSSDK.swf file is loaded as an invisible element into the page via DHTML.

The UcompOSSDK.swf file is actually a UcompOS Application with the UcompOS SDK incorporated into it.

The UcompOSSDK.swf application utilizes a Proxy Component (more on Proxy Components in a future post) called JavaScriptCommand.  The UcompOS JavaScript SDK serves as a traffic manager between a UcompOS Application’s internal implementation and the UcompOSSDK.swf application.  Then the UcompOSSDK.swf application and its JavaScriptCommand Proxy Component serves as a proxy to the UcompOS Continuum.

If all this sounds complicated, well, it is.  It took a lot of time to think through the implementation details and to develop, test, and perfect them.  But once you get your head around it, it is very easy to implement.

For the most part, the mechanics involved with leveraging the UcompOS JavaScript SDK are very similar to those involved with the UcompOS AIR and Flash/Flex SDK.

ActionScript 3 and JavaScript are different languages though.  For starters, ActionScript 3 is a strongly typed language and JavaScript is not.  Also, implementing Object Oriented design patterns in JavaScript is more convention than strict procedure so there are subtle differences I’ll cover in this blog as the project evolves.

To get started building simple UcompOS HTML applications, you really only need to know a very basic amount of JavaScript.  To build full fledged powerful UcompOS HTML applications however that implement Services Dictionaries and Proxy Components (I’ll devote separate postings to each of these exciting topics in the next week), you do need to invest some time into learning Object Oriented Programming conventions in the JavaScript programming language.

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.