detect the size of swf. flex/as3 - apache-flex

I'm creating a map that has points of interest. (POI) When a user mouses over the POI an info bubble pops onto the screen and it loads an swf. I currently have 3 problems. My 4th problem is that this is due Monday 21st! so any help would be greatly appreciated!
I can't detect the size of the swf so that my infobubble will size itself to the size of the swf.
When I mouse over my swf file, it disappears.
I would love to have the my swf file pop up in a layer on its own instead of being on the stage of my main flex file...but i have no clue how to do this.
package com.modestmaps
{
import flash.display.Graphics;
import flash.display.Loader;
import flash.display.Shape;
import flash.display.Sprite;
import flash.filters.BlurFilter;
import flash.geom.Matrix;
import flash.geom.Rectangle;
import flash.net.URLRequest;
import flash.text.TextField;
public class InfoBubble extends Sprite
{
public var textField:TextField;
public var background:Shape;
public var shadow:Shape;
public function InfoBubble(text:String)
{
//I name the instance of my POI marker on my map to the url link of my swf file. So whatever marker i click on the correct url will
this.name = urlLink;
this.mouseEnabled = true;
this.mouseChildren = false;
//this creates a shadow behind my infobubble
shadow = new Shape();
shadow.filters = [ new BlurFilter(16, 16) ];
shadow.transform.matrix = new Matrix(1, 0, -0.5, 0.5, 0, 0);
addChild(shadow);
background = new Shape();
addChild(background);
textField = new TextField();
textField.selectable = true;
textField.multiline = true;
textField.wordWrap = true;
//textField.text = urlLink;
textField.width = textField.textWidth+300;
textField.height = textField.textHeight+288;
//addChild(textField);
var request:URLRequest = new URLRequest(urlLink);
var loader:Loader = new Loader();
loader.load(request);
addChild(loader);
//marker clips are positioned with (0,0) at the given location
//current measurements of swf file w432 h288
//if i could dynamically determine the size of the loaded swf file its position would be automatically calculated
loader.y = -288 - 37;
loader.x = -8;
//marker clips are positioned with (0,0) at the given location
textField.y = -textField.height - 35;
textField.x = -10;
//currently my rectangle's size is determined by the textField size. I don't even use the textfield. I want the rectangle to be drawn using the dimensions of the swf file instead.
var rect:Rectangle = textField.getRect(this);
// get your graph paper ready, here's a "speech bubble"
background.graphics.beginFill(0x12345);
shadow.graphics.beginFill(0x000000);
for each (var g:Graphics in [ background.graphics, shadow.graphics ] ) {
g.moveTo(rect.left, rect.top);
g.lineTo(rect.right, rect.top);
g.lineTo(rect.right, rect.bottom);
g.lineTo(rect.left+15, rect.bottom);
g.lineTo(rect.left+10, rect.bottom+15);
g.lineTo(rect.left+5, rect.bottom);
g.lineTo(rect.left, rect.bottom);
g.lineTo(rect.left, rect.top);
g.endFill();
}
}
}
}
I hope you more skilled coders can help me out. I'm new to flex and as3
Edit: There is no javascript in this file. All of it is AS3.
Edit2: This is the temporary site I am testing it on http://cjbutchershop.com/temp/adtypes/mapTest.swf

You can get the size of your application by doing:
var width:int = Application.application.width;
var height:int = Application.application.height;
With regards to the text disappearing when you hover over the info bubble; you might want to reconsider your approach. Rather than loading an external swf, I have implemented info bubbles for modest maps by adding/removing child objects (like a TextField) to my marker object (which extends Sprite) in response to the appropriate mouse events.

I am new to Flex myself, but i have done something similar while trying out an example while learning.
Basically what i suggest is Open the bubble in a new popup window using the PopUpManager class on MouseOver event on the parent window (on your map).
And show the popup in a TitleWindow Component,also tap the close event on Title window component.That way you will come back to the same page.Hope this helps.
Posting code here
< ? xml version="1.0" encoding="utf-8" ? >
< mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">
<mx:Script>
<![CDATA[
import mx.events.ListEvent;
import mx.controls.Alert;
import mx.managers.PopUpManager;
import mx.rpc.events.ResultEvent;
import mx.collections.ArrayCollection;
[Bindable]
public var photoFeed:ArrayCollection;
public function searchFlickr():void {
photoService.cancel();
var params:Object = new Object();
params.format = 'rss_200_enc';
params.tags = srchTxtId.text;
photoService.send(params);
}
public function resultHandler(event:ResultEvent):void {
photoFeed = event.result.rss.channel.item as ArrayCollection;
}
public function openPanel(levent:ListEvent):void {
var panelCmpObj:panelcomp = new panelcomp();
panelCmpObj.source = levent.itemRenderer.data.content.url;
PopUpManager.addPopUp(panelCmpObj,this,true);
}
public function test():void {
Alert.show('testtest');
}
]]>
</mx:Script>
<mx:HTTPService id="photoService" url="http://api.flickr.com/services/feeds/photos_public.gne" result="resultHandler(event)"/>
<mx:HBox width="362" height="24">
<mx:TextInput id="srchTxtId"/>
<mx:Button label="Search for pics" id="srchBtnId" click="searchFlickr()"/>
</mx:HBox>
<mx:TileList id="imgTileList" dataProvider="{photoFeed}" width="100%" height="100%" itemClick="openPanel(event)">
<mx:itemRenderer>
<mx:Component>
<mx:VBox width="125" height="125"
paddingBottom="5"
paddingLeft="5"
paddingTop="5"
paddingRight="5">
<mx:Image width="75" height="75" source="{data.thumbnail.url}"/>
</mx:VBox>
</mx:Component>
</mx:itemRenderer>
</mx:TileList>
CODE FOR THE COMPONENT shown on PopUP
< ? xml version="1.0" encoding="utf-8" ? >
< mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml"
showCloseButton="true"
styleName="noPadding"
creationComplete="init();"
close="titleWindow_close(event);" >
< ![CDATA[
import mx.managers.IFocusManagerComponent;
import mx.controls.Alert;
import mx.core.IFlexDisplayObject;
import mx.events.CloseEvent;
import mx.managers.PopUpManager;
[Bindable]
public var source:String;
private function init():void {
PopUpManager.centerPopUp(this);
}
private function titleWindow_close(evt:CloseEvent):void {
PopUpManager.removePopUp(evt.target as IFlexDisplayObject);
}
]] >
< /mx:Script>
< mx:Image width="379" height="261" id="imgId" source="{source}"/>
<mx:ControlBar horizontalAlign="right" width="100%">
</ mx:ControlBar>
< /mx:TitleWindow >

"So you are trying to get the application size from within the info bubble swf? Why is the info bubble in a separate swf? If you have the info bubble source code, I suggest adding it into your map application and directly instantiate the info bubble object. – elevine 2 hours ago"
I have three different type of infoBubbles (only static bubble is shown). Some of my info bubbles have moving content. I am not looking for the application size of the external swf in the bubble, i am looking for the physical size. The height and width of the external swf that is populating the bubble. If I knew the height and width, I can have the infobubble match the height and width. Right now I have the info bubble hardcoded to the size of the current info bubble; however, i will have different sizes of info bubbles swf files.

Related

How to splice 2 mx canvas objects with repeat-x backgrounds?

I have 2 canvas objects that both contain a tiling image. My client recently requested that both the images be able to appear at the same time. I simply allowed them to be both enabled at the same time thinking they would tile appropriately but they do not.
After some careful thought I realized this is because they are of varying width so although my tiling image is 7 pixels in width, it may not always end at 7 pixels thus causing it to not appear to tile cleanly.
I can't just lop off the remainders because the imagery is being used to assess quantities of items (without going into too much detail) and having item 1 with 97 quantity next to item 2 with 200 quantity on one row compared to row 2 with item 1 having 100 quantity and item 2 having 300 quantity will show up strange to the end-user.
Does anyone know of how I could get started with maybe splicing the two canvas objects together or rather using 1 canvas object and then using BOTH background images and setting a percentWidth or something that the other one comes into affect?
You can use the copyPixels() method of the BitmapData class to achieve this sort of result. To do this, you need to load each image with a Loader. When the images are loaded, you have two Bitmap objects. From there, you access the corresponding BitmapData for each Bitmap and can splice them together.
After the splice, you create a new Bitmap object from the combined BitmapData. Then you feed the combined Bitmap to some other component. Unfortunately, a Canvas won't accept a Bitmap for its backgroundImage style. But you can add the combined Bitmap to a UIComponent or set it as the source of an Image component.
Finally, add either the UIComponent or Image to a Canvas. Since you can layer things on the Canvas, you effectively have a background image as long as place (and leave) the combined image at index 0 of the Canvas.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical"
minWidth="955" minHeight="600"
creationComplete="onCreationComplete()">
<mx:Script>
<![CDATA[
import mx.containers.Canvas;
import mx.controls.Image;
import mx.core.UIComponent;
import mx.events.FlexEvent;
private var loader1:Loader;
private var loader2:Loader;
private var bitmap1:BitmapData;
private var bitmap2:BitmapData;
protected function onCreationComplete():void
{
loader1 = new Loader();
loader1.load(new URLRequest("Android_Robot_100.png"));
loader1.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoader1Complete, false,0,true);
loader2 = new Loader();
loader2.load(new URLRequest("rails.png"));
loader2.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoader2Complete, false,0,true);
}
protected function onLoader1Complete(event:Event):void
{
bitmap1 = (loader1.content as Bitmap).bitmapData;
if (bitmap1 && bitmap2)
copyPixels();
}
private function onLoader2Complete(event:Event):void
{
bitmap2 = (loader2.content as Bitmap).bitmapData;
if (bitmap1 && bitmap2)
copyPixels();
}
protected function copyPixels():void
{
// false = non-transparent background
var combined:BitmapData = new BitmapData(200,200, false);
var sourceRect1:Rectangle = new Rectangle(0,0,bitmap1.width, bitmap1.height);
var sourceRect2:Rectangle = new Rectangle(0,0,bitmap2.width, bitmap2.height);
combined.copyPixels(bitmap1, sourceRect1, new Point(0,0));
combined.copyPixels(bitmap2, sourceRect2, new Point(bitmap1.width, 0));
var result:Bitmap = new Bitmap(combined);
var image:Image = new Image();
image.source = result;
var canvas:Canvas = new Canvas();
canvas.addChildAt(image, 0);
addChild(canvas);
// as an alternative, just add the bitmap to a UIComponent
// note you can't do this and the above at the same time,
// becuase the 'result` Bitmap can only be the child of one
// object, adding it to one thing removes it from the other...
// var uic:UIComponent = new UIComponent();
// uic.addChild(result);
// addChild(uic);
}
]]>
</mx:Script>
</mx:Application>
Ultimately I was overcomplicating it. I simply did this with masking like...
<mx:Canvas width="100%" height="100%">
<mx:Image id="myFirstUnrelatedImage" width="50%" height="65%" maintainAspectRatio="false"
verticalCenter="0" left="3"
source="#Embed('../assets/image1.png')" visible="true"/>
<!-- not sure why borderStyle here is required but it won't show up without? -->
<mx:Canvas id="image1mask" width="30%" height="94%"
borderStyle="none" visible="false"/>
<mx:Canvas id="image1" width="100%" height="100%"
minWidth="0" styleName="myStyle"
mask="{image1mask}"/>
<!-- not sure why borderStyle here is required but it won't show up without? -->
<mx:Canvas id="image2mask" width="20%" height="94%"
right="0" borderStyle="none" visible="false"
includeInLayout="false"/>
<mx:Canvas id="image2" width="100%" height="100%"
minWidth="0" styleName="myStyle2"
mask="{image2mask}"/>
</mx:Canvas>
Where my styles were controlling the backgroundImage and backgroundRepeat properties in css.

Flex : Unable to rotate header text in Datagrid

I'm having trouble in rotating the header text in my datagrid. I don't know understand the reason why its failing.Can someone help?
Datagrid column AS3 code:
dgc=new DataGridColumn();
dgc.dataField=columnName.gene;
dgc.labelFunction=gridLabelFunction
dgc.headerText=columnName.gene;
//dgc.headerWordWrap=true;
dgc.headerRenderer=new ClassFactory(VDGHeader);
dgc.width=20;
_datagridColumnsArray.push(dgc);
Please find my Header Renderer component below
import mx.controls.dataGridClasses.DataGridColumn;
import mx.managers.SystemManager;
[Bindable] private var text:String;
[Bindable] private var src:String;
override public function set data(value:Object):void{
var col:DataGridColumn = value as DataGridColumn;
text = col.headerText;
}
]]>
</fx:Script>
<mx:Label id="txtLbl" text="{text}" rotation="10" width="100%" />
This actually doesn't have anything to do with column headers.
To rotate text in Flex you must embed the font. Otherwise the rotation will simply be ignored.
See Adobe's docs on Embedding Fonts

Is there a way to show the errorTip (error ToolTip) to the left of the target?

I'm creating an errorTip that gets displayed when the user mouses over an image. I would like the popup to appear to the left of the image, but the only properties I can pass to create the toolTip are "errorTipRight", "errorTipAbove" and "errorTipBelow".
Any thoughts?
Sample code:
<?xml version="1.0" encoding="utf-8"?>
<mx:HBox xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<fx:Script>
<![CDATA[
import mx.controls.ToolTip;
import mx.managers.ToolTipManager;
[Embed(source="assets/some_image.png")]
[Bindable]
private var myIcon:Class;
private var myToolTip:ToolTip;
private function showToolTip(evt:MouseEvent, text:String):void
{
var pt:Point = new Point(evt.currentTarget.x, evt.currentTarget.y);
pt = evt.currentTarget.parent.contentToGlobal(pt);
// I WANT TO POP THE ERRORTIP UP TO THE LEFT HERE INSTEAD OF ABOVE.
myToolTip = ToolTipManager.createToolTip(text, pt.x, pt.y, "errorTipAbove") as ToolTip;
var yOffset:int = myToolTip.height + 5;
myToolTip.y -= yOffset;
}
// Remove the tooltip
private function killToolTip():void
{
ToolTipManager.destroyToolTip(myToolTip);
}
]]>
</fx:Script>
<mx:Image source="{myIcon}" mouseOver="showToolTip(event, 'My ToolTip Message Goes Here')" mouseOut="killToolTip()" />
</mx:HBox>
You'll need to create a replacement for the ToolTipBorder class and assign that as the skin for your ToolTip. I would do this by copying the ToolTipBorder source and modifying the updateDisplayList and borderMetrics methods to include a new "errorTipLeft" style to the switch statements in those methods. Then assign that skin class to the ToolTip class in CSS. Hope that helps.
Why can't you subtract the width of the tooltip from the pt.x when you give the coordinates to the ToolTipManager?
myToolTip = ToolTipManager.createToolTip(text, (pt.x - somewidth), pt.y, "errorTipAbove") as ToolTip;

Flex: Binding to the Height of the UITextField

I'm having problems binding the height of a UITextField to the y of a VBox and the height of the TitleWindow. I'm trying to adjust the height of the TitleWindow and the height of the VBox so, that the UITextField doesn't overlap the other content.
Alternatively, I've tried setting the height of the UITextField to an explicit height, but I haven't been able to get it to work.
I have to use a UITextField instead of Text, because I'm using Flash Eff2.
<?xml version="1.0" encoding="utf-8"?>
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute"
width="520"
height="{tf.height + 380}">
<mx:Script>
<![CDATA[
import mx.core.UITextFormat;
import mx.events.ItemClickEvent;
import mx.controls.RadioButton;
import mx.controls.RadioButtonGroup;
import mx.core.UITextField;
import mx.managers.PopUpManager;
[Bindable]
public var tf:UITextField = new UITextField;
[Bindable]
public var myText:String;
[Embed(source="../libs/arial.ttf", fontFamily="ArialEmbedded")]
public const ArialEmbedded:Class;
public function createEffect2():void{
tf.autoSize = TextFieldAutoSize.LEFT;
//tf.height=150;
tf.embedFonts = true;
tf.multiline = true;
tf.text = myText;
tf.width = 400;
tf.wordWrap = true;
var myFormat:TextFormat = new TextFormat;
myFormat.size = 25;
myFormat.blockIndent=50;
this.addChild(tf);
tf.validateNow();
tf.setTextFormat(myFormat);
}
]]>
</mx:Script>
<mx:VBox x="180" y="{tf.height + 140}" width="480" >
<mx:RadioButtonGroup id="choicesRadioButtonGroup" />
<mx:RadioButton groupName="choicesRadioButtonGroup" label="A" horizontalCenter="150"/>
<mx:RadioButton groupName="choicesRadioButtonGroup" label="B" horizontalCenter="150"/>
<mx:RadioButton groupName="choicesRadioButtonGroup" label="C" horizontalCenter="150"/>
</mx:VBox>
</mx:TitleWindow>
I'm getting: Data Binding will not be able to detect assignments to "height".
Any suggestions?
Thank you.
-Laxmidi
If I had to guess, Binding is a Flex construct, not an "ActionScript' construct. Height is a made Bindable in UIComponent, but UITextField does not extend UIComponent. Instead it extends, FlexTextField, which extends TextField (A Closed source Flash class).
You can either extend UITextField and override height to make it Bindable or just use a Flex TextInput class, which does extend UIComponent.

Flex: Problems using scale9Grid with Image

I'm trying to create an image component that can be scaled using 9-slice scaling.
I'm 100% positive the grid rectangle is inside the image's bounds. However, the scale9Grid property seems not to affect anything.
I have tried many different things. Here is my last attempt where I try to put the image in a canvas. Any idea what I'm doing wrong?
mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="init()"
>
<mx:Script>
<![CDATA[
import mx.core.BitmapAsset;
import mx.controls.Image;
[Embed(source="assets/image.png")]
private var barImageClass:Class;
private var barImage:Image;
private function init():void
{
barImage = new Image();
barImage.addChild( new Bitmap( (new barImageClass() as BitmapAsset).bitmapData ) );
barImage.scale9Grid = new Rectangle( 120, 4, 2, 2 );
barImage.scaleX = 2;
addChild( barImage );
}
]]>
</mx:Script>
I believe you need to apply the scale9Grid to the bitmap, instead of to the sprite/movieclip it's inside of.
See this adobe doc. I think it will solve your problem. Cheers

Resources