Properties: a header row over the slot table

Names the four columns -- Name, Type, Value, Unit -- in grey at row size over a
hairline rule, so it labels the table without competing with it.

A fifth column of raw flags= letters was tried alongside it and taken out
again. c, a, s and o are the manifest's own shorthand, and a column of them
told the reader nothing the row was not already saying: c is what the white
field means, a is what an "action" value means. What the flags decide is still
decided by them; it is just not spelled out twice.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-06 00:22:26 +03:00
co-authored by Claude Opus 5
parent eee48eb2bb
commit b29af7d96a
3 changed files with 33 additions and 3 deletions
+9 -1
View File
@@ -5,7 +5,7 @@ component hierarchy as a navigation tree, paints the selected folder's children
wiresheet of draggable component boxes, draws the links between them, and writes box
positions back into each component's `meta` property on save.
Current version: **0.0.0.051** (see [Versioning](#versioning)).
Current version: **0.0.0.053** (see [Versioning](#versioning)).
## Requirements
@@ -166,6 +166,14 @@ Each row carries the slot's declared type between its name and its value, writte
a slot sheet writes it: the manifest stores the primitives bare and everything else already
qualified, so `int` is shown as `sys::int` and `sys::Buf` is left as it stands.
A column of raw `flags=` letters was tried here and taken out again: `c`, `a`, `s` and `o`
are the manifest's own shorthand, and a column of them told the reader nothing the row was
not already saying -- `c` is what the white field means, `a` is what an `action` value
means. What the flags decide is still decided by them; it is just not spelled out twice.
The **header row** stays. It is deliberately quiet -- row-sized, grey, over a hairline
rule -- so it labels the table without competing with it.
Which rows can be typed into is the slot's own business, not the view's:
| Slot | Field |
+1 -1
View File
@@ -8,7 +8,7 @@ so later rebinding would only ever be seen by the module that did it.
import configparser
import os
VERSION = "0.0.0.051"
VERSION = "0.0.0.053"
PROPERTIES_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "editor.properties")
DEFAULT_GRID_SIZE = 10
DEFAULT_ADD_TIMESTAMP = True
+23 -1
View File
@@ -89,6 +89,7 @@ UNIT_SYMBOLS = {
EDITABLE_FIELD_BG = "#ffffff"
READONLY_FIELD_BG = "#e8e8dc"
LABEL_COLOUR = "#000000"
HEADING_COLOUR = "#6b6b6b"
READONLY_TEXT = "#444444"
ROW_BG = "#ffffff"
HEADER_BG = "#f2f2f2"
@@ -688,12 +689,33 @@ class PropertiesPanel:
self.frame.bind("<MouseWheel>", self._on_wheel)
self.frame.bind("<Shift-MouseWheel>", self._on_shift_wheel)
for grid_row, slot in enumerate(self.slots):
self._build_header_row()
# Slots start below the header and its rule.
for grid_row, slot in enumerate(self.slots, start=2):
if slot["name"] == "meta":
self._build_meta_row(grid_row, slot)
else:
self._build_slot_row(grid_row, slot)
def _build_header_row(self):
"""Names the columns.
Deliberately quiet -- the same size as the rows, in grey, over a hairline rule --
so it labels the table without competing with it.
"""
heading_font = tkfont.Font(family="Segoe UI", size=8, weight="bold")
headings = ((1, "Name"), (2, "Type"), (3, "Value"), (4, "Unit"))
for column, text in headings:
label = self._tinted(tk.Label(self.rows_frame, text=text, anchor="w",
bg=ROW_BG, fg=HEADING_COLOUR,
font=heading_font), ROW_BG)
label.grid(row=0, column=column, sticky="w", padx=(2, 8), pady=(4, 2))
rule = self._tinted(tk.Frame(self.rows_frame, height=1, bg="#c8c8c8"), "#c8c8c8")
rule.grid(row=1, column=0, columnspan=5, sticky="ew", pady=(0, 2))
def _row_label(self, slot):
"""'14. Proportional Band' — the manifest slot id, so rows match the box's numbering."""
return f"{slot['slot_id']:02d}. {humanise(slot['name'])}"