Comandos, menús y cuadros de diálogo
Un paquete de extensión puede añadir elementos a la ventana de ParametriQ CAD: comandos que se ejecutan con la API de dibujo y se deshacen en un solo paso, elementos de menú y botones de la barra de herramientas que los ejecutan, formularios y selecciones en el dibujo que piden datos, y un espacio de trabajo simplificado con algunos elementos propios de la aplicación ocultos. El paquete solo describe estos elementos; la aplicación crea los controles, con su propio estilo, de modo que un paquete sigue funcionando cuando cambia el aspecto de la aplicación.
Un paquete
Un paquete es una carpeta dentro de su carpeta de extensiones (Archivo › Extensiones › Abrir carpeta de
extensiones), o en la de la aplicación, con un manifest.json:
QuickBox/
manifest.json
main.js what it declares
strings/en.json its text in English (es.json, zh-Hans.json for Spanish and Chinese)
icons/quickbox.svg its icons
{
"id": "quickBox",
"name": "Quick box",
"version": "1.0",
"main": "main.js",
"description": "A regular slotted box from three sizes.",
"permissions": ["commands", "menus", "dialogs", "pick", "drawing", "designs"],
"enabled": true
}
| Propiedad | Significado |
|---|---|
id |
Su id: letras, dígitos, _ y -. Empiece con él los ids de sus comandos (quickBox.box). Un paquete suyo con el mismo id que uno de la aplicación ocupa su lugar. |
name, version, description, author |
Se muestran en Archivo › Extensiones › Administrar extensiones…. |
main |
El script que declara lo que añade (main.js si se omite). |
permissions |
Lo que puede hacer (véase más abajo). Cualquier otra cosa que intente se rechaza, con un mensaje que nombra el permiso que necesita. |
enabled |
false: está desactivado hasta que se active en Administrar extensiones… (para una configuración especial, como el espacio de trabajo de un operario). |
Un archivo .js suelto en la carpeta de extensiones puede declarar posprocesadores, reglas de diseño, plantillas,
informes y extensiones de guardado, pero no comandos, menús ni cuadros de diálogo: para eso hace falta un paquete.
Permisos
| Permiso | Le permite |
|---|---|
commands |
Declarar comandos con command({…}). |
menus |
Añadir elementos de menú, submenús, botones y grupos de la barra de herramientas. |
customise |
Ocultar y mover los elementos de menú, los botones y los grupos propios de la aplicación. |
dialogs |
Preguntar con ui.form, ui.message, ui.confirm y mostrar ui.progress. |
pick |
Pedir al usuario que seleccione en el dibujo con ui.pick. |
drawing |
Modificar el dibujo desde un comando (sin él, un comando solo puede leerlo). |
designs |
Abrir los diseños paramétricos de la biblioteca como dibujos nuevos con ui.runDesign. |
Activar y desactivar paquetes
Archivo › Extensiones › Administrar extensiones… enumera los paquetes, con lo que usa cada uno; active o desactive
cada uno y elija Aplicar: las extensiones se vuelven a leer y la ventana cambia de inmediato. Su elección se guarda
en packages.json, en su carpeta de extensiones.
Sus textos
t("key") da el texto del paquete para una clave en el idioma en que se muestra la aplicación: de strings/es.json
para español, de strings/zh-Hans.json para chino y de strings/en.json para inglés, o para una clave que no tenga
la tabla del idioma. t("count", n) rellena {0} (y {1} …) en el texto con lo que sigue a la clave.
{ "boxTitle": "_Quick Box…", "pickCentre": "Click the middle of the hand hole" }
Iconos
Un icono es un archivo SVG de la carpeta del paquete, nombrado a partir de ella ("icons/quickbox.svg"), o uno de los
propios de la aplicación, por su nombre ("tuckflaptool"). Dibújelo en un viewBox cuadrado con currentColor para
sus líneas: la aplicación las colorea para el tema claro o el oscuro, como sus propios iconos.
Comandos
command({
id: "quickBox.handHole",
title: t("handHoleTitle"), // "_Hand Hole…"
description: t("handHoleDescription"),
icon: "icons/handhole.svg",
shortcut: "Ctrl+Shift+H",
industries: ["Packaging"],
enabledWhen: "drawing",
async run(state) {
const centre = await ui.pick({ kind: "point", prompt: t("pickCentre") });
if (!centre) return; // Esc
circle(centre, 15);
}
});
| Propiedad | Significado |
|---|---|
id |
Su id, único entre los comandos instalados: el nombre con el que lo designan los elementos de menú y los botones. |
title |
Su etiqueta; _ delante de su tecla de acceso. |
description |
Se muestra como su información sobre herramientas. |
icon |
Su icono. |
shortcut |
Un atajo de teclado (Ctrl+Shift+B). Uno que ya usan la aplicación u otro comando se omite, y se indica al leer las extensiones. |
industries |
Los sectores para los que se ofrece (si se omite: todos). Sus elementos de menú y sus botones solo se muestran cuando el dibujo es de uno de ellos (o General, o con Mostrar todas las herramientas activado). |
enabledWhen |
"drawing" (hay un dibujo abierto: el valor predeterminado), "selection" (hay algo seleccionado), "always", o una función que recibe el estado indicado más abajo y devuelve true cuando se puede ejecutar. |
run(state) |
Lo que hace. state es {hasDrawing, industry, selected} (selected: los ids de los elementos seleccionados). |
run trabaja sobre el dibujo en curso con la API de dibujo (line, newPoint, setVariable,
command …), como hace una plantilla. Todo lo que modifica se deshace en un solo paso (Edición › Deshacer
nombra el comando). Si algo sale mal (un error que no captura), lo que modificó se revierte, y el mensaje indica el
motivo, con el archivo y la línea.
Los comandos se ejecutan desde los elementos de menú y los botones que los nombran, con su atajo de teclado y desde Ejecutar comando….
Ejecutar comando…
Archivo › Extensiones › Ejecutar comando… (Ctrl+Shift+P) abre la paleta de comandos (Ver › Paleta de comandos…, Ctrl+K), que encuentra cualquier comando escribiendo parte de su nombre: los comandos de las extensiones y todos los elementos de los menús que se pueden usar en ese momento (se muestran con los menús en los que están: Archivo › Exportar), las herramientas, los ajustes, los dibujos recientes y las páginas de ayuda. Cada palabra escrita debe estar en el nombre o en sus menús; las teclas de flecha eligen y Enter lo ejecuta.
Menús y barra de herramientas
uiExtension({…}) describe lo que un paquete añade a los menús y a la barra de herramientas, y qué elementos propios
de la aplicación oculta o mueve:
uiExtension({
name: "Quick box menus and toolbar",
menus: [
{ menu: "Tool/Packaging", command: "quickBox.box" },
{ menu: "File/Export", command: "quickBox.export" },
{ menu: "Extensions", submenu: "quickBox", title: "_Quick Box" },
{ menu: "Extensions/quickBox", command: "quickBox.handHole" },
{ menu: "File", separator: true, after: "ExportForPalletSoftware" }
],
toolbar: [
{ group: "Packaging", command: "quickBox.box", after: "CreaseOffset" },
{ group: "quickBox", title: "Quick box", after: "Packaging", industries: ["Packaging"],
commands: ["quickBox.box", "quickBox.handHole"] }
]
});
Elementos de menú
| Propiedad | Significado |
|---|---|
menu |
Dónde va: la ruta de un menú (File, Extensions, Tool/Packaging). Una ruta que termina en un elemento lo coloca después de ese elemento (File/Export); una ruta que termina en un encabezado, al final de la sección de ese encabezado (Tool/Packaging: las herramientas de envases en Herramienta › Herramientas de Envases y embalajes). |
command |
El comando que ejecuta. |
submenu, title |
En lugar de un comando: un submenú, su id y su etiqueta. Los elementos posteriores entran en él por su ruta (Extensions/quickBox). |
separator |
true: una línea en lugar de un elemento. |
before, after |
El id del elemento (en el mismo menú) antes o después del que va. |
title |
Su etiqueta, si no es la de su comando. |
industries |
Solo se muestra para estos sectores (si se omite: los de su comando; en la sección de un sector, ese sector). |
Botones y grupos de la barra de herramientas
| Propiedad | Significado |
|---|---|
group |
El id del grupo al que van los botones: uno de la aplicación (véase más abajo) o uno nuevo. |
command, commands |
El comando, o los comandos, cuyos botones se añaden, en orden. |
title |
Un grupo nuevo: su nombre (se muestra como su información sobre herramientas). |
before, after |
El id de un botón del grupo antes o después del que va; para un grupo nuevo, el id de un grupo. Un grupo nuevo va al final de la barra de herramientas si no se indica ninguno de los dos. |
industries |
Solo se muestra para estos sectores (un grupo nuevo; si no, los de sus comandos). |
Ids
Los menús, los elementos, los botones y los grupos se designan con ids que son los mismos sea cual sea el idioma en
que se muestra la aplicación, y que se escriben en rutas con /: File/Export, Draw/Bezier. Una ruta cuyo primer
paso no es un menú de la barra de menús se busca en cualquier parte (Bezier: todos los botones Bézier;
Tool/Packaging: el encabezado dentro del submenú Herramienta). Extensions es Archivo › Extensiones.
| Qué | Su id | Ejemplos |
|---|---|---|
| Los menús de la barra de menús | Sus nombres en inglés | File, Edit, Production, 3D, View, Help (Herramienta está en Edición: Tool, o Edit/Tool) |
| Elementos de menú y submenús | Sus nombres en inglés, sin espacios ni signos de puntuación | File/NewFromTemplate, File/Export, File/SendToMachine, File/Extensions, Edit/Constrain, Edit/CheckParametric, Tool/Line |
| Los submenús en los que se agrupan los elementos de un menú | Sus nombres en inglés; Importar y Exportar de Archivo y de 3D, ImportMenu y ExportMenu, e Imposición de Herramienta, ToolLayout (los elementos llevan los nombres simples). Una ruta a un elemento de uno de ellos lo encuentra ahí (File/Export, Tool/Line) |
Tool/Draw, Tool/Modify, Tool/Dimensions, Tool/Insert, Tool/MeasureAndInspect, Tool/ToolLayout, File/ImportMenu, File/ExportMenu, 3D/Display, 3D/Folding, 3D/MeasureAndAnnotate, 3D/ModelsAndProducts, 3D/ExportMenu |
| Herramienta › Herramientas de sector | IndustryTools; sus encabezados, por sector |
Tool/IndustryTools, Tool/Production, Tool/Packaging, Tool/Cutting, Tool/SheetMetal |
| El elemento o el botón de una herramienta | El nombre de la herramienta | Line, Fillet, TuckFlap, FlapOrSeam, RegistrationMark |
| Grupos de la barra de herramientas | Lo que contienen | Select, Draw, Modify, Annotate, Insert, Inquiry; en las herramientas de sector (IndustryTools): Production, Cutting y cada sector (Packaging, SheetMetal …) |
El botón de una herramienta compartida (FlapOrSeam, Holes, BridgeOrTab …: véase Herramientas) está
en el grupo de cada uno de sus sectores: Packaging/FlapOrSeam es el del grupo Packaging, y FlapOrSeam, todos
ellos.
Ocultar y mover los elementos propios de la aplicación
Un paquete con el permiso customise puede ocultar elementos de menú, menús enteros, botones y grupos de la barra de
herramientas, y moverlos: por ejemplo, para un operario que solo abre, comprueba y envía dibujos a la máquina.
uiExtension({
name: "Operator workspace",
hide: {
menus: ["File/NewFromTemplate", "File/SendByEmail", "Edit/Constrain", "3D"],
toolbar: ["Draw/Bezier", "Draw/Spline", "Annotate"]
},
move: {
menus: [{ item: "File/SendToMachine", after: "Save" }],
toolbar: [{ item: "Inquiry", before: "Draw" }]
}
});
Un movimiento nombra el elemento y adónde va: before o after un id del mismo menú o grupo, o una ruta a cualquier
parte. Se quita una línea separadora que queda al principio o al final de un menú, o junto a otra, por lo que se ha
ocultado. Los atajos de teclado siguen funcionando para lo que está oculto. La aplicación incluye este paquete
(Operator workspace), desactivado.
Teclas de acceso
La tecla de acceso de un elemento de menú es la letra que sigue al _ en su título. Si otro elemento del mismo menú ya
la usa (para los sectores en los que se muestra: en Herramienta › Herramientas de Envases y embalajes, los
elementos que muestra un dibujo de envases), la aplicación le da la primera letra libre con la que empieza una palabra
de su título y, si no hay ninguna, cualquier letra libre de él; si todas las letras están ocupadas, conserva la suya,
compartida. Recargar extensiones indica lo que ha cambiado.
Qué puede salir mal
Un id o un menú que no existe, un comando que ningún paquete declara o un atajo de teclado ya usado se indican al leer las extensiones (como con un archivo de extensión que no se puede leer), con el nombre del paquete; el resto de lo que añade se añade igualmente.
Cuadros de diálogo y selecciones
El run de un comando puede preguntar cosas con las funciones de ui. Cada una devuelve una promesa: run es una
función async que la espera con await, y la aplicación sigue funcionando (dibujando, moviendo la vista) mientras el
usuario responde. Cada fragmento del comando entre dos await puede ejecutarse durante diez segundos y un millón de
instrucciones, como cualquier llamada de extensión.
| Función | Devuelve | Permiso |
|---|---|---|
ui.form({ title, fields, … }) |
Los valores por id de campo, o null si se cancela. |
dialogs |
ui.pick({ kind, prompt, filter }) |
Lo seleccionado, o null si se cancela (Esc). |
pick |
ui.message(text, { title, kind }) |
(Al cerrarse.) kind: "information", "warning" o "error". |
dialogs |
ui.confirm(text, { title }) |
true para Sí. |
dialogs |
ui.progress({ title, cancellable }) |
Una ventana de progreso: await p.update(fraction, text) muestra cuánto ha avanzado y devuelve false en cuanto se elige Cancelar; p.cancelled(); p.close() (se cierra de todos modos cuando termina el comando). |
dialogs |
ui.runDesign(name, values) |
Abre un diseño de la biblioteca como dibujo nuevo con los valores indicados, como hace Archivo › Ejecutar paramétrico: true si pudo. name: "Packaging/FEFCO 0201 Regular slotted container", o su propio nombre si solo un diseño lo tiene; una opción de lista, por su texto. |
designs |
Solo se pueden usar mientras se ejecuta un comando.
Formularios
const sizes = await ui.form({
title: "Quick box",
description: "The box's inside sizes.",
ok: "Make Box",
fields: [
{ id: "L", label: "Length", type: "length", default: 300, min: 10, max: 2000 },
{ id: "W", label: "Width", type: "length", default: 200, min: 10 },
{ id: "board", label: "Board", type: "choice", choices: ["E flute", "B flute"], default: "B flute" },
{ id: "lid", label: "Lid", type: "check", default: true },
{ id: "at", label: "Corner", type: "point", default: { x: 0, y: 0 } }
],
validate: v => v.W > v.L ? "The width is longer than the length." : null
});
if (!sizes) return;
El formulario se muestra como los cuadros de diálogo de opciones de la aplicación, una fila por campo.
| Propiedad del campo | Significado |
|---|---|
id |
El nombre con el que se devuelve su valor. |
label, description |
Lo que dice su fila, y debajo de ella. |
type |
"number", "integer", "length" (en las unidades del dibujo), "angle" (grados), "text", "choice", "check" (sí o no) o "point" ({x, y}). Si se omite: según default (o "choice" si hay choices). |
default |
Su valor inicial. |
choices |
Las opciones de una lista de opciones. |
min, max |
Los límites de un número. |
unit |
Se muestra después de un número. |
required |
true: el texto no puede quedar vacío. |
Antes de que se cierre el formulario, cada valor se comprueba con su campo (un número dentro de sus límites, un número
entero, una opción de su lista, un texto indicado) y después con validate(values) si el formulario lo tiene: un
mensaje (o false) indica lo que está mal, y el formulario se vuelve a mostrar con él. Los valores se recuerdan para la
próxima vez que se muestre el formulario (remember: false: parte cada vez de los valores predeterminados).
Selecciones
const at = await ui.pick({ kind: "point", prompt: "Click the middle of the hole" });
const edge = await ui.pick({ kind: "element", filter: { kinds: ["LINE", "ARC"], cutting: true } });
const outlines = await ui.pick({ kind: "elements", filter: { closed: true } });
| Tipo | El usuario | Devuelve |
|---|---|---|
"point" |
Hace clic en un lugar. | {x, y}; y id si hizo clic sobre un punto, para que lo que se cree sobre él lo siga. |
"element" |
Hace clic en un elemento. | El elemento, tal como lo describe drawingInfo() (id, kind, layer, length …). |
"elements" |
Hace clic en elementos (otra vez: se quita) y luego hace clic con el botón derecho. | Una lista de ellos. |
filter limita los elementos que se iluminan y se pueden seleccionar: kinds ("LINE", "ARC", "CIRCLE" …),
layers (sus números), closed y cutting (true o false). La indicación se muestra en la ventana Interactiva y
en la barra de estado.
Cómo funciona la espera
El motor ejecuta por sí mismo las promesas y las funciones async de JavaScript. Cuando run espera una función de
ui, el comando se detiene ahí y la aplicación muestra el cuadro de diálogo; la ventana de la aplicación sigue
funcionando. Cuando el usuario responde, el comando continúa desde el await con la respuesta, en el propio hilo de la
aplicación, de modo que nunca se ejecuta a la vez que otra cosa en el dibujo. Solo se ejecuta un comando a la vez:
hasta que termina, no se pueden elegir los demás. Un comando que nunca espera se ejecuta de principio a fin, como
cualquier llamada de extensión.
Un ejemplo: Quick box
La aplicación incluye el paquete Quick box (en su carpeta de extensiones): Quick Box… pide la longitud, la
anchura, la profundidad y el cartón de una caja y abre con ellos el diseño FEFCO 0201 de la biblioteca; Hand Hole…
pide un punto y un tamaño y dibuja allí un coliso redondeado en la capa de corte, con variables para su anchura y su
altura (HH1W, HH1H) para que siga siendo paramétrico. Ambos están en Herramienta › Herramientas de Envases y
embalajes y en un grupo propio de la barra de herramientas después del grupo Packaging, que se muestra en los
dibujos de envases. Copie su carpeta a la suya, dele un id nuevo y modifíquelo para crear el suyo.
Véase también: Extensiones, API de dibujo, Plantillas, Sectores.