add vlayout and hlayout
This commit is contained in:
parent
bc596a1a5e
commit
e99ec29919
3
dist/Counter.js
vendored
3
dist/Counter.js
vendored
@ -21,6 +21,9 @@ class CounterView extends doric.ViewHolder {
|
||||
child1.left = 100
|
||||
child1.backgroundColor = doric.Color.RED;
|
||||
child1.padding = { left: 50, top: 50 }
|
||||
child1.layoutConfig = {
|
||||
alignment: doric.Gravity.Center
|
||||
}
|
||||
const grandson = new doric.Stack;
|
||||
grandson.width = 100;
|
||||
grandson.height = 100;
|
||||
|
@ -2,7 +2,7 @@ import { jsObtainContext, jsCallEntityMethod } from 'doric/src/runtime/sandbox'
|
||||
import { Panel } from 'doric'
|
||||
import { DoricPlugin } from "./DoricPlugin"
|
||||
import { createContext } from "./DoricDriver"
|
||||
import { DoricStackViewNode } from './shader/DoricStackViewNode'
|
||||
import { DoricStackNode } from './shader/DoricStackNode'
|
||||
const doricContexts: Map<string, DoricContext> = new Map
|
||||
|
||||
let __contextId__ = 0
|
||||
@ -17,11 +17,11 @@ export function getDoricContext(contextId: string) {
|
||||
export class DoricContext {
|
||||
contextId = getContextId()
|
||||
pluginInstances: Map<string, DoricPlugin> = new Map
|
||||
rootNode: DoricStackViewNode
|
||||
rootNode: DoricStackNode
|
||||
constructor(content: string) {
|
||||
createContext(this.contextId, content)
|
||||
doricContexts.set(this.contextId, this)
|
||||
this.rootNode = new DoricStackViewNode(this)
|
||||
this.rootNode = new DoricStackNode(this)
|
||||
}
|
||||
|
||||
get panel() {
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { DoricPluginClass } from "./DoricPlugin"
|
||||
import { ShaderPlugin } from "./plugins/ShaderPlugin"
|
||||
import { DoricViewNodeClass } from "./shader/DoricViewNode"
|
||||
import { DoricStackViewNode } from "./shader/DoricStackViewNode"
|
||||
|
||||
import { DoricStackNode } from "./shader/DoricStackNode"
|
||||
import { DoricVLayoutNode } from './shader/DoricVLayoutNode'
|
||||
import { DoricHLayoutNode } from './shader/DoricHLayoutNode'
|
||||
|
||||
const bundles: Map<string, string> = new Map
|
||||
|
||||
@ -37,4 +38,6 @@ export function acquireViewNode(name: string) {
|
||||
|
||||
registerPlugin('shader', ShaderPlugin)
|
||||
|
||||
registerViewNode('Stack', DoricStackViewNode)
|
||||
registerViewNode('Stack', DoricStackNode)
|
||||
registerViewNode('VLayout', DoricVLayoutNode)
|
||||
registerViewNode('HLayout', DoricHLayoutNode)
|
122
src/shader/DoricHLayoutNode.ts
Normal file
122
src/shader/DoricHLayoutNode.ts
Normal file
@ -0,0 +1,122 @@
|
||||
import { DoricGroupViewNode, LayoutSpec, FrameSize, LEFT, RIGHT, CENTER_X, CENTER_Y, TOP, BOTTOM } from "./DoricViewNode";
|
||||
|
||||
export class DoricHLayoutNode extends DoricGroupViewNode {
|
||||
space = 0
|
||||
gravity = 0
|
||||
contentSize = {
|
||||
width: 0,
|
||||
height: 0,
|
||||
weight: 0,
|
||||
}
|
||||
build() {
|
||||
return document.createElement('div')
|
||||
}
|
||||
blendProps(v: HTMLElement, propName: string, prop: any) {
|
||||
if (propName === 'space') {
|
||||
this.space = prop
|
||||
} else if (propName === 'gravity') {
|
||||
this.gravity = prop
|
||||
} else {
|
||||
super.blendProps(v, propName, prop)
|
||||
}
|
||||
}
|
||||
blend(props: { [index: string]: any }) {
|
||||
super.blend(props)
|
||||
this.childNodes.forEach(e => {
|
||||
e.view.style.position = "absolute"
|
||||
})
|
||||
}
|
||||
|
||||
measureContentSize(targetSize: { width: number, height: number }) {
|
||||
let width = this.frameWidth
|
||||
let height = this.frameHeight
|
||||
let contentSize = { width: 0, height: 0, weight: 0 }
|
||||
let limitSize = {
|
||||
width: targetSize.width - this.paddingLeft - this.paddingRight,
|
||||
height: targetSize.height - this.paddingTop - this.paddingBottom,
|
||||
}
|
||||
contentSize = this.childNodes.reduce((prev, current) => {
|
||||
const size = current.measureContentSize(limitSize)
|
||||
return {
|
||||
width: prev.width + size.width + this.space
|
||||
+ current.layoutConfig?.margin?.left || 0
|
||||
+ current.layoutConfig?.margin?.right || 0,
|
||||
height: Math.max(prev.height, size.height),
|
||||
weight: prev.weight + current.layoutConfig?.weight || 0
|
||||
}
|
||||
}, contentSize)
|
||||
contentSize.width -= this.space
|
||||
switch (this.layoutConfig.widthSpec) {
|
||||
case LayoutSpec.AT_MOST:
|
||||
width = targetSize.width
|
||||
break
|
||||
case LayoutSpec.WRAP_CONTENT:
|
||||
width = contentSize.width
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
switch (this.layoutConfig.heightSpec) {
|
||||
case LayoutSpec.AT_MOST:
|
||||
height = targetSize.height
|
||||
break
|
||||
case LayoutSpec.WRAP_CONTENT:
|
||||
height = contentSize.height
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
if (contentSize.weight > 0) {
|
||||
contentSize.width = targetSize.width
|
||||
}
|
||||
this.contentSize = contentSize
|
||||
return { width, height }
|
||||
}
|
||||
|
||||
layoutSelf(targetSize: FrameSize) {
|
||||
const { width, height } = this.measureContentSize(targetSize)
|
||||
this.width = width
|
||||
this.height = height
|
||||
let xStart = this.paddingLeft;
|
||||
if ((this.gravity & LEFT) == LEFT) {
|
||||
xStart = this.paddingLeft
|
||||
} else if ((this.gravity & RIGHT) == RIGHT) {
|
||||
xStart = targetSize.width - this.contentSize.width - this.paddingRight;
|
||||
} else if ((this.gravity & CENTER_X) == CENTER_X) {
|
||||
xStart = (targetSize.width - this.contentSize.width - this.paddingLeft - this.paddingRight) / 2 + this.paddingLeft
|
||||
}
|
||||
let remain = targetSize.width - this.contentSize.width - this.paddingLeft - this.paddingRight
|
||||
this.childNodes.forEach(e => {
|
||||
const childTargetSize = {
|
||||
width: width - xStart - this.paddingRight,
|
||||
height: height - this.paddingTop - this.paddingBottom,
|
||||
}
|
||||
if (e.layoutConfig?.weight > 0) {
|
||||
childTargetSize.width += remain / this.contentSize.weight * e.layoutConfig.weight
|
||||
}
|
||||
e.layoutSelf(childTargetSize)
|
||||
let gravity = e.layoutConfig?.alignment | this.gravity
|
||||
if ((gravity & TOP) === TOP) {
|
||||
e.y = 0
|
||||
} else if ((gravity & BOTTOM) === BOTTOM) {
|
||||
e.y = height - e.height + this.paddingTop - this.paddingBottom
|
||||
} else if ((gravity & CENTER_Y) === CENTER_Y) {
|
||||
e.x = height / 2 - e.height / 2 - this.paddingTop
|
||||
} else {
|
||||
if (e.layoutConfig.margin?.left) {
|
||||
e.x = e.layoutConfig.margin?.left
|
||||
} else if (e.layoutConfig.margin?.right) {
|
||||
e.x = width - e.width + this.paddingLeft - this.paddingRight - e.layoutConfig.margin?.right
|
||||
}
|
||||
}
|
||||
if (e.layoutConfig.margin?.left !== undefined) {
|
||||
xStart += e.layoutConfig.margin.left
|
||||
}
|
||||
e.x = xStart - this.paddingLeft
|
||||
xStart += e.width + this.space
|
||||
if (e.layoutConfig.margin?.right !== undefined) {
|
||||
xStart += e.layoutConfig.margin.right
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
import { DoricGroupViewNode, LayoutSpec, FrameSize, LEFT, RIGHT, CENTER_X, CENTER_Y, TOP, BOTTOM } from "./DoricViewNode";
|
||||
|
||||
export class DoricStackViewNode extends DoricGroupViewNode {
|
||||
export class DoricStackNode extends DoricGroupViewNode {
|
||||
|
||||
build() {
|
||||
return document.createElement('div')
|
122
src/shader/DoricVLayoutNode.ts
Normal file
122
src/shader/DoricVLayoutNode.ts
Normal file
@ -0,0 +1,122 @@
|
||||
import { DoricGroupViewNode, LayoutSpec, FrameSize, LEFT, RIGHT, CENTER_X, CENTER_Y, TOP, BOTTOM } from "./DoricViewNode";
|
||||
|
||||
export class DoricVLayoutNode extends DoricGroupViewNode {
|
||||
space = 0
|
||||
gravity = 0
|
||||
contentSize = {
|
||||
width: 0,
|
||||
height: 0,
|
||||
weight: 0,
|
||||
}
|
||||
build() {
|
||||
return document.createElement('div')
|
||||
}
|
||||
blendProps(v: HTMLElement, propName: string, prop: any) {
|
||||
if (propName === 'space') {
|
||||
this.space = prop
|
||||
} else if (propName === 'gravity') {
|
||||
this.gravity = prop
|
||||
} else {
|
||||
super.blendProps(v, propName, prop)
|
||||
}
|
||||
}
|
||||
blend(props: { [index: string]: any }) {
|
||||
super.blend(props)
|
||||
this.childNodes.forEach(e => {
|
||||
e.view.style.position = "absolute"
|
||||
})
|
||||
}
|
||||
|
||||
measureContentSize(targetSize: { width: number, height: number }) {
|
||||
let width = this.frameWidth
|
||||
let height = this.frameHeight
|
||||
let contentSize = { width: 0, height: 0, weight: 0 }
|
||||
let limitSize = {
|
||||
width: targetSize.width - this.paddingLeft - this.paddingRight,
|
||||
height: targetSize.height - this.paddingTop - this.paddingBottom,
|
||||
}
|
||||
contentSize = this.childNodes.reduce((prev, current) => {
|
||||
const size = current.measureContentSize(limitSize)
|
||||
return {
|
||||
width: Math.max(prev.width, size.width),
|
||||
height: prev.height + size.height + this.space
|
||||
+ current.layoutConfig?.margin?.top || 0
|
||||
+ current.layoutConfig?.margin?.bottom || 0,
|
||||
weight: prev.weight + current.layoutConfig?.weight || 0
|
||||
}
|
||||
}, contentSize)
|
||||
contentSize.height -= this.space
|
||||
switch (this.layoutConfig.widthSpec) {
|
||||
case LayoutSpec.AT_MOST:
|
||||
width = targetSize.width
|
||||
break
|
||||
case LayoutSpec.WRAP_CONTENT:
|
||||
width = contentSize.width
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
switch (this.layoutConfig.heightSpec) {
|
||||
case LayoutSpec.AT_MOST:
|
||||
height = targetSize.height
|
||||
break
|
||||
case LayoutSpec.WRAP_CONTENT:
|
||||
height = contentSize.height
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
if (contentSize.weight > 0) {
|
||||
contentSize.height = targetSize.height
|
||||
}
|
||||
this.contentSize = contentSize
|
||||
return { width, height }
|
||||
}
|
||||
|
||||
layoutSelf(targetSize: FrameSize) {
|
||||
const { width, height } = this.measureContentSize(targetSize)
|
||||
this.width = width
|
||||
this.height = height
|
||||
let yStart = this.paddingTop;
|
||||
if ((this.gravity & TOP) == TOP) {
|
||||
yStart = this.paddingTop
|
||||
} else if ((this.gravity & BOTTOM) == BOTTOM) {
|
||||
yStart = targetSize.height - this.contentSize.height - this.paddingBottom;
|
||||
} else if ((this.gravity & CENTER_Y) == CENTER_Y) {
|
||||
yStart = (targetSize.height - this.contentSize.height - this.paddingTop - this.paddingBottom) / 2 + this.paddingTop
|
||||
}
|
||||
let remain = targetSize.height - this.contentSize.height - this.paddingTop - this.paddingBottom
|
||||
this.childNodes.forEach(e => {
|
||||
const childTargetSize = {
|
||||
width: width - this.paddingLeft - this.paddingRight,
|
||||
height: height - yStart - this.paddingBottom,
|
||||
}
|
||||
if (e.layoutConfig?.weight > 0) {
|
||||
childTargetSize.height += remain / this.contentSize.weight * e.layoutConfig.weight
|
||||
}
|
||||
e.layoutSelf(childTargetSize)
|
||||
let gravity = e.layoutConfig?.alignment | this.gravity
|
||||
if ((gravity & LEFT) === LEFT) {
|
||||
e.x = 0
|
||||
} else if ((gravity & RIGHT) === RIGHT) {
|
||||
e.x = width - e.width + this.paddingLeft - this.paddingRight
|
||||
} else if ((gravity & CENTER_X) === CENTER_X) {
|
||||
e.x = width / 2 - e.width / 2 - this.paddingLeft
|
||||
} else {
|
||||
if (e.layoutConfig.margin?.left) {
|
||||
e.x = e.layoutConfig.margin?.left
|
||||
} else if (e.layoutConfig.margin?.right) {
|
||||
e.x = width - e.width + this.paddingLeft - this.paddingRight - e.layoutConfig.margin?.right
|
||||
}
|
||||
}
|
||||
if (e.layoutConfig.margin?.top !== undefined) {
|
||||
yStart += e.layoutConfig.margin.top
|
||||
}
|
||||
e.y = yStart - this.paddingTop
|
||||
yStart += e.width + this.space
|
||||
if (e.layoutConfig.margin?.bottom !== undefined) {
|
||||
yStart += e.layoutConfig.margin.bottom
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user