[macro] add StyleMacro

This commit is contained in:
2019-07-16 11:44:32 +03:00
parent 5faa179116
commit d52d8ff4f3
26 changed files with 373 additions and 91 deletions

View File

@@ -3,12 +3,14 @@ package haxework.macro;
import haxe.macro.Context; import haxe.macro.Context;
import haxe.macro.Expr; import haxe.macro.Expr;
using haxework.macro.Util;
class ProvideMacro { class ProvideMacro {
private static var metaName = ":provide"; private static var metaName = ":provide";
public static function has(field:Field):Bool { public static function has(field:Field):Bool {
return Util.hasFieldMeta(metaName, field); return field.getFieldMeta(metaName) != null;
} }
private var field:Field; private var field:Field;
@@ -16,7 +18,7 @@ class ProvideMacro {
public function new(field:Field) { public function new(field:Field) {
this.field = field; this.field = field;
this.meta = Util.getFieldMeta(metaName, field); this.meta = field.getFieldMeta(metaName);
} }
public function apply():Array<Field> { public function apply():Array<Field> {

View File

@@ -2,14 +2,13 @@ package haxework.macro;
import haxe.macro.Expr; import haxe.macro.Expr;
using haxework.macro.Util;
class ResourceMacro { class ResourceMacro {
public static function has(field:Field):Bool { public static function has(field:Field):Bool {
return Util.hasFieldMeta(":resource", field); return field.getFieldMeta(":resource") != null;
} }
private var field:Field; private var field:Field;
public function new(field:Field) { public function new(field:Field) {

View File

@@ -0,0 +1,220 @@
package haxework.macro;
import haxe.macro.Context;
import haxe.macro.Expr;
import haxe.macro.Type;
using haxe.macro.ComplexTypeTools;
using haxework.macro.Util;
using haxe.macro.MacroStringTools;
typedef TProperty<T> = {
var field: Field;
var defaultValue: T;
}
class StyleMacro {
private static inline var metaName:String = ':style';
public static function has(classType:ClassType):Bool {
return classType.getClassMeta(metaName) != null;
}
private var classType:ClassType;
private var fields:Array<Field>;
private var overrideStyle:Bool;
public function new(classType:ClassType, fields:Array<Field>) {
this.classType = classType;
this.fields = fields;
this.overrideStyle = classType.getClassMeta(":style").params.length > 0;
}
private static function processPropertyField(field:Field):Array<Field> {
var result:Array<Field> = [];
var type:ComplexType = field.getComplexType();
var meta = field.getFieldMeta(":style");
var defaultValue:Expr = meta.params.length > 0 ? meta.params[0] : null;
field.kind = FProp("get", "set", type);
var defaultName = 'default_${field.name}';
result.push({
name: defaultName,
access: [APrivate],
pos: field.pos,
kind: FVar(type, defaultValue),
});
var currentName = 'current_${field.name}';
result.push({
name: currentName,
access: [APrivate],
pos: field.pos,
kind: FVar(type),
});
var themeName = 'theme_${field.name}';
result.push({
name: themeName,
access: [APrivate],
pos: field.pos,
kind: FVar(type),
});
var getter = [];
getter.push(macro var result = $i{currentName});
getter.push(macro if (result == null) result = $i{themeName});
getter.push(macro if (result == null) result = $i{defaultName});
getter.push(macro return result);
result.push({
name: 'get_${field.name}',
access: [APrivate],
pos: field.pos,
kind: FFun({
args: [],
expr: macro $b{getter},
params: [],
ret: type,
})
});
result.push({
name: 'set_${field.name}',
access: [APrivate],
pos: field.pos,
kind: FFun({
args: [{name: "value", type: type}],
expr: macro $b{[
macro $i{currentName} = value,
macro return $i{field.name}
]},
params: [],
ret: type,
})
});
return result;
}
private static function processStyledField(field:Field):Array<Field> {
var type:ComplexType = field.getComplexType();
var result:Array<Field> = [];
field.kind = FProp("default", "set", type);
var expr:Array<Expr> = [];
expr.push(macro value.styleKey = (styleKey!=null?(styleKey+"."):"")+$v{field.name});
expr.push(macro value.style = style);
expr.push(macro $i{field.name} = value);
expr.push(macro return $i{field.name});
result.push({
name: 'set_${field.name}',
access: [APrivate],
pos: field.pos,
kind: FFun({
args: [{name: "value", type: type}],
expr: macro $b{expr},
params: [],
ret: type,
})
});
return result;
}
private static function buildStyleKeyField(overrideField:Bool):Array<Field> {
var result:Array<Field> = [];
var type:ComplexType = "String".toComplex();
if (!overrideField) {
result.push({
name: "styleKey",
access: [APublic],
pos: Context.currentPos(),
kind: FProp("default", "set", type),
});
}
var expr:Array<Expr> = [];
if (overrideField) {
expr.push(macro super.styleKey = value);
}
expr.push(macro styleKey = value);
expr.push(macro return styleKey);
var access:Array<Access> = [APrivate];
if (overrideField) {
access.push(AOverride);
}
result.push({
name: 'set_styleKey',
access: access,
pos: Context.currentPos(),
kind: FFun({
args: [{name: "value", type: type}],
expr: macro $b{expr},
params: [],
ret: type,
})
});
return result;
}
private static function buildStyleField(properties:Array<Field>, styleds:Array<Field>, hasOnStyle:Bool, overrideField:Bool):Array<Field> {
var result:Array<Field> = [];
var type:ComplexType = "haxework.view.theme.StyleId".toComplex();
if (!overrideField) {
result.push({
name: "style",
access: [APublic],
pos: Context.currentPos(),
kind: FProp("default", "set", type),
});
}
var expr:Array<Expr> = [];
if (overrideField) {
expr.push(macro super.style = value);
}
expr.push(macro style = value);
for (field in styleds) {
expr.push(macro $i{field.name}.style = style);
}
for (field in properties) {
var propertyName = 'theme_${field.name}';
expr.push(macro $i{propertyName} = haxework.provider.Provider.get(haxework.view.theme.ITheme).resolve((styleKey!=null?(styleKey+"."):"")+$v{field.name}, style));
}
if (hasOnStyle) {
expr.push(macro onStyle());
}
expr.push(macro return style);
var access:Array<Access> = [APrivate];
if (overrideField) {
access.push(AOverride);
}
result.push({
name: 'set_style',
access: access,
pos: Context.currentPos(),
kind: FFun({
args: [{name: "value", type: type}],
expr: macro $b{expr},
params: [],
ret: type,
})
});
return result;
}
public function apply():Array<Field> {
var result:Array<Field> = fields.slice(0);
var styleds:Array<Field> = [];
var properties:Array<Field> = [];
var newFields:Array<Field> = [];
var hasOnStyle:Bool = fields.getField("onStyle") != null;
for (field in fields) if (field.meta != null) {
var meta = field.getFieldMeta(":style");
if (meta != null) {
if (meta.params.length > 0) {
newFields = newFields.concat(processPropertyField(field));
properties.push(field);
} else {
newFields = newFields.concat(processStyledField(field));
styleds.push(field);
}
}
}
result = result
.concat(newFields)
.concat(buildStyleKeyField(overrideStyle))
.concat(buildStyleField(properties, styleds, hasOnStyle, overrideStyle));
return result;
}
}

View File

@@ -6,32 +6,29 @@ import haxe.macro.Expr;
import haxe.macro.Type; import haxe.macro.Type;
import haxework.macro.PositionJsonParser; import haxework.macro.PositionJsonParser;
using haxework.macro.Util;
class TemplateMacro { class TemplateMacro {
private static inline var metaName:String = ':template'; private static inline var metaName:String = ':template';
public static function has(classType:ClassType):Bool { public static function has(classType:ClassType):Bool {
return Util.hasClassMeta(metaName, classType); return classType.getClassMeta(metaName) != null;
} }
private var classType:ClassType; private var classType:ClassType;
private var fields:Array<Field>; private var fields:Array<Field>;
private var bindings:Map<String, String>; private var bindings:Map<String, String>;
private var meta(get, never):MetadataEntry; private var meta:MetadataEntry;
private var templateFile:String; private var templateFile:String;
private var template:Dynamic; private var template:Dynamic;
private var i:Int; private var i:Int;
private function get_meta():MetadataEntry {
for (md in classType.meta.get()) if (md.name == metaName) {
return md;
}
return null;
}
public function new(classType:ClassType, fields:Array<Field>) { public function new(classType:ClassType, fields:Array<Field>) {
this.classType = classType; this.classType = classType;
this.meta = classType.getClassMeta(metaName);
this.fields = fields; this.fields = fields;
var params = Util.getMetaParams(meta); var params = Util.getMetaParams(meta);
var filePath = params[0]; var filePath = params[0];

View File

@@ -3,7 +3,6 @@ package haxework.macro;
import haxe.macro.Type.ClassType; import haxe.macro.Type.ClassType;
import haxe.macro.Expr; import haxe.macro.Expr;
class Util { class Util {
public static function getMetaParams(meta:MetadataEntry):Array<String> { public static function getMetaParams(meta:MetadataEntry):Array<String> {
@@ -17,21 +16,14 @@ class Util {
return ComplexType.TPath({name:'Dynamic', pack:[], params:[]}); return ComplexType.TPath({name:'Dynamic', pack:[], params:[]});
} }
public static function hasClassMeta(metaName:String, classType:ClassType):Bool { public static function getClassMeta(classType:ClassType, metaName:String):Null<MetadataEntry> {
for (md in classType.meta.get()) if (md.name == metaName) { for (md in classType.meta.get()) if (md.name == metaName) {
return true; return md;
} }
return false; return null;
} }
public static function hasFieldMeta(metaName:String, field:Field):Bool { public static function getFieldMeta(field:Field, metaName:String):Null<MetadataEntry> {
for (md in field.meta) if (md.name == metaName) {
return true;
}
return false;
}
public static function getFieldMeta(metaName:String, field:Field):MetadataEntry {
for (md in field.meta) if (md.name == metaName) { for (md in field.meta) if (md.name == metaName) {
return md; return md;
} }
@@ -44,4 +36,16 @@ class Util {
case _: null; case _: null;
} }
} }
public static function getComplexType(field:Field):Null<ComplexType> {
return switch field.kind {
case FProp(get, set, t, e): t;
case FVar(t, e): t;
case _: null;
}
}
public static function getField(fields:Array<Field>, name:String):Null<Field> {
return Lambda.find(fields, function(field:Field):Bool return field.name == name);
}
} }

View File

@@ -1,5 +1,6 @@
package haxework.parser; package haxework.parser;
import haxework.macro.StyleMacro;
import haxe.macro.TypeTools; import haxe.macro.TypeTools;
import haxe.macro.Context; import haxe.macro.Context;
import haxe.macro.Expr; import haxe.macro.Expr;
@@ -57,6 +58,11 @@ class Parser {
var dispatcher = new DispatcherMacro(ct, fields); var dispatcher = new DispatcherMacro(ct, fields);
fields = dispatcher.apply(); fields = dispatcher.apply();
} }
if (StyleMacro.has(ct)) {
modify = true;
var style = new StyleMacro(ct, fields);
fields = style.apply();
}
processed.set(localName, true); processed.set(localName, true);
modify ? fields : null; modify ? fields : null;
default: null; default: null;

View File

@@ -9,8 +9,8 @@ import haxework.view.skin.ISkin;
import haxework.view.theme.StyleId; import haxework.view.theme.StyleId;
interface IView<C:DisplayObject> { interface IView<C:DisplayObject> {
@:style public var geometry(default, default):Geometry; public var geometry(default, set):Geometry;
@:style public var skin(default, set):ISkin<Dynamic>; public var skin(default, set):ISkin<Dynamic>;
public var id(default, default):String; public var id(default, default):String;

View File

@@ -73,4 +73,19 @@ class Root {
onResize.dispose(); onResize.dispose();
} }
private static function getViews(view:IView<Dynamic>):Array<IView<Dynamic>> {
var result = [];
result.push(view);
if (Std.is(view, IGroupView)) {
for (v in cast(view, IGroupView).views) {
result = result.concat(getViews(v));
}
}
return result;
}
public function views():Array<IView<Dynamic>> {
return getViews(view);
}
} }

View File

@@ -9,18 +9,16 @@ import haxework.view.geometry.SizeSet;
import haxework.view.group.IGroupView; import haxework.view.group.IGroupView;
import haxework.view.skin.ISkin; import haxework.view.skin.ISkin;
import haxework.view.theme.ITheme; import haxework.view.theme.ITheme;
import haxework.view.theme.StyleId;
class View<C:DisplayObject> implements IView<C> { @:style class View<C:DisplayObject> implements IView<C> {
private static var counter:Int = 0; private static var counter:Int = 0;
public static var updater(default, null):ViewUpdater = new ViewUpdater(); public static var updater(default, null):ViewUpdater = new ViewUpdater();
@:provide var theme:ITheme; @:provide var theme:ITheme;
public var geometry(default, default):Geometry; @:style public var geometry(default, default):Geometry;
public var skin(default, set):ISkin<Dynamic>; @:style public var skin(default, default):ISkin<Dynamic>;
public var style(default, set):StyleId;
public var id(default, default):String; public var id(default, default):String;
@@ -56,7 +54,11 @@ class View<C:DisplayObject> implements IView<C> {
geometry = new Geometry(); geometry = new Geometry();
visible = true; visible = true;
index = -1; index = -1;
skin = null; }
private function onStyle():Void {
toUpdate();
toRedraw();
} }
public function toRedraw():Void { public function toRedraw():Void {
@@ -118,22 +120,13 @@ class View<C:DisplayObject> implements IView<C> {
return y; return y;
} }
private function set_skin(value:ISkin<Dynamic>):ISkin<Dynamic> { // ToDo:
/*private function set_skin(value:ISkin<Dynamic>):ISkin<Dynamic> {
this.skin = value; this.skin = value;
toRedraw(); toRedraw();
return this.skin; return this.skin;
} }
*/
private function set_style(value:StyleId):StyleId {
if (value != null && style != value) {
style = value;
if (theme != null) {
theme.bind(style, this);
}
}
return style;
}
private function set_visible(value:Bool):Bool { private function set_visible(value:Bool):Bool {
if (visible != value) { if (visible != value) {
visible = value; visible = value;

View File

@@ -1,5 +1,6 @@
package haxework.view.form; package haxework.view.form;
import haxework.view.skin.ButtonColorSkin;
import haxework.signal.Signal; import haxework.signal.Signal;
import flash.events.MouseEvent; import flash.events.MouseEvent;
@@ -23,6 +24,7 @@ class ButtonView extends LabelView {
public function new() { public function new() {
super(); super();
skin = new ButtonColorSkin();
style = "button"; style = "button";
overed = false; overed = false;
downed = false; downed = false;

View File

@@ -69,11 +69,11 @@ abstract Box(Array<Float>) {
return new Box(this); return new Box(this);
} }
@:from static public inline function fromArray(value:Array<Float>):Box { @:from static public function fromArray(value:Array<Float>):Box {
return new Box(value); return new Box(value);
} }
@:from static public inline function fromFloat(value:Float):Box { @:from static public function fromFloat(value:Float):Box {
return new Box([value]); return new Box([value]);
} }
} }

View File

@@ -1,25 +1,17 @@
package haxework.view.geometry; package haxework.view.geometry;
class Geometry { @:style class Geometry {
public var width(default, default):SizeValue; @:style(0) public var width(default, default):SizeValue;
public var height(default, default):SizeValue; @:style(0) public var height(default, default):SizeValue;
public var padding(default, default):Box; @:style(0) public var padding(default, default):Box;
public var margin(default, default):Box; @:style(0) public var margin(default, default):Box;
public var hAlign(default, default):HAlign; @:style(HAlign.NONE) public var hAlign(default, default):HAlign;
public var vAlign(default, default):VAlign; @:style(VAlign.NONE) public var vAlign(default, default):VAlign;
public var position(default, default):Position; @:style(Position.LAYOUT) public var position(default, default):Position;
public var ratio(default, default):Float; @:style(-1) public var ratio(default, default):Null<Float>;
public var stretch(null, set):Bool; public var stretch(null, set):Bool;
public function new() { public function new() {
this.padding = [];
this.margin = [];
this.width = 0;
this.height = 0;
this.hAlign = HAlign.NONE;
this.vAlign = VAlign.NONE;
this.position = Position.LAYOUT;
this.ratio = -1;
} }
private function set_stretch(value:Bool):Bool { private function set_stretch(value:Bool):Bool {

View File

@@ -4,7 +4,7 @@ import flash.display.BitmapData;
import flash.geom.Rectangle; import flash.geom.Rectangle;
import haxework.view.utils.DrawUtil; import haxework.view.utils.DrawUtil;
class BitmapSkin implements ISkin<SpriteView> { @:style class BitmapSkin implements ISkin<SpriteView> {
public var image(null, set):BitmapData; public var image(null, set):BitmapData;
public var color(default, default):Int; public var color(default, default):Int;
public var fillType(default, default):FillType; public var fillType(default, default):FillType;

View File

@@ -7,7 +7,7 @@ import haxework.view.form.ButtonView;
import haxework.view.utils.BitmapUtil; import haxework.view.utils.BitmapUtil;
import haxework.view.utils.DrawUtil; import haxework.view.utils.DrawUtil;
class ButtonBitmapSkin implements ISkin<ButtonView> { @:style class ButtonBitmapSkin implements ISkin<ButtonView> {
public var fillType(default, default):FillType; public var fillType(default, default):FillType;
public var color(default, default):Int; public var color(default, default):Int;

View File

@@ -10,21 +10,21 @@ import haxework.view.form.ToggleButtonView;
using haxework.color.ColorUtil; using haxework.color.ColorUtil;
class ButtonColorSkin implements ISkin<ButtonView> { @:style class ButtonColorSkin implements ISkin<ButtonView> {
public var color(default, default):Color; @:style(0xffffff) public var color(default, default):Null<Color>;
public var borderColor(default, default):Null<Color>; public var borderColor(default, default):Null<Color>;
public var round(default, default):Float; public var round(default, default):Float;
private var colors:Map<ButtonState, Int>; private var colors:Map<ButtonState, Int>;
public function new(?color:Color, ?borderColor:Color, round:Float = 15) { public function new(?color:Color, ?borderColor:Color, round:Float = 15) {
this.color = color != null ? color : 0xffffff; this.color = color;
this.borderColor = borderColor; this.borderColor = borderColor;
this.round = round; this.round = round;
} }
public function draw(view:ButtonView):Void { public function draw(view:ButtonView):Void {
var color:Color = stateColor(color, view.state); var color = color;
var borderColor:Color = borderColor != null ? borderColor : color.multiply(1.5); var borderColor:Color = borderColor != null ? borderColor : color.multiply(1.5);
if (Std.is(view, ToggleButtonView)) { if (Std.is(view, ToggleButtonView)) {
if (!cast(view, ToggleButtonView).on) { if (!cast(view, ToggleButtonView).on) {

View File

@@ -3,7 +3,7 @@ package haxework.view.skin;
import haxework.color.ColorUtil; import haxework.color.ColorUtil;
import haxework.view.list.ScrollBarView; import haxework.view.list.ScrollBarView;
class HScrollBarSkin implements ISkin<ScrollBarView> { @:style class HScrollBarSkin implements ISkin<ScrollBarView> {
public var foreColor(default, default):Int; public var foreColor(default, default):Int;
public var backColor(default, default):Int; public var backColor(default, default):Int;

View File

@@ -1,5 +1,7 @@
package haxework.view.skin; package haxework.view.skin;
interface ISkin<V:IView<Dynamic>> { import haxework.view.theme.IStylable;
interface ISkin<V:IView<Dynamic>> extends IStylable {
public function draw(view:V):Void; public function draw(view:V):Void;
} }

View File

@@ -3,7 +3,7 @@ package haxework.view.skin;
import flash.display.Graphics; import flash.display.Graphics;
import haxework.view.skin.ISkin; import haxework.view.skin.ISkin;
class ProgressSkin implements ISkin<ProgressView> { @:style class ProgressSkin implements ISkin<ProgressView> {
public var foreColor:Int; public var foreColor:Int;
public var backColor:Int; public var backColor:Int;

View File

@@ -14,10 +14,10 @@ typedef Background = {
@:optional var alpha:Float; @:optional var alpha:Float;
} }
class SpriteSkin implements ISkin<SpriteView> { @:style class SpriteSkin implements ISkin<SpriteView> {
public var border(default, default):Border; @:style({}) public var border(default, default):Border;
public var background(default, default):Background; @:style({}) public var background(default, default):Background;
public function new(?background:Background, ?border:Border) { public function new(?background:Background, ?border:Border) {
this.background = resolveBackground(background); this.background = resolveBackground(background);
@@ -28,7 +28,7 @@ class SpriteSkin implements ISkin<SpriteView> {
return value != null ? { return value != null ? {
color: value.color != null ? value.color : 0x000000, color: value.color != null ? value.color : 0x000000,
alpha: value.alpha != null ? value.alpha : 1.0 alpha: value.alpha != null ? value.alpha : 1.0
} : {}; } : null;
} }
private static function resolveBorder(value:Border):Border { private static function resolveBorder(value:Border):Border {
@@ -36,7 +36,7 @@ class SpriteSkin implements ISkin<SpriteView> {
color: value.color != null ? value.color : 0x000000, color: value.color != null ? value.color : 0x000000,
alpha: value.alpha != null ? value.alpha : 1.0, alpha: value.alpha != null ? value.alpha : 1.0,
thickness: value.thickness != null ? value.thickness : 1 thickness: value.thickness != null ? value.thickness : 1
} : {}; } : null;
} }
public function draw(view:SpriteView):Void { public function draw(view:SpriteView):Void {

View File

@@ -3,7 +3,7 @@ package haxework.view.skin;
import haxework.color.ColorUtil; import haxework.color.ColorUtil;
import haxework.view.list.ScrollBarView; import haxework.view.list.ScrollBarView;
class VScrollBarSkin implements ISkin<ScrollBarView> { @:style class VScrollBarSkin implements ISkin<ScrollBarView> {
public var foreColor(default, default):Int; public var foreColor(default, default):Int;
public var backColor(default, default):Int; public var backColor(default, default):Int;

View File

@@ -3,13 +3,13 @@ package haxework.view.text;
import haxework.color.Color; import haxework.color.Color;
import flash.text.TextFormatAlign; import flash.text.TextFormatAlign;
class FontPreset { @:style class FontPreset {
public var family(default, default):String; @:style("Courirer") public var family(default, default):String;
public var embed(default, default):Bool; @:style(false) public var embed(default, default):Null<Bool>;
public var color(default, default):Null<Color>; @:style(0xffffff) public var color(default, default):Null<Color>;
public var size(default, default):Null<Int>; @:style(16) public var size(default, default):Null<Int>;
public var bold(default, default):Bool; @:style(false) public var bold(default, default):Null<Bool>;
public var align(default, default):TextFormatAlign; @:style(TextFormatAlign.LEFT) public var align(default, default):TextFormatAlign;
public function new(?family:String, ?embed:Bool, ?color:Color, ?size:Int, public function new(?family:String, ?embed:Bool, ?color:Color, ?size:Int,
?bold:Bool, ?align:TextFormatAlign) { ?bold:Bool, ?align:TextFormatAlign) {

View File

@@ -5,8 +5,8 @@ import haxework.view.IView;
import haxework.view.layout.ILayout; import haxework.view.layout.ILayout;
interface ITextView extends IView<Dynamic> { interface ITextView extends IView<Dynamic> {
@:style public var font(default, default):FontPreset; public var font(default, set):FontPreset;
@:style public var layout(default, default):ILayout; public var layout(default, default):ILayout;
public var textField(default, null):TextField; public var textField(default, null):TextField;
public var text(get, set):String; public var text(get, set):String;

View File

@@ -11,8 +11,8 @@ import haxework.view.geometry.VAlign;
import haxework.view.layout.ILayout; import haxework.view.layout.ILayout;
import haxework.view.layout.Layout; import haxework.view.layout.Layout;
class TextView extends SpriteView implements ITextView { @:style(true) class TextView extends SpriteView implements ITextView {
public var font(default, default):FontPreset; @:style public var font(default, default):FontPreset;
public var layout(default, default):ILayout; public var layout(default, default):ILayout;
public var textField(default, null):TextField; public var textField(default, null):TextField;

View File

@@ -0,0 +1,6 @@
package haxework.view.theme;
interface IStylable {
public var styleKey(default, set):String;
public var style(default, set):StyleId;
}

View File

@@ -1,5 +1,6 @@
package haxework.view.theme; package haxework.view.theme;
import haxework.signal.Signal;
import haxework.color.Color; import haxework.color.Color;
typedef ThemeFont = { typedef ThemeFont = {
@@ -18,5 +19,6 @@ typedef ThemeColors = {
interface ITheme { interface ITheme {
public var font(default, set):ThemeFont; public var font(default, set):ThemeFont;
public var colors(default, set):ThemeColors; public var colors(default, set):ThemeColors;
public function bind(style:StyleId, view:IView<Dynamic>):Void; public var updateSignal(default, null):Signal0;
public function resolve<T>(key:String, style:StyleId):T;
} }

View File

@@ -1,9 +1,11 @@
package haxework.view.theme; package haxework.view.theme;
import haxework.view.geometry.Box;
import flash.text.Font; import flash.text.Font;
import flash.text.FontType; import flash.text.FontType;
import haxe.ds.StringMap; import haxe.ds.StringMap;
import haxework.color.Color; import haxework.color.Color;
import haxework.signal.Signal;
import haxework.view.geometry.Geometry; import haxework.view.geometry.Geometry;
import haxework.view.skin.Skin; import haxework.view.skin.Skin;
import haxework.view.skin.SpriteSkin; import haxework.view.skin.SpriteSkin;
@@ -61,11 +63,16 @@ class Theme implements ITheme {
public var font(default, set):ThemeFont; public var font(default, set):ThemeFont;
public var colors(default, set):ThemeColors; public var colors(default, set):ThemeColors;
public var updateSignal(default, null):Signal0;
private var styles:StyleMap; private var styles:StyleMap;
private var data:Map<String, Map<String, Dynamic>>;
public function new(?font:ThemeFont, ?colors:ThemeColors) { public function new(?font:ThemeFont, ?colors:ThemeColors) {
styles = new StyleMap(); styles = new StyleMap();
updateSignal = new Signal0();
data = new Map();
this.font = font; this.font = font;
this.colors = colors; this.colors = colors;
L.d("Theme", 'font: ${this.font}'); L.d("Theme", 'font: ${this.font}');
@@ -90,6 +97,37 @@ class Theme implements ITheme {
private function reload():Void { private function reload():Void {
data.set("background", [
"skin.background" => {color: colors.dark, alpha: 1},
]);
data.set("text", [
"font.color" => colors.text,
"font.family" => font.name,
"font.embed" => font.embed,
]);
data.set("button", [
"skin.color" => colors.light,
"geometry.padding" => Box.fromArray([25, 8]),
"font.color" => colors.text,
"font.family" => font.name,
"font.embed" => font.embed,
]);
data.set("button.tab", [
"skin.color" => colors.light,
"geometry.padding" => Box.fromArray([25, 8]),
"font.color" => colors.text,
"font.family" => font.name,
"font.embed" => font.embed,
]);
// ToDo: hardcode update views
if (Root.instance != null) {
for (view in Root.instance.views()) {
view.style = view.style;
}
}
updateSignal.emit();
styles.put("background", background()); styles.put("background", background());
styles.put("border", background(null, true)); styles.put("border", background(null, true));
styles.put("frame", background(null, true).concat([new GeometryStyle(new Geometry().setPadding(2))])); styles.put("frame", background(null, true).concat([new GeometryStyle(new Geometry().setPadding(2))]));
@@ -162,6 +200,10 @@ class Theme implements ITheme {
styles.disconnect(view); styles.disconnect(view);
} }
public function resolve<T>(key:String, style:StyleId):T {
return style != null && data.exists(style) ? data.get(style).get(key) : null;
}
private static function resolveFont(font:ThemeFont):ThemeFont { private static function resolveFont(font:ThemeFont):ThemeFont {
if (font == null) { if (font == null) {
font = {}; font = {};