Flex 4, Set variable in component skin from component - flex4

Given a custom component based on SkinnableContainer, how can I set values in the skin at runtime? Specifically, it is a whiteboard component with maxWidth and maxHeight values that indicate the smallest shared width/height of all the whiteboards in the conversation.
[Bindable]
public var maxWhiteBoardWidth:Number;
[Bindable]
public var maxWhiteBoardHeight:Number;
These values are used to draw guidelines on the surface of all the larger whiteboards in the conversation using stroke lines in the skin:
<!-- smallest common denominator boundaries -->
<s:Line left="300" top="0" bottom="0">
<s:stroke>
<s:SolidColorStroke weight="1" color="0xFFFFFF" />
</s:stroke>
</s:Line>
<s:Line top="300" left="0" right="0">
<s:stroke>
<s:SolidColorStroke weight="1" color="0xFFFFFF" />
</s:stroke>
</s:Line>
The value of 300 in the top and left attributes of s:Line should not be hard-coded into the skin. They should reflect the changing values of maxWhiteBoardWidth/maxWhiteBoardHeight from the component.
I am setting the skin using the skinClass attribute in MXML. Do I need to dynamically load the skin? If so when/how in the lifecycle?
I'm recently coming from Flex 3 so the Spark skinning architecture is still a bit murky. Thanks.

Try:
<s:Line left="{hostComponent.maxWhiteBoardWidth}" top="0" bottom="0">
...
</s:Line>
<s:Line top="{hostComponent.maxWhiteBoardHeight}" left="0" right="0">
...
</s:Line>
and make sure you have the metadata directive:
<fx:Metadata>
<!-- Specify the component that uses this skin class. -->
[HostComponent("my.component.MyComponent")]
</fx:Metadata>
otherwise your custom properties on the component will not be exposed to the skin properly.

Related

Using v-template outside of listView NATIVESCRIPT-VUE

I need to use a single v-template in my custom component like
<FlexboxLayout class="ticker-col" ref="tickercol">
<v-template name="charttemplate">
<Chart :chartData="chartData" />
</v-template>
</FlexboxLayout>
As mentioned on official docs (link), it says I have to use registerTemplate method. And I have to use a scopedSlot render function as 3rd parameter of this function. But I couldn't find out how to do this. My Chart component is still invisible.
mounted() {
const tickercol = this.$refs.tickercol;
tickercol.$templates.registerTemplate("charttemplate", null, 'what should be here?');
I'm not sure that I'm on the right way. Can anybody help?
Thanks in advance.

How to set custom style for blueprintjs component?

I am using blueprintjs with react and would like to customize blueprint component's size and color.
For example, I have a spinner, and would like to customize it size to 30px.
<Spinner className={'customSize'}/>
Which customSize is
.customSize{
width: 30px;
}
However, it's not going to overwrite original size.
Is there a possible way to customize the size or color of spinner?
Thanks
You can either write a more specific style than the one BlueprintJS supplies. They have quite strict opinions about how their toolkit is supposed to render.
They do support different sizes for the Spinner component though:
<Spinner size={SpinnerSize.LARGE} />
The options in the SpinnerSize constant are SMALL, STANDARD or LARGE. Those map to numbers, meaning the size prop expects a number. Why not try to give it our own number?
<Spinner size={137} />
You can learn more in the docs here.
For <Spinner> component
Size:
The size prop accepts a number including the following constants:
SpinnerSize.SMALL
SpinnerSize.STANDARD
SpinnerSize.LARGE
<Spinner size={SpinnerSize.LARGE} />
<Spinner size={128} />
Color:
As far as I know, there is no built-in component prop accepted to change the color. You can however customize the spinner's css classes:
// MyComponent.jsx
import styles from './MyComponent.module.scss'
<Spinner className={styles.mySpinner} />
/* MyComponent.module.css */
.mySpinner :global(.bp4-spinner-track) { /* Unspinning part of circle */
stroke: #000;
}
.mySpinner :global(.bp4-spinner-head) { /* Spinning head */
stroke: #fff;
}
Other components
Size:
Some have the large prop, few ones have also the small prop.
<InputGroup small />
<Switch large />
Color:
You can use CSS, but there are also some predefined color constants available in JS side: https://blueprintjs.com/docs/#core/colors
import { Colors } from "#blueprintjs/core"
<Button style={{ color: Colors.BLUE3, background: Colors.LIME2}}/>

Flex mobile resized image layout

I'm trying to display a resized image in a flex mobile application and I couldn't get it displayed correctly.
When set to width="100%" it looks OK. (Image 1)
When I scale it down to let's say 30% by Flex (scaleMode="letterbox"), it is scaled down, but the components above and below the image still keep the distance from the Image control as it were 100% height. (Image 2)
I tried dozens of layout tricks from autolayout=true to dynamically scaled elements, but couldn't find a solution. What am I doing wrong?
(I use Flash Builder 4.7, Flex 4.6 and Air SDK 13.0 on a 64-bit Win 7 Machine.)
Thank you for your answer, really appreciate it! However, this is unfortunately not a solution as it just sets the height the same as width. In this case, the two labels gets closer to the image, but not in the place where they supposed to go.
Meanwhile I could find a way to correctly resize the image along with its bounding box.
The main idea is to put the image in a container, and adjust the image size according to the ratio of the container size divided by the original image size.
Then the image will fully fill the container, and I can then set the desired scaling ratio by adjusting the container's width.
Here is my code that works perfectly, and I really hope that it will help someone else in the future:
<?xml version="1.0" encoding="utf-8"?>
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
import spark.components.Image;
private var img:Image = new Image();
private function init():void {
drawImg("assets/image.png");
}
private function drawImg(src:String):void {
img.source = src;
img.scaleMode = "letterbox";
img.smooth = true;
imgHolder.addElement(img);
img.addEventListener(FlexEvent.READY, imgStatus);
}
private function imgStatus(e:FlexEvent):void {
var imgw:Number = e.currentTarget.bitmapData.width;
var imgh:Number = e.currentTarget.bitmapData.height;
var ratio:Number = Number(imgHolder.width/imgw);
img.width = imgw*ratio
img.height = imgh*ratio
}
]]>
</fx:Script>
<s:VGroup width="100%" horizontalAlign="center">
<s:Label text="Foo" />
<s:HGroup id="imgHolder" width="30%" />
<s:Label text="Bar" />
</s:VGroup>
First I always got a null object, so I found that I need to listen for the image to be fully loaded, and now it works perfectly.
Again, the desired width property can be set on the container and not the image.
Here's a screenshot with the results.
The height of the image indeed remains untouched by only setting the image width.
If you draw a rectangle around the image you will see the bounding box with the same size all the time.
You can modify your code like the following to have a dynamic height and have the labels positioned as you wish:
<s:VGroup width="100%"
horizontalAlign="center">
<s:Label verticalAlign="bottom"
text="Foo" />
<s:Image id="img"
source="test.gif"
width="30%"
height="{img.width}"
scaleMode="letterbox" />
<s:Label verticalAlign="top"
text="Bar" />
</s:VGroup>

Problem with animation extender and IE9

I am using ajax animation extender in my application. It is working perfectly in almost all browsersexcept IE9. I am using the code as:
<cc1:AnimationExtender ID="OpenAnimation" runat="server" TargetControlID="btnAddNewComment"
BehaviorID="OpenAnimationBehavior">
<Animations>
<OnClick>
<Sequence>
<%-- Disable the button so it can't be clicked again --%>
<EnableAction Enabled="false" />
<%-- Position the wire frame and show it --%>
<StyleAction AnimationTarget="flyout" Attribute="display" Value="block"/>
<%-- Move the wire frame from the button's bounds to the info panel's bounds --%>
<Parallel AnimationTarget="flyout" Duration=".3" Fps="25">
<Resize Width="850" Height="420" />
<Color PropertyKey="backgroundColor" StartValue="#AAAAAA" EndValue="#FFFFFF" />
</Parallel>
<%-- Move the panel on top of the wire frame, fade it in, and hide the frame --%>
<StyleAction AnimationTarget="info" Attribute="display" Value="block"/>
<FadeIn AnimationTarget="info" Duration=".2" />
<StyleAction AnimationTarget="flyout" Attribute="display" Value="none"/>
</Sequence>
</OnClick>
</Animations>
</cc1:AnimationExtender>
Corresponding JS function to play the animation is:
// function to open the animation popup
function OpenExtender(tempCommentID)
{
var behaveYourself = $find("OpenAnimationBehavior");
var onClickAnimation = behaveYourself.get_OnClickBehavior();
onClickAnimation.play();
return false;
}
While clicking on button 'btnAddNewComment' a pop up is coming, but the problem is on mouse over the popup div. When i do mouse over over the popup, the popup get disappeared.
Could anybody say what will be the problem?
it seem to me, that IE9 doesn't remember the changes made via Animation Extender. Even the official sample doesn't work. If (for example) the Display: none, and you animated it to Dislay: block, when the animation stops it will revert do Display: none on the next redraw (you need to move mouse over the element, or otherwise invoke refresh). I hope it will be fixed really soon.
I realize the next step:
Remove the following code in the control called from the AnimationExtender:
"opacity: 0; filter: progid:DXImageTransform.Microsoft.Alpha(opacity=0);"
After that, the problem was fixed.

Flex 4 Bubbling custom event

How to create a bubbling custom event in Flex 4?
To create and expose a custom event in MXML, you need to declare it at the component that will dispatch the event with this line:
<fx:Metadata>
[Event(name="select", type="my.engine.events.SelectionEvent")]
</fx:Metadata>
This allows you to:
<my:CustomComponent select="doSomething()"/>
However, how do you make this bubble upwards. I want to do this
<s:DataGroup select="doSomethingForAll();">
<s:itemRenderer>
<fx:Component>
<my:CustomComponent/>
</fx:Component>
</s:itemRenderer>
</s:DataGroup/>
Thanks!
Your Custom event must extend Event. On constructor you'll find name:string, bubbling:boolean, and cacellable:boolean as arguments.
Set the bubbling parameter to true. In your example, the metadata tag must be in your DataGroup tag.
One possible solution but not exactly what i was looking for is to add this line of code at the DataGroup level.
this.addEventListener(SelectionEvent.SELECTED, onSelect);
This will ensure all events fired by CustomComponent is cought.
You can either extend s:DataGroup container with specified custom metatag data information built-in into the extended class or you can either call "doSomethingForAll()" method from itemRenderer's "select" event handler, see code below:
<s:DataGroup
dataProvider="{instructions}"
width="100%">
<s:itemRenderer>
<fx:Component>
<my:CustomComponent
select="rendererSelect()">
<fx:Script>
<![CDATA[
protected function rendererSelect():void
{
outerDocument.doSomethingForAll();
}
]]>
</fx:Script>
</my:CustomComponent>
</fx:Component>
</s:itemRenderer>
</s:DataGroup>
Catch the dataGroups select event and then dispatch a doSomethingForAll()
Make sure the doSomethingForAll event has it's bubbling property set to true.
Then any event listeners listening for doSomethingForAll above it in the display list will get called.

Resources