Uploading Files to a UcompOSArtifactProxy Instance

In a major UcompOS Portal Application I am building, I place UcompOS Artifact instances that represent file volumes on the UcompOS Portal. Over this past weekend, I found myself with the need to enable the user to right-click on the file volume artifacts (revealing their context menus) and choose an “Upload Files” option with the goal of providing the user a way to upload files directly to the root directory of the particular file volume.

My initial approach to this was to attach a Context Menu to the artifact instances with an “Upload Files” option.  I then created an event listener to listen for the UcompOSArtifactProxy.MENU_ITEM_SELECT event dispatched by the UcompOSArtifactProxy instance.

Once this event is dispatched, I reasoned I could then create a FileReferenceList instance and then call its browse() method and go from there.

However, when I attempted this, I was reminded of an important detail when an error was thrown once I called the FileReference.browse() method.

Just like the launching of AIR applications as well as the entry into Full Screen Mode, the opening of the file browse dialogue by the Flash Player must succeed a user-triggered mouse event.

In the context of the UcompOS Continuum, the entity where the mouse event occurs is the UcompOS Portal.  This is a completely separate entity from the code that is calling the FileReference.browse() method.

In my implementation, I have a Flash application that is running as a background application that sets up the aforementioned UcompOS Artifact instances that represent file volumes.

So when the user right clicks on the artifact and selects the Context Menu item, they are actually operating on the UcompOS Portal itself.

An SDKEvent is then dispatched to the background application and then what follows is the call to FileReferenceList.browse().

However, as far as the Flash Player is concerned, in that scenario, the call to FileReferenceList.browse() does NOT proceed a user-triggered mouse event because the mouse event occurs in a totally different scope.

So I have engineered a new process into the UcompOS Portal to enable the goals I described above.

I think the use case I am speaking to here is one that has good merit to be repeated by many developers – i.e. a widget that you can upload files to.  I can envision many scenarios where this could be useful such as file conversion utilities for one.

The model I have developed involves creating an uploadFiles property on the UcompOSArtifactProxy‘s data Object property.

The value of this uploadFiles property must be the same String value as the label placed on a Context Menu item that is attached to the artifact.

What will happen in this case, when the user selects the context menu option on the artifact on the UcompOS Portal, the file browse dialogue will open, and the user will be able to select multiple files.

After the user selects the files, what happens next is very important.

The UcompOS Portal will dispatch to the UcompOSArtifactProxy instance an SDKEvent for each attached file.

The SDKEvent‘s data property will have two properties: fileName:String and fileData:ByteArray, i.e. the name of the file and the contents of the file as a ByteArray.

From here you can do whatever you need to do with this information including upload the file to a remote server, do some sort of conversion, or anything else your specific use case requires.

Below, is a very simple code-based example of how you can create an Artifact and the user can change the artifact’s icon representation by uploading a new image to it.

The application is a UcompOS Flash application loaded into the UcompOS Portal as a background application.

	import flash.display.Sprite;
	import com.ucompass.ucompos.sdk.proxycomponents.UcompOSArtifactProxy;
	import com.ucompass.ucompos.sdk.SDKClient;
	import com.ucompass.ucompos.sdk.events.SDKEvent;
	import flash.events.Event;
	public class Main extends Sprite
		private static const UPLOAD_LABEL:String = "Upload a new artifact image";
		public function Main()
			// Instantiate the UcompOS SDK
			// Create a UcompOS Artifact Proxy instance
			var artifact:UcompOSArtifactProxy = new UcompOSArtifactProxy();
			// Listen for uploaded files
			// Initialize the artifact using a pre-defined image
			artifact.add("RIGHT CLICK ON ME!",null,"http://desktop.ucompass.com/UploadToArtifact/cloud-48x48.png",100,100,true,true,{uploadFiles:UPLOAD_LABEL});
			// Establish the context menu on the artifact with an Upload option
			artifact.setContextMenu(new XML(""));
		private function uploadHandler(event:SDKEvent):void
			var artifact:UcompOSArtifactProxy = event.target as UcompOSArtifactProxy;
			// Replace the artifact image with the content of the uploaded file
			// Show the name of the uploaded file as the label on the artifact

Also, here is a link to a movie that shows the simple application in action.

Overriding the UcompOS Default MenuBar Item

The Menu Bar on the UcompOS Portal by default has a built-in menu item as displayed below:


You can override this default Menu Bar item in one of two ways.

First, in the application manifest for a particular application, you can specify the model for the Menu Bar that should be present when the application is in focus.

A sample Menu Bar model for a very simple File Management application may look something like this:

	<menuitem label="File">
		<menuitem label="Open" data="open"/>
		<menuitem label="Close" data="close"/>
		<menuitem label="Quit" icon="http://apps.ucompass.com/exit.png" data="quit"/>

As a relevant aside, the UcompOSWindowProxy has a setMenuBar(); method that accepts an XML object as input of the same form shown above. This lets you specify the model for the Menu Bar that should be in display while a particular window is in focus.

So you can have multiple windows spawned by the same UcompOS application all with different Menu Bar implementations. This is a very important capability.

What if you want to override the default UcompOS menu item and have 100% unique branding.

You can do this by building a baseMenu model into the application manifest.

For instance, my Educator 2 Menu Bar default Menu Bar item looks like this:


Here is the relevant code from my Application Manifest that articulates the base menu item:

	<menuitem label="" icon="http://applications.ucompass.com/Educator2PortalFoundation/images/Educator2_Menu_Bar_Icon.png">
		<menuitem label="About Educator 2" data="About Educator 2"/>
		<menuitem type="separator"/>
		<menuitem label="Logout" data="Logout" />

The setMenuBar(); method of the UcompOSMenuBarProxy class also has a second Boolean parameter named baseMenu. When you set a Menu Bar and pass true as the value for this parameter, that model will override the default UcompOS MenuBar implementation.

Overriding the default UcompOS MenuBar is just one of many ways to create a 100% unique and customized experience for users of your Rich Portal Application.

Self-Referencing Proxy Components

The AbstractProxyComponent class in the UcompOS SDK must, by strict convention, be the superclass for all Proxy Components. Understanding the mechanics of AbstractProxyComponent and its public properties and methods is a crucial step in building the most powerful Proxy Components that promote richer and more engaging experiences for users of your Rich Portal Application.

In this post, I will touch on one of the public properties of AbstractProxyComponent, self, and explain its purpose and provide a use-case scenario.

As you know, in the context of the UcompOS Continuum, the UcompOS Portal is simply one of X UcompOS entities, each of which have the UcompOS SDK implemented.

The UcompOS Portal sponsors a host of public API methods and the UcompOS SDK has been equipped with a batch of Proxy Components that serve as clients that can be used in your own UcompOS Applications to connect to these public API methods.

At the current time, the self property on AbstractProxyComponent may seem tightly coupled to the UcompOS Portal’s Proxy Components and specifically, to two of those Proxy Components: UcompOSWindowProxy and UcompOSArtifactProxy. However, as the UcompOS RPF continues to expand, the self property on a Proxy Component will take on increasingly significant meaning.

Right now however, the UcompOSWindowProxy and UcompOSArtifactProxy provide a very good model with which to illustrate the purpose of this self property.

As you know, when you create an instance of UcompOSWindowProxy and call its add(); method, you are launching a UcompOS Window on the UcompOS Portal and you are specifying the URL of the content that should be loaded into this window.

Behind the scenes, when the UcompOS SDK loads this content to the UcompOS Window, it passes the content some crucial information that that content will use to become a member of the UcompOS Continuum thereby being able to participate in SDK transmissions with other entities.

Here’s an interesting question:

What if you load some content into a UcompOS Window, and then you want to reference the UcompOS Window that the content is loaded into from the content itself?

The answer to this is you would create a UcompOSWindowProxy instance and then set its self property to true.

As an example of how I have used this capability, I have created a Rich Text Editor for my Educator 2 application I am building on top of the UcompOS RPF. This editor is a Flex 4 implementation.

In Educator 2, by strict convention, all SWF content I load into UcompOS Window and UcompOS Artifact instances is loaded in sandboxed configurations and I rely 100% on SDK transmissions for communication with other entities (the exception is drag and drop which I talked about in this posting).

The challenge then becomes, how do I resize the editor? To resize the editor, the user isn’t going to actually resize the editor itself, rather, the UcompOS Window instance the editor is loaded into. Since my content is sandboxed, I can’t access the parent container the content is loaded into using traditional scripting from within my Editor application.

The solution is to create a reference to a UcompOSWindowProxy and set its self property to true.

Let’s take a look at some code here that is similar to what you’d see in my editor application:

private function init(event:FlexEvent):void
	// Instantiate the UcompOS SDK
	SDKClient.getInstance(this,new ServicesDictionary());
	// Create a UcompOS Window Proxy instance
	var w:UcompOSWindowProxy = new UcompOSWindowProxy();
	// Create a self-reference - w in this case becomes a reference to
	// the UcompOS Window instance the content in scope is loaded into
	w.self = true;
	// listen for window resize events
// the SDKEvent instance dispatched to this handler following
// a window resize operation contains the new width/height of the
// UcompOS Window - the width and height of the content viewing
// portions of the UcompOS Window are housed in the event.data.width
// and event.data.height properties
private function resizeHandler(event:SDKEvent):void
	var w:UcompOSWindowProxy = event.target as UcompOSWindowProxy;
	// suppose my editor component is a variable named myEditor
	myEditor.width = event.data.width;
	myEditor.height = event.data.height;

These same mechanics can be leveraged in UcompOSArtifactProxy instances.

In fact, in one of my earliest UcompOS Video Tutorials entitled Building a UcompOS Weather Channel Widget, we saw this technique.

In that implementation, I created a self referencing UcompOSArtifactProxy instance so I could attach a Context Menu to the UcompOS Artifact and capture user selections on this Context Menu.

Here is a very simple example of a Flash CS4/CS5 UcompOS Application that leverages this principle:

	import flash.display.Sprite;
	import com.ucompass.ucompos.sdk.SDKClient;
	import com.ucompass.ucompos.sdk.proxycomponents.UcompOSArtifactProxy;
	import com.ucompass.ucompos.sdk.events.SDKEvent;
	public class Example extends Sprite
		public function Example()
			var sdkClient:SDKClient = SDKClient.getInstance(this);
			var artifact:UcompOSArtifactProxy = new UcompOSArtifactProxy();
			artifact.self = true;
			artifact.setContextMenu(new XML(""));
		private function contextMenu_handler(event:SDKEvent):void
			trace("User selected "+event.data.label);