Using mx components in spark skins - apache-flex

Since fontSharpness and fontThickness don't work in Flex 4, as it says here (though I'd like to be proven wrong), I have replaced every <s:Label/> in my application with <mx:Label/>.
Though it works well in panels and dialogs, it doesn't work in skins.
When I add skin parts to skins, they should extend a predefined class.
Say for promptDisplay in TextInputSkin I cannot use this:
<mx:Label id="promptDisplay"/>
where this:
<s:Label id="promptDisplay"/>
is supposed to be, because promptDisplay should extend an IDisplayText.
What is the best workaround for this?

Well, I suppose the quickest workaround would be to create your own Label class by subclassing mx Label and implementing IDisplayText. Something like this:
import mx.controls.Label;
public class MyLabel extends Label implements IDisplayText {
public function get isTruncated():Boolean {
return false;
}
}
Now you can use MyLabel wherever an IDisplayText is required and apply fontSharpness and fontThickness to it, since those two styles are inherited.
Be warned though that this will not work if a TextBase is required.

Related

javafx - easiest way of changing the caret color

I would like to set the caret color for all JavaFX text inputs (e.g. TextField, TextArea, the ones in ComboBox:editable, DatePicker, etc...)
I found this Stackoverflow answer: How to change the caret color in JavaFX 2.0?
... and an example on GitHub.
The first one does change the text and the caret color which is not good. The second one extends the TextFieldSkin class, which is already better, but how can I use it in CSS?
Any help is appreciated.
UPDATE 1:
I found the following CSS style property for JavaFX controls: -fx-skin.
This would theoretically allow me to set a custom skin class (-fx-skin: "package.MySkin";), however, the skin class just isn't used!
The class looks like the following:
package gui;
…
public class MyTextFieldSkin extends TextFieldSkin
{
public MyTextFieldSkin(TextField tf) {
super(tf);
System.out.println("MyTextFieldSkin constructor called!");
ReadOnlyObjectWrapper<Color> farbe = new ReadOnlyObjectWrapper<>(Color.green);
caretPath.strokeProperty().bind(farbe);
caretPath.setStrokeWidth(1.5);
}
}
… and is set in CSS like that:
.text-field {
-fx-skin: "gui.MyTextFieldSkin";
}
What am I doing wrong? I looked at the source code of AquaFX, and they are doing it the same way as me!
After a bit of try & error, I solved the problem in the following way:
I gathered all TextFields and controls that have TextFields in them (like ComboBox, DatePicker and so on) inside a container recursively (in deference of TitledPane, ScrollPane, SplitPane and TabPane, because they don't publish their children in getChildren(), so one has to call the getContent() method of the individual classes and scan through it).
After I had all the TextField controls, I looped over them and changed their Skin with the following code:
public class MyTextFieldSkin extends TextFieldSkin {
public MyTextFieldSkin(TextField tf)
{
super(tf);
ReadOnlyObjectWrapper<Color> color = new ReadOnlyObjectWrapper<>(Color.RED);
caretPath.strokeProperty().bind(color);
}
}
Then I just had to call
textfield.setSkin(new MyTextFieldSkin(textfield));
and that was about it.
Cheers

Integrating Actionscript classes into Flex

I am trying to learn Flex and Actionscript. I found the Moock quiz example in Flash and want to turn it into a Flex application. I am trying to understand the relationship between the actionscript and the mxml. How do I take the class QuizApp and place its contents in a container in the mxml file?
MXML
<fx:Script>
<![CDATA[
import QuizApp;
var ms:QuizApp = new QuizApp;
protected function init():void
{
msc.addChild(ms);
}
]]>
</fx:Script>
<mx:VBox id="msc" />
Class
package {
import flash.display.Sprite;
import mx.controls.Button;
import flash.events.MouseEvent;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
public class QuizApp extends Sprite {
//for managing questions:
private var quizQuestions:Array;
private var currentQuestion:QuizQuestion;
private var currentIndex:int = 0;
public function QuizApp() {
quizQuestions = new Array();
createQuestions();
createButtons();
createStatusBox();
addAllQuestions();
hideAllQuestions();
firstQuestion();
}
... etc
}
}
I am trying to understand the relationship between the actionscript
and the mxml.
MXML is an ActionScript code generation language. When you write MXML, the Flex compiler does some "magic" to turn your MXML file into an ActionScript class. You can save this generated code by specifying the 'keep-generated-actionscript' argument to the Flex Compiler. I'll often shorten it to'-keep' and it works fine.
MXML masks a lot of the complexity that is going on under the scenes.
I hope that helps set your frame of expectations.
To use your "Flex agnostic" ActionScript Sprite Class inside of a MX Flex Container, you should be able to use it just like any other class you create. First, import the namespace at your top level tag of your component:
myNamespace:xmlns="*"
Then you should be able to use it, like this:
<myNamespace:QuizApp id="quizAppInstance" />
If you're using a Flex 4 Spark Container, you need something that implements IVisualElement; which a Sprite does not. However, you can wrap your own class inside of a SpriteVisualElement class without too much effort.

how to specify height and width of flex alert box in css?

In my Flex 4 app I would like all my alert boxes to be a specific width and height, how do I specify that in the CSS? I want to avoid having to specify the width and height every time I want to show an alert, that's why I'd like to set it in the CSS, but does not look like there's a way to..
Something like this does not work:
mx|Alert
{
height: 100;
width: 300;
}
You can do it Using Style + Code like this
Define Style Properties as
Alert {
height:300;
weight:300;
}
Note: height and weight are not default style of Alert
Using them in Code as
var alert:Alert = Alert.show("Hello World");
alert.explicitHeight = Number(alert.getStyle("height"));
alert.explicitWidth = Number(alert.getStyle("weight"));
Working example of Flex3 is
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
creationComplete="{show()}">
<mx:Style>
Alert {
height:300;
weight:300;
}
</mx:Style>
<mx:Script>
<![CDATA[
import mx.controls.Alert;
private function show():void
{
var alert:Alert = Alert.show("Hello World");
alert.explicitHeight = Number(alert.getStyle("height"));
alert.explicitWidth = Number(alert.getStyle("weight"));
}
]]>
</mx:Script>
</mx:Application>
Explanation
Since Alert Control by default not support height and weight style, so example used them just for holding user defined values as variable.
In routine to display Alert/Popup on screen Static method show of class Alert is used, which returns the instance/object of created/active Alert/Popup, using this refrence its properties can be manipulated at runtime as done in above example i.e. explicitHeight and explicitWidth.
Hopes that Help
CSS can only be used to set Style properties of components. There are no dimension based style properties for the mx:Alert as you can see here - although there is one to adjust the height of the header named 'headerHeight'.
You could try extending the mx:Alert class and giving it new style properties that would allow you to change the dimensions via CSS. Or you could extend the class and give it default dimensions in its constructor.
You can't do it out of the box, but you could do it by extending your Alert and adding your own logic in the updateDisplayList to check for the style and change the property appropriately.
Generally not recommended however. Just use the properties given to you instead.

How do I change a box components direction in Flex 3?

With mx:Box I can set the direction to be either "horizontal" or "vertical". I'd like to reverse the order of the components in the box though. For example:
before:
|button1| |button2| |button3|
after:
|button3| |button2| |button1|
I've created a custom component that lives in a mx:Box and would like to do this in as simplest a way as possible.
Any help appreciated,
Many thanks,
Bryn
The simplest that comes to mind is to override the addChild method in Box:
import mx.containers.Box;
public class ReverseBox extends Box
{
public override function addChild(child:flash.display.DisplayObject):flash.display.DisplayObject
{
return addChildAt(child, 0);
}
}
hth
Koen

Flex: Label.addChild() not working?

I want to make a label that has a tiny title above it, for example so the label say $1,000 with a small retail price or our price above it. I am trying to add the title label to the display list of the main label. I get no error but the title does not show up. I also considered rawChildren but apparently Label has no rawChildren property.
Here is my code:
package
{
import mx.controls.Label;
public class PriceLabel extends StrikeThroughLabel //<-- exntension of label to add strike
{
private var _title:Label;
public function PriceLabel()
{
super();
}
[Bindable]
public function set title(s:String):void
{
if(_title == null)
{
_title = new Label();
addChild(_title);
this.alpha = .2;
}
_title.text = s;
}
public function get title():String
{
var s:String
if(_title != null)
{
s = _title.text;
}
return s;
}
}
}
If you add children to a Flex component that is not a container, then you have to manually manage sizing and positioning of those children. Containers do a lot of that work for you.
Here's what you should do:
Move the creation of your child Label into an override of the createChildren() function.
Set the text property of the child label in an override of the commitProperties() function. Your title getter and setter should save the value in a _title variable to be used later for the assignment in commitProperties(). This is actually important for performance.
Override the measure() function and update measuredWidth and measuredHeight to be the maximum width and height values of the main label and it's child.
Override updateDisplayList() and use setActualSize() on the child Label to set it to the required width and height.
That may seem like a lot of work, but in terms of best practices, that's the way you're supposed to build custom components. The Flex Team at Adobe spent a lot of time maximizing performance, and that's why things happen in several steps like that.
That's how to do it based on what you asked. Personally, I would make a subclass of UIComponent with two Labels or UITextFields as children, each with their own separate property.
By the way, the rawChildren property is only available on containers. It exists so that you can add "chrome" to a container that isn't part of the container's child layout algorithm. For example, Panel has a title bar and a border that aren't affected by the vertical/horizontal/absolute layout options.
Why not create a custom component that contains both labels as its children, instead of trying to throw a child on the Label? That feels cleaner to me, as adding children to build-in components like that doesn't seem right.

Resources