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

Using Controllers

Ian Harrigan edited this page Nov 13, 2015 · 1 revision

Controllers can be used to split your code into modules on a more manageable level than a single class holding all your applications' logic and UI.

Logic and UI that is related to each other should be bundled together in a single class, and HaxeUI can do much to make the UI part painless. The Controller class and its subclasses are responsible for managing a subset of your applications controls. The root of this subset is accessible via the view property, and child controls can be manipulated using addChild, getComponent and similar methods.

All that remains (when using a suitable subclass such as XMLController) is to add your own methods for handling the logic.

Hello World using XMLController

We can reuse the "hello-world.xml" file from "XML Based UIs" with just a single modification here; the addition of an id to our button. This will allow us to look up the control by name using methods like attachEvent and getComponentAs.

<?xml version="1.0" encoding="utf-8" ?>
<button id="myButton" text="Click Me!" />

Now we subclass XMLController and pass it the resource id of our xml file as the argument to its constructor. Notice that we are passing a named function rather than an anonymous function to attachEvent now. Separation in this manner makes it possible to write clearer code without fear of accidentally stepping on the names or logic of an unrelated part of your application (any large application is going to have many OK buttons for instance).

import haxe.ui.toolkit.controls.Button;
import haxe.ui.toolkit.core.XMLController;
import haxe.ui.toolkit.events.UIEvent;

class HelloWorldController extends XMLController {
	public function new ():Void {
		super ("hello-world.xml");
		attachEvent ("myButton", UIEvent.CLICK, myButtonClicked);
	}
	private function myButtonClicked (e:UIEvent):Void {
		getComponentAs ("myButton", Button).text = "You clicked me!";
	}
}

Now we can instantiate as many instances of HelloWorldController as we wish, all of which act independently and without impacting any other module.

class Main {
	public function new ():Void {
		Toolkit.theme = new GradientTheme();
		Toolkit.init();
		
		Toolkit.openFullscreen(function (root:Root) {
			var vbox = new VBox ();
			for (_ in 0...3)
				vbox.addChild (new HelloWorldController ().view);
			root.addChild (vbox);
		});
	}
}

Using Macros.buildController

In order to reduce the amount of `boilerplate' code involved (and associated typos and bugs) in the creation of new controllers HaxeUI provides a macro to automatically build private members for each of the named components in the UI.

This not only reduces the amount of typing needed but allows static type checking to be performed giving you more chances to catch mistakes at compile time.

Here is the same example as before, but this time using Macros.buildController.

import haxe.ui.toolkit.controls.Button;
import haxe.ui.toolkit.core.XMLController;
import haxe.ui.toolkit.events.UIEvent;

@:build(haxe.ui.toolkit.core.Macros.buildController ("assets/hello-world.xml"))
class HelloWorldController extends XMLController {
	public function new ():Void {
		myButton.addEventListener (UIEvent.CLICK, myButtonClicked);
	}
	private function myButtonClicked (e:UIEvent):Void {
		myButton.text = "You clicked me!";
	}
}

Wrapping Controllers in Components

For some applications it may be helpful to be able to instantiate controllers from your ui xml. A small custom component can be used to achieve this effect.

import haxe.ui.toolkit.containers.Box;

class HelloWorldControllerComponent extends Box {
	public var controller (default, null):Null<HelloWorldController> = null;
	public static function init ():Void {
		ClassManager.instance.registerComponentClass (HelloWorldControllerComponent, "helloworldcontroller");
	}
	override public function initialize ():Void {
		super.initialize ();
		controller = new HelloWorldController ();
		addChild (controller.view);
	}
}

Then the previous example can then be recreated using a new xml file controllers.xml:

<?xml version="1.0" encoding="utf-8" ?>
<vbox>
	<helloworldcontroller />
	<helloworldcontroller />
	<helloworldcontroller />
</vbox>
class Main {
	public function new ():Void {
		Toolkit.theme = new GradientTheme();
		Toolkit.init();
		HelloWorldControllerComponent.init();
		
		Toolkit.openFullscreen(function(root:Root) {
			root.addChild(Toolkit.processXmlResource("assets/controllers.xml"));
		});
	}
}

What Next:

Not Covered Yet:

  • Add application logic to Controllers
  • Subclassing/using Controller rather than XMLController
  • Adding events to Controllers