26 Commits
1.0.0 ... 1.3.0

Author SHA1 Message Date
7b7819fe6e [view] fix change in FrameSwitcher 2020-02-28 21:58:49 +03:00
2428ed20e0 [yaml] use yaml 2.0.0 library 2020-02-21 14:10:24 +03:00
bc3d6e4458 [view] add stretch param to TailLayout 2020-02-19 20:52:25 +03:00
d217727d94 [demo] add TestStorage 2020-02-13 22:31:10 +03:00
c889ca04da [yaml] add sources 2020-02-13 17:20:50 +03:00
39ca4b3d9b [style] rework 2020-02-11 22:47:03 +03:00
f81ab02e67 [geom] addd 2020-02-11 22:46:47 +03:00
284593e82c [view] add ConfirmView 2020-02-07 17:02:56 +03:00
a311dc1c19 [view] add AlertView 2020-02-06 17:10:19 +03:00
07c228121c [view] add back method to frame switcher 2020-02-05 23:18:29 +03:00
a6ff04fd1b [macro] TemplateMacro: move init to constructor 2019-11-19 21:53:33 +03:00
a768e75cec [demo] fixes 2019-11-19 17:51:30 +03:00
7a5b32b251 [macro] add ClassProvideMacro 2019-11-18 18:00:55 +03:00
74ed2d4425 [macro] add ClassTypeMacro and FieldMacro 2019-11-15 16:32:57 +03:00
fcbac5587e [view] add focus method 2019-11-14 16:48:51 +03:00
78f4ae3a03 [view] popup close fix 2019-11-10 17:03:24 +03:00
b18b9d2d30 [macro] add SignletonMacro 2019-10-30 22:15:46 +03:00
c88a2c810f [view] fix onTouchEnd in GroupView 2019-09-29 12:26:28 +03:00
a253aeaed4 [view] SpriteSkin: add round param 2019-09-11 21:04:42 +03:00
3478963a6f [view] add ActionDataView 2019-09-11 17:52:30 +03:00
5989da3fe4 [view] ListView: add selected style 2019-09-10 19:48:08 +03:00
32309389e5 Merge branch 'master' of bitbucket.org:shmyga/haxework 2019-09-09 21:46:03 +03:00
3d54a2489b [view] DataView: add onDataAction signal 2019-09-09 21:45:39 +03:00
7a68604cad [log] add AndroidLog 2019-08-23 14:38:27 +03:00
f31b1ce506 [view] GroupView: add maskEnable; Color: fromString improve 2019-07-29 17:57:11 +03:00
f186b08e9f build fixes 2019-07-22 23:25:18 +03:00
55 changed files with 883 additions and 296 deletions

View File

@@ -1,7 +1,8 @@
-cp src
-cp ../src/main
#-cp ../src/main
-lib yaml
-lib promhx
-lib haxework
--macro haxework.parser.Parser.auto()
-debug
-D native_trace

View File

@@ -8,13 +8,13 @@
<source path="src"/>
<assets path="src" rename="image" include="*.png"/>
<haxelib name="lime" version="7.3.0"/>
<haxelib name="openfl" version="8.9.0"/>
<haxelib name="hxcpp" version="4.0.8"/>
<haxelib name="promhx" version="1.1.0"/>
<haxelib name="yaml" version="1.3.0"/>
<haxelib name="lime" version=""/>
<haxelib name="openfl" version=""/>
<haxelib name="hxcpp" version=""/>
<!--<haxelib name="promhx" version=""/>-->
<haxelib name="haxework" version="git"/>
<haxeflag name="--macro" value="haxework.parser.Parser.auto()"/>
<!--<haxeflag name="&#45;&#45;macro" value="haxework.parser.Parser.auto()"/>-->
<haxeflag name="--macro" value="CompilationOption.set('build','xxx')"/>
<window fps="30"/>

View File

@@ -1,6 +1,7 @@
#!/usr/bin/env bash
SDK_PATH=~/sdk
echo "`pwd`/target" > ~/.macromedia/Flash_Player/#Security/FlashPlayerTrust/haxework_demo.cfg
. /opt/sdk/neko/2.2.0/activate
. /opt/sdk/haxe/3.4.7/activate
haxe build.hxml && flashplayerdebugger target/demo.swf &
. ${SDK_PATH}/neko/2.2.0/activate
. ${SDK_PATH}/haxe/4.0.5/activate
haxe build.hxml && ${SDK_PATH}/flashplayer/32/flashplayerdebugger target/demo.swf &
tail -f ~/.macromedia/Flash_Player/Logs/flashlog.txt

View File

@@ -1,5 +1,7 @@
#!/usr/bin/env bash
SDK_PATH=~/sdk
echo "`pwd`/target/flash/bin" > ~/.macromedia/Flash_Player/#Security/FlashPlayerTrust/haxework_demo.cfg
. /opt/sdk/neko/2.2.0/activate
. /opt/sdk/haxe/3.4.7/activate
haxelib run openfl test flash
. ${SDK_PATH}/neko/2.2.0/activate
. ${SDK_PATH}/haxe/4.0.5/activate
#haxelib run openfl test flash
haxelib run openfl test html5

View File

@@ -1,5 +1,8 @@
package demo;
import demo.storage.TestStorage;
import haxework.resources.IResources;
import haxework.provider.Provider;
import demo.dispatch.DemoDispatcher;
import demo.popup.ColorPopup;
import demo.popup.FontPopup;
@@ -15,7 +18,8 @@ import haxework.view.group.VGroupView;
@:view var switcher:FrameSwitcher;
@:view var tabs:ButtonGroup<String>;
private function init():Void {
public function new():Void {
super();
switcher.change("list");
}
@@ -42,13 +46,19 @@ import haxework.view.group.VGroupView;
class Demo extends App implements DemoListener {
@:provide static var resources:IResources;
@:provide static var storage:TestStorage;
public static function main() {
L.push(new TraceLogger());
var app = new Demo(new AppTheme());
app.resources.image.put("logo", HaxeLogo.resolve());
resources.image.put("logo", HaxeLogo.resolve());
var app = new Demo(new AppTheme(), resources.image.get("logo"));
app.start(new DemoView());
trace(storage);
storage.write("test", "value");
var dispatcher = new DemoDispatcher();
dispatcher.connect(app);
dispatcher.test1Signal.emit();
@@ -63,8 +73,8 @@ class Demo extends App implements DemoListener {
new JsonLoader().GET("https://embed.tvbit.co/channel/data2/renova.json")
.then(function(data:Array<Model>) {
app.resources.any.put("data", data);
app.resources.any.put("data50", Util.marray(data, 50));
resources.any.put("data", data);
resources.any.put("data50", Util.marray(data, 50));
})
.catchError(function(error) trace(error));
}

View File

@@ -9,6 +9,6 @@ interface DemoListener {
public function onTest4(app:App):Void;
}
@:yield @:dispatcher(DemoListener) class DemoDispatcher {
@:dispatcher(DemoListener) class DemoDispatcher {
public function new() {}
}

View File

@@ -10,9 +10,6 @@ import haxework.view.SpriteView;
public function new() {
super("test_layout");
}
public function init():Void {
resize();
content.addEventListener(MouseEvent.CLICK, function(_) {
resize();

View File

@@ -23,7 +23,8 @@ class FontLabelView extends LabelListItem<ThemeFont> {
@:view var fonts:ListView<ThemeFont>;
private function init():Void {
public function new():Void {
super();
var values:Array<ThemeFont> = Font.enumerateFonts(true).map(function(font:Font) {
return {
name: font.fontName,

View File

@@ -0,0 +1,10 @@
package demo.storage;
import haxework.storage.SharedObjectStorage;
@:provide class TestStorage extends SharedObjectStorage {
public function new() {
super("test");
}
}

View File

@@ -8,7 +8,7 @@
"template"
],
"description": "View framework.",
"version": "1.0.0",
"version": "1.3.0",
"releasenote": "Update.",
"contributors": [
"shmyga"
@@ -16,6 +16,6 @@
"classPath": "src/main",
"dependencies": {
"promhx": "1.1.0",
"yaml": "1.3.0"
"yaml": "2.0.0"
}
}

View File

@@ -1,13 +1,10 @@
package haxework;
import flash.display.BitmapData;
import flash.Lib;
import haxework.animate.Animate;
import haxework.animate.FadeAnimate;
import haxework.animate.UnFadeAnimate;
import haxework.net.manage.ILoaderManager;
import haxework.net.manage.LoaderManager;
import haxework.resources.IResources;
import haxework.resources.Resources;
import haxework.view.IView;
import haxework.view.popup.PopupManager;
import haxework.view.Root;
@@ -17,15 +14,15 @@ class App {
@:provide var app:App;
@:provide var theme:ITheme;
@:provide var resources:IResources;
@:provide var loaderManager:ILoaderManager;
@:provide var popupManager:PopupManager;
public function new(?theme:ITheme) {
public function new(?theme:ITheme, ?icon:BitmapData) {
this.theme = theme;
resources = new Resources();
loaderManager = new LoaderManager();
popupManager = new PopupManager();
#if linux
if (icon != null) {
haxework.app.LinuxIcon.value = icon;
}
#end
popupManager.showAnimateFactory = function(v) return new UnFadeAnimate(v);
popupManager.closeAnimateFactory = function(v) return new FadeAnimate(v);
app = this;

View File

@@ -0,0 +1,29 @@
package haxework.app;
import flash.display.BitmapData;
import flash.filters.ColorMatrixFilter;
import flash.geom.Point;
import flash.Lib;
class LinuxIcon {
public static var value(default, set):BitmapData;
private static function set_value(value:BitmapData):BitmapData {
LinuxIcon.value = value;
Lib.current.stage.window.setIcon(prepareIcon(value).image);
return LinuxIcon.value;
}
private static function prepareIcon(bitmap:BitmapData):BitmapData {
var matrix:Array<Float> = [];
matrix = matrix.concat([0, 0, 1, 0, 0]);
matrix = matrix.concat([0, 1, 0, 0, 0]);
matrix = matrix.concat([1, 0, 0, 0, 0]);
matrix = matrix.concat([0, 0, 0, 1, 0]);
var cmf:ColorMatrixFilter = new ColorMatrixFilter(matrix);
var bitmap:BitmapData = bitmap.clone();
bitmap.applyFilter(bitmap, bitmap.rect, new Point(0, 0), cmf);
return bitmap;
}
}

View File

@@ -44,7 +44,25 @@ abstract Color(Int) {
}
@:from static public inline function fromString(value:String):Color {
return new Color(Std.parseInt('0x${value.split('#').pop()}'));
return new Color(switch value {
case "white": 0xFFFFFF;
case "silver": 0xC0C0C0;
case "gray": 0x808080;
case "black": 0x000000;
case "red": 0xFF0000;
case "maroon": 0x800000;
case "yellow": 0xFFFF00;
case "olive": 0x808000;
case "lime": 0x00FF00;
case "green": 0x008000;
case "aqua": 0x00FFFF;
case "teal": 0x008080;
case "blue": 0x0000FF;
case "navy": 0x000080;
case "fuchsia": 0xFF00FF;
case "purple": 0x800080;
case x: Std.parseInt('0x${x.split('#').pop()}');
});
}
@:to public inline function toString():String {

View File

@@ -0,0 +1,35 @@
package haxework.geom;
abstract IntPoint(Array<Int>) {
public var x(get, set):Int;
public var y(get, set):Int;
public function new(x:Int, y:Int) {
this = [x, y];
}
private inline function get_x() return this[0];
private inline function set_x(value) return this[0] = value;
private inline function get_y() return this[1];
private inline function set_y(value) return this[1] = value;
public function clone():IntPoint {
return new IntPoint(x, y);
}
public function toString():String {
return 'IntPoint{x=$x,y=$y}';
}
@:to inline public function toInt():Int {
return (x << 16) + y;
}
@:to inline public function toPoint():Point {
return new Point(x, y);
}
}

View File

@@ -0,0 +1,40 @@
package haxework.geom;
import flash.geom.Point as FlashPoint;
abstract Point(Array<Float>) {
public var x(get, set):Float;
public var y(get, set):Float;
public function new(x:Float, y:Float) {
this = [x, y];
}
private inline function get_x() return this[0];
private inline function set_x(value) return this[0] = value;
private inline function get_y() return this[1];
private inline function set_y(value) return this[1] = value;
public function add(point:Point):Point {
return new Point(x + point.x, y + point.y);
}
public function subtract(point:Point):Point {
return new Point(x - point.x, y - point.y);
}
public function clone():Point {
return new Point(x, y);
}
public function toString():String {
return 'Point{x=$x,y=$y}';
}
@:from public static function fromFlashPoint(value:FlashPoint):Point {
return new Point(value.x, value.y);
}
}

View File

@@ -0,0 +1,102 @@
package haxework.geom;
abstract Rectangle(Array<Float>) {
public var x(get, set):Float;
public var y(get, set):Float;
public var width(get, set):Float;
public var height(get, set):Float;
public var center(get, set):Point;
public var size(get, set):Point;
public var left(get, never):Float;
public var right(get, never):Float;
public var top(get, never):Float;
public var bottom(get, never):Float;
public var position(get, set):Point;
public function new(x:Float = 0, y:Float = 0, width:Float = 0, height:Float = 0) {
this = [x, y, width, height];
}
private inline function get_x() return this[0];
private inline function set_x(value) return this[0] = value;
private inline function get_y() return this[1];
private inline function set_y(value) return this[1] = value;
private inline function get_width() return this[2];
private inline function set_width(value) return this[2] = value;
private inline function get_height() return this[3];
private inline function set_height(value) return this[3] = value;
private function get_center():Point {
return new Point(x + width / 2, y + height / 2);
}
private function set_center(value:Point):Point {
x = value.x - width / 2;
y = value.y - height / 2;
return value;
}
private function get_size():Point {
return new Point(width, height);
}
private function set_size(value:Point):Point {
width = value.x;
height = value.y;
return value;
}
public function contain(point:Point):Bool {
return point.x >= left && point.y >= top && point.x <= right && point.y <= bottom;
}
public function intersection(rect:Rectangle):Bool {
return !(
rect.left > right ||
rect.right < left ||
rect.top > bottom ||
rect.bottom < top
);
}
public function clone():Rectangle {
return new Rectangle(x, y, width, height);
}
public function toString():String {
return 'Rectangle{x=$x,y=$y,width=$width,height=$height}';
}
private function get_left():Float {
return x;
}
private function get_right():Float {
return x + width;
}
private function get_top():Float {
return y;
}
private function get_bottom():Float {
return y + height;
}
private function get_position():Point {
return new Point(x, y);
}
private function set_position(position:Point):Point {
x = position.x;
y = position.y;
return position;
}
}

View File

@@ -0,0 +1,15 @@
package haxework.log;
import cpp.VarArg;
import haxe.extern.Rest;
import cpp.ConstCharStar;
@:include("android/log.h")
extern class AndroidLog {
@:native("__android_log_print")
public static function print(prio:Int, tag:ConstCharStar, fmt:ConstCharStar, rest:Rest<VarArg>):Void;
@:native("__android_log_write")
public static function write(prio:Int, tag:ConstCharStar, message:ConstCharStar):Void;
}

View File

@@ -12,11 +12,11 @@ class LoggerUtil {
public static function printStackItem(item:StackItem):String {
return switch item {
case StackItem.CFunction: 'CFunction';
case StackItem.Module(m): m;
case StackItem.FilePos(s, file, line): '${file}:${line}';
case StackItem.Method(classname, method): '${classname}::${method}}';
case StackItem.LocalFunction(v): 'LocalFunction(${v})';
case CFunction: 'CFunction';
case Module(m): m;
case FilePos(s, file, line): '${file}:${line}';
case Method(classname, method): '${classname}::${method}}';
case LocalFunction(v): 'LocalFunction(${v})';
}
}

View File

@@ -27,7 +27,11 @@ class TraceLogger extends BaseLogger {
$print("\n");
}
#elseif js
untyped js.Boot.__trace(v, infos);
if (js.Syntax.typeof(untyped console) != "undefined" && (untyped console).log != null)
(untyped console).log(v);
//untyped js.Boot.__trace(v, infos);
#elseif android
haxework.log.AndroidLog.write(3, "", ConstCharStar.fromString(Std.string(v)));
#elseif (php && php7)
php.Boot.trace(v);
#elseif php

View File

@@ -0,0 +1,20 @@
package haxework.macro;
import haxe.macro.Expr;
import haxe.macro.Type;
class ClassProvideMacro extends ClassTypeMacro {
public static var bundle(default, null):Array<{key: ClassType, value: ClassType}> = [];
public function new() {
super(":provide");
}
override public function apply(classType:ClassType, fields:Array<Field>):Array<Field> {
var meta = MacroUtil.getClassMeta(classType, metaName);
var valueType = meta.params.length == 0 ? classType : MacroUtil.getExprClassType(meta.params[0]);
bundle.push({key: classType, value: valueType});
return super.apply(classType, fields);
}
}

View File

@@ -0,0 +1,21 @@
package haxework.macro;
import haxe.macro.Expr;
import haxe.macro.Type;
class ClassTypeMacro {
public var metaName(default, null):String;
public function new(metaName:String) {
this.metaName = metaName;
}
public function has(classType:ClassType):Bool {
return classType.meta.has(metaName);
}
public function apply(classType:ClassType, fields:Array<Field>):Array<Field> {
return fields;
}
}

View File

@@ -6,20 +6,10 @@ import haxe.macro.ExprTools;
import haxe.macro.Expr;
import haxe.macro.Type;
class DispatcherMacro {
class DispatcherMacro extends ClassTypeMacro {
private static inline var metaName:String = ':dispatcher';
public static function has(classType:ClassType):Bool {
return classType.meta.has(metaName);
}
private var classType:ClassType;
private var fields:Array<Field>;
public function new(classType:ClassType, fields:Array<Field>) {
this.classType = classType;
this.fields = fields;
public function new() {
super(":dispatcher");
}
private static inline function signalName(fieldName:String):String {
@@ -30,13 +20,10 @@ class DispatcherMacro {
}
}
public function apply():Array<Field> {
override public function apply(classType:ClassType, fields:Array<Field>):Array<Field> {
var result:Array<Field> = fields.slice(0);
var typeName = ExprTools.toString(classType.meta.extract(metaName)[0].params[0]);
var type:ClassType = switch Context.getType(typeName) {
case TInst(t, _): t.get();
case _: null;
}
var type:ClassType = MacroUtil.getExprClassType(classType.meta.extract(metaName)[0].params[0]);
var fields = type.fields.get();
for (field in fields) {
var argsTypes:Array<Type> = switch field.type {

View File

@@ -0,0 +1,21 @@
package haxework.macro;
import haxe.macro.Expr;
using haxework.macro.MacroUtil;
class FieldMacro {
public var metaName(default, null):String;
public function new(metaName:String) {
this.metaName = metaName;
}
public function has(field:Field):Bool {
return field.getFieldMeta(metaName) != null;
}
public function apply(field:Field):Array<Field> {
return [];
}
}

View File

@@ -1,9 +1,11 @@
package haxework.macro;
import haxe.macro.Type.ClassType;
import haxe.macro.Context;
import haxe.macro.ExprTools;
import haxe.macro.Expr;
import haxe.macro.Type;
class Util {
class MacroUtil {
public static function getMetaParams(meta:MetadataEntry):Array<String> {
return meta.params.map(function(param:Expr) return switch param.expr {
@@ -17,15 +19,21 @@ class Util {
}
public static function getClassMeta(classType:ClassType, metaName:String):Null<MetadataEntry> {
for (md in classType.meta.get()) if (md.name == metaName) {
return md;
for (meta in classType.meta.get()) {
if (meta.name == metaName) {
return meta;
}
}
return null;
}
public static function getFieldMeta(field:Field, metaName:String):Null<MetadataEntry> {
for (md in field.meta) if (md.name == metaName) {
return md;
if (field.meta != null) {
for (meta in field.meta) {
if (meta.name == metaName) {
return meta;
}
}
}
return null;
}
@@ -48,4 +56,29 @@ class Util {
public static function getField(fields:Array<Field>, name:String):Null<Field> {
return Lambda.find(fields, function(field:Field):Bool return field.name == name);
}
public static function getExprClassType(expr:Expr):Null<ClassType> {
var typeName = ExprTools.toString(expr);
return switch Context.getType(typeName) {
case TInst(t, _): t.get();
case _: null;
}
}
public static function upgradeField(field:Field, expr:Expr, position:Int = 0):Field {
switch field.kind {
case FFun(f):
var fieldExpr = f.expr;
switch fieldExpr.expr {
case EBlock(exprs):
exprs.insert(position, expr);
fieldExpr = macro $b{exprs};
case _:
fieldExpr = macro $b{[fieldExpr, expr]}
}
f.expr = fieldExpr;
case _:
}
return field;
}
}

View File

@@ -17,7 +17,7 @@ class PositionYamlParser {
}
private function parseAll():Void {
parseBlock(result);
//parseBlock(result);
}
private function parseBlock(result:DynamicAccess<Dynamic>):Void {

View File

@@ -3,25 +3,16 @@ package haxework.macro;
import haxe.macro.Context;
import haxe.macro.Expr;
using haxework.macro.Util;
using haxework.macro.MacroUtil;
class ProvideMacro {
class ProvideMacro extends FieldMacro {
private static var metaName = ":provide";
public static function has(field:Field):Bool {
return field.getFieldMeta(metaName) != null;
public function new() {
super(":provide");
}
private var field:Field;
private var meta:MetadataEntry;
public function new(field:Field) {
this.field = field;
this.meta = field.getFieldMeta(metaName);
}
public function apply():Array<Field> {
override public function apply(field:Field):Array<Field> {
var meta:MetadataEntry = field.getFieldMeta(metaName);
var result:Array<Field> = [];
var type:ComplexType = switch field.kind {
case FVar(t): t;
@@ -31,14 +22,9 @@ class ProvideMacro {
case TPath(p): p.name;
default: null;
}
var provideType:String = meta.params.length == 0 ? null : Util.getExprString(meta.params[0].expr);
var provideType:String = meta.params.length == 0 ? null : MacroUtil.getExprString(meta.params[0].expr);
var isStatic = Lambda.exists(field.access, function(a: Access) return a == AStatic);
result.push({
name: field.name,
access: isStatic ? [APublic, AStatic] : [APublic],
pos: field.pos,
kind: FProp('get', 'set', type),
});
field.kind = FProp('get', 'set', type);
var access = [APrivate, AInline];
if (isStatic) access.push(AStatic);
var args = [name];
@@ -49,7 +35,7 @@ class ProvideMacro {
pos: field.pos,
kind: FFun({
args: [],
expr: Context.parse('return haxework.provider.Provider.get(${args.join(',')})', field.pos),
expr: Context.parse('return haxework.provider.Provider.instance.get(${args.join(',')})', field.pos),
params: [],
ret: type,
})
@@ -61,7 +47,7 @@ class ProvideMacro {
pos: field.pos,
kind: FFun({
args: [{name: 'value', type: type}],
expr: Context.parse('{haxework.provider.Provider.set(${args.join(',')}); return value;}', field.pos),
expr: Context.parse('{haxework.provider.Provider.instance.set(${args.join(',')}); return value;}', field.pos),
params: [],
ret: type,
})

View File

@@ -1,22 +1,10 @@
package haxework.macro;
import haxe.macro.Expr;
using haxework.macro.MacroUtil;
using haxework.macro.Util;
class ResourceMacro extends FieldMacro {
class ResourceMacro {
public static function has(field:Field):Bool {
return field.getFieldMeta(":resource") != null;
}
private var field:Field;
public function new(field:Field) {
this.field = field;
}
public function apply():Array<Field> {
var result:Array<Field> = [];
return result;
public function new() {
super(":resource");
}
}

View File

@@ -0,0 +1,43 @@
package haxework.macro;
import haxe.macro.Context;
import haxe.macro.Expr;
import haxe.macro.Type;
class SingletonMacro extends ClassTypeMacro {
public function new() {
super(":singleton");
}
override public function apply(classType:ClassType, fields:Array<Field>):Array<Field> {
var result:Array<Field> = fields.slice(0);
var classTypePath:TypePath = {
pack: classType.pack,
name: classType.name,
};
var type:ComplexType = TPath(classTypePath);
result.push({
name: 'instance',
access: [APublic, AStatic],
pos: Context.currentPos(),
kind: FProp('get', 'null', type),
});
var typeStr = classType.name;
result.push({
name: 'get_instance',
access: [APrivate, AStatic],
pos: Context.currentPos(),
kind: FFun({
args: [],
ret: type,
expr: macro $b{[
macro if (instance == null) instance = new $classTypePath(),
macro return instance
]},
}),
});
return result;
}
}

View File

@@ -5,7 +5,7 @@ import haxe.macro.Expr;
import haxe.macro.Type;
using haxe.macro.ComplexTypeTools;
using haxework.macro.Util;
using haxework.macro.MacroUtil;
using haxe.macro.MacroStringTools;
typedef TProperty<T> = {
@@ -13,21 +13,10 @@ typedef TProperty<T> = {
var defaultValue: T;
}
class StyleMacro {
private static inline var metaName:String = ':style';
class StyleMacro extends ClassTypeMacro {
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;
public function new() {
super(":style");
}
private static function processPropertyField(field:Field):Array<Field> {
@@ -173,11 +162,11 @@ class StyleMacro {
}
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));
expr.push(macro $i{propertyName} = haxework.provider.Provider.instance.get(haxework.view.theme.ITheme).resolve((styleKey!=null?(styleKey+"."):"")+$v{field.name}, style));
}
for (field in styleds) {
var propertyName = '${field.name}';
expr.push(macro $i{propertyName} = haxework.provider.Provider.get(haxework.view.theme.ITheme).resolve((styleKey!=null?(styleKey+"."):"")+$v{field.name}, style));
expr.push(macro $i{propertyName} = haxework.provider.Provider.instance.get(haxework.view.theme.ITheme).resolve((styleKey!=null?(styleKey+"."):"")+$v{field.name}, style));
}
if (hasOnStyle) {
expr.push(macro onStyle());
@@ -201,14 +190,15 @@ class StyleMacro {
return result;
}
public function apply():Array<Field> {
override public function apply(classType:ClassType, fields:Array<Field>):Array<Field> {
var overrideStyle = classType.getClassMeta(metaName).params.length > 0;
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");
var meta = field.getFieldMeta(metaName);
if (meta != null) {
if (meta.params.length > 0) {
newFields = newFields.concat(processPropertyField(field));

View File

@@ -1,45 +1,23 @@
package haxework.macro;
import Lambda;
import haxe.macro.Context;
import haxe.macro.Expr;
import haxe.macro.Type;
import haxework.macro.PositionJsonParser;
import Lambda;
using haxework.macro.Util;
using haxework.macro.MacroUtil;
class TemplateMacro {
class TemplateMacro extends ClassTypeMacro {
private static inline var metaName:String = ':template';
public static function has(classType:ClassType):Bool {
return classType.getClassMeta(metaName) != null;
}
private var classType:ClassType;
private var fields:Array<Field>;
private var bindings:Map<String, String>;
private var meta:MetadataEntry;
private var templateFile:String;
private var template:Dynamic;
private var i:Int;
public function new(classType:ClassType, fields:Array<Field>) {
this.classType = classType;
this.meta = classType.getClassMeta(metaName);
this.fields = fields;
var params = Util.getMetaParams(meta);
var filePath = params[0];
if (filePath == null) {
filePath = classType.pack.join("/") + "/" + classType.name + ".yaml";
public function new() {
super(":template");
}
templateFile = Context.resolvePath(filePath);
template = FileUtil.loadFile(templateFile);
bindings = findViewsBindings(fields);
}
private static function getSpecField(object:Dynamic, field:String):Dynamic {
if (Reflect.hasField(object, "@" + field)) {
@@ -68,7 +46,7 @@ class TemplateMacro {
a[2];
}
case "resource" | "r":
var bindExpr = 'haxework.provider.Provider.get(haxework.resources.IResources).${a[1]}.bind("${a[2]}", ${name}, "${key}")';
var bindExpr = 'haxework.provider.Provider.instance.get(haxework.resources.IResources).${a[1]}.bind("${a[2]}", ${name}, "${key}")';
exprs.push(Context.parse(bindExpr, getPosition(position)));
null;
case "translate" | "t":
@@ -176,57 +154,57 @@ class TemplateMacro {
}
}
private function buildConstructor(init:Bool, constructor:Field = null):Field {
var contstrExprs = [];
if (constructor != null) {
switch constructor.kind {
case FFun(f): contstrExprs.push(f.expr);
case _:
}
} else {
contstrExprs.push(macro super());
}
contstrExprs.push(macro build());
if (init) contstrExprs.push(macro init());
return {
private function upgradeConstructor(constructor:Field = null):Field {
if (constructor == null) {
constructor = {
name: "new",
access: [Access.APublic],
pos: getPosition(),
kind: FieldType.FFun({
args: [],
expr: macro $b{contstrExprs},
expr: macro super(),
params: [],
ret: null
})
};
}
}
MacroUtil.upgradeField(constructor, macro build(), 1);
return constructor;
}
private static function findViewsBindings(fields:Array<Field>):Map<String, String> {
var result:Map<String, String> = new Map();
for (field in fields) if (field.meta != null) {
for (meta in field.meta) {
if (meta.name == ':view') {
var viewId:String = meta.params.length == 0 ? field.name : Util.getExprString(meta.params[0].expr);
for (field in fields) {
var viewMeta = field.getFieldMeta(":view");
if (viewMeta != null) {
var viewId:String = viewMeta.params.length == 0 ? field.name : MacroUtil.getExprString(viewMeta.params[0].expr);
result.set(viewId, field.name);
}
}
}
return result;
}
public function apply():Array<Field> {
override public function apply(classType:ClassType, fields:Array<Field>):Array<Field> {
i = 0;
var meta = classType.getClassMeta(metaName);
var params = MacroUtil.getMetaParams(meta);
var filePath = params[0];
if (filePath == null) {
filePath = classType.pack.join("/") + "/" + classType.name + ".yaml";
}
// ToDo: template builder
templateFile = Context.resolvePath(filePath);
template = FileUtil.loadFile(templateFile);
bindings = findViewsBindings(fields);
var result:Array<Field> = fields.slice(0);
var exprs:Array<Expr> = [];
var init = Lambda.exists(result, function(f) return f.name == "init");
createElement("this", template, exprs);
result.push(buildBuild(exprs));
var constructor = Lambda.find(result, function(f) return f.name == "new");
if (constructor != null) {
result.remove(constructor);
}
result.push(buildConstructor(init, constructor));
result.push(upgradeConstructor(constructor));
if (Lambda.count(bindings) > 0) {
var keys = Lambda.map({iterator: bindings.keys}, function(k) return '"${k}"').join(",");
Context.error('Invalid @:view bindings: $keys', getPosition());

View File

@@ -1,6 +1,6 @@
package haxework.net.manage;
interface ILoaderManager {
@:provide(LoaderManager) interface ILoaderManager {
public var actives(default, null):Array<ILoader<Dynamic>>;
public var queue(default, null):Array<ILoader<Dynamic>>;
public var limit(default, default):Int;

View File

@@ -1,17 +1,34 @@
package haxework.parser;
import haxework.macro.StyleMacro;
import haxe.macro.TypeTools;
import haxe.macro.Context;
import haxe.macro.Expr;
import haxe.macro.Type;
import haxe.macro.TypeTools;
import haxework.macro.ClassProvideMacro;
import haxework.macro.ClassTypeMacro;
import haxework.macro.DispatcherMacro;
import haxework.macro.FieldMacro;
import haxework.macro.ProvideMacro;
import haxework.macro.ResourceMacro;
import haxework.macro.SingletonMacro;
import haxework.macro.StyleMacro;
import haxework.macro.TemplateMacro;
class Parser {
private static var classTypeMacros:Array<ClassTypeMacro> = [
new ClassProvideMacro(),
new TemplateMacro(),
new DispatcherMacro(),
new StyleMacro(),
new SingletonMacro(),
];
private static var fieldMacros:Array<FieldMacro> = [
new ProvideMacro(),
new ResourceMacro(),
];
private static var processed:Map<String, Bool> = new Map();
private static function auto():Void {
@@ -29,39 +46,25 @@ class Parser {
var modify:Bool = false;
var fields:Array<Field> = Context.getBuildFields();
var result:Array<Field> = [];
var appends:Array<Field> = [];
// process fields meta
for (field in fields) {
if (ProvideMacro.has(field)) {
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);
for (item in fieldMacros) {
if (item.has(field)) {
modify = true;
result = result.concat(item.apply(field));
}
}
}
if (modify) {
fields = result;
}
// process class meta
if (TemplateMacro.has(ct)) {
for (item in classTypeMacros) {
if (item.has(ct)) {
modify = true;
var template = new TemplateMacro(ct, fields);
fields = template.apply();
fields = item.apply(ct, fields);
}
if (DispatcherMacro.has(ct)) {
modify = true;
var dispatcher = new DispatcherMacro(ct, fields);
fields = dispatcher.apply();
}
if (StyleMacro.has(ct)) {
modify = true;
var style = new StyleMacro(ct, fields);
fields = style.apply();
}
processed.set(localName, true);
modify ? fields : null;

View File

@@ -15,7 +15,7 @@ abstract KeyType<T>(String) {
}
}
class Provider {
@:singleton class Provider {
private static function key<T>(i:KeyType<T>, ?type:Dynamic):String {
var result:String = Std.string(i);
@@ -23,22 +23,40 @@ class Provider {
return result;
}
private static var factories:Map<String, Class<Dynamic>> = new Map();
private static var args:Map<String, Array<Dynamic>> = new Map();
private static var instances:Map<String, Dynamic> = new Map();
public var factories:Map<String, Class<Dynamic>>;
private var args:Map<String, Array<Dynamic>>;
private var instances:Map<String, Dynamic>;
public static function setFactory<T>(i:KeyType<T>, clazz:Class<T>, ?type:Dynamic, ?args:Array<Dynamic>):Void {
var key = key(i, type);
factories.set(key, clazz);
if (args != null) Provider.args.set(key, args);
public function new() {
factories = new Map();
args = new Map();
instances = new Map();
resolveDefaultFactories();
}
public static function set<T>(i:KeyType<T>, instance:T, ?type:Dynamic):Void {
macro static function resolveDefaultFactories() {
var result = [];
for (item in haxework.macro.ClassProvideMacro.bundle) {
// ToDo: ClassType to Expr?
var k = haxe.macro.Context.parse(haxe.macro.MacroStringTools.toDotPath(item.key.pack, item.key.name), haxe.macro.Context.currentPos());
var v = haxe.macro.Context.parse(haxe.macro.MacroStringTools.toDotPath(item.value.pack, item.value.name), haxe.macro.Context.currentPos());
result.push(macro setFactory(${k}, ${v}));
}
return macro $b{result};
}
public function setFactory<T>(i:KeyType<T>, clazz:Class<T>, ?type:Dynamic, ?args:Array<Dynamic>):Void {
var key = key(i, type);
factories.set(key, clazz);
if (args != null) this.args.set(key, args);
}
public function set<T>(i:KeyType<T>, instance:T, ?type:Dynamic):Void {
var key = key(i, type);
instances.set(key, instance);
}
public static function get<T>(i:KeyType<T>, ?type:Dynamic):T {
public function get<T>(i:KeyType<T>, ?type:Dynamic):T {
var key = key(i, type);
if (instances.exists(key)) {
return instances.get(key);
@@ -47,12 +65,11 @@ class Provider {
instances.set(key, instance);
return instance;
} else {
return null;
//throw 'Factory for "${key}" not found';
throw 'Factory for "${key}" not found';
}
}
public static function build<T>(i:Class<T>, ?type:Dynamic):T {
public function build<T>(i:Class<T>, ?type:Dynamic):T {
var key = key(i, type);
if (factories.exists(key)) {
var instance:T = Type.createInstance(factories.get(key), args.exists(key) ? args.get(key) : []);
@@ -62,7 +79,7 @@ class Provider {
}
}
public static function setProperty<T>(i:Class<T>, field:String, value:Dynamic, ?type:Dynamic):Void {
public function setProperty<T>(i:Class<T>, field:String, value:Dynamic, ?type:Dynamic):Void {
var o:Dynamic = get(i, type);
if (o != null && Reflect.hasField(o, field)) {
Reflect.setProperty(o, field, value);

View File

@@ -2,9 +2,9 @@ package haxework.resources;
import flash.display.BitmapData;
import flash.display.MovieClip;
import haxework.resources.Resources.ResMap;
import haxework.resources.Resources;
interface IResources {
@:provide(Resources) interface IResources {
public var image(default, null):ResMap<BitmapData>;
public var color(default, null):ResMap<Int>;
public var movie(default, null):ResMap<MovieClip>;

View File

@@ -30,7 +30,7 @@ class Root {
this.autoSize = autoSize;
Lib.current.addChild(view.content);
if (Std.is(view, IGroupView)) {
Provider.set(IGroupView, cast view);
Provider.instance.set(IGroupView, cast view);
}
var content:DisplayObject = view.content;
if (content.stage == null) {

View File

@@ -1,6 +1,7 @@
package haxework.view;
import haxework.view.form.InputView;
import flash.Lib;
import flash.display.Stage;
import flash.display.DisplayObject;
import flash.display.InteractiveObject;
import flash.geom.Rectangle;
@@ -40,6 +41,12 @@ import haxework.view.theme.ITheme;
public var rect(get, null):Rectangle;
private var stage(get, null):Stage;
private function get_stage():Stage {
return Lib.current.stage;
}
public function new(content:C) {
id = Type.getClassName(Type.getClass(this)) + counter++;
size = new SizeSet();

View File

@@ -9,6 +9,10 @@ import haxework.view.layout.VerticalLayout;
typedef Factory<D, V:IView<Dynamic>> = Int -> D -> V
class ActionDataView<D, V:IView<Dynamic>, A> extends DataView<D, V> {
public var onDataAction(default, null):Signal2<D, A> = new Signal2();
}
class DataView<D, V:IView<Dynamic>> extends GroupView {
public var data(default, set):Array<D>;

View File

@@ -18,6 +18,7 @@ class ButtonView extends LabelView {
public var disabled(default, set):Bool;
public var state(get, null):ButtonState;
public var onPress(default, null):Signal<ButtonView>;
public var propagation(default, default):Bool;
private var overed:Bool;
private var downed:Bool;
@@ -26,6 +27,7 @@ class ButtonView extends LabelView {
super();
skin = new ButtonColorSkin();
style = "button";
propagation = true;
overed = false;
downed = false;
state = ButtonState.UP;
@@ -47,7 +49,7 @@ class ButtonView extends LabelView {
private function onMouseClick(event:MouseEvent):Void {
#if js if (downed) { #end
//event.stopImmediatePropagation();
if (!propagation) event.stopImmediatePropagation();
if (!disabled) onPress.emit(this);
#if js } #end
}

View File

@@ -17,11 +17,13 @@ class FrameSwitcher extends GroupView {
public var animateFactory(default, default):Class<IAnimate>;
private var animate:IAnimate;
private var history:Array<{id:String, data:Dynamic}>;
public function new() {
super();
factory = new Map();
frames = new Map();
history = [];
current = null;
}
@@ -55,29 +57,33 @@ class FrameSwitcher extends GroupView {
if (current == null) {
throw 'frame "$id" not found';
}
addView(current);
toUpdate();
update();
//ToDo:
if (content.stage != null) {
content.stage.focus = current.content;
}
current.onShow(data);
if (animate != null) {
animate.cancel();
}
animate = buildAnimate(current);
if (animate != null && prev != null) {
animate.start(function(_) {
removePrev(prev);
});
animate.start(function(_) removePrev(prev));
} else {
removePrev(prev);
}
addView(current);
toUpdate();
update();
focus(current);
current.onShow(data);
history.push({id:current.frameId, data:data});
onSwitch.emit(current);
return cast current;
}
public function back():Void {
if (history.length > 1) {
history.pop();
var item = history.pop();
change(item.id, item.data);
}
}
private function removePrev(prev:Null<FrameView<Dynamic>>):Void {
if (prev != null) {
prev.onHide();

View File

@@ -67,7 +67,7 @@ class OverflowControl {
}
@:style(true) class GroupView extends SpriteView implements IGroupView {
public var container(null, null):DisplayObjectContainer;
public var container(default, null):DisplayObjectContainer;
public var views(default, set):Array<IView<Dynamic>>;
@:style public var layout(default, default):ILayout;
@@ -79,6 +79,7 @@ class OverflowControl {
private var _mask:Sprite;
private var scrollX(get, null):HScrollBarView;
private var scrollY(get, null):VScrollBarView;
private var maskEnable(default, set):Bool;
public var overflowControlX(default, null):OverflowControl;
public var overflowControlY(default, null):OverflowControl;
@@ -88,8 +89,6 @@ class OverflowControl {
container = new Sprite();
content.addChild(container);
_mask = new Sprite();
content.addChild(_mask);
container.mask = _mask;
this.layout = layout != null ? layout : new DefaultLayout();
this.overflow = overflow != null ? overflow : new Overflow();
views = [];
@@ -101,6 +100,21 @@ class OverflowControl {
content.addEventListener(TouchEvent.TOUCH_BEGIN, onTouchBegin);
}
private function set_maskEnable(value:Bool):Bool {
if (maskEnable != value) {
maskEnable = value;
if (maskEnable) {
content.addChild(_mask);
container.mask = _mask;
} else {
content.removeChild(_mask);
container.mask = null;
}
}
return value;
}
private function onMouseWheelEvent(event:MouseEvent):Void {
if (overflowY > 1) {
#if flash event.preventDefault(); #end
@@ -130,8 +144,8 @@ class OverflowControl {
private function onTouchEnd(event:TouchEvent):Void {
event.preventDefault();
content.stage.removeEventListener(TouchEvent.TOUCH_MOVE, onTouchMove);
content.stage.removeEventListener(TouchEvent.TOUCH_END, onTouchEnd);
stage.removeEventListener(TouchEvent.TOUCH_MOVE, onTouchMove);
stage.removeEventListener(TouchEvent.TOUCH_END, onTouchEnd);
}
private function get_scrollX():HScrollBarView {
@@ -157,10 +171,12 @@ class OverflowControl {
}
public function set_overflowX(value:Float):Float {
maskEnable = value > 1;
return overflowX = overflowControlX.overflow = value;
}
public function set_overflowY(value:Float):Float {
maskEnable = value > 1;
return overflowY = overflowControlY.overflow = value;
}
@@ -177,7 +193,9 @@ class OverflowControl {
overflowControlY.size = height;
_mask.graphics.clear();
_mask.graphics.beginFill(0, 1);
if (!Math.isNaN(width) && !Math.isNaN(height) && width > 0 && height > 0) {
_mask.graphics.drawRect(0, 0, width, height);
}
_mask.graphics.endFill();
}
@@ -235,6 +253,12 @@ class OverflowControl {
}
}
public function focus(?view:IView<Dynamic>):Void {
if (container.stage != null) {
container.stage.focus = view != null ? view.content : content;
}
}
override private function get_rect():Rectangle {
var result = super.get_rect();
result.x += overflowControlX.offset;

View File

@@ -11,7 +11,7 @@ interface IGroupView extends IView<Dynamic> {
public var overflowX(default, set):Float;
public var overflowY(default, set):Float;
public var container(null, null):DisplayObjectContainer;
public var container(default, null):DisplayObjectContainer;
public var views(default, set):Array<IView<Dynamic>>;
public function containsView(view:IView<Dynamic>):Bool;
@@ -25,4 +25,6 @@ interface IGroupView extends IView<Dynamic> {
public function removeView(view:IView<Dynamic>):IView<Dynamic>;
public function removeAllViews():Void;
public function focus(?view:IView<Dynamic>):Void;
}

View File

@@ -35,16 +35,18 @@ class DefaultLayout extends Layout {
},
"group"
);
switch group.overflow.x {
var ox = switch group.overflow.x {
case SCROLL:
group.overflowX = width / (group.width - group.geometry.padding.horizontal);
case _:
width / (group.width - group.geometry.padding.horizontal);
case _: 1;
}
switch group.overflow.y {
group.overflowX = ox;
var oy = switch group.overflow.y {
case SCROLL:
group.overflowY = height / (group.height - group.geometry.padding.vertical);
case _:
height / (group.height - group.geometry.padding.vertical);
case _: 1;
}
group.overflowY = oy;
}
private function filterViews(group:IGroupView, views:Array<IView<Dynamic>>):Array<IView<Dynamic>> {

View File

@@ -11,17 +11,19 @@ typedef Row = {
class TailLayout extends DefaultLayout {
public var rowSize:Int = 0;
@:style(0) public var rowSize:Null<Int>;
@:style(false) public var stretch:Null<Bool>;
private function placeRow(group:IGroupView, y:Float, row:Row):Void {
var x:Float = (group.width - row.width) / 2;
for (v in row.views) {
v.x = x;
v.y = switch group.layout.vAlign {
var vy = switch group.layout.vAlign {
case TOP | NONE: y;
case MIDDLE: y + (row.height - v.height) / 2;
case BOTTOM: y + (row.height - v.height);
}
v.y = vy;
x += v.width + margin;
}
}
@@ -40,7 +42,7 @@ class TailLayout extends DefaultLayout {
setViewHeight(group, view);
if (
(rowSize > 0 && row.views.length >= rowSize) ||
(/*rowSize == 0 && */row.width + view.width + margin + group.geometry.margin.horizontal > size.width)
(/*rowSize == 0 && */row.width + view.width + margin + group.geometry.margin.horizontal > size.width && !stretch)
) {
row.width -= margin;
w = Math.max(w, row.width);

View File

@@ -180,6 +180,13 @@ class ListView<D> extends GroupView {
item.visible = true;
item.item_index = index;
item.data = filteredData[item.item_index];
if (
selected != null && selected.indexOf(item.data) > -1 ?
item.style.add("selected") :
item.style.remove("selected")
) {
item.style = item.style;
}
}
}
}

View File

@@ -0,0 +1,21 @@
package haxework.view.popup;
import haxework.view.form.LabelView;
import haxework.view.text.TextView;
import promhx.Promise;
@:template class AlertView extends PopupView<Dynamic> {
@:view var header:LabelView;
@:view var message:TextView;
public function new() {
super();
}
public static function alert(message:String):Promise<Dynamic> {
var result = new AlertView();
result.message.text = message;
return result.show();
}
}

View File

@@ -0,0 +1,31 @@
---
view:
$type: haxework.view.group.VGroupView
geometry.width: 400
geometry.height: 200
geometry.padding: 10
geometry.hAlign: center
geometry.vAlign: middle
style: frame
views:
- $type: haxework.view.group.HGroupView
geometry.width: 100%
layout.margin: 10
views:
- id: header
$type: haxework.view.form.LabelView
- id: message
$type: haxework.view.form.LabelView
font.align: CENTER
layout.hAlign: center
layout.vAlign: middle
geometry.width: 100%
geometry.height: 100%
- $type: haxework.view.group.HGroupView
geometry.width: 100%
layout.hAlign: center
layout.margin: 10
views:
- $type: haxework.view.form.ButtonView
text: OK
+onPress: ~close('ok')

View File

@@ -0,0 +1,21 @@
package haxework.view.popup;
import haxework.view.form.LabelView;
import haxework.view.text.TextView;
import promhx.Promise;
@:template class ConfirmView extends PopupView<Bool> {
@:view var header:LabelView;
@:view var message:TextView;
public function new() {
super();
}
public static function confirm(message:String):Promise<Bool> {
var result = new ConfirmView();
result.message.text = message;
return result.show();
}
}

View File

@@ -0,0 +1,34 @@
---
view:
$type: haxework.view.group.VGroupView
geometry.width: 400
geometry.height: 200
geometry.padding: 10
geometry.hAlign: center
geometry.vAlign: middle
style: frame
views:
- $type: haxework.view.group.HGroupView
geometry.width: 100%
layout.margin: 10
views:
- id: header
$type: haxework.view.form.LabelView
- id: message
$type: haxework.view.form.LabelView
font.align: CENTER
layout.hAlign: center
layout.vAlign: middle
geometry.width: 100%
geometry.height: 100%
- $type: haxework.view.group.HGroupView
geometry.width: 100%
layout.hAlign: center
layout.margin: 10
views:
- $type: haxework.view.form.ButtonView
text: Yes
+onPress: ~close(true)
- $type: haxework.view.form.ButtonView
text: No
+onPress: ~reject('no')

View File

@@ -5,7 +5,7 @@ import haxework.animate.IAnimate;
typedef P = PopupView<Dynamic>;
class PopupManager {
@:provide class PopupManager {
public var showAnimateFactory(default, default):IView<Dynamic> -> IAnimate;
public var closeAnimateFactory(default, default):IView<Dynamic> -> IAnimate;
@@ -38,6 +38,7 @@ class PopupManager {
public function remove(popup:P):Void {
if (root.containsView(popup)) {
root.removeView(popup);
root.focus();
}
}

View File

@@ -56,20 +56,22 @@ class PopupView<R> extends GroupView {
}
public function close(result:R):Void {
var d = deferred;
deferred = null;
manager.close(this);
onClose();
if (deferred != null) {
deferred.resolve(result);
deferred = null;
if (d != null) {
d.resolve(result);
}
}
public function reject(reason:Dynamic):Void {
manager.close(this);
if (deferred != null) {
//deferred.throwError(reason);
deferred.resolve(null);
var d = deferred;
deferred = null;
manager.close(this);
if (d != null) {
//d.throwError(reason);
d.resolve(null);
}
}
}

View File

@@ -14,10 +14,10 @@ using haxework.color.ColorUtil;
@:style(0xffffff) public var color(default, default):Null<Color>;
@:style(null) public var borderColor(default, default):Null<Color>;
public var round(default, default):Float;
@:style(15) public var round(default, default):Null<Float>;
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) {
this.color = color;
this.borderColor = borderColor;
this.round = round;

View File

@@ -6,10 +6,12 @@ import flash.display.Graphics;
@:style public var border(default, default):Border;
@:style public var background(default, default):Background;
@:style(null) public var round(default, default):Null<Float>;
public function new(?background:Background, ?border:Border) {
public function new(?background:Background, ?border:Border, ?round:Float) {
this.background = background != null ? background : new Background();
this.border = border != null ? border : new Border();
this.round = round;
}
public function draw(view:SpriteView):Void {
@@ -24,7 +26,11 @@ import flash.display.Graphics;
graphics.beginFill(0, 0);
}
var o = border.color != null ? border.thickness / 2 : 0;
if (round != null) {
graphics.drawRoundRect(o, o, view.width - o * 2, view.height - o * 2, round, round);
} else {
graphics.drawRect(o, o, view.width - o * 2, view.height - o * 2);
}
graphics.lineStyle();
graphics.endFill();
}

View File

@@ -23,7 +23,9 @@ import haxework.view.list.ScrollBarView;
graphics.drawRect(0, 0, view.width, view.height);
graphics.beginFill(foreColor);
graphics.lineStyle();
if (!Math.isNaN(position) && !Math.isNaN(size)) {
graphics.drawRect(0, position, view.width, size);
}
graphics.endFill();
}
}

View File

@@ -6,6 +6,27 @@ abstract StyleId(Array<String>) {
this = value != null ? value : [];
}
public function add(value:String):Bool {
if (this.indexOf(value) == -1) {
this.push(value);
return true;
}
return false;
}
public inline function remove(value:String):Bool {
return this.remove(value);
}
public function match(value:StyleId):Bool {
for (v in value.toArray()) {
if (this.indexOf(v) == -1) {
return false;
}
}
return true;
}
@:to public inline function toArray():Array<String> {
return this;
}

View File

@@ -1,13 +1,13 @@
package haxework.view.theme;
import haxework.view.geometry.VAlign;
import haxework.view.geometry.HAlign;
import flash.text.Font;
import flash.text.FontType;
import haxework.color.Color;
import haxework.signal.Signal;
import haxework.view.geometry.Box;
import haxework.view.geometry.HAlign;
import haxework.view.geometry.SizeValue;
import haxework.view.geometry.VAlign;
import haxework.view.skin.TabColorSkin;
import haxework.view.theme.ITheme;
@@ -25,19 +25,68 @@ class Style {
}
}
class StyleBundle {
private var data:Map<String, Map<String, Dynamic>>;
private var parentMap:Map<String, String>;
public function new() {
data = new Map();
parentMap = new Map();
}
public function register(style:Style):Void {
for (key in style.data.keys()) {
if (!data.exists(key)) {
data.set(key, new Map());
}
data.get(key).set(style.id, style.data.get(key));
}
if (style.parent != null) {
parentMap.set(style.id, style.parent);
}
}
public function get(key:String, id:StyleId):Null<Dynamic> {
var result = null;
if (data.exists(key)) {
var bundle:Map<String, Dynamic> = data.get(key);
var length = 0;
for (key in bundle.keys()) {
if (id.match(key) && key.length > length) {
result = bundle.get(key);
length = key.length;
}
}
}
if (result == null) {
if (parentMap.exists(id)) {
var parentId:StyleId = parentMap.get(id);
for (pId in parentId.toArray()) {
result = get(key, pId);
if (result != null) {
break;
}
}
}
}
return result;
}
}
class Theme implements ITheme {
public var font(default, set):ThemeFont;
public var fontSize(default, set):ThemeFontSize;
public var colors(default, set):ThemeColors;
public var updateSignal(default, null):Signal0;
private var data:Map<String, Style>;
private var cache:Map<String, Dynamic>;
private var bundle:StyleBundle;
public function new(?font:ThemeFont, ?colors:ThemeColors, ?fontSize:ThemeFontSize) {
updateSignal = new Signal0();
data = new Map();
cache = new Map();
bundle = new StyleBundle();
this.font = font;
this.colors = colors;
this.fontSize = fontSize;
@@ -79,7 +128,7 @@ class Theme implements ITheme {
}
private function register(style:Style):Void {
data.set(style.id, style);
bundle.register(style);
}
private function reload():Void {
@@ -104,6 +153,12 @@ class Theme implements ITheme {
register(new Style("text1", [
"skin.background.color" => colors.light.diff(16),
], ["text"]));
register(new Style("text0.selected", [
"font.color" => colors.active,
], ["text0"]));
register(new Style("text1.selected", [
"font.color" => colors.active,
], ["text1"]));
register(new Style("label", [
"geometry.padding" => Box.fromArray([8, 2]),
], ["text"]));
@@ -142,20 +197,8 @@ class Theme implements ITheme {
]));
}
private function _resolve<T>(key:String, style:Style):Null<T> {
if (style == null) {
return null;
} else if (style.data.exists(key)) {
return style.data.get(key);
} else if (style.parent != null) {
for (s in style.parent.toArray()) {
var result = _resolve(key, data.get(s));
if (result != null) {
return result;
}
}
}
return null;
private function _resolve<T>(key:String, style:StyleId):Null<T> {
return bundle.get(key, style);
}
public function resolve<T>(key:String, style:StyleId):T {
@@ -165,7 +208,7 @@ class Theme implements ITheme {
if (cache.exists(k)) {
result = cache.get(k);
} else {
result = _resolve(key, data.get(style));
result = _resolve(key, style);
cache.set(k, result);
}
}