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 {
event.stopImmediatePropagation();
dispatcher.dispatch(pressCaller);
}

View File

@@ -12,7 +12,7 @@ typedef 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 y(default, set):Float;

View File

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

View File

@@ -1,41 +1,58 @@
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 haxework.gui.core.HAlign;
import flash.display.Sprite;
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 renderer(null, set):IRenderer<V, D>;
public var renderer(null, set):IRenderer<Dynamic, V, D>;
public var offset(default, set):Int;
public var dispatcher(default, null):IDispatcher<ListViewListener<V, D>>;
private var scroll:ScrollView;
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() {
super();
dispatcher = new Dispatcher<ListViewListener<V, D>>();
offset = 0;
scroll = new ScrollView();
scroll.dispatcher.addListener(this);
scroll.inLayout = false;
scroll.pHeight = 100;
scroll.width = 5;
scroll.width = 10;
scroll.hAlign = HAlign.RIGHT;
scroll.position = 0;
scroll.ratio = 1;
scroll.rightMargin = -12;
rightPadding = 12;
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);
}
public function onScroll(position:Float):Void {
offset = Math.round(data.length * position);
}
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 {
value = NumberUtil.limitInt(value, 0, data == null ? 0 : data.length - size);
if (offset != value) {
offset = value;
render();
@@ -49,7 +66,7 @@ class ListView<V:View<Dynamic>, D> extends VGroupView {
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;
render();
return renderer;
@@ -60,39 +77,68 @@ class ListView<V:View<Dynamic>, D> extends VGroupView {
scroll.ratio = Math.min(1.0, size / data.length);
scroll.position = (offset / data.length);
for (i in 0...size) {
var view:V = items[i];
if (data[offset + i] == null) break;
renderer.render(view, data[offset + i]);
var item:ListItem<V, D> = items[i];
item.index = offset + i;
if (data[item.index] == null) break;
item.data = data[item.index];
renderer.render(this, item);
}
}
}
override public function update():Void {
super.update();
var item:V = renderer.factory();
size = Math.round(height / item.height);
var item:ListItem<V, D> = renderer.factory();
size = Math.round(Math.max(0, height / item.view.height));
render();
}
private function set_size(value:Int):Int {
if (size != value) {
size = value;
for (item in items) removeView(item);
items = new Array<V>();
var item:V = renderer.factory();
var newSize = Math.round(height / item.height);
for (i in 0...size) {
item = renderer.factory();
items.push(item);
addView(item);
var diff:Int = size - items.length;
if (diff > 0) {
for (i in 0...diff) {
var item:ListItem<V, D> = renderer.factory();
items.push(item);
setClickListener(item);
addView(item.view);
}
} 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;
}
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> {
public function factory():V;
public function render(view:V, data:D):Void;
interface IRenderer<L, V, D> {
public function factory():ListItem<V, D>;
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;
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.Sprite;
import haxework.gui.skin.ISkin;
@@ -10,12 +15,39 @@ class ScrollView extends SpriteView {
public var position(default, set):Float;
public var ratio(default, set):Float;
public var dispatcher(default, null):IDispatcher<ScrollListener>;
private var mousePosition:Float;
public function new() {
super();
dispatcher = new Dispatcher<ScrollListener>();
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 {
value = NumberUtil.limitFloat(value, 0, 1 - ratio);
if (position != value) {
position = value;
invalidate();
@@ -52,3 +84,7 @@ class ScrollSkin implements ISkin<Sprite, ScrollView> {
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 {
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)) {
var event:ErrorEvent = cast(error, ErrorEvent);
event.type + " - " + event.text;

View File

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