[view] add SelectView

This commit is contained in:
2019-07-09 12:03:38 +03:00
parent 34cb98beb1
commit 61e74a3755
18 changed files with 247 additions and 57 deletions

View File

@@ -1,30 +0,0 @@
package;
#if macro
import haxe.macro.Context;
import haxe.macro.Expr;
#end
class Meta {
#if macro
private static inline var VERSION:String = "version";
private static inline var BUILD:String = "build";
private static var data:Map<String, Dynamic> = new Map<String, Dynamic>();
#end
macro static public function getBuild():ExprOf<String> {
return Context.makeExpr(data.get(BUILD), Context.currentPos());
}
macro static public function getVersion():ExprOf<String> {
return Context.makeExpr(data.get(VERSION), Context.currentPos());
}
macro static public function set(version:String) {
data.set(BUILD, Date.now().toString());
data.set(VERSION, version);
return macro {};
}
}

View File

@@ -64,7 +64,7 @@ class TemplateMacro {
private function specialValue(name:String, key:String, a:Array<String>, position:JsonKeyPosition, exprs:Array<Expr>):Dynamic {
return switch (a[0]) {
case "asset" | "a":
switch (a[1]) {
switch a[1] {
case "image":
'openfl.Assets.getBitmapData("${a[2]}")';
case _:
@@ -76,12 +76,8 @@ class TemplateMacro {
null;
case "translate" | "t":
'new haxework.translate.TranslateString("${a[1]}")';
case "code":
a[1];
case "this":
'this.${a[1]}';
case "layout":
var template = FileUtil.loadJsonFile(a[1]);
case "template":
var template = FileUtil.loadFile(a[1]);
return createValue(name, key, template, position, exprs);
case _:
Context.error('Unsupported prefix "${a[0]}"', getPosition(position));
@@ -94,7 +90,9 @@ class TemplateMacro {
return createValue(null, null, v, position, exprs);
});
} else if (Std.is(value, String)) {
if (value.charAt(0) == "@" || value.charAt(0) == "$") {
if (value.charAt(0) == "~" ) {
value.substring(1, value.length);
} else if (value.charAt(0) == "@" || value.charAt(0) == "$") {
specialValue(name, key, value.substring(1, value.length).split(":"), position, exprs);
} else if (~/(0x|#)[A-Fa-f\d]{6}/.match(value)) {
Std.parseInt(StringTools.replace(Std.string(value), "#", "0x"));
@@ -134,7 +132,8 @@ class TemplateMacro {
private function createElement(name:String, data:Dynamic, exprs:Array<Expr>):String {
if (Reflect.hasField(data, "id")) {
var id = Reflect.field(data, "id");
if (bindings.exists(id)) {
// ToDo: only for view?
if (Std.is(id, String) && bindings.exists(id)) {
var bind = bindings.get(id);
exprs.push(Context.parse('this.${bind} = ${name}', getPosition()));
bindings.remove(id);
@@ -149,7 +148,7 @@ class TemplateMacro {
switch [key.charAt(0), key.charAt(key.length - 1)] {
case ["+", _]:
var e:Expr = Context.parse(value, getPosition(position));
e = switch (e.expr) {
e = switch e.expr {
case ECall(_, _): macro function(_) ${e};
case _: e;
}

View File

@@ -3,6 +3,8 @@ package haxework.view;
import flash.display.DisplayObject;
import flash.events.MouseEvent;
import haxework.signal.Signal;
import haxework.view.layout.ILayout;
import haxework.view.layout.VerticalLayout;
typedef Factory<D, V:IView<Dynamic>> = Int -> D -> V
@@ -16,6 +18,10 @@ class DataView<D, V:IView<Dynamic>> extends GroupView {
private var objectIndexes:Map<DisplayObject, Int> = new Map();
public function new(?layout:ILayout) {
super(layout != null ? layout : new VerticalLayout());
}
private function set_data(value:Array<D>):Array<D> {
data = value;
if (factory != null) rebuild();

View File

@@ -56,6 +56,10 @@ class GroupView extends SpriteView implements IGroupView {
return views;
}
public function containsView(view:IView<Dynamic>):Bool {
return views.indexOf(view) > -1;
}
public function addView(view:IView<Dynamic>):IView<Dynamic> {
views.push(view);
if (view.content != null) content.addChild(view.content);

View File

@@ -9,6 +9,8 @@ interface IGroupView extends IView<Dynamic> {
public var views(default, set):Array<IView<Dynamic>>;
public var layout(default, default):ILayout;
public function containsView(view:IView<Dynamic>):Bool;
public function addView(view:IView<Dynamic>):IView<Dynamic>;
public function addViewFirst(view:IView<Dynamic>):IView<Dynamic>;

View File

@@ -1,6 +1,7 @@
package haxework.view;
import flash.display.DisplayObject;
import flash.geom.Rectangle;
import haxework.view.core.Geometry;
import haxework.view.skin.ISkin.SkinSet;
@@ -25,6 +26,8 @@ interface IView<C:DisplayObject> {
public var index(default, set):Int;
public var mouseEnabled(default, set):Bool;
public var rect(get, null):Rectangle;
public function update():Void;
public function redraw():Void;

View File

@@ -1,5 +1,6 @@
package haxework.view;
import haxework.provider.Provider;
import flash.display.DisplayObject;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
@@ -27,6 +28,9 @@ class Root {
this.view = view;
this.autoSize = autoSize;
Lib.current.addChild(view.content);
if (Std.is(view, IGroupView)) {
Provider.set(IGroupView, cast view);
}
var content:DisplayObject = view.content;
if (content.stage == null) {
content.addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);

View File

@@ -0,0 +1,146 @@
package haxework.view;
import flash.events.MouseEvent;
import flash.geom.Point;
import haxework.signal.Signal;
import haxework.view.core.Geometry.Position;
import haxework.view.layout.VerticalLayout;
import haxework.view.skin.Skin;
using haxework.utils.StringUtil;
class SelectIdView<D, K> extends SelectView<D> {
public var selectedId(get, set):K;
public var idResolver(default, default):D -> K;
private var _selectedId:K;
public function new() {
super();
idResolver = function(item:D):K return Reflect.field(item, "id");
}
override private function set_selected(value:D):D {
var result = super.set_selected(value);
_selectedId = idResolver(result);
return result;
}
private inline function get_selectedId():K {
return _selectedId;
}
private function set_selectedId(value:K):K {
if (_selectedId != value) {
_selectedId = value;
for (item in data) {
if (idResolver(item) == _selectedId) {
selected = item;
break;
}
}
}
return _selectedId;
}
}
class SelectView<D> extends GroupView {
public var currentView(default, null):ButtonView;
public var dataView(default, null):DataView<D, LabelView>;
public var labelSkinId(default, set):String;
public var labelBuilder(default, set):D -> String;
public var data(default, set):Array<D>;
public var selected(default, set):D;
public var onSelect(default, null):Signal<D> = new Signal();
@:provide private static var root:IGroupView;
public function new() {
super(new VerticalLayout());
skin = [Skin.transparent];
currentView = new ButtonView();
currentView.onPress.connect(function(_) toggle());
dataView = new DataView();
dataView.skin = [Skin.transparent];
dataView.geometry.position = ABSOLUTE;
dataView.factory = factory;
dataView.onDataSelect.connect(function(value:D):Void {
selected = value;
close();
});
views = [currentView];
labelBuilder = function(value:D):String return Std.string(value).title();
}
private function factory(index:Int, value:D):LabelView {
var result = new LabelView();
result.skinId = labelSkinId;
result.text = labelBuilder(value);
return result;
}
private function set_labelSkinId(value:String):String {
if (labelSkinId != value) {
labelSkinId = value;
currentView.skinId = labelSkinId;
for (view in dataView.dataViews) {
view.skinId = labelSkinId;
}
}
return labelSkinId;
}
private function set_labelBuilder(value:D -> String):D -> String {
labelBuilder = value;
for (i in 0...dataView.dataViews.length) {
dataView.dataViews[i].text = labelBuilder(data[i]);
}
return labelBuilder;
}
private function set_data(value:Array<D>):Array<D> {
data = value;
dataView.data = value;
return data;
}
private function set_selected(value:D):D {
selected = value;
currentView.text = labelBuilder(selected);
onSelect.emit(selected);
return selected;
}
public function toggle():Void {
if (root.containsView(dataView)) {
close();
} else {
open();
}
}
public function open():Void {
root.addView(dataView);
content.stage.addEventListener(MouseEvent.MOUSE_DOWN, onStageMouseClick);
}
public function close():Void {
content.stage.removeEventListener(MouseEvent.MOUSE_DOWN, onStageMouseClick);
root.removeView(dataView);
}
override public function update():Void {
super.update();
var rect = currentView.rect;
dataView.geometry.margin.left = rect.left;
dataView.geometry.margin.top = rect.top + rect.height + layout.margin;
}
private function onStageMouseClick(event:MouseEvent):Void {
var objects = content.stage.getObjectsUnderPoint(new Point(event.stageX, event.stageY));
if (objects.indexOf(content) == -1 && objects.indexOf(dataView.content) == -1) {
close();
}
}
}

View File

@@ -2,9 +2,10 @@ package haxework.view;
import flash.display.DisplayObject;
import flash.display.InteractiveObject;
import flash.geom.Rectangle;
import haxework.resources.IResources;
import haxework.view.core.Geometry;
import haxework.view.skin.ISkin;
import haxework.resources.IResources;
class View<C:DisplayObject> implements IView<C> {
@:provide private var r:IResources;
@@ -32,6 +33,8 @@ class View<C:DisplayObject> implements IView<C> {
public var index(default, set):Int;
public var mouseEnabled(default, set):Bool = true;
public var rect(get, null):Rectangle;
public function new(content:C) {
id = Type.getClassName(Type.getClass(this)) + counter++;
this.content = content;
@@ -160,4 +163,16 @@ class View<C:DisplayObject> implements IView<C> {
}
return mouseEnabled;
}
private function get_rect():Rectangle {
var x = this.x;
var y = this.y;
var parent = this.parent;
while (parent != null) {
x += parent.x;
y += parent.y;
parent = parent.parent;
}
return new Rectangle(x, y, width, height);
}
}

View File

@@ -1,7 +1,6 @@
package haxework.view.popup;
import haxework.animate.IAnimate;
import haxework.view.Root;
import haxework.view.IGroupView;
typedef P = PopupView<Dynamic>;
@@ -13,12 +12,14 @@ class PopupManager {
private var popups:Array<P>;
@:provide private static var root:IGroupView;
public function new() {
popups = new Array<P>();
}
public function show(popup:P):Void {
cast(Root.instance.view, IGroupView).addView(popup);
root.addView(popup);
if (showAnimateFactory != null) {
showAnimateFactory(popup).start(null);
}
@@ -35,9 +36,8 @@ class PopupManager {
}
public function remove(popup:P):Void {
var container = cast(Root.instance.view, IGroupView);
if (container.views.indexOf(popup) > -1) {
container.removeView(popup);
if (root.containsView(popup)) {
root.removeView(popup);
}
}

View File

@@ -7,6 +7,8 @@ import flash.display.BitmapData;
class Skin {
public static var transparent(default, never):ISkin<SpriteView> = new ColorSkin(0, 0);
public static function size(width:Float, height:Float):ISkin<Dynamic> {
return new GeometrySkin(new Geometry().setSize(width, height));
}