11 Commits

184 changed files with 1634 additions and 696 deletions

3
.gitignore vendored
View File

@@ -5,4 +5,5 @@
out/
target/
*.zip
pack.sh
pack.sh
.vscode/

View File

@@ -1,46 +1,45 @@
# haxework
# HaxeWork
Gui framework for Haxe.
HaXe framework.
## View
`haxework.gui` provides views classes.
`hw.view` provides views classes.
### Example
Build form using macro @:template.
form.json:
form.yaml:
```json
{
"$type": "haxework.gui.VGroupView",
"skin": [{"$type": "haxework.gui.skin.ColorSkin", "color": "0xffff00"}],
"geometry.padding": 20,
"layout.margin": 10,
"views":[
{
"id": "view1",
"type":"haxework.gui.SpriteView",
"geometry.size.stretch": true,
"skin":[{"$type":"haxework.gui.skin.ColorSkin", "color": "0xff0000"}]
},
{
"id": "view2",
"type": "haxework.gui.SpriteView",
"geometry.size.width": "100%",
"geometry.size.height": 50,
"skin": [{"$type":"haxework.gui.skin.ColorSkin", "color": "0x00ff00"}]
}
]
}
```yaml
---
skin:
- $type: hw.gui.skin.ColorSkin
color: 0xffff00
geometry.padding: 20
layout.margin: 10
views:
- id: view1
type: hw.view.SpriteView
geometry.size.stretch: true
skin:
- $type: hw.view.skin.ColorSkin
color: 0xff0000
- id: view2
type: hw.view.SpriteView
geometry.size.width: 100%
geometry.size.height: 50
skin:
- "$type": hw.view.skin.ColorSkin
color: 0x00ff00
```
```haxe
@:template("form.json")
@:template("form.yaml")
class FormView extends VGroupView {
@:view public var view1:SpriteView;
@:view("view2") public var anyVarName:SpriteView;
@:view("view2") public var anyVarName:SpriteView;
}
var form = new FormView();
@@ -51,7 +50,7 @@ trace(form.anyVarName);
## Loader
`haxework.net` provides loaders classes.
`hw.net` provides loaders classes.
### Example

1
build.hxml Normal file
View File

@@ -0,0 +1 @@
-p src/main

View File

@@ -3,7 +3,7 @@
-lib yaml
-lib promhx
-lib haxework
--macro haxework.parser.Parser.auto()
--macro hw.parser.Parser.auto()
-debug
-D native_trace
#-D dev_layout

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<project>
<meta title="Demo" package="haxework.demo" version="1.0.0" company="MegaLoMania"/>
<meta title="Demo" package="hw.demo" version="1.0.0" company="MegaLoMania"/>
<app main="demo.Demo" path="target" file="demo"/>
<icon path="src/haxe-logo.png"/>
@@ -14,7 +14,7 @@
<!--<haxelib name="promhx" version=""/>-->
<haxelib name="haxework" version="git"/>
<!--<haxeflag name="&#45;&#45;macro" value="haxework.parser.Parser.auto()"/>-->
<!--<haxeflag name="&#45;&#45;macro" value="hw.parser.Parser.auto()"/>-->
<haxeflag name="--macro" value="CompilationOption.set('build','xxx')"/>
<window fps="30"/>

View File

@@ -1,10 +1,10 @@
package demo;
import haxework.view.geometry.Box;
import haxework.color.Color;
import haxework.view.theme.Theme;
import hw.view.geometry.Box;
import hw.color.Color;
import hw.view.theme.Theme;
using haxework.color.ColorUtil;
using hw.color.ColorUtil;
class AppTheme extends Theme {

View File

@@ -1,18 +1,17 @@
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;
import haxework.App;
import haxework.log.TraceLogger;
import haxework.net.JsonLoader;
import haxework.view.data.ButtonGroup;
import haxework.view.frame.FrameSwitcher;
import haxework.view.frame.FrameView;
import haxework.view.group.VGroupView;
import demo.storage.TestStorage;
import hw.app.App;
import hw.log.TraceLogger;
import hw.net.JsonLoader;
import hw.resources.IResources;
import hw.view.data.ButtonGroup;
import hw.view.frame.FrameSwitcher;
import hw.view.frame.FrameView;
import hw.view.group.VGroupView;
@:template class DemoView extends VGroupView {
@:view var switcher:FrameSwitcher;
@@ -46,16 +45,16 @@ 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());
resources.image.put("logo", HaxeLogo.resolve());
var app = new Demo(new AppTheme(), resources.image.get("logo"));
app.start(new DemoView());
App.resources.image.put("logo", HaxeLogo.resolve());
var app = new Demo();
app.theme = new AppTheme();
app.icon = App.resources.image.get("logo");
app.view = new DemoView();
trace(storage);
storage.write("test", "value");
@@ -73,8 +72,8 @@ class Demo extends App implements DemoListener {
new JsonLoader().GET("https://embed.tvbit.co/channel/data2/renova.json")
.then(function(data:Array<Model>) {
resources.any.put("data", data);
resources.any.put("data50", Util.marray(data, 50));
App.resources.any.put("data", data);
App.resources.any.put("data50", Util.marray(data, 50));
})
.catchError(function(error) trace(error));
}

View File

@@ -1,11 +1,11 @@
---
style: background
views:
- $type: haxework.view.ImageView
- $type: hw.view.ImageView
geometry.padding: 10
image: $r:image:logo
- id: tabs
$type: haxework.view.data.ButtonGroup<String>
$type: hw.view.data.ButtonGroup<String>
layout.margin: 5
layout.hAlign: left
geometry.width: 100%
@@ -20,8 +20,8 @@ views:
- "test_layout"
- "select"
- id: switcher
$type: haxework.view.frame.FrameSwitcher
animateFactory: { $class: haxework.animate.SlideAnimate }
$type: hw.view.frame.FrameSwitcher
animateFactory: { $class: hw.animate.SlideAnimate }
+onSwitch: ~onFrameSwitch
geometry.stretch: true
geometry.padding: 5
@@ -31,24 +31,24 @@ views:
_data_: {$class: demo.form.DataForm}
_test_layout_: {$class: demo.form.TestLayoutForm}
_select_: {$class: demo.form.SelectForm}
- $type: haxework.view.group.HGroupView
- $type: hw.view.group.HGroupView
geometry.width: 100%
geometry.padding: 10
layout.margin: 10
views:
- $type: haxework.view.form.ButtonView
- $type: hw.view.form.ButtonView
text: Color
+onPress: ~choiceColor()
- $type: haxework.view.form.ButtonView
- $type: hw.view.form.ButtonView
text: Font
+onPress: ~choiceFont()
# separator
- $type: haxework.view.SpriteView
- $type: hw.view.SpriteView
geometry.stretch: true
- $type: haxework.view.form.ButtonView
- $type: hw.view.form.ButtonView
text: OK
- $type: haxework.view.form.ButtonView
- $type: hw.view.form.ButtonView
text: Apply
- $type: haxework.view.form.ButtonView
- $type: hw.view.form.ButtonView
text: Cancel
+onPress: ~flash.system.System.exit(0)

View File

@@ -1,8 +1,8 @@
package demo;
import demo.test.TestView;
import haxework.view.Root;
import haxework.view.SpriteView;
import hw.view.Root;
import hw.view.SpriteView;
class Test {
public static function main():Void {

View File

@@ -1,6 +1,6 @@
package demo.dispatch;
import haxework.App;
import hw.app.App;
interface DemoListener {
public function onTest1():Void;

View File

@@ -1,7 +1,7 @@
package demo.form;
import haxework.view.frame.FrameView;
import haxework.view.text.TextView;
import hw.view.frame.FrameView;
import hw.view.text.TextView;
@:template class DataForm extends FrameView<Dynamic> {
public function new() {

View File

@@ -2,9 +2,9 @@
overflow.y: scroll
views:
- id: data
$type: haxework.view.data.DataView
$type: hw.view.data.DataView
layout:
$type: haxework.view.layout.VerticalLayout
$type: hw.view.layout.VerticalLayout
factory: ~factory
geometry.width: 100%
data: $r:any:data

View File

@@ -1,9 +1,9 @@
package demo.form;
import haxework.view.frame.FrameView;
import haxework.view.list.LabelListItem;
import haxework.view.list.ListView.IListItemView;
import haxework.view.list.VListView;
import hw.view.frame.FrameView;
import hw.view.list.LabelListItem;
import hw.view.list.ListView.IListItemView;
import hw.view.list.VListView;
@:template class ListForm extends FrameView<Dynamic> {
@:view public var list(default, null):VListView<Model>;

View File

@@ -1,10 +1,10 @@
---
views:
- id: list
$type: haxework.view.list.VListView
$type: hw.view.list.VListView
+onItemSelect: ~onItemSelect
factory: ~factory
geometry.stretch: true
scroll:
$type: haxework.view.list.VScrollBarView
$type: hw.view.list.VScrollBarView
data: $r:any:data50

View File

@@ -1,6 +1,6 @@
package demo.form;
import haxework.view.frame.FrameView;
import hw.view.frame.FrameView;
@:template class SelectForm extends FrameView<Dynamic> {
public function new() {

View File

@@ -2,7 +2,7 @@
geometry.padding: 10
layout.margin: 5
views:
- $type: haxework.view.form.SelectView<String>
- $type: hw.view.form.SelectView<String>
layout.margin: 2
dataView.layout.margin: 1
data:
@@ -13,7 +13,7 @@ views:
selected: "value 1"
+onSelect: ~function(value) trace('select', value)
- $type: haxework.view.form.SelectView.SelectIdView<{id:Int,label:String}, Int>
- $type: hw.view.form.SelectView.SelectIdView<{id:Int,label:String}, Int>
layout.margin: 2
dataView.layout.margin: 1
labelBuilder: |

View File

@@ -1,10 +1,10 @@
package demo.form;
import haxework.view.frame.FrameView;
import haxework.view.ImageView;
import haxework.view.IView;
import haxework.view.text.TextView;
import haxework.view.utils.DrawUtil;
import hw.view.frame.FrameView;
import hw.view.ImageView;
import hw.view.IView;
import hw.view.text.TextView;
import hw.view.utils.DrawUtil;
@:template class TailForm extends FrameView<Dynamic> {

View File

@@ -2,10 +2,10 @@
overflow.y: scroll
views:
- id: data
$type: haxework.view.data.DataView
$type: hw.view.data.DataView
geometry.padding: 4
layout:
$type: haxework.view.layout.TailLayout
$type: hw.view.layout.TailLayout
margin: 6
factory: ~factory
geometry.width: 100%

View File

@@ -1,8 +1,8 @@
package demo.form;
import flash.events.MouseEvent;
import haxework.view.frame.FrameView;
import haxework.view.SpriteView;
import hw.view.frame.FrameView;
import hw.view.SpriteView;
@:template class TestLayoutForm extends FrameView<Dynamic> {

View File

@@ -1,52 +1,52 @@
---
views:
- id: main
$type: haxework.view.group.VGroupView
$type: hw.view.group.VGroupView
geometry.stretch: true
layout.hAlign: center
layout.vAlign: middle
views:
- id: container
$type: haxework.view.group.VGroupView
$type: hw.view.group.VGroupView
layout.margin: 10
skin:
$type: [haxework.view.skin.Skin.color, 0xffff00]
$type: [hw.view.skin.Skin.color, 0xffff00]
views:
- id: top
$type: haxework.view.group.GroupView
$type: hw.view.group.GroupView
layout.hAlign: center
geometry.width: 100%
geometry.height: 20
style: test
- id: middle
$type: haxework.view.group.HGroupView
$type: hw.view.group.HGroupView
layout.margin: 10
views:
- id: left
$type: haxework.view.group.GroupView
$type: hw.view.group.GroupView
layout.vAlign: middle
geometry.width: 20
geometry.height: 100%
style: test
- id: render
$type: haxework.view.SpriteView
$type: hw.view.SpriteView
#geometry.width: 300
#geometry.height: 200
style: test
- id: right
$type: haxework.view.group.GroupView
$type: hw.view.group.GroupView
layout.vAlign: middle
geometry.width: 20
geometry.height: 100%
style: test
views:
- $type: haxework.view.SpriteView
- $type: hw.view.SpriteView
geometry.width: 100
geometry.height: 100%
skin:
$type: [haxework.view.skin.Skin.color, 0xff0000]
$type: [hw.view.skin.Skin.color, 0xff0000]
- id: bottom
$type: haxework.view.group.GroupView
$type: hw.view.group.GroupView
layout.hAlign: center
style: test
geometry.width: 100%

View File

@@ -1,8 +1,8 @@
package demo.popup;
import haxework.view.form.ButtonView;
import haxework.view.popup.PopupView;
import haxework.view.skin.Skin;
import hw.view.form.ButtonView;
import hw.view.popup.PopupView;
import hw.view.skin.Skin;
@:template class ColorPopup extends PopupView<Null<Int>> {

View File

@@ -1,6 +1,6 @@
---
view:
$type: haxework.view.group.VGroupView
$type: hw.view.group.VGroupView
geometry.width: 400
geometry.height: 200
geometry.padding: 10
@@ -9,10 +9,10 @@ view:
style: frame
views:
- id: colors
$type: haxework.view.data.DataView
$type: hw.view.data.DataView
geometry.stretch: true
layout:
$type: haxework.view.layout.TailLayout
$type: hw.view.layout.TailLayout
vAlign: middle
margin: 5
factory: ~colorViewFactory
@@ -23,11 +23,11 @@ view:
- 0xCC33AA
- 0x3333AA
+onDataSelect: ~close
- $type: haxework.view.group.HGroupView
- $type: hw.view.group.HGroupView
geometry.width: 100%
layout.hAlign: right
layout.margin: 10
views:
- $type: haxework.view.form.ButtonView
- $type: hw.view.form.ButtonView
text: Cancel
+onPress: ~reject('cancel')

View File

@@ -2,10 +2,10 @@ package demo.popup;
import flash.text.Font;
import flash.text.FontType;
import haxework.view.list.LabelListItem;
import haxework.view.list.ListView;
import haxework.view.popup.PopupView;
import haxework.view.theme.ITheme;
import hw.view.list.LabelListItem;
import hw.view.list.ListView;
import hw.view.popup.PopupView;
import hw.view.theme.ITheme;
class FontLabelView extends LabelListItem<ThemeFont> {

View File

@@ -1,6 +1,6 @@
---
view:
$type: haxework.view.group.VGroupView
$type: hw.view.group.VGroupView
geometry.width: 400
geometry.height: 80%
geometry.padding: 10
@@ -9,17 +9,17 @@ view:
style: frame
views:
- id: fonts
$type: haxework.view.list.VListView
$type: hw.view.list.VListView
geometry.stretch: true
factory: ~fontViewFactory
+onItemSelect: ~function(item) close(item.data)
scroll:
$type: haxework.view.list.VScrollBarView
- $type: haxework.view.group.HGroupView
$type: hw.view.list.VScrollBarView
- $type: hw.view.group.HGroupView
geometry.width: 100%
geometry.margin.top: 10
layout.hAlign: right
views:
- $type: haxework.view.form.ButtonView
- $type: hw.view.form.ButtonView
text: Cancel
+onPress: ~reject('cancel')

View File

@@ -1,6 +1,6 @@
package demo.storage;
import haxework.storage.SharedObjectStorage;
import hw.storage.SharedObjectStorage;
@:provide class TestStorage extends SharedObjectStorage {

View File

@@ -1,6 +1,6 @@
package demo.test;
import haxework.view.group.GroupView;
import hw.view.group.GroupView;
@:template class TestView extends GroupView {

View File

@@ -1,61 +1,61 @@
---
geometry.padding: 10
views:
- $type: haxework.view.group.HGroupView
- $type: hw.view.group.HGroupView
geometry.padding: 10
geometry.width: 100%
layout.margin: 10
layout.vAlign: middle
skin:
$type: haxework.view.skin.SpriteSkin
$type: hw.view.skin.SpriteSkin
background.color: 0xffff00
background.alpha: 1
views:
- $type: haxework.view.SpriteView
- $type: hw.view.SpriteView
geometry.width: 100
geometry.height: 100
skin:
$type: haxework.view.skin.SpriteSkin
$type: hw.view.skin.SpriteSkin
background.color: 0xff0000
background.alpha: 1
- $type: haxework.view.group.VGroupView
- $type: hw.view.group.VGroupView
geometry.padding: 10
layout.margin: 10
skin:
$type: haxework.view.skin.SpriteSkin
$type: hw.view.skin.SpriteSkin
background.color: 0x00ffff
background.alpha: 1
views:
- $type: haxework.view.SpriteView
- $type: hw.view.SpriteView
geometry.width: 100
geometry.height: 100
size:
_test_: [200, 200]
skin:
$type: haxework.view.skin.SpriteSkin
$type: hw.view.skin.SpriteSkin
background.color: 0xff0000
background.alpha: 1
- $type: haxework.view.SpriteView
- $type: hw.view.SpriteView
geometry.width: 100
geometry.height: 100
skin:
$type: haxework.view.skin.SpriteSkin
$type: hw.view.skin.SpriteSkin
background.color: 0xff0000
background.alpha: 1
- $type: haxework.view.text.TextView
- $type: hw.view.text.TextView
geometry.padding: 20
text: "Azazaza"
- $type: haxework.view.SpriteView
- $type: hw.view.SpriteView
geometry.width: 60%
geometry.height: 100%
skin:
$type: haxework.view.skin.SpriteSkin
$type: hw.view.skin.SpriteSkin
background.color: 0xff0000
background.alpha: 1
- $type: haxework.view.SpriteView
- $type: hw.view.SpriteView
geometry.width: 40%
geometry.height: 80%
skin:
$type: haxework.view.skin.SpriteSkin
$type: hw.view.skin.SpriteSkin
background.color: 0xff0000
background.alpha: 1

View File

@@ -1 +1 @@
--macro haxework.parser.Parser.auto()
--macro hw.parser.Parser.auto()

View File

@@ -2,20 +2,16 @@
"name": "haxework",
"url": "https://bitbucket.org/shmyga/haxework",
"license": "MIT",
"tags": [
"view",
"layout",
"template"
],
"tags": ["view", "layout", "template"],
"description": "View framework.",
"version": "1.3.0",
"version": "2.1.0",
"releasenote": "Update.",
"contributors": [
"shmyga"
],
"contributors": ["shmyga"],
"classPath": "src/main",
"dependencies": {
"promhx": "1.1.0",
"yaml": "2.0.0"
"protohx": "0.4.6",
"haxe-crypto": "0.0.8",
"yaml": "2.0.1"
}
}

View File

@@ -1,6 +1,6 @@
package;
import haxework.log.ILogger;
import hw.log.ILogger;
class L {
@@ -25,4 +25,4 @@ class L {
public static function e(tag:String, message:String, ?error:Dynamic, ?p:haxe.PosInfos):Void {
for (logger in loggers) logger.e(tag, message, error, p);
}
}
}

View File

@@ -1,35 +0,0 @@
package haxework;
import flash.display.BitmapData;
import flash.Lib;
import haxework.animate.Animate;
import haxework.animate.FadeAnimate;
import haxework.animate.UnFadeAnimate;
import haxework.view.IView;
import haxework.view.popup.PopupManager;
import haxework.view.Root;
import haxework.view.theme.ITheme;
class App {
@:provide var app:App;
@:provide var theme:ITheme;
@:provide var popupManager:PopupManager;
public function new(?theme:ITheme, ?icon:BitmapData) {
this.theme = theme;
#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;
}
public function start(view:IView<Dynamic>) {
Animate.bind(Lib.current.stage);
Root.bind(view);
}
}

View File

@@ -1,64 +0,0 @@
package haxework.animate;
import flash.display.DisplayObject;
import flash.display.Stage;
import flash.events.Event;
import haxework.view.IView;
class Animate implements IAnimate {
public static var defaultDuraion = 300;
private static var running:Array<IAnimate> = new Array<IAnimate>();
public static function bind(stage:Stage):Void {
stage.addEventListener(Event.ENTER_FRAME, function(_) {
Animate.updateAll();
});
}
public static function updateAll():Void {
if (running.length > 0) {
var time = Date.now().getTime();
for (animate in running) animate.update(time);
}
}
private var callback:Animate -> Void;
private var view:IView<Dynamic>;
private var duration:Int;
private var startTime:Float;
private var progress:Float;
private var object(get, null):DisplayObject;
public function new(view:IView<Dynamic>, duration:Int = -1) {
this.view = view;
this.duration = duration > -1 ? duration : defaultDuraion;
}
private inline function get_object():DisplayObject {
return cast view.content;
}
public function start(callback:IAnimate -> Void, custom:Bool = false):Void {
startTime = Date.now().getTime();
this.callback = callback;
if (!custom) running.push(this);
update(startTime);
}
private function update(time:Float):Void {
progress = (time - startTime) / duration;
if (progress >= 1) {
running.remove(this);
if (callback != null) {
callback(this);
callback = null;
}
}
}
public function cancel():Void {
if (!Math.isNaN(startTime)) update(startTime + duration);
}
}

View File

@@ -1,20 +0,0 @@
package haxework.animate;
import haxework.animate.Animate;
import haxework.animate.IAnimate;
class FadeAnimate extends Animate {
override public function start(callback:IAnimate -> Void, custom:Bool = false):Void {
object.alpha = 1.0;
super.start(callback, custom);
}
override private function update(time:Float):Void {
super.update(time);
object.alpha = 1 - (progress * 1.0);
if (progress >= 1) {
object.alpha = 0.0;
}
}
}

View File

@@ -1,10 +0,0 @@
package haxework.animate;
interface IAnimate {
public function start(callback:IAnimate -> Void, custom:Bool = false):Void;
public function cancel():Void;
private function update(time:Float):Void;
}

View File

@@ -1,14 +0,0 @@
package haxework.animate;
class SlideAnimate extends Animate {
override public function start(callback:IAnimate -> Void, custom:Bool = false):Void {
object.x = view.x - this.view.width + this.view.width / progress;
super.start(callback, custom);
}
override private function update(time:Float):Void {
super.update(time);
object.x = view.x - this.view.width + this.view.width / Math.min(1, progress);
}
}

View File

@@ -1,19 +0,0 @@
package haxework.animate;
import haxework.animate.Animate;
class UnFadeAnimate extends Animate {
override public function start(callback:IAnimate -> Void, custom:Bool = false):Void {
object.alpha = 0.0;
super.start(callback, custom);
}
override private function update(time:Float):Void {
super.update(time);
object.alpha = progress * 1.0;
if (progress >= 1) {
object.alpha = 1.0;
}
}
}

60
src/main/hw/Timer.hx Normal file
View File

@@ -0,0 +1,60 @@
package hw;
#if cpp
import haxe.Log;
import haxe.PosInfos;
import cpp.vm.Thread;
class Timer {
private var sleep:Float;
private var stopped:Bool;
public function new(time_ms:Int) {
this.sleep = time_ms / 1000.0;
this.stopped = false;
Thread.create(function() {
while (!stopped) {
Sys.sleep(sleep);
try {
run();
} catch (error:Dynamic) {
trace(hw.log.BaseLogger.LoggerUtil.printError(error));
}
}
});
}
public function stop() {
stopped = true;
}
public dynamic function run() {}
public static function delay(f:Void -> Void, time_ms:Int) {
var t = new Timer(time_ms);
t.run = function() {
t.stop();
f();
};
return t;
}
public static function measure<T>(f:Void -> T, ?pos:PosInfos):T {
var t0 = stamp();
var r = f();
Log.trace((stamp() - t0) + "s", pos);
return r;
}
public static inline function stamp():Float {
return Sys.time();
}
}
#else
typedef Timer = haxe.Timer;
#end

View File

@@ -0,0 +1,51 @@
package hw.animate;
import flash.display.DisplayObject;
import hw.view.IView;
import promhx.Deferred;
import promhx.Promise;
class Animate implements IAnimate {
public static var defaultDuraion = 300;
@:provide private static var runner:AnimateRunner;
private var view:IView<Dynamic>;
private var duration:Int;
private var startTime:Float;
private var progress:Float;
private var object(get, null):DisplayObject;
private var deferred:Deferred<IAnimate>;
public function new(view:IView<Dynamic>, duration:Int = -1) {
this.view = view;
this.duration = duration > -1 ? duration : defaultDuraion;
this.startTime = 0;
}
private inline function get_object():DisplayObject {
return cast view.content;
}
public function start():Promise<IAnimate> {
startTime = Date.now().getTime();
deferred = new Deferred();
runner.push(this);
this.update(startTime);
return deferred.promise();
}
public function update(time:Float):Bool {
progress = (time - startTime) / duration;
if (progress >= 1) {
deferred.resolve(this);
return false;
}
return true;
}
public function cancel():Void {
progress = startTime + duration;
}
}

View File

@@ -0,0 +1,25 @@
package hw.animate;
import flash.events.Event;
import flash.Lib;
@:provide class AnimateRunner {
private var animates:Array<IAnimate>;
public function new() {
animates = [];
Lib.current.stage.addEventListener(Event.ENTER_FRAME, _ -> update());
}
private function update():Void {
if (animates.length > 0) {
var time = Date.now().getTime();
animates = animates.filter(animate -> animate.update(time));
}
}
public function push(animate:IAnimate):Void {
animates.push(animate);
}
}

View File

@@ -1,10 +1,11 @@
package haxework.animate;
package hw.animate;
import flash.display.DisplayObject;
import flash.display.Sprite;
import haxework.animate.Animate;
import haxework.animate.IAnimate;
import haxework.view.IView;
import hw.animate.Animate;
import hw.animate.IAnimate;
import hw.view.IView;
import promhx.Promise;
class CircleMaskAnimate extends Animate {
@@ -19,7 +20,7 @@ class CircleMaskAnimate extends Animate {
this.cyrcle = new Sprite();
}
override public function start(callback:IAnimate -> Void, custom:Bool = false):Void {
override public function start():Promise<IAnimate> {
var width = view.parent.width;
var height = view.parent.height;
size = Math.sqrt(width * width + height * height);
@@ -33,7 +34,7 @@ class CircleMaskAnimate extends Animate {
view.content.mask = mask;
view.parent.container.addChild(cyrcle);
super.start(callback, custom);
return super.start();
}
private function redraw(size:Float, r:Float):Void {
@@ -48,15 +49,14 @@ class CircleMaskAnimate extends Animate {
cyrcle.graphics.lineStyle();
}
override private function update(time:Float):Void {
super.update(time);
override public function update(time:Float):Bool {
var result = super.update(time);
redraw(size, size * progress);
if (progress >= 1 && view.content.parent != null) {
if (view.content.parent.contains(mask)) view.content.parent.removeChild(mask);
view.content.mask = null;
if (view.content.parent.contains(cyrcle)) view.parent.container.removeChild(cyrcle);
}
return result;
}
}

View File

@@ -0,0 +1,22 @@
package hw.animate;
import hw.animate.Animate;
import hw.animate.IAnimate;
import promhx.Promise;
class FadeAnimate extends Animate {
override public function start():Promise<IAnimate> {
object.alpha = 1.0;
return super.start();
}
override public function update(time:Float):Bool {
var result = super.update(time);
object.alpha = 1 - (progress * 1.0);
if (progress >= 1) {
object.alpha = 0.0;
}
return result;
}
}

View File

@@ -0,0 +1,12 @@
package hw.animate;
import promhx.Promise;
interface IAnimate {
public function start():Promise<IAnimate>;
public function cancel():Void;
public function update(time:Float):Bool;
}

View File

@@ -0,0 +1,17 @@
package hw.animate;
import promhx.Promise;
class SlideAnimate extends Animate {
override public function start():Promise<IAnimate> {
object.x = view.x - this.view.width + this.view.width / progress;
return super.start();
}
override public function update(time:Float):Bool {
var result = super.update(time);
object.x = view.x - this.view.width + this.view.width / Math.min(1, progress);
return result;
}
}

View File

@@ -0,0 +1,21 @@
package hw.animate;
import hw.animate.Animate;
import promhx.Promise;
class UnFadeAnimate extends Animate {
override public function start():Promise<IAnimate> {
object.alpha = 0.0;
return super.start();
}
override public function update(time:Float):Bool {
var result = super.update(time);
object.alpha = progress * 1.0;
if (progress >= 1) {
object.alpha = 1.0;
}
return result;
}
}

84
src/main/hw/app/App.hx Normal file
View File

@@ -0,0 +1,84 @@
package hw.app;
import flash.display.BitmapData;
import flash.display.StageDisplayState;
import flash.events.FullScreenEvent;
import flash.Lib;
import hw.animate.FadeAnimate;
import hw.animate.IAnimate;
import hw.animate.UnFadeAnimate;
import hw.resources.IResources;
import hw.signal.Signal;
import hw.view.IView;
import hw.view.popup.PopupManager;
import hw.view.Root;
import hw.view.theme.ITheme;
class App {
public var view(default, set):IView<Dynamic>;
private function set_view(value:IView<Dynamic>):IView<Dynamic> {
view = value;
Root.bind(view);
return view;
}
public var icon(default, set):BitmapData;
private function set_icon(value:BitmapData):BitmapData {
icon = value;
#if linux
if (icon != null) {
hw.app.LinuxIcon.value = icon;
}
#end
return icon;
}
public var fullScreenSupport(get, never):Bool;
public function get_fullScreenSupport():Bool {
return Lib.current.stage.allowsFullScreen;
}
public var fullScreen(get, set):Bool;
private function get_fullScreen():Bool {
return Lib.current.stage.displayState != StageDisplayState.NORMAL;
}
private function set_fullScreen(value:Bool):Bool {
Lib.current.stage.displayState = value ? StageDisplayState.FULL_SCREEN : StageDisplayState.NORMAL;
return get_fullScreen();
}
public var fullScreenSignal(default, null):Signal<Bool> = new Signal();
@:provide static var app:App;
@:provide static var resources:IResources;
@:provide static var popupManager:PopupManager;
@:provide public var theme:ITheme;
public function new() {
Lib.current.stage.stageFocusRect = false;
Lib.current.stage.addEventListener(FullScreenEvent.FULL_SCREEN, event -> fullScreenSignal.emit(event.fullScreen));
popupManager.showAnimateFactory = createShowAnimate;
popupManager.closeAnimateFactory = createCloseAnimate;
resources.text.put("app.version", Const.instance.VERSION);
resources.text.put("app.name", Const.instance.NAME);
app = this;
}
private function createShowAnimate(view:IView<Dynamic>):IAnimate {
return new UnFadeAnimate(view);
}
private function createCloseAnimate(view:IView<Dynamic>):IAnimate {
return new FadeAnimate(view);
}
}

22
src/main/hw/app/Const.hx Executable file
View File

@@ -0,0 +1,22 @@
package hw.app;
import flash.Lib;
import flash.system.Capabilities;
@:singleton class Const {
public var FPS(default, null):Int;
public var BUILD(default, null):String;
public var VERSION(default, null):String;
public var NAME(default, null):String;
public var DEBUG(default, null):Bool;
public function new():Void {
BUILD = CompilationOption.get("build");
#if lime
FPS = Std.parseInt(Lib.current.stage.application.meta.get("fps"));
VERSION = Lib.current.stage.application.meta.get("version");
NAME = Lib.current.stage.application.meta.get("name");
#end
DEBUG = Capabilities.isDebugger;
}
}

View File

@@ -1,4 +1,4 @@
package haxework.app;
package hw.app;
import flash.display.BitmapData;
import flash.filters.ColorMatrixFilter;

View File

@@ -1,4 +1,4 @@
package haxework.color;
package hw.color;
abstract Color(Int) {
public var alpha(get, never):Int;

View File

@@ -1,4 +1,4 @@
package haxework.color;
package hw.color;
class ColorUtil {

View File

@@ -0,0 +1,52 @@
package hw.connect;
import haxe.io.Bytes;
import hw.connect.IConnection;
import hw.signal.Signal;
import promhx.Deferred;
import promhx.Promise;
import protohx.Message;
class BaseConnection<O:Message, I:Message> implements IConnection<O, I> {
public var handler(default, null):Signal<ConnectionEvent>;
public var sendHandler(default, null):Signal<O>;
public var receiveHandler(default, null):Signal<I>;
public var connected(default, null):Bool;
public var queue(default, null):PacketQueue<I>;
private var connectDeferred:Deferred<IConnection<O, I>>;
public function new(inputFactory:Class<I>) {
queue = new PacketQueue<I>(inputFactory);
handler = new Signal<ConnectionEvent>();
sendHandler = new Signal<O>();
receiveHandler = new Signal<I>();
}
public function connect():Promise<IConnection<O, I>> {
throw "Not implemented";
}
public function disconnect():Void {
throw "Not implemented";
}
public function pushData(bytes:Bytes):Void {
#if proto_debug L.d('Proto', 'pushData: ${bytes.length}'); #end
queue.addBytes(bytes);
while (queue.hasMsg()) {
var packet:I = queue.popMsg();
receive(packet);
}
}
public function send(packet:O):Void {
#if proto_debug L.d('Proto', 'send: ${packet}'); #end
sendHandler.emit(packet);
}
public function receive(packet:I):Void {
#if proto_debug L.d('Proto', 'receive: ${packet}'); #end
receiveHandler.emit(packet);
}
}

View File

@@ -0,0 +1,16 @@
package hw.connect;
import protohx.Message;
class ConnectionFactory {
public static function buildClientConnection<O:Message, I:Message>(host: String, port:Int, inputFactory:Class<I>):IConnection<O, I> {
#if flash
return new hw.connect.flash.FlashConnection<O, I>(host, port, inputFactory);
#elseif html5
return new hw.connect.js.JsConnection<O, I>(host, port + (hw.connect.js.JsConnection.isSecured() ? 1 : 0), inputFactory);
#else
return new hw.connect.desktop.DesktopConnection<O, I>(host, port, inputFactory);
#end
}
}

View File

@@ -0,0 +1,24 @@
package hw.connect;
import haxe.io.Bytes;
import hw.signal.Signal;
import promhx.Promise;
import protohx.Message;
enum ConnectionEvent {
CONNECTED;
DISCONNECTED;
ERROR(error:Dynamic);
}
interface IConnection<O:Message, I:Message> {
public var connected(default, null):Bool;
public var handler(default, null):Signal<ConnectionEvent>;
public var sendHandler(default, null):Signal<O>;
public var receiveHandler(default, null):Signal<I>;
public function connect():Promise<IConnection<O, I>>;
public function disconnect():Void;
public function send(packet:O):Void;
public function pushData(bytes:Bytes):Void;
}

View File

@@ -0,0 +1,70 @@
package hw.connect;
import haxe.io.Bytes;
import haxe.io.BytesBuffer;
import haxe.io.BytesInput;
import protohx.Message;
class PacketQueue<P:Message> {
public var packetClass(default, null):Class<P>;
private var buffer:BytesBuffer;
private var msgs:List<P>;
public function new(packetClass:Class<P>) {
this.packetClass = packetClass;
msgs = new List<P>();
buffer = new BytesBuffer();
}
public inline function hasMsg():Bool {
return !msgs.isEmpty();
}
public inline function popMsg():P {
return msgs.pop();
}
public inline function addMsg(msg:P):Void {
msgs.add(msg);
}
private function readPackage():Null<P> {
var bytes = buffer.getBytes();
var input = new BytesInput(bytes);
input.bigEndian = false;
if (input.length > 1) {
var packetSize = input.readUInt16();
if (input.length >= packetSize + 2) {
var packet:P = Type.createInstance(packetClass, []);
try {
packet.mergeFrom(input.read(packetSize));
buffer = new BytesBuffer();
buffer.add(input.read(input.length - (packetSize + 2)));
return packet;
} catch (error:Dynamic) {
L.w("PacketQueue", "readPackage ", error);
buffer = new BytesBuffer();
return null;
}
}
}
buffer = new BytesBuffer();
buffer.add(bytes);
return null;
}
public function addBytes(bytes:Bytes):Void {
buffer.add(bytes);
var packet = readPackage();
while (packet != null) {
msgs.add(packet);
packet = readPackage();
}
}
public function clean():Void {
buffer = new BytesBuffer();
}
}

View File

@@ -0,0 +1,29 @@
package hw.connect;
import haxe.io.Bytes;
import haxe.io.BytesOutput;
import protohx.Message;
class PacketUtil {
public static function fromBytes<P:Message>(bytes:Bytes, factory:Class<P>):P {
var packet:P = Type.createInstance(factory, []);
packet.mergeFrom(bytes);
return packet;
}
public static function toBytes<P:Message>(packet:P):Bytes {
var out = new BytesOutput();
packet.writeTo(out);
return out.getBytes();
}
public static function toBytesWithSize<P:Message>(packet:P):Bytes {
var out = new BytesOutput();
out.writeUInt16(0);
packet.writeTo(out);
var bytes = out.getBytes();
bytes.setUInt16(0, bytes.length - 2);
return bytes;
}
}

View File

@@ -0,0 +1,76 @@
package hw.connect.desktop;
import cpp.vm.Thread;
import haxe.Timer;
import hw.connect.IConnection;
import promhx.Deferred;
import promhx.Promise;
import protohx.Message;
import sys.net.Host;
import sys.net.Socket;
class DesktopConnection<O:Message, I:Message> extends BaseConnection<O, I> {
private var host:String;
private var port:Int;
private var socket:Socket;
private var reader:Thread;
public function new(host:String, port:Int, inputFactory:Class<I>) {
super(inputFactory);
this.host = host;
this.port = port;
connected = false;
socket = new Socket();
socket.setFastSend(true);
socket.output.bigEndian = false;
socket.input.bigEndian = false;
sendHandler.connect(_send);
}
override public function connect():Promise<IConnection<O, I>> {
connectDeferred = new Deferred();
try {
if (connected) {
connectDeferred.resolve(this);
} else {
socket.connect(new Host(host), port);
connected = true;
reader = Thread.create(_read);
connectDeferred.resolve(this);
handler.emit(ConnectionEvent.CONNECTED);
}
} catch (error:Dynamic) {
handler.emit(ConnectionEvent.ERROR(error));
Timer.delay(function() connectDeferred.throwError(error), 1);
}
return connectDeferred.promise();
}
override public function disconnect():Void {
socket.close();
connected = false;
handler.emit(DISCONNECTED);
}
private function _read():Void {
try {
while (connected) {
socket.waitForRead();
var size = socket.input.readUInt16();
var data = socket.input.read(size);
var packet:I = PacketUtil.fromBytes(data, queue.packetClass);
receiveHandler.emit(packet);
}
} catch (error:Dynamic) {
handler.emit(ERROR(error));
}
}
private function _send(packet:O):Void {
var bytes = PacketUtil.toBytes(packet);
socket.output.writeUInt16(bytes.length);
socket.output.write(bytes);
socket.output.flush();
}
}

View File

@@ -0,0 +1,18 @@
package hw.connect.fake;
import hw.connect.IConnection;
import promhx.Promise;
import protohx.Message;
class FakeConnection<O:Message, I:Message> extends BaseConnection<O, I> {
override public function connect():Promise<IConnection<O, I>> {
handler.emit(ConnectionEvent.CONNECTED);
var promise:Promise<IConnection<O, I>> = cast Promise.promise(this);
return promise;
}
override public function disconnect():Void {
handler.emit(ConnectionEvent.DISCONNECTED);
}
}

View File

@@ -0,0 +1,89 @@
package hw.connect.flash;
import flash.events.ErrorEvent;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.events.SecurityErrorEvent;
import flash.net.Socket;
import flash.utils.Endian;
import haxe.io.Bytes;
import promhx.Deferred;
import promhx.Promise;
import protohx.Message;
import hw.connect.IConnection;
class FlashConnection<O:Message, I:Message> extends BaseConnection<O, I> {
private var host:String;
private var port:Int;
private var socket:Socket;
public function new(host:String, port:Int, inputFactory:Class<I>) {
super(inputFactory);
this.host = host;
this.port = port;
connected = false;
socket = new Socket();
socket.addEventListener(IOErrorEvent.IO_ERROR, onError);
socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onError);
socket.addEventListener(Event.CLOSE, onClose);
socket.addEventListener(Event.CONNECT, onConnect);
socket.addEventListener(ProgressEvent.SOCKET_DATA, onSocketData);
socket.endian = Endian.LITTLE_ENDIAN;
sendHandler.connect(_send);
}
override public function connect():Promise<IConnection<O, I>> {
socket.connect(host, port);
connectDeferred = new Deferred();
return connectDeferred.promise();
}
override public function disconnect():Void {
if (socket.connected) {
socket.close();
connected = false;
handler.emit(ConnectionEvent.DISCONNECTED);
}
}
private function onError(event:ErrorEvent):Void {
socket.close();
connected = false;
handler.emit(ConnectionEvent.ERROR(event));
if (connectDeferred != null) {
connectDeferred.throwError(event);
connectDeferred = null;
}
}
private function onConnect(_):Void {
connected = true;
handler.emit(ConnectionEvent.CONNECTED);
if (connectDeferred != null) {
connectDeferred.resolve(this);
connectDeferred = null;
}
}
private function onClose(_):Void {
socket.close();
connected = false;
handler.emit(ConnectionEvent.DISCONNECTED);
}
private function onSocketData(_):Void {
var data = new flash.utils.ByteArray();
socket.readBytes(data);
var bytes = Bytes.ofData(data);
pushData(bytes);
}
private function _send(packet:O):Void {
var bytes = PacketUtil.toBytes(packet);
socket.writeShort(bytes.length);
socket.writeBytes(bytes.getData());
socket.flush();
}
}

View File

@@ -0,0 +1,87 @@
package hw.connect.js;
import haxe.io.Bytes;
import hw.connect.IConnection;
import js.Browser;
import js.html.BinaryType;
import js.html.WebSocket;
import promhx.Deferred;
import promhx.Promise;
import protohx.Message;
class JsConnection<O:Message, I:Message> extends BaseConnection<O, I> {
private var host:String;
private var port:Int;
private var socket:WebSocket;
public function new(host:String, port:Int, inputFactory:Class<I>) {
super(inputFactory);
this.host = host;
this.port = port;
connected = false;
}
public static function isSecured():Bool {
return Browser.location.protocol == "https:";
}
private function buildSocket(host:String, port:Int):WebSocket {
var protocol = isSecured() ? "wss:" : "ws:";
return new WebSocket('$protocol//$host:$port');
}
override public function connect():Promise<IConnection<O, I>> {
var self = this;
connectDeferred = new Deferred();
try {
socket = buildSocket(host, port);
socket.binaryType = BinaryType.ARRAYBUFFER;
socket.onopen = this.onConnect;
socket.onclose = this.onClose;
socket.onerror = this.onError;
socket.onmessage = this.onSocketData;
} catch (error:Dynamic) {
connectDeferred.throwError(error);
}
return connectDeferred.promise();
}
override public function disconnect():Void {
socket.close(1000);
connected = false;
}
private function onError(event:Dynamic):Void {
socket.close(1000);
connected = false;
handler.emit(ConnectionEvent.ERROR(event));
}
private function onConnect(_):Void {
connected = true;
handler.emit(ConnectionEvent.CONNECTED);
connectDeferred.resolve(this);
}
private function onClose(_):Void {
socket.close();
connected = false;
handler.emit(ConnectionEvent.DISCONNECTED);
}
private function onSocketData(event:Dynamic):Void {
var bytes = Bytes.ofData(event.data);
pushData(bytes);
}
override public function send(packet:O):Void {
if (connected) {
super.send(packet);
var bytes = PacketUtil.toBytesWithSize(packet);
socket.send(bytes.getData());
} else {
L.w("Connection", "closed");
}
}
}

View File

@@ -0,0 +1,57 @@
package hw.connect.server;
import hw.Timer;
import protohx.Message;
import sys.net.Socket;
class ServerConnection<O:Message, I:Message> extends BaseConnection<O, I> {
public var socket(default, null):Socket;
private var sendQueue:Array<O>;
private var timer:Timer;
public function new(socket:Socket, i:Class<I>) {
super(i);
this.socket = socket;
socket.setFastSend(true);
socket.output.bigEndian = false;
socket.input.bigEndian = false;
sendHandler.connect(pushPacket);
sendQueue = [];
timer = new Timer(1);
timer.run = sendRun;
}
private function sendPacket(packet:O):Void {
try {
var bytes = PacketUtil.toBytes(packet);
socket.output.writeUInt16(bytes.length);
socket.output.write(bytes);
socket.output.flush();
} catch (error:Dynamic) {
L.e('Proto', 'Error send packet: ${packet}', error);
}
}
private function sendRun():Void {
if (sendQueue.length > 0) {
for (packet in sendQueue) {
sendPacket(packet);
}
sendQueue = [];
}
}
private function pushPacket(packet:O):Void {
sendQueue.push(packet);
}
override public function disconnect():Void {
if (timer != null) {
timer.stop();
timer = null;
}
super.disconnect();
}
}

View File

@@ -0,0 +1,155 @@
package hw.connect.server;
import com.hurlant.crypto.hash.SHA1;
import com.hurlant.util.Base64;
import haxe.io.Bytes;
import haxe.io.BytesBuffer;
import protohx.Message;
import sys.net.Socket;
class ServerWSConnection<O:Message, I:Message> extends ServerConnection<O, I> {
private var opened:Bool;
private var buffer:Bytes;
public function new(socket:Socket, i:Class<I>) {
super(socket, i);
opened = false;
}
override private function sendPacket(packet:O):Void {
var bytes = PacketUtil.toBytesWithSize(packet);
writeData(bytes, socket);
}
override public function pushData(bytes:Bytes):Void {
if (!opened) {
var str:String = bytes.getString(0, bytes.length);
if (StringTools.startsWith(str, "GET")) {
var r = ~/Sec-WebSocket-Key:\s*([A-z0-9=+\/]+)/;
r.match(str);
opened = true;
sendServerHandShake(socket, r.matched(1));
}
} else {
var data = parseData(bytes);
if (data != null) {
super.pushData(data);
}
}
}
private function sendServerHandShake(socket:sys.net.Socket, inpKey:String) {
var magicKey = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
var value:String = StringTools.trim(inpKey) + magicKey;
var hash = new SHA1().hash(Bytes.ofString(value));
var outKey = Base64.encodeByteArray(hash);
var s = "HTTP/1.1 101 Switching Protocols\r\n"
+ "Upgrade: websocket\r\n"
+ "Connection: Upgrade\r\n"
+ "Sec-WebSocket-Accept: " + outKey + "\r\n"
+ "\r\n";
socket.output.writeString(s);
}
private function writeData(data:Bytes, socket:sys.net.Socket, isServer = true):Void {
socket.output.writeByte(130);
var len = 0;
if (data.length < 126) len = data.length;
else if (data.length < 65536) len = 126;
else len = 127;
socket.output.writeByte(len | (!isServer ? 0x80 : 0x00));
if (data.length >= 126) {
if (data.length < 65536) {
socket.output.writeByte((data.length >> 8) & 0xFF);
socket.output.writeByte(data.length & 0xFF);
}
else {
socket.output.writeByte((data.length >> 24) & 0xFF);
socket.output.writeByte((data.length >> 16) & 0xFF);
socket.output.writeByte((data.length >> 8) & 0xFF);
socket.output.writeByte(data.length & 0xFF);
}
}
if (isServer) {
socket.output.writeBytes(data, 0, data.length);
}
else {
var mask = [ Std.random(256), Std.random(256), Std.random(256), Std.random(256) ];
socket.output.writeByte(mask[0]);
socket.output.writeByte(mask[1]);
socket.output.writeByte(mask[2]);
socket.output.writeByte(mask[3]);
var maskedData = new BytesBuffer();
for (i in 0...data.length) {
maskedData.addByte(data.get(i) ^ mask[i % 4]);
}
socket.output.writeBytes(maskedData.getBytes(), 0, maskedData.length);
}
}
private function parseData(bytes:Bytes):Bytes {
var p = 0;
var opcode = bytes.get(p++);
if (opcode == 0x00) {
var data = new BytesBuffer();
var b:Int;
while ((b = bytes.get(p++)) != 0xFF) {
data.addByte(b);
}
return data.getBytes();
}
// 130 = binary data
if (opcode == 130) {
var len = bytes.get(p++);
// mask
if (len & 0x80 != 0) {
len &= 0x7F;
if (len == 126) {
var b2 = bytes.get(p++);
var b3 = bytes.get(p++);
len = (b2 << 8) + b3;
}
else if (len == 127) {
var b2 = bytes.get(p++);
var b3 = bytes.get(p++);
var b4 = bytes.get(p++);
var b5 = bytes.get(p++);
len = (b2 << 24) + (b3 << 16) + (b4 << 8) + b5;
}
var mask = [];
mask.push(bytes.get(p++));
mask.push(bytes.get(p++));
mask.push(bytes.get(p++));
mask.push(bytes.get(p++));
var data = new BytesBuffer();
for (i in 0...len) {
data.addByte(bytes.get(p++) ^ mask[i % 4]);
}
return data.getBytes();
} else {
throw "Expected masked data.";
}
}
if (opcode == 136) {
//socket.close();
opened = false;
return null;
} else {
throw "Unsupported websocket opcode: " + opcode;
}
return null;
}
}

View File

@@ -0,0 +1,9 @@
package hw.connect.session;
import haxe.io.Bytes;
interface ISession {
public var id(default, null):Int;
public function pushData(bytes:Bytes):Void;
public function disconnect():Void;
}

View File

@@ -0,0 +1,71 @@
package hw.connect.session;
import haxe.io.Bytes;
import hw.connect.server.ServerConnection;
import hw.connect.server.ServerWSConnection;
import protohx.Message;
import sys.net.Socket;
class ProtoSession<O:Message, I:Message> implements ISession {
private static inline var TAG = "Session";
private static var POLICY_FILE:String = [
"<?xml version=\"1.0\"?>",
"<!DOCTYPE cross-domain-policy SYSTEM \"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd\">",
"<cross-domain-policy>",
"<site-control permitted-cross-domain-policies=\"master-only\"/>",
"<allow-access-from domain=\"*\" to-ports=\"*\"/>",
"</cross-domain-policy>"
].join("\n");
private static var idCounter:Int = 0;
public var id(default, null):Int;
public var connection(default, null):IConnection<O, I>;
private var socket:Socket;
private var request:Class<I>;
public function new(socket:Socket, request:Class<I>) {
this.id = ++idCounter;
this.socket = socket;
this.request = request;
}
private function buildConnection(bytes:Bytes):IConnection<O, I> {
var str:String = bytes.getString(0, bytes.length);
if (str == "<policy-file-request/>" + String.fromCharCode(0)) {
L.d(TAG, "policy-file-request");
socket.output.writeString(POLICY_FILE + String.fromCharCode(0));
socket.output.flush();
return null;
}
if (StringTools.startsWith(str, "GET")) {
connection = new ServerWSConnection<O, I>(socket, request);
} else {
connection = new ServerConnection<O, I>(socket, request);
}
connection.receiveHandler.connect(onRequest);
return connection;
}
public function send(packet:O):Void {
connection.send(packet);
}
public function pushData(bytes:Bytes):Void {
if (connection == null) {
connection = buildConnection(bytes);
}
if (connection != null) {
connection.pushData(bytes);
}
}
public function disconnect():Void {
connection.disconnect();
}
private function onRequest(request:I):Void {
L.d(TAG, 'onRequest: ${request}');
}
}

View File

@@ -1,4 +1,4 @@
package haxework.geom;
package hw.geom;
abstract IntPoint(Array<Int>) {
public var x(get, set):Int;

View File

@@ -1,6 +1,4 @@
package haxework.geom;
import flash.geom.Point as FlashPoint;
package hw.geom;
abstract Point(Array<Float>) {
public var x(get, set):Float;
@@ -33,8 +31,4 @@ abstract Point(Array<Float>) {
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

@@ -1,4 +1,4 @@
package haxework.geom;
package hw.geom;
abstract Rectangle(Array<Float>) {
public var x(get, set):Float;

View File

@@ -1,4 +1,4 @@
package haxework.log;
package hw.log;
import cpp.VarArg;
import haxe.extern.Rest;

View File

@@ -1,6 +1,6 @@
package haxework.log;
package hw.log;
import haxework.log.ILogger.LogLevel;
import hw.log.ILogger.LogLevel;
import haxe.CallStack;
@@ -20,8 +20,17 @@ class LoggerUtil {
}
}
public static function getErrorStack(error:Dynamic):String {
#if flash
if (Std.is(error, flash.errors.Error)) {
return cast(error, flash.errors.Error).getStackTrace();
}
#end
return CallStack.exceptionStack().map(printStackItem).join('\n\t');
}
public static function printError(error:Dynamic):String {
return error == null ? '' : Std.string('${error}\n\t${CallStack.exceptionStack().map(printStackItem).join('\n\t')}');
return error == null ? '' : Std.string('${error}\n\t${getErrorStack(error)}');
}
}

View File

@@ -1,4 +1,4 @@
package haxework.log;
package hw.log;
enum LogLevel {
DEBUG; INFO; WARNING; ERROR;
@@ -10,4 +10,4 @@ interface ILogger {
public function i(tag:String, message:String, ?error:Dynamic, ?p:haxe.PosInfos):Void;
public function w(tag:String, message:String, ?error:Dynamic, ?p:haxe.PosInfos):Void;
public function e(tag:String, message:String, ?error:Dynamic, ?p:haxe.PosInfos):Void;
}
}

View File

@@ -1,8 +1,8 @@
package haxework.log;
package hw.log;
import haxework.log.ILogger.LogLevel;
import hw.log.ILogger.LogLevel;
import flash.external.ExternalInterface;
import haxework.log.BaseLogger;
import hw.log.BaseLogger;
class JSLogger extends BaseLogger {
@@ -26,4 +26,4 @@ class JSLogger extends BaseLogger {
try {ExternalInterface.call("console.log", text);} catch (error:Dynamic) {available = false;}
}
}
}
}

View File

@@ -1,6 +1,6 @@
package haxework.log;
package hw.log;
import haxework.log.BaseLogger;
import hw.log.BaseLogger;
#if js
class SocketLogger extends BaseLogger {}
@@ -58,4 +58,4 @@ class SocketLogger extends BaseLogger {
}
}
#end
#end

View File

@@ -1,4 +1,4 @@
package haxework.log;
package hw.log;
import flash.text.TextField;
@@ -15,4 +15,4 @@ class TextFieldLogger extends BaseLogger {
override private function write(text:String):Void {
this.textField.text += ("\n" + text);
}
}
}

View File

@@ -1,4 +1,4 @@
package haxework.log;
package hw.log;
import haxe.PosInfos;
#if cpp
@@ -31,13 +31,13 @@ class TraceLogger extends BaseLogger {
(untyped console).log(v);
//untyped js.Boot.__trace(v, infos);
#elseif android
haxework.log.AndroidLog.write(3, "", ConstCharStar.fromString(Std.string(v)));
hw.log.AndroidLog.write(3, "", ConstCharStar.fromString(Std.string(v)));
#elseif (php && php7)
php.Boot.trace(v);
#elseif php
untyped __call__('_hx_trace', v);
#elseif cpp
Stdio.printf(ConstCharStar.fromString(Std.string(v)));
Stdio.printf(ConstCharStar.fromString(Std.string(v)+'\n'));
//untyped __trace(v, null);
#elseif cs
cs.system.Console.WriteLine(v);

View File

@@ -1,4 +1,4 @@
package haxework.macro;
package hw.macro;
import haxe.macro.Expr;
import haxe.macro.Type;

View File

@@ -1,4 +1,4 @@
package haxework.macro;
package hw.macro;
import haxe.macro.Expr;
import haxe.macro.Type;

View File

@@ -1,4 +1,4 @@
package haxework.macro;
package hw.macro;
import haxe.macro.TypeTools;
import haxe.macro.Context;
@@ -32,7 +32,7 @@ class DispatcherMacro extends ClassTypeMacro {
}
var signal = 'Signal${argsTypes.length}';
var type = TPath({
pack: ['haxework', 'signal'],
pack: ['hw', 'signal'],
name: 'Signal',
sub: signal,
params: argsTypes.map(function(t) return TPType(TypeTools.toComplexType(t))),
@@ -41,7 +41,7 @@ class DispatcherMacro extends ClassTypeMacro {
name: signalName(field.name),
access: [APublic],
pos: Context.currentPos(),
kind: FProp('default', 'null', type, Context.parse('new haxework.signal.Signal.${signal}()', Context.currentPos())),
kind: FProp('default', 'null', type, Context.parse('new hw.signal.Signal.${signal}()', Context.currentPos())),
});
}
result.push({

View File

@@ -1,8 +1,8 @@
package haxework.macro;
package hw.macro;
import haxe.macro.Expr;
using haxework.macro.MacroUtil;
using hw.macro.MacroUtil;
class FieldMacro {
public var metaName(default, null):String;

View File

@@ -1,4 +1,4 @@
package haxework.macro;
package hw.macro;
import yaml.YamlException;
import yaml.Parser;

View File

@@ -1,4 +1,4 @@
package haxework.macro;
package hw.macro;
import haxe.macro.Context;
import haxe.macro.ExprTools;

View File

@@ -1,4 +1,4 @@
package haxework.macro;
package hw.macro;
typedef JsonKeyPosition = {
var min:Int;

View File

@@ -1,4 +1,4 @@
package haxework.macro;
package hw.macro;
import haxe.DynamicAccess;

View File

@@ -1,9 +1,9 @@
package haxework.macro;
package hw.macro;
import haxe.macro.Context;
import haxe.macro.Expr;
using haxework.macro.MacroUtil;
using hw.macro.MacroUtil;
class ProvideMacro extends FieldMacro {
@@ -35,7 +35,7 @@ class ProvideMacro extends FieldMacro {
pos: field.pos,
kind: FFun({
args: [],
expr: Context.parse('return haxework.provider.Provider.instance.get(${args.join(',')})', field.pos),
expr: Context.parse('return hw.provider.Provider.instance.get(${args.join(',')})', field.pos),
params: [],
ret: type,
})
@@ -47,7 +47,7 @@ class ProvideMacro extends FieldMacro {
pos: field.pos,
kind: FFun({
args: [{name: 'value', type: type}],
expr: Context.parse('{haxework.provider.Provider.instance.set(${args.join(',')}); return value;}', field.pos),
expr: Context.parse('{hw.provider.Provider.instance.set(${args.join(',')}); return value;}', field.pos),
params: [],
ret: type,
})

View File

@@ -1,6 +1,6 @@
package haxework.macro;
package hw.macro;
using haxework.macro.MacroUtil;
using hw.macro.MacroUtil;
class ResourceMacro extends FieldMacro {

View File

@@ -1,4 +1,4 @@
package haxework.macro;
package hw.macro;
import haxe.macro.Context;
import haxe.macro.Expr;

View File

@@ -1,11 +1,11 @@
package haxework.macro;
package hw.macro;
import haxe.macro.Context;
import haxe.macro.Expr;
import haxe.macro.Type;
using haxe.macro.ComplexTypeTools;
using haxework.macro.MacroUtil;
using hw.macro.MacroUtil;
using haxe.macro.MacroStringTools;
typedef TProperty<T> = {
@@ -143,7 +143,7 @@ class StyleMacro extends ClassTypeMacro {
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();
var type:ComplexType = "hw.view.theme.StyleId".toComplex();
if (!overrideField) {
result.push({
name: "style",
@@ -162,11 +162,11 @@ class StyleMacro extends ClassTypeMacro {
}
for (field in properties) {
var propertyName = 'theme_${field.name}';
expr.push(macro $i{propertyName} = haxework.provider.Provider.instance.get(haxework.view.theme.ITheme).resolve((styleKey!=null?(styleKey+"."):"")+$v{field.name}, style));
expr.push(macro $i{propertyName} = hw.provider.Provider.instance.get(hw.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.instance.get(haxework.view.theme.ITheme).resolve((styleKey!=null?(styleKey+"."):"")+$v{field.name}, style));
expr.push(macro $i{propertyName} = hw.provider.Provider.instance.get(hw.view.theme.ITheme).resolve((styleKey!=null?(styleKey+"."):"")+$v{field.name}, style));
}
if (hasOnStyle) {
expr.push(macro onStyle());

View File

@@ -1,12 +1,12 @@
package haxework.macro;
package hw.macro;
import haxe.macro.Context;
import haxe.macro.Expr;
import haxe.macro.Type;
import haxework.macro.PositionJsonParser;
import hw.macro.PositionJsonParser;
import Lambda;
using haxework.macro.MacroUtil;
using hw.macro.MacroUtil;
class TemplateMacro extends ClassTypeMacro {
@@ -46,11 +46,11 @@ class TemplateMacro extends ClassTypeMacro {
a[2];
}
case "resource" | "r":
var bindExpr = 'haxework.provider.Provider.instance.get(haxework.resources.IResources).${a[1]}.bind("${a[2]}", ${name}, "${key}")';
var bindExpr = 'hw.provider.Provider.instance.get(hw.resources.IResources).${a[1]}.bind("${a[2]}", ${name}, "${key}")';
exprs.push(Context.parse(bindExpr, getPosition(position)));
null;
case "translate" | "t":
'new haxework.translate.TranslateString("${a[1]}")';
'new hw.translate.TranslateString("${a[1]}")';
case "template":
var template = FileUtil.loadFile(a[1]);
return createValue(name, key, template, position, exprs);
@@ -127,7 +127,7 @@ class TemplateMacro extends ClassTypeMacro {
case ECall(_, _): macro function(_) ${e};
case _: e;
}
exprs.push(macro $p{[name, key.substr(1)]}.connect(${e}));
exprs.push(macro $p{[name].concat(key.substr(1).split("."))}.connect(${e}));
case ["_", "_"]:
//exprs.push(Context.parse('${name}["${key.substr(1, key.length - 2)}"] = ${value}', getPosition(position)));
exprs.push(Context.parse('${name}.set("${key.substr(1, key.length - 2)}", ${value})', getPosition(position)));

View File

@@ -1,11 +1,11 @@
package haxework.net;
package hw.net;
import promhx.Deferred;
import promhx.Promise;
import haxe.Timer;
import flash.net.URLRequestMethod;
import flash.events.ProgressEvent;
import haxework.net.manage.ILoaderManager;
import hw.net.manage.ILoaderManager;
import flash.utils.ByteArray;
import flash.events.Event;

View File

@@ -1,4 +1,4 @@
package haxework.net;
package hw.net;
import flash.events.ProgressEvent;
import flash.system.Security;
@@ -6,7 +6,7 @@ import flash.system.SecurityDomain;
import flash.system.ApplicationDomain;
import flash.system.LoaderContext;
import flash.utils.ByteArray;
import haxework.net.BaseLoader;
import hw.net.BaseLoader;
import flash.events.SecurityErrorEvent;
import flash.events.IOErrorEvent;
import flash.events.Event;

View File

@@ -1,4 +1,4 @@
package haxework.net;
package hw.net;
import flash.events.ErrorEvent;
import haxe.Timer;

View File

@@ -1,4 +1,4 @@
package haxework.net;
package hw.net;
import promhx.Promise;
import promhx.Deferred;
@@ -17,4 +17,4 @@ class BatchLoader<T> {
return loader.GET(url);
}));
}
}
}

View File

@@ -1,4 +1,4 @@
package haxework.net;
package hw.net;
import flash.net.URLLoaderDataFormat;
import flash.utils.ByteArray;

View File

@@ -1,4 +1,4 @@
package haxework.net;
package hw.net;
import flash.system.Security;
import flash.utils.ByteArray;

View File

@@ -1,4 +1,4 @@
package haxework.net;
package hw.net;
import promhx.Promise;
import flash.utils.ByteArray;

View File

@@ -1,4 +1,4 @@
package haxework.net;
package hw.net;
import flash.display.LoaderInfo;
import flash.display.Loader;

View File

@@ -1,4 +1,4 @@
package haxework.net;
package hw.net;
import flash.utils.ByteArray;
import flash.events.Event;

View File

@@ -1,4 +1,4 @@
package haxework.net;
package hw.net;
import flash.display.MovieClip;
import flash.display.LoaderInfo;

View File

@@ -1,4 +1,4 @@
package haxework.net;
package hw.net;
import flash.net.URLLoader;
import flash.events.Event;

View File

@@ -1,4 +1,4 @@
package haxework.net;
package hw.net;
import flash.events.Event;
import flash.net.URLLoader;

View File

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

View File

@@ -1,4 +1,4 @@
package haxework.net.manage;
package hw.net.manage;
class LoaderManager implements ILoaderManager {

View File

@@ -1,18 +1,18 @@
package haxework.parser;
package hw.parser;
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;
import hw.macro.ClassProvideMacro;
import hw.macro.ClassTypeMacro;
import hw.macro.DispatcherMacro;
import hw.macro.FieldMacro;
import hw.macro.ProvideMacro;
import hw.macro.ResourceMacro;
import hw.macro.SingletonMacro;
import hw.macro.StyleMacro;
import hw.macro.TemplateMacro;
class Parser {
@@ -32,7 +32,7 @@ class Parser {
private static var processed:Map<String, Bool> = new Map();
private static function auto():Void {
haxe.macro.Compiler.addGlobalMetadata("", "@:build(haxework.parser.Parser.autoRun())", true, true, false);
haxe.macro.Compiler.addGlobalMetadata("", "@:build(hw.parser.Parser.autoRun())", true, true, false);
}
private static macro function autoRun():Array<Field> {

Some files were not shown because too many files have changed in this diff Show More