[view] add SelectView
This commit is contained in:
@@ -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 {};
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
146
src/main/haxework/view/SelectView.hx
Normal file
146
src/main/haxework/view/SelectView.hx
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user