modifying the contents of a PasteOperation in Flex 4 - apache-flex

I need to capture and modify the contents of a paste operation in my Flex 4 application. I am listening for the TextOperation.CHANGING event, pulling out the PasteOperation, and setting its textScrap property. Everything seems to be working, except that after I modify the textScrap, a newline character is added to the paste. I have created some sample code that illustrates the simplest version of the problem. I am not actually changing the copy, I am grabbing the existing textScrap's textFlow, creating a new TextScrap with it, and setting it on the PasteOperation. I did this to rule out TextFlow creation as the problem:
<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" minWidth="955" minHeight="600">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import flash.desktop.Clipboard;
import flash.desktop.ClipboardFormats;
import flashx.textLayout.edit.TextScrap;
import flashx.textLayout.elements.TextFlow;
import flashx.textLayout.operations.PasteOperation;
import flashx.textLayout.tlf_internal;
import spark.events.TextOperationEvent;
use namespace tlf_internal;
protected function textArea_changingHandler(event:TextOperationEvent):void
{
if (event.operation is PasteOperation)
{
var pasteOp:PasteOperation = event.operation as PasteOperation;
pasteOp.textScrap = new TextScrap(pasteOp.textScrap.textFlow);
}
}
]]>
</fx:Script>
<s:TextArea id="textArea" changing="textArea_changingHandler(event)"/>
</s:Application>
Thanks in advance,
Gerry

This appears to be a bug that Adobe fixed in sdk 4.6.
As some additional information, replacing the pasteOp.textScrap line above with:
pasteOp.textScrap = pasteOp.textScrap.clone() used to throw a null pointer exception, and in 4.6 that works too now.
Also, this bug only appeared when the textarea / textinput was empty. if there was something already in there, everything worked as expected.

Related

How to detect if font is applicable on text layer or not before applying the font?

I created a panel in flex which will have 2 combo-boxes that will display system font family and font styles and when user selects any font family or style from the combo-box the font gets applied on the selected text layer. But when I try to apply few fonts for eg Euro sign then the text in the selected text layers become all rectangles. I found that Character panel of Photoshop does not apply the font(Euro sign) on the selected text layer.
Is there any method in flex which can help us detect whether a font is applicable on the selected text layer or not?
Thanks
For your Q. I need a method which can tell me either a system font can be applied or not?
Here I have sample where you can read System Font and check on combobox if that font is available in system font or not. Please find below 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/mx" minWidth="955" minHeight="600">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
private var systemFontsCollection:ArrayCollection = new ArrayCollection();
private function getSystemFont():void
{
var fonts:Array = Font.enumerateFonts(true).sortOn("fontName");
for (var i:int = 0; i < fonts.length; i++) {
systemFontsCollection.addItem(new String(fonts[i].fontName));
}
}
private function init():void
{
var fontName:String = fontName.selectedLabel;
if(systemFontsCollection.contains(fontName))
{
trace(" ----System Font is applied ----");
}
else{
trace(" ----System Font is NOT applied ----");
}
}
]]>
</fx:Script>
<mx:Form>
<mx:FormItem label="Font name:">
<mx:ComboBox id="fontName" change="init();" creationComplete="getSystemFont()">
<mx:dataProvider>
<fx:Array>
<fx:String>Arial</fx:String>
<fx:String>ArialEmbedded</fx:String>
<fx:String>Verdana</fx:String>
<fx:String>VerdanaEmbedded</fx:String>
</fx:Array>
</mx:dataProvider>
</mx:ComboBox>
</mx:FormItem>
</mx:Form>
</s:Application>

Flex 4 AIR APP unloading module the proper way

I've been looking all over google for this but I cannot find a good answer.
I am using flex 4 and building an air app using modules (there will be plenty of modules because this is a big project).
I managed to load modules in a titlewindow that is called by popupmanager but when the titlewindow is closed the module is not unloaded (garbaged) -- I checked this using the profiler in flasbuilder.
Here is my code, I need to know if I am going in the right direction using modules before getting to much in the project.
Thanks to all
Main APP: MXML
<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/mx"
xmlns:tblusersservice="services.tblusersservice.*"
xmlns:valueObjects="valueObjects.*"
xmlns:tbluserservice="services.tbluserservice.*"
width="100%" height="100%" applicationComplete="checkForUpdate()" preinitialize="nativeWindow.maximize();" currentState="login">
<fx:Script source="includes/_loadtracker.as"/>
<s:Panel id="panelmain" includeIn="mainmenu" left="5" width="100%" height="100%" resizeEffect="Resize" title="Main menu">
<s:Image id="companymenu" right="15" top="130" width="118" height="93" buttonMode="true"
click="loadmodule('mod_company', 'Company Information', 931, 446);" source="assets/company.png" useHandCursor="true"/>
</s:Panel>
</s:WindowedApplication>
_loadtracker.as:
// ActionScript file
import flash.filesystem.*;
import flash.events.ErrorEvent;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.display.*;
import air.update.ApplicationUpdaterUI;
import air.update.events.UpdateEvent;
import mx.controls.Alert;
import mx.managers.PopUpManager;
import mx.rpc.events.ResultEvent;
import spark.components.TitleWindow;
import valueObjects.*;
import flash.desktop.NativeApplication;
// Open the pop-up window.
private function loadmodule(modname:String, modtitle:String, modwidth:int, modheight:int):void {
// Create a non-modal TitleWindow container.
settings.moduletoload = modname;
var titleWindow:TitleWindow=
PopUpManager.createPopUp(this, showmodules, true) as TitleWindow;
titleWindow.title = modtitle;
titleWindow.width = modwidth;
titleWindow.height = modheight + 35;
PopUpManager.centerPopUp(titleWindow);
}
showmodules.mxml
<s:TitleWindow xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" width="400" height="400" creationComplete="initModule()" close="handleCloseEvent()">
<fx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.core.IVisualElement;
import mx.events.ModuleEvent;
import mx.managers.PopUpManager;
import mx.modules.IModuleInfo;
import mx.modules.ModuleManager;
import mx.rpc.events.ResultEvent;
import services.tbluserservice.*;
public var info:IModuleInfo;
public var modclosed:Boolean = false;
private function initModule():void {
this.addEventListener("foobar", handleCloseEventmodule);
info = ModuleManager.getModule("/modules/"+settings.moduletoload+".swf");
info.addEventListener(ModuleEvent.READY, modEventHandler);
info.load(null, null, null, moduleFactory);
}
/* Add an instance of the module's class to the display list. */
private function modEventHandler(e:ModuleEvent):void {
this.addElement(info.factory.create() as IVisualElement);
}
// Handle the close button and Cancel button.
public function handleCloseEvent():void {
PopUpManager.removePopUp(this);
info.unload();
info.release();
info = null;
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
</s:TitleWindow>
mod_company.mxml
<s:Module xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:tblcompanyservice="services.tblcompanyservice.*"
xmlns:valueObjects="valueObjects.*"
width="931" height="446"
creationComplete="LoadData()">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
protected function dataGrid_creationCompleteHandler(event:FlexEvent):void
{
getAllTblcompanyResult.token = tblcompanyService.getAllTblcompany();
}
]]>
</fx:Script>
<fx:Script source="../includes/_company.as"/>
<fx:Declarations>
<tblcompanyservice:TblcompanyService id="tblcompanyService"
fault="Alert.show(event.fault.faultString + '\n' + event.fault.faultDetail)"
showBusyCursor="true"/>
<s:CallResponder id="getTblcompanyByIDResult" fault="Alert.show(event.fault.faultString + '\n' + event.fault.faultDetail)"
result="tblcompany = getTblcompanyByIDResult.lastResult as Tblcompany"/>
<valueObjects:Tblcompany id="tblcompany"/>
<s:CallResponder id="updateTblcompanyResult"/>
<s:CallResponder id="getAllTblcompanyResult"/>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:Label x="81" y="41" text="COMPANY NAME"/>
<s:Label x="81" y="71" text="ADDRESS"/>
<s:Label x="83" y="131" text="CITY"/>
<s:Label x="83" y="161" text="STATE"/>
<s:Label x="83" y="191" text="ZIP"/>
<s:Label x="83" y="221" text="COUNTRY"/>
<s:Label x="582" y="41" text="TELEPHONE"/>
<s:Label x="582" y="71" text="FAX"/>
<s:Label x="582" y="102" text="WATTS"/>
<s:Label x="83" y="276" text="OWNER"/>
<s:Label x="83" y="324" text="LOGO PATH"/>
<s:TextInput id="fNameTextInput" x="185" y="32" width="323" text="{tblcompany.fName}"/>
<s:TextInput id="faddressTextInput" x="185" y="62" width="256" text="{tblcompany.faddress}"/>
<s:TextInput id="faddress2TextInput" x="185" y="92" width="256" text="{tblcompany.faddress2}"/>
<s:TextInput id="fcityTextInput" x="185" y="122" width="256" text="{tblcompany.fcity}" textAlign="left"/>
<s:TextInput id="fstateTextInput" x="185" y="152" width="256" text="{tblcompany.fstate}"/>
<s:TextInput id="fzipTextInput" x="185" y="182" width="81" text="{tblcompany.fzip}"/>
<s:TextInput id="fcountryTextInput" x="185" y="212" width="256" text="{tblcompany.fcountry}"/>
<s:TextInput id="ftelTextInput" x="701" y="32" text="{tblcompany.ftel}"/>
<s:TextInput id="ffaxTextInput" x="701" y="62" text="{tblcompany.ffax}"/>
<s:TextInput id="fwattsTextInput" x="701" y="92" text="{tblcompany.fwatts}"/>
<s:TextInput id="fownerTextInput" x="185" y="266" width="418" text="{tblcompany.fowner}"/>
<s:TextInput id="flogopathTextInput" x="185" y="314" width="644" text="{tblcompany.flogopath}"/>
<s:TextInput id="fidTextInput" x="224" y="379" text="{tblcompany.fid}" visible="false"/>
<s:Button id="button" x="79" y="379" label="Save" click="button_clickHandler(event)"/>
<s:DataGrid id="dataGrid" x="158" y="242"
creationComplete="dataGrid_creationCompleteHandler(event)" requestedRowCount="4">
<s:columns>
<s:ArrayList>
<s:GridColumn dataField="fid" headerText="fid"></s:GridColumn>
<s:GridColumn dataField="fName" headerText="fName"></s:GridColumn>
<s:GridColumn dataField="fowner" headerText="fowner"></s:GridColumn>
<s:GridColumn dataField="faddress" headerText="faddress"></s:GridColumn>
<s:GridColumn dataField="faddress2" headerText="faddress2"></s:GridColumn>
<s:GridColumn dataField="fcity" headerText="fcity"></s:GridColumn>
<s:GridColumn dataField="fzip" headerText="fzip"></s:GridColumn>
<s:GridColumn dataField="fstate" headerText="fstate"></s:GridColumn>
<s:GridColumn dataField="fcountry" headerText="fcountry"></s:GridColumn>
<s:GridColumn dataField="ftel" headerText="ftel"></s:GridColumn>
<s:GridColumn dataField="ffax" headerText="ffax"></s:GridColumn>
<s:GridColumn dataField="fwatts" headerText="fwatts"></s:GridColumn>
<s:GridColumn dataField="flogopath" headerText="flogopath"></s:GridColumn>
<s:GridColumn dataField="femail" headerText="femail"></s:GridColumn>
</s:ArrayList>
</s:columns>
<s:typicalItem>
<fx:Object faddress="faddress1" faddress2="faddress21" fcity="fcity1"
fcountry="fcountry1" femail="femail1" ffax="ffax1" fid="fid1"
flogopath="flogopath1" fName="fName1" fowner="fowner1" fstate="fstate1"
ftel="ftel1" fwatts="fwatts1" fzip="fzip1"></fx:Object>
</s:typicalItem>
<s:AsyncListView list="{getAllTblcompanyResult.lastResult}"/>
</s:DataGrid>
</s:Module>
_company.as
// ActionScript file
//import flash.desktop.NativeApplication;
import flash.events.MouseEvent;
import flash.events.Event;
import mx.controls.Alert;
//import mx.core.Application;
//import mx.core.mx_internal;
import services.tblcompanyservice.*;
import valueObjects.*;
protected function LoadData():void {
getTblcompanyByIDResult.token = tblcompanyService.getTblcompanyByID(parseInt("1"));
}
protected function button_clickHandler(event:MouseEvent):void {
tblcompany.fid = parseInt(fidTextInput.text);
tblcompany.fName = fNameTextInput.text;
tblcompany.fowner = fownerTextInput.text;
tblcompany.faddress = faddressTextInput.text;
tblcompany.faddress2 = faddress2TextInput.text;
tblcompany.fcity = fcityTextInput.text;
tblcompany.fzip = fzipTextInput.text;
tblcompany.fstate = fstateTextInput.text;
tblcompany.fcountry = fcountryTextInput.text;
tblcompany.ftel = ftelTextInput.text;
tblcompany.ffax = ffaxTextInput.text;
tblcompany.fwatts = fwattsTextInput.text;
tblcompany.flogopath = flogopathTextInput.text;
tblcompany.femail = "";
updateTblcompanyResult.token = tblcompanyService.updateTblcompany(tblcompany);
//Alert.show("Modifications saved");
//this.dispatchEvent(new Event("foobar", true));
}
Unloading Flex modules has historically been problematic. Flex 4 and I assume 4.5 started to chip away at the underlying issues to make our lives easier.
When something in your main app maintains a reference to an object in your module, it will prevent your module from unloading. There are many ways this can happen. Flex may still cause some of these problems due to the way it works. But the major headaches have been mitigated (I'd make sure you're on Flex 4.5 though).
You're definitely wise for thinking about this now. Not the choice about whether to use modules, but making sure they are unloading.
The article I linked to is an old post from a Flex SDK developer, while some of those issues may no longer exist the concepts should be enlightening.
Edit
On further review, only one of the things that jumped out at me seem worth looking at:
The script tag in your module may have the same problems that styles can introduce (also could be a red herring). The idea is that the first class that uses this script may be permanently associated w/the script internally by Flex. If that class is a module, it will never unload. As a test, you can try declaring the script tag in the WindowedApplication class as well (even though it's not being used).
The other thing I thought about was bindable variables in your view. But on further review, I can't see how those could be causing a memory leak.
I think the problem is just that you're creating a new TitleWindow each time, and the TitleWindow adds an event listener to the module that is loaded through the module loader and never removes it. In theory, PopupManager.removePopup should also dereference your TitleWindow each time, but, honestly, someone who would write this functionality as a global/static Class probably can't be trusted to adhere to good practice in other places, so you should probably use F3 to look through the code on PopupManager and make sure it's removing any event listeners it added and nulling the reference to your title window. Since it's a static Class, once something talks to it, if it doesn't dereference things properly they will stick around for the life of your app.
Next, you're manually creating an instance of your Module even though you already have one that's loaded. You do a few things (short of removing your event listener) to try to let go of the loader, but you never release the manually created instance. To simplify things a bit, try just adding the loaded module instead of creating an extra one.
Another suggestion is to not use View elements in lieu of a data store. So, instead of binding to the VO, when you get it populate your fields from it. When anything changes, update the VO based on the VO's value. This results in a bit more code, but for one thing, you always know your data is up to date. For another, the data can travel if it needs to, independently of the View. But this is one thing that could help you eliminate the possibility that bindings are holding the VO in memory.
There are also a few things you do that create sort of a faint barnyard smell around your code, and these could also be sources of the problem. For instance, your title window subclass seems to have a reference to settings, even though you haven't given it one. This suggests settings is actually a static Class, and that you've ignored the naming convention that Classes should start with an upper case. More importantly, if you have communication going on in the back channel like this, there's no way to look at your code and determine that you don't have something going on where somehow you've given settings a reference to something that it is holding onto.
You also have what appears to be an undeclared variable, modulefactory, but I'm thinking this is probably a badly-named Class that lives in the same package as your TitleWindow (so there's no import statement for it). Quick word of advice: if you want to get help on forums, following naming conventions wil make it easier for people wanting to help you to unravel what you've done. In this case, there may places that you have "illicit" functionality sidestepping best practice OOP communication, and they're not easy to identify because of the way you name thing.
But ultimately, I think if you go down to just one copy of the module and remove the event listener, you should be able to let go of your Module, which should let you release the VO.

Flex 4.5.1 Add a simple Bitmap or Sprite on new application?

Maybe it is a bad habit which I still have since Flash Professional, but I'm trying to add a simple Sprite or/and Bitmap I just created to an empty Application and it's not happening.
<?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/mx"
minWidth="955" minHeight="600"
creationComplete="application1_creationCompleteHandler(event)">
<fx:Script>
<![CDATA[
import mx.core.FlexGlobals;
import mx.core.UIComponent;
import mx.events.FlexEvent;
protected function application1_creationCompleteHandler( event : FlexEvent ) : void
{
var s:Sprite = new Sprite();
s.graphics.beginFill( 0xFF0000, 0.5 );
s.graphics.drawRect( 0, 0, 100, 100 );
s.graphics.endFill();
this.addChild( s );
}
]]>
</fx:Script>
</s:Application>
Could someone tell me what I am doing wrong and help me correct it?
Try putting your sprite in UIComponent or SpriteVisualElement.
This works for me:
<?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/mx" minWidth="955" minHeight="600"
creationComplete="test()">
<fx:Script>
<![CDATA[
import spark.core.SpriteVisualElement;
private function test():void
{
var sprCont:SpriteVisualElement = new SpriteVisualElement();
sprCont.horizontalCenter = 0;
sprCont.verticalCenter = 0;
var spr:Sprite = new Sprite();
spr.graphics.beginFill(0xFF0000);
spr.graphics.drawCircle(0,0, 100);
spr.graphics.endFill();
sprCont.addChild(spr);
addElement(sprCont);
}
]]>
</fx:Script>
</s:Application>
For some reasons the 's:Application' tags are not shown, but they are there.
HTH,
FTQuest
There are a few things to consider. You don't specify a height or width for your sprite. Won't it default to a height and width of 0; effectively rendering it invisible?
The second thing to note is that I strongly recommend you make use of the Flex Component Lifecycle methods for creating children. Instead of using a creationComplete handler, override createChildren() to create the sprite and add it. It would be common to use updateDisplayList() for the drawing, sizing, and positioning of the component.
The second thing to note is that Application is actually a sprite. Depending on what you're trying to do you could do the drawing directly on the application:
this.graphics.beginFill( 0xFF0000, 0.5 );
this.graphics.drawRect( 0, 0, 100, 100 );
this.graphics.endFill();
I perceive it will be more flexible to use a sprite than to draw directly on the Application; but it depends what you're trying to accomplish.

Can't see contextMenu on UIComponent, but on its subviews in Flex

I have a UIComponent (tried it also with Canvas) and some icons in it (sub views). On the UIComponent I defined some extra ContextMenuItems.
Now when I'm testing it, the context menu appears only on the subviews (icons) with a right-click.
I've checked the documentation but found nothing about required properties for using context menus.
Do you have any ideas why it's only on subviews?
This is probably happening because your UIComponent's (or Canvas') graphics are clean/empty. If the component doesn't have any "content" it will act as transparent, which means the click event will not be caught.
If you are using a Canvas there's a simple way to check this out, try to add some background color and it should work:
<mx:Canvas backgroundColor="#FFFFFF" backgroundAlpha="0.001"/>
I think this is what you're looking for:
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark"
creationComplete="onCreationComplete()">
<fx:Script>
<![CDATA[
private function onCreationComplete():void
{
var menu:ContextMenu = new ContextMenu();
menu.customItems.push(new ContextMenuItem('weee'));
menu.customItems.push(new ContextMenuItem('weee2'));
menu.hideBuiltInItems();
canvas.contextMenu = menu;
}
]]>
</fx:Script>
<mx:Canvas id="canvas" backgroundColor="#000000" height="50%" width="50%" >
<s:Button label="blarg" />
</mx:Canvas>
</s:Application>
Notice how I'm creating a menu, then adding items, which then replaces the contextMenu property. This should work on any object that extends InteractiveObject.
What the problem was is the mouseEnabled="{false}" property in one of the parent-parent containers. I removed it and it works now.

Prefix for element not bound

I am a newbie in Flex development and using Flash Builder 4 with SDK 4. Now I get the error that "the prefix "fx" for element "fx:Style" is not bound" in line number 4.
I searched for it, and it has sth. to do with namespaces, but I can not solve it by myelf.
I have the file called "UserStory.mxml" in the directory "components" to place it via the main.mxml onto the screen:
<fx:Script>
<![CDATA[
import components.UserStory;
private function init():void {
var userStory1:UserStory = new UserStory();
userStory1.x = 100;
userStory1.y = 100;
userStory1.userStoryText = "test";
this.addChild(userStory1);
}
]]>
</fx:Script>
The file in which the error occurs in line no. 4:
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="300" height="150" styleName="userstory">
<fx:Style source="styles/styles.css"/>
<fx:Text x="5" y="5" width="275" height="135" text="{userStoryText}" fontFamily="notes" fontSize="18"/>
<mx:Script>
...
</mx:Script>
</mx:Canvas>
Can someone tell me what's wrong?
As you suspected it is a problem with the namespace. MXML is just XML and in XML you can define namespaces and bind them to a URL. The namespaces are the part before the colon of an XML element and are usually defined on the enclosing element.
If you look at your MXML file you'll see one namespace declaration for the mx namespace:
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" ...
The declaration for fx is missing and that's what the compiler complains about. Add the appropriate definition and you should be fine (see this page for more details):
<mx:Canvas xmlns:fx="http://ns.adobe.com/mxml/2009" ...
Also, if you are using Flex 4 you should review the file as mx:Canvas is a Flex 3 component and as such not directly usable in Flex 4 apps. Have a look at the API docs of Canvas for the Flex 4 SDK.

Resources