[macro] add StyleMacro
This commit is contained in:
@@ -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> {
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
220
src/main/haxework/macro/StyleMacro.hx
Normal file
220
src/main/haxework/macro/StyleMacro.hx
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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];
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
6
src/main/haxework/view/theme/IStylable.hx
Normal file
6
src/main/haxework/view/theme/IStylable.hx
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package haxework.view.theme;
|
||||||
|
|
||||||
|
interface IStylable {
|
||||||
|
public var styleKey(default, set):String;
|
||||||
|
public var style(default, set):StyleId;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 = {};
|
||||||
|
|||||||
Reference in New Issue
Block a user