26 September 2009

Scaling an mx:Text – The Bottom Line…

Have a look at my little test app here.

On the numeric stepper, keep increasing the scaling.

You’ll find at about 1.26, a strange thing happens – you lose the bottom line.

As usual in my adventures with the Flex SDK, it’s a bug.  But this time I don’t think it’s a bug in the Flex SDK.   I believe it is in the text control in Flash Player.

Anyway, there is a bug report, and it’s here: SDK-16876.

If you encounter this issue with showing controls on the screen, you can probably get around it by setting an explicit height on the Text control.  However, what happens if you want the Text control to grow it’s height?  Setting an explicit height simply isn’t going to work if you don’t know at runtime if the Text control will hold 2 lines or 20.

But there is another sting in the tail of this particular bug.  You may be able to work around this issue on the screen by either sizing components or not scaling them.  But there is one time where you will have to use scaling…..

Printing.

And that’s where I hit this problem.  I can’t use any of the existing solutions in my app because I need the Text control to grow to show all it’s text, and I need to print that Text component, so it needs to scale properly.

My test app uses a copy of the Text component, and I have updated it a bit.   I have added a new function:

private function getCalculatedTextHeight():Number { var textHeight:Number = 0; for(var i:int=0; i < textField.numLines; i++) { textHeight += textField.getLineMetrics(i).height; } // SDK-16876 // Comment in this line instead of the following one // to fix the issue. // return Math.ceil(textHeight) + 4; return Math.ceil(textHeight); }

It seems that there is a rounding error somewhere, because if you add 4 to the height returned by getCalculatedTextHeight(), the problem goes away. The downside is that Text controls appear a bit larger in height, but the major plus side is that all the lines in my Text controls now get printed.

I thank you.

25 August 2009

MAXwidget

18 August 2009

Loading assets on demand, and blowing up Flex Builder…

We’re using the Flash API for Google Maps.  You can specify your own image for a location marker, and because we don’t do anything by halves here, we wanted an image for each location.

So we generated 99 icons for 20 routes, with each route being a different colour, and the number embedded in the icon.  In fact, the background colours from the icons were generated using the colours from my Colour Scheme tool that I mentioned in my previous post.

So thats about 180 small images that we wanted to download to the client.  Rather than making each client download these images every time, we wanted the client to only download the images when they were required.  So the images are in their own swf which is simply a compiled stylesheet.  The stylesheet looks like this:


route1
{
drop1: Embed(source='../assets/drop_icons/1/drop_icons_1_1.png');
drop2: Embed(source='../assets/drop_icons/1/drop_icons_1_2.png');
drop3: Embed(source='../assets/drop_icons/1/drop_icons_1_3.png');
drop4: Embed(source='../assets/drop_icons/1/drop_icons_1_4.png');
drop5: Embed(source='../assets/drop_icons/1/drop_icons_1_5.png');
...etc...

I’ve named the styles according to how they are used, so that one style has all the icons for a single route.

Then I wrote a simple little app to make sure that I could get the images out and pass them to the map API.  You can click on the image at the top of this post to go to the test app – View Source is enabled, but you won’t get the images cos we had to pay for those…:-D

And then there was the problem of Flex Builder just exiting without warning. I found that after I had built the swf containing these 180 images, I would continue normally for a couple of minutes and then I performed some action like opening a project, and Flex Builder would just vanish. It exited. It was no more. A few very strange messages were produce, and reading between the lines it seems that Flex Builder just ran out of memory.

Flex Builder is working ok up to a point in that it managed to compile the swf.  However, there’s obviously something not being tidied up after the compilation, so I have raised a bug with Adobe and it’s here.  I’m pleased that it seems to be getting quite a bit of attention from the Adobe guys….

18 August 2009

Overlay colours in Google Maps

ColourScheme Test App

When you have more than one route overlay shown on a map, it gets a bit difficult to separate them out.  We needed to show several routes on a map all at once, and generating the colours using some fancy colour-wheel stuff just didn’t make the route overlays show up.

So we went for Plan B.  We needed to generate a fixed set of colours that we knew would show up on the map.  I needed a way of showing about 20 colours up against each other so that as routes were added, the colours would be so different that we would be able to see each route.  In addition, we wanted to make sure that the route colours were different to the default colours used to show roads etc on the maps themselves.

So I wrote a simple little app to show colours in a list.  You can drag the colours around, and as you select each colour, the colour picker at the top gets set, and you can then edit that individual colour with the picker.  You can click on the add button to add a new bar to the list.   As you make changes, the code window on the right gets updates, and you can copy that and paste it into your actionscript to create a colour array.

21 June 2009

Flash Builder 4 and netmon.swc

I downloaded the latest build of the new Flash Builder 4.0 standalone, hoping for a bit of a fiddle to see what it did.  Unfortunately I didn’t get very far.  I created about the simplest test app you’re like to to find, but when I came to build it, I got this error:

unable to open ‘C:\Program Files\Adobe\Flash Builder4 Beta\sdks\4.0.0\frameworks/libs/netmon.swc’

I’m not sure whether the forward slashes at the end of the path are the problem, and even if they were, I couldn’t find any configuration file to correct it. In any case, I really don’t think Flash Builder should throw an error like this just after a vanilla installation.

You can get around the issue by simply unchecking “enable network monitor” in the compiler settings for the project, but to me that’s not acceptable as I wanted to play around with the network monitor.

I’ve had a look at the Adobe bugs and there is an issue that mentions this error message here, but the issue report isn’t actually about the error itself. I’ve commented on this issue asking if there should be a separate issue for this.  After thinking about it for a bit, I added a new bug report anyway, and it’s here.

25 May 2009

Sliding Panel

Sliding Panel Test App

Sliding Panel Test App

I’ve been working on a screen that shows a diary something like the calendar in Outlook.  We’re targeting fairly low-spec machines with screen resolutions not more than 1024 x 768.

On one side I have a list of items that I can drag onto the schedule to create entries.  As development continues, the width of this list is getting wider as the implementors want more columns in the list, and the visible area of the schedule is getting smaller.

Once again, the old saying is never more true – Necessity is the Mother of Invention. I need to show a list and a schedule almost at the same time.

So here’s my solution to the problem.  My list of things to drag onto the schedule will go in a SlidingPanel on the right.  The user can click on the arrow button to show or hide the panel.  Once they have selected an item from the list on the right they can drag it onto the schedule, close the panel, and then move the item around on the schedule.

Click on the image above to go to my test app.  The SlidingPanel component can be set to anchor to the left or right, and start up open or closed.  The tab (the vertical bar with the button on it) is a separate component, SlidingPanelTabSkin, and you can change that to alter how the tab is displayed.   The only requirement is that it implements ISlidingPanelTabSkin and dispatches a SlidingPanelEvent when the user clicks somewhere on the tab to get the panel to open or close.

23 April 2009

Expanding TextArea Component

I’ve been working with printing with Flex for a while now, and hit a problem where my TextArea controls weren’t showing all their text when they were printed.

The problem arises because it’s difficult to figure out how many lines of text the TextArea will show, and hence how high to make the TextArea control.  My first attempt involved searching through the text for \r\n etc and adding the height of one text line for each of them.  That won’t work if the text has automatically wrapped within the control.

Why not use the textHeight property of TextArea, you’re asking?  Well, that’s what I tried, and I would have finished a lot quicker if it was that easy.  But unfortunately there are some bugs with the calculations that produce the textHeight.  One of them is described here.

I found some helpful stuff on the web, and the most promising page was from a bunch of guys called idletogether.com, here.  So I used that and created a test app that demonstrates a control based on TextArea, which will automaticlly expand or shrink as you edit the text.  It will also print properly by sizing itself according the length of text in it.  My app is here.

14 April 2009

Google Maps: Security Sandbox Error when using Flex Effects

For a while we have been wondering why we get a Security Sandbox Violation when we run an effect over a container that has a map in it. Just to make sure we all know what we’re talking about, here’s the error that we currently get:


SecurityError: Error #2122: Security sandbox violation: BitmapData.draw: http://10.44.181.34:8080/tls-hs/HomeServices.swf/[[DYNAMIC]]/1 cannot access http://mt0.google.com/mt/v=ap.92&hl=en&x=253&y=167&zoom=8&s=Galile. A policy file is required, but the checkPolicyFile flag was not set when this media was loaded.
at flash.display::BitmapData/draw()
at mx.effects.effectClasses::MaskEffectInstance/getVisibleBounds()[E:\dev\3.1.0\frameworks\projects\framework\src\mx\effects\effectClasses\MaskEffectInstance.as:771]
at mx.effects.effectClasses::MaskEffectInstance/initMask()[E:\dev\3.1.0\frameworks\projects\framework\src\mx\effects\effectClasses\MaskEffectInstance.as:650]
at mx.effects.effectClasses::MaskEffectInstance/startEffect()[E:\dev\3.1.0\frameworks\projects\framework\src\mx\effects\effectClasses\MaskEffectInstance.as:463]
at mx.effects::Effect/play()[E:\dev\3.1.0\frameworks\projects\framework\src\mx\effects\Effect.as:930]
..etc...

I think we have finally found the answer here.  And the answer is…

You can’t.   So don’t try.

When you run an effect, it attempts to render the entire container and everything in it to a bitmap, which it then processes to produce the effect.  But as Pamela Fox explains in the Google Groups post, they don’t really want to allow people to render parts of their maps to bitmaps which people can then mess about with.

I’ve had a moan about this on three points:

  1. I can’t find any documentation anywhere that explicitly says that you can’t do effects over a map. At least if you type in “Google maps flash effects” there’s nothing that I could see to tell me that effects aren’t supported.
  2. I think effects should be able to run over a map.  After all, the whole point of Flex it provide a “Rich” application, and effects are a sizeable part of that.
  3. The error message we get relates to a Sandbox Violation.  How are we supposed to figure out from that that drawing to a bitmap (and hence effects) is disabled?

In the meantime, it seems we have to remove the map from the display list whilst an effect is playing, and that’s the solution described in the Google Groups post.

Update – I had a reply from Pamela Fox on the Google Maps team and there’s a issue for this here.  Please star this issue and add to the growing band of developers who want to do effects stuff….

6 March 2009

Printing using layout and images

I needed to print an exam ready for someone to fill in.  Looking at the demos for printing in the SDK documentation, they were a bit thin on the ground. 

According to the documentation, printing is simple – you create a FlexPrintJob, create your display objects and add them to the job using addObject() and then call send().   What could be easier?

Well a lot of things actually.  

The documentation doesn’t mention a bunch of pitfalls that you need to overcome before you can print properly.  Here is a brief list of the ones I found…
  1. Images need to be downloaded before you start printing.  Image loading is inherently asynchronous, so if you request the images at print time, there is no guarantee that they will be loaded by the time printing occurs. So you have to explicitly go through your document, request each image, and wait until they are all loaded before starting to create the display objects for printing.
  2. The sample code in the documentation always seems to lay out the display objects with specific x and y coordinates.  But what happens if you want to use the standard layout components?  When I tried that, nothing appeared.  I simply tried to use VBox and HBox to position the individual parts of the page, and whatever I tried, the layout of the controls on the display objects didn’t work properly. Its seems that you have to add any display objects that you want to print to the actual display list otherwise they won’t be laid out properly, if at all.  In other words you have to add your printed page to a parent that already exists on the display list.  There might be a function somewhere that you can call to ensure that all your pages are laid out, but I couldn’t find it.
  3. In  addition to point 2, you have to allow the LayoutManager a few frames to actually perform the layout, otherwise some containers seemed to be laid out properly, but others didn’t.  In my test app, I create the controls and then the printing is done at the other end of a callLater(). 

My working test app is here.  The printed layout is pretty much the same as the displayed layout, and it only works because I have solved the particular problems described above.

6 March 2009

Flash Player Version detection is bust in Flex Builder 3.0.1

I have just upgraded to FB 3.0.1. It just happened that I needed to create a small test project for a problem that I wanted to isolate and sort out. When I ran the project, I got a little message asking me if I wanted to update my Flash Player to 10.

Update to Flash Player 10    

This is quite obviously a bug.   It’s wrong on two counts:

  • Firstly I don’t have to update to Flash Player 10.  The code in my test project will happily work on Flash Player 9.0.115.
  • Secondly it doesn’t tell me what version I do need to update to.   By default, the required Flash Player version in a new project is version 9.0.128.  If that’s what the developer has set (by default or otherwise), then that’s what the message should say.

There is already an issue with Flash Player detection on the Adobe bug system here.  But this didn’t cover all the issues I was seeing.  It turned out that I could reproduce this issue by turning off  Express Install in the project compiler settings.   My issue seems to revolve specifically around the detection of the Flash Player version when Express Install is set.  I did a cursory check to see if anyone has already reported this and found nothing much.  So I added my own bug report here – vote it up, comment on it, shout it down at your leisure.

There’s a sort of workaround in that you can artificially lower the required version of Flash Player in the project compiler settings so that there’s less likelihood that anyone will get this message.