declarative ui
This commit is contained in:
parent
b1a2211dcf
commit
042a1dbf17
@ -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
|
||||||
|
@ -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 = {
|
||||||
|
@ -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'
|
||||||
|
87
js-framework/src/ui/declarative.ts
Normal file
87
js-framework/src/ui/declarative.ts
Normal 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
|
||||||
|
}
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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) => {
|
||||||
|
Reference in New Issue
Block a user