Created
August 30, 2023 20:54
-
-
Save Crinfarr/c84ea776640777206d041999fb55b5ca to your computer and use it in GitHub Desktop.
Scalable HaxeUI macro impl
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package haxe.ui.core; | |
//in file path haxe/ui/core | |
#if !macro | |
import haxe.ui.core.Component; | |
#end | |
@:autoBuild(haxe.ui.macros.ScalableType.applyScalable()) | |
interface Scalable { | |
private var baseWidth:Null<Float>; | |
private var baseHeight:Null<Float>; | |
private var scalableChildren:Array<Scalable>; | |
public function addComponent(component:Component):Component; | |
@:isVar public var scale(get, set):Float; | |
private function get_scale():Float; | |
private function set_scale(value:Float):Float; | |
private function set_width(value:Null<Float>):Null<Float>; | |
private function set_height(value:Null<Float>):Null<Float>; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package haxe.ui.macros; | |
//in file path haxe/ui/macros | |
#if macro | |
import haxe.macro.Context; | |
import haxe.macro.Expr.Field; | |
import haxe.macro.Type.ClassType; | |
#end | |
class ScalableType { | |
macro function applyScalable():Array<Field> { | |
var isComponent = false; | |
var _last:haxe.macro.Type.Ref<ClassType> = Context.getLocalClass(); | |
do { | |
isComponent = _last.toString() == 'haxe.ui.core.Component'; | |
if (isComponent) | |
break; | |
_last = _last.get().superClass.t; | |
} while (_last.get().superClass != null); | |
if (!isComponent) { | |
Context.error('Non-component classes cannot be Scalable', Context.currentPos()); | |
} | |
var fields:Array<Field> = Context.getBuildFields(); | |
// Compiler.addMetadata('scalable', Context.getLocalClass().toString()); | |
Context.getLocalClass().get().meta.add('scalable', [macro true], Context.currentPos()); | |
/** | |
* Base width and height (to use with scale) | |
*/ | |
fields.push({ | |
name: 'baseWidth', | |
access: [APrivate], | |
pos: Context.currentPos(), | |
kind: FVar(macro :Null<Float>, macro null) | |
}); | |
fields.push({ | |
name: 'baseHeight', | |
access: [APrivate], | |
pos: Context.currentPos(), | |
kind: FVar(macro :Null<Float>, macro null) | |
}); | |
/** | |
* Separate scalable children | |
*/ | |
fields.push({ | |
name: 'scalableChildren', | |
access: [APrivate], | |
kind: FVar(macro :Array<Scalable>, { | |
expr: EArrayDecl([]), | |
pos: Context.currentPos() | |
}), | |
pos: Context.currentPos(), | |
}); | |
fields.push({ | |
name: 'addComponent', | |
access: [AOverride, APublic], | |
kind: FFun({ | |
args: [ | |
{ | |
name: 'component', | |
type: (macro :haxe.ui.core.Component) | |
} | |
], | |
expr: macro { | |
if (Std.isOfType(component, Scalable)) { | |
scalableChildren.push(untyped component); | |
} | |
return super.addComponent(component); | |
} | |
}), | |
pos: Context.currentPos(), | |
}); | |
/** | |
* scale, getters, and setters | |
*/ | |
fields.push({ | |
name: 'scale', | |
access: [APublic], | |
pos: Context.currentPos(), | |
kind: FProp('get', 'set', (macro :Float), (macro 1)), | |
meta: [ | |
// make sure var field is generated | |
{ | |
name: ':isVar', | |
pos: Context.currentPos() | |
} | |
] | |
}); | |
fields.push({ | |
name: 'get_scale', | |
access: [APrivate], | |
kind: FFun({ | |
args: [], | |
ret: (macro :Float), | |
expr: macro { | |
return scale; | |
} | |
}), | |
pos: Context.currentPos() | |
}); | |
fields.push({ | |
name: 'set_scale', | |
kind: FFun({ | |
args: [ | |
{ | |
name: 'value', | |
type: (macro :Float), | |
} | |
], | |
ret: (macro :Float), | |
expr: macro { | |
scale = value; | |
if (baseWidth == null) | |
baseWidth = width; | |
if (baseHeight == null) | |
baseHeight = height; | |
super.set_width(baseWidth * scale); | |
super.set_height(baseHeight * scale); | |
this.customStyle.fontSize = 13 * scale; | |
this.invalidateComponentStyle(); | |
for (child in scalableChildren) { | |
child.scale = scale; | |
} | |
return scale; | |
} | |
}), | |
pos: Context.currentPos(), | |
}); | |
/** | |
* Override set_width to modify base width instead | |
*/ | |
fields.push({ | |
name: 'set_width', | |
kind: FFun({ | |
args: [ | |
{ | |
name: 'value', | |
type: (macro :Null<Float>) | |
} | |
], | |
ret: (macro :Null<Float>), | |
expr: macro { | |
baseWidth = value; | |
return super.set_width(baseWidth * scale); | |
} | |
}), | |
access: [AOverride, APrivate], | |
pos: Context.currentPos() | |
}); | |
/** | |
* Override set_height to modify base height instad | |
*/ | |
fields.push({ | |
name: 'set_height', | |
kind: FFun({ | |
args: [ | |
{ | |
name: 'value', | |
type: (macro :Null<Float>) | |
} | |
], | |
ret: (macro :Null<Float>), | |
expr: macro { | |
baseHeight = value; | |
return super.set_height(baseHeight * scale); | |
} | |
}), | |
access: [AOverride, APrivate], | |
pos: Context.currentPos() | |
}); | |
return fields; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment