declarative ui

This commit is contained in:
pengfei.zhou 2019-10-28 11:28:46 +08:00 committed by unknown
parent b1a2211dcf
commit 042a1dbf17
7 changed files with 224 additions and 196 deletions

View File

@ -1,4 +1,4 @@
import { vlayout, Image, ViewHolder, VMPanel, ViewModel, Gravity, NativeCall, Text, Color, log, logw, loge, Group, LayoutSpec, } from "doric" import { text, vlayout, Image, ViewHolder, VMPanel, ViewModel, Gravity, NativeCall, Text, Color, log, logw, loge, Group, LayoutSpec, } from "doric"
interface CountModel { interface CountModel {
count: number count: number
@ -10,39 +10,31 @@ class CounterView extends ViewHolder<CountModel> {
counter!: Text counter!: Text
build(root: Group) { build(root: Group) {
root.addChild(vlayout([ root.addChild(vlayout([
() => { text({
return (new Text).also(it => { textSize: 40,
it.textSize = 40 layoutConfig: {
it.layoutConfig = {
alignment: new Gravity().center() alignment: new Gravity().center()
}
this.number = it
})
}, },
() => { }).also(it => { this.number = it }),
return (new Text).also(it => { text({
it.text = "点击计数" text: "点击计数",
it.textSize = 20 textSize: 20,
border: {
it.border = {
width: 1, width: 1,
color: Color.parse('#000000'), color: Color.parse('#000000'),
} },
it.corners = 5 corners: 5,
layoutConfig: {
it.layoutConfig = {
alignment: new Gravity().center() alignment: new Gravity().center()
} },
it.shadow = { shadow: {
color: Color.parse("#00ff00"), color: Color.parse("#00ff00"),
opacity: 0.5, opacity: 0.5,
radius: 20, radius: 20,
offsetX: 10, offsetX: 10,
offsetY: 10, offsetY: 10,
} }
this.counter = it }).also(it => { this.counter = it }),
})
},
]).also(it => { ]).also(it => {
it.width = 200 it.width = 200
it.height = 200 it.height = 200

View File

@ -1,4 +1,4 @@
import { loge, log, ViewHolder, Stack, ViewModel, Gravity, Text, Color, HLayout, VLayout, Group, VMPanel, LayoutSpec, vlayout, hlayout, takeNonNull } from "doric"; import { text, loge, log, ViewHolder, Stack, ViewModel, Gravity, Text, Color, HLayout, VLayout, Group, VMPanel, LayoutSpec, vlayout, hlayout, takeNonNull, stack } from "doric";
type SnakeNode = { type SnakeNode = {
x: number x: number
@ -146,91 +146,89 @@ class SnakeView extends ViewHolder<SnakeModel> {
build(root: Group): void { build(root: Group): void {
root.bgColor = Color.parse('#000000') root.bgColor = Color.parse('#000000')
vlayout([ vlayout([
() => { text({
return (new Text).also(title => { text: "Snake",
title.text = "Snake" textSize: 20,
title.textSize = 20 textColor: Color.parse("#ffffff"),
title.textColor = Color.parse("#ffffff") layoutConfig: {
title.layoutConfig = {
alignment: new Gravity().centerX(), alignment: new Gravity().centerX(),
margin: { margin: {
top: 20 top: 20
}, },
widthSpec: LayoutSpec.WRAP_CONTENT, widthSpec: LayoutSpec.WRAP_CONTENT,
heightSpec: LayoutSpec.WRAP_CONTENT, heightSpec: LayoutSpec.WRAP_CONTENT,
}
})
}, },
() => { }),
return (new Stack).also(panel => { (new Stack).also(panel => {
panel.bgColor = Color.parse('#00ff00') panel.bgColor = Color.parse('#00ff00')
this.panel = panel this.panel = panel
}) }),
}, hlayout([
() => { text({
return hlayout([ text: "Start",
() => { textSize: 30,
return (new Text).also(it => { textColor: Color.parse("#ffffff"),
it.text = "Start" layoutConfig: {
it.textSize = 30
it.textColor = Color.parse("#ffffff")
it.layoutConfig = {
widthSpec: LayoutSpec.WRAP_CONTENT, widthSpec: LayoutSpec.WRAP_CONTENT,
heightSpec: LayoutSpec.WRAP_CONTENT, heightSpec: LayoutSpec.WRAP_CONTENT,
}
this.start = it
})
}, },
}).also(it => this.start = it),
]).also(it => { ]).also(it => {
it.layoutConfig = { it.layoutConfig = {
widthSpec: LayoutSpec.WRAP_CONTENT, widthSpec: LayoutSpec.WRAP_CONTENT,
heightSpec: LayoutSpec.WRAP_CONTENT, heightSpec: LayoutSpec.WRAP_CONTENT,
} }
}) }),
},
() => { vlayout([
return vlayout([ hlayout([
() => { text({
return hlayout([ width: 50,
() => { height: 50,
return this.buildController("↑").also(it => { text: "↑",
this.up = it textSize: 30,
}) textAlignment: new Gravity().center(),
} bgColor: Color.parse('#ffff00'),
}).also(it => this.up = it)
]).also(it => { ]).also(it => {
it.layoutConfig = { it.layoutConfig = {
widthSpec: LayoutSpec.WRAP_CONTENT, widthSpec: LayoutSpec.WRAP_CONTENT,
heightSpec: LayoutSpec.WRAP_CONTENT, heightSpec: LayoutSpec.WRAP_CONTENT,
} }
}) }),
}, hlayout([
() => { text({
return hlayout([ width: 50,
() => { height: 50,
return this.buildController("←").also(it => { text: "←",
this.left = it textSize: 30,
}) textAlignment: new Gravity().center(),
}, bgColor: Color.parse('#ffff00'),
() => { }).also(it => this.left = it),
return this.buildController("↓").also(it => { text({
this.down = it width: 50,
}) height: 50,
}, text: "↓",
() => { textSize: 30,
return this.buildController("→").also(it => { textAlignment: new Gravity().center(),
this.right = it bgColor: Color.parse('#ffff00'),
}) }).also(it => this.down = it),
}, text({
width: 50,
height: 50,
text: "→",
textSize: 30,
textAlignment: new Gravity().center(),
bgColor: Color.parse('#ffff00'),
}).also(it => this.right = it),
]).also(it => { ]).also(it => {
it.layoutConfig = { it.layoutConfig = {
widthSpec: LayoutSpec.WRAP_CONTENT, widthSpec: LayoutSpec.WRAP_CONTENT,
heightSpec: LayoutSpec.WRAP_CONTENT, heightSpec: LayoutSpec.WRAP_CONTENT,
} }
it.space = 10 it.space = 10
}) }),
}, ]).also(controlArea => {
])
.also(controlArea => {
controlArea.gravity = new Gravity().centerX() controlArea.gravity = new Gravity().centerX()
controlArea.space = 10 controlArea.space = 10
controlArea.layoutConfig = { controlArea.layoutConfig = {
@ -238,8 +236,7 @@ class SnakeView extends ViewHolder<SnakeModel> {
widthSpec: LayoutSpec.WRAP_CONTENT, widthSpec: LayoutSpec.WRAP_CONTENT,
heightSpec: LayoutSpec.WRAP_CONTENT, heightSpec: LayoutSpec.WRAP_CONTENT,
} }
}) }),
}
]).also(it => { ]).also(it => {
it.space = 20 it.space = 20
it.layoutConfig = { it.layoutConfig = {

View File

@ -15,6 +15,7 @@
*/ */
export * from "./src/ui/view" export * from "./src/ui/view"
export * from "./src/ui/panel" export * from "./src/ui/panel"
export * from "./src/ui/declarative"
export * from "./src/util/color" export * from "./src/util/color"
export * from './src/util/log' export * from './src/util/log'
export * from './src/util/types' export * from './src/util/types'

View File

@ -0,0 +1,87 @@
import { Text, Image, HLayout, VLayout, Stack, LayoutConfig, View } from './view'
import { Color, GradientColor } from '../util/color'
import { Gravity } from '../util/gravity'
export interface IView {
width?: number
height?: number
bgColor?: Color | GradientColor
corners?: number | { leftTop?: number; rightTop?: number; leftBottom?: number; rightBottom?: number }
border?: { width: number; color: Color; }
shadow?: { color: Color; opacity: number; radius: number; offsetX: number; offsetY: number }
alpha?: number
hidden?: boolean
padding?: {
left?: number,
right?: number,
top?: number,
bottom?: number,
}
layoutConfig?: LayoutConfig
onClick?: Function
identifier?: string
}
export interface IText extends IView {
text?: string
textColor?: Color
textSize?: number
maxLines?: number
textAlignment?: Gravity
}
export interface IImage extends IView {
imageUrl?: string
}
export interface IStack extends IView {
gravity?: Gravity
}
export interface IVLayout extends IView {
space?: number
gravity?: Gravity
}
export interface IHLayout extends IView {
space?: number
gravity?: Gravity
}
export function text(config: IText) {
const ret = new Text
for (let key in config) {
Reflect.set(ret, key, Reflect.get(config, key, config), ret)
}
return ret
}
export function image(config: IImage) {
const ret = new Image
for (let key in config) {
Reflect.set(ret, key, Reflect.get(config, key, config), ret)
}
return ret
}
export function stack(views: View[]) {
const ret = new Stack
for (let v of views) {
ret.addChild(v)
}
return ret
}
export function hlayout(views: View[]) {
const ret = new HLayout
for (let v of views) {
ret.addChild(v)
}
return ret
}
export function vlayout(views: View[]) {
const ret = new VLayout
for (let v of views) {
ret.addChild(v)
}
return ret
}

View File

@ -1,47 +0,0 @@
/*
* 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.
*/
function from(obj: Object) {
return new Proxy(obj, {
set: (target, prop, value, receiver) => {
return Reflect.set(target, prop, value, receiver)
}
})
}
class Wrapper {
val: any
constructor(val: any) {
this.val = val
}
toVal(): any {
return this.val
}
}
export class State {
static of<T extends Object>(obj: T): T {
return new Proxy(obj, {
get: (target, prop) => {
const ret = Reflect.get(target, prop)
if (ret instanceof Object) {
return State.of(ret)
} else {
return new Wrapper(ret)
}
}
})
}
}

View File

@ -37,8 +37,6 @@ export interface LayoutConfig {
alignment?: Gravity alignment?: Gravity
} }
export function Property(target: Object, propKey: string) { export function Property(target: Object, propKey: string) {
Reflect.defineMetadata(propKey, true, target) Reflect.defineMetadata(propKey, true, target)
} }

View File

@ -13,36 +13,36 @@
* 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 { View, Stack, VLayout, HLayout } from "../ui/view" // import { View, Stack, VLayout, HLayout } from "../ui/view"
export type ViewBlock = () => View // export type ViewBlock = () => View
export function stack(blocks: ViewBlock[]) { // export function stack(blocks: ViewBlock[]) {
return takeAlso(new Stack)( // return takeAlso(new Stack)(
it => { // it => {
for (let block of blocks) { // for (let block of blocks) {
it.addChild(block()) // it.addChild(block())
} // }
}) // })
} // }
export function vlayout(blocks: ViewBlock[]) { // export function vlayout(blocks: ViewBlock[]) {
return takeAlso(new VLayout)( // return takeAlso(new VLayout)(
it => { // it => {
for (let block of blocks) { // for (let block of blocks) {
it.addChild(block()) // it.addChild(block())
} // }
}) // })
} // }
export function hlayout(blocks: ViewBlock[]) { // export function hlayout(blocks: ViewBlock[]) {
return takeAlso(new HLayout)( // return takeAlso(new HLayout)(
it => { // it => {
for (let block of blocks) { // for (let block of blocks) {
it.addChild(block()) // it.addChild(block())
} // }
}) // })
} // }
export function take<T>(target: T) { export function take<T>(target: T) {
return (block: (p: T) => void) => { return (block: (p: T) => void) => {