Howdy!
Ive finally managed to get round to releasing haxeui v1.3 to haxelib. I cant believe its been 5 months since the 1.2.3 release! Time really does fly.
This release is a general release and although a massive amount of things have changed there isnt that much to go over (compared to previous releases at least). There are some big changes but alot of this release is refinement and bug fixing.
Breaking Changes
So there have been a number of breaking changes this release. Almost all of them revolve around issues identified where references to components were being brought in unnecessarily (which iI’ll go over in a little more detail later).
Dialog shortcuts moved
Prior to this release, you could show a custom dialog or a message box quite simply with one of these calls:
Toolkit.messageBox(...)
Toolkit.dialog(...)
Screen.instance.messageBox(...)
Screen.instance.dialog(...)
The problem with these calls being in such a fundamental part of haxeui is that if you werent using dialogs at all (which would certainly be quite common) then you were pulling in all the code and components for Dialog
anyway.
These calls have now been moved to a Dialogs
helper class (package: haxe.ui.containers.dialogs
), eg:
Dialogs.messageBox(...)
The function signature is exactly the same, and by moving it to a separate, non “core” class it makes usage of dialogs (and therefore inclusion of its dependencies) much more explicit.
Note that “normal” custom dialog usage remains the same:
var myDialog = new MyDialog();
myDialog.show();
Toolkit.componentFromString
in a similar vein prior to this release it was possible to create a component from a string at runtime using Toolkit.componentFromString
. To be honest, I seriously doubt this function is ever used to any great degree (though I do know of at least one project that does use it). Much like the dialog issue above this also brought in a number of dependencies unnecessarily - not a huge amount, but enough to warrant it to be refactored out. This call has now moved to haxe.ui.RuntimeComponentBuilder.fromString
.
Another (non breaking) change is that components built at compile time can now use a differently named set of macros (these are really just aliases to make things simpler):
haxe.ui.ComponentBuilder.fromString(...)
haxe.ui.ComponentBuilder.fromFile(...)
haxe.ui.ComponentBuilder.build(...)
The previous macros are still available, but these are shorter, neater and “fit” with the new RuntimeComponentBuilder
Component aliasing removed
One of the major things that was identified in this release was how the haxeui component macros were bringing in a reference to every component when it scanned the class path and build up a “component class map”! I’ll get into the details a little more later, but suffice to say that you used to be able to define an alias for a component for use with xml in your module.xml
:
<module>
<components>
<class name="foo.bar.MyComponent" alias="myfoo" />
</componens>
</module>
This would mean you could use “mycomponent” or “myfoo” in your xml. This is no longer an option. The way that tags are resolved to classes has changed now, and aliasing is no longer simple or feasible. If you really want to use “myfoo” you could always just create a new class: class MyFoo extends MyComponent
haxeui-html5 no longer supports native components
The haxeui-html5 backed used to be able to use native components (where they were available - eg buttons, sliders, scrollers, etc). This functionality has been stripped now and a new backend has this functionality haxeui-html5-native
- the reasoning for this is pretty much the same as all the above - this feature (rarely used i suspect) was bringing references to components and other bits of code that simply were not relevant for 99% of use cases. If you want a browser native UI, then you can use haxeui-html5-native
as a drop in replacement that will allow this.
Thats it, as far as I remember, for the breaking changes. I really hope these wont cause too much friction upgrading but they were really quite important to get haxeui file sizes nice and trim, dependencies at a minimum and build speed as fast as possible.
Now thats out the way, some of the more interesting changes!
Removal of hscript!
HaxeUI always had a dependency on hscript. It used this for various things, but mainly it was for allowing code to run at runtime (usually inside <script>
tags, but also for event handlers in xml and other things). This not only added a layer of complexity it also caused various DCE and runtime related problems (or potential problems at least).
This dependency has now been totally removed. If you use code in your xml files, or handlers, etc then, at compile time that “script” code is injected into your class (if you are using a custom xml component) or into you function (if you are using haxeui expression macros), this has a bunch of benefits and side effects.
The most obvious is that you will get compile time errors if your code doesnt make sense. Previously this would have been a runtime error.
Performance is better. This, to me, wasnt a big issue but its nice to have anyway. Since now your script code will be real haxe code it will have the same performance as the underlying haxe target you are using (it wont need to pass through an interpreter etc).
You can do “crazy” things now since your script code will essentially be injected into your class, eg:
<vbox>
<script>
private override function onReady() {
super.onReady();
trace("Im ready!");
}
</script>
</vbox>
Here the onReady
function will be injected into the class as an override for a haxeui core function. If the “old” hscript method was being use this simply wouldnt be possible without some (overly complex) layer to call the appropriate script function when haxeui calls “onReady”.
Its probably worth noting that i 100% do not advocate things like this - its very ugly in my opinion and completely breaks separation of UI and logic. But its there, and ready to be abused should your wish to
All in all the hscript removal was super essential. It had wormed its way into so many subsystems (language binding, component binding, even parts of the module resolution phase in the macros!) - All of these systems now work much better, much simpler and a whole bunch of code was deleted because of it. I can only hold my hand up a plead total laziness for letting it get into so many parts of haxeui!
ComponentClassMap populated on demand
Another massive oversight on my part was how haxeui was resolving xml node names → component classes. Previously it would scan the entire class path looking for Component
derived classes and add them to a class map ready for lookup. This, upon reflection, was just such a dumb idea.
The biggest issue with it is that it used getType
/ getModule
. I had no idea, but using these functions in a macro actually created a reference to that component. So this meant that every single component that was discovered by the macros (ie, all of them) had a reference created and was brought into the the final output. Needless to say, this was a little crazy!
Another issue with this method was that if you never used the xml / markup part of haxeui, well, you were still scanning the classpath, still building up a map of all components that would, essentially, never be used. So your build time would be longer for no reason what-so-ever.
Both of these issues have now been rectified. When haxeui builds a component from xml / markup and wants to find a classname based on a node name it then scans the classpath looking for matches (unless its already found one previously in which case it will just use that one). This has a number of improvements, namely the things mentioned above. References are not brought in for no reason, the entire class path isnt scanned (just until it finds a match the first time) and if you arent using xml at all, then you dont scan the class path at all, ever.
This drastically improves build time and final output size. For example, previously a simple “1 button” application brought in a reference to every component and container (), would take about 4 seconds to build a JS output and would weigh in at a whopping 1.8mb.
With this new “on demand” lookup system (and some of the other enhancements above), the same app takes about 1.3 seconds to build, has a file size of around 650kb (130ish zipped) and has a totally sensible set of dependencies.
im almost sure there is some more fat to trim, but this is a pretty important step and fixes an absolutely huge oversight on my part regarding creating a reference to every component ( - it deserves another facepalm!)
As part of this ive create a tool to track down dependencies that has been pretty invaluable: Dependency Analyzer
New Component - SideBar
Its been there for a while, but there is a new component in haxeui: SideBar
as you gather this allows you slide in content from top / bottom / left / right and can optionally “sqaush” / “shift” the content beneath it.
Click here to see it in action http://haxeui.org/shared/sidebar5.gif (its a huge gif so cant be rendered into the page)
Usage is prtty simple, its basically the same as dialogs from an API perspective:
var sidebar = new MySideBar();
sidebar.method = "squeeze"; // default is "float"
sidebar.position = "bottom"; // default is "left"
sidebar.show();
You can build the sidebar with xml if you want, or plain code, any way that you build any other component.
DataSource filtering and sorting
DataSources can now be filtered and sorted. This has been on my todo list for quite a while and has finally made its way into core. Filtering can be achieved with:
myDataSource.filter(function(index, item) {
return index % 2 == 0; // this example will filter out any odd items
});
The type of item
will be whatever the type of the datasource is, ie, if its DataSource<Int>
then item
will be Int
.
Sorting works pretty similar - the big difference is that there is a helper function to perform an alpha-numeric sort, some examples:
myDataSource.sort(SortDirection.DECENDING);
myDataSource.sort("someField", SortDirection.DECENDING);
myDataSource.sortCustom(function(item1, item2) {
return 0;
});
For both filtering and sorting, if the data sources are attached to something like a TableView
or ListView
then the order / items will reflect the sorted / filtered data source contents.
Also, for TableView
specifically, sorting can be linked up very easily be doing something similar in the table header:
<header width="100%">
<column width="32" id="colX" sortable="true" sortField="imageIndex" />
<column width="32" id="colA" sortable="true" />
<column id="colB" width="180" text="Progress" sortable="true" />
<column width="100%" id="colC" text="Status" sortable="true" />
</header>
(obviously thats using xml, but the same applies to using it from code).
New Slider properties
Sliders (both vertical and horizontal) get some snazzy new properties:
-
center
this is where the “center” of the slider is calculate at -
step
this will what increments the slider value will go up by -
minorTicks
this will define how often to draw small “tick” lines -
majorTicks
this will define how often to draw larger “tick” lines
New Backend: haxeui-raylib
HaxeUI has yet another backend. This time using the pretty amazing RayLib. This started off by spending a little bit of time writing externs for raylib (https://github.com/haxeui/raylib-haxe/) for no particular reason. Then, to test them, i thought about playing with a backend - i had no intention of making it official. Very very quickly it all came together and once it had full text input (modeled after haxeui-kha) I decided it should become a full, official backend! Theres not much in the way of instructions at the moment, but its pretty simple, and pretty much like every other haxeui backend. haxelib run haxeui-core create raylib
in a blank directory will create a skeleton project.
Notable Mentions
As usual, this “wall of text” has gotten away from me, and im running the risk of rambling on and on. This has been another really big release, and long overdue, an untold amount of bug fixes and enhancements. And great feed back from a bunch of project authors.
One i would like to highlight is “kLabs” 100% native TODO app that uses haxeui-hxwidgets and coconut.ui (coconut.haxeui)
This has been an extremely interesting app to watch evolve since its using a 100% native backend and a coconut.ui which, although i dont know that much about it, i know its pretty damned cool. So seeing it play well with a native UI has been great. Its also been a good source of bugs (and fixes) for hxWidgets and haxeui-hxwidgets
Some other very small additions that come to mind are
- full list of html colours can be used in styles, etc (thanks Joe!)
- when using “file://something.png” in image resources, paths relative to the executable work - tiny change but essential
- ability to omit the root node when importing xml from an external file via the
omitRoot
property on<import>
- another small but useful change
So I think thats it for now. Ill try and not a) leave the next update so long b) not ramble so much in the release details
Cheers,
Ian