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.
package { 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 SDKClient.getInstance(this); // Create a UcompOS Artifact Proxy instance var artifact:UcompOSArtifactProxy = new UcompOSArtifactProxy(); // Listen for uploaded files artifact.addEventListener(UcompOSArtifactProxy.UPLOAD_FILE,uploadHandler); // 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 artifact.setImage(event.data.fileData); // Show the name of the uploaded file as the label on the artifact artifact.setLabel(event.data.fileName); } } }
Also, here is a link to a movie that shows the simple application in action.
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 RXF 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 RXF. 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 w.addEventListener(UcompOSWindowProxy.RESIZE_END,resizeHandler); w.addEventListener(UcompOSWindowProxy.MAXIMIZE,resizeHandler); w.addEventListener(UcompOSWindowProxy.RESTORE,resizeHandler); } // 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:
package { 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("")); artifact.addEventListener(UcompOSArtifactProxy.MENU_ITEM_SELECT,contextMenu_handler); } private function contextMenu_handler(event:SDKEvent):void { trace("User selected "+event.data.label); } } }


