[view] remove ScrollView, add scrolls to GroupView

This commit is contained in:
2019-07-18 17:55:55 +03:00
parent ddc8581445
commit ec42687d1b
14 changed files with 217 additions and 127 deletions

View File

@@ -1,12 +1,10 @@
--- ---
overflow.y: scroll
views: views:
- $type: haxework.view.ScrollView - id: data
geometry.stretch: true $type: haxework.view.data.DataView
view: layout:
id: data $type: haxework.view.layout.VerticalLayout
$type: haxework.view.data.DataView factory: ~factory
layout: geometry.width: 100%
$type: haxework.view.layout.VerticalLayout data: $r:any:data
factory: ~factory
geometry.width: 100%
data: $r:any:data

View File

@@ -1,14 +1,12 @@
--- ---
overflow.y: scroll
views: views:
- $type: haxework.view.ScrollView - id: data
geometry.stretch: true $type: haxework.view.data.DataView
view: geometry.padding: 4
id: data layout:
$type: haxework.view.data.DataView $type: haxework.view.layout.TailLayout
geometry.padding: 4 margin: 6
layout: factory: ~factory
$type: haxework.view.layout.TailLayout geometry.width: 100%
margin: 6 data: $r:any:data
factory: ~factory
geometry.width: 100%
data: $r:any:data

View File

@@ -1,82 +0,0 @@
package haxework.view;
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.events.MouseEvent;
import haxework.signal.Signal;
import haxework.view.geometry.Position;
import haxework.view.group.HGroupView;
import haxework.view.list.ScrollBarView;
import haxework.view.list.VScrollBarView;
import haxework.view.skin.Skin;
class ScrollView extends HGroupView {
public var view(default, set):IView<Dynamic>;
public var scroll(default, set):ScrollBarView;
public var ratio(default, null):Signal<Float> = new Signal();
public var position(default, set):Float = 0;
private var mask:Sprite;
public function new() {
super();
layout.overflow = true;
skin = Skin.transparent();
mask = new Sprite();
content.addChild(mask);
content.addEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheelEvent);
scroll = new VScrollBarView();
}
private function onMouseWheelEvent(event:MouseEvent):Void {
#if flash event.preventDefault(); #end
position -= event.delta * scroll.ratio / 3;
}
private function set_view(value:IView<Dynamic>):IView<Dynamic> {
view = value;
views = [view, scroll];
cast(view.content, DisplayObject).mask = mask;
return view;
}
private function set_scroll(value:ScrollBarView):ScrollBarView {
scroll = value;
views = [view, scroll];
ratio.connect(function(ratio) {
if (scroll.ratio == ratio) return;
scroll.ratio = ratio;
scroll.visible = ratio < 1;
scroll.geometry.position = ratio < 1 ? LAYOUT : ABSOLUTE;
});
scroll.onScroll.connect(function(position) this.position = position);
return scroll;
}
override public function set_views(value:Array<IView<Dynamic>>):Array<IView<Dynamic>> {
return super.set_views(value.filter(function(view) return view != null));
}
private function set_position(value:Float):Float {
position = Math.min(Math.max(0, value), 1 - (height / view.height));
if (height / view.height > 1) position = 0;
if (scroll != null) {
scroll.position = position;
}
toUpdate();
return position;
}
override public function update():Void {
super.update();
ratio.emit(height / view.height);
view.y = - position * view.height;
// mask redraw
mask.graphics.clear();
mask.graphics.beginFill(0xffffff);
mask.graphics.drawRect(0, 0, width, height);
mask.graphics.endFill();
}
}

View File

@@ -1,23 +1,137 @@
package haxework.view.group; package haxework.view.group;
import flash.display.DisplayObjectContainer; import flash.display.DisplayObjectContainer;
import flash.display.Sprite;
import flash.events.MouseEvent;
import haxework.signal.Signal;
import haxework.view.geometry.Position;
import haxework.view.layout.DefaultLayout; import haxework.view.layout.DefaultLayout;
import haxework.view.layout.ILayout; import haxework.view.layout.ILayout;
import haxework.view.list.HScrollBarView;
import haxework.view.list.ScrollBarView;
import haxework.view.list.VScrollBarView;
class OverflowControl {
public var overflow(default, set):Float = 0;
public var offset(default, set):Float = 0;
public var size(default, default):Float = 0;
public var scroll(null, null):ScrollBarView;
public var offsetSignal(default, null):Signal<Float>;
private var scrollFactory:Void -> ScrollBarView;
public function new(scrollFactory:Void -> ScrollBarView) {
this.scrollFactory = scrollFactory;
offsetSignal = new Signal();
}
private function set_offset(value:Float):Float {
if (offset != value) {
offset = checkOffset(value);
if (scroll != null) {
scroll.position = -offset / size / overflow;
}
offsetSignal.emit(offset);
}
return offset;
}
private function checkOffset(value:Float):Float {
if (value > 0) {
return 0;
} else if (value < -size * (overflow - 1)) {
return -size * (overflow - 1);
}
return value;
}
public function set_overflow(value:Float):Float {
if (overflow != value) {
overflow = value;
if (overflow > 1 && scroll == null) {
scroll = scrollFactory();
scroll.onScroll.connect(function(value) {
offset = value > 0 ? -value * overflow * size : 0;
});
}
if (scroll != null) {
scroll.ratio = 1 / overflow;
}
offset = checkOffset(offset);
}
return overflow;
}
}
@:style(true) class GroupView extends SpriteView implements IGroupView { @:style(true) class GroupView extends SpriteView implements IGroupView {
public var container(get, null):DisplayObjectContainer; public var container(null, null):DisplayObjectContainer;
public var views(default, set):Array<IView<Dynamic>>; public var views(default, set):Array<IView<Dynamic>>;
@:style public var layout(default, default):ILayout; @:style public var layout(default, default):ILayout;
@:style public var overflow(default, default):Overflow;
public function new(?layout:ILayout) { public var overflowX(default, set):Float;
public var overflowY(default, set):Float;
private var _mask:Sprite;
private var scrollX(get, null):HScrollBarView;
private var scrollY(get, null):VScrollBarView;
public var overflowControlX(default, null):OverflowControl;
public var overflowControlY(default, null):OverflowControl;
public function new(?layout:ILayout, ?overflow:Overflow) {
super(); super();
this.layout = layout == null ? new DefaultLayout() : layout; container = new Sprite();
content.addChild(container);
_mask = new Sprite();
content.addChild(_mask);
container.mask = _mask;
this.layout = layout != null ? layout : new DefaultLayout();
this.overflow = overflow != null ? overflow : new Overflow();
views = []; views = [];
overflowControlX = new OverflowControl(function() return scrollX);
overflowControlX.offsetSignal.connect(function(value) container.x = value);
overflowControlY = new OverflowControl(function() return scrollY);
overflowControlY.offsetSignal.connect(function(value) container.y = value);
content.addEventListener(MouseEvent.MOUSE_WHEEL, _onMouseWheelEvent);
} }
inline private function get_container():DisplayObjectContainer { private function get_scrollX():HScrollBarView {
return content; if (scrollX == null) {
scrollX = new HScrollBarView();
scrollX.geometry.position = Position.ABSOLUTE;
addView(scrollX);
container.removeChild(scrollX.content);
content.addChild(scrollX.content);
}
return scrollX;
}
private function get_scrollY():VScrollBarView {
if (scrollY == null) {
scrollY = new VScrollBarView();
scrollY.geometry.position = Position.ABSOLUTE;
addView(scrollY);
container.removeChild(scrollY.content);
content.addChild(scrollY.content);
}
return scrollY;
}
private function _onMouseWheelEvent(event:MouseEvent):Void {
if (overflowY > 1) {
#if flash event.preventDefault(); #end
overflowControlY.offset += event.delta * 15;
}
}
public function set_overflowX(value:Float):Float {
return overflowX = overflowControlX.overflow = value;
}
public function set_overflowY(value:Float):Float {
return overflowY = overflowControlY.overflow = value;
} }
override public function update():Void { override public function update():Void {
@@ -26,9 +140,15 @@ import haxework.view.layout.ILayout;
for (view in views) { for (view in views) {
view.update(); view.update();
if (view.index > -1) { if (view.index > -1) {
content.setChildIndex(view.content, view.index); container.setChildIndex(view.content, Std.int(Math.min(views.length - 1, view.index)));
} }
} }
overflowControlX.size = width;
overflowControlY.size = height;
_mask.graphics.clear();
_mask.graphics.beginFill(0, 1);
_mask.graphics.drawRect(0, 0, width, height);
_mask.graphics.endFill();
} }
public function set_views(value:Array<IView<Dynamic>>):Array<IView<Dynamic>> { public function set_views(value:Array<IView<Dynamic>>):Array<IView<Dynamic>> {
@@ -44,7 +164,7 @@ import haxework.view.layout.ILayout;
public function addView(view:IView<Dynamic>):IView<Dynamic> { public function addView(view:IView<Dynamic>):IView<Dynamic> {
views.push(view); views.push(view);
if (view.content != null) content.addChild(view.content); if (view.content != null) container.addChild(view.content);
view.parent = this; view.parent = this;
toUpdate(); toUpdate();
return view; return view;
@@ -53,7 +173,7 @@ import haxework.view.layout.ILayout;
public function insertView(view:IView<Dynamic>, index:Int):IView<Dynamic> { public function insertView(view:IView<Dynamic>, index:Int):IView<Dynamic> {
if (index < 0) index = views.length + index; if (index < 0) index = views.length + index;
views.insert(index, view); views.insert(index, view);
if (view.content != null) content.addChild(view.content); if (view.content != null) container.addChild(view.content);
view.parent = this; view.parent = this;
toUpdate(); toUpdate();
return view; return view;
@@ -61,7 +181,7 @@ import haxework.view.layout.ILayout;
public function addViewFirst(view:IView<Dynamic>):IView<Dynamic> { public function addViewFirst(view:IView<Dynamic>):IView<Dynamic> {
views.unshift(view); views.unshift(view);
content.addChild(view.content); container.addChild(view.content);
view.parent = this; view.parent = this;
toUpdate(); toUpdate();
return view; return view;
@@ -70,14 +190,22 @@ import haxework.view.layout.ILayout;
public function removeView(view:IView<Dynamic>):IView<Dynamic> { public function removeView(view:IView<Dynamic>):IView<Dynamic> {
view.parent = null; view.parent = null;
views.remove(view); views.remove(view);
if (view.content != null) content.removeChild(view.content); if (view.content != null) container.removeChild(view.content);
toUpdate(); toUpdate();
return view; return view;
} }
public function removeAllViews():Void { public function removeAllViews():Void {
if (views != null) while (views.length > 0) { /*if (views != null) while (views.length > 0) {
removeView(views[0]); removeView(views[0]);
}*/
if (views != null) {
for (i in 0...views.length) {
var view = views[i];
if (view != scrollX && view != scrollY) {
removeView(view);
}
}
} }
} }
} }

View File

@@ -1,12 +1,17 @@
package haxework.view.group; package haxework.view.group;
import flash.display.DisplayObjectContainer; import flash.display.DisplayObjectContainer;
import haxework.view.group.Overflow.Overflow;
import haxework.view.layout.ILayout; import haxework.view.layout.ILayout;
interface IGroupView extends IView<Dynamic> { interface IGroupView extends IView<Dynamic> {
public var layout(default, set):ILayout; public var layout(default, set):ILayout;
public var overflow(default, set):Overflow;
public var container(get, null):DisplayObjectContainer; public var overflowX(default, set):Float;
public var overflowY(default, set):Float;
public var container(null, null):DisplayObjectContainer;
public var views(default, set):Array<IView<Dynamic>>; public var views(default, set):Array<IView<Dynamic>>;
public function containsView(view:IView<Dynamic>):Bool; public function containsView(view:IView<Dynamic>):Bool;

View File

@@ -0,0 +1,17 @@
package haxework.view.group;
@:enum abstract OverflowType(String) from String to String {
var STRETCH = "stretch";
var SCROLL = "scroll";
var CROP = "crop";
}
@:style class Overflow {
@:style(STRETCH) public var x(default, default):OverflowType;
@:style(STRETCH) public var y(default, default):OverflowType;
public function new(?overflowX:OverflowType, ?overflowY:OverflowType) {
this.x = x;
this.y = y;
}
}

View File

@@ -4,6 +4,7 @@ import haxework.view.geometry.HAlign;
import haxework.view.geometry.Position; import haxework.view.geometry.Position;
import haxework.view.geometry.VAlign; import haxework.view.geometry.VAlign;
import haxework.view.group.IGroupView; import haxework.view.group.IGroupView;
import haxework.view.group.Overflow;
class DefaultLayout extends Layout { class DefaultLayout extends Layout {
@@ -19,7 +20,31 @@ class DefaultLayout extends Layout {
width = Math.max(width, size.width + view.geometry.margin.horizontal); width = Math.max(width, size.width + view.geometry.margin.horizontal);
height = Math.max(height, size.height + view.geometry.margin.horizontal); height = Math.max(height, size.height + view.geometry.margin.horizontal);
} }
if (!overflow) group.setSize(width, height, "group"); setGroupSize(group, width, height);
}
private function setGroupSize(group:IGroupView, width:Float, height:Float):Void {
group.setSize(
switch group.overflow.x {
case STRETCH: width;
case _: 0;
},
switch group.overflow.y {
case STRETCH: height;
case _: 0;
},
"group"
);
switch group.overflow.x {
case SCROLL:
group.overflowX = width / group.width;
case _:
}
switch group.overflow.y {
case SCROLL:
group.overflowY = height / group.height;
case _:
}
} }
private function filterViews(group:IGroupView, views:Array<IView<Dynamic>>):Array<IView<Dynamic>> { private function filterViews(group:IGroupView, views:Array<IView<Dynamic>>):Array<IView<Dynamic>> {

View File

@@ -25,7 +25,7 @@ class HorizontalLayout extends DefaultLayout {
maxSize = Math.max(maxSize, view.size.toSize("percent").height + view.geometry.padding.vertical + view.geometry.margin.vertical); maxSize = Math.max(maxSize, view.size.toSize("percent").height + view.geometry.padding.vertical + view.geometry.margin.vertical);
} }
if (!overflow) group.setSize(fixedSize, maxSize, "group"); setGroupSize(group, fixedSize, maxSize);
leftSize -= fixedSize; leftSize -= fixedSize;
for (view in views) { for (view in views) {

View File

@@ -9,7 +9,6 @@ interface ILayout extends IStylable {
public var hAlign(get, set):HAlign; public var hAlign(get, set):HAlign;
public var vAlign(get, set):VAlign; public var vAlign(get, set):VAlign;
public var margin(get, set):Null<Float>; public var margin(get, set):Null<Float>;
public var overflow(get, set):Null<Bool>;
public function place(group:IGroupView, views:Array<IView<Dynamic>>):Void; public function place(group:IGroupView, views:Array<IView<Dynamic>>):Void;

View File

@@ -9,11 +9,8 @@ import haxework.view.group.IGroupView;
@:style(HAlign.NONE) public var hAlign(default, default):HAlign; @:style(HAlign.NONE) public var hAlign(default, default):HAlign;
@:style(VAlign.NONE) public var vAlign(default, default):VAlign; @:style(VAlign.NONE) public var vAlign(default, default):VAlign;
@:style(0) public var margin(default, default):Null<Float>; @:style(0) public var margin(default, default):Null<Float>;
@:style(false) public var overflow(default, default):Null<Bool>;
public function new() { public function new() {}
}
public function place(group:IGroupView, views:Array<IView<Dynamic>>):Void {} public function place(group:IGroupView, views:Array<IView<Dynamic>>):Void {}

View File

@@ -25,7 +25,7 @@ class VerticalLayout extends DefaultLayout {
maxSize = Math.max(maxSize, view.size.toSize("percent").width + view.geometry.padding.horizontal + view.geometry.margin.horizontal); maxSize = Math.max(maxSize, view.size.toSize("percent").width + view.geometry.padding.horizontal + view.geometry.margin.horizontal);
} }
if (!overflow) group.setSize(maxSize, fixedSize, "group"); setGroupSize(group, maxSize, fixedSize);
leftSize -= fixedSize; leftSize -= fixedSize;
for (view in views) { for (view in views) {

View File

@@ -1,5 +1,6 @@
package haxework.view.list; package haxework.view.list;
import haxework.view.group.Overflow;
import flash.events.MouseEvent; import flash.events.MouseEvent;
import haxework.signal.Signal; import haxework.signal.Signal;
import haxework.utils.NumberUtil; import haxework.utils.NumberUtil;
@@ -50,7 +51,7 @@ class ListView<D> extends GroupView {
addView(main); addView(main);
box = new GroupView(layout); box = new GroupView(layout);
box.geometry.stretch = true; box.geometry.stretch = true;
box.layout.overflow = true; box.overflow.y = CROP;
main.addView(box); main.addView(box);
mask = new SpriteView(); mask = new SpriteView();
mask.geometry.stretch = true; mask.geometry.stretch = true;

View File

@@ -5,8 +5,8 @@ import haxework.color.ColorUtil;
import haxework.view.list.ScrollBarView; import haxework.view.list.ScrollBarView;
@:style class VScrollBarSkin implements ISkin<ScrollBarView> { @:style class VScrollBarSkin implements ISkin<ScrollBarView> {
@:style(0xff0000) public var foreColor(default, default):Null<Color>; @:style(0) public var foreColor(default, default):Null<Color>;
@:style(0xffff00) public var backColor(default, default):Null<Color>; @:style(0) public var backColor(default, default):Null<Color>;
public function new(?foreColor:Color, ?backColor:Color) { public function new(?foreColor:Color, ?backColor:Color) {
this.foreColor = foreColor; this.foreColor = foreColor;

View File

@@ -1,5 +1,7 @@
package haxework.view.theme; package haxework.view.theme;
import haxework.view.geometry.VAlign;
import haxework.view.geometry.HAlign;
import flash.text.Font; import flash.text.Font;
import flash.text.FontType; import flash.text.FontType;
import haxework.color.Color; import haxework.color.Color;
@@ -124,12 +126,14 @@ class Theme implements ITheme {
"skin.backColor" => colors.dark, "skin.backColor" => colors.dark,
"geometry.width" => SizeValue.fromFloat(10), "geometry.width" => SizeValue.fromFloat(10),
"geometry.height" => SizeValue.fromString("100%"), "geometry.height" => SizeValue.fromString("100%"),
"geometry.hAlign" => HAlign.RIGHT,
])); ]));
register(new Style("scroll.horizontal", [ register(new Style("scroll.horizontal", [
"skin.foreColor" => colors.light, "skin.foreColor" => colors.light,
"skin.backColor" => colors.dark, "skin.backColor" => colors.dark,
"geometry.width" => SizeValue.fromString("100%"), "geometry.width" => SizeValue.fromString("100%"),
"geometry.height" => SizeValue.fromFloat(10), "geometry.height" => SizeValue.fromFloat(10),
"geometry.vAlign" => VAlign.BOTTOM,
])); ]));
} }