feat(core): Added support for stacks in layout
This commit is contained in:
parent
85748db201
commit
7ac5a88dff
7 changed files with 114 additions and 45 deletions
|
@ -111,31 +111,15 @@ Part.prototype.boundary = function () {
|
|||
if (topLeft.y === Infinity) topLeft.y = 0
|
||||
if (bottomRight.x === -Infinity) bottomRight.x = 0
|
||||
if (bottomRight.y === -Infinity) bottomRight.y = 0
|
||||
// Add margin
|
||||
let margin = this.context.settings.margin
|
||||
if (this.context.settings.paperless && margin < 10) margin = 10
|
||||
this.topLeft = new Point(topLeft.x - margin, topLeft.y - margin)
|
||||
this.bottomRight = new Point(bottomRight.x + margin, bottomRight.y + margin)
|
||||
|
||||
this.topLeft = topLeft
|
||||
this.bottomRight = bottomRight
|
||||
this.width = this.bottomRight.x - this.topLeft.x
|
||||
this.height = this.bottomRight.y - this.topLeft.y
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
/** Homes part so that its top left corner is in (0,0) */
|
||||
Part.prototype.home = function () {
|
||||
if (this.topLeft !== false) return this
|
||||
else this.boundary()
|
||||
if (this.topLeft.x == 0 && this.topLeft.y == 0) return this
|
||||
else {
|
||||
this.attr('transform', `translate(${this.topLeft.x * -1}, ${this.topLeft.y * -1})`)
|
||||
this.layout.move.x = this.topLeft.x * -1
|
||||
this.layout.move.y = this.topLeft.y * -1
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
/** Adds an attribute. This is here to make this call chainable in assignment */
|
||||
Part.prototype.attr = function (name, value, overwrite = false) {
|
||||
if (overwrite) this.attributes.set(name, value)
|
||||
|
|
|
@ -104,6 +104,19 @@ Pattern.prototype.__createPartWithContext = function (name) {
|
|||
return part
|
||||
}
|
||||
|
||||
Pattern.prototype.__createStackWithContext = function (name) {
|
||||
// Context object to add to Stack closure
|
||||
const stack = new Stack()
|
||||
stack.name = name
|
||||
stack.context = {
|
||||
config: this.config,
|
||||
settings: this.settings,
|
||||
store: this.store,
|
||||
}
|
||||
|
||||
return stack
|
||||
}
|
||||
|
||||
// Merges default for options with user-provided options
|
||||
Pattern.prototype.__loadOptionDefaults = function () {
|
||||
if (Object.keys(this.config.options).length < 1) return this
|
||||
|
@ -548,7 +561,8 @@ Pattern.prototype.pack = function () {
|
|||
// First, create all stacks
|
||||
this.stacks = {}
|
||||
for (const [name, part] of Object.entries(this.parts)) {
|
||||
if (typeof this.stacks[part.stack] === 'undefined') this.stacks[part.stack] = new Stack(part.stack)
|
||||
if (typeof this.stacks[part.stack] === 'undefined')
|
||||
this.stacks[part.stack] = this.__createStackWithContext(part.stack)
|
||||
this.stacks[part.stack].addPart(part)
|
||||
}
|
||||
|
||||
|
@ -558,7 +572,8 @@ Pattern.prototype.pack = function () {
|
|||
stack.attributes.remove('transform')
|
||||
if (!this.isStackHidden(key)) {
|
||||
stack.home()
|
||||
if (this.settings.layout === true) bins.push({ id: key, width: stack.width, height: stack.height })
|
||||
if (this.settings.layout === true)
|
||||
bins.push({ id: key, width: stack.width, height: stack.height })
|
||||
else {
|
||||
if (this.width < stack.width) this.width = stack.width
|
||||
if (this.height < stack.height) this.height = stack.height
|
||||
|
@ -573,7 +588,6 @@ Pattern.prototype.pack = function () {
|
|||
if (bin.x !== 0 || bin.y !== 0) {
|
||||
stack.attr('transform', `translate(${bin.x}, ${bin.y})`)
|
||||
}
|
||||
|
||||
this.autoLayout.stacks[bin.id].move = {
|
||||
x: bin.x + stack.layout.move.x,
|
||||
y: bin.y + stack.layout.move.y,
|
||||
|
@ -845,6 +859,12 @@ Pattern.prototype.getRenderProps = function () {
|
|||
}
|
||||
}
|
||||
}
|
||||
props.stacks = {}
|
||||
for (let s in this.stacks) {
|
||||
if (!this.isStackHidden(s)) {
|
||||
props.stacks[s] = this.stacks[s]
|
||||
}
|
||||
}
|
||||
|
||||
return props
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ Stack.prototype.getPartList = function(part) {
|
|||
|
||||
/* Returns a list of names of parts in this stack */
|
||||
Stack.prototype.getPartNames = function (part) {
|
||||
return [...this.parts].map(p => p.name)
|
||||
return [...this.parts].map((p) => p.name)
|
||||
}
|
||||
|
||||
/** Homes the stack so that its top left corner is in (0,0) */
|
||||
|
@ -58,9 +58,11 @@ Stack.prototype.home = function () {
|
|||
|
||||
/** Calculates the stack's bounding box and sets it */
|
||||
Stack.prototype.home = function () {
|
||||
if (this.topLeft) return this // Cached
|
||||
this.topLeft = new Point(Infinity, Infinity)
|
||||
this.bottomRight = new Point(-Infinity, -Infinity)
|
||||
for (const part of this.getPartList()) {
|
||||
part.boundary()
|
||||
if (part.topLeft.x < this.topLeft.x) this.topLeft.x = part.topLeft.x
|
||||
if (part.topLeft.y < this.topLeft.y) this.topLeft.y = part.topLeft.y
|
||||
if (part.bottomRight.x > this.bottomRight.x) this.bottomRight.x = part.bottomRight.x
|
||||
|
@ -73,8 +75,53 @@ Stack.prototype.home = function () {
|
|||
if (this.bottomRight.x === -Infinity) this.bottomRight.x = 0
|
||||
if (this.bottomRight.y === -Infinity) this.bottomRight.y = 0
|
||||
|
||||
// Add margin
|
||||
let margin = this.context.settings.margin
|
||||
if (this.context.settings.paperless && margin < 10) margin = 10
|
||||
this.topLeft.x -= margin
|
||||
this.topLeft.y -= margin
|
||||
this.bottomRight.x += margin
|
||||
this.bottomRight.y += margin
|
||||
|
||||
// Set dimensions
|
||||
this.width = this.bottomRight.x - this.topLeft.x
|
||||
this.height = this.bottomRight.y - this.topLeft.y
|
||||
this.width = this.bottomRight.x - this.topLeft.x
|
||||
this.height = this.bottomRight.y - this.topLeft.y
|
||||
|
||||
// Add transform
|
||||
this.anchor = this.getAnchor()
|
||||
|
||||
if (this.topLeft.x === this.anchor.x && this.topLeft.y === this.anchor.y) return this
|
||||
else {
|
||||
this.attr('transform', `translate(${this.anchor.x - this.topLeft.x}, ${this.anchor.y - this.topLeft.y})`)
|
||||
this.layout.move.x = this.anchor.x - this.topLeft.x
|
||||
this.layout.move.y = this.anchor.y - this.topLeft.y
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
/** Finds the anchor to aling parts in this stack */
|
||||
Stack.prototype.getAnchor = function() {
|
||||
let anchorPoint = true
|
||||
let gridAnchorPoint = true
|
||||
const parts = this.getPartList()
|
||||
for (const part of parts) {
|
||||
if (typeof part.points.anchor === 'undefined') anchorPoint = false
|
||||
if (typeof part.points.gridAnchor === 'undefined') gridAnchorPoint = false
|
||||
}
|
||||
|
||||
if (anchorPoint) return parts[0].points.anchor
|
||||
if (gridAnchorPoint) return parts[0].points.gridAnchor
|
||||
|
||||
return new Point(0,0)
|
||||
}
|
||||
|
||||
/** Adds an attribute. This is here to make this call chainable in assignment */
|
||||
Stack.prototype.attr = function (name, value, overwrite = false) {
|
||||
if (overwrite) this.attributes.set(name, value)
|
||||
else this.attributes.add(name, value)
|
||||
|
||||
return this
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import { round, Design, Point, pctBasedOn } from '../src/index.mjs'
|
|||
const expect = chai.expect
|
||||
|
||||
describe('Stacks', () => {
|
||||
|
||||
describe('Pattern.init()', () => {
|
||||
const partA = {
|
||||
name: 'test.partA',
|
||||
|
@ -65,8 +64,8 @@ describe('Stacks', () => {
|
|||
})
|
||||
const pattern = new Pattern({
|
||||
measurements: {
|
||||
head: 400
|
||||
}
|
||||
head: 400,
|
||||
},
|
||||
})
|
||||
pattern.draft()
|
||||
console.log(pattern.store.logs)
|
||||
|
@ -90,6 +89,5 @@ describe('Stacks', () => {
|
|||
pattern.config.resolvedDependencies['test.partC'].indexOf('test.partB') !== -1
|
||||
).to.equal(true)
|
||||
})
|
||||
|
||||
})
|
||||
})
|
||||
|
|
|
@ -27,7 +27,7 @@ const LabDraft = props => {
|
|||
|
||||
return (
|
||||
<>
|
||||
{(!patternProps || patternProps.events?.error?.length > 0)
|
||||
{(!patternProps || patternProps.logs?.error?.length > 0)
|
||||
? <Error {...{ draft, patternProps, updateGist }} />
|
||||
: null
|
||||
}
|
||||
|
|
20
sites/shared/components/workbench/draft/stack.js
Normal file
20
sites/shared/components/workbench/draft/stack.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
import Part from './part'
|
||||
import { getProps } from './utils'
|
||||
|
||||
const Stack = props => {
|
||||
const { stackName, stack, patternProps, gist, app, updateGist, unsetGist, showInfo } = props
|
||||
|
||||
return (
|
||||
<g {...getProps(stack)} id={`stack-${stackName}`}>
|
||||
{[...stack.parts].map((part) => (
|
||||
<Part {...{ app, gist, updateGist, unsetGist, showInfo }}
|
||||
key={part.name}
|
||||
partName={part.name}
|
||||
part={part}
|
||||
/>
|
||||
))}
|
||||
</g>
|
||||
)
|
||||
}
|
||||
|
||||
export default Stack
|
|
@ -2,7 +2,7 @@ import { SizeMe } from 'react-sizeme'
|
|||
import { TransformWrapper, TransformComponent } from "react-zoom-pan-pinch"
|
||||
import Svg from './svg'
|
||||
import Defs from './defs'
|
||||
import Part from './part'
|
||||
import Stack from './stack'
|
||||
|
||||
/* What's with all the wrapping?
|
||||
*
|
||||
|
@ -40,11 +40,11 @@ const SvgWrapper = props => {
|
|||
<Defs {...patternProps} />
|
||||
<style>{`:root { --pattern-scale: ${gist.scale || 1}} ${patternProps.svg.style}`}</style>
|
||||
<g>
|
||||
{Object.keys(patternProps.parts).map((name) => (
|
||||
<Part {...{ app, gist, updateGist, unsetGist, showInfo }}
|
||||
key={name}
|
||||
partName={name}
|
||||
part={patternProps.parts[name]}
|
||||
{Object.keys(patternProps.stacks).map((stackName) => (
|
||||
<Stack {...{ app, gist, updateGist, unsetGist, showInfo, patternProps }}
|
||||
key={stackName}
|
||||
stackName={stackName}
|
||||
stack={patternProps.stacks[stackName]}
|
||||
/>
|
||||
))}
|
||||
</g>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue