TrayLayout: Make generation a one step operation in the web UI

Add Java Script for generating the layout from sx and sy
Drop special handling in boxesserver
Add .UI attribute to Boxes class to allow behaving differntly on different UIs
Traylayout is still filtered out from Inkscape INX file generation
Slightly adjust layout format of GridfinityTrayLayout

Co-authored-by: Florian Festi <florian@festi.info>
This commit is contained in:
caleb crome 2023-03-02 15:14:50 +01:00 committed by Florian Festi
parent b807cc99ff
commit 0b986eeb0c
5 changed files with 108 additions and 36 deletions

View File

@ -285,6 +285,7 @@ class Boxes:
webinterface = True
ui_group = "Misc"
UI = ""
description: str = "" # Markdown syntax is supported

View File

@ -1,10 +1,10 @@
import boxes
from boxes import Boxes
from boxes.generators.traylayout import TrayLayout, TrayLayout2
from boxes.generators.traylayout import TrayLayout
from boxes.Color import Color
from boxes import restore
class GridfinityTrayLayout(TrayLayout2):
class GridfinityTrayLayout(TrayLayout):
"""A Gridfinity Tray Generator based on TrayLayout"""
description = """

View File

@ -19,7 +19,7 @@ import boxes
from boxes import *
class TrayLayout(Boxes):
class TrayLayoutFile(Boxes):
"""Generate a layout file for a typetray."""
# This class generates the skeleton text file that can then be edited
# to describe the actual box
@ -29,7 +29,7 @@ The layout is based on a grid of sizes in x and y direction.
Choose how many distances you need in both directions.
The actual sizes and all other settings can be entered in the second step."""
webinterface = True
webinterface = False
ui_group = "Tray"
@ -83,13 +83,13 @@ The actual sizes and all other settings can be entered in the second step."""
f.write(str(self))
class TrayLayout2(Boxes):
class TrayLayout(Boxes):
"""Generate a typetray from a layout file."""
# This class reads in the layout either from a file (with --input) or
# as string (with --layout) and turns it into a drawing for a box.
webinterface = True
ui_group = "Tray"
description = """This is a two step process. This is step 2.
Edit the layout text graphics to adjust your tray.
@ -98,19 +98,19 @@ vertical bars representing the walls with a space character to remove the walls.
You can replace the space characters representing the floor by a "X" to remove the floor for this compartment.
"""
def __init__(self, input=None, webargs=False) -> None:
Boxes.__init__(self)
def __init__(self) -> None:
super().__init__()
self.addSettingsArgs(boxes.edges.FingerJointSettings)
self.buildArgParser("h", "hi", "outside")
if not webargs:
self.buildArgParser("h", "hi", "outside", "sx", "sy")
if self.UI == "web":
self.argparser.add_argument(
"--layout", action="store", type=str, default="")
else:
self.argparser.add_argument(
"--input", action="store", type=argparse.FileType('r'),
default="traylayout.txt",
help="layout file")
self.layout = None
else:
self.argparser.add_argument(
"--layout", action="store", type=str, default="")
def vWalls(self, x: int, y: int) -> int:
"""Number of vertical walls at a crossing."""

View File

@ -113,11 +113,11 @@ class BServer:
def __init__(self, url_prefix="", static_url="static") -> None:
self.boxes = {b.__name__: b for b in boxes.generators.getAllBoxGenerators().values() if b.webinterface}
self.boxes['TrayLayout2'] = boxes.generators.traylayout.TrayLayout2 # type: ignore # no attribute "traylayout"
self.groups = boxes.generators.ui_groups
self.groups_by_name = boxes.generators.ui_groups_by_name
for name, box in self.boxes.items():
box.UI = "web"
self.groups_by_name.get(box.ui_group,
self.groups_by_name["Misc"]).add(box)
@ -351,8 +351,6 @@ class BServer:
<div id="{nr}">\n <ul>\n''')
for box in group.generators:
name = box.__name__
if name in ("TrayLayout2",):
continue
docs = ""
if box.__doc__:
docs = " - " + _(box.__doc__)
@ -595,10 +593,7 @@ class BServer:
self._cache[lang_name] = list(self.genPageMenu(lang))
return self._cache[lang_name]
if name == "TrayLayout2":
box = box_cls(self, webargs=True)
else:
box = box_cls()
box = box_cls()
box.translations = lang
@ -618,18 +613,6 @@ class BServer:
except ArgumentParserError as e:
start_response(status, headers)
return self.genPageError(name, e, lang)
if name == "TrayLayout":
start_response(status, headers)
box.fillDefault(box.sx, box.sy)
layout2 = boxes.generators.traylayout.TrayLayout2(self, webargs=True)
layout2.argparser.set_defaults(layout=str(box))
return self.args2html(name, layout2, lang, action="TrayLayout2")
if name == "TrayLayout2":
try:
box.parse(box.layout.split("\n"))
except Exception as e:
start_response(status, headers)
return self.genPageError(name, e, lang)
try:
fd, box.output = tempfile.mkstemp()

View File

@ -108,7 +108,7 @@ function GridfinityTrayLayout_GenerateLayout(x, y, nx, ny, countx, county) {
}
for (i = 0; i < county; i++) {
layout += "+-".repeat(countx) + "+\n";
layout += "| ".repeat(countx) + `|${stepy}mm\n`;
layout += "| ".repeat(countx) + `| ${stepy}mm\n`;
}
layout += "+-".repeat(countx) + "+\n";
return layout
@ -157,16 +157,104 @@ function GridfinityTrayLayoutInit() {
layout_id.rows = 20;
layout_id.cols = 24;
}
function ParseSections(s) {
var sections = [];
for (var section of s.split(":")) {
var operands = section.split("/");
if (operands.length > 2) return sections;
if (operands.length == 2) {
for (var i=0; i<operands[1]; i++) {
sections.push(Number(operands[0])/Number(operands[1]));
}
continue;
}
operands = section.split("*");
if (operands.length > 2) return sections;
if (operands.length == 2) {
for (var i=0; i<operands[1]; i++) {
sections.push(Number(operands[0]));
}
continue;
}
sections.push(Number(section));
}
return sections;
}
function TrayLayout_GenerateLayout(sx, sy) {
sx = ParseSections(sx);
sy = ParseSections(sy);
nx = sx.length
ny = sy.length
layout = '';
if (nx <= 0)
nx = 1;
if (ny <= 0)
ny = 1;
for (i = 0; i < nx; i++) {
line = ' |'.repeat(i) + ` ,> ${sx[i].toFixed(2)}mm\n`;
layout += line;
}
for (i = 0; i < ny; i++) {
layout += "+-".repeat(nx) + "+\n";
layout += "| ".repeat(nx) + `| ${sy[i].toFixed(2)}mm\n`;
}
layout += "+-".repeat(nx) + "+\n";
return layout
}
function TrayUpdateLayout(event) {
if (window.layoutUpdated == true) {
// Don't do the update if the layout has been manually touched.
if (confirm("You have manually updated the Layout. Do you wish to regenerate it?")) {
window.layoutUpdated = false;
} else {
return;
}
}
sx = document.getElementById('sx').value;
sy = document.getElementById('sy').value;
layout_id = document.getElementById('layout');
layout_id.value = TrayLayout_GenerateLayout(sx, sy);
}
function TrayLayoutInit() {
ids = ['sx', 'sy'];
window.layoutUpdated=false;
for (id_string of ids) {
id = document.getElementById(id_string);
id.addEventListener('input', TrayUpdateLayout);
}
TrayUpdateLayout();
layout_id = document.getElementById('layout');
layout_id.addEventListener('change', setUpdated);
layout_id.addEventListener('input', setUpdated);
layout_id.rows = 20;
layout_id.cols = 24;
}
function addCallbacks() {
if (window.location.href.includes("/GridfinityTrayLayout"))
GridfinityTrayLayoutInit();
page_callbacks = {
"TrayLayout": TrayLayoutInit,
"GridfinityTrayLayout": GridfinityTrayLayoutInit,
};
loc = new URL(window.location.href);
pathname = loc.pathname;
page = pathname.substr(pathname.lastIndexOf('/')+1);
if (page in page_callbacks) {
callback = page_callbacks[page];
callback();
}
}
document.addEventListener('DOMContentLoaded', function() {
addCallbacks();
}, false);
function collapseAll() {
const h = document.getElementsByClassName("toggle");
for (let el of h) {