gui: lists and texts
This commit is contained in:
@@ -2,6 +2,10 @@ package haxework.gui;
|
|||||||
|
|
||||||
|
|
||||||
//ToDo:
|
//ToDo:
|
||||||
|
import flash.errors.Error;
|
||||||
|
import openfl.Assets;
|
||||||
|
import flash.errors.TypeError;
|
||||||
|
import flash.errors.ArgumentError;
|
||||||
import haxework.resources.IResources;
|
import haxework.resources.IResources;
|
||||||
import haxework.provider.Provider;
|
import haxework.provider.Provider;
|
||||||
import haxework.gui.View;
|
import haxework.gui.View;
|
||||||
@@ -11,6 +15,7 @@ import haxework.gui.GroupView;
|
|||||||
import haxework.gui.HGroupView;
|
import haxework.gui.HGroupView;
|
||||||
import haxework.gui.VGroupView;
|
import haxework.gui.VGroupView;
|
||||||
import haxework.gui.TextView;
|
import haxework.gui.TextView;
|
||||||
|
import haxework.gui.InputView;
|
||||||
import haxework.gui.LabelView;
|
import haxework.gui.LabelView;
|
||||||
import haxework.gui.ButtonView;
|
import haxework.gui.ButtonView;
|
||||||
import haxework.gui.ToggleButtonView;
|
import haxework.gui.ToggleButtonView;
|
||||||
@@ -24,28 +29,66 @@ import haxework.frame.FrameSwitcher;
|
|||||||
|
|
||||||
class GuiBuilder {
|
class GuiBuilder {
|
||||||
|
|
||||||
private function new() {}
|
|
||||||
|
|
||||||
public static function build(data:Dynamic, ?links:Dynamic):Dynamic {
|
public static function build(data:Dynamic, ?links:Dynamic):Dynamic {
|
||||||
|
return new GuiB(data, links).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function fill(object:Dynamic, data:Dynamic, ?links:Dynamic):Void {
|
||||||
|
new GuiF(object, data, links).fill();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GuiB {
|
||||||
|
|
||||||
|
private var data:Dynamic;
|
||||||
|
private var links:Dynamic;
|
||||||
|
|
||||||
|
public function new(data:Dynamic, ?links:Dynamic) {
|
||||||
|
this.data = data;
|
||||||
|
this.links = links;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function build():Dynamic {
|
||||||
if (Reflect.hasField(data, "type")) {
|
if (Reflect.hasField(data, "type")) {
|
||||||
var type:String = data.type;
|
var type:String = data.type;
|
||||||
Reflect.deleteField(data, "type");
|
//Reflect.deleteField(data, "type");
|
||||||
var object:Dynamic = instance(type);
|
var object:Dynamic = instance(type);
|
||||||
fill(object, data, links);
|
new GuiF(object, data, links).fill();
|
||||||
return object;
|
return object;
|
||||||
} else {
|
} else {
|
||||||
fill(data, data, links);
|
new GuiF(data, data, links).fill();
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function fill(object:Dynamic, data:Dynamic, ?links:Dynamic):Void {
|
private static function instance(type:String):Dynamic {
|
||||||
|
var clazz:Class<Dynamic> = Type.resolveClass(type);
|
||||||
|
if (clazz == null) throw new TypeError("Class \"" + type + "\" not found");
|
||||||
|
var instance:Dynamic = Type.createInstance(clazz, []);
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GuiF {
|
||||||
|
|
||||||
|
private var object:Dynamic;
|
||||||
|
private var data:Dynamic;
|
||||||
|
private var links:Dynamic;
|
||||||
|
|
||||||
|
public function new(object:Dynamic, data:Dynamic, ?links:Dynamic) {
|
||||||
|
this.object = object;
|
||||||
|
this.data = data;
|
||||||
|
this.links = links;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function fill() {
|
||||||
var fields:Array<String> = Reflect.fields(data);
|
var fields:Array<String> = Reflect.fields(data);
|
||||||
for (field in fields) {
|
for (field in fields) {
|
||||||
|
if (field == "type") continue;
|
||||||
var value:Dynamic = Reflect.field(data, field);
|
var value:Dynamic = Reflect.field(data, field);
|
||||||
if (Std.is(value, Array)) {
|
if (Std.is(value, Array)) {
|
||||||
var a:Array<Dynamic> = [];
|
var a:Array<Dynamic> = [];
|
||||||
for (o in cast(value, Array<Dynamic>)) a.push(build(o, links));
|
for (o in cast(value, Array<Dynamic>)) a.push(new GuiB(o, links).build());
|
||||||
value = a;
|
value = a;
|
||||||
} else if (Std.is(value, String)) {
|
} else if (Std.is(value, String)) {
|
||||||
var s:String = cast(value, String);
|
var s:String = cast(value, String);
|
||||||
@@ -57,9 +100,16 @@ class GuiBuilder {
|
|||||||
var e:Enum<Dynamic> = Type.resolveEnum(a[0]);
|
var e:Enum<Dynamic> = Type.resolveEnum(a[0]);
|
||||||
value = Type.createEnum(e, a[1]);
|
value = Type.createEnum(e, a[1]);
|
||||||
} else if (c == "@") {
|
} else if (c == "@") {
|
||||||
var a:Array<String> = s.substr(1).split(":");
|
if (s.charAt(1) == "~") {
|
||||||
//value = Reflect.field(Provider.get(IResources), a[0]).get(a[1]);
|
var a:Array<String> = s.substr(2).split(":");
|
||||||
Reflect.field(Provider.get(IResources), a[0]).bind(a[1], object, field);
|
switch (a[0]) {
|
||||||
|
case "image": Reflect.setProperty(object, field, Assets.getBitmapData(a[1]));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var a:Array<String> = s.substr(1).split(":");
|
||||||
|
//value = Reflect.field(Provider.get(IResources), a[0]).get(a[1]);
|
||||||
|
Reflect.field(Provider.get(IResources), a[0]).bind(a[1], object, field);
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
} else if (~/0x[A-Fa-f\d]{6}/.match(value)) {
|
} else if (~/0x[A-Fa-f\d]{6}/.match(value)) {
|
||||||
value = Std.parseInt(value);
|
value = Std.parseInt(value);
|
||||||
@@ -69,17 +119,15 @@ class GuiBuilder {
|
|||||||
} else if (Std.is(value, Bool)) {
|
} else if (Std.is(value, Bool)) {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
var o:Dynamic = build(value, links);
|
var o:Dynamic = new GuiB(value, links).build();
|
||||||
fill(o, value, links);
|
new GuiF(o, value, links).fill();
|
||||||
value = o;
|
value = o;
|
||||||
}
|
}
|
||||||
Reflect.setProperty(object, field, value);
|
try {
|
||||||
|
Reflect.setProperty(object, field, value);
|
||||||
|
} catch(error:Dynamic) {
|
||||||
|
L.e("GuiBuilder", "", error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private static function instance(type:String):Dynamic {
|
|
||||||
var clazz:Class<Dynamic> = Type.resolveClass(type);
|
|
||||||
var instance:Dynamic = Type.createInstance(clazz, []);
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -5,7 +5,7 @@ import flash.text.TextFormatAlign;
|
|||||||
|
|
||||||
interface ITextView<C:Content, T> extends IView<C> {
|
interface ITextView<C:Content, T> extends IView<C> {
|
||||||
public var textField(default, null):T;
|
public var textField(default, null):T;
|
||||||
public var text(default, set):String;
|
public var text(get, set):String;
|
||||||
public var align(default, set):TextFormatAlign;
|
public var align(default, set):TextFormatAlign;
|
||||||
public var fontFamily(default, set):String;
|
public var fontFamily(default, set):String;
|
||||||
public var fontColor(default, set):Int;
|
public var fontColor(default, set):Int;
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ import flash.display.BitmapData;
|
|||||||
|
|
||||||
class ImageView extends SpriteView {
|
class ImageView extends SpriteView {
|
||||||
|
|
||||||
private var image(default, set):BitmapData;
|
public var image(default, set):BitmapData;
|
||||||
|
|
||||||
public function new() {
|
public function new() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function set_image(value:BitmapData):BitmapData {
|
private function set_image(value:BitmapData):BitmapData {
|
||||||
if (image != value) {
|
if (image != value) {
|
||||||
image = value;
|
image = value;
|
||||||
skin = untyped new BitmapSkin(image);
|
skin = untyped new BitmapSkin(image);
|
||||||
|
|||||||
12
haxework/gui/InputView.hx
Executable file
12
haxework/gui/InputView.hx
Executable file
@@ -0,0 +1,12 @@
|
|||||||
|
package haxework.gui;
|
||||||
|
|
||||||
|
import flash.events.TextEvent;
|
||||||
|
import flash.text.TextFieldType;
|
||||||
|
|
||||||
|
class InputView extends TextView {
|
||||||
|
|
||||||
|
public function new() {
|
||||||
|
super();
|
||||||
|
textField.type = TextFieldType.INPUT;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,19 +1,17 @@
|
|||||||
package haxework.gui;
|
package haxework.gui;
|
||||||
|
|
||||||
|
import haxework.gui.core.HAlign;
|
||||||
|
import haxework.gui.core.VAlign;
|
||||||
import flash.text.TextFieldAutoSize;
|
import flash.text.TextFieldAutoSize;
|
||||||
|
|
||||||
class LabelView extends TextView {
|
class LabelView extends TextView {
|
||||||
|
|
||||||
public function new() {
|
public function new() {
|
||||||
super();
|
super();
|
||||||
|
fill = false;
|
||||||
textField.selectable = false;
|
textField.selectable = false;
|
||||||
textField.wordWrap = false;
|
textField.wordWrap = false;
|
||||||
textField.autoSize = TextFieldAutoSize.LEFT;
|
layoutHAlign = HAlign.CENTER;
|
||||||
}
|
layoutVAlign = VAlign.MIDDLE;
|
||||||
|
|
||||||
override public function update():Void {
|
|
||||||
super.update();
|
|
||||||
textField.x = (width - textField.width) / 2;
|
|
||||||
textField.y = (height - textField.height) / 2;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
package haxework.gui;
|
package haxework.gui;
|
||||||
|
|
||||||
|
import flash.text.TextFieldAutoSize;
|
||||||
|
import haxework.gui.core.HAlign;
|
||||||
|
import haxework.gui.core.VAlign;
|
||||||
import flash.text.TextFormatAlign;
|
import flash.text.TextFormatAlign;
|
||||||
import haxework.gui.skin.ISize;
|
import haxework.gui.skin.ISize;
|
||||||
import flash.text.TextFormat;
|
import flash.text.TextFormat;
|
||||||
@@ -9,16 +12,24 @@ import flash.text.TextField;
|
|||||||
class TextView extends SpriteView implements ITextView<Sprite, TextField> {
|
class TextView extends SpriteView implements ITextView<Sprite, TextField> {
|
||||||
|
|
||||||
public var textField(default, null):TextField;
|
public var textField(default, null):TextField;
|
||||||
public var text(default, set):String;
|
public var text(get, set):String;
|
||||||
|
private var _text:String;
|
||||||
public var align(default, set):TextFormatAlign;
|
public var align(default, set):TextFormatAlign;
|
||||||
public var fontFamily(default, set):String;
|
public var fontFamily(default, set):String;
|
||||||
public var fontColor(default, set):Int;
|
public var fontColor(default, set):Int;
|
||||||
public var fontSize(default, set):Float;
|
public var fontSize(default, set):Float;
|
||||||
|
|
||||||
|
public var layoutHAlign(default, set):HAlign;
|
||||||
|
public var layoutVAlign(default, set):VAlign;
|
||||||
|
public var fill(default, set):Bool = true;
|
||||||
|
public var paddings(default, set):Float = 0.0;
|
||||||
|
|
||||||
private var textFormat:TextFormat;
|
private var textFormat:TextFormat;
|
||||||
|
|
||||||
public function new() {
|
public function new() {
|
||||||
super();
|
super();
|
||||||
|
layoutHAlign = HAlign.NONE;
|
||||||
|
layoutVAlign = VAlign.NONE;
|
||||||
textField = new TextField();
|
textField = new TextField();
|
||||||
textField.width = 1;
|
textField.width = 1;
|
||||||
textField.height = 1;
|
textField.height = 1;
|
||||||
@@ -29,13 +40,48 @@ class TextView extends SpriteView implements ITextView<Sprite, TextField> {
|
|||||||
content.addChild(textField);
|
content.addChild(textField);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function set_text(value:String):String {
|
private function set_paddings(value:Float):Float {
|
||||||
if (text != value) {
|
if (paddings != value) {
|
||||||
text = value;
|
paddings = value;
|
||||||
//textField.text = text;
|
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
return text;
|
return paddings;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function set_fill(value:Bool):Bool {
|
||||||
|
if (fill != value) {
|
||||||
|
fill = value;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
return fill;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function set_layoutHAlign(value:HAlign):HAlign {
|
||||||
|
if (layoutHAlign != value) {
|
||||||
|
layoutHAlign = value;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
return layoutHAlign;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function set_layoutVAlign(value:VAlign):VAlign {
|
||||||
|
if (layoutVAlign != value) {
|
||||||
|
layoutVAlign = value;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
return layoutVAlign;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function get_text():String {
|
||||||
|
return textField.text;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function set_text(value:String):String {
|
||||||
|
if (_text != value) {
|
||||||
|
_text = value;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
return _text;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function set_align(value:TextFormatAlign):TextFormatAlign {
|
private function set_align(value:TextFormatAlign):TextFormatAlign {
|
||||||
@@ -75,13 +121,31 @@ class TextView extends SpriteView implements ITextView<Sprite, TextField> {
|
|||||||
|
|
||||||
override public function update():Void {
|
override public function update():Void {
|
||||||
textField.defaultTextFormat = textFormat;
|
textField.defaultTextFormat = textFormat;
|
||||||
if (text != null) textField.text = text;
|
textField.autoSize = fill ? TextFieldAutoSize.NONE : TextFieldAutoSize.LEFT;
|
||||||
|
if (_text != null) textField.text = _text;
|
||||||
if (contentSize && !Std.is(skin, ISize)) {
|
if (contentSize && !Std.is(skin, ISize)) {
|
||||||
width = textField.width;
|
width = textField.width;
|
||||||
height = textField.height;
|
height = textField.height;
|
||||||
} else {
|
} else {
|
||||||
textField.width = width;
|
if (fill) {
|
||||||
textField.height = height;
|
textField.width = width - paddings * 2;
|
||||||
|
textField.height = height - paddings * 2;
|
||||||
|
textField.x = paddings;
|
||||||
|
textField.y = paddings;
|
||||||
|
} else {
|
||||||
|
textField.x = switch (layoutHAlign) {
|
||||||
|
case HAlign.NONE: 0;
|
||||||
|
case HAlign.LEFT: 0;
|
||||||
|
case HAlign.CENTER: (width - textField.width) / 2;
|
||||||
|
case HAlign.RIGHT: width - textField.width;
|
||||||
|
}
|
||||||
|
textField.y = switch (layoutVAlign) {
|
||||||
|
case VAlign.NONE: 0;
|
||||||
|
case VAlign.TOP: 0;
|
||||||
|
case VAlign.MIDDLE: (height - textField.height) / 2;
|
||||||
|
case VAlign.BOTTOM: height - textField.height;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
super.update();
|
super.update();
|
||||||
}
|
}
|
||||||
|
|||||||
33
haxework/gui/list/HListView.hx
Executable file
33
haxework/gui/list/HListView.hx
Executable file
@@ -0,0 +1,33 @@
|
|||||||
|
package haxework.gui.list;
|
||||||
|
|
||||||
|
import haxework.gui.core.HAlign;
|
||||||
|
import haxework.gui.layout.VerticalLayout;
|
||||||
|
import haxework.gui.list.ListView.ListItem;
|
||||||
|
import haxework.gui.list.HScrollView;
|
||||||
|
import haxework.gui.core.VAlign;
|
||||||
|
import haxework.gui.layout.HorizontalLayout;
|
||||||
|
|
||||||
|
class HListView<V:View<Dynamic>, D> extends ListView<V, D> {
|
||||||
|
|
||||||
|
public function new() {
|
||||||
|
super(new HorizontalLayout(), new VerticalLayout());
|
||||||
|
container.layoutHAlign = HAlign.LEFT;
|
||||||
|
container.layoutVAlign = VAlign.MIDDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
override private function recalcSize(item:ListItem<V, D>):Void {
|
||||||
|
var view:IView<Dynamic> = item.view;
|
||||||
|
itemSize = view.width + view.leftMargin + view.rightMargin + layoutMargin;
|
||||||
|
size = Math.round(Math.max(0, width / itemSize)) + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
override private function set_diff(value:Float):Float {
|
||||||
|
container.leftPadding = -value * itemSize;
|
||||||
|
mask.leftMargin = -container.leftPadding;
|
||||||
|
return super.set_diff(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
override private function onMouseWheel(value:Int):Void {
|
||||||
|
offset = offset + value;
|
||||||
|
}
|
||||||
|
}
|
||||||
26
haxework/gui/list/HScrollSkin.hx
Executable file
26
haxework/gui/list/HScrollSkin.hx
Executable file
@@ -0,0 +1,26 @@
|
|||||||
|
package haxework.gui.list;
|
||||||
|
|
||||||
|
import haxework.gui.skin.ISkin;
|
||||||
|
import flash.display.Sprite;
|
||||||
|
import flash.display.Graphics;
|
||||||
|
|
||||||
|
class HScrollSkin implements ISkin<Sprite, ScrollView> {
|
||||||
|
|
||||||
|
public var foreColor(default, default):Int;
|
||||||
|
public var backColor(default, default):Int;
|
||||||
|
|
||||||
|
public function new(?foreColor:Int = 0xffffff, ?backColor:Int = 0x707070) {
|
||||||
|
this.foreColor = foreColor;
|
||||||
|
this.backColor = backColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function draw(view:ScrollView):Void {
|
||||||
|
var graphics:Graphics = view.content.graphics;
|
||||||
|
graphics.clear();
|
||||||
|
graphics.beginFill(backColor);
|
||||||
|
graphics.drawRect(0, 0, view.width, view.height);
|
||||||
|
graphics.beginFill(foreColor);
|
||||||
|
graphics.drawRect(view.width * view.position, 0, view.width * view.ratio, view.height);
|
||||||
|
graphics.endFill();
|
||||||
|
}
|
||||||
|
}
|
||||||
23
haxework/gui/list/HScrollView.hx
Executable file
23
haxework/gui/list/HScrollView.hx
Executable file
@@ -0,0 +1,23 @@
|
|||||||
|
package haxework.gui.list;
|
||||||
|
|
||||||
|
import haxework.gui.list.ScrollView.ScrollListener;
|
||||||
|
import flash.geom.Point;
|
||||||
|
import haxework.gui.list.HScrollSkin;
|
||||||
|
|
||||||
|
class HScrollView extends ScrollView {
|
||||||
|
|
||||||
|
public function new() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
override private function onMouseDown(p:Point):Void {
|
||||||
|
mousePosition = p.x - width * position;
|
||||||
|
}
|
||||||
|
|
||||||
|
override private function onMouseMove(p:Point):Void {
|
||||||
|
position = (p.x - mousePosition) / width;
|
||||||
|
dispatcher.dispatch(function(listener:ScrollListener):Void {
|
||||||
|
listener.onScroll(position);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,8 @@
|
|||||||
package haxework.gui.list;
|
package haxework.gui.list;
|
||||||
|
|
||||||
|
import haxework.gui.skin.ColorSkin;
|
||||||
|
import haxework.gui.core.VAlign;
|
||||||
|
import haxework.gui.layout.ILayout;
|
||||||
import haxework.utils.NumberUtil;
|
import haxework.utils.NumberUtil;
|
||||||
import haxework.dispath.Dispatcher;
|
import haxework.dispath.Dispatcher;
|
||||||
import haxework.dispath.IDispatcher;
|
import haxework.dispath.IDispatcher;
|
||||||
@@ -9,48 +12,73 @@ 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 implements ScrollListener {
|
class ListView<V:View<Dynamic>, D> extends GroupView implements ScrollListener {
|
||||||
|
|
||||||
public var data(default, set):Array<D>;
|
public var data(default, set):Array<D>;
|
||||||
public var renderer(null, set):IRenderer<Dynamic, 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>>;
|
public var dispatcher(default, null):IDispatcher<ListViewListener<V, D>>;
|
||||||
|
public var scroll(default, set):ScrollView;
|
||||||
|
|
||||||
private var scroll:ScrollView;
|
private var container:GroupView;
|
||||||
|
private var mask:SpriteView;
|
||||||
|
private var itemSize:Float;
|
||||||
|
private var diff(default, set):Float;
|
||||||
private var size(default, set):Int;
|
private var size(default, set):Int;
|
||||||
|
|
||||||
private var items:Array<ListItem<V, D>>;
|
private var items:Array<ListItem<V, D>>;
|
||||||
private var itemsListeners:Map<ListItem<V, D>, MouseEvent->Void>;
|
private var itemsListeners:Map<ListItem<V, D>, MouseEvent->Void>;
|
||||||
|
|
||||||
public function new() {
|
public function new(layout:ILayout, otherLayout:ILayout) {
|
||||||
super();
|
super(otherLayout);
|
||||||
|
container = new GroupView(layout);
|
||||||
|
container.pWidth = 100;
|
||||||
|
container.pHeight = 100;
|
||||||
|
addView(container);
|
||||||
|
mask = new SpriteView();
|
||||||
|
mask.pWidth = 100;
|
||||||
|
mask.pHeight = 100;
|
||||||
|
mask.inLayout = false;
|
||||||
|
mask.skin = new ColorSkin(0xffffff);
|
||||||
|
container.content.mask = mask.content;
|
||||||
|
container.addView(mask);
|
||||||
dispatcher = new Dispatcher<ListViewListener<V, D>>();
|
dispatcher = new Dispatcher<ListViewListener<V, D>>();
|
||||||
|
itemSize = 0;
|
||||||
offset = 0;
|
offset = 0;
|
||||||
scroll = new ScrollView();
|
diff = 0;
|
||||||
scroll.dispatcher.addListener(this);
|
|
||||||
scroll.inLayout = false;
|
|
||||||
scroll.pHeight = 100;
|
|
||||||
scroll.width = 10;
|
|
||||||
scroll.hAlign = HAlign.RIGHT;
|
|
||||||
scroll.position = 0;
|
|
||||||
scroll.ratio = 1;
|
|
||||||
scroll.rightMargin = -12;
|
|
||||||
rightPadding = 12;
|
|
||||||
addView(scroll);
|
|
||||||
items = new Array<ListItem<V, D>>();
|
items = new Array<ListItem<V, D>>();
|
||||||
itemsListeners = new Map<ListItem<V, D>, MouseEvent->Void>();
|
itemsListeners = new Map<ListItem<V, D>, MouseEvent->Void>();
|
||||||
content.addEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheel);
|
content.addEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheelEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function set_scroll(value:ScrollView):ScrollView {
|
||||||
|
if (scroll != null) {
|
||||||
|
scroll.dispatcher.removeListener(this);
|
||||||
|
removeView(scroll);
|
||||||
|
}
|
||||||
|
scroll = value;
|
||||||
|
if (scroll != null) {
|
||||||
|
scroll.dispatcher.addListener(this);
|
||||||
|
addView(scroll);
|
||||||
|
}
|
||||||
|
invalidate();
|
||||||
|
return scroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onScroll(position:Float):Void {
|
public function onScroll(position:Float):Void {
|
||||||
offset = Math.round(data.length * position);
|
var x:Float = data.length * position;
|
||||||
|
offset = Math.round(x) - 1;
|
||||||
|
diff = (x - offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function onMouseWheel(event:MouseEvent):Void {
|
private function onMouseWheelEvent(event:MouseEvent):Void {
|
||||||
offset = offset - event.delta * 3;
|
diff = 0;
|
||||||
|
onMouseWheel(event.delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function onMouseWheel(value:Int):Void {}
|
||||||
|
|
||||||
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);
|
value = NumberUtil.limitInt(value, 0, data == null ? 0 : data.length - size);
|
||||||
if (offset != value) {
|
if (offset != value) {
|
||||||
@@ -88,11 +116,12 @@ class ListView<V:View<Dynamic>, D> extends VGroupView implements ScrollListener
|
|||||||
|
|
||||||
override public function update():Void {
|
override public function update():Void {
|
||||||
super.update();
|
super.update();
|
||||||
var item:ListItem<V, D> = renderer.factory();
|
recalcSize(renderer.factory());
|
||||||
size = Math.round(Math.max(0, height / item.view.height));
|
|
||||||
render();
|
render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function recalcSize(item:ListItem<V, D>):Void {}
|
||||||
|
|
||||||
private function set_size(value:Int):Int {
|
private function set_size(value:Int):Int {
|
||||||
if (size != value) {
|
if (size != value) {
|
||||||
size = value;
|
size = value;
|
||||||
@@ -102,20 +131,25 @@ class ListView<V:View<Dynamic>, D> extends VGroupView implements ScrollListener
|
|||||||
var item:ListItem<V, D> = renderer.factory();
|
var item:ListItem<V, D> = renderer.factory();
|
||||||
items.push(item);
|
items.push(item);
|
||||||
setClickListener(item);
|
setClickListener(item);
|
||||||
addView(item.view);
|
container.addView(item.view);
|
||||||
}
|
}
|
||||||
} else if (diff < 0) {
|
} else if (diff < 0) {
|
||||||
for (i in 0...-diff) {
|
for (i in 0...-diff) {
|
||||||
var item:ListItem<V, D> = items.pop();
|
var item:ListItem<V, D> = items.pop();
|
||||||
item.view.content.removeEventListener(MouseEvent.CLICK, itemsListeners.get(item));
|
item.view.content.removeEventListener(MouseEvent.CLICK, itemsListeners.get(item));
|
||||||
itemsListeners.remove(item);
|
itemsListeners.remove(item);
|
||||||
removeView(item.view);
|
container.removeView(item.view);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function set_diff(value:Float):Float {
|
||||||
|
diff = value;
|
||||||
|
return diff;
|
||||||
|
}
|
||||||
|
|
||||||
private function setClickListener(item:ListItem<V, D>):Void {
|
private function setClickListener(item:ListItem<V, D>):Void {
|
||||||
var listener:MouseEvent->Void = function(event:MouseEvent):Void {
|
var listener:MouseEvent->Void = function(event:MouseEvent):Void {
|
||||||
dispatcher.dispatch(function(listener:ListViewListener<V, D>):Void {
|
dispatcher.dispatch(function(listener:ListViewListener<V, D>):Void {
|
||||||
|
|||||||
@@ -5,10 +5,6 @@ import flash.geom.Point;
|
|||||||
import haxework.dispath.Dispatcher;
|
import haxework.dispath.Dispatcher;
|
||||||
import haxework.dispath.IDispatcher;
|
import haxework.dispath.IDispatcher;
|
||||||
import flash.events.MouseEvent;
|
import flash.events.MouseEvent;
|
||||||
import flash.display.Graphics;
|
|
||||||
import flash.display.Sprite;
|
|
||||||
import haxework.gui.skin.ISkin;
|
|
||||||
import haxework.gui.View;
|
|
||||||
|
|
||||||
class ScrollView extends SpriteView {
|
class ScrollView extends SpriteView {
|
||||||
|
|
||||||
@@ -21,31 +17,34 @@ class ScrollView extends SpriteView {
|
|||||||
|
|
||||||
public function new() {
|
public function new() {
|
||||||
super();
|
super();
|
||||||
|
content.buttonMode = true;
|
||||||
|
position = 0;
|
||||||
|
ratio = 1;
|
||||||
dispatcher = new Dispatcher<ScrollListener>();
|
dispatcher = new Dispatcher<ScrollListener>();
|
||||||
skin = untyped new ScrollSkin();
|
content.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDownEvent);
|
||||||
content.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function onMouseDown(event:MouseEvent):Void {
|
private function onMouseDownEvent(event:MouseEvent):Void {
|
||||||
content.stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
|
content.stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMoveEvent);
|
||||||
content.stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
|
content.stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUpEvent);
|
||||||
var p:Point = content.globalToLocal(new Point(event.stageX, event.stageY));
|
var p:Point = content.globalToLocal(new Point(event.stageX, event.stageY));
|
||||||
mousePosition = p.y - height * position;
|
onMouseDown(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function onMouseMove(event:MouseEvent):Void {
|
private function onMouseMoveEvent(event:MouseEvent):Void {
|
||||||
var p:Point = content.globalToLocal(new Point(event.stageX, event.stageY));
|
var p:Point = content.globalToLocal(new Point(event.stageX, event.stageY));
|
||||||
position = (p.y - mousePosition) / height;
|
onMouseMove(p);
|
||||||
dispatcher.dispatch(function(listener:ScrollListener):Void {
|
|
||||||
listener.onScroll(position);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function onMouseUp(event:MouseEvent):Void {
|
private function onMouseUpEvent(event:MouseEvent):Void {
|
||||||
content.stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
|
content.stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMoveEvent);
|
||||||
content.stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
|
content.stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUpEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function onMouseDown(p:Point):Void {}
|
||||||
|
|
||||||
|
private function onMouseMove(p:Point):Void {}
|
||||||
|
|
||||||
private function set_position(value:Float):Float {
|
private function set_position(value:Float):Float {
|
||||||
value = NumberUtil.limitFloat(value, 0, 1 - ratio);
|
value = NumberUtil.limitFloat(value, 0, 1 - ratio);
|
||||||
if (position != value) {
|
if (position != value) {
|
||||||
@@ -64,27 +63,6 @@ class ScrollView extends SpriteView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ScrollSkin implements ISkin<Sprite, ScrollView> {
|
|
||||||
|
|
||||||
public var foreColor:Int;
|
|
||||||
public var backColor:Int;
|
|
||||||
|
|
||||||
public function new() {
|
|
||||||
foreColor = 0xffffff;
|
|
||||||
backColor = 0x505050;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function draw(view:ScrollView):Void {
|
|
||||||
var graphics:Graphics = view.content.graphics;
|
|
||||||
graphics.clear();
|
|
||||||
graphics.beginFill(backColor);
|
|
||||||
graphics.drawRect(0, 0, view.width, view.height);
|
|
||||||
graphics.beginFill(foreColor);
|
|
||||||
graphics.drawRect(0, view.height * view.position, view.width, view.height * view.ratio);
|
|
||||||
graphics.endFill();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ScrollListener {
|
interface ScrollListener {
|
||||||
public function onScroll(position:Float):Void;
|
public function onScroll(position:Float):Void;
|
||||||
}
|
}
|
||||||
33
haxework/gui/list/VListView.hx
Executable file
33
haxework/gui/list/VListView.hx
Executable file
@@ -0,0 +1,33 @@
|
|||||||
|
package haxework.gui.list;
|
||||||
|
|
||||||
|
import haxework.gui.core.VAlign;
|
||||||
|
import haxework.gui.list.ListView.ListItem;
|
||||||
|
import haxework.gui.layout.VerticalLayout;
|
||||||
|
import haxework.gui.list.VScrollView;
|
||||||
|
import haxework.gui.core.HAlign;
|
||||||
|
import haxework.gui.layout.HorizontalLayout;
|
||||||
|
|
||||||
|
class VListView<V:View<Dynamic>, D> extends ListView<V, D> {
|
||||||
|
|
||||||
|
public function new() {
|
||||||
|
super(new VerticalLayout(), new HorizontalLayout());
|
||||||
|
container.layoutHAlign = HAlign.CENTER;
|
||||||
|
container.layoutVAlign = VAlign.TOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
override private function recalcSize(item:ListItem<V, D>):Void {
|
||||||
|
var view:IView<Dynamic> = item.view;
|
||||||
|
itemSize = view.height + view.topMargin + view.bottomMargin + layoutMargin;
|
||||||
|
size = Math.round(Math.max(0, height / itemSize)) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
override private function set_diff(value:Float):Float {
|
||||||
|
container.topPadding = -value * itemSize;
|
||||||
|
mask.topMargin = -container.topPadding;
|
||||||
|
return super.set_diff(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
override private function onMouseWheel(value:Int):Void {
|
||||||
|
offset = offset - value;
|
||||||
|
}
|
||||||
|
}
|
||||||
26
haxework/gui/list/VScrollSkin.hx
Executable file
26
haxework/gui/list/VScrollSkin.hx
Executable file
@@ -0,0 +1,26 @@
|
|||||||
|
package haxework.gui.list;
|
||||||
|
|
||||||
|
import haxework.gui.skin.ISkin;
|
||||||
|
import flash.display.Sprite;
|
||||||
|
import flash.display.Graphics;
|
||||||
|
|
||||||
|
class VScrollSkin implements ISkin<Sprite, ScrollView> {
|
||||||
|
|
||||||
|
public var foreColor(default, default):Int;
|
||||||
|
public var backColor(default, default):Int;
|
||||||
|
|
||||||
|
public function new(?foreColor:Int = 0xffffff, ?backColor:Int = 0x707070) {
|
||||||
|
this.foreColor = foreColor;
|
||||||
|
this.backColor = backColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function draw(view:ScrollView):Void {
|
||||||
|
var graphics:Graphics = view.content.graphics;
|
||||||
|
graphics.clear();
|
||||||
|
graphics.beginFill(backColor);
|
||||||
|
graphics.drawRect(0, 0, view.width, view.height);
|
||||||
|
graphics.beginFill(foreColor);
|
||||||
|
graphics.drawRect(0, view.height * view.position, view.width, view.height * view.ratio);
|
||||||
|
graphics.endFill();
|
||||||
|
}
|
||||||
|
}
|
||||||
23
haxework/gui/list/VScrollView.hx
Executable file
23
haxework/gui/list/VScrollView.hx
Executable file
@@ -0,0 +1,23 @@
|
|||||||
|
package haxework.gui.list;
|
||||||
|
|
||||||
|
import haxework.gui.list.ScrollView.ScrollListener;
|
||||||
|
import flash.geom.Point;
|
||||||
|
import haxework.gui.list.VScrollSkin;
|
||||||
|
|
||||||
|
class VScrollView extends ScrollView {
|
||||||
|
|
||||||
|
public function new() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
override private function onMouseDown(p:Point):Void {
|
||||||
|
mousePosition = p.y - height * position;
|
||||||
|
}
|
||||||
|
|
||||||
|
override private function onMouseMove(p:Point):Void {
|
||||||
|
position = (p.y - mousePosition) / height;
|
||||||
|
dispatcher.dispatch(function(listener:ScrollListener):Void {
|
||||||
|
listener.onScroll(position);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,10 @@
|
|||||||
package haxework.gui.skin;
|
package haxework.gui.skin;
|
||||||
|
|
||||||
|
import flash.geom.Rectangle;
|
||||||
|
import flash.geom.Matrix;
|
||||||
import flash.display.BitmapData;
|
import flash.display.BitmapData;
|
||||||
import haxework.gui.utils.ColorUtils;
|
import haxework.gui.utils.ColorUtils;
|
||||||
|
import haxework.gui.utils.DrawUtil;
|
||||||
import haxework.gui.ButtonView.ButtonState;
|
import haxework.gui.ButtonView.ButtonState;
|
||||||
import flash.display.Graphics;
|
import flash.display.Graphics;
|
||||||
import flash.display.Sprite;
|
import flash.display.Sprite;
|
||||||
@@ -12,11 +15,15 @@ class BitmapSkin implements ISkin<Sprite, SpriteView> implements ISize {
|
|||||||
public var height(default, null):Float;
|
public var height(default, null):Float;
|
||||||
|
|
||||||
public var image(null, set):BitmapData;
|
public var image(null, set):BitmapData;
|
||||||
|
public var color(default, default):Int;
|
||||||
|
public var fillType(default, default):FillType;
|
||||||
|
|
||||||
public function new(?image:BitmapData = null) {
|
public function new(?image:BitmapData = null, ?fillType = null, ?color = -1) {
|
||||||
if (image != null) {
|
if (image != null) {
|
||||||
this.image = image;
|
this.image = image;
|
||||||
}
|
}
|
||||||
|
this.fillType = fillType;
|
||||||
|
this.color = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function set_image(value:BitmapData):BitmapData {
|
private function set_image(value:BitmapData):BitmapData {
|
||||||
@@ -30,11 +37,7 @@ class BitmapSkin implements ISkin<Sprite, SpriteView> implements ISize {
|
|||||||
|
|
||||||
public function draw(view:SpriteView):Void {
|
public function draw(view:SpriteView):Void {
|
||||||
if (image == null) return;
|
if (image == null) return;
|
||||||
var graphics:Graphics = view.content.graphics;
|
DrawUtil.draw(view.content.graphics, image, new Rectangle(0, 0, view.width, view.height), fillType, color);
|
||||||
graphics.clear();
|
|
||||||
graphics.beginBitmapFill(image, null, false, true);
|
|
||||||
graphics.drawRect(0, 0, view.width, view.height);
|
|
||||||
graphics.endFill();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
package haxework.gui.skin;
|
package haxework.gui.skin;
|
||||||
|
|
||||||
|
import haxework.gui.utils.DrawUtil;
|
||||||
|
import flash.geom.Rectangle;
|
||||||
import flash.display.BitmapData;
|
import flash.display.BitmapData;
|
||||||
import haxework.gui.utils.ColorUtils;
|
import haxework.gui.utils.ColorUtils;
|
||||||
import haxework.gui.ButtonView.ButtonState;
|
import haxework.gui.ButtonView.ButtonState;
|
||||||
@@ -11,6 +13,8 @@ class ButtonBitmapSkin implements ISkin<Sprite, ButtonView> implements ISize {
|
|||||||
public var width(default, null):Float;
|
public var width(default, null):Float;
|
||||||
public var height(default, null):Float;
|
public var height(default, null):Float;
|
||||||
|
|
||||||
|
public var fillType(default, default):FillType;
|
||||||
|
public var color(default, default):Int;
|
||||||
public var image(null, set):BitmapData;
|
public var image(null, set):BitmapData;
|
||||||
public var upImage(null, set):BitmapData;
|
public var upImage(null, set):BitmapData;
|
||||||
public var overImage(null, set):BitmapData;
|
public var overImage(null, set):BitmapData;
|
||||||
@@ -18,11 +22,13 @@ class ButtonBitmapSkin implements ISkin<Sprite, ButtonView> implements ISize {
|
|||||||
|
|
||||||
private var images:Map<ButtonState, BitmapData>;
|
private var images:Map<ButtonState, BitmapData>;
|
||||||
|
|
||||||
public function new(?image:BitmapData = null) {
|
public function new(?image:BitmapData = null, ?fillType = null, ?color = -1) {
|
||||||
images = new Map<ButtonState, BitmapData>();
|
images = new Map<ButtonState, BitmapData>();
|
||||||
if (image != null) {
|
if (image != null) {
|
||||||
this.image = image;
|
this.image = image;
|
||||||
}
|
}
|
||||||
|
this.fillType = fillType;
|
||||||
|
this.color = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function set_image(value:BitmapData):BitmapData {
|
private function set_image(value:BitmapData):BitmapData {
|
||||||
@@ -55,11 +61,7 @@ class ButtonBitmapSkin implements ISkin<Sprite, ButtonView> implements ISize {
|
|||||||
public function draw(view:ButtonView):Void {
|
public function draw(view:ButtonView):Void {
|
||||||
if (images == null) return;
|
if (images == null) return;
|
||||||
var image:BitmapData = images.get(view.state);
|
var image:BitmapData = images.get(view.state);
|
||||||
var graphics:Graphics = view.content.graphics;
|
DrawUtil.draw(view.content.graphics, image, new Rectangle(0, 0, view.width, view.height), fillType, color);
|
||||||
graphics.clear();
|
|
||||||
graphics.beginBitmapFill(image, null, false, true);
|
|
||||||
graphics.drawRect(0, 0, view.width, view.height);
|
|
||||||
graphics.endFill();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
45
haxework/gui/utils/DrawUtil.hx
Executable file
45
haxework/gui/utils/DrawUtil.hx
Executable file
@@ -0,0 +1,45 @@
|
|||||||
|
package haxework.gui.utils;
|
||||||
|
|
||||||
|
import flash.geom.Matrix;
|
||||||
|
import flash.geom.Rectangle;
|
||||||
|
import flash.display.BitmapData;
|
||||||
|
import flash.display.Graphics;
|
||||||
|
|
||||||
|
enum FillType {
|
||||||
|
DEFAULT;
|
||||||
|
COVER;
|
||||||
|
CONTAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
class DrawUtil {
|
||||||
|
|
||||||
|
public static function draw(graphics:Graphics, image:BitmapData, rect:Rectangle, ?fillType:FillType = null, ?color:Int = -1):Void {
|
||||||
|
if (fillType == null) fillType = FillType.DEFAULT;
|
||||||
|
graphics.clear();
|
||||||
|
if (color > -1) {
|
||||||
|
graphics.beginFill(color);
|
||||||
|
graphics.drawRect(rect.x, rect.y, rect.width, rect.height);
|
||||||
|
graphics.endFill();
|
||||||
|
}
|
||||||
|
var m:Matrix = new Matrix();
|
||||||
|
var s:Float = 1.0;
|
||||||
|
switch (fillType) {
|
||||||
|
case FillType.DEFAULT:
|
||||||
|
case FillType.CONTAIN:
|
||||||
|
s = Math.min(rect.width / image.width, rect.height / image.height);
|
||||||
|
case FillType.COVER:
|
||||||
|
s = Math.max(rect.width / image.width, rect.height / image.height);
|
||||||
|
}
|
||||||
|
m.scale(s, s);
|
||||||
|
var dx:Float = (rect.width - image.width * s) / 2;
|
||||||
|
var dy:Float = (rect.height - image.height * s) / 2;
|
||||||
|
m.translate(dx, dy);
|
||||||
|
graphics.beginBitmapFill(image, m, false, false);
|
||||||
|
rect.x = Math.max(rect.x, m.tx);
|
||||||
|
rect.y = Math.max(rect.y, m.ty);
|
||||||
|
rect.width = Math.min(rect.width, image.width * s);
|
||||||
|
rect.height = Math.min(rect.height, image.height * s);
|
||||||
|
graphics.drawRect(rect.x, rect.y, rect.width, rect.height);
|
||||||
|
graphics.endFill();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user