MichaelRKessler Claude Fable 5 commited on
Commit
dabc7b1
·
1 Parent(s): 975a31d

Add per-shape G-code preview boxes with correct download filenames

Browse files

On the TIFF Slices to GCode tab, each shape now shows its generated
G-code in a fixed-height, scrollable box aligned under its download
box, populated on generation. The in-box download button is stamped
with the real filename (e.g. Hollow_Pyramid_SnakePath_gcode.txt)
instead of gr.Code's hardcoded "file.txt".

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Files changed (1) hide show
  1. app.py +78 -0
app.py CHANGED
@@ -129,6 +129,15 @@ APP_CSS = """
129
  color: var(--body-text-color-subdued);
130
  margin-top: -0.3rem !important;
131
  }
 
 
 
 
 
 
 
 
 
132
  """
133
 
134
  # Gradio 6.10's gr.Model3D leaves the Undo (reset view) button permanently
@@ -982,6 +991,23 @@ def run_all_tiff_to_gcode(
982
  return outputs[0], outputs[1], outputs[2], "\n".join(messages)
983
 
984
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
985
  GCODE_SOURCE_SHAPE1 = "Use Shape 1 G-Code"
986
  GCODE_SOURCE_SHAPE2 = "Use Shape 2 G-Code"
987
  GCODE_SOURCE_SHAPE3 = "Use Shape 3 G-Code"
@@ -1572,6 +1598,22 @@ def build_demo() -> gr.Blocks:
1572
  gcode_file_2 = gr.File(label="Download G-Code Shape 2")
1573
  gcode_file_3 = gr.File(label="Download G-Code Shape 3")
1574
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1575
  gcode_status = gr.Markdown("")
1576
 
1577
  gcode_button.click(
@@ -1593,6 +1635,42 @@ def build_demo() -> gr.Blocks:
1593
  pixel_size,
1594
  ],
1595
  outputs=[gcode_file_1, gcode_file_2, gcode_file_3, gcode_status],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1596
  )
1597
 
1598
  with gr.Tab("G-Code Visualization"):
 
129
  color: var(--body-text-color-subdued);
130
  margin-top: -0.3rem !important;
131
  }
132
+
133
+ /* Keep the per-shape G-code previews at a fixed height with internal scroll
134
+ (gr.Code's max_lines does not constrain the editor in this Gradio build). */
135
+ .gcode-view .cm-editor {
136
+ max-height: 320px;
137
+ }
138
+ .gcode-view .cm-scroller {
139
+ overflow: auto;
140
+ }
141
  """
142
 
143
  # Gradio 6.10's gr.Model3D leaves the Undo (reset view) button permanently
 
991
  return outputs[0], outputs[1], outputs[2], "\n".join(messages)
992
 
993
 
994
+ def load_all_gcode_text(
995
+ path1: str | None,
996
+ path2: str | None,
997
+ path3: str | None,
998
+ ) -> tuple[str, str, str]:
999
+ """Return the raw text of each shape's generated G-code file for display."""
1000
+ def read(path: str | None, shape_num: int) -> str:
1001
+ if not path:
1002
+ return f"# No G-code generated for Shape {shape_num} yet."
1003
+ try:
1004
+ return Path(path).read_text()
1005
+ except OSError as exc:
1006
+ return f"# Failed to read G-code file: {exc}"
1007
+
1008
+ return read(path1, 1), read(path2, 2), read(path3, 3)
1009
+
1010
+
1011
  GCODE_SOURCE_SHAPE1 = "Use Shape 1 G-Code"
1012
  GCODE_SOURCE_SHAPE2 = "Use Shape 2 G-Code"
1013
  GCODE_SOURCE_SHAPE3 = "Use Shape 3 G-Code"
 
1598
  gcode_file_2 = gr.File(label="Download G-Code Shape 2")
1599
  gcode_file_3 = gr.File(label="Download G-Code Shape 3")
1600
 
1601
+ # Per-shape G-code preview, aligned under each download box. Fixed
1602
+ # height with internal scrolling so the files don't fill the page.
1603
+ with gr.Row():
1604
+ gcode_view_1 = gr.Code(
1605
+ label="Shape 1 G-Code", language=None, lines=15, max_lines=15,
1606
+ interactive=False, elem_classes=["gcode-view"], elem_id="gcode-view-1",
1607
+ )
1608
+ gcode_view_2 = gr.Code(
1609
+ label="Shape 2 G-Code", language=None, lines=15, max_lines=15,
1610
+ interactive=False, elem_classes=["gcode-view"], elem_id="gcode-view-2",
1611
+ )
1612
+ gcode_view_3 = gr.Code(
1613
+ label="Shape 3 G-Code", language=None, lines=15, max_lines=15,
1614
+ interactive=False, elem_classes=["gcode-view"], elem_id="gcode-view-3",
1615
+ )
1616
+
1617
  gcode_status = gr.Markdown("")
1618
 
1619
  gcode_button.click(
 
1635
  pixel_size,
1636
  ],
1637
  outputs=[gcode_file_1, gcode_file_2, gcode_file_3, gcode_status],
1638
+ ).then(
1639
+ fn=load_all_gcode_text,
1640
+ inputs=[gcode_file_1, gcode_file_2, gcode_file_3],
1641
+ outputs=[gcode_view_1, gcode_view_2, gcode_view_3],
1642
+ ).then(
1643
+ # gr.Code's built-in download button hardcodes "file.txt"; stamp
1644
+ # the real filename (from each File value's orig_name) onto the
1645
+ # download link so it matches the Download G-Code Shape box.
1646
+ fn=None,
1647
+ inputs=[gcode_file_1, gcode_file_2, gcode_file_3],
1648
+ outputs=[],
1649
+ js="""(f1, f2, f3) => {
1650
+ const files = [f1, f2, f3];
1651
+ const nameOf = (f) => {
1652
+ if (!f) return null;
1653
+ if (f.orig_name) return f.orig_name;
1654
+ const p = f.path || f.url || "";
1655
+ return p ? p.split(/[\\\\/]/).pop() : null;
1656
+ };
1657
+ const apply = (tries) => {
1658
+ let pending = false;
1659
+ files.forEach((f, i) => {
1660
+ const name = nameOf(f);
1661
+ if (!name) return;
1662
+ const a = document.querySelector(`#gcode-view-${i + 1} a[download]`);
1663
+ if (a) {
1664
+ if (a.getAttribute("download") !== name) a.setAttribute("download", name);
1665
+ } else {
1666
+ pending = true;
1667
+ }
1668
+ });
1669
+ if (pending && tries < 20) setTimeout(() => apply(tries + 1), 150);
1670
+ };
1671
+ apply(0);
1672
+ return [];
1673
+ }""",
1674
  )
1675
 
1676
  with gr.Tab("G-Code Visualization"):