|
In most applications, even very large applications, the entire
base of source code is compiled before release. This recompilation
ensures that all pieces of the applications are using the same APIs.
This model works well for desktop software and software whose releases
are tightly controlled. But it does not always work well in the
Internet model of application development, where applications are
continually updated.
Internet applications are often developed and released gradually,
with new pieces of functionality being added to the application
all the time. To ease application development of this kind, Flex
lets you create multi-versioned applications. A single application
can load multiple sub-applications even if those sub-applications
are compiled with different versions of the Flex framework. Sub-applications
must, however, be compiled with the same or older version of the compiler
that was used to compile the main application.
Using multi-versioned applications is common for sandboxed applications where
more than one group of developers works on different pieces of functionality.
It is also common on very large applications that are continually
improved on and released.
When compiling multi-versioned applications, you should include
the MarshallingSupport class into the main application and sub-applications.
You do this with the includes compiler argument,
as the following example shows: -includes=mx.managers.systemClasses.MarshallingSupport
Using RPC and DataServices-related functionality in your multi-versioned
applications has some limitations. These limitations depend on the
type of remote data access you use: RPC classes with a proxy server,
RPC classes without a proxy server, and DataServices and RemoteObject
functionality. In many of these cases, you should develop sandboxed
applications rather than multi-versioned applications. For more
information, see Using RPC and DataServices classes with multi-versioned applications.
Flex supports multi-versioned applications that were compiled
with version 3.2 of the Flex framework and later. For example, your
main application can be a Flex 4.6 application, and the loaded applications
can be compiled with the following versions of the framework:
If you try to load an sub-application that
was compiled with a more recent version of the framework than the
main application, you will get run time errors if the two applications
use a shared resource whose API changed between versions of the
Flex framework.
In general, a main application that is compiled for Flash Player
11 can load sub-applications that were compiled for Flash Player
11 or Flash Player 10. However, main applications that were compiled
for Flash Player 10 cannot load sub-applications that were compiled
for Flash Player 11.
Sub-applications that are compiled with an older version of the
Flex framework can be loaded either locally (from the same domain
or subdomain, in which case they are trusted) or cross-domain (from
a different domain, in which case they are untrusted by default).
A trusted multi-versioned application will have nearly the same
level of interoperability with the main application as a single-versioned trusted
application. Styles and resource bundles are not shared, but otherwise they
have the same level of interoperability. An untrusted multi-versioned
application has slightly more interoperability than a single-versioned
untrusted application has when loaded. With untrusted multi-versioned
applications, focus management and mouse events work with the main
application.
When you load a multi-versioned application, you set the loadForCompatibility property
of the SWFLoader control
to true. Setting this property instructs the loader
to load the application into a sibling application domain. Applications
that are in sibling application domains each maintain their own
class definitions. They communicate through event passing, if necessary.
For example, if a sub-application must do something that only the top-level
application’s manager can do, then it communicates with the main application
by dispatching an event.
The following sections describe how to develop multi-versioned
applications. They assume that all applications are trusted (loaded
into the same security domain), and loaded into sibling application
domains of the main application. For information about building
applications that are in separate security domains, see Developing sandboxed applications.
Using RPC and DataServices classes with multi-versioned applicationsRPC and DataServices classes are a special case when used
in multi-versioned sub-applications. All applications in the same
security domain must share the same definitions of the RPC and DataServices
classes for messaging to work. In addition, they might also need
to share the same definitions for custom value object classes. This
can be a problem because the only way to ensure that a main application
and a sub-application use the same set of definitions is to load
the sub-application into a child application domain of the main
application, which would prevent multi-versioned applications from
working. As a result, to use RPC classes in multi-versioned applications,
you can do one of the following: - Load the applications
as sandboxed applications
- If you do this, you must call the Security.allowDomain() method
from the main application on the sub-application’s domain in the
SWFLoader control’s complete event handler. You
must also call the Security.allowDomain() method
from the sub-application on the main application’s domain. This
provides the same level of application interoperability as multi-versioned
applications. In the sub-application, you must call the allowDomain() method
early on in the initialization cycle. Use the application’s preinitialize event.
- Use a bootstrap loader
- You define the messaging classes in a bootstrap loader. You
then load the main application into the bootstrap loader. The main
application and its sub-applications can then share those class
definitions.
When you use RPC classes (such as WebService and HTTPService)
without a proxy server, you do not need to load the sub-application
as a sandboxed application or externalize the classes in a bootstrap
class loader. Applications that use these classes without a proxy
server should work as well as any multi-versioned application. Be
sure to that either the URLs for the target services are on the
same server as the main application, or that the target server has
a crossdomain.xml file on it that allows access.
Pop-up controls in multi-versioned applicationsWhen a sub-application launches a pop-up control, it floats
over the entire application, and can be dragged anywhere on the
stage. Pop-up controls are created in the sub-application’s application
domain and passed to the main application's PopUpManager.
Pop-up controls cannot be strongly-typed as IUIComponent, so they
are marshaled from the sub-application to the main application for
display.
Pop-up windows behave as follows in a multi-versioned sub-application
(these behaviors are the same for single-versioned sub-applications):
Launching a modal dialog box dims the entire application,
not just the sub-application that launched it
Centering a pop-up centers it over the entire application,
not just the sub-application
Dragging pop-up controls works over the entire application,
not just the sub-application
Focus shifts to the pop-up when you first launch a pop-up
from the sub-application
The PopUpManager must be linked in to all applications that are
sandbox roots. When using the PopUpManager in a child application,
there must also be an instance of the PopUpManager in the main application.
To link the PopUpManager to a main application that doesn’t use
it, you can add the following code:
import mx.managers.PopUpManager;
private var popupManager1:PopUpManager;
If you do not link a PopUpManager into an application, and a
sub-application in its sandbox requests that it display a modal
dialog box, you might get the following error: No class registered for interface 'mx.managers::IPopUpManager'.
List controls require some additional code when used in sub-applications.
If you have a List control in a sub-application’s pop-up and no
List control in your main application, you must also link the List
class into your main application. In addition, the List control
must have a data provider. You can link an invisible List into your
main application and set its data provider to an empty array, as
the following example shows: <mx:List visible="false" includeInLayout="false" dataProvider="[]"/>
Embedded fonts in multi-versioned applicationsApplications that are in the same application domain are
able to use the same embedded fonts by specifying the font name.
However, if the sub-application is loaded into a different application
domain (as is the case with multi-versioned applications), then
the sub-application must embed the font to use it.
Styles and style modules in multi-versioned applicationsUsing styles and style modules in multi-versioned sub-applications
is the same as using them in sandboxed sub-applications. For more
information on using styles and style modules in sub-applications,
see Styles and style modules in sandboxed applications.
Focus in multi-versioned applications
Cursors in multi-versioned applicationsThe CursorManager class
in the main application and sub-application communicate much like
the PopupManager class. If the sub-application changes the cursor
to a custom cursor, this custom cursor continues to appear when
the cursor is moved outside the sub-application and over the main
application. Calling a method or setting a property on the CursorManager
in the sub-application bubbles up to the main application, and vice
versa.
If a busy cursor is visible while the mouse is over the sub-application,
and you move the cursor to the main application, the cursor remains
as a busy cursor.
Localizing multi-versioned applicationsUsing resource bundles in multi-versioned sub-applications
is the same as using them in sandboxed sub-applications. For more
information on using resource bundles in sub-applications, see Localizing sandboxed applications.
ToolTip objects in multi-versioned applicationsToolTip objects are created in the sub-application’s application
domain and are passed to the main application’s ToolTipManager.
This is an example of marshaling a class across application boundaries.
This behavior applies to error tips and data tips on List objects
in multi-versioned applications as well.
Layouts in multi-versioned applicationsThe main application dictates the area of the screen that
is available to the sub-application for screen layout.
LayoutManagers in different applications run independent of one
another. The applications are not clipped.
Deep linking in multi-versioned applicationsYou cannot access the main application’s BrowserManager directly
from a sub-application that is in a different application domain.
The sub-application’s BrowserManager is disabled. This is the same
for sandboxed and multi-versioned sub-applications. For more information,
see Deep linking in sandboxed applications.
Dragging and dropping in multi-versioned applicationsWhen the sub-application is in the same security domain
as the main application, but in a different application domain,
you can drag list items from a sub-application to a list in the
main application, and vice versa. For this to work across applications,
the class that defines the drop target must be public.
The DragProxy maintains the item’s appearance during the entire
event, regardless of which application the mouse is over. Drag events
are triggered for all source and destination controls, as if they
are in the same application.
In the background, the DragManager generates
the DragProxy in the sub-application's application domain then passes
that DragProxy to the main application's DragManager during the
drag operation.
Strongly-typed objects cannot be passed from the main application
to the sub-application or vice versa. As a result, the DragManager
accepts a DragProxy that is not strongly typed.
All properties and methods defined by the IDragManager interface
are handled through delegation to the main application’s DragManager.
If you drag a generic type object, the object will be of generic
type Object in Flash Player’s application domain. Flex marshals
the properties so that the drag and drop operation works without
having to write any custom code.
If you use a custom class as part of the drop data, that class
cannot be shared as strongly-typed. In that case, override the drop
events and add logic to marshall the data from the drag source to
the drop target.
Listening for mouse events in multi-versioned applicationsMouse interaction between a main application and a sub-application
can be confusing, especially when those events occur in different
application domains. For example, when you click and drag an object
in a sub-application, and then release the button over the main
application, typical Flex mouse events such as MOUSE_UP, MOUSE_DOWN_OUTSIDE,
or MOUSE_LEAVE are triggered but cannot be listened
to directly in the sub-application.
To listen for mouse events across application domains, listen
to all mouse activity in the security domain. To listen, get a reference
to the sandbox root and register your event listeners with that
SystemManager.
When loaded into a separate application domain, the topLevelSystemManager property
refers to the sub-application’s SystemManager because the main application's
SystemManager is in another application domain. As a result, you
do not use the topLevelSystemManager property to
get a reference to the main application’s SystemManager. Instead, you
use the systemManager.getSandboxRoot() method to
get a reference to the top-level SystemManager in the security domain.
From this SystemManager, you can access all mouse activity in the
current security domain.
The following example uses calls to the getSandboxRoot() method
to get references to the top-level SystemManager in the security
domain.
<?xml version="1.0" encoding="utf-8"?>
<!-- apploading/ZoomerPattern3.mxml -->
<s:Application
creationComplete="setup()"
height="250"
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<fx:Script>
<![CDATA[
import mx.core.UIComponent;
import mx.managers.PopUpManager;
[Bindable]
public var data1:Array = ["Ice Cream", "Fudge", "Whipped Cream", "Nuts"];
public var zoomTool:UIComponent;
public function setup():void {
// Draw the zoom rectangle.
zoomWidget.graphics.lineStyle(1);
zoomWidget.graphics.beginFill(0, 0);
zoomWidget.graphics.drawRect(0, 0, 17, 17);
zoomWidget.graphics.endFill();
// Listen for mouse down events.
zoomWidget.addEventListener(MouseEvent.MOUSE_DOWN, zoom_mouseDownHandler);
}
private var lastX:int;
private var lastY:int;
private function zoom_mouseDownHandler(event:MouseEvent):void {
// When the mouse is down, listen for the move and up events.
// The getSandboxRoot() method lets you listen to all mouse activity in your
// SecurityDomain.
systemManager.getSandboxRoot().addEventListener(
MouseEvent.MOUSE_MOVE, zoom_mouseMoveHandler, true);
systemManager.getSandboxRoot().addEventListener(
MouseEvent.MOUSE_UP, zoom_mouseUpHandler, true);
// Update last position of the mouse.
lastX = event.stageX;
lastY = event.stageY;
// Create and pop up the zoomTool. This is the rectangle that is dragged around.
// It must be a popup so that it can float over other content.
zoomTool = new UIComponent();
PopUpManager.addPopUp(zoomTool, this);
var pt:Point = new Point(zoomWidget.transform.pixelBounds.x,
zoomWidget.transform.pixelBounds.y);
pt = zoomTool.parent.globalToLocal(pt);
zoomTool.x = pt.x;
zoomTool.y = pt.y;
zoomTool.graphics.lineStyle(1);
zoomTool.graphics.beginFill(0, 0);
zoomTool.graphics.drawRect(0, 0, 17, 17);
zoomTool.graphics.endFill();
// Hide the rectangle that was the target.
zoomWidget.visible = false;
}
private function zoom_mouseMoveHandler(event:MouseEvent):void {
// Update the position of the dragged rectangle.
zoomTool.x += event.stageX - lastX;
zoomTool.y += event.stageY - lastY;
lastX = event.stageX;
lastY = event.stageY;
var bm:BitmapData = new BitmapData(16, 16);
// Capture the bits on the screen.
// You must use the getSandboxRoot() method here, too, because it gets
// the parent of all of the pixels you are allowed to access.
bm.draw(DisplayObject(systemManager.getSandboxRoot()),
new Matrix(1, 0, 0, 1, -zoomTool.transform.pixelBounds.x - 2,
-zoomTool.transform.pixelBounds.y - 2));
// Create a Bitmap to hold the bits.
if (zoomed.numChildren == 0) {
var bmp:Bitmap = new Bitmap();
zoomed.addChild(bmp);
} else
bmp = zoomed.getChildAt(0) as Bitmap;
// Set the bits.
bmp.bitmapData = bm;
// Zoom in on the bits.
bmp.scaleX = bmp.scaleY = 8;
}
private function zoom_mouseUpHandler(event:Event):void {
// Remove the listeners.
systemManager.getSandboxRoot().removeEventListener(
MouseEvent.MOUSE_MOVE, zoom_mouseMoveHandler, true);
systemManager.getSandboxRoot().removeEventListener(
MouseEvent.MOUSE_UP, zoom_mouseUpHandler, true);
// Replace the target rectangle.
zoomWidget.visible = true;
// Remove the dragged rectangle.
PopUpManager.removePopUp(zoomTool);
}
]]>
</fx:Script>
<mx:HBox>
<mx:HBox backgroundColor="0x00eeee" height="140" paddingTop="4" paddingRight="4">
<mx:Label text="Drag Rectangle"/>
<mx:UIComponent id="zoomWidget" width="17" height="17"/>
<mx:Canvas id="zoom"
borderStyle="solid"
width="132"
height="132"
>
<mx:UIComponent id="zoomed" width="128" height="128"/>
</mx:Canvas>
</mx:HBox>
<mx:List dataProvider="{data1}"/>
</mx:HBox>
</s:Application>
The following example main application
loads the previous example application. It sets the loadForCompatibility property
to true so that the sub-application loads a multi-versioned
application.
<?xml version="1.0" encoding="utf-8"?>
<!-- apploading/MainZoomerPattern3.mxml -->
<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/mx">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<mx:Text text="Cross-Versioning (trusted versioning application):"/>
<mx:SWFLoader id="swf1" loadForCompatibility="true" source="ZoomerPattern3.swf"/>
</s:Application>
|
|
|