From 6a526039513de9aa5067171e88626f9380ad6c0f Mon Sep 17 00:00:00 2001 From: Arda Aydin Date: Sat, 26 Sep 2026 22:10:18 +0300 Subject: [PATCH] Add a "No image" entry to the Page Editor's image dropdown It heads the list and empties imageFileName; a widget with no image shows it too. Co-Authored-By: Claude Opus 5.5 --- app_state.py | 2 +- ox_widget_properties.py | 30 +++++++++++++++++++----------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/app_state.py b/app_state.py index 6693bb5..9f2b794 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.132" +VERSION = "0.0.0.133" 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/ox_widget_properties.py b/ox_widget_properties.py index b51ae6b..03de72f 100644 --- a/ox_widget_properties.py +++ b/ox_widget_properties.py @@ -83,6 +83,7 @@ NUMERIC_FORMAT_TYPES = ("ontrolOx::NumericLabel", "ontrolOx::NumericLabelSet") BUF_ENCODING = "latin-1" IMAGE_EXTENSIONS = (".png", ".jpg", ".jpeg", ".bmp", ".bin") +NO_IMAGE = "No image" # the image list's entry for an empty imageFileName # --- value conversions ---------------------------------------------------------------- @@ -292,20 +293,24 @@ def image_names(): def image_file_text(name): """An imageFileName value with its bank file's extension: 'trt' -> 'trt.jpg'. - A name no bank file matches is shown as it is. + A name no bank file matches is shown as it is, and an empty one as NO_IMAGE. """ - if name: - for file_name in image_names(): - if os.path.splitext(file_name)[0] == name: - return file_name + if not name: + return NO_IMAGE + for file_name in image_names(): + if os.path.splitext(file_name)[0] == name: + return file_name return name def image_file_value(text): """The imageFileName value for a listed file: 'trt.jpg' -> 'trt'. - The slot holds the bare name, as the device looks the file up by it. + The slot holds the bare name, as the device looks the file up by it; NO_IMAGE + empties it. """ + if text == NO_IMAGE: + return "" stem, ext = os.path.splitext(text.strip()) return stem if ext.lower() in IMAGE_EXTENSIONS else text.strip() @@ -900,15 +905,18 @@ class OxWidgetPropertiesPanel: self._bind_commit(entry, row) self._controls.append((entry, None)) - def _bank_combo(self, cell, row, bank_values): - """A pick-only list filled from a bank each time it opens, the value kept listed.""" + def _bank_combo(self, cell, row, bank_values, first=None): + """A pick-only list filled from a bank each time it opens, the value kept listed. + + `first`, when given, heads the list: the entry for a slot naming nothing. + """ var = row["var"] def fill(): - values = bank_values() + values = ([first] if first else []) + bank_values() current = var.get() if current and current not in values: - values = [current] + values + values.insert(1 if first else 0, current) combo.configure(values=values) combo = ttk.Combobox(cell, textvariable=var, state="readonly", font=self._name_font, @@ -926,7 +934,7 @@ class OxWidgetPropertiesPanel: return combo def _build_image(self, cell, row): - self._bank_combo(cell, row, image_names) + self._bank_combo(cell, row, image_names, first=NO_IMAGE) def _build_font(self, cell, row): self._bank_combo(cell, row, font_bank_names)