This commit is contained in:
2014-01-27 16:52:58 +04:00
parent fe13fd7455
commit af22b3e4d0
8 changed files with 125 additions and 29 deletions

View File

@@ -35,6 +35,7 @@ class ButtonView extends LabelView {
} }
private function onMouseClick(event:MouseEvent):Void { private function onMouseClick(event:MouseEvent):Void {
event.stopImmediatePropagation();
dispatcher.dispatch(pressCaller); dispatcher.dispatch(pressCaller);
} }

View File

@@ -12,7 +12,7 @@ typedef Content = {
} }
interface IView<C:Content> { interface IView<C:Content> {
public var id(default, null):String; public var id(default, default):String;
public var x(default, set):Float; public var x(default, set):Float;
public var y(default, set):Float; public var y(default, set):Float;

View File

@@ -17,7 +17,7 @@ class View<C:Content> implements IView<C> {
private static var counter:Int = 0; private static var counter:Int = 0;
public static var updater(default, null):Updater = new Updater(); public static var updater(default, null):Updater = new Updater();
public var id(default, null):String; public var id(default, default):String;
public var x(default, set):Float; public var x(default, set):Float;
public var y(default, set):Float; public var y(default, set):Float;
@@ -279,7 +279,7 @@ class Updater {
} }
public function invalidate(view:IView<Dynamic>):Void { public function invalidate(view:IView<Dynamic>):Void {
invalidated.push(view); if (Lambda.indexOf(invalidated, view) == -1) invalidated.push(view);
} }
public function update(?_):Void { public function update(?_):Void {

View File

@@ -1,41 +1,58 @@
package haxework.gui.list; package haxework.gui.list;
import haxework.utils.NumberUtil;
import haxework.dispath.Dispatcher;
import haxework.dispath.IDispatcher;
import haxework.gui.list.ScrollView.ScrollListener;
import flash.events.MouseEvent; import flash.events.MouseEvent;
import haxework.gui.core.HAlign; import haxework.gui.core.HAlign;
import flash.display.Sprite; import flash.display.Sprite;
import haxework.gui.skin.ISkin; import haxework.gui.skin.ISkin;
class ListView<V:View<Dynamic>, D> extends VGroupView { class ListView<V:View<Dynamic>, D> extends VGroupView implements ScrollListener {
public var data(default, set):Array<D>; public var data(default, set):Array<D>;
public var renderer(null, set):IRenderer<V, D>; public var renderer(null, set):IRenderer<Dynamic, V, D>;
public var offset(default, set):Int; public var offset(default, set):Int;
public var dispatcher(default, null):IDispatcher<ListViewListener<V, D>>;
private var scroll:ScrollView; private var scroll:ScrollView;
private var size(default, set):Int; private var size(default, set):Int;
private var items:Array<V>; private var items:Array<ListItem<V, D>>;
private var itemsListeners:Map<ListItem<V, D>, MouseEvent->Void>;
public function new() { public function new() {
super(); super();
dispatcher = new Dispatcher<ListViewListener<V, D>>();
offset = 0; offset = 0;
scroll = new ScrollView(); scroll = new ScrollView();
scroll.dispatcher.addListener(this);
scroll.inLayout = false; scroll.inLayout = false;
scroll.pHeight = 100; scroll.pHeight = 100;
scroll.width = 5; scroll.width = 10;
scroll.hAlign = HAlign.RIGHT; scroll.hAlign = HAlign.RIGHT;
scroll.position = 0; scroll.position = 0;
scroll.ratio = 1; scroll.ratio = 1;
scroll.rightMargin = -12;
rightPadding = 12;
addView(scroll); addView(scroll);
items = new Array<V>(); items = new Array<ListItem<V, D>>();
itemsListeners = new Map<ListItem<V, D>, MouseEvent->Void>();
content.addEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheel); content.addEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheel);
} }
public function onScroll(position:Float):Void {
offset = Math.round(data.length * position);
}
private function onMouseWheel(event:MouseEvent):Void { private function onMouseWheel(event:MouseEvent):Void {
offset = Math.round(Math.min(Math.max(0, offset -= event.delta*3), data.length - size)); offset = offset - event.delta * 3;
} }
private function set_offset(value:Int):Int { private function set_offset(value:Int):Int {
value = NumberUtil.limitInt(value, 0, data == null ? 0 : data.length - size);
if (offset != value) { if (offset != value) {
offset = value; offset = value;
render(); render();
@@ -49,7 +66,7 @@ class ListView<V:View<Dynamic>, D> extends VGroupView {
return data; return data;
} }
private function set_renderer(value:IRenderer<V, D>):IRenderer<V, D> { private function set_renderer(value:IRenderer<Dynamic, V, D>):IRenderer<Dynamic, V, D> {
renderer = value; renderer = value;
render(); render();
return renderer; return renderer;
@@ -60,39 +77,68 @@ class ListView<V:View<Dynamic>, D> extends VGroupView {
scroll.ratio = Math.min(1.0, size / data.length); scroll.ratio = Math.min(1.0, size / data.length);
scroll.position = (offset / data.length); scroll.position = (offset / data.length);
for (i in 0...size) { for (i in 0...size) {
var view:V = items[i]; var item:ListItem<V, D> = items[i];
if (data[offset + i] == null) break; item.index = offset + i;
renderer.render(view, data[offset + i]); if (data[item.index] == null) break;
item.data = data[item.index];
renderer.render(this, item);
} }
} }
} }
override public function update():Void { override public function update():Void {
super.update(); super.update();
var item:V = renderer.factory(); var item:ListItem<V, D> = renderer.factory();
size = Math.round(height / item.height); size = Math.round(Math.max(0, height / item.view.height));
render(); render();
} }
private function set_size(value:Int):Int { private function set_size(value:Int):Int {
if (size != value) { if (size != value) {
size = value; size = value;
for (item in items) removeView(item); var diff:Int = size - items.length;
items = new Array<V>(); if (diff > 0) {
var item:V = renderer.factory(); for (i in 0...diff) {
var newSize = Math.round(height / item.height); var item:ListItem<V, D> = renderer.factory();
for (i in 0...size) { items.push(item);
item = renderer.factory(); setClickListener(item);
items.push(item); addView(item.view);
addView(item); }
} else if (diff < 0) {
for (i in 0...-diff) {
var item:ListItem<V, D> = items.pop();
item.view.content.removeEventListener(MouseEvent.CLICK, itemsListeners.get(item));
itemsListeners.remove(item);
removeView(item.view);
}
} }
} }
return size; return size;
} }
private function setClickListener(item:ListItem<V, D>):Void {
var listener:MouseEvent->Void = function(event:MouseEvent):Void {
dispatcher.dispatch(function(listener:ListViewListener<V, D>):Void {
listener.onListItemClick(item);
});
}
item.view.content.addEventListener(MouseEvent.CLICK, listener);
itemsListeners.set(item, listener);
}
} }
interface IRenderer<V, D> { interface IRenderer<L, V, D> {
public function factory():V; public function factory():ListItem<V, D>;
public function render(view:V, data:D):Void; public function render(list:L, item:ListItem<V, D>):Void;
}
interface ListViewListener<V, D> {
public function onListItemClick(item:ListItem<V, D>):Void;
}
typedef ListItem<V, D> = {
var view:V;
@:optional var index:Int;
@:optional var data:D;
} }

View File

@@ -1,5 +1,10 @@
package haxework.gui.list; package haxework.gui.list;
import haxework.utils.NumberUtil;
import flash.geom.Point;
import haxework.dispath.Dispatcher;
import haxework.dispath.IDispatcher;
import flash.events.MouseEvent;
import flash.display.Graphics; import flash.display.Graphics;
import flash.display.Sprite; import flash.display.Sprite;
import haxework.gui.skin.ISkin; import haxework.gui.skin.ISkin;
@@ -10,12 +15,39 @@ class ScrollView extends SpriteView {
public var position(default, set):Float; public var position(default, set):Float;
public var ratio(default, set):Float; public var ratio(default, set):Float;
public var dispatcher(default, null):IDispatcher<ScrollListener>;
private var mousePosition:Float;
public function new() { public function new() {
super(); super();
dispatcher = new Dispatcher<ScrollListener>();
skin = untyped new ScrollSkin(); skin = untyped new ScrollSkin();
content.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
}
private function onMouseDown(event:MouseEvent):Void {
content.stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
content.stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
var p:Point = content.globalToLocal(new Point(event.stageX, event.stageY));
mousePosition = p.y - height * position;
}
private function onMouseMove(event:MouseEvent):Void {
var p:Point = content.globalToLocal(new Point(event.stageX, event.stageY));
position = (p.y - mousePosition) / height;
dispatcher.dispatch(function(listener:ScrollListener):Void {
listener.onScroll(position);
});
}
private function onMouseUp(event:MouseEvent):Void {
content.stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
content.stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
} }
private function set_position(value:Float):Float { private function set_position(value:Float):Float {
value = NumberUtil.limitFloat(value, 0, 1 - ratio);
if (position != value) { if (position != value) {
position = value; position = value;
invalidate(); invalidate();
@@ -51,4 +83,8 @@ class ScrollSkin implements ISkin<Sprite, ScrollView> {
graphics.drawRect(0, view.height * view.position, view.width, view.height * view.ratio); graphics.drawRect(0, view.height * view.position, view.width, view.height * view.ratio);
graphics.endFill(); graphics.endFill();
} }
}
interface ScrollListener {
public function onScroll(position:Float):Void;
} }

View File

@@ -18,7 +18,8 @@ class BaseLogger implements ILogger {
public static function error2strign(error:Dynamic):String { public static function error2strign(error:Dynamic):String {
return if (Std.is(error, Error)) { return if (Std.is(error, Error)) {
cast(error, Error).getStackTrace(); var stack:String = error.getStackTrace();
stack == null ? Std.string(error) : stack;
} else if (Std.is(error, ErrorEvent)) { } else if (Std.is(error, ErrorEvent)) {
var event:ErrorEvent = cast(error, ErrorEvent); var event:ErrorEvent = cast(error, ErrorEvent);
event.type + " - " + event.text; event.type + " - " + event.text;

View File

@@ -15,7 +15,7 @@ class JsonLoader<T> extends BaseURLLoader<T> {
str = Std.string(cast(e.currentTarget, URLLoader).data); str = Std.string(cast(e.currentTarget, URLLoader).data);
data = Json.parse(str); data = Json.parse(str);
} catch (error:Dynamic) { } catch (error:Dynamic) {
throw new Error(error + ": " + str); throw new Error(error + ": " + url);
} }
return data; return data;
} }
@@ -27,7 +27,7 @@ class JsonLoader<T> extends BaseURLLoader<T> {
str = bytes.readUTFBytes(bytes.length); str = bytes.readUTFBytes(bytes.length);
data = Json.parse(str); data = Json.parse(str);
} catch (error:Dynamic) { } catch (error:Dynamic) {
throw new Error(error + ": " + str); throw new Error(error + ": " + url);
} }
return data; return data;
} }

12
haxework/utils/NumberUtil.hx Executable file
View File

@@ -0,0 +1,12 @@
package haxework.utils;
class NumberUtil {
public static inline function limitInt(value:Int, min:Int, max:Int):Int {
return Math.round(Math.min(Math.max(min, value), max));
}
public static inline function limitFloat(value:Float, min:Float, max:Float):Float {
return Math.min(Math.max(min, value), max);
}
}