2023-09-05 20:38:47 +02:00
|
|
|
import { getIds } from './utils.mjs'
|
|
|
|
|
2023-09-05 11:05:14 +02:00
|
|
|
/*
|
|
|
|
* Defaults for the title macro
|
|
|
|
*/
|
|
|
|
const macroDefaults = {
|
|
|
|
align: 'left',
|
|
|
|
append: false,
|
|
|
|
cutlist: true,
|
|
|
|
dy: 8,
|
|
|
|
id: 'title',
|
2023-09-05 12:05:47 +02:00
|
|
|
force: false,
|
2023-09-05 11:05:14 +02:00
|
|
|
nr: 1,
|
|
|
|
rotation: 0,
|
|
|
|
scale: 1,
|
2023-09-06 08:14:49 +02:00
|
|
|
title: 'plugin-annotations:noName',
|
2023-09-05 11:18:19 +02:00
|
|
|
classes: {
|
|
|
|
cutlist: 'text-md fill-current',
|
|
|
|
date: 'text-sm fill-current',
|
|
|
|
for: 'fill-current font-bold',
|
|
|
|
name: 'fill-note',
|
|
|
|
nr: 'text-4xl fill-note font-bold',
|
|
|
|
title: 'text-lg fill-current font-bold',
|
|
|
|
},
|
2023-09-05 11:05:14 +02:00
|
|
|
}
|
2023-04-15 15:14:56 +02:00
|
|
|
|
2023-09-05 11:05:14 +02:00
|
|
|
/*
|
|
|
|
* Removing all this is easy as all IDs are available in the store
|
|
|
|
* and all we need to remove are points.
|
|
|
|
*/
|
|
|
|
const removeTitleMacro = function (id = macroDefaults.id, { points, store, part }) {
|
|
|
|
for (const pid of Object.values(
|
|
|
|
store.get(['parts', part.name, 'macros', 'title', 'ids', id, 'points'], {})
|
|
|
|
))
|
|
|
|
delete points[pid]
|
|
|
|
}
|
2023-04-15 15:14:56 +02:00
|
|
|
|
2023-09-05 11:05:14 +02:00
|
|
|
/*
|
|
|
|
* The title macro
|
|
|
|
*/
|
2023-09-05 12:05:47 +02:00
|
|
|
const addTitleMacro = function (
|
|
|
|
config,
|
|
|
|
{ Point, points, scale, locale, store, part, log, complete }
|
|
|
|
) {
|
|
|
|
/*
|
|
|
|
* Don't add a title when complete is false, unless force is true
|
|
|
|
*/
|
|
|
|
if (!complete && !config.force) return
|
|
|
|
|
2023-09-05 11:05:14 +02:00
|
|
|
/*
|
2023-09-05 12:05:47 +02:00
|
|
|
* Merge macro defaults with user-provided config to create the macro config (mc)
|
2023-09-05 11:05:14 +02:00
|
|
|
*/
|
2023-09-05 12:05:47 +02:00
|
|
|
const mc = {
|
2023-09-05 11:18:19 +02:00
|
|
|
...macroDefaults,
|
|
|
|
...config,
|
|
|
|
classes: macroDefaults.classes,
|
|
|
|
}
|
2023-09-05 12:05:47 +02:00
|
|
|
if (config.classes) mc.classes = { ...mc.classes, ...config.classes }
|
2023-09-05 11:05:14 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Take global scale setting into account
|
|
|
|
*/
|
2023-09-05 12:05:47 +02:00
|
|
|
mc.scale = mc.scale * scale
|
2023-04-18 15:31:37 -04:00
|
|
|
|
2023-09-05 11:05:14 +02:00
|
|
|
/*
|
2023-09-05 12:05:47 +02:00
|
|
|
* Make sure mc.at is a Point so we can anchor the title
|
2023-09-05 11:05:14 +02:00
|
|
|
*/
|
2023-09-05 12:05:47 +02:00
|
|
|
if (!mc.at || typeof mc.at.attr !== 'function') {
|
2023-09-05 11:05:14 +02:00
|
|
|
log.warn(`Title macro called without a valid anchor point. Anchoring title at (0,0).`)
|
2023-09-05 12:05:47 +02:00
|
|
|
mc.at = new Point(0, 0)
|
2023-09-05 11:05:14 +02:00
|
|
|
}
|
2023-04-18 15:31:37 -04:00
|
|
|
|
2023-09-05 11:05:14 +02:00
|
|
|
/*
|
2023-09-05 12:05:47 +02:00
|
|
|
* Make sure mc.align is a valid alignment
|
2023-09-05 11:05:14 +02:00
|
|
|
*/
|
2023-09-05 12:05:47 +02:00
|
|
|
if (!['left', 'right', 'center'].includes(mc.align)) {
|
|
|
|
log.warn(`Title macro called with invalid alignement (${mc.align}). Left-aligning title.`)
|
|
|
|
mc.align = 'left'
|
2023-04-15 15:14:56 +02:00
|
|
|
}
|
2023-04-18 15:31:37 -04:00
|
|
|
|
2023-09-05 11:05:14 +02:00
|
|
|
/*
|
|
|
|
* Calculate the transform only once
|
|
|
|
*/
|
|
|
|
const transform =
|
|
|
|
'matrix(' +
|
2023-09-05 12:05:47 +02:00
|
|
|
`${mc.scale}, 0, 0, ${mc.scale}, ` +
|
|
|
|
`${mc.at.x - mc.scale * mc.at.x}, ` +
|
|
|
|
`${mc.at.y - mc.scale * mc.at.y}` +
|
|
|
|
`) rotate(${mc.rotation} ${mc.at.x} ${mc.at.y})`
|
2023-09-05 11:05:14 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Get the list of IDs
|
|
|
|
* Initialize the verticle cadence
|
|
|
|
*/
|
2023-09-05 20:38:47 +02:00
|
|
|
const ids = getIds(['cutlist', 'date', 'for', 'name', 'nr', 'title'], mc.id, 'title')
|
|
|
|
|
2023-09-05 12:05:47 +02:00
|
|
|
let shift = mc.dy
|
2023-09-05 11:05:14 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Title: nr
|
|
|
|
*/
|
2023-09-05 12:05:47 +02:00
|
|
|
if (typeof mc.nr !== 'undefined') {
|
|
|
|
points[ids.nr] = mc.at
|
2023-09-05 11:05:14 +02:00
|
|
|
.clone()
|
2023-09-05 12:05:47 +02:00
|
|
|
.attr('data-text', mc.nr, mc.append ? false : true)
|
|
|
|
.attr('data-text-class', `${mc.classes.nr} ${mc.align}`)
|
2023-09-05 11:05:14 +02:00
|
|
|
.attr('data-text-transform', transform)
|
2023-09-05 12:05:47 +02:00
|
|
|
store.set(['partNumbers', part.name], mc.nr)
|
2023-09-05 11:05:14 +02:00
|
|
|
} else delete ids.nr
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Title: title
|
|
|
|
*/
|
2023-09-05 12:05:47 +02:00
|
|
|
if (mc.title) {
|
|
|
|
points[ids.title] = mc.at
|
2023-09-05 11:05:14 +02:00
|
|
|
.clone()
|
|
|
|
.shift(-90, shift)
|
2023-09-05 12:05:47 +02:00
|
|
|
.attr('data-text', mc.title, mc.append ? false : true)
|
|
|
|
.attr('data-text-class', `${mc.classes.title} ${mc.align}`)
|
2023-09-05 11:05:14 +02:00
|
|
|
.attr('data-text-transform', transform)
|
2023-09-05 12:05:47 +02:00
|
|
|
shift += mc.dy
|
|
|
|
store.set(['partTitles', part.name], mc.title)
|
2023-09-05 11:05:14 +02:00
|
|
|
} else delete ids.title
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Title: cutlist
|
|
|
|
*/
|
2023-09-05 12:05:47 +02:00
|
|
|
if (mc.cutlist) {
|
2023-09-05 11:05:14 +02:00
|
|
|
/*
|
|
|
|
* Get cutlist instructions from the store, only proceed if the list is available
|
|
|
|
*/
|
|
|
|
const partCutlist = store.get(['cutlist', part.name], null)
|
|
|
|
if (partCutlist?.materials) {
|
|
|
|
/*
|
|
|
|
* Iterate over materials
|
|
|
|
*/
|
|
|
|
for (const [material, instructions] of Object.entries(partCutlist.materials)) {
|
|
|
|
instructions.forEach(({ cut, identical, bias, ignoreOnFold }, c) => {
|
|
|
|
/*
|
|
|
|
* Create point
|
|
|
|
*/
|
|
|
|
const id = `${ids.cutlist}_${material}_${c}`
|
|
|
|
ids[`cutlist_${material}_${c}`] = id
|
2023-09-05 12:05:47 +02:00
|
|
|
points[id] = mc.at
|
2023-09-05 11:05:14 +02:00
|
|
|
.clone()
|
|
|
|
.shift(-90, shift)
|
2023-09-06 08:14:49 +02:00
|
|
|
.attr('data-text', 'plugin-annotations:cut')
|
2023-09-05 12:05:47 +02:00
|
|
|
.attr('data-text-class', `${mc.classes.cutlist} ${mc.align}`)
|
2023-09-05 11:05:14 +02:00
|
|
|
.attr('data-text-transform', transform)
|
|
|
|
.addText(cut)
|
2023-09-05 12:05:47 +02:00
|
|
|
shift += mc.dy
|
2023-09-05 11:05:14 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Add instructions if parts are mirrored
|
|
|
|
*/
|
2023-09-06 08:14:49 +02:00
|
|
|
if (!identical && cut > 1) points[id].addText('plugin-annotations:mirrored')
|
2023-09-05 11:05:14 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Add instructions if parts are cut on fold
|
|
|
|
*/
|
|
|
|
if (partCutlist.cutOnFold && !ignoreOnFold)
|
2023-09-06 08:14:49 +02:00
|
|
|
points[id].addText(
|
|
|
|
bias ? 'plugin-annotations:onFoldAndBias' : 'plugin-annotations:onFold'
|
|
|
|
)
|
2023-09-05 11:05:14 +02:00
|
|
|
/*
|
|
|
|
* Add instructions if parts on on bias
|
2023-09-06 08:14:49 +02:00
|
|
|
*/ else if (bias) points[id].addText('plugin-annotations:onBias')
|
2023-09-05 11:05:14 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Add 'from' (material) text
|
|
|
|
*/
|
2023-09-06 08:14:49 +02:00
|
|
|
points[id].addText('plugin-annotations:from').addText('plugin-annotations:' + material)
|
2023-09-05 11:05:14 +02:00
|
|
|
})
|
|
|
|
}
|
2023-04-18 15:31:37 -04:00
|
|
|
}
|
2023-09-05 11:05:14 +02:00
|
|
|
} else delete ids.cutlist
|
2023-04-18 15:31:37 -04:00
|
|
|
|
2023-09-05 11:05:14 +02:00
|
|
|
/*
|
|
|
|
* Title: Design name
|
|
|
|
*/
|
2023-09-05 12:05:47 +02:00
|
|
|
points[ids.name] = mc.at
|
2023-09-05 11:05:14 +02:00
|
|
|
.clone()
|
|
|
|
.shift(-90, shift)
|
|
|
|
.attr(
|
|
|
|
'data-text',
|
2023-09-06 08:14:49 +02:00
|
|
|
`${(store.data?.name || 'plugin-annotations:noName').replace('@freesewing/', '')} v ${
|
|
|
|
store.data?.version || 'plugin-annotations:noVersion'
|
2023-09-05 11:05:14 +02:00
|
|
|
}`
|
|
|
|
)
|
2023-09-05 12:05:47 +02:00
|
|
|
.attr('data-text-class', `${mc.classes.name} ${mc.align}`)
|
2023-09-05 11:05:14 +02:00
|
|
|
.attr('data-text-transform', transform)
|
2023-09-05 12:05:47 +02:00
|
|
|
shift += mc.dy
|
2023-04-18 15:31:37 -04:00
|
|
|
|
2023-09-05 11:05:14 +02:00
|
|
|
/*
|
|
|
|
* Title: For (measurements set)
|
|
|
|
*/
|
2023-04-15 15:14:56 +02:00
|
|
|
if (store.data.for) {
|
2023-09-05 12:05:47 +02:00
|
|
|
points[ids.for] = mc.at
|
2023-09-05 11:05:14 +02:00
|
|
|
.shift(-90, shift)
|
|
|
|
.attr('data-text', `(${store.data.for})`)
|
2023-09-05 12:05:47 +02:00
|
|
|
.attr('data-text-class', `${mc.classes.for} ${mc.align}`)
|
2023-09-07 10:29:19 +02:00
|
|
|
.attr('data-text-transform', transform)
|
2023-09-05 12:05:47 +02:00
|
|
|
shift += mc.dy
|
2023-09-05 11:05:14 +02:00
|
|
|
} else delete ids.for
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Title: Date
|
|
|
|
*/
|
2023-09-05 12:05:47 +02:00
|
|
|
points[ids.date] = mc.at
|
2023-09-05 11:05:14 +02:00
|
|
|
.shift(-90, shift)
|
|
|
|
.attr(
|
|
|
|
'data-text',
|
|
|
|
new Date().toLocaleString(locale || 'en', {
|
|
|
|
weekday: 'long',
|
|
|
|
year: 'numeric',
|
|
|
|
month: 'short',
|
|
|
|
day: 'numeric',
|
|
|
|
})
|
2023-05-04 15:24:48 -07:00
|
|
|
)
|
2023-09-05 12:05:47 +02:00
|
|
|
.attr('data-text-class', `${mc.classes.date} ${mc.align}`)
|
2023-09-07 10:29:19 +02:00
|
|
|
.attr('data-text-transform', transform)
|
2023-09-05 11:05:14 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Store all IDs in the store so we can remove this macro with rmtitle
|
|
|
|
*/
|
2023-09-05 12:05:47 +02:00
|
|
|
store.set(['parts', part.name, 'macros', 'title', 'ids', mc.id, 'points'], ids)
|
2023-04-15 15:14:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Export macros
|
2023-09-05 11:05:14 +02:00
|
|
|
export const titleMacros = {
|
|
|
|
title: addTitleMacro,
|
|
|
|
rmtitle: removeTitleMacro,
|
|
|
|
}
|