Thanks Alex for your response.

I tried all kinds of combinations of capturing the updateComplete event on different components as well as chaining callLaters with checking of properties etc, but couldn't get it to work without side effects.

Eventually I found that all I needed to do was validate the container and the Legend control before taking the snapshot, the important part being that the container must be validated before the Legend so that the Legend picks up the CSS changes when it's validateNow is called.

Here's my new method of saving pictures of charts etc for anyone that might come across the same problem, it's not particularly efficient what with all the validateNows (3 in total), but seeing as this is triggered from a button press or hot key, the user isn't doing anything else and must have the result as quickly as possible, it's not such a big deal. It's pretty responsive.

private function saveToFile():void
{
        var crossPlatform:ICrossPlatform;
        crossPlatform = CrossPlatform.getInstance();                            
        
        if (mainTabs.selectedChild.id == "casesTab")
        {
                var dataString:String = delimitedCaseListString();
crossPlatform.saveStringToFile(dataString, currentFilter.sFilterName + ".txt");
        }
        
        if (mainTabs.selectedChild.id == "pieChartTab")
        {
                pieChartContainer.styleName = "forPrint";
pieChartContainer.validateNow(); //*** Make sure container has style set and displayed. pieChartLegend.validateNow(); //*** Make sure troublesome child has style set and displayed.
                callLater(saveSnapshotAndResetStyleName, [pieChartContainer]);
pieChartContainer.validateNow(); //*** Kick off snapshot in timely fashion.
        }
}

private function saveSnapshotAndResetStyleName(component:UIComponent):void
{
        // Take snapshot and remove print style.
        var dataBytes:ByteArray = byteArrayFromComponent(component);
        pieChartContainer.styleName = null;

        // Save image to file.
        var crossPlatform:ICrossPlatform;
        crossPlatform = CrossPlatform.getInstance();                            
crossPlatform.saveByteArrayToFile(dataBytes, currentFilter.sFilterName + ".png");
}

private function byteArrayFromComponent(component:UIComponent):ByteArray
{
var imageSnapshot:ImageSnapshot = ImageSnapshot.captureImage(component);
        return imageSnapshot.data;
}

It seems to work.

Thanks for trying to help, trying to implement something off your suggestion lead to the final fix.

Ian
________________________________________
IMiJ Software
http://www.imijsoft.com
http://www.ianmjones.net (blog)



On 29 Aug 2008, at 18:52, Alex Harui wrote:


Does the legend change color eventually? Maybe waiting for updateComplete will be better. You can always chain callLaters



From: flexcoders@yahoogroups.com [mailto:[EMAIL PROTECTED] On Behalf Of Ian M. Jones
Sent: Friday, August 29, 2008 4:50 AM
To: flexcoders@yahoogroups.com
Subject: [flexcoders] How do I make sure container's child components have applied new style before ImageSnapshot?



Hi,

I'm having a bit of a problem with capturing a snapshot of a VBox's
contents with a simple colour change applied through a styleName change.

The container layout is something like:

<mx:VBox id="pieChartContainer" width="100%" height="100%"
horizontalAlign="center">
<mx:Label id="pieChartTitle"
text="{currentFilter.sFilterName}"
fontSize="14"
fontWeight="bold"
textDecoration="underline"/>
<mx:PieChart id="pieChart" width="100%" height="100%"
showDataTips="true" dataTipFunction="pieChartDataTipFunction"
resizeEffect="{moveAndResize}">
<mx:series>
// Some series, not relevant to problem.
</mx:series>
</mx:PieChart>
<mx:Legend id="pieChartLegend"
dataProvider="{pieChart}"
width="100%"
visible="{chkPieChartLegend.selected}"
includeInLayout="{chkPieChartLegend.selected}"
direction="horizontal"
resizeEffect="{moveAndResize}"/>
</mx:VBox>

Because by default my app has a dark theme with light text applied
through CSS, before capturing a snapshot, I set the style to:

.forPrint
{
color: #000000;
}

This means the image should have black text which is good for print etc.

I call saveToFile() to start the capture, only when the referenced pie
chart is visible.

private function saveToFile():void
{
pieChartContainer.styleName = "forPrint";
callLater(saveSnapshotAndResetStyleName, [pieChartContainer]);
pieChartContainer.validateNow();
}

private function
saveSnapshotAndResetStyleName(component:UIComponent):void
{
var dataBytes:ByteArray = byteArrayFromComponent(component); // The
bit that does all the real work!
var crossPlatform:ICrossPlatform;

pieChartContainer.styleName = null;

crossPlatform = CrossPlatform.getInstance();
crossPlatform.saveByteArrayFile(dataBytes, currentFilter.sFilterName
+ ".png");
}

The problem is that although the pie chart gets the change in text
colour before the snapshot is taken, if the Legend control is included
in the container it still retains it's light label colour.

As you can see from the code above I've tried to delay the capture
until the refresh happens by using a combination of callLater and
validateNow, but that doesn't seem to help.

If I comment out the resetting of the container's styleName after the
snapshot has been taken, the Legend control is shown with the required
black text, so the change does happen, but not before I take the
snapshot.

Has anyone got any advice on how to make sure a container and it's
child controls have applied a new style before using ImageSnapshot?

Thanks in advance for your help,

Ian
________________________________________
IMiJ Software
http://www.imijsoft.com
http://www.ianmjones.net (blog)




Reply via email to