UNPKG

uicore-ts

Version:

UICore is a library to build native-like user interfaces using pure Typescript. No HTML is needed at all. Components are described as TS classes and all user interactions are handled explicitly. This library is strongly inspired by the UIKit framework tha

201 lines (96 loc) 4.58 kB
import { IS_NOT, nil, NO, YES } from "./UIObject" import { UIPoint } from "./UIPoint" import { UIRectangle } from "./UIRectangle" import { UIView } from "./UIView" export class UIScrollView extends UIView { containerView: UIView _contentOffset: UIPoint = new UIPoint(0, 0) _contentScale: number = 1 _pointerDown?: boolean _scrollEnabled: boolean = YES override _previousClientPoint: UIPoint = nil _intrinsicContentFrame?: UIRectangle constructor(elementID: string, viewHTMLElement?: HTMLElement) { super(elementID, viewHTMLElement) this.containerView = new UIView(elementID + "ContainerView") super.addSubview(this.containerView) this.style.overflow = "hidden" this.pausesPointerEvents = NO //YES; this.addTargetForControlEvent(UIView.controlEvent.PointerDown, () => this._pointerDown = YES) this.addTargetForControlEvent(UIView.controlEvent.PointerUp, () => { this._pointerDown = NO this._previousClientPoint = nil scrollStopped() }) function scrollStopped() { // Handle paging if needed } this.addTargetForControlEvent(UIView.controlEvent.PointerMove, (sender, event) => { if (!(this._pointerDown && this._scrollEnabled && this._enabled)) { return } const currentClientPoint = new UIPoint(nil, nil) if ((window as any).MouseEvent && event instanceof MouseEvent) { currentClientPoint.x = (event as MouseEvent).clientX currentClientPoint.y = (event as MouseEvent).clientY } if ((window as any).TouchEvent && event instanceof TouchEvent) { const touchEvent: TouchEvent = event if (touchEvent.touches.length != 1) { this._pointerDown = NO this._previousClientPoint = nil scrollStopped() return } currentClientPoint.x = touchEvent.touches[0].clientX currentClientPoint.y = touchEvent.touches[0].clientY } if (IS_NOT(this._previousClientPoint)) { this._previousClientPoint = currentClientPoint return } const changePoint = currentClientPoint.copy().subtract(this._previousClientPoint) if (this.containerView.bounds.width <= this.bounds.width) { changePoint.x = 0 } if (0 < this.contentOffset.x + changePoint.x) { changePoint.x = -this.contentOffset.x } if (this.contentOffset.x + changePoint.x < -this.bounds.width) { changePoint.x = -this.bounds.width - this.contentOffset.x } if (this.containerView.bounds.height <= this.bounds.height) { changePoint.y = 0 } if (0 < this.contentOffset.y + changePoint.y) { changePoint.y = -this.contentOffset.y } if (this.contentOffset.y + changePoint.y < -this.bounds.height) { changePoint.y = -this.bounds.height - this.contentOffset.y } this.contentOffset = this.contentOffset.add(changePoint) this._previousClientPoint = currentClientPoint }) } invalidateIntrinsicContentFrame() { this._intrinsicContentFrame = undefined } get contentOffset() { return this._contentOffset } set contentOffset(offset: UIPoint) { this._contentOffset = offset this.setNeedsLayout() } override layoutSubviews() { super.layoutSubviews() this.containerView.frame = this.containerView.bounds.offsetByPoint(this.contentOffset) } override hasSubview(view: UIView) { return this.containerView.hasSubview(view) } override addSubview(view: UIView) { this.containerView.addSubview(view) this.invalidateIntrinsicContentFrame() } }