1
0
Fork 0

wip(shared): Working on custom layout

This commit is contained in:
Joost De Cock 2022-02-20 18:46:21 +01:00
parent f4ee97a626
commit 34c8a6b2a5
13 changed files with 357 additions and 0 deletions

View file

@ -0,0 +1,7 @@
const PageSizeIcon = props => (
<svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 7v8a2 2 0 002 2h6M8 7V5a2 2 0 012-2h4.586a1 1 0 01.707.293l4.414 4.414a1 1 0 01.293.707V15a2 2 0 01-2 2h-2M8 7H6a2 2 0 00-2 2v10a2 2 0 002 2h8a2 2 0 002-2v-2" />
</svg>
)
export default PageSizeIcon

View file

@ -0,0 +1,7 @@
const PageIcon = props => (
<svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z" />
</svg>
)
export default PageIcon

View file

@ -0,0 +1,21 @@
import { useTranslation } from 'next-i18next'
import Settings from './settings'
const CutLayout = props => {
const { t } = useTranslation(['workbench'])
return (
<div>
<h2 className="capitalize">
{
t('layoutThing', { thing: props.pattern.config.name })
+ ': '
+ t('forCutting')
}
</h2>
<Settings {...props} />
</div>
)
}
export default CutLayout

View file

@ -0,0 +1,10 @@
const CutLayoutSettings = props => {
return (
<div>
<p>Fixme: Cut layout settings here</p>
</div>
)
}
export default CutLayoutSettings

View file

@ -0,0 +1,33 @@
import Svg from '../draft/svg'
import Defs from '../draft/defs'
import Part from '../draft/part'
const Draft = props => {
const { patternProps, gist, app, updateGist, unsetGist, bgProps={} } = props
return (
<div className="my-8 w-11/12 m-auto">
<Svg {...patternProps} embed={gist.embed}>
<Defs {...patternProps} />
<style>{`:root { --pattern-scale: ${gist.scale || 1}}`}</style>
<g>
<rect x="0" y="0" width={patternProps.width} height={patternProps.height} {...bgProps} />
{Object.keys(patternProps.parts).map((name) => (
<Part
key={name}
partName={name}
part={patternProps.parts[name]}
app={app}
gist={gist}
updateGist={updateGist}
unsetGist={unsetGist}
/>
))}
</g>
</Svg>
</div>
)
}
export default Draft

View file

@ -0,0 +1,49 @@
import { useTranslation } from 'next-i18next'
import Settings from './settings'
import Draft from '../draft'
import pluginBuilder from './plugin'
const addPages = (gist) => {
const pages = []
}
const PrintLayout = props => {
const { t } = useTranslation(['workbench'])
const draft = new props.pattern(props.gist).use(pluginBuilder(
props.gist?._state?.layout?.forPrinting?.page?.size,
props.gist?._state?.layout?.forPrinting?.page?.orientation,
))
let patternProps
try {
draft.draft()
patternProps = draft.getRenderProps()
} catch(err) {
console.log(err)
}
const bgProps = { fill: "url(#page)" }
return (
<div>
<h2 className="capitalize">
{
t('layoutThing', { thing: props.pattern.config.name })
+ ': '
+ t('forPrinting')
}
</h2>
<div className="m-4">
<Settings {...props} />
</div>
<Draft
draft={draft}
gist={props.gist}
patternProps={patternProps}
bgProps={bgProps}
/>
</div>
)
}
export default PrintLayout

View file

@ -0,0 +1,29 @@
import PageIcon from 'shared/components/icons/page'
import { useTranslation } from 'next-i18next'
const PageOrientationPicker = ({ gist, updateGist }) => {
const { t } = useTranslation(['workbench'])
return (
<button className={`
btn btn-primary flex flex-row gap-2 items-center
hover:text-primary-content
`}
onClick={() => updateGist(
['_state', 'layout', 'forPrinting', 'page', 'orientation'],
gist._state?.layout?.forPrinting?.page?.orientation === 'portrait'
? 'landscape'
: 'portrait'
)}
>
<span className={
gist._state?.layout?.forPrinting?.page?.orientation === 'landscape'
? 'rotate-90'
: ''
}><PageIcon /></span>
<span>{t(`pageOrientation`)}</span>
</button>
)
}
export default PageOrientationPicker

View file

@ -0,0 +1,78 @@
import PageSizeIcon from 'shared/components/icons/page-size'
import { useTranslation } from 'next-i18next'
import Popout from 'shared/components/popout'
const sizes = ['a4', 'a3', 'a2', 'a1', 'a0', 'letter', 'tabloid']
const PageSizePicker = ({ gist, updateGist }) => {
const { t } = useTranslation(['workbench'])
const setSize = size => {
updateGist(
['_state', 'layout', 'forPrinting', 'page', 'size'],
size
)
if (!gist._state?.layout?.forPrinting?.page?.orientation) {
updateGist(
['_state', 'layout', 'forPrinting', 'page', 'orientation'],
'portrait'
)
}
}
if (
!gist._state?.layout?.forPrinting?.page?.size ||
sizes.indexOf(gist._state.layout.forPrinting.page.size) === -1
) return (
<Popout tip>
<h3>{t('startBySelectingAThing', { thing: t('pageSize')})}</h3>
<div className="flex flex-row gap-4">
{sizes.map(size => (
<button
key={size}
onClick={() => setSize(size)}
className="btn btn-primary"
>
<span className="capitalize">
{size}
</span>
</button>
))}
</div>
</Popout>
)
return (
<div className={`dropdown`}>
<div tabIndex="0" className={`
m-0 btn btn-primary flex flex-row gap-2
hover:text-primary-content
`}>
<PageSizeIcon />
<span>{t(`pageSize`)}:</span>
<span className="ml-2 font-bold">{gist._state.layout.forPrinting.page.size}</span>
</div>
<ul
tabIndex="0"
className="p-2 shadow menu dropdown-content bg-base-100 rounded-box w-52"
>
{sizes.map(size => (
<li key={size}>
<button
onClick={() => setSize(size)}
className="btn btn-ghost hover:bg-base-200"
>
<span className="text-base-content capitalize">
{size}
</span>
</button>
</li>
))}
</ul>
</div>
)
}
export default PageSizePicker

View file

@ -0,0 +1,76 @@
const name = 'Pages Plugin'
const version = '1.0.0'
const sizes = {
a4: [ 210, 297 ],
a3: [ 297, 420 ],
a2: [ 420, 594 ],
a1: [ 594, 841 ],
a0: [ 841, 1188 ],
letter: [ 215.9, 279.4 ],
tabloid: [ 279.4, 431.8 ],
}
const drawPage = (x, y, size, orientation) => {
//
}
const pagesPlugin = (size='a4', orientation='portrait') => ({
name,
version,
hooks: {
postLayout: function(pattern) {
// Add part
pattern.parts.pages = pattern.Part('pages')
// Keep part out of layout
pattern.parts.pages.layout = false
// Add pages
const { macro } = pattern.parts.pages.shorthand()
const { height, width } = pattern
macro('addPages', { size, orientation, height, width })
}
},
macros: {
addPages: function(so) {
const ls = so.orientation === 'landscape'
const w = sizes[so.size][ls ? 1 : 0]
const h = sizes[so.size][ls ? 0 : 1]
const cols = Math.ceil(so.width / w)
const rows = Math.ceil(so.height / h)
const { points, Point, paths, Path } = this.shorthand()
let x = 0
let y = 0
let count = 0
for (let row=0;row<rows;row++) {
x=0
for (let col=0;col<cols;col++) {
count++
points[`_pages__row${row}-col${col}-tl`] = new Point(x,y)
points[`_pages__row${row}-col${col}-tr`] = new Point(x+w,y)
points[`_pages__row${row}-col${col}-br`] = new Point(x+w,y+h)
points[`_pages__row${row}-col${col}-bl`] = new Point(x,y+h)
points[`_pages__row${row}-col${col}-circle`] = new Point(x+w/2,y+h/2-24)
.attr('data-circle', 42)
.attr('data-circle-class', 'stroke-4xl muted')
points[`_pages__row${row}-col${col}-text`] = new Point(x+w/2,y+h/2)
.attr('data-text', `${count}`)
.attr('data-text-class', 'text-4xl center bold muted')
paths[`_pages__row${row}-col${col}`] = new Path()
.move(points[`_pages__row${row}-col${col}-tl`])
.line(points[`_pages__row${row}-col${col}-bl`])
.line(points[`_pages__row${row}-col${col}-br`])
.line(points[`_pages__row${row}-col${col}-tr`])
.close()
.attr('class', 'fill-fabric')
.attr('style', `stroke-opacity: 0; fill-opacity: ${(col+row)%2===0 ? 0.03 : 0.09};`)
x += w
}
y += h
}
this.pages = { cols, rows, count: (cols+1)*(rows+1) }
}
}
})
export default pagesPlugin

View file

@ -0,0 +1,20 @@
import { useTranslation } from 'next-i18next'
import PageSizePicker from './pagesize-picker'
import OrientationPicker from './orientation-picker'
const PrintLayoutSettings = props => {
const settingsProps = {
gist: props.gist,
updateGist: props.updateGist
}
return (
<div className="flex flex-row gap-4 justify-center">
<PageSizePicker {...props} />
<OrientationPicker {...props} />
<pre>{JSON.stringify(props.gist._state, null ,2)}</pre>
</div>
)
}
export default PrintLayoutSettings

View file

@ -20,8 +20,21 @@ const View = props => {
title: t('testPattern', { pattern: props.pattern.config.name }),
onClick: () => props.updateGist(['_state', 'view'], 'test')
},
{
name: 'printingLayout',
title: t('layoutThing', { thing: props.pattern.config.name })
+ ': ' + t('forPrinting'),
onClick: () => props.updateGist(['_state', 'view'], 'printingLayout')
},
{
name: 'cuttingLayout',
title: t('layoutThing', { thing: props.pattern.config.name })
+ ': ' + t('forCutting'),
onClick: () => props.updateGist(['_state', 'view'], 'cuttingLayout')
},
{
name: 'export',
title: t('exportThing', { thing: props.pattern.config.name }),
title: t('export'),
onClick: () => props.updateGist(['_state', 'view'], 'export')
},
@ -40,6 +53,11 @@ const View = props => {
title: t('JSON'),
onClick: () => props.updateGist(['_state', 'view'], 'json')
},
{
name: 'edit',
title: t('editThing', { thing: 'YAML' }),
onClick: () => props.updateGist(['_state', 'view'], 'edit')
},
]
return (

View file

@ -16,11 +16,15 @@ import ExportDraft from 'shared/components/workbench/export.js'
import GistAsJson from 'shared/components/workbench/json.js'
import GistAsYaml from 'shared/components/workbench/yaml.js'
import DraftEvents from 'shared/components/workbench/events.js'
import CutLayout from 'shared/components/workbench/layout/cut'
import PrintLayout from 'shared/components/workbench/layout/print'
const views = {
measurements: Measurements,
draft: LabDraft,
test: LabSample,
printingLayout: PrintLayout,
cuttingLayout: CutLayout,
export: ExportDraft,
events: DraftEvents,
yaml: GistAsYaml,

View file

@ -57,6 +57,11 @@ svg.freesewing.pattern {
.center { text-anchor: middle; }
.right { text-anchor: end; }
/* muted page numbers */
.muted {
opacity: 0.1;
}
/* Developer view */
g.develop.point {
circle.center {