bootstack 0.1.2__tar.gz → 0.1.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {bootstack-0.1.2/src/bootstack.egg-info → bootstack-0.1.4}/PKG-INFO +7 -6
- {bootstack-0.1.2 → bootstack-0.1.4}/README.md +5 -4
- {bootstack-0.1.2 → bootstack-0.1.4}/pyproject.toml +3 -3
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/form.py +173 -240
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/select.py +27 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/types.py +3 -1
- {bootstack-0.1.2 → bootstack-0.1.4/src/bootstack.egg-info}/PKG-INFO +7 -6
- {bootstack-0.1.2 → bootstack-0.1.4}/LICENSE +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/MANIFEST.in +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/NOTICE +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/setup.cfg +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/__main__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/_core/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/_core/capabilities/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/_core/capabilities/after.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/_core/capabilities/bind.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/_core/capabilities/bindtags.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/_core/capabilities/busy.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/_core/capabilities/clipboard.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/_core/capabilities/focus.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/_core/capabilities/grab.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/_core/capabilities/grid.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/_core/capabilities/localization.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/_core/capabilities/pack.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/_core/capabilities/place.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/_core/capabilities/selection.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/_core/capabilities/signals.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/_core/capabilities/winfo.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/_core/colorutils.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/_core/exceptions.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/_core/images.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/_core/mixins/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/_core/mixins/ttk_state.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/_core/mixins/widget.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/_core/paths.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/_core/publisher.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/_core/variables.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/_runtime/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/_runtime/app.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/_runtime/base_window.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/_runtime/events.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/_runtime/shortcuts.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/_runtime/tk_patch.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/_runtime/toplevel.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/_runtime/utility.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/_runtime/visual_focus.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/_runtime/window_utilities.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/bootstack.ico +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/bootstack.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/badge-pill.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/badge-square.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/button-compact.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/button-default.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/buttongroup-after-h-compact.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/buttongroup-after-h-default.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/buttongroup-after-v-compact.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/buttongroup-after-v-default.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/buttongroup-before-h-compact.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/buttongroup-before-h-default.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/buttongroup-before-v-compact.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/buttongroup-before-v-default.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/buttongroup-center-h-compact.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/buttongroup-center-h-default.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/buttongroup-center-v-compact.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/buttongroup-center-v-default.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/card.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/checkbox-checked.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/checkbox-indeterminate.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/checkbox-unchecked.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/field.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/input-addon-compact.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/input-addon-default.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/input-compact.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/input-default.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/list-item-separated.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/list-item.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/listrow-compact.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/listrow-default.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/manifest.toml +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/menu-item.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/navitem-compact.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/navitem-default.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/progressbar-h-compact.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/progressbar-h-default.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/progressbar-v-compact.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/progressbar-v-default.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/radiobutton.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/scrollbar-horizontal.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/scrollbar-vertical.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/slider-handle.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/slider-track-h.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/slider-track-v.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/switch-off.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/switch-on.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/tab-h.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/elements/tab-v.png +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/icons/bootstrap.ttf +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/icons/glyphmap.json +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/icons/icon_metrics.json +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/ar/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/ar/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/bg/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/bg/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/cs/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/cs/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/da/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/da/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/de/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/de/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/en/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/en/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/es/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/es/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/fr/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/fr/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/he/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/he/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/hi/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/hi/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/it/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/it/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/ja/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/ja/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/ko/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/ko/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/nb/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/nb/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/nl/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/nl/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/pl/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/pl/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/pt/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/pt/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/sl/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/sl/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/sv/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/sv/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/tr/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/tr/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/cli/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/cli/__main__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/cli/add.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/cli/appicon.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/cli/build.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/cli/config.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/cli/demo.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/cli/dev.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/cli/doctor.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/cli/icons.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/cli/promote.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/cli/pyinstaller.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/cli/run.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/cli/start.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/cli/templates/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/clipboard.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/constants.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/data/README.md +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/data/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/data/_observable.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/data/base.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/data/file_source.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/data/memory_source.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/data/query.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/data/readers.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/data/sqlite_source.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/data/types.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/data/writers.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/dev/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/dev/_capture.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/dev/_env.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/dev/_registry.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/dev/_reloader.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/dev/_reset.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/dev/_watcher.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/dialogs/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/dialogs/_impl/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/dialogs/_impl/colorchooser.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/dialogs/_impl/datedialog.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/dialogs/_impl/dialog.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/dialogs/_impl/filterdialog.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/dialogs/_impl/fontdialog.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/dialogs/_impl/formdialog.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/dialogs/_impl/message.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/dialogs/_impl/query.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/errors.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/events/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/events/_event.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/events/_payloads.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/events/_subscription.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/i18n/README.md +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/i18n/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/i18n/catalog.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/i18n/intl_format.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/i18n/msgcat.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/i18n/specs.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/images.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/py.typed +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/scheduling/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/scheduling/_schedule.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/shortcuts.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/signals/README.md +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/signals/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/signals/integration.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/signals/signal.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/signals/types.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/store.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/streams/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/streams/_stream.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/builders/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/builders/badge.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/builders/button.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/builders/buttongroup.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/builders/calendar.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/builders/checkbutton.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/builders/combobox.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/builders/contextmenu.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/builders/entry.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/builders/expander.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/builders/field.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/builders/frame.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/builders/label.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/builders/labelframe.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/builders/listview.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/builders/menubar.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/builders/menubutton.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/builders/panedwindow.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/builders/progressbar.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/builders/radiobutton.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/builders/scale.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/builders/scrollbar.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/builders/separator.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/builders/sidenav.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/builders/sizegrip.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/builders/spinbox.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/builders/switch.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/builders/tabitem.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/builders/togglegroup.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/builders/toolbutton.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/builders/tooltip.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/builders/treeview.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/builders/utils.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/builders_tk/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/builders_tk/defaults.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/element.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/fonts.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/style.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/style_builder_base.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/style_builder_mixed.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/style_builder_tk.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/style_builder_ttk.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/style_resolver.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/theme.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/theme_provider.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/themes/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/tk_patch.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/token_maps.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/types.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/typography.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/style/utility.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/types.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/validation/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/validation/types.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/validation/validation_result.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/validation/validation_rules.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_core/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_core/app_config.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_core/base.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_core/container.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_core/context.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_core/events.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_core/field_mixin.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_core/icon_image_props.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_core/image_binding.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_core/navmodel.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_core/options.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_core/selection_group.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_core/window_controls.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_core/window_menu.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/_internal/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/_internal/wrapper_base.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/_parts/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/_parts/numberentry_part.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/_parts/spinnerentry_part.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/_parts/textentry_part.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/_dateutils.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/_image_fit.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/accordion.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/avatar.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/buttongroup.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/calendar.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/carousel.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/chart.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/compositeframe.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/contextmenu.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/dateentry.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/dropdownbutton.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/expander.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/field.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/gallery.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/list/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/list/listitem.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/list/listview.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/menu/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/menu/model.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/menu/render_native.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/menu/render_themed.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/meter.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/numericentry.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/pagestack.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/passwordentry.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/pathentry.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/picture.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/radiogroup.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/scrolledtext.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/scrolledtext.pyi +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/scrollview.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/selectbox.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/shell/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/shell/content_host.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/shell/layout.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/shell/nav_panel.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/shell/providers.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/shell/rail.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/shell/shell.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/shell/workspace.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/sidenav/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/sidenav/header.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/sidenav/separator.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/slider/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/slider/_shared.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/slider/rangeslider.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/slider/slider.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/spinnerentry.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/tableview/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/tableview/tableview.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/tableview/types.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/tabs/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/tabs/tabitem.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/tabs/tabs.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/tabs/tabview.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/textarea/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/textarea/change.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/textarea/codeeditor.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/textarea/core.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/textarea/decoration.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/textarea/diff.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/textarea/extensions/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/textarea/extensions/bracket_matcher.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/textarea/extensions/indent_guides.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/textarea/extensions/line_numbers.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/textarea/extensions/pygments_highlighter.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/textarea/extensions/smart_indent.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/textarea/filter.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/textarea/search_overlay.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/textarea/sidebar.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/textarea/style_registry.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/textarea/textarea.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/textarea/undo.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/textentry.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/timeentry.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/toast.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/toast_stack.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/togglegroup.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/toolbar.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/tooltip.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/tree/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/tree/source_binding.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/tree/treeitem.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/tree/treenode.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/composites/tree/treeview.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/mixins/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/mixins/configure_mixin.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/mixins/entry_mixin.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/mixins/font_mixin.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/mixins/icon_mixin.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/mixins/localization_mixin.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/mixins/signal_mixin.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/mixins/validation_mixin.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/primitives/__init__.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/primitives/_menubutton.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/primitives/badge.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/primitives/button.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/primitives/card.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/primitives/checkbutton.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/primitives/checktoggle.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/primitives/combobox.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/primitives/entry.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/primitives/flexframe.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/primitives/frame.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/primitives/gridframe.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/primitives/label.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/primitives/labelframe.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/primitives/optionmenu.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/primitives/packframe.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/primitives/panedwindow.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/primitives/progressbar.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/primitives/radiobutton.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/primitives/radiotoggle.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/primitives/scrollbar.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/primitives/separator.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/primitives/sizegrip.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/primitives/spinbox.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/primitives/switch.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/_impl/primitives/treeview.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/app.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/appshell.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/avatar.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/boolean_controls.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/button.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/buttongroup.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/calendar.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/card.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/carousel.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/chart.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/codeeditor.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/contextmenu.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/datatable.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/datefield.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/divider.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/expander.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/form.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/gallery.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/gauge.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/grid.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/groupbox.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/label.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/listview.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/menubutton.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/numberfield.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/pagestack.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/passwordfield.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/pathfield.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/picture.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/progressbar.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/radio_variants.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/radiogroup.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/scrollbar.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/scrollview.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/selectbutton.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/sidebar_toggle.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/sizegrip.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/slider.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/spinbox.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/spinnerfield.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/splash.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/splitview.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/stacks.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/statusbar.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/tabs.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/textarea.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/textfield.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/theme_toggle.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/timefield.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/toast.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/togglegroup.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/toolbar.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/tooltip.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/tree.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack/widgets/window.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack.egg-info/SOURCES.txt +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack.egg-info/dependency_links.txt +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack.egg-info/entry_points.txt +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack.egg-info/requires.txt +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/src/bootstack.egg-info/top_level.txt +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/tests/test_dialog_anchor.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/tests/test_events_doc_coverage.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/tests/test_hot_reload.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/tests/test_images.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/tests/test_images_gui.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/tests/test_intl_format.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/tests/test_navmodel.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/tests/test_on_color_contrast.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/tests/test_public_surface.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/tests/test_store.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/tests/test_theme_from_existing.py +0 -0
- {bootstack-0.1.2 → bootstack-0.1.4}/tests/test_validation_rules.py +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bootstack
|
|
3
|
-
Version: 0.1.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 0.1.4
|
|
4
|
+
Summary: Build desktop GUI apps in pure Python and ship them as a standalone executable — built on Tk, no Tkinter boilerplate.
|
|
5
5
|
Author-email: Israel Dryer <israel.dryer@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
7
7
|
Project-URL: Homepage, https://github.com/israel-dryer/bootstack
|
|
@@ -64,11 +64,12 @@ Dynamic: license-file
|
|
|
64
64
|
|
|
65
65
|
> Full documentation is at **[bootstack.org](https://bootstack.org)**.
|
|
66
66
|
|
|
67
|
-
###
|
|
67
|
+
### Desktop apps in pure Python — Tk underneath, none of the boilerplate.
|
|
68
68
|
|
|
69
|
-
bootstack
|
|
70
|
-
|
|
71
|
-
|
|
69
|
+
bootstack is built on Tk, so the install is light, there's no Qt license, and
|
|
70
|
+
your app ships as a small standalone executable. But you'll never write a
|
|
71
|
+
`StringVar` or call `.pack()` — the API is its own. 60+ widgets, reactive state,
|
|
72
|
+
and a CLI that scaffolds and packages the whole thing.
|
|
72
73
|
|
|
73
74
|
<p align="center">
|
|
74
75
|
<picture>
|
|
@@ -11,11 +11,12 @@
|
|
|
11
11
|
|
|
12
12
|
> Full documentation is at **[bootstack.org](https://bootstack.org)**.
|
|
13
13
|
|
|
14
|
-
###
|
|
14
|
+
### Desktop apps in pure Python — Tk underneath, none of the boilerplate.
|
|
15
15
|
|
|
16
|
-
bootstack
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
bootstack is built on Tk, so the install is light, there's no Qt license, and
|
|
17
|
+
your app ships as a small standalone executable. But you'll never write a
|
|
18
|
+
`StringVar` or call `.pack()` — the API is its own. 60+ widgets, reactive state,
|
|
19
|
+
and a CLI that scaffolds and packages the whole thing.
|
|
19
20
|
|
|
20
21
|
<p align="center">
|
|
21
22
|
<picture>
|
|
@@ -4,8 +4,8 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "bootstack"
|
|
7
|
-
version = "0.1.
|
|
8
|
-
description = "
|
|
7
|
+
version = "0.1.4"
|
|
8
|
+
description = "Build desktop GUI apps in pure Python and ship them as a standalone executable — built on Tk, no Tkinter boilerplate."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.12"
|
|
11
11
|
license = "MIT"
|
|
@@ -114,7 +114,7 @@ where = ["src"]
|
|
|
114
114
|
]
|
|
115
115
|
|
|
116
116
|
[tool.bumpversion]
|
|
117
|
-
current_version = "0.1.
|
|
117
|
+
current_version = "0.1.4"
|
|
118
118
|
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)((?P<pre>a|b|rc)(?P<pre_n>\\d+))?"
|
|
119
119
|
serialize = [
|
|
120
120
|
"{major}.{minor}.{patch}{pre}{pre_n}",
|
|
@@ -4,27 +4,17 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
from dataclasses import dataclass, field
|
|
6
6
|
from datetime import date, datetime
|
|
7
|
-
from tkinter import
|
|
7
|
+
from tkinter import Variable
|
|
8
8
|
from typing import Any, Callable, Iterable, Literal, Mapping, Sequence, TYPE_CHECKING
|
|
9
9
|
|
|
10
10
|
from bootstack.constants import DEFAULT_MIN_COL_WIDTH
|
|
11
11
|
from bootstack.signals import Signal
|
|
12
12
|
from bootstack.widgets._impl.primitives.button import Button
|
|
13
|
-
from bootstack.widgets._impl.primitives.checkbutton import CheckButton
|
|
14
|
-
from bootstack.widgets._impl.primitives.switch import Switch
|
|
15
|
-
from bootstack.widgets._impl.composites.dateentry import DateEntry
|
|
16
|
-
from bootstack.widgets._impl.composites.field import Field
|
|
17
13
|
from bootstack.widgets._impl.primitives.frame import Frame
|
|
18
14
|
from bootstack.widgets._impl.primitives.label import Label
|
|
19
15
|
from bootstack.widgets._impl.primitives.labelframe import LabelFrame
|
|
20
16
|
from bootstack.widgets._impl.mixins import configure_delegate
|
|
21
|
-
from bootstack.widgets._impl.composites.numericentry import NumericEntry
|
|
22
17
|
from bootstack.widgets._impl.composites.tabs.tabview import TabView
|
|
23
|
-
from bootstack.widgets._impl.composites.passwordentry import PasswordEntry
|
|
24
|
-
from bootstack.widgets._impl.composites.slider.slider import Slider
|
|
25
|
-
from bootstack.widgets._impl.composites.selectbox import SelectBox
|
|
26
|
-
from bootstack.widgets._impl.primitives.spinbox import Spinbox
|
|
27
|
-
from bootstack.widgets._impl.composites.textentry import TextEntry
|
|
28
18
|
from bootstack.widgets.types import EditorType, Master
|
|
29
19
|
|
|
30
20
|
if TYPE_CHECKING:
|
|
@@ -50,8 +40,9 @@ class FieldItem:
|
|
|
50
40
|
"""Render the field read-only. Default `False`."""
|
|
51
41
|
required: bool = False
|
|
52
42
|
"""Mark the field as required — adds a `'required'` validation rule and appends
|
|
53
|
-
an asterisk to the label. Honored by the text, number, password, date,
|
|
54
|
-
|
|
43
|
+
an asterisk to the label. Honored by the text, number, password, date, select,
|
|
44
|
+
textarea, and spinner editors; has no effect on boolean or slider editors.
|
|
45
|
+
Default `False`."""
|
|
55
46
|
visible: bool = True
|
|
56
47
|
"""Show the field. Set `False` to hide it. Default `True`."""
|
|
57
48
|
column: int | None = None
|
|
@@ -66,9 +57,11 @@ class FieldItem:
|
|
|
66
57
|
"""Force a specific editor widget (see `EditorType`). `None` infers it from
|
|
67
58
|
`dtype`."""
|
|
68
59
|
editor_options: dict[str, Any] = field(default_factory=dict)
|
|
69
|
-
"""
|
|
70
|
-
|
|
71
|
-
|
|
60
|
+
"""Keyword arguments for the editor widget, using its public `bs.*` parameter
|
|
61
|
+
names — e.g. `{"step": 10}` for a `numberfield`, `{"show_border": True}` for a
|
|
62
|
+
`textarea`, `{"mask": "*"}` for a `textfield`. For `'select'`, pass the choices
|
|
63
|
+
as `{"values": ["A", "B", "C"]}` (or `{"items": [...]}`); add
|
|
64
|
+
`{"allow_custom_values": True}` for an editable combobox."""
|
|
72
65
|
type: Literal['field'] = "field"
|
|
73
66
|
"""Item-type discriminator. Set automatically; only needed when building items
|
|
74
67
|
as plain dicts."""
|
|
@@ -152,8 +145,8 @@ class Form(Frame):
|
|
|
152
145
|
and manipulating form fields and their values.
|
|
153
146
|
|
|
154
147
|
Field Access:
|
|
155
|
-
- `field(key)` — returns the
|
|
156
|
-
- `fields()` — returns all
|
|
148
|
+
- `field(key)` — returns the field widget for a key
|
|
149
|
+
- `fields()` — returns all field widgets in order
|
|
157
150
|
- `keys()` — returns all field keys in order
|
|
158
151
|
|
|
159
152
|
Value Operations:
|
|
@@ -304,12 +297,18 @@ class Form(Frame):
|
|
|
304
297
|
|
|
305
298
|
@staticmethod
|
|
306
299
|
def _validity_entry(widget: Any) -> Any | None:
|
|
307
|
-
"""Return a field's validation-bearing entry, or None if it has none.
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
300
|
+
"""Return a field's validation-bearing entry, or None if it has none.
|
|
301
|
+
|
|
302
|
+
Resolves through a public wrapper's internal widget: a field editor's
|
|
303
|
+
internal `Field` exposes the validity signals on its `_entry`, while the
|
|
304
|
+
text-area composite carries them directly.
|
|
305
|
+
"""
|
|
306
|
+
internal = getattr(widget, "_internal", widget)
|
|
307
|
+
entry = getattr(internal, "_entry", None)
|
|
311
308
|
if entry is not None and hasattr(entry, "_valid_signal"):
|
|
312
309
|
return entry
|
|
310
|
+
if hasattr(internal, "_valid_signal"):
|
|
311
|
+
return internal
|
|
313
312
|
return None
|
|
314
313
|
|
|
315
314
|
def _register_validity_aggregate(self) -> None:
|
|
@@ -331,39 +330,46 @@ class Form(Frame):
|
|
|
331
330
|
all_valid = True
|
|
332
331
|
first_invalid_widget = None
|
|
333
332
|
|
|
334
|
-
def
|
|
335
|
-
entry = getattr(widget, "_entry", widget)
|
|
333
|
+
def _validate_entry(entry: Any) -> bool:
|
|
336
334
|
if not getattr(entry, "_rules", None):
|
|
337
335
|
return True
|
|
338
336
|
# Delegate to the entry's own validator. An explicit form.validate()
|
|
339
337
|
# is a manual action, so the "manual" trigger runs every rule; the
|
|
340
338
|
# entry validates its typed value, updates the field's reactive
|
|
341
|
-
# validity signals, and emits the validation events.
|
|
342
|
-
|
|
339
|
+
# validity signals, and emits the validation events. The text-area
|
|
340
|
+
# composite exposes a no-argument validate().
|
|
341
|
+
if hasattr(entry, "_get_validation_value"):
|
|
342
|
+
return entry.validate(entry._get_validation_value(), trigger="manual")
|
|
343
|
+
return entry.validate()
|
|
343
344
|
|
|
344
345
|
for widget in self._widgets.values():
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
346
|
+
entry = self._validity_entry(widget)
|
|
347
|
+
if entry is None:
|
|
348
|
+
continue
|
|
349
|
+
ok = _validate_entry(entry)
|
|
350
|
+
if not ok and first_invalid_widget is None:
|
|
351
|
+
first_invalid_widget = widget
|
|
352
|
+
all_valid = all_valid and ok
|
|
353
|
+
if first_invalid_widget is not None:
|
|
351
354
|
try:
|
|
352
|
-
first_invalid_widget.
|
|
355
|
+
first_invalid_widget.focus()
|
|
353
356
|
except Exception:
|
|
354
|
-
|
|
357
|
+
try:
|
|
358
|
+
first_invalid_widget._internal.focus_set()
|
|
359
|
+
except Exception:
|
|
360
|
+
pass
|
|
355
361
|
return all_valid
|
|
356
362
|
|
|
357
363
|
# --- Field access API (v2) -------------------------------------------
|
|
358
364
|
|
|
359
|
-
def field(self, key: str) ->
|
|
360
|
-
"""Return the
|
|
365
|
+
def field(self, key: str) -> Any:
|
|
366
|
+
"""Return the field widget for the given key.
|
|
361
367
|
|
|
362
368
|
Args:
|
|
363
369
|
key: The field key.
|
|
364
370
|
|
|
365
371
|
Returns:
|
|
366
|
-
The
|
|
372
|
+
The public field widget instance (e.g. `NumberField`, `TextArea`).
|
|
367
373
|
|
|
368
374
|
Raises:
|
|
369
375
|
KeyError: If no field with the given key exists.
|
|
@@ -372,11 +378,11 @@ class Form(Frame):
|
|
|
372
378
|
raise KeyError(f"No field with key '{key}'")
|
|
373
379
|
return self._widgets[key]
|
|
374
380
|
|
|
375
|
-
def fields(self) -> tuple[
|
|
381
|
+
def fields(self) -> tuple[Any, ...]:
|
|
376
382
|
"""Return all field widgets in insertion order.
|
|
377
383
|
|
|
378
384
|
Returns:
|
|
379
|
-
Tuple of
|
|
385
|
+
Tuple of public field widget instances.
|
|
380
386
|
"""
|
|
381
387
|
return tuple(self._widgets[k] for k in self._items_by_key.keys() if k in self._widgets)
|
|
382
388
|
|
|
@@ -597,111 +603,49 @@ class Form(Frame):
|
|
|
597
603
|
auto_col = 0
|
|
598
604
|
auto_row += 1
|
|
599
605
|
|
|
606
|
+
# Editors that accept validation kwargs (required, etc.). Boolean and slider
|
|
607
|
+
# editors validate nothing, so `required` and friends are dropped for them.
|
|
608
|
+
_VALIDATING_EDITORS = frozenset(
|
|
609
|
+
{'textfield', 'numberfield', 'passwordfield', 'datefield', 'textarea', 'select', 'spinnerfield'})
|
|
610
|
+
|
|
600
611
|
def _build_field(self, parent: Frame, item: FieldItem):
|
|
601
612
|
if not item.visible:
|
|
602
613
|
return None
|
|
603
614
|
|
|
604
615
|
editor = item.editor or self._default_editor_for_dtype(item.dtype, self._data.get(item.key))
|
|
605
616
|
options = dict(item.editor_options or {})
|
|
606
|
-
if item.required:
|
|
617
|
+
if item.required and editor in self._VALIDATING_EDITORS:
|
|
607
618
|
options["required"] = True
|
|
608
619
|
initial_value = self._data.get(item.key)
|
|
609
|
-
variable = self._variable_for_item(item, initial_value, editor)
|
|
610
620
|
label_text = item.label if item.label is not None else item.key.replace("_", " ").title()
|
|
611
621
|
|
|
612
622
|
container = Frame(parent)
|
|
613
623
|
container.columnconfigure(0, weight=1) # Allow field widgets to expand horizontally
|
|
614
624
|
|
|
615
|
-
#
|
|
616
|
-
|
|
625
|
+
# Build the public wrapper. `editor_options` are that widget's public
|
|
626
|
+
# kwargs (issue #353) — the wrapper is the single translation layer to
|
|
627
|
+
# the internal Tk options, so `step`, `show_border`, `mask`, etc. work.
|
|
628
|
+
field_widget = self._construct_editor(editor, container, label_text, initial_value, options)
|
|
617
629
|
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
field_widget =
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
numeric_value = initial_value if initial_value is not None else 0
|
|
624
|
-
field_widget = NumericEntry(
|
|
625
|
-
container, value=numeric_value, label=label_text, **options)
|
|
626
|
-
self._bind_numeric_variable(item.key, field_widget, variable)
|
|
627
|
-
elif editor == 'passwordfield':
|
|
628
|
-
field_widget = PasswordEntry(
|
|
629
|
-
container, value=initial_value or "", label=label_text, textvariable=variable, **options)
|
|
630
|
-
elif editor == 'datefield':
|
|
631
|
-
field_widget = DateEntry(container, value=initial_value, label=label_text, textvariable=variable, **options)
|
|
632
|
-
else:
|
|
633
|
-
# Filter out validation options for widgets that don't support ValidationMixin
|
|
634
|
-
filtered_options = {k: v for k, v in options.items() if k not in validation_options}
|
|
635
|
-
|
|
636
|
-
# Checkbox and switch use an inline label; select handles its own label.
|
|
637
|
-
if editor in ('checkbox', 'switch'):
|
|
638
|
-
if not filtered_options.get("text"):
|
|
639
|
-
filtered_options["text"] = label_text
|
|
640
|
-
elif label_text != "" and editor != 'select':
|
|
641
|
-
Label(container, text=label_text).pack(anchor='w', pady=(0, 2))
|
|
630
|
+
# Commit sync: mirror the field's committed value into the form data.
|
|
631
|
+
try:
|
|
632
|
+
field_widget.on_change(lambda *_a, k=item.key: self._sync_value_from_widget(k))
|
|
633
|
+
except Exception:
|
|
634
|
+
pass
|
|
642
635
|
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
textvariable=variable,
|
|
652
|
-
**options
|
|
653
|
-
)
|
|
654
|
-
if initial_value is not None and variable is not None:
|
|
655
|
-
variable.set(initial_value)
|
|
656
|
-
elif editor == 'spinnerfield':
|
|
657
|
-
field_widget = Spinbox(container, textvariable=variable, **filtered_options)
|
|
658
|
-
if initial_value is not None:
|
|
659
|
-
variable.set(initial_value)
|
|
660
|
-
elif editor == 'textarea':
|
|
661
|
-
field_widget = Text(container, **filtered_options)
|
|
662
|
-
if initial_value:
|
|
663
|
-
field_widget.insert('1.0', str(initial_value))
|
|
664
|
-
elif editor == 'switch':
|
|
665
|
-
field_widget = Switch(container, variable=variable, **filtered_options)
|
|
666
|
-
elif editor == 'checkbox':
|
|
667
|
-
field_widget = CheckButton(container, variable=variable, **filtered_options)
|
|
668
|
-
elif editor == 'slider':
|
|
669
|
-
slider_opts = dict(filtered_options)
|
|
670
|
-
if 'from_' in slider_opts:
|
|
671
|
-
slider_opts['minvalue'] = slider_opts.pop('from_')
|
|
672
|
-
if 'to' in slider_opts:
|
|
673
|
-
slider_opts['maxvalue'] = slider_opts.pop('to')
|
|
674
|
-
field_widget = Slider(container, variable=variable, **slider_opts)
|
|
675
|
-
else:
|
|
676
|
-
field_widget = TextEntry(
|
|
677
|
-
container, value=initial_value or "", label=label_text, textvariable=variable, **options)
|
|
636
|
+
# Preserve field_variable(): adopt the internal tk variable when present.
|
|
637
|
+
internal = getattr(field_widget, "_internal", None)
|
|
638
|
+
try:
|
|
639
|
+
var = getattr(internal, "variable", None)
|
|
640
|
+
except Exception:
|
|
641
|
+
var = None
|
|
642
|
+
if var is not None:
|
|
643
|
+
self._variables[item.key] = var
|
|
678
644
|
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
else:
|
|
682
|
-
field_widget.pack(fill='both', expand=True)
|
|
683
|
-
|
|
684
|
-
if isinstance(field_widget, Field):
|
|
685
|
-
field_widget.bind("<<Change>>", lambda _e, k=item.key: self._sync_value_from_widget(k))
|
|
686
|
-
field_widget.pack(fill='both', expand=True)
|
|
687
|
-
if not isinstance(field_widget, NumericEntry):
|
|
688
|
-
traced_var = getattr(field_widget, "variable", None)
|
|
689
|
-
if traced_var is not None:
|
|
690
|
-
self._register_variable(item.key, traced_var)
|
|
691
|
-
elif isinstance(field_widget, Text):
|
|
692
|
-
text_var = variable or StringVar(value=str(initial_value) if initial_value is not None else "")
|
|
693
|
-
self._register_variable(item.key, text_var)
|
|
694
|
-
self._bind_text_change(field_widget, item.key, text_var)
|
|
695
|
-
elif variable is not None:
|
|
696
|
-
self._register_variable(item.key, variable)
|
|
697
|
-
|
|
698
|
-
# record signals if the widget exposes them
|
|
699
|
-
signal_obj = getattr(field_widget, "_signal", None)
|
|
645
|
+
# Record signals the wrapper exposes (for field_signal/field_textsignal).
|
|
646
|
+
signal_obj = getattr(field_widget, "signal", None)
|
|
700
647
|
if signal_obj is not None:
|
|
701
648
|
self._signals[item.key] = signal_obj
|
|
702
|
-
text_signal = getattr(field_widget, "_textsignal", None)
|
|
703
|
-
if text_signal is not None:
|
|
704
|
-
self._textsignals[item.key] = text_signal
|
|
705
649
|
|
|
706
650
|
if item.readonly:
|
|
707
651
|
self._set_readonly(field_widget)
|
|
@@ -709,6 +653,73 @@ class Form(Frame):
|
|
|
709
653
|
self._widgets[item.key] = field_widget
|
|
710
654
|
return container
|
|
711
655
|
|
|
656
|
+
def _construct_editor(self, editor: str, container: Frame, label_text: str, initial: Any, options: dict):
|
|
657
|
+
"""Construct the public wrapper widget for an editor, parented to `container`.
|
|
658
|
+
|
|
659
|
+
`options` are the wrapper's public keyword arguments; a few documented
|
|
660
|
+
aliases (`values`/`items` for the option list) are normalized to the
|
|
661
|
+
wrapper's parameter name. The wrapper auto-attaches to `container`.
|
|
662
|
+
"""
|
|
663
|
+
# Local imports: the public wrappers depend on this package, so import
|
|
664
|
+
# them lazily to avoid import-time cycles (mirrors _normalize_buttons).
|
|
665
|
+
from bootstack.widgets.textfield import TextField
|
|
666
|
+
from bootstack.widgets.numberfield import NumberField
|
|
667
|
+
from bootstack.widgets.passwordfield import PasswordField
|
|
668
|
+
from bootstack.widgets.datefield import DateField
|
|
669
|
+
from bootstack.widgets.textarea import TextArea
|
|
670
|
+
from bootstack.widgets.select import Select
|
|
671
|
+
from bootstack.widgets.spinnerfield import SpinnerField
|
|
672
|
+
from bootstack.widgets.boolean_controls import Checkbox, Switch
|
|
673
|
+
from bootstack.widgets.slider import Slider
|
|
674
|
+
|
|
675
|
+
opts = dict(options)
|
|
676
|
+
# Internal-only options the public wrappers don't accept. Dropping them
|
|
677
|
+
# keeps the strict boolean controls from raising and matches the old
|
|
678
|
+
# per-editor filtering (a required/message field auto-reserves its
|
|
679
|
+
# message row, so `show_message` is no longer needed here).
|
|
680
|
+
for internal_only in ("show_message", "validator"):
|
|
681
|
+
opts.pop(internal_only, None)
|
|
682
|
+
|
|
683
|
+
if editor == 'textfield':
|
|
684
|
+
return TextField(value=initial or "", label=label_text, parent=container, **opts)
|
|
685
|
+
if editor == 'numberfield':
|
|
686
|
+
numeric_value = initial if initial is not None else 0
|
|
687
|
+
return NumberField(value=numeric_value, label=label_text, parent=container, **opts)
|
|
688
|
+
if editor == 'passwordfield':
|
|
689
|
+
return PasswordField(value=initial or "", label=label_text, parent=container, **opts)
|
|
690
|
+
if editor == 'datefield':
|
|
691
|
+
return DateField(value=initial, label=label_text, parent=container, **opts)
|
|
692
|
+
if editor == 'textarea':
|
|
693
|
+
text = str(initial) if initial is not None else ""
|
|
694
|
+
return TextArea(value=text, label=label_text, parent=container, **opts)
|
|
695
|
+
if editor == 'select':
|
|
696
|
+
choices = opts.pop('items', opts.pop('values', None)) or []
|
|
697
|
+
choices = [str(i) for i in choices]
|
|
698
|
+
return Select(options=choices, value=initial if initial is not None else "",
|
|
699
|
+
label=label_text, parent=container, **opts)
|
|
700
|
+
if editor == 'spinnerfield':
|
|
701
|
+
choices = opts.pop('items', opts.pop('values', None))
|
|
702
|
+
if choices is not None:
|
|
703
|
+
opts['options'] = [str(i) for i in choices]
|
|
704
|
+
return SpinnerField(value=initial if initial is not None else "",
|
|
705
|
+
label=label_text, parent=container, **opts)
|
|
706
|
+
if editor == 'checkbox':
|
|
707
|
+
text = opts.pop('text', None) or label_text
|
|
708
|
+
return Checkbox(text, value=bool(initial) if initial is not None else False,
|
|
709
|
+
parent=container, **opts)
|
|
710
|
+
if editor == 'switch':
|
|
711
|
+
text = opts.pop('text', None) or label_text
|
|
712
|
+
return Switch(text, value=bool(initial) if initial is not None else False,
|
|
713
|
+
parent=container, **opts)
|
|
714
|
+
if editor == 'slider':
|
|
715
|
+
# Slider has no label parameter, so render a stacked caption above it
|
|
716
|
+
# (the field wrappers render their own label internally).
|
|
717
|
+
if label_text:
|
|
718
|
+
Label(container, text=label_text).pack(anchor='w', pady=(0, 2))
|
|
719
|
+
return Slider(value=initial if initial is not None else 0, parent=container, **opts)
|
|
720
|
+
# Fallback: treat any unknown editor as a text field.
|
|
721
|
+
return TextField(value=initial or "", label=label_text, parent=container, **opts)
|
|
722
|
+
|
|
712
723
|
def _build_buttons(self, parent: Frame, buttons: Sequence[ButtonInput]) -> None:
|
|
713
724
|
parsed = self._normalize_buttons(buttons)
|
|
714
725
|
for spec in reversed(parsed):
|
|
@@ -820,17 +831,13 @@ class Form(Frame):
|
|
|
820
831
|
if widget is None:
|
|
821
832
|
return self._data.get(key)
|
|
822
833
|
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
value =
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
else:
|
|
831
|
-
try:
|
|
832
|
-
value = widget.get()
|
|
833
|
-
except Exception:
|
|
834
|
+
# Every public wrapper exposes a `.value` property.
|
|
835
|
+
try:
|
|
836
|
+
value = widget.value
|
|
837
|
+
except Exception:
|
|
838
|
+
if key in self._variables:
|
|
839
|
+
value = self._variables[key].get()
|
|
840
|
+
else:
|
|
834
841
|
value = self._data.get(key)
|
|
835
842
|
|
|
836
843
|
item = self._items_by_key.get(key)
|
|
@@ -843,31 +850,21 @@ class Form(Frame):
|
|
|
843
850
|
if widget is None:
|
|
844
851
|
return
|
|
845
852
|
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
finally:
|
|
852
|
-
widget._suppress_changed_event = False # type: ignore[attr-defined]
|
|
853
|
-
else:
|
|
854
|
-
widget.value = value
|
|
855
|
-
return
|
|
856
|
-
|
|
857
|
-
if isinstance(widget, Text):
|
|
858
|
-
widget.delete("1.0", "end")
|
|
859
|
-
if value is not None:
|
|
860
|
-
widget.insert("1.0", str(value))
|
|
861
|
-
return
|
|
862
|
-
|
|
863
|
-
if key in self._variables:
|
|
864
|
-
self._variables[key].set("" if value is None else value)
|
|
865
|
-
return
|
|
866
|
-
|
|
853
|
+
# Programmatic writes must not echo back as a user change. Suspend sync
|
|
854
|
+
# around the assignment so a wrapper that emits <<Change>> synchronously
|
|
855
|
+
# doesn't re-enter _sync_value_from_widget.
|
|
856
|
+
previous_suspend = self._suspend_sync
|
|
857
|
+
self._suspend_sync = True
|
|
867
858
|
try:
|
|
868
|
-
widget.
|
|
859
|
+
widget.value = value
|
|
869
860
|
except Exception:
|
|
870
|
-
|
|
861
|
+
if key in self._variables:
|
|
862
|
+
try:
|
|
863
|
+
self._variables[key].set("" if value is None else value)
|
|
864
|
+
except Exception:
|
|
865
|
+
pass
|
|
866
|
+
finally:
|
|
867
|
+
self._suspend_sync = previous_suspend
|
|
871
868
|
|
|
872
869
|
def _sync_value_from_widget(self, key: str) -> None:
|
|
873
870
|
if self._suspend_sync:
|
|
@@ -875,21 +872,17 @@ class Form(Frame):
|
|
|
875
872
|
if key not in self._items_by_key:
|
|
876
873
|
return
|
|
877
874
|
new_value = self._read_value_from_widget(key)
|
|
875
|
+
# Notify only on a real change. This also drops a spurious echo from an
|
|
876
|
+
# editor that emits its change event asynchronously (e.g. Select fires
|
|
877
|
+
# `<<Change>>` with when="tail"), which lands after a programmatic write
|
|
878
|
+
# has already restored `_suspend_sync` and stored the value.
|
|
879
|
+
if key in self._data and new_value == self._data[key]:
|
|
880
|
+
return
|
|
878
881
|
self._data[key] = new_value
|
|
879
882
|
if self._on_data_change:
|
|
880
883
|
self._on_data_change(dict(self._data))
|
|
881
884
|
self.event_generate("<<BsDataChange>>")
|
|
882
885
|
|
|
883
|
-
def _variable_for_item(self, item: FieldItem, initial: Any, editor: EditorType | None) -> Variable | None:
|
|
884
|
-
dtype = item.dtype
|
|
885
|
-
if editor in ('checkbox', 'switch'):
|
|
886
|
-
return BooleanVar(value=bool(initial) if initial is not None else False)
|
|
887
|
-
if editor in ('numberfield', 'spinnerfield', 'slider') or dtype in ('int', int, 'float', float):
|
|
888
|
-
if dtype in ('float', float):
|
|
889
|
-
return DoubleVar(value=float(initial) if initial is not None else 0.0)
|
|
890
|
-
return IntVar(value=int(initial) if initial is not None else 0)
|
|
891
|
-
return StringVar(value="" if initial is None else str(initial))
|
|
892
|
-
|
|
893
886
|
def _default_editor_for_dtype(self, dtype: Any, value: Any) -> EditorType:
|
|
894
887
|
if dtype in ('int', int, 'float', float):
|
|
895
888
|
return 'numberfield'
|
|
@@ -925,81 +918,22 @@ class Form(Frame):
|
|
|
925
918
|
return value
|
|
926
919
|
return value
|
|
927
920
|
|
|
928
|
-
def _register_variable(self, key: str, var: Variable) -> None:
|
|
929
|
-
self._variables[key] = var
|
|
930
|
-
var.trace_add("write", lambda *_a, k=key: self._sync_value_from_widget(k))
|
|
931
|
-
|
|
932
|
-
def _bind_text_change(self, widget: Text, key: str, var: StringVar | None = None) -> None:
|
|
933
|
-
_updating = {"text": False}
|
|
934
|
-
|
|
935
|
-
def _on_change(_event=None):
|
|
936
|
-
if _updating["text"]:
|
|
937
|
-
return
|
|
938
|
-
_updating["text"] = True
|
|
939
|
-
try:
|
|
940
|
-
widget.edit_modified(False)
|
|
941
|
-
text = widget.get("1.0", "end-1c")
|
|
942
|
-
if var is not None:
|
|
943
|
-
var.set(text)
|
|
944
|
-
self._sync_value_from_widget(key)
|
|
945
|
-
finally:
|
|
946
|
-
_updating["text"] = False
|
|
947
921
|
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
922
|
+
def _set_readonly(self, widget: Any) -> None:
|
|
923
|
+
# Field editors expose a live `read_only` property; boolean and slider
|
|
924
|
+
# editors have no read-only state, so they fall back to `disabled`
|
|
925
|
+
# (matching the pre-rewrite behavior for those editors).
|
|
926
|
+
if hasattr(widget, "read_only"):
|
|
952
927
|
try:
|
|
953
|
-
widget.
|
|
954
|
-
widget.insert("1.0", var.get())
|
|
955
|
-
finally:
|
|
956
|
-
_updating["text"] = False
|
|
957
|
-
|
|
958
|
-
widget.bind("<<Modified>>", _on_change)
|
|
959
|
-
widget.edit_modified(False)
|
|
960
|
-
|
|
961
|
-
if var is not None:
|
|
962
|
-
var.trace_add("write", _on_var_change)
|
|
963
|
-
|
|
964
|
-
def _bind_numeric_variable(self, key: str, widget: NumericEntry, var: Variable | None) -> None:
|
|
965
|
-
if var is None:
|
|
966
|
-
return
|
|
967
|
-
|
|
968
|
-
self._register_variable(key, var)
|
|
969
|
-
|
|
970
|
-
def _sync_numeric_var(*_args):
|
|
971
|
-
new_value = widget.value
|
|
972
|
-
if new_value is None:
|
|
928
|
+
widget.read_only = True
|
|
973
929
|
return
|
|
974
|
-
try:
|
|
975
|
-
current_value = var.get()
|
|
976
930
|
except Exception:
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
return
|
|
980
|
-
previous_suspend = self._suspend_sync
|
|
981
|
-
self._suspend_sync = True
|
|
982
|
-
try:
|
|
983
|
-
var.set(new_value)
|
|
984
|
-
finally:
|
|
985
|
-
self._suspend_sync = previous_suspend
|
|
986
|
-
|
|
987
|
-
text_signal = getattr(widget, "signal", None)
|
|
988
|
-
if text_signal is not None:
|
|
989
|
-
text_signal.subscribe(lambda *_: _sync_numeric_var())
|
|
990
|
-
_sync_numeric_var()
|
|
991
|
-
|
|
992
|
-
def _set_readonly(self, widget: Any) -> None:
|
|
993
|
-
if isinstance(widget, Field):
|
|
994
|
-
widget.readonly(True)
|
|
995
|
-
else:
|
|
931
|
+
pass
|
|
932
|
+
if hasattr(widget, "disabled"):
|
|
996
933
|
try:
|
|
997
|
-
widget.
|
|
934
|
+
widget.disabled = True
|
|
998
935
|
except Exception:
|
|
999
|
-
|
|
1000
|
-
widget.configure(state='disabled')
|
|
1001
|
-
except Exception:
|
|
1002
|
-
pass
|
|
936
|
+
pass
|
|
1003
937
|
|
|
1004
938
|
# --- button helpers -------------------------------------------------
|
|
1005
939
|
def _make_button_command(self, spec: DialogButton):
|
|
@@ -1038,7 +972,6 @@ class Form(Frame):
|
|
|
1038
972
|
label=str(key).replace('_', ' ').title(),
|
|
1039
973
|
dtype=self._infer_dtype_from_value(value),
|
|
1040
974
|
editor=self._default_editor_for_dtype(self._infer_dtype_from_value(value), value),
|
|
1041
|
-
editor_options={"show_message": True},
|
|
1042
975
|
)
|
|
1043
976
|
)
|
|
1044
977
|
return inferred
|