Skip to content
This repository has been archived by the owner on Oct 14, 2019. It is now read-only.

Styling

Ian Harrigan edited this page Nov 13, 2015 · 9 revisions

There are various ways to style components in HaxeUI. The following page will describe the options available for styling as well as their pros and cons (where appropriate).

Styling from code

Styling individual components one by one in code is probably the most straight forward method to add custom styles to components, however, because of limitations and verbosity it isnt really recommended and is simply listed here for completeness.

var button:Button = new Button();
button.x = 100;
button.y = 100;
button.style.width = 150;
button.style.height = 100;
button.style.color = 0xFF00FF;
button.style.icon = "assets/fav_32.png";
button.style.iconPosition = "top";
button.text = "Styled";
root.addChild(button);

As you could imagine, styling this way is extremely verbose and would require styling each component individually. A better idea would be to use the StyleManager to define rules that will be applied to components when they initialize.

Using the StyleManager

A much better way to style from code would be to add custom rules to the StyleManager class that will be applied to the correct component each time a match is found. The following rule will result in the exact same button as displayed above.

StyleManager.instance.addStyle("Button", new Style({
    width: 150,
    height: 100,
    color: 0xFF00FF,
    icon: "assets/fav_32.png",
    iconPosition: "top",
}));

The rule here is simply "Button", this means that any button that you create will now have these style properties applied to it, this is clearly not ideal a better way would be to either use an id or a styleName, a new, better rule could be any of the following

Button.myStyle
.myStyle
#myButton
#myButton.myStyle

All of these rules will select the same style if you give your button an id of "myButton" or the button a style name of "myStyle". A full example of this is shown below.

import haxe.ui.toolkit.containers.HBox;
import haxe.ui.toolkit.controls.Button;
import haxe.ui.toolkit.core.Root;
import haxe.ui.toolkit.core.Toolkit;
import haxe.ui.toolkit.style.Style;
import haxe.ui.toolkit.style.StyleManager;
import haxe.ui.toolkit.themes.GradientTheme;

class Main {
    public static function main() {
        Toolkit.theme = new GradientTheme();
        Toolkit.init();
        Toolkit.openFullscreen(function(root:Root) {
            StyleManager.instance.addStyle("Button.myStyle, .myStyle, #myButton, #myButton.myStyle", new Style({
                width: 150,
                height: 100,
                color: 0xFF00FF,
                icon: "assets/fav_32.png",
                iconPosition: "top",
            }));
			
            var hbox:HBox = new HBox();
            hbox.x = 10;
            hbox.y = 10;
			
            var button:Button = new Button();
            button.text = "Normal";
            hbox.addChild(button);

            var button:Button = new Button();
            button.text = "#myButton";
            button.id = "myButton";
            hbox.addChild(button);

            var button:Button = new Button();
            button.text = ".myStyle";
            button.styleName = "myStyle";
            hbox.addChild(button);

            var button:Button = new Button();
            button.text = "myButton.myStyle";
            button.id = "myButton";
            button.styleName = "myStyle";
            hbox.addChild(button);
			
            root.addChild(hbox);
     });
}

Styling by component location

Another useful feature of the style system is being able to apply styles based on where a component is inside the component hierarchy, for example rules like this are completely valid:

HBox #myButton
Root HBox #myButton

The rule set doesnt have to list all the components between nodes. The style system will match the next available component, so if you had

Root -> VBox -> HBox -> VBox -> Button

On the display tree then the rule set

Root HBox Button

Would match it fine. A good example of how this works is found inside gradient.css. The snippet below (extracted from gradient.css) shows how the buttons (up,down,thumb) are styled differently in the vertical scrollbar from the standard gradient buttons and how each one has a different icon.

VScroll Button {
	backgroundColor: 0x606c88;
	backgroundColorGradientEnd: 0x606c88;
	borderColor: 0x606c88;
	cornerRadius: 1;
	filter: null;
	iconPosition: "center";
}

VScroll Button:over {
	backgroundColor: 0x4b546a;
	backgroundColorGradientEnd: 0x4b546a;
	borderColor: 0x4b546a;
}

VScroll Button:down {
	backgroundColor: 0x4b546a;
	backgroundColorGradientEnd: 0x4b546a;
	borderColor: 0x4b546a;
}

VScroll Button:disabled {
	backgroundColor: 0x8C8C8C;
	backgroundColorGradientEnd: 0x8C8C8C;
	borderColor: 0x8C8C8C;
}

VScroll Button.up {
	icon: "styles/gradient/arrow_up.png";
}

VScroll Button.down {
	icon: "styles/gradient/arrow_down.png";
}

VScroll Button.thumb {
	icon: "styles/gradient/gripper_vertical.png";
}

VScroll Button.thumb:disabled {
	icon: "styles/gradient/gripper_vertical_disabled.png";
}

VScroll Button.up:disabled {
	icon: "styles/gradient/arrow_up_disabled.png";
}

VScroll Button.down:disabled {
	icon: "styles/gradient/arrow_down_disabled.png";
}

As you might have noticed from the css above each control can also define a set of "states", this are denoted with the ":{stateName}" selector. Each of the states are component specific and will be listed on their respective wiki and api pages pages. So the ruleset

VScroll Button.up:disabled

Will select any Button that has an ancestor of VScroll, a styleName of "up" (ie, the deincrement button) and will set the ":disabled" state style.

Loading css resources

As usual for HaxeUI you can also load resources from the file system at compile time or from assets at run time. Loading compile time style resources is done with the call

Macros.addStyleSheet("assets/myStyles.css");

This is really just a utility function to generate the code as if you loaded the style by hand and added it to the StyleManager. Loading style assets at runtime is achieved in a similar fashion with the following snippet:

StyleManager.instance.addStyles(StyleParser.fromString(ResourceManager.instance.getText("assets/myStyles.css")));

As you can see loading styles in runtime takes a few more steps and it is recommended just to use the Macro.addStyleSheet approach. The runtime styles are mainly used if you are using styles inside xml (covered below)

Using styles in xml interfaces

As discussed previously, a much better way to create HaxeUI interfaces is using xml markup to define interface components. As well as including ui components, it is also possible to add style definitions in xml also. Consider the following example that will result in exactly the same output as full example used here

<?xml version="1.0" encoding="utf-8" ?>
<hbox x="10" y="10">
	<style>
		Button.myStyle, .myStyle, #myButton, #myButton.myStyle {
			width: 150;
			height: 100;
			color: #FF00FF;
			icon: "assets/fav_32.png";
			iconPosition: "top";
		}
	</style>
	<button text="Normal" />
	<button text="#myButton" id="myButton" />
	<button text=".myStyle" styleName="myStyle" />
	<button text="myButton.myStyle" id="myButton" styleName="myStyle"/>
</hbox>

Inline styles

Quite often is needed that we simply want to tweak a current style and not go through the bother or setting up a specific rule for it inside the StyleManager, this can be achieved in an XML based UI by simply using the style attribute to define inline styles as follows:

<?xml version="1.0" encoding="utf-8" ?>
<button text="Inline Style" x="100" y="100" style="fontSize: 40" />

Full example

A full example of how to use styles from XML is listed below

<?xml version="1.0" encoding="utf-8" ?>
<hbox x="10" y="10" style="padding: 10; spacing: 10; borderColor: #FF0000; borderSize: 2; cornerRadius: 5; backgroundColor: #FFAAAA">
	<style>
		Button.myStyle, .myStyle, #myButton, #myButton.myStyle {
			width: 150;
			height: 100;
			color: #FF00FF;
			icon: "assets/fav_32.png";
			iconPosition: "top";
		}
	</style>
	<button text="Normal" />
	<button text="#myButton" id="myButton" />
	<button text=".myStyle" styleName="myStyle" />
	<button text="myButton.myStyle" id="myButton" styleName="myStyle"/>
	<button text="Inline" style="fontSize: 18" />
</hbox>

Then to load the xml definition

import haxe.ui.toolkit.core.interfaces.IDisplayObject;
import haxe.ui.toolkit.core.Root;
import haxe.ui.toolkit.core.Toolkit;

class Main {
    public static function main() {
        Toolkit.theme = new GradientTheme();
        Toolkit.init();

        Toolkit.openFullscreen(function(root:Root) {
            var view:IDisplayObject = Toolkit.processXmlResource("assets/styles.xml");
            root.addChild(view);
        });
    }
}

What Next:

See Also: