FeathersUI backend for coconut.ui

Regarding issues with lix and lime there are some discussion already, but basically can not invoke lime from lix, could be because lime sets global variables

For events now think what would be the best approuch as feathers uses add/remove event, so need to create new attributes with macro that can add these events, just not sure if its possible to add only valid events as then need to have some mapping events → component, or just add all of them for every component :slight_smile:

I could probably add some metadata to each component that lists the events that the component dispatches. You could check for it in the macro.

@Hersir I just pushed a commit to Feathers UI with some extra metadata for events.

One or more instances of @:event metadata are added to each component class, and they might look something like this:

@:event("change", openfl.events.Event)
@:event("stateChange", feathers.events.FeathersEvent)

I tested in a macro, and I was able to read all of the events on a class like this:

var eventMeta = theClass.meta.extract(":event");
for (meta in eventMeta) {
	var constant = meta.params[0];
	var type = meta.params[1];
	var eventName = ExprTools.getValue(constant); // example: change
	var typeName = ExprTools.toString(type); // example: openfl.events.Event
}

Side note: I tried using a single expression, like the one below, but I couldn’t for the life of me figure out how to make a macro resolve the original string value.

@:event(openfl.events.Event.CHANGE) // not sure how to resolve

You will need to check the super classes for @:event metadata too. For instance, FeathersControl has metadata for the “initialize” event, but its subclass Button does not because that would be redundant.

Any events inherited from classes like openfl.display.Sprite won’t have @:event metadata, so to expose those events, you’ll need to hard-code them. That should be a lot easier than trying to hard-code the Feathers UI events, though.

Thanks will take a look at the weekend

The safest path is via the typed AST:

switch Context.typeExpr(e).expr {
  case TField(_, FStatic(_.get() => cl, _.get() => f)):
    trace(cl.pack.concat([cl.name]).join('.') + '.' + f.name + '=' + TypedExprTools.toString(f.expr()));
  default:
}

In this case you’ll find that f.expr().expr is TConst(TString(v)) where v is the value you’re after.

1 Like

Thank you, Juraj!

1 Like

Got first success, parsed events and now can call them, still support only trigger for button but will add other types as well, will think how to explain renderer what are events and what not

1 Like

Transferred repo to new account

will try to finalize event support and make it better typed, but could be will need more workshops from @back2dos regarding macros :smiley:

1 Like

Still need global install from libs as lime still dont work with local lix

I’ll try to fit in some time this week to change the event metadata to look like this:

@:event(openfl.events.Event.CHANGE)

I’ll post here when I’ve made that change.

The macro code to parse this style is in this post from @back2dos.

Ok, will update when it will be available

@back2dos @joshtynjala made pull request for event support, feel free to add any comments suggestions :slight_smile:

Soon could be released as haxelib, so could get more feedback.

@joshtynjala I used ValidateSprite as base type, I hope that is ok, as could not find any use case for openfl sprite usage directly in feathersui

I just pushed the commit that updates the @:event annotations to use this style instead.

@:event(openfl.events.Event.CHANGE)

OK will update my pull request

I was playing around with the @:event metadata yesterday, and I wrote a couple of helper functions for a macro I was working on. I figured I’d share, in case it might help anyone.

The first gets all of the @:event MetadataEntry values from a class and its superclasses:

private static function getAllEvents(type:ClassType):Array<MetadataEntry> {
	if (type == null) {
		return [];
	}
	var events = type.meta.extract(":event").filter(eventMeta -> eventMeta.params.length == 1);
	var superClass = type.superClass;
	if (superClass != null) {
		for (event in getAllEvents(superClass.t.get())) {
			events.push(event);
		}
	}
	return events;
}

The second gets the string value from the referenced event.

private static function getEventName(eventMeta:MetadataEntry):String {
	var typedExprDef = Context.typeExpr(eventMeta.params[0]).expr;
	return switch (typedExprDef) {
		case TCast(e, m):
			switch (e.expr) {
				case TConst(c):
					switch (c) {
						case TString(s): s;
						default: null;
					}
				default: null;
			}
		default: null;
	};
}

You can use a single switch case :wink:

switch typedExprDef {
  case TCast({expr: TConst(TString(s))}, _): s;
  case _: null;
}
5 Likes

Made changes to support new event syntax, still some things to improve but it can be used with newest git version, also made haxelib release, there is example in test folder with usage.
@joshtynjala haxelib version

1 Like

Nice work and I would love to know more about this project. From what I can tell Coconut is a vdom based UI library for Haxe that traditionally targets HTML5. This backend though will allow it to target FeatherUI which is essentially a UI layer on OpenFL.

Are the primary benefits here that this is essentially an alternative to electron for Coconut based apps?

Great, @Hersir! I hope to give it a try later this week.