Horizontal Layout: mx vs spark - Resizing children - actionscript-3

In Flex 3, I used to be able to take 2 panels, lay them out with 100% width settings in an HBox. If I changed the width property of the first panel to something smaller, let's say 20%, the second would automatically update and fill in the space that used to be taken up by the first as the first resized down.
I notice in spark, this doesn't happen. I have an app with a HorizontalLayout, and a resizable panel control on the left and a panel on the right that has width="100%." When I resize my left-side panel down, the right side panel doesn't do anything. So I end up with a clean resizable panel, a bunch of wasted space, and my right-side panel just sitting there.
What I expect is that since the right-side panel has a width="100%" then if the panel to its left is resized, then there would be a corresponding growth in the right-side panel to fill in.
I've tried to manually trigger validation on properties and size without effect. I'm wondering what changed in the HorizontalLayout that no longer allows this technique to work. I would also like to know what solutions are available?
Here's some chomp chomp:
<mx:Application>
<mx:Script>
<![CDATA[
protected function resizeClick(event:MouseEvent):void
{
pnl1.percentWidth = 10; // When this would execute, pnl2 would automatically
// fill in the space previously held by pnl1.
}
]]>
</mx:Script>
<mx:HBox width="100%" height="100%">
<mx:Panel id="pnl1" width="40%" height="100%"> // Uses 40%
<mx:Button id="resizeButton" click="resizeClick(event)"/>
</mx:Panel>
<mx:Panel id="pnl2" width="100%" height="100%"/> // Fills in the rest of the available space
</mx:HBox>
</mx:Application>
Flex 4.5 doesn't automatically update the size of pnl2 when the size of pnl1 changes. I would think that since a HorizontalLayout is being used, that both children would update when the width of one of them was changed. But that just doesn't seem to be the case. I know I can create two states to accomplish this, but I was thinking that I shouldn't have to for something so trivial.

This sample works fine and illustrates correct changes of sizes:
<?xml version="1.0" encoding="utf-8"?>
<s:Application minHeight="600" minWidth="955" xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:s="library://ns.adobe.com/flex/spark">
<s:VGroup height="100%" width="100%">
<s:HSlider change="firstPanel.percentWidth = event.currentTarget.value" maximum="100" minimum="0"
value="{firstPanel.percentWidth}" />
<s:HGroup height="100%" width="100%">
<s:Panel height="100%" id="firstPanel" minWidth="0" width="40%" />
<s:Panel height="100%" width="100%" />
</s:HGroup>
</s:VGroup>
</s:Application>

So this is how I eventually solved this problem. I should have been a little more specific in my post to explain that Panel 1 is actually a "collapsible" panel that modifies its own size whenever its header button is clicked. The example above does work, but since there is no numeric control on the view to "tell" the panel.percentWidth property how much to change, I set my collapsible panel up to dispatch custom events that are handled by the wrapper. The custom events basically indicate what is happening to the collapsible panel. From there, I can handle the events separately and then control the size of Panel 2.
The solution is actually rather simple and I was hoping for something a little more "behind the scenes" but this worked fine.
<s:Application initialize="initApp(event)">
<fx:Script>
<![CDATA[
protected function initApp(event:FlexEvent):void
{
this.addEventListener("PanelCollapse", panelHandler);
this.addEventListener("PanelNormal", panelHandler);
}
protected function panelHandler(event:Event):void
{
switch(event.type)
{
case "PanelCollapse":
pnl2.percentWidth = 100;
break;
case "PanelNormal":
pnl2.percentWidth = 60;
break;
}
}
]]>
</fx:Script>
<comp:CollapsiblePanel id="pnl1" width="40%" height="100%">
</mx:Panel>
<s:Panel id="pnl2" width="100%" height="100%"/> // Fills in the rest of the available space
</s:Application>

Related

AS3 Scroller, odd interaction with constraint layout?

I have a form that uses constraint layouts (left/right/top/bottom) to position the main form inside a background. When I use the form in a popup TitleWindow, it lays out and sizes the components (and sets the TitleWindow size) as I would expect.
When trying to use the same set of components inside a Scroller, the layout is incorrect - the background gets resized to fit the Scroller, while the interior form is the correct size (but the right/bottom constraints aren't applied).
This simplified program demonstrates the issue. Without the Scroller, the form lays out correctly, and if the WindowedApplication is resized to show the entire form it looks correct.
<?xml version="1.0" encoding="utf-8"?>
<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"
width="400" height="400">
<fx:Declarations>
<s:SolidColor id="bgFill" color="#8080c0"/>
<s:SolidColor id="whiteFill" color="#ffffff"/>
</fx:Declarations>
<fx:Script>
<![CDATA[
protected function checkSizes():void
{
trace('Base is ' + base.width + 'x' + base.height);
trace('Background is ' + bg.width + 'x' + bg.height);
trace('Border is ' + border.width + 'x' + border.height);
trace('Form is ' + form.width + 'x' + form.height);
}
]]>
</fx:Script>
<s:Group id="base">
<s:Rect id="bg"
left="0" right="0" top="0" bottom="0"
fill="{bgFill}"/>
<s:Rect id="border"
left="10" right="10" top="10" bottom="10"
fill="{whiteFill}"/>
<s:VGroup id="form" left="20" right="20" top="20" bottom="20">
<s:Button width="600" height="600"
label="Push Me!"
click="checkSizes()"/>
</s:VGroup>
</s:Group>
</s:WindowedApplication>
Clicking the button shows the component sizes as I'd expect:
Base is 640x640
Background is 640x640
Border is 620x620
Form is 600x600
If I add a scroller to fit the parent window, base, bg and border all fit inside the scroller, rather than being sized to fit as borders around form:
<s:Scroller width="100%" height="100%">
<s:Group id="base">
...
Base is 385x361
Background is 385x361
Border is 365x341
Form is 600x600
Oddly enough, if I put an extra group around base, then everyone lays out correctly...
<s:Scroller width="100%" height="100%">
<s:Group id="dummy">
<s:Group id="base">
...
Before I start digging through the Scroller and ScrollerSkin source, anyone know if I'm off my rocker and doing something worng in the first scroller example? I'd rather not create extra layers of components that I don't need.
The scroller restricts its first (and only) child to stay within his bounds, it will move the viewport of that child when you scroll.
Because your main application restricts the size of the scroller to 400x400, the base will never exceed 400x400 aswell.
If you add the dummy, base is free to expand as much as it wants but dummy will be restricted to expand.
I hope this explains it a bit. If not ask me more =)

Problems with adding Spark elements to a MX wrapper

So I made a simplified version of the code I'm working on ...
I have a custom Flex component that has following structure (based on the s:HGroup):
<s:HGroup 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="100%" height="100%" >
<fx:Script>
<![CDATA[
import spark.components.Button;
public function addButton():void{
var myButton:Button = new Button(); 
            myButton.label = "New Button"; 
buttonContent.addElement(myButton);
}
]]>
</fx:Script>
<mx:HDividedBox width="100%" height="100%">
<s:VGroup width="100%" height="100%" gap="5">
<s:VGroup width="100%" height="100%">
</s:VGroup>
<s:Group width="100%" height="100%">
<s:Group left="5" top="15" bottom="5" right="5" id="buttonContent" />
</s:Group>
</s:VGroup>
<s:VGroup width="100%" height="100%">
</s:VGroup>
</mx:HDividedBox>
Inside this component I make use a the mx:HDividedBox component since there is no Sparkalternative...
So when I call the function addButton(), my intend is to add a custom Spark DataGrid (in this example a simple s:Button made with code) to the Spark Group with id buttonContent. I noticed that this button isn't added to the Groupwith id buttonContent.
When I commented out the mx:HDividedBox the Spark button was added like it should...
I suppose there is some conflict rising between the Sparkand mx display formats.
Has anyone had the same problem? Or know a usable solution / work around?
Any tips are welcome! Thanks!
Try adding an "id" field to the HDividedBox. Flex has had issues with not recognizing elements when their parents don't have an id in the past, this might be a regression issue?
(Would've added as a comment, but I don't have the access yet..)
Your exemple works on my computer.
Which flex SDK version are you using ?
Are you really using "100%" width and height in you real code ? (DividedBox are tricky with sizes, if you don't set resizeToContent to true then the dividedBox will not resize itself if the content changes)

create custom chrome adobe air desktop application using flex4 sparks controls

I have googled around but the only resource for teaching me how to create an Adobe Air Desktop Application uses mx controls instead.
inside app-xml i have set transparent to true and systemChrome to none.
the following is my main mxml
<?xml version="1.0" encoding="utf-8"?>
<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:dragdrop="org.robotlegs.demos.draganddrop.*"
xmlns:view="org.robotlegs.demos.draganddrop.view.*"
mouseOver="layoutCanvas.visible = true;"
mouseOut="layoutCanvas.visible = false;"
>
<fx:Style>
#namespace s "library://ns.adobe.com/flex/spark";
#namespace mx "library://ns.adobe.com/flex/mx";
s|Application {
background-alpha:"0.7";
padding: 0px;
}
</fx:Style>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
<dragdrop:DragAndDropContext contextView="{this}"/>
</fx:Declarations>
<s:Image id="background" width="100%" height="100%"
source="#Embed('theme/assets/MaxBackground.png')"/>
<s:BorderContainer id="layoutCanvas" width="100%" height="100%" visible="false">
<s:Image id="applicationClose" right="5" top="2"
click="stage.nativeWindow.close()"
source="#Embed('theme/assets/buttons/CLOSE WINDOW icon.png')"/>
<s:Image id="applicationMaximize" right="25" top="2"
click="stage.nativeWindow.maximize()"
source="#Embed('theme/assets/buttons/EXPAND WINDOW icon.png')"/>
<s:Image id="applicationMinimize" right="45" top="2"
click="stage.nativeWindow.minimize()"
source="#Embed('theme/assets/buttons/COLLAPSED WINDOW icon.png')"/>
</s:BorderContainer>
</s:WindowedApplication>
I have two issues.
1) the initial application window size. How can i set this to 100% full screen?
2) there is a strange grey horizontal footer at the bottom. How do i get rid of it? See here
I do not wish to use mx controls. I want to use sparks controls as much as possible.
Thank you.
1) the initial application window size. How can i set this to 100% full screen?
To do this you can add a CREATION_COMPLETE handler to your application and within that handler add a line similar to:
this.maximize() where this is you WindowedApplication.
2) there is a strange grey horizontal footer at the bottom
From the sounds of it, this is the status bar. Try setting the showStatusBar property on you WindowedApplication root tag to false :
showStatusBar="false"
Hope this helps.

Preventing ViewStack from Changing Index

I have a ViewStack, with a bunch of NavigatorContainers in. Each NavigatorContainer contains a different category of settings for the application.
I would like to be able to display a popup prompting the user if they try to leave the current NavigatorContainer without saving the changes they have made to the container's settings.
What would be ideal is something like the 'changing' event in the List component, whereby you are able to cancel or defer the event. Calling preventDefault() on the change event in ViewStack doesn't prevent the index change from happening.
Is there a way of doing this with a minimum of hoop-jumping?
Thanks
It depends what is changing your viewstack. For example if you have ButtonBar as view changer, then you can easily write like this:
protected function btnBar_changingHandler(event:IndexChangeEvent):void
{
event.preventDefault();
//enter code here
}
and
<s:VGroup width="100%" height="100%" horizontalAlign="center">
<s:ButtonBar id="btnBar" dataProvider="{viewStack}" requireSelection="true" changing="btnBar_changingHandler(event)">
<s:layout>
<s:ButtonBarHorizontalLayout gap="2" />
</s:layout>
</s:ButtonBar>
<mx:ViewStack id="viewStack" width="100%" height="100%">
<s:NavigatorContent width="100%" height="100%" label="First View">
<comp:FirstView/>
</s:NavigatorContent>
<s:NavigatorContent width="100%" height="100%" label="Second View">
<comp:SecondView/>
</s:NavigatorContent>
</mx:ViewStack>
</s:VGroup>
If nothing dreadful happens on index change, why not keep a current index and then in your change event just pop them back and give your alert?

Browser scrollbar issue when embedded with swf

I am developing a flex application which is embedded in a html file. The issue is I am not able to get the browser scroll bars, once the browser window resizes. I have tried setting overflow:scroll in the css code for html, but didn't work.
Consider an example like:
<?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="600" minHeight="400" width="100%" height="100%">
<s:BorderContainer left="30" right="30" height="120" width="100%" backgroundColor="#FFFFFF" borderVisible="true">
<s:Label x="10" y="10" fontSize="12" fontFamily="Arial" fontStyle="normal" text="PCA title"/>
</s:BorderContainer>
<s:BorderContainer left="30" right="30" top="150" height="100%" bottom="30" width="100%" backgroundColor="#000000" borderVisible="true">
</s:BorderContainer>
</s:Application>
Here if i set the absolute values for height and weight as height="768" and weight="1366", i do get the scrollbars. But i am developing the application using relative coordinates so that it works across all machines irrespective of their screen sizes. So, i cannot specify absolute value for height and weight.
Can someone help me with this as to how to get the scrollbars working without disturbing my relative coordinate system.
I'm not certain that I understand your question correctly, but I think you need SWFFit.
This is a JavaScript tool that can limit the minimum and maximum sizes of the container of your Flash object, and will force the browser to supply scrollbars when required.