[skin] update

This commit is contained in:
2019-02-22 15:38:34 +03:00
parent 78ecd35587
commit 5cd1bbc30a
19 changed files with 199 additions and 203 deletions

View File

@@ -1,5 +1,7 @@
package demo;
import haxework.resources.Resources;
import haxework.resources.IResources;
import haxework.gui.frame.IFrameSwitcher;
import haxework.net.manage.LoaderManager;
import haxework.net.manage.ILoaderManager;
@@ -9,11 +11,14 @@ import haxework.gui.VGroupView;
@:template class Demo extends VGroupView {
@:provide static var resources:IResources;
@:provide static var manager:ILoaderManager;
public static function main() {
L.push(new TraceLogger());
resources = new Resources();
manager = new LoaderManager();
Style.register();
var demo = new Demo();
demo.switcher.change("list_form");
Root.bind(demo);

View File

@@ -1,27 +1,31 @@
---
pWidth: 100
pHeight: 100
skin: [ $type: [haxework.gui.skin.Skin.color, 0x333333] ]
skin: $r:skin:background
views:
- $type: haxework.gui.HGroupView
layoutMargin: 10
layoutMargin: 5
layoutHAlign: LEFT
leftPadding: 5
pWidth: 100
height: 40
views:
- $type: haxework.gui.ButtonView
skin: $raw:Style.buttonSkin
skin: $r:skin:button
contentSize: true
paddings: 8
text: List Form
+onPress: "$raw:function(_) switcher.change('list_form')"
+onPress: "$code:function(_) switcher.change('list_form')"
- $type: haxework.gui.ButtonView
skin: $raw:Style.buttonSkin
skin: $r:skin:button
contentSize: true
paddings: 8
text: Tail Form
+onPress: "$raw:function(_) switcher.change('tail_form')"
+onPress: "$code:function(_) switcher.change('tail_form')"
- id: switcher
$type: haxework.gui.frame.FrameSwitcher
skin: [ $type: [ haxework.gui.skin.Skin.border, 0x33aa33, 1, 2 ] ]
paddings: 5
pWidth: 100
pHeight: 100
views:

View File

@@ -1,23 +1,45 @@
package demo;
import haxework.gui.list.ScrollBarSkin;
import haxework.resources.IResources;
import haxework.gui.skin.ISkin;
import haxework.gui.skin.ButtonColorSkin;
import haxework.gui.skin.TextSkin;
import haxework.gui.skin.ButtonSkin;
import haxework.gui.skin.Skin;
import haxework.gui.skin.ISkin.SkinSet;
import haxework.gui.skin.TextSkin;
class Style {
public static var textSkin = new TextSkin(0xffffff, "Courirer");
@:provide static var resources:IResources;
public static var buttonSkin: SkinSet = [
new ButtonColorSkin(0x33aa33),
textSkin,
public static var backColor = 0x33aa33;
public static var textColor = 0xffffff;
public static var borderColor = 0xffffff;
public static var text:ISkin<Dynamic> = new TextSkin(textColor, "Courirer");
public static var background:SkinSet = [
Skin.color(0x00000),
];
public static var viewSkin:SkinSet = [
Skin.color(0x33aa33),
Skin.border(0xffffff),
textSkin,
public static var button:SkinSet = [
ButtonSkin.color(backColor),
text,
];
public static var view:SkinSet = [
Skin.color(backColor),
Skin.border(borderColor),
text,
];
public static var scroll:SkinSet = [
ScrollBarSkin.vertical(0x55cc55, 0xccffcc),
];
public static function register():Void {
resources.skin.put("background", background);
resources.skin.put("button", button);
resources.skin.put("view", view);
resources.skin.put("scroll", scroll);
}
}

View File

@@ -1,8 +1,6 @@
---
$type: haxework.gui.VGroupView
paddings: 20
layoutMargin: 10
skin: [ $type: [haxework.gui.skin.Skin.color, 0x333333] ]
views:
- id: list
$type: haxework.gui.list.VListView<String>
@@ -12,36 +10,7 @@ views:
pHeight: 100
scroll:
$type: haxework.gui.list.VScrollBarView
skin: $r:skin:scroll
width: 10
pHeight: 100
skin: [ $type: [haxework.gui.list.ScrollBarSkin.vertical, 0x55cc55, 0xccffcc] ]
skin: [ $type: [haxework.gui.skin.Skin.color, 0xffffff] ]
- id: panel
$type: haxework.gui.HGroupView
pWidth: 100
height: 60
# contentSize: true
layoutMargin: 10
skin: [ $type: [haxework.gui.skin.Skin.color, 0x555555] ]
views:
- id: button1
$type: haxework.gui.ButtonView
+onPress: $this:onPress
contentSize: true
paddings: 8
skin: $raw:Style.buttonSkin
text: OK
- id: button2
$type: haxework.gui.ButtonView
+onPress: $this:onPress
contentSize: true
paddings: 8
skin: $raw:Style.buttonSkin
text: Apply
- id: button3
$type: haxework.gui.ButtonView
+onPress: $this:onPress
contentSize: true
paddings: 8
skin: $raw:Style.buttonSkin
text: Cancel

View File

@@ -14,7 +14,7 @@ import haxework.gui.TextView;
var view = new TextView();
view.width = 100 + 100 * Math.random();
view.height = 100 + 100 * Math.random();
view.skin = Style.viewSkin;
view.skin = Style.view;
view.text = 'View #${i}';
group.addView(view);
}

View File

@@ -3,18 +3,16 @@ pWidth: 100
pHeight: 100
views:
- $type: haxework.gui.ScrollView
skin: [ $type: [haxework.gui.skin.Skin.color, 0xff0000] ]
pWidth: 100
pHeight: 100
scroll:
$type: haxework.gui.list.VScrollBarView
skin: $r:skin:scroll
width: 10
pHeight: 100
skin: [ $type: [haxework.gui.list.ScrollBarSkin.vertical, 0x55cc55, 0xccffcc] ]
view:
id: group
$type: haxework.gui.GroupView
skin: [ $type: [haxework.gui.skin.Skin.color, 0xffff00] ]
pWidth: 100
contentSize: true
layoutMargin: 5

View File

@@ -21,7 +21,7 @@ class ImageView extends SpriteView {
private function set_image(value:BitmapData):BitmapData {
if (image != value) {
image = value;
skin = cast new BitmapSkin(image, FillType.CONTAIN);
skin = [new BitmapSkin(image, FillType.CONTAIN)];
invalidate();
}
return image;
@@ -36,4 +36,4 @@ class ImageView extends SpriteView {
}
return imageUrl;
}
}
}

View File

@@ -18,7 +18,7 @@ class ScrollView extends HGroupView {
public function new() {
super();
skin = [Skin.color(0x0000FF, 1.0)];
skin = [Skin.color(0x000000, 0.0)];
mask = new Shape();
content.addChild(mask);
content.addEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheelEvent);

View File

@@ -1,12 +1,12 @@
package haxework.gui;
import flash.display.Sprite;
import haxework.gui.skin.ISkin;
import haxework.gui.skin.ISkin.SkinSet;
class ToggleButtonView extends ButtonView {
public var on(default, set):Bool;
public var onSkin(default, set):ISkin<Dynamic>;
public var onSkin(default, set):SkinSet;
public var onText(default, set):String;
@@ -20,13 +20,13 @@ class ToggleButtonView extends ButtonView {
return on;
}
private function set_onSkin(value:ISkin<Dynamic>):ISkin<Dynamic> {
private function set_onSkin(value:SkinSet):SkinSet {
onSkin = value;
invalidate();
return onSkin;
}
override private function currentSkin():ISkin<Dynamic> {
private function currentSkin():SkinSet {
return on ? onSkin : skin;
}
@@ -41,4 +41,4 @@ class ToggleButtonView extends ButtonView {
override private function currentText():String {
return on && onText != null ? onText : super.currentText();
}
}
}

View File

@@ -4,7 +4,7 @@ import flash.display.BitmapData;
import flash.geom.Rectangle;
import haxework.gui.utils.DrawUtil;
class BitmapSkin implements ISkin<SpriteView> implements ISize {
class BitmapSkin implements ISkin<SpriteView> {
public var width(default, null):Float;
public var height(default, null):Float;

View File

@@ -14,7 +14,7 @@ class BorderSkin implements ISkin<SpriteView> {
public function draw(view:SpriteView):Void {
view.content.graphics.lineStyle(tickness, color, alpha, true);
view.content.graphics.drawRect(0, 0, view.width, view.height);
view.content.graphics.drawRect(0, 0, view.width - tickness, view.height - tickness);
view.content.graphics.lineStyle();
}
}

View File

@@ -1,10 +1,10 @@
package haxework.macro;
import yaml.YamlException;
import yaml.Parser;
import yaml.Yaml;
import haxe.macro.Context;
class FileUtil {
public static function loadJsonFile(path:String):Dynamic {
@@ -21,16 +21,17 @@ class FileUtil {
}
public static function loadYamlFile(path:String):Dynamic {
path = sys.FileSystem.absolutePath(path);
Context.registerModuleDependency(Context.getLocalModule(), path);
var content = sys.io.File.getContent(path);
var result = null;
try {
// ToDo: extract poisiton info
result = Yaml.parse(content, Parser.options().useObjects());
} catch (error:Dynamic) {
Context.error(error, Context.makePosition({min:0, max:0, file:path}));
PositionYamlParser.parse(path, content, result);
} catch (error:YamlException) {
Context.error(Std.string(error), Context.makePosition({min:0, max:0, file:path}));
}
//Context.parse(content, Context.makePosition({min:0, max:0, file:path}));
Context.parse('/*$content*/""', Context.makePosition({min:0, max:0, file:path}));
return result;
}
@@ -42,4 +43,4 @@ class FileUtil {
case x: throw 'Unsupported file format: "${x}"';
}
}
}
}

View File

@@ -0,0 +1,44 @@
package haxework.macro;
class PositionYamlParser {
private var filename:String;
private var content:String;
private var cache:Map<String, Int>;
private var result:Dynamic;
private function new(filename:String, content:String, result:Dynamic) {
this.filename = filename;
this.content = content;
this.result = result;
this.cache = new Map();
}
private function parseAll():Void {
parseBlock(result);
}
private function parseBlock(result:Dynamic):Void {
for (field in Reflect.fields(result)) {
var offset = content.indexOf(field, cache.get(field));
cache.set(field, offset);
Reflect.setField(result, "$" + field, {
min:offset,
max:offset + field.length,
file:filename,
});
var value = Reflect.field(result, field);
if (Std.is(value, Array)) {
for (item in cast(value, Array<Dynamic>)) {
parseBlock(item);
}
} else {
parseBlock(value);
}
}
}
public static function parse(filename:String, content:String, result:Dynamic):Void {
new PositionYamlParser(filename, content, result).parseAll();
}
}

View File

@@ -0,0 +1,23 @@
package haxework.macro;
import haxe.macro.Expr;
class ResourceMacro {
public static function has(field:Field):Bool {
return Util.hasFieldMeta(":resource", field);
}
private var field:Field;
public function new(field:Field) {
this.field = field;
}
public function apply():Array<Field> {
var result:Array<Field> = [];
return result;
}
}

View File

@@ -1,42 +0,0 @@
package haxework.macro;
import haxe.macro.Expr.MetadataEntry;
import haxe.macro.Context;
import haxe.macro.Type.ClassType;
class StyleMacro {
private static inline var metaName:String = ':style';
public static function has(classType:ClassType):Bool {
return Util.hasClassMeta(metaName, classType);
}
public static var style:Dynamic;
private var classType:ClassType;
private var bindings:Map<String, String>;
private var meta(get, never):MetadataEntry;
private var styleFile:String;
private function get_meta():MetadataEntry {
for (md in classType.meta.get()) if (md.name == metaName) {
return md;
}
return null;
}
public function new(classType:ClassType) {
this.classType = classType;
var params = Util.getMetaParams(meta);
var filePath = params[0];
if (filePath == null) {
filePath = classType.pack.join("/") + "/" + classType.name + ".yaml";
}
styleFile = Context.resolvePath(filePath);
style = FileUtil.loadFile(styleFile);
}
}

View File

@@ -22,7 +22,6 @@ class TemplateMacro {
private var meta(get, never):MetadataEntry;
private var templateFile:String;
private var template:Dynamic;
private var style:Dynamic;
private var i:Int;
private function get_meta():MetadataEntry {
@@ -42,12 +41,6 @@ class TemplateMacro {
}
templateFile = Context.resolvePath(filePath);
template = FileUtil.loadFile(templateFile);
if (params.length > 1) {
var styleFile = params.length > 1 ? Context.resolvePath(params[1]) : null;
style = FileUtil.loadFile(styleFile);
} else {
style = StyleMacro.style;
}
bindings = findViewsBindings(fields);
}
@@ -63,8 +56,8 @@ class TemplateMacro {
}
private function getPosition(?position:JsonKeyPosition):Position {
var min = position == null ? 1 : position.min + 32; // :-(
var max = position == null ? 1 : position.max + 32;
var min = position == null ? 1 : position.min; // :-(
var max = position == null ? 1 : position.max;
var file = position == null || position.file == null ? templateFile : position.file;
return Context.makePosition({min:min, max:max, file:file});
}
@@ -78,13 +71,13 @@ class TemplateMacro {
case _:
a[2];
}
case "res":
var bindExpr = 'haxework.provider.Provider.get(haxework.resources.IResources).${a[1]}.bind("${[2]}", "${name}", "${key}")';
case "res" | "r":
var bindExpr = 'haxework.provider.Provider.get(haxework.resources.IResources).${a[1]}.bind("${a[2]}", ${name}, "${key}")';
exprs.push(Context.parse(bindExpr, getPosition(position)));
null;
case "locale":
'new haxework.locale.LString("${[1]}")';
case "raw":
case "code":
a[1];
case "this":
'this.${a[1]}';
@@ -99,7 +92,7 @@ class TemplateMacro {
private static function getType(value:Dynamic, position:Position):Dynamic {
var type:Dynamic = getSpecField(value, "type");
if (type == null) {
Context.error("Need @type field", position);
Context.error("Need $type field", position);
}
return type;
}
@@ -147,17 +140,6 @@ class TemplateMacro {
}
private function createElement(name:String, data:Dynamic, exprs:Array<Expr>):String {
var s = getSpecField(data, "style");
if (s != null) {
var s = Reflect.field(style, s);
for (key in Reflect.fields(s)) {
if (key.charAt(0) != "$" && !Reflect.hasField(data, key)) {
Reflect.setField(data, key, Reflect.field(s, key));
Reflect.setField(data, "$" + key, Reflect.field(s, "$" + key));
}
}
}
if (Reflect.hasField(data, "id")) {
var id = Reflect.field(data, "id");
if (bindings.exists(id)) {

View File

@@ -1,12 +1,10 @@
package haxework.parser;
import haxework.macro.StyleMacro;
import haxe.macro.Context;
import haxe.macro.Expr;
import haxe.macro.Type.ClassType;
import haxe.macro.Type.Ref;
import haxe.macro.Type;
import haxework.macro.ProvideMacro;
import haxework.macro.ResourceMacro;
import haxework.macro.TemplateMacro;
@@ -31,6 +29,10 @@ class Parser {
modify = true;
var provide = new ProvideMacro(field);
result = result.concat(provide.apply());
} else if (ResourceMacro.has(field)) {
modify = true;
var resource = new ResourceMacro(field);
result = result.concat(resource.apply());
} else {
result.push(field);
}
@@ -39,9 +41,6 @@ class Parser {
fields = result;
}
// process class meta
if (StyleMacro.has(ct)) {
new StyleMacro(ct);
}
if (TemplateMacro.has(ct)) {
modify = true;
var template = new TemplateMacro(ct, fields);

View File

@@ -1,5 +1,6 @@
package haxework.resources;
import haxework.gui.skin.ISkin.SkinSet;
import flash.display.MovieClip;
import haxework.resources.Resources.ResMap;
import flash.display.BitmapData;
@@ -11,8 +12,6 @@ interface IResources {
public var text(default, null):ResMap<String>;
public var float(default, null):ResMap<Float>;
public var int(default, null):ResMap<Int>;
public var styles(default, null):ResMap<Dynamic>;
public var any(default, null):ResMap<Dynamic>;
public function loadStyles(asset:String):Void;
}
public var skin(default, null):ResMap<SkinSet>;
}

View File

@@ -1,77 +1,69 @@
package haxework.resources;
import openfl.Assets;
import haxe.Json;
import flash.display.MovieClip;
import haxework.core.Tuple;
import haxe.ds.StringMap;
import haxework.gui.skin.ISkin.SkinSet;
import flash.display.BitmapData;
import flash.display.MovieClip;
import haxe.ds.StringMap;
import haxework.core.Tuple;
private typedef F = Tuple2<Dynamic, String>
class ResMap<T> extends StringMap<T> {
private var listeners:Map<String, Array<F>>;
private var listeners:Map<String, Array<F>>;
public function new() {
super();
listeners = new Map<String, Array<F>>();
}
public function put(key:String, value:T):Void {
set(key, value);
if (listeners.exists(key)) {
for (f in listeners.get(key)) call(f, value);
public function new() {
super();
listeners = new Map<String, Array<F>>();
}
}
public function bind(key:String, object:Dynamic, field:String):Void {
var f:F = Tuple.two(object, field);
if (listeners.exists(key)) {
listeners.get(key).push(f);
} else {
listeners.set(key, [f]);
public function put(key:String, value:T):Void {
set(key, value);
if (listeners.exists(key)) {
for (f in listeners.get(key)) call(f, value);
}
}
if (exists(key)) call(f, get(key));
}
private function call(field:F, value:T):Void {
Reflect.setProperty(field.first, field.second, value);
}
public function merge(value:Dynamic<T>):Void {
for (field in Reflect.fields(value)) {
put(field, Reflect.field(value, field));
public function bind(key:String, object:Dynamic, field:String):Void {
var f:F = Tuple.two(object, field);
if (listeners.exists(key)) {
listeners.get(key).push(f);
} else {
listeners.set(key, [f]);
}
if (exists(key)) call(f, get(key));
}
private function call(field:F, value:T):Void {
Reflect.setProperty(field.first, field.second, value);
}
public function merge(value:Dynamic<T>):Void {
for (field in Reflect.fields(value)) {
put(field, Reflect.field(value, field));
}
}
}
}
class Resources implements IResources {
public var image(default, null):ResMap<BitmapData>;
public var color(default, null):ResMap<Int>;
public var movie(default, null):ResMap<MovieClip>;
public var text(default, null):ResMap<String>;
public var float(default, null):ResMap<Float>;
public var int(default, null):ResMap<Int>;
public var styles(default, null):ResMap<Dynamic>;
public var any(default, null):ResMap<Dynamic>;
public var image(default, null):ResMap<BitmapData>;
public var color(default, null):ResMap<Int>;
public var movie(default, null):ResMap<MovieClip>;
public var text(default, null):ResMap<String>;
public var float(default, null):ResMap<Float>;
public var int(default, null):ResMap<Int>;
public var any(default, null):ResMap<Dynamic>;
public var skin(default, null):ResMap<SkinSet>;
public function new() {
image = new ResMap<BitmapData>();
color = new ResMap<Int>();
movie = new ResMap<MovieClip>();
text = new ResMap<String>();
float = new ResMap<Float>();
int = new ResMap<Int>();
styles = new ResMap<Dynamic>();
any = new ResMap<Dynamic>();
}
public function loadStyles(asset:String):Void {
var stylesData = Json.parse(Assets.getText(asset));
for (key in Reflect.fields(stylesData)) {
styles.put(key, Reflect.field(stylesData, key));
public function new() {
image = new ResMap<BitmapData>();
color = new ResMap<Int>();
movie = new ResMap<MovieClip>();
text = new ResMap<String>();
float = new ResMap<Float>();
int = new ResMap<Int>();
any = new ResMap<Dynamic>();
skin = new ResMap<SkinSet>();
}
}
}
}