bootstack 0.2.0__tar.gz → 0.2.1__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.2.0/src/bootstack.egg-info → bootstack-0.2.1}/PKG-INFO +1 -1
- {bootstack-0.2.0 → bootstack-0.2.1}/pyproject.toml +2 -2
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_runtime/base_window.py +17 -2
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_runtime/events.py +46 -12
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_runtime/shortcuts.py +10 -2
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_runtime/utility.py +22 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/dialogs/_impl/colorchooser.py +19 -23
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/dialogs/_impl/datedialog.py +15 -27
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/dialogs/_impl/dialog.py +52 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/dialogs/_impl/message.py +18 -22
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/dialogs/_impl/query.py +15 -22
- bootstack-0.2.1/src/bootstack/events/_subscription.py +60 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_core/base.py +51 -11
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/_parts/numberentry_part.py +7 -2
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/shell/shell.py +5 -1
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/codeeditor.py +7 -33
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/datefield.py +7 -34
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/numberfield.py +7 -33
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/passwordfield.py +7 -33
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/pathfield.py +7 -33
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/select.py +8 -34
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/spinnerfield.py +7 -33
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/tabs.py +2 -21
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/textarea.py +7 -33
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/textfield.py +7 -33
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/timefield.py +7 -34
- {bootstack-0.2.0 → bootstack-0.2.1/src/bootstack.egg-info}/PKG-INFO +1 -1
- bootstack-0.2.0/src/bootstack/events/_subscription.py +0 -38
- {bootstack-0.2.0 → bootstack-0.2.1}/LICENSE +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/MANIFEST.in +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/NOTICE +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/README.md +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/setup.cfg +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/__main__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_core/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_core/capabilities/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_core/capabilities/after.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_core/capabilities/bind.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_core/capabilities/bindtags.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_core/capabilities/busy.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_core/capabilities/clipboard.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_core/capabilities/focus.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_core/capabilities/grab.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_core/capabilities/grid.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_core/capabilities/localization.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_core/capabilities/pack.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_core/capabilities/place.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_core/capabilities/selection.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_core/capabilities/signals.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_core/capabilities/winfo.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_core/colorutils.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_core/exceptions.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_core/images.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_core/mixins/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_core/mixins/ttk_state.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_core/mixins/widget.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_core/paths.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_core/publisher.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_core/variables.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_runtime/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_runtime/app.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_runtime/tk_patch.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_runtime/toplevel.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_runtime/visual_focus.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_runtime/wheel.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/_runtime/window_utilities.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/bootstack.ico +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/bootstack.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/badge-pill.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/badge-square.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/button-compact.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/button-default.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/buttongroup-after-h-compact.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/buttongroup-after-h-default.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/buttongroup-after-v-compact.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/buttongroup-after-v-default.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/buttongroup-before-h-compact.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/buttongroup-before-h-default.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/buttongroup-before-v-compact.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/buttongroup-before-v-default.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/buttongroup-center-h-compact.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/buttongroup-center-h-default.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/buttongroup-center-v-compact.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/buttongroup-center-v-default.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/card.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/checkbox-checked.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/checkbox-indeterminate.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/checkbox-unchecked.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/field.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/input-addon-compact.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/input-addon-default.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/input-compact.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/input-default.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/list-item-separated.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/list-item.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/listrow-compact.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/listrow-default.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/manifest.toml +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/menu-item.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/navitem-compact.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/navitem-default.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/progressbar-h-compact.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/progressbar-h-default.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/progressbar-v-compact.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/progressbar-v-default.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/radiobutton.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/scrollbar-horizontal.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/scrollbar-vertical.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/slider-handle.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/slider-track-h.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/slider-track-v.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/switch-off.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/switch-on.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/tab-h.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/elements/tab-v.png +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/icons/bootstrap.ttf +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/icons/glyphmap.json +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/icons/icon_metrics.json +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/ar/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/ar/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/bg/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/bg/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/cs/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/cs/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/da/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/da/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/de/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/de/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/en/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/en/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/es/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/es/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/fr/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/fr/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/he/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/he/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/hi/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/hi/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/it/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/it/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/ja/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/ja/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/ko/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/ko/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/nb/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/nb/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/nl/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/nl/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/pl/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/pl/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/pt/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/pt/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/sl/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/sl/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/sv/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/sv/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/tr/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/tr/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/cli/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/cli/__main__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/cli/add.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/cli/appicon.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/cli/build.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/cli/config.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/cli/demo.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/cli/dev.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/cli/doctor.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/cli/icons.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/cli/promote.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/cli/pyinstaller.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/cli/run.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/cli/start.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/cli/templates/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/clipboard.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/constants.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/data/README.md +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/data/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/data/_observable.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/data/base.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/data/file_source.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/data/memory_source.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/data/query.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/data/readers.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/data/sqlite_source.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/data/types.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/data/writers.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/dev/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/dev/_capture.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/dev/_env.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/dev/_registry.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/dev/_reloader.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/dev/_reset.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/dev/_watcher.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/dialogs/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/dialogs/_impl/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/dialogs/_impl/filterdialog.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/dialogs/_impl/fontdialog.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/dialogs/_impl/formdialog.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/errors.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/events/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/events/_event.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/events/_payloads.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/i18n/README.md +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/i18n/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/i18n/catalog.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/i18n/intl_format.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/i18n/msgcat.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/i18n/specs.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/images.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/py.typed +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/scheduling/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/scheduling/_schedule.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/shortcuts.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/signals/README.md +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/signals/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/signals/integration.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/signals/signal.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/signals/types.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/store.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/streams/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/streams/_stream.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/builders/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/builders/badge.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/builders/button.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/builders/buttongroup.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/builders/calendar.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/builders/checkbutton.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/builders/combobox.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/builders/contextmenu.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/builders/entry.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/builders/expander.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/builders/field.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/builders/frame.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/builders/label.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/builders/labelframe.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/builders/listview.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/builders/menubar.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/builders/menubutton.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/builders/panedwindow.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/builders/progressbar.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/builders/radiobutton.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/builders/scale.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/builders/scrollbar.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/builders/separator.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/builders/sidenav.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/builders/sizegrip.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/builders/spinbox.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/builders/switch.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/builders/tabitem.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/builders/togglegroup.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/builders/toolbutton.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/builders/tooltip.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/builders/treeview.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/builders/utils.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/builders_tk/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/builders_tk/defaults.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/element.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/fonts.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/style.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/style_builder_base.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/style_builder_mixed.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/style_builder_tk.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/style_builder_ttk.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/style_resolver.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/theme.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/theme_provider.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/themes/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/tk_patch.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/token_maps.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/types.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/typography.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/style/utility.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/types.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/validation/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/validation/types.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/validation/validation_result.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/validation/validation_rules.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_core/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_core/app_config.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_core/choices.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_core/container.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_core/context.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_core/events.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_core/field_mixin.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_core/icon_image_props.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_core/image_binding.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_core/kwargs.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_core/navmodel.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_core/options.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_core/selection_group.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_core/window_controls.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_core/window_menu.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/_internal/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/_internal/wrapper_base.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/_parts/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/_parts/spinnerentry_part.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/_parts/textentry_part.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/_dateutils.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/_image_fit.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/accordion.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/avatar.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/buttongroup.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/calendar.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/carousel.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/chart.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/compositeframe.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/contextmenu.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/dateentry.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/dropdownbutton.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/expander.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/field.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/form.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/gallery.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/list/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/list/listitem.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/list/listview.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/menu/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/menu/model.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/menu/render_native.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/menu/render_themed.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/meter.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/numericentry.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/pagestack.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/passwordentry.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/pathentry.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/picture.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/radiogroup.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/scrolledtext.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/scrolledtext.pyi +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/scrollview.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/selectbox.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/shell/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/shell/content_host.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/shell/layout.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/shell/nav_panel.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/shell/providers.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/shell/rail.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/shell/workspace.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/sidenav/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/sidenav/header.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/sidenav/separator.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/slider/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/slider/_shared.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/slider/rangeslider.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/slider/slider.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/spinnerentry.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/tableview/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/tableview/tableview.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/tableview/types.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/tabs/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/tabs/tabitem.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/tabs/tabs.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/tabs/tabview.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/textarea/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/textarea/change.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/textarea/codeeditor.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/textarea/core.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/textarea/decoration.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/textarea/diff.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/textarea/extensions/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/textarea/extensions/bracket_matcher.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/textarea/extensions/indent_guides.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/textarea/extensions/line_numbers.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/textarea/extensions/pygments_highlighter.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/textarea/extensions/smart_indent.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/textarea/filter.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/textarea/search_overlay.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/textarea/sidebar.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/textarea/style_registry.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/textarea/textarea.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/textarea/undo.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/textentry.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/timeentry.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/toast.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/toast_stack.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/togglegroup.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/toolbar.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/tooltip.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/tree/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/tree/source_binding.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/tree/treeitem.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/tree/treenode.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/composites/tree/treeview.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/mixins/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/mixins/configure_mixin.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/mixins/entry_mixin.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/mixins/font_mixin.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/mixins/icon_mixin.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/mixins/localization_mixin.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/mixins/signal_mixin.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/mixins/validation_mixin.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/primitives/__init__.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/primitives/_menubutton.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/primitives/badge.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/primitives/button.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/primitives/card.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/primitives/checkbutton.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/primitives/checktoggle.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/primitives/combobox.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/primitives/entry.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/primitives/flexframe.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/primitives/frame.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/primitives/gridframe.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/primitives/label.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/primitives/labelframe.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/primitives/optionmenu.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/primitives/packframe.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/primitives/panedwindow.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/primitives/progressbar.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/primitives/radiobutton.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/primitives/radiotoggle.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/primitives/scrollbar.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/primitives/separator.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/primitives/sizegrip.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/primitives/spinbox.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/primitives/switch.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/_impl/primitives/treeview.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/app.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/appshell.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/avatar.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/boolean_controls.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/button.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/buttongroup.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/calendar.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/card.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/carousel.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/chart.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/contextmenu.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/datatable.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/divider.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/expander.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/form.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/gallery.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/gauge.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/grid.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/groupbox.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/label.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/listview.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/menubutton.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/pagestack.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/picture.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/progressbar.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/radio_variants.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/radiogroup.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/scrollbar.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/scrollview.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/selectbutton.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/sidebar_toggle.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/sizegrip.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/slider.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/spinbox.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/splash.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/splitview.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/stacks.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/statusbar.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/theme_toggle.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/toast.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/togglegroup.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/toolbar.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/tooltip.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/tree.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/types.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack/widgets/window.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack.egg-info/SOURCES.txt +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack.egg-info/dependency_links.txt +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack.egg-info/entry_points.txt +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack.egg-info/requires.txt +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/src/bootstack.egg-info/top_level.txt +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/tests/test_dialog_anchor.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/tests/test_events_doc_coverage.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/tests/test_hot_reload.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/tests/test_images.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/tests/test_images_gui.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/tests/test_intl_format.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/tests/test_navmodel.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/tests/test_on_color_contrast.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/tests/test_public_surface.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/tests/test_store.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/tests/test_theme_from_existing.py +0 -0
- {bootstack-0.2.0 → bootstack-0.2.1}/tests/test_validation_rules.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bootstack
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.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
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "bootstack"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.1"
|
|
8
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"
|
|
@@ -114,7 +114,7 @@ where = ["src"]
|
|
|
114
114
|
]
|
|
115
115
|
|
|
116
116
|
[tool.bumpversion]
|
|
117
|
-
current_version = "0.2.
|
|
117
|
+
current_version = "0.2.1"
|
|
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}",
|
|
@@ -34,14 +34,29 @@ def on_visibility_alpha(event: tkinter.Event) -> None:
|
|
|
34
34
|
X11 requires alpha to be set after the window is visible, so we bind
|
|
35
35
|
to the <Visibility> event and set alpha then, unbinding after first use.
|
|
36
36
|
|
|
37
|
+
Being woken by this event at all is what proves the precondition: X11
|
|
38
|
+
reports visibility only for a window that is already on screen, so the very
|
|
39
|
+
first delivery is a valid moment to apply alpha. Whether that first report
|
|
40
|
+
says obscured or unobscured makes no difference — opacity is a property of
|
|
41
|
+
the window, not of how much of it happens to be uncovered.
|
|
42
|
+
|
|
43
|
+
Alpha is therefore applied before the binding is released, so first use is
|
|
44
|
+
genuinely the last one needed. Applying first also means that if the request
|
|
45
|
+
itself fails, the binding is still in place and the next visibility change
|
|
46
|
+
tries again — the one failure where a retry could help (#398).
|
|
47
|
+
|
|
37
48
|
Args:
|
|
38
49
|
event: The visibility event containing the widget.
|
|
39
50
|
"""
|
|
40
51
|
widget = event.widget
|
|
41
52
|
if hasattr(widget, 'alpha') and hasattr(widget, 'alpha_bind'):
|
|
42
|
-
if widget.alpha_bind:
|
|
43
|
-
widget.unbind(widget.alpha_bind)
|
|
44
53
|
widget.attributes("-alpha", widget.alpha)
|
|
54
|
+
if widget.alpha_bind:
|
|
55
|
+
# `alpha_bind` is the id `bind` returned, so it is the *funcid*
|
|
56
|
+
# argument — passing it as the sequence removes nothing at all and
|
|
57
|
+
# raises nothing either, which is how this stayed unnoticed (#398).
|
|
58
|
+
widget.unbind("<Visibility>", widget.alpha_bind)
|
|
59
|
+
widget.alpha_bind = None
|
|
45
60
|
|
|
46
61
|
|
|
47
62
|
class BaseWindow:
|
|
@@ -354,22 +354,56 @@ def _patched_unbind(
|
|
|
354
354
|
what = ('bind', self._w, sequence)
|
|
355
355
|
try:
|
|
356
356
|
script = self.tk.call(what)
|
|
357
|
-
|
|
358
|
-
#
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
357
|
+
except tk.TclError:
|
|
358
|
+
# Reading the script is the one step whose failure is expected: the
|
|
359
|
+
# widget is gone, and its bindings and commands went with it. Nothing
|
|
360
|
+
# to remove and nothing to leak.
|
|
361
|
+
return
|
|
362
|
+
|
|
363
|
+
lines = str(script).split('\n')
|
|
364
|
+
# Must match what `_patched_bind` emits (and stock `Misc._bind`).
|
|
365
|
+
prefix = 'if {"[%s ' % funcid
|
|
366
|
+
keep = [line for line in lines if not line.startswith(prefix)]
|
|
367
|
+
if len(keep) == len(lines):
|
|
368
|
+
# This funcid is not bound to this widget and sequence, so it is
|
|
369
|
+
# not ours to delete — the live binding may be somewhere else, and
|
|
370
|
+
# deleting its command would orphan it. Leave everything alone.
|
|
371
|
+
#
|
|
372
|
+
# Correct, but it means the command and its closure survive for the
|
|
373
|
+
# life of the interpreter, invisibly. Surface it in development so the
|
|
374
|
+
# drift that produced it can be found (#399).
|
|
375
|
+
#
|
|
376
|
+
# Reported, not warned. This runs inside event dispatch and on the
|
|
377
|
+
# teardown path behind `Subscription.cancel()` and its `__exit__`, both
|
|
378
|
+
# documented as safe to call on a dead or already-removed handler. A
|
|
379
|
+
# `warnings.warn` here becomes an exception out of both under
|
|
380
|
+
# `-W error`, which is a worse outcome than the leak it describes.
|
|
381
|
+
from bootstack._runtime.utility import debug_log
|
|
382
|
+
debug_log(
|
|
383
|
+
f"unbind({sequence!r}, {funcid!r}) on {self._w!r} matched no "
|
|
384
|
+
"binding, so its Tcl command cannot safely be released and will "
|
|
385
|
+
"leak. The usual cause is an unbind that targeted a different "
|
|
386
|
+
"widget than the bind did; hold the Subscription that bind() "
|
|
387
|
+
"returned instead of re-deriving the target."
|
|
388
|
+
)
|
|
389
|
+
return
|
|
390
|
+
|
|
391
|
+
remaining = '\n'.join(keep)
|
|
392
|
+
# Deliberately NOT guarded: if the rewrite fails the handler is still bound
|
|
393
|
+
# and still firing, and swallowing that would report a successful
|
|
394
|
+
# cancellation for a live handler — a silent wrong answer (#400).
|
|
395
|
+
self.tk.call(*what, remaining if remaining.strip() else '')
|
|
396
|
+
|
|
397
|
+
try:
|
|
368
398
|
# Replace the command rather than deleting it, so an in-flight copy of
|
|
369
399
|
# the concatenated script has something harmless to call.
|
|
370
400
|
self.tk.createcommand(funcid, lambda *args: '')
|
|
371
401
|
except tk.TclError:
|
|
372
|
-
|
|
402
|
+
# The binding line is already gone, so the handler is genuinely removed
|
|
403
|
+
# and an in-flight script would find the original command rather than a
|
|
404
|
+
# deleted one. Fall through to the deferred delete instead of returning,
|
|
405
|
+
# which would strand the command forever (#400).
|
|
406
|
+
pass
|
|
373
407
|
|
|
374
408
|
def _delete_command() -> None:
|
|
375
409
|
try:
|
|
@@ -57,13 +57,21 @@ _WIN_NAMES = {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
# Tkinter binding modifiers
|
|
60
|
+
#
|
|
61
|
+
# `command` and `option` are platform-mapped for the same reason `mod` and `alt`
|
|
62
|
+
# are. Off macOS the toolkit resolves the words "Command" and "Option" to its
|
|
63
|
+
# generic Mod1 and Mod2 slots, and Windows reports NumLock as Mod1 — so a
|
|
64
|
+
# `Command+S` binding fired on a bare `s` for anyone with NumLock switched on,
|
|
65
|
+
# while the menu beside it read "Ctrl+S". Naming the modifier the display has
|
|
66
|
+
# always claimed keeps the two from disagreeing (#405, and the same trap as
|
|
67
|
+
# #403).
|
|
60
68
|
_BINDING_MODIFIERS = {
|
|
61
69
|
'mod': 'Command' if IS_MAC else 'Control',
|
|
62
|
-
'command': 'Command',
|
|
70
|
+
'command': 'Command' if IS_MAC else 'Control',
|
|
63
71
|
'ctrl': 'Control',
|
|
64
72
|
'control': 'Control',
|
|
65
73
|
'alt': 'Option' if IS_MAC else 'Alt',
|
|
66
|
-
'option': 'Option',
|
|
74
|
+
'option': 'Option' if IS_MAC else 'Alt',
|
|
67
75
|
'shift': 'Shift',
|
|
68
76
|
}
|
|
69
77
|
|
|
@@ -344,6 +344,28 @@ def _debug_enabled() -> bool:
|
|
|
344
344
|
return str(os.environ.get("BOOTSTACK_DEBUG", "")).lower() in {"1", "true", "yes"}
|
|
345
345
|
|
|
346
346
|
|
|
347
|
+
def debug_log(message: str) -> None:
|
|
348
|
+
"""Print a diagnostic message if debug is enabled.
|
|
349
|
+
|
|
350
|
+
For reporting a condition that has no exception behind it. Use
|
|
351
|
+
`debug_log_exception` when there is one.
|
|
352
|
+
|
|
353
|
+
Never raises, and deliberately does not use `warnings.warn`: these fire from
|
|
354
|
+
inside event dispatch and teardown, where a warning filter set to `error`
|
|
355
|
+
would turn a diagnostic into a failure on a path documented as safe.
|
|
356
|
+
|
|
357
|
+
Args:
|
|
358
|
+
message: The text to print.
|
|
359
|
+
"""
|
|
360
|
+
if not _debug_enabled():
|
|
361
|
+
return
|
|
362
|
+
try:
|
|
363
|
+
print(f"bootstack DEBUG: {message}")
|
|
364
|
+
except Exception:
|
|
365
|
+
# Never raise from debug logging
|
|
366
|
+
pass
|
|
367
|
+
|
|
368
|
+
|
|
347
369
|
def debug_log_exception(message: str = "") -> None:
|
|
348
370
|
"""Print the current exception traceback if debug is enabled.
|
|
349
371
|
|
|
@@ -15,7 +15,10 @@ from PIL import ImageColor
|
|
|
15
15
|
from bootstack.constants import *
|
|
16
16
|
from bootstack._core import colorutils
|
|
17
17
|
from bootstack._core.colorutils import HEX, HSL, HUE, LUM, RGB, SAT
|
|
18
|
-
from bootstack.
|
|
18
|
+
from bootstack.events import Subscription
|
|
19
|
+
from bootstack.dialogs._impl.dialog import (
|
|
20
|
+
DIALOG_RESULT, Dialog, emit_dialog_result, result_target,
|
|
21
|
+
)
|
|
19
22
|
from bootstack.i18n import MessageCatalog
|
|
20
23
|
from bootstack._runtime import utility
|
|
21
24
|
from bootstack.style.style import get_style, get_theme_color
|
|
@@ -554,35 +557,28 @@ class ColorChooserDialog:
|
|
|
554
557
|
if not self._emitted_result:
|
|
555
558
|
self._emit_result(confirmed=self.result is not None)
|
|
556
559
|
|
|
557
|
-
def on_dialog_result(self, callback: Callable[[Any], None]) -> Optional[
|
|
558
|
-
"""Bind a callback fired when the dialog produces a result.
|
|
559
|
-
|
|
560
|
+
def on_dialog_result(self, callback: Callable[[Any], None]) -> "Optional[Subscription]":
|
|
561
|
+
"""Bind a callback fired when the dialog produces a result.
|
|
562
|
+
|
|
563
|
+
Returns:
|
|
564
|
+
A `Subscription`, or `None` if there is no widget to bind to.
|
|
565
|
+
Cancel it with `.cancel()`.
|
|
566
|
+
"""
|
|
567
|
+
target = result_target(self._dialog, self._master)
|
|
560
568
|
if target is None:
|
|
561
569
|
return None
|
|
562
570
|
|
|
563
571
|
def handler(event):
|
|
564
572
|
callback(getattr(event, "data", None))
|
|
565
573
|
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
"""Unbind a previously bound dialog result callback."""
|
|
570
|
-
target = self._master or self._dialog.toplevel
|
|
571
|
-
if target is None:
|
|
572
|
-
return
|
|
573
|
-
target.unbind("<<DialogResult>>", funcid)
|
|
574
|
+
# The Subscription remembers the widget it bound to — see #397.
|
|
575
|
+
bind_id = target.bind(DIALOG_RESULT, handler, add="+")
|
|
576
|
+
return Subscription(target, DIALOG_RESULT, bind_id)
|
|
574
577
|
|
|
575
578
|
# helpers ------------------------------------------------------------------
|
|
576
579
|
def _emit_result(self, confirmed: bool) -> None:
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
try:
|
|
582
|
-
target.event_generate("<<DialogResult>>", data=payload)
|
|
583
|
-
except Exception:
|
|
584
|
-
try:
|
|
585
|
-
target.event_generate("<<DialogResult>>")
|
|
586
|
-
except Exception:
|
|
587
|
-
pass
|
|
580
|
+
emit_dialog_result(
|
|
581
|
+
result_target(self._dialog, self._master),
|
|
582
|
+
{"result": self.result, "confirmed": confirmed},
|
|
583
|
+
)
|
|
588
584
|
self._emitted_result = True
|
|
@@ -14,7 +14,10 @@ from tkinter import Widget
|
|
|
14
14
|
|
|
15
15
|
from bootstack.widgets._impl.primitives import Frame
|
|
16
16
|
from bootstack.constants import BOTH, YES
|
|
17
|
-
from bootstack.
|
|
17
|
+
from bootstack.events import Subscription
|
|
18
|
+
from bootstack.dialogs._impl.dialog import (
|
|
19
|
+
DIALOG_RESULT, Dialog, DialogButton, emit_dialog_result, result_target,
|
|
20
|
+
)
|
|
18
21
|
from bootstack._runtime.window_utilities import AnchorPoint
|
|
19
22
|
from bootstack.widgets._impl.composites.calendar import Calendar
|
|
20
23
|
|
|
@@ -404,7 +407,7 @@ class DateDialog:
|
|
|
404
407
|
"""The selected date (single mode) or `(start, end)` tuple (range mode), or None if cancelled."""
|
|
405
408
|
return self._dialog.result
|
|
406
409
|
|
|
407
|
-
def on_result(self, callback: Callable[[date], None]) -> Optional[
|
|
410
|
+
def on_result(self, callback: Callable[[date], None]) -> Optional[Subscription]:
|
|
408
411
|
"""Bind a callback fired when a result is produced.
|
|
409
412
|
|
|
410
413
|
The callback receives `event.data["result"]` (a `datetime.date`).
|
|
@@ -413,38 +416,23 @@ class DateDialog:
|
|
|
413
416
|
callback: Callable that receives the selected `datetime.date`.
|
|
414
417
|
|
|
415
418
|
Returns:
|
|
416
|
-
|
|
419
|
+
A `Subscription`, or `None` if there is no widget to bind to.
|
|
420
|
+
Cancel it with `.cancel()`.
|
|
417
421
|
"""
|
|
418
|
-
target = self._dialog
|
|
422
|
+
target = result_target(self._dialog, self._master)
|
|
419
423
|
if target is None:
|
|
420
424
|
return None
|
|
421
425
|
|
|
422
426
|
def handler(event: tkinter.Event) -> None:
|
|
423
427
|
callback(getattr(event, "data", None))
|
|
424
428
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
"""Unbind a previously bound `on_result` callback.
|
|
429
|
-
|
|
430
|
-
Args:
|
|
431
|
-
funcid: Binding identifier returned by `on_result`.
|
|
432
|
-
"""
|
|
433
|
-
target = self._dialog.toplevel or self._master
|
|
434
|
-
if target is None:
|
|
435
|
-
return
|
|
436
|
-
target.unbind("<<DialogResult>>", funcid)
|
|
429
|
+
# The Subscription remembers the widget it bound to — see #397.
|
|
430
|
+
bind_id = target.bind(DIALOG_RESULT, handler, add="+")
|
|
431
|
+
return Subscription(target, DIALOG_RESULT, bind_id)
|
|
437
432
|
|
|
438
433
|
def _emit_result(self, value: date, confirmed: bool) -> None:
|
|
439
434
|
"""Emit a virtual Tk event with the dialog result."""
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
try:
|
|
445
|
-
target.event_generate("<<DialogResult>>", data=payload)
|
|
446
|
-
except Exception:
|
|
447
|
-
try:
|
|
448
|
-
target.event_generate("<<DialogResult>>")
|
|
449
|
-
except Exception:
|
|
450
|
-
pass
|
|
435
|
+
emit_dialog_result(
|
|
436
|
+
result_target(self._dialog, self._master),
|
|
437
|
+
{"result": value, "confirmed": confirmed},
|
|
438
|
+
)
|
|
@@ -127,6 +127,58 @@ class ShowOptions(TypedDict, total=False):
|
|
|
127
127
|
auto_flip: Union[bool, Literal['vertical', 'horizontal']]
|
|
128
128
|
|
|
129
129
|
|
|
130
|
+
# --- Dialog result delivery -------------------------------------------------
|
|
131
|
+
|
|
132
|
+
DIALOG_RESULT = "<<DialogResult>>"
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def result_target(dialog: "Dialog", master: Optional[tkinter.Misc]) -> Optional[tkinter.Misc]:
|
|
136
|
+
"""The widget `<<DialogResult>>` is bound on and fired from.
|
|
137
|
+
|
|
138
|
+
Binding and firing both route through here so the two cannot resolve
|
|
139
|
+
differently. That mattered: `Dialog.toplevel` is `None` before `show()`
|
|
140
|
+
and a *destroyed* widget after it, because nothing resets `_toplevel`
|
|
141
|
+
when the modal wait ends. A target derived from it is therefore never
|
|
142
|
+
live at both ends — subscribers bound to the master while the result
|
|
143
|
+
fired at a dead toplevel, where `event_generate` raised and the error
|
|
144
|
+
was swallowed (#397).
|
|
145
|
+
|
|
146
|
+
`master` comes first for that reason: it outlives the dialog.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
dialog: The dialog producing the result.
|
|
150
|
+
master: The dialog's master widget, if it has one.
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
A live widget, or `None` when there is nothing left to fire on.
|
|
154
|
+
"""
|
|
155
|
+
if master is not None:
|
|
156
|
+
return master
|
|
157
|
+
top = dialog.toplevel
|
|
158
|
+
if top is not None and top.winfo_exists():
|
|
159
|
+
return top
|
|
160
|
+
return None
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def emit_dialog_result(target: Optional[tkinter.Misc], payload: dict) -> None:
|
|
164
|
+
"""Fire `<<DialogResult>>` on `target` with `payload` attached.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
target: The widget from `result_target`, or `None` to do nothing.
|
|
168
|
+
payload: Mapping with `result` and `confirmed` keys.
|
|
169
|
+
"""
|
|
170
|
+
if target is None:
|
|
171
|
+
return
|
|
172
|
+
try:
|
|
173
|
+
target.event_generate(DIALOG_RESULT, data=payload)
|
|
174
|
+
except tkinter.TclError:
|
|
175
|
+
# `result_target` hands back a live widget, so reaching here means it
|
|
176
|
+
# was destroyed in between. Nothing can receive the result; surface it
|
|
177
|
+
# in development rather than letting it vanish the way it used to.
|
|
178
|
+
from bootstack._runtime.utility import debug_log_exception
|
|
179
|
+
debug_log_exception(f"could not deliver {DIALOG_RESULT}")
|
|
180
|
+
|
|
181
|
+
|
|
130
182
|
# --- Dialog ----------------------------------------------------------------
|
|
131
183
|
|
|
132
184
|
class Dialog:
|
|
@@ -10,7 +10,10 @@ from bootstack.widgets._impl.primitives import Frame, Label
|
|
|
10
10
|
from bootstack._core.images import _ImageService
|
|
11
11
|
from bootstack.constants import *
|
|
12
12
|
from bootstack.i18n import MessageCatalog
|
|
13
|
-
from .
|
|
13
|
+
from bootstack.events import Subscription
|
|
14
|
+
from .dialog import (
|
|
15
|
+
DIALOG_RESULT, ButtonRole, Dialog, DialogButton, emit_dialog_result, result_target,
|
|
16
|
+
)
|
|
14
17
|
|
|
15
18
|
ttk = SimpleNamespace(Frame=Frame, Label=Label)
|
|
16
19
|
|
|
@@ -198,23 +201,17 @@ class MessageDialog:
|
|
|
198
201
|
position: x and y coordinates to position the dialog. If None, centers on parent.
|
|
199
202
|
"""
|
|
200
203
|
self._dialog.show(position=position, modal=True)
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
target.event_generate("<<DialogResult>>", data=payload)
|
|
206
|
-
except Exception:
|
|
207
|
-
try:
|
|
208
|
-
target.event_generate("<<DialogResult>>")
|
|
209
|
-
except Exception:
|
|
210
|
-
pass
|
|
204
|
+
emit_dialog_result(
|
|
205
|
+
result_target(self._dialog, self._master),
|
|
206
|
+
{"result": self._dialog.result, "confirmed": self._dialog.result is not None},
|
|
207
|
+
)
|
|
211
208
|
|
|
212
209
|
@property
|
|
213
210
|
def result(self) -> Any:
|
|
214
211
|
"""The dialog result value (the text of the button pressed)."""
|
|
215
212
|
return self._dialog.result
|
|
216
213
|
|
|
217
|
-
def on_dialog_result(self, callback: Callable[[Any], None]) -> Optional[
|
|
214
|
+
def on_dialog_result(self, callback: Callable[[Any], None]) -> "Optional[Subscription]":
|
|
218
215
|
"""Bind a callback fired when the dialog produces a result.
|
|
219
216
|
|
|
220
217
|
The callback receives `event.data["result"]` when available.
|
|
@@ -223,23 +220,22 @@ class MessageDialog:
|
|
|
223
220
|
callback: Callable that receives the result payload.
|
|
224
221
|
|
|
225
222
|
Returns:
|
|
226
|
-
|
|
223
|
+
A `Subscription`, or `None` if there is no widget to bind to.
|
|
224
|
+
Cancel it with `.cancel()`.
|
|
227
225
|
"""
|
|
228
|
-
target = self._dialog
|
|
226
|
+
target = result_target(self._dialog, self._master)
|
|
229
227
|
if target is None:
|
|
230
228
|
return None
|
|
231
229
|
|
|
232
230
|
def handler(event):
|
|
233
231
|
callback(getattr(event, "data", None))
|
|
234
232
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
return
|
|
242
|
-
target.unbind("<<DialogResult>>", funcid)
|
|
233
|
+
# The Subscription remembers the widget it bound to. Resolving the
|
|
234
|
+
# target a second time to unbind would not: `_dialog.toplevel` is None
|
|
235
|
+
# until show(), so subscribing before and cancelling after resolved to
|
|
236
|
+
# two different widgets and the removal silently matched nothing (#397).
|
|
237
|
+
bind_id = target.bind(DIALOG_RESULT, handler, add="+")
|
|
238
|
+
return Subscription(target, DIALOG_RESULT, bind_id)
|
|
243
239
|
|
|
244
240
|
|
|
245
241
|
class MessageBox:
|
|
@@ -16,7 +16,10 @@ ttk = SimpleNamespace(
|
|
|
16
16
|
)
|
|
17
17
|
from bootstack.i18n import MessageCatalog
|
|
18
18
|
from bootstack.dialogs._impl.datedialog import DateDialog
|
|
19
|
-
from bootstack.
|
|
19
|
+
from bootstack.events import Subscription
|
|
20
|
+
from bootstack.dialogs._impl.dialog import (
|
|
21
|
+
DIALOG_RESULT, Dialog, DialogButton, emit_dialog_result, result_target,
|
|
22
|
+
)
|
|
20
23
|
from bootstack.dialogs._impl.fontdialog import FontDialog
|
|
21
24
|
from bootstack.dialogs._impl.message import MessageBox
|
|
22
25
|
from bootstack.widgets._impl.composites.textentry import TextEntry
|
|
@@ -264,23 +267,17 @@ class QueryDialog:
|
|
|
264
267
|
position: x and y coordinates to position the dialog. If None, centers on parent.
|
|
265
268
|
"""
|
|
266
269
|
self._dialog.show(position=position, modal=True)
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
target.event_generate("<<DialogResult>>", data=payload)
|
|
272
|
-
except Exception:
|
|
273
|
-
try:
|
|
274
|
-
target.event_generate("<<DialogResult>>")
|
|
275
|
-
except Exception:
|
|
276
|
-
pass
|
|
270
|
+
emit_dialog_result(
|
|
271
|
+
result_target(self._dialog, self._master),
|
|
272
|
+
{"result": self._dialog.result, "confirmed": self._dialog.result is not None},
|
|
273
|
+
)
|
|
277
274
|
|
|
278
275
|
@property
|
|
279
276
|
def result(self) -> Any:
|
|
280
277
|
"""The dialog result value."""
|
|
281
278
|
return self._dialog.result
|
|
282
279
|
|
|
283
|
-
def on_dialog_result(self, callback: Callable[[Any], None]) -> Optional[
|
|
280
|
+
def on_dialog_result(self, callback: Callable[[Any], None]) -> "Optional[Subscription]":
|
|
284
281
|
"""Bind a callback fired when the dialog produces a result.
|
|
285
282
|
|
|
286
283
|
The callback receives `event.data["result"]` when available.
|
|
@@ -289,23 +286,19 @@ class QueryDialog:
|
|
|
289
286
|
callback: Callable that receives the result payload.
|
|
290
287
|
|
|
291
288
|
Returns:
|
|
292
|
-
|
|
289
|
+
A `Subscription`, or `None` if there is no widget to bind to.
|
|
290
|
+
Cancel it with `.cancel()`.
|
|
293
291
|
"""
|
|
294
|
-
target = self._dialog
|
|
292
|
+
target = result_target(self._dialog, self._master)
|
|
295
293
|
if target is None:
|
|
296
294
|
return None
|
|
297
295
|
|
|
298
296
|
def handler(event):
|
|
299
297
|
callback(getattr(event, "data", None))
|
|
300
298
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
"""Unbind a previously bound dialog result callback."""
|
|
305
|
-
target = self._dialog.toplevel or self._master
|
|
306
|
-
if target is None:
|
|
307
|
-
return
|
|
308
|
-
target.unbind("<<DialogResult>>", funcid)
|
|
299
|
+
# The Subscription remembers the widget it bound to — see #397.
|
|
300
|
+
bind_id = target.bind(DIALOG_RESULT, handler, add="+")
|
|
301
|
+
return Subscription(target, DIALOG_RESULT, bind_id)
|
|
309
302
|
|
|
310
303
|
|
|
311
304
|
class QueryBox:
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import tkinter
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Subscription:
|
|
7
|
+
"""Handle returned by `widget.on(...)`. Cancels the binding when `.cancel()`
|
|
8
|
+
is called or the context manager exits.
|
|
9
|
+
|
|
10
|
+
Idempotent: calling `cancel()` more than once is a no-op.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
__slots__ = ("_widget", "_sequence", "_bind_id", "_cancelled")
|
|
14
|
+
|
|
15
|
+
def __init__(self, widget: tkinter.Misc, sequence: str, bind_id: str) -> None:
|
|
16
|
+
self._widget = widget
|
|
17
|
+
self._sequence = sequence
|
|
18
|
+
self._bind_id = bind_id
|
|
19
|
+
self._cancelled = False
|
|
20
|
+
|
|
21
|
+
def cancel(self) -> None:
|
|
22
|
+
"""Remove the binding. Safe to call more than once, and on a dead widget.
|
|
23
|
+
|
|
24
|
+
`cancelled` afterwards means the removal was carried out as far as this
|
|
25
|
+
handle can carry it — the handler will not be delivered to again through
|
|
26
|
+
this subscription.
|
|
27
|
+
"""
|
|
28
|
+
if self._cancelled:
|
|
29
|
+
return
|
|
30
|
+
try:
|
|
31
|
+
self._widget.unbind(self._sequence, self._bind_id)
|
|
32
|
+
except tkinter.TclError:
|
|
33
|
+
# The removal failed partway, which leaves the handler bound and
|
|
34
|
+
# still firing. Swallowed so teardown never fails, but deliberately
|
|
35
|
+
# NOT marked cancelled: claiming otherwise made `cancelled` read
|
|
36
|
+
# True for a live handler (#400). A later cancel() may still succeed.
|
|
37
|
+
#
|
|
38
|
+
# A widget that is merely gone does not reach here — unbind absorbs
|
|
39
|
+
# that case itself, and rightly reports success, since a destroyed
|
|
40
|
+
# widget takes its bindings with it.
|
|
41
|
+
return
|
|
42
|
+
# Includes the case where unbind found nothing to remove: the handler is
|
|
43
|
+
# already unreachable through this widget and sequence, and no retry can
|
|
44
|
+
# change that, so reporting anything but cancelled would be both wrong
|
|
45
|
+
# and permanent. If it is unreachable here because it was bound
|
|
46
|
+
# somewhere else, that is drift rather than a completed cancel, and
|
|
47
|
+
# unbind reports it under BOOTSTACK_DEBUG (#399) — this handle has no
|
|
48
|
+
# way to tell the two apart.
|
|
49
|
+
self._cancelled = True
|
|
50
|
+
|
|
51
|
+
def __enter__(self) -> "Subscription":
|
|
52
|
+
return self
|
|
53
|
+
|
|
54
|
+
def __exit__(self, exc_type, exc, tb) -> None:
|
|
55
|
+
self.cancel()
|
|
56
|
+
|
|
57
|
+
@property
|
|
58
|
+
def cancelled(self) -> bool:
|
|
59
|
+
"""Whether `cancel()` has completed for this subscription."""
|
|
60
|
+
return self._cancelled
|