refact view and groupview

This commit is contained in:
pengfei.zhou 2019-11-12 17:18:10 +08:00
parent 3d4605c497
commit dab3c00b4c
6 changed files with 83 additions and 220 deletions

View File

@ -25,9 +25,9 @@ import androidx.appcompat.app.AppCompatActivity;
import java.io.IOException; import java.io.IOException;
import pub.doric.dev.DevPanel;
import pub.doric.DoricContext; import pub.doric.DoricContext;
import pub.doric.DoricDriver; import pub.doric.DoricDriver;
import pub.doric.dev.DevPanel;
import pub.doric.dev.LocalServer; import pub.doric.dev.LocalServer;
import pub.doric.dev.event.EnterDebugEvent; import pub.doric.dev.event.EnterDebugEvent;
import pub.doric.dev.event.QuitDebugEvent; import pub.doric.dev.event.QuitDebugEvent;

View File

@ -16,6 +16,7 @@
export * from "./src/ui/view" export * from "./src/ui/view"
export * from "./src/ui/layout" export * from "./src/ui/layout"
export * from "./src/ui/listview" export * from "./src/ui/listview"
export * from "./src/ui/widgets"
export * from "./src/ui/panel" export * from "./src/ui/panel"
export * from "./src/ui/declarative" export * from "./src/ui/declarative"
export * from "./src/util/color" export * from "./src/util/color"

View File

@ -13,8 +13,9 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import { Text, Image, LayoutConfig, View, IText, IImage } from './view' import { View, } from './view'
import { Stack, HLayout, VLayout } from './layout' import { Stack, HLayout, VLayout } from './layout'
import { IText, IImage, Text, Image } from './widgets'
export function text(config: IText) { export function text(config: IText) {
const ret = new Text const ret = new Text

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { View, Property, SuperView, Group, LayoutSpec } from "./view"; import { View, Property, LayoutSpec, Superview } from "./view";
import { Model } from "../util/types"; import { Model } from "../util/types";
import { O_TRUNC } from "constants"; import { O_TRUNC } from "constants";
import { Stack } from "./layout"; import { Stack } from "./layout";
@ -35,12 +35,9 @@ export class ListItem extends Stack {
@Property @Property
identifier?: string identifier?: string
list!: List list!: List
onChildPropertyChanged(child: View) {
super.onChildPropertyChanged(child)
}
} }
export class List extends View implements SuperView { export class List extends Superview {
private cachedViews: Map<string, ListItem> = new Map private cachedViews: Map<string, ListItem> = new Map
subviewById(id: string): ListItem | undefined { subviewById(id: string): ListItem | undefined {

View File

@ -110,7 +110,7 @@ export abstract class View implements Modeling, IView {
@Property @Property
onClick?: Function onClick?: Function
parent?: Group superview?: Superview
callbacks: Map<String, Function> = new Map callbacks: Map<String, Function> = new Map
@ -188,7 +188,11 @@ export abstract class View implements Modeling, IView {
} }
/** Anchor end*/ /** Anchor end*/
__dirty_props__: { [index: string]: Model | undefined } = {} private __dirty_props__: { [index: string]: Model | undefined } = {}
get dirtyProps() {
return this.__dirty_props__
}
nativeViewModel = { nativeViewModel = {
id: this.viewId, id: this.viewId,
@ -203,9 +207,6 @@ export abstract class View implements Modeling, IView {
newV = obj2Model(newV) newV = obj2Model(newV)
} }
this.__dirty_props__[propKey] = newV this.__dirty_props__[propKey] = newV
if (this.parent instanceof Group) {
this.parent.onChildPropertyChanged(this)
}
} }
clean() { clean() {
@ -236,48 +237,33 @@ export abstract class View implements Modeling, IView {
toModel() { toModel() {
return this.nativeViewModel return this.nativeViewModel
} }
let(block: (it: this) => void) { let(block: (it: this) => void) {
block(this) block(this)
} }
also(block: (it: this) => void) { also(block: (it: this) => void) {
block(this) block(this)
return this return this
} }
in(group: Group) { in(group: Group) {
group.addChild(this) group.addChild(this)
} }
} }
export interface StackConfig extends LayoutConfig { export abstract class Superview extends View {
abstract subviewById(id: string): View | undefined
} }
export interface LinearConfig extends LayoutConfig { export abstract class Group extends Superview {
weight?: number
}
export interface SuperView {
subviewById(id: string): View | undefined
}
export abstract class Group extends View implements SuperView {
@Property
readonly children: View[] = new Proxy([], { readonly children: View[] = new Proxy([], {
set: (target, index, value) => { set: (target, index, value) => {
if (index === 'length') { const ret = Reflect.set(target, index, value)
this.getDirtyChildrenModel().length = value as number // Let getDirty return true
} else if (typeof index === 'string' this.dirtyProps.children = []
&& parseInt(index) >= 0 return ret
&& value instanceof View) {
value.parent = this
const childrenModel = this.getDirtyChildrenModel()
childrenModel[parseInt(index)] = value.nativeViewModel
}
if (this.parent) {
this.parent.onChildPropertyChanged(this)
}
return Reflect.set(target, index, value)
} }
}) })
@ -289,195 +275,21 @@ export abstract class Group extends View implements SuperView {
} }
return undefined return undefined
} }
addChild(view: View) { addChild(view: View) {
this.children.push(view) this.children.push(view)
} }
clean() {
this.children.forEach(e => { e.clean() })
super.clean()
}
getDirtyChildrenModel(): Model[] {
if (this.__dirty_props__.children === undefined) {
this.__dirty_props__.children = []
}
return this.__dirty_props__.children as Model[]
}
toModel() { toModel() {
if (this.__dirty_props__.children != undefined) { this.dirtyProps.children = this.children.map(e => {
(this.__dirty_props__.children as Model[]).length = this.children.length if (e.isDirty()) {
return e.toModel()
} else {
//Dont need return model
return {}
} }
})
return super.toModel() return super.toModel()
} }
onChildPropertyChanged(child: View) {
this.getDirtyChildrenModel()[this.children.indexOf(child)] = child.nativeViewModel
this.getDirtyChildrenModel().length = this.children.length
if (this.parent) {
this.parent.onChildPropertyChanged(this)
}
}
isDirty() {
return super.isDirty()
}
}
export interface IStack extends IView {
gravity?: Gravity
} }
export class Stack extends Group implements IStack {
@Property
gravity?: Gravity
}
export class Scroller extends View implements SuperView {
@Property
contentView?: View
subviewById(id: string): View | undefined {
return this.contentView
}
}
export class Root extends Stack {
}
class LinearLayout extends Group {
@Property
space?: number
@Property
gravity?: Gravity
}
export interface IVLayout extends IView {
space?: number
gravity?: Gravity
}
export class VLayout extends LinearLayout implements VLayout {
}
export interface IHLayout extends IView {
space?: number
gravity?: Gravity
}
export class HLayout extends LinearLayout implements IHLayout {
}
export interface IText extends IView {
text?: string
textColor?: Color
textSize?: number
maxLines?: number
textAlignment?: Gravity
}
export class Text extends View implements IText {
@Property
text?: string
@Property
textColor?: Color
@Property
textSize?: number
@Property
maxLines?: number
@Property
textAlignment?: Gravity
}
export interface IImage extends IView {
imageUrl?: string
}
export class Image extends View implements IImage {
@Property
imageUrl?: string
}
export class SectionList extends View implements SuperView {
private cachedViews: Map<string, View> = new Map
subviewById(id: string): View | undefined {
return this.cachedViews.get(id)
}
@Property
sectionRowsCount: number[] = []
@Property
renderSectionHeader!: (sectionIdx: number) => View
@Property
renderItem!: (sectionIdx: number, itemIdx: number) => View
@Property
sectionHeaderSticky = true
setupSectionRows(sectionCount: number, numberOfSection: (section: number) => number) {
this.sectionRowsCount = [...Array(sectionCount).keys()].map(e => numberOfSection(e))
}
private getItem(sectionIdx: number, itemIdx: number) {
let view = this.cachedViews.get(`${sectionIdx}:${itemIdx}`)
if (view === undefined) {
view = this.renderItem(sectionIdx, itemIdx)
this.cachedViews.set(`${sectionIdx}:${itemIdx}`, view)
}
return view
}
private getSectionHeader(sectionIdx: number) {
let view = this.cachedViews.get(`${sectionIdx}:`)
if (view === undefined) {
view = this.renderSectionHeader(sectionIdx)
this.cachedViews.set(`${sectionIdx}:`, view)
}
return view
}
@Property
private renderBunchedItems(items: Array<{ itemIdx: number, sectionIdx: number }>,
headers: number[]): { items: View[], headers: View[] } {
return {
items: items.map(e => this.getItem(e.sectionIdx, e.itemIdx)),
headers: headers.map(e => this.getSectionHeader(e))
}
}
}
export class Slide extends View implements SuperView {
@Property
pageCount = 0
@Property
renderPage!: (pageIdx: number) => View
private cachedViews: Map<string, View> = new Map
subviewById(id: string): View | undefined {
return this.cachedViews.get(id)
}
private getPage(pageIdx: number) {
let view = this.cachedViews.get(`${pageIdx}`)
if (view === undefined) {
view = this.renderPage(pageIdx)
this.cachedViews.set(`${pageIdx}`, view)
}
return view
}
@Property
private renderBunchedPages(pages: number[]): View[] {
return pages.map(e => this.getPage(e))
}
}

View File

@ -0,0 +1,52 @@
/*
* Copyright [2019] [Doric.Pub]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { IView, View, Property } from "./view"
import { Color } from "../util/color"
import { Gravity } from "../util/gravity"
export interface IText extends IView {
text?: string
textColor?: Color
textSize?: number
maxLines?: number
textAlignment?: Gravity
}
export class Text extends View implements IText {
@Property
text?: string
@Property
textColor?: Color
@Property
textSize?: number
@Property
maxLines?: number
@Property
textAlignment?: Gravity
}
export interface IImage extends IView {
imageUrl?: string
}
export class Image extends View implements IImage {
@Property
imageUrl?: string
}