From b29af7d96adba686d1d83bb2a0370395e49717a9 Mon Sep 17 00:00:00 2001 From: Arda Aydin Date: Sun, 6 Sep 2026 00:22:26 +0300 Subject: [PATCH] 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 --- README.md | 10 +++++++++- app_state.py | 2 +- properties.py | 24 +++++++++++++++++++++++- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 570a3f5..d483cee 100644 --- a/README.md +++ b/README.md @@ -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 | diff --git a/app_state.py b/app_state.py index 8122ff2..f704612 100644 --- a/app_state.py +++ b/app_state.py @@ -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 diff --git a/properties.py b/properties.py index 58f3016..f936e06 100644 --- a/properties.py +++ b/properties.py @@ -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("", self._on_wheel) self.frame.bind("", 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'])}"