bootstack 0.3.2__tar.gz → 0.4.0__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.3.2/src/bootstack.egg-info → bootstack-0.4.0}/PKG-INFO +1 -1
- {bootstack-0.3.2 → bootstack-0.4.0}/pyproject.toml +2 -2
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/_core/__init__.py +0 -4
- bootstack-0.4.0/src/bootstack/_core/mixins/widget.py +387 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/_runtime/app.py +0 -6
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/_runtime/base_window.py +0 -3
- bootstack-0.4.0/src/bootstack/_runtime/grab.py +109 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/_runtime/toplevel.py +50 -4
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/dialogs/_impl/colorchooser.py +10 -6
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/dialogs/_impl/dialog.py +1 -84
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/signals/signal.py +180 -22
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/validation/validation_rules.py +74 -2
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_core/base.py +19 -6
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_core/field_mixin.py +29 -9
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/expander.py +1 -1
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/form.py +5 -4
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/list/listview.py +1 -2
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/tableview/tableview.py +15 -10
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/tabs/tabitem.py +1 -1
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/textarea/core.py +65 -4
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/textarea/textarea.py +13 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/mixins/localization_mixin.py +1 -1
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/mixins/signal_mixin.py +1 -1
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/primitives/gridframe.py +0 -4
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/primitives/optionmenu.py +6 -2
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/primitives/packframe.py +0 -4
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/boolean_controls.py +3 -3
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/chart.py +3 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/codeeditor.py +2 -2
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/datatable.py +15 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/datefield.py +2 -1
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/menubutton.py +3 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/numberfield.py +2 -1
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/passwordfield.py +3 -3
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/pathfield.py +3 -3
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/picture.py +3 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/select.py +100 -40
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/selectbutton.py +15 -11
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/spinnerfield.py +3 -3
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/splitview.py +1 -3
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/statusbar.py +3 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/textarea.py +2 -2
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/textfield.py +3 -3
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/timefield.py +11 -2
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/toolbar.py +3 -0
- {bootstack-0.3.2 → bootstack-0.4.0/src/bootstack.egg-info}/PKG-INFO +1 -1
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack.egg-info/SOURCES.txt +3 -17
- bootstack-0.3.2/src/bootstack/_core/capabilities/__init__.py +0 -45
- bootstack-0.3.2/src/bootstack/_core/capabilities/after.py +0 -103
- bootstack-0.3.2/src/bootstack/_core/capabilities/bind.py +0 -192
- bootstack-0.3.2/src/bootstack/_core/capabilities/bindtags.py +0 -112
- bootstack-0.3.2/src/bootstack/_core/capabilities/busy.py +0 -72
- bootstack-0.3.2/src/bootstack/_core/capabilities/clipboard.py +0 -89
- bootstack-0.3.2/src/bootstack/_core/capabilities/focus.py +0 -118
- bootstack-0.3.2/src/bootstack/_core/capabilities/grab.py +0 -65
- bootstack-0.3.2/src/bootstack/_core/capabilities/grid.py +0 -211
- bootstack-0.3.2/src/bootstack/_core/capabilities/pack.py +0 -140
- bootstack-0.3.2/src/bootstack/_core/capabilities/place.py +0 -113
- bootstack-0.3.2/src/bootstack/_core/capabilities/selection.py +0 -136
- bootstack-0.3.2/src/bootstack/_core/capabilities/winfo.py +0 -315
- bootstack-0.3.2/src/bootstack/_core/colorutils.py +0 -234
- bootstack-0.3.2/src/bootstack/_core/mixins/widget.py +0 -132
- bootstack-0.3.2/src/bootstack/_core/publisher.py +0 -149
- {bootstack-0.3.2 → bootstack-0.4.0}/LICENSE +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/MANIFEST.in +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/NOTICE +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/README.md +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/setup.cfg +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/__main__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/_core/capture.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/_core/exceptions.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/_core/images.py +0 -0
- {bootstack-0.3.2/src/bootstack/_core/capabilities → bootstack-0.4.0/src/bootstack/_core}/localization.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/_core/mixins/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/_core/mixins/ttk_state.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/_core/paths.py +0 -0
- /bootstack-0.3.2/src/bootstack/_core/capabilities/signals.py → /bootstack-0.4.0/src/bootstack/_core/signal_binding.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/_core/variables.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/_runtime/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/_runtime/events.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/_runtime/shortcuts.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/_runtime/tk_patch.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/_runtime/utility.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/_runtime/visual_focus.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/_runtime/wheel.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/_runtime/window_utilities.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/bootstack.ico +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/bootstack.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/badge-pill.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/badge-square.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/button-compact.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/button-default.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/buttongroup-after-h-compact.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/buttongroup-after-h-default.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/buttongroup-after-v-compact.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/buttongroup-after-v-default.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/buttongroup-before-h-compact.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/buttongroup-before-h-default.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/buttongroup-before-v-compact.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/buttongroup-before-v-default.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/buttongroup-center-h-compact.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/buttongroup-center-h-default.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/buttongroup-center-v-compact.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/buttongroup-center-v-default.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/card.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/checkbox-checked.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/checkbox-indeterminate.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/checkbox-unchecked.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/field.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/input-addon-compact.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/input-addon-default.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/input-compact.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/input-default.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/list-item-separated.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/list-item.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/listrow-compact.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/listrow-default.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/manifest.toml +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/menu-item.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/navitem-compact.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/navitem-default.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/progressbar-h-compact.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/progressbar-h-default.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/progressbar-v-compact.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/progressbar-v-default.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/radiobutton.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/scrollbar-horizontal.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/scrollbar-vertical.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/slider-handle.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/slider-track-h.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/slider-track-v.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/switch-off.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/switch-on.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/tab-h.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/elements/tab-v.png +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/icons/bootstrap.ttf +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/icons/glyphmap.json +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/icons/icon_metrics.json +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/ar/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/ar/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/bg/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/bg/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/cs/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/cs/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/da/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/da/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/de/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/de/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/en/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/en/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/es/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/es/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/fr/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/fr/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/he/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/he/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/hi/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/hi/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/it/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/it/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/ja/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/ja/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/ko/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/ko/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/nb/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/nb/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/nl/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/nl/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/pl/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/pl/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/pt/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/pt/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/sl/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/sl/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/sv/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/sv/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/tr/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/tr/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/cli/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/cli/__main__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/cli/add.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/cli/appicon.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/cli/build.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/cli/config.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/cli/demo.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/cli/dev.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/cli/doctor.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/cli/icons.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/cli/promote.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/cli/pyinstaller.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/cli/run.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/cli/start.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/cli/templates/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/clipboard.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/constants.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/data/README.md +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/data/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/data/_observable.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/data/base.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/data/file_source.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/data/memory_source.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/data/query.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/data/readers.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/data/sqlite_source.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/data/types.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/data/writers.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/dev/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/dev/_capture.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/dev/_env.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/dev/_registry.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/dev/_reloader.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/dev/_reset.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/dev/_watcher.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/dialogs/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/dialogs/_impl/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/dialogs/_impl/datedialog.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/dialogs/_impl/filterdialog.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/dialogs/_impl/fontdialog.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/dialogs/_impl/formdialog.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/dialogs/_impl/message.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/dialogs/_impl/query.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/errors.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/events/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/events/_event.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/events/_payloads.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/events/_subscription.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/i18n/README.md +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/i18n/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/i18n/catalog.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/i18n/intl_format.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/i18n/msgcat.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/i18n/specs.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/images.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/py.typed +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/scheduling/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/scheduling/_schedule.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/shortcuts.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/signals/README.md +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/signals/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/signals/integration.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/signals/types.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/store.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/streams/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/streams/_stream.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/builders/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/builders/badge.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/builders/button.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/builders/buttongroup.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/builders/calendar.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/builders/checkbutton.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/builders/combobox.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/builders/contextmenu.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/builders/entry.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/builders/expander.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/builders/field.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/builders/frame.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/builders/label.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/builders/labelframe.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/builders/listview.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/builders/menubar.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/builders/menubutton.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/builders/panedwindow.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/builders/progressbar.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/builders/radiobutton.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/builders/scale.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/builders/scrollbar.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/builders/separator.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/builders/sidenav.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/builders/sizegrip.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/builders/spinbox.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/builders/switch.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/builders/tabitem.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/builders/togglegroup.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/builders/toolbutton.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/builders/tooltip.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/builders/treeview.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/builders/utils.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/builders_tk/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/builders_tk/defaults.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/element.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/fonts.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/style.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/style_builder_base.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/style_builder_mixed.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/style_builder_tk.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/style_builder_ttk.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/style_resolver.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/theme.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/theme_provider.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/themes/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/tk_patch.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/token_maps.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/types.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/typography.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/style/utility.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/types.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/validation/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/validation/types.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/validation/validation_result.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_core/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_core/app_config.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_core/choices.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_core/container.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_core/context.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_core/events.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_core/icon_image_props.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_core/image_binding.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_core/kwargs.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_core/navmodel.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_core/options.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_core/selection_group.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_core/window_controls.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_core/window_menu.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/_internal/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/_internal/wrapper_base.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/_parts/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/_parts/numberentry_part.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/_parts/spinnerentry_part.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/_parts/textentry_part.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/_dateutils.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/_image_fit.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/accordion.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/avatar.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/buttongroup.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/calendar.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/carousel.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/chart.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/compositeframe.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/contextmenu.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/dateentry.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/dropdownbutton.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/field.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/gallery.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/list/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/list/listitem.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/menu/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/menu/model.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/menu/render_native.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/menu/render_themed.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/meter.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/numericentry.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/pagestack.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/passwordentry.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/pathentry.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/picture.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/radiogroup.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/scrolledtext.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/scrolledtext.pyi +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/scrollview.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/selectbox.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/shell/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/shell/content_host.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/shell/layout.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/shell/nav_panel.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/shell/providers.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/shell/rail.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/shell/shell.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/shell/workspace.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/sidenav/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/sidenav/header.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/sidenav/separator.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/slider/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/slider/_shared.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/slider/rangeslider.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/slider/slider.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/spinnerentry.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/tableview/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/tableview/types.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/tabs/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/tabs/tabs.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/tabs/tabview.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/textarea/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/textarea/change.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/textarea/codeeditor.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/textarea/decoration.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/textarea/diff.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/textarea/extensions/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/textarea/extensions/bracket_matcher.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/textarea/extensions/indent_guides.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/textarea/extensions/line_numbers.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/textarea/extensions/pygments_highlighter.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/textarea/extensions/smart_indent.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/textarea/filter.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/textarea/redirector.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/textarea/search_overlay.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/textarea/sidebar.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/textarea/style_registry.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/textarea/undo.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/textentry.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/timeentry.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/toast.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/toast_stack.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/togglegroup.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/toolbar.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/tooltip.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/tree/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/tree/source_binding.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/tree/treeitem.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/tree/treenode.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/composites/tree/treeview.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/mixins/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/mixins/configure_mixin.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/mixins/entry_mixin.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/mixins/font_mixin.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/mixins/icon_mixin.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/mixins/validation_mixin.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/primitives/__init__.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/primitives/_menubutton.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/primitives/badge.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/primitives/button.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/primitives/card.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/primitives/checkbutton.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/primitives/checktoggle.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/primitives/combobox.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/primitives/entry.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/primitives/flexframe.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/primitives/frame.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/primitives/label.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/primitives/labelframe.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/primitives/panedwindow.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/primitives/progressbar.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/primitives/radiobutton.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/primitives/radiotoggle.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/primitives/scrollbar.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/primitives/separator.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/primitives/sizegrip.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/primitives/spinbox.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/primitives/switch.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/_impl/primitives/treeview.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/app.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/appshell.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/avatar.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/button.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/buttongroup.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/calendar.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/card.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/carousel.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/contextmenu.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/divider.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/expander.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/form.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/gallery.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/gauge.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/grid.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/groupbox.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/label.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/listview.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/pagestack.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/progressbar.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/radio_variants.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/radiogroup.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/scrollbar.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/scrollview.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/sidebar_toggle.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/sizegrip.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/slider.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/spinbox.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/splash.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/stacks.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/tabs.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/theme_toggle.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/toast.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/togglegroup.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/tooltip.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/tree.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/types.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack/widgets/window.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack.egg-info/dependency_links.txt +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack.egg-info/entry_points.txt +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack.egg-info/requires.txt +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/src/bootstack.egg-info/top_level.txt +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/tests/test_dialog_anchor.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/tests/test_events_doc_coverage.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/tests/test_hot_reload.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/tests/test_images.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/tests/test_images_gui.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/tests/test_intl_format.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/tests/test_navmodel.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/tests/test_on_color_contrast.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/tests/test_public_surface.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/tests/test_store.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/tests/test_theme_from_existing.py +0 -0
- {bootstack-0.3.2 → bootstack-0.4.0}/tests/test_validation_rules.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bootstack
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
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.
|
|
7
|
+
version = "0.4.0"
|
|
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.
|
|
117
|
+
current_version = "0.4.0"
|
|
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}",
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from . import colorutils, publisher, capabilities
|
|
6
5
|
from bootstack._core.exceptions import (
|
|
7
6
|
ThemeError,
|
|
8
7
|
NavigationError,
|
|
@@ -11,9 +10,6 @@ from bootstack._core.exceptions import (
|
|
|
11
10
|
)
|
|
12
11
|
|
|
13
12
|
__all__ = [
|
|
14
|
-
"colorutils",
|
|
15
|
-
"publisher",
|
|
16
|
-
"capabilities",
|
|
17
13
|
"ThemeError",
|
|
18
14
|
"NavigationError",
|
|
19
15
|
"StyleBuilderError",
|
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Mapping, Any, Callable, TypedDict, Unpack, Self
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ClipboardKwargs(TypedDict, total=False):
|
|
7
|
+
"""Keyword options accepted by clipboard operations."""
|
|
8
|
+
|
|
9
|
+
displayof: Any
|
|
10
|
+
"""Widget or window whose display to target. Omit for the main application display."""
|
|
11
|
+
type: str
|
|
12
|
+
"""Clipboard type name (e.g., `'STRING'`, `'UTF8_STRING'`). Platform-dependent."""
|
|
13
|
+
format: str
|
|
14
|
+
"""Data format for representing selection data to the X server (e.g., `'STRING'`). Platform-dependent."""
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class GridKwargs(TypedDict, total=False):
|
|
18
|
+
"""Keyword options for `grid()` and `grid_configure()`."""
|
|
19
|
+
|
|
20
|
+
row: int
|
|
21
|
+
"""Row index (0-based). Defaults to the next available row."""
|
|
22
|
+
column: int
|
|
23
|
+
"""Column index (0-based). Defaults to 0."""
|
|
24
|
+
rowspan: int
|
|
25
|
+
"""Number of rows to span. Defaults to 1."""
|
|
26
|
+
columnspan: int
|
|
27
|
+
"""Number of columns to span. Defaults to 1."""
|
|
28
|
+
sticky: str
|
|
29
|
+
"""How the widget expands within its cell (e.g., `'nsew'`, `'ew'`, `'n'`). Defaults to `''`."""
|
|
30
|
+
padx: int | tuple[int, int]
|
|
31
|
+
"""Horizontal external padding in pixels. A tuple sets (left, right) independently."""
|
|
32
|
+
pady: int | tuple[int, int]
|
|
33
|
+
"""Vertical external padding in pixels. A tuple sets (top, bottom) independently."""
|
|
34
|
+
ipadx: int
|
|
35
|
+
"""Horizontal internal padding in pixels."""
|
|
36
|
+
ipady: int
|
|
37
|
+
"""Vertical internal padding in pixels."""
|
|
38
|
+
in_: Any
|
|
39
|
+
"""Parent widget to grid into (rarely needed — defaults to the widget's own master)."""
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class GridRowColumnKwargs(TypedDict, total=False):
|
|
43
|
+
"""Keyword options for `grid_rowconfigure()` and `grid_columnconfigure()`."""
|
|
44
|
+
|
|
45
|
+
weight: int
|
|
46
|
+
"""How extra space is distributed among rows/columns. 0 means no expansion. Defaults to 0."""
|
|
47
|
+
minsize: int
|
|
48
|
+
"""Minimum row/column size in pixels. Defaults to 0."""
|
|
49
|
+
pad: int
|
|
50
|
+
"""Extra padding added to the row/column in pixels. Defaults to 0."""
|
|
51
|
+
uniform: str
|
|
52
|
+
"""Group name — rows/columns sharing a group are given equal size."""
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class PackKwargs(TypedDict, total=False):
|
|
56
|
+
"""Keyword options for `pack()` and `pack_configure()`."""
|
|
57
|
+
|
|
58
|
+
side: str
|
|
59
|
+
"""Side to pack against — `'top'`, `'bottom'`, `'left'`, or `'right'`. Defaults to `'top'`."""
|
|
60
|
+
fill: str
|
|
61
|
+
"""How to fill extra space — `'x'`, `'y'`, `'both'`, or `'none'`. Defaults to `'none'`."""
|
|
62
|
+
expand: bool | int
|
|
63
|
+
"""If True/1, the widget expands to fill extra space in the packing direction. Defaults to False."""
|
|
64
|
+
anchor: str
|
|
65
|
+
"""Where to place the widget when it does not fill available space (e.g., `'center'`, `'nw'`). Defaults to `'center'`."""
|
|
66
|
+
padx: int | tuple[int, int]
|
|
67
|
+
"""Horizontal external padding in pixels. A tuple sets (left, right) independently."""
|
|
68
|
+
pady: int | tuple[int, int]
|
|
69
|
+
"""Vertical external padding in pixels. A tuple sets (top, bottom) independently."""
|
|
70
|
+
ipadx: int
|
|
71
|
+
"""Horizontal internal padding in pixels."""
|
|
72
|
+
ipady: int
|
|
73
|
+
"""Vertical internal padding in pixels."""
|
|
74
|
+
before: Any
|
|
75
|
+
"""Pack this widget immediately before the given widget."""
|
|
76
|
+
after: Any
|
|
77
|
+
"""Pack this widget immediately after the given widget."""
|
|
78
|
+
in_: Any
|
|
79
|
+
"""Parent widget to pack into (rarely needed — defaults to the widget's own master)."""
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class WidgetCapabilitiesMixin:
|
|
83
|
+
"""Common widget API surface (tk + ttk).
|
|
84
|
+
|
|
85
|
+
This mixin aggregates documented capability mixins into a single interface
|
|
86
|
+
suitable for both Tk and ttk widgets, plus a small set of commonly used
|
|
87
|
+
widget operations (configure/cget/destroy, stacking order, etc.).
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
# -------------------------------------------------------------------------
|
|
91
|
+
# Lifecycle
|
|
92
|
+
# -------------------------------------------------------------------------
|
|
93
|
+
|
|
94
|
+
def destroy(self) -> None:
|
|
95
|
+
"""Destroy this widget and release its Tk resources."""
|
|
96
|
+
return super().destroy() # type: ignore[misc]
|
|
97
|
+
|
|
98
|
+
# -------------------------------------------------------------------------
|
|
99
|
+
# Configuration
|
|
100
|
+
# -------------------------------------------------------------------------
|
|
101
|
+
|
|
102
|
+
def configure(self, cnf: Mapping[str, Any] | None = None, **kw: Any) -> Any:
|
|
103
|
+
"""Configure widget options.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
cnf: Optional mapping of option values.
|
|
107
|
+
**kw: Option values as keyword arguments.
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
Tk returns configuration details when called with no args; otherwise
|
|
111
|
+
the return value is implementation-dependent.
|
|
112
|
+
"""
|
|
113
|
+
if cnf is None:
|
|
114
|
+
return super().configure(**kw) # type: ignore[misc]
|
|
115
|
+
return super().configure(cnf, **kw) # type: ignore[misc]
|
|
116
|
+
|
|
117
|
+
config = configure
|
|
118
|
+
|
|
119
|
+
def cget(self, key: str) -> Any:
|
|
120
|
+
"""Return the current value for an option.
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
key: Option name (with or without a leading dash).
|
|
124
|
+
|
|
125
|
+
Returns:
|
|
126
|
+
The option value.
|
|
127
|
+
"""
|
|
128
|
+
return super().cget(key) # type: ignore[misc]
|
|
129
|
+
|
|
130
|
+
# -------------------------------------------------------------------------
|
|
131
|
+
# Stacking order
|
|
132
|
+
# -------------------------------------------------------------------------
|
|
133
|
+
|
|
134
|
+
def lift(self, aboveThis: Any | None = None) -> None:
|
|
135
|
+
"""Raise this widget above its siblings.
|
|
136
|
+
|
|
137
|
+
Args:
|
|
138
|
+
aboveThis: Optional sibling widget to raise above.
|
|
139
|
+
"""
|
|
140
|
+
return super().lift(aboveThis) # type: ignore[misc]
|
|
141
|
+
|
|
142
|
+
tkraise = lift
|
|
143
|
+
|
|
144
|
+
def lower(self, belowThis: Any | None = None) -> None:
|
|
145
|
+
"""Lower this widget below its siblings.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
belowThis: Optional sibling widget to lower below.
|
|
149
|
+
"""
|
|
150
|
+
return super().lower(belowThis) # type: ignore[misc]
|
|
151
|
+
|
|
152
|
+
def after_repeat(
|
|
153
|
+
self, ms: int, func: Callable[..., Any], *args: Any
|
|
154
|
+
) -> Callable[[], None]:
|
|
155
|
+
"""Call `func` repeatedly every `ms` milliseconds.
|
|
156
|
+
|
|
157
|
+
This helper schedules `func` and then automatically reschedules it after
|
|
158
|
+
each run. It returns a `cancel()` function you can call to stop repetition.
|
|
159
|
+
|
|
160
|
+
Args:
|
|
161
|
+
ms: Interval in milliseconds.
|
|
162
|
+
func: Callback to run each interval.
|
|
163
|
+
*args: Arguments to pass to `func`.
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
A `cancel()` callable. Call it to stop the repeating schedule.
|
|
167
|
+
|
|
168
|
+
Examples:
|
|
169
|
+
>>> cancel = widget.after_repeat(250, tick)
|
|
170
|
+
>>> cancel()
|
|
171
|
+
"""
|
|
172
|
+
cancelled = False
|
|
173
|
+
token: str | None = None
|
|
174
|
+
|
|
175
|
+
def _run():
|
|
176
|
+
nonlocal token
|
|
177
|
+
if cancelled:
|
|
178
|
+
return
|
|
179
|
+
func(*args)
|
|
180
|
+
token = self.after(ms, _run)
|
|
181
|
+
|
|
182
|
+
token = self.after(ms, _run)
|
|
183
|
+
|
|
184
|
+
def cancel() -> None:
|
|
185
|
+
nonlocal cancelled, token
|
|
186
|
+
cancelled = True
|
|
187
|
+
if token is not None:
|
|
188
|
+
try:
|
|
189
|
+
self.after_cancel(token)
|
|
190
|
+
except Exception:
|
|
191
|
+
pass
|
|
192
|
+
token = None
|
|
193
|
+
|
|
194
|
+
return cancel
|
|
195
|
+
|
|
196
|
+
def bindtags_prepend(self, tag: str) -> tuple[str, ...]:
|
|
197
|
+
"""Prepend a tag to the bindtags list.
|
|
198
|
+
|
|
199
|
+
This increases the tag's priority (it will be processed earlier).
|
|
200
|
+
|
|
201
|
+
Args:
|
|
202
|
+
tag: Tag name to prepend.
|
|
203
|
+
|
|
204
|
+
Returns:
|
|
205
|
+
The updated bindtags tuple.
|
|
206
|
+
"""
|
|
207
|
+
current = list(self.bindtags())
|
|
208
|
+
if tag not in current:
|
|
209
|
+
current.insert(0, tag)
|
|
210
|
+
self.bindtags(current)
|
|
211
|
+
return tuple(current)
|
|
212
|
+
|
|
213
|
+
def bindtags_append(self, tag: str) -> tuple[str, ...]:
|
|
214
|
+
"""Append a tag to the bindtags list.
|
|
215
|
+
|
|
216
|
+
This decreases the tag's priority (it will be processed later).
|
|
217
|
+
|
|
218
|
+
Args:
|
|
219
|
+
tag: Tag name to append.
|
|
220
|
+
|
|
221
|
+
Returns:
|
|
222
|
+
The updated bindtags tuple.
|
|
223
|
+
"""
|
|
224
|
+
current = list(self.bindtags())
|
|
225
|
+
if tag not in current:
|
|
226
|
+
current.append(tag)
|
|
227
|
+
self.bindtags(current)
|
|
228
|
+
return tuple(current)
|
|
229
|
+
|
|
230
|
+
def bindtags_remove(self, tag: str) -> tuple[str, ...]:
|
|
231
|
+
"""Remove a tag from the bindtags list.
|
|
232
|
+
|
|
233
|
+
Args:
|
|
234
|
+
tag: Tag name to remove.
|
|
235
|
+
|
|
236
|
+
Returns:
|
|
237
|
+
The updated bindtags tuple.
|
|
238
|
+
"""
|
|
239
|
+
current = [t for t in self.bindtags() if t != tag]
|
|
240
|
+
self.bindtags(current)
|
|
241
|
+
return tuple(current)
|
|
242
|
+
|
|
243
|
+
def bindtags_replace(self, old: str, new: str) -> tuple[str, ...]:
|
|
244
|
+
"""Replace a bindtag with another tag.
|
|
245
|
+
|
|
246
|
+
Args:
|
|
247
|
+
old: Existing tag name.
|
|
248
|
+
new: Replacement tag name.
|
|
249
|
+
|
|
250
|
+
Returns:
|
|
251
|
+
The updated bindtags tuple.
|
|
252
|
+
"""
|
|
253
|
+
current = list(self.bindtags())
|
|
254
|
+
try:
|
|
255
|
+
idx = current.index(old)
|
|
256
|
+
except ValueError:
|
|
257
|
+
return tuple(current)
|
|
258
|
+
current[idx] = new
|
|
259
|
+
self.bindtags(current)
|
|
260
|
+
return tuple(current)
|
|
261
|
+
|
|
262
|
+
def clipboard_set(self, text: str, **kw: Unpack[ClipboardKwargs]) -> None:
|
|
263
|
+
"""Replace clipboard contents with *text*.
|
|
264
|
+
|
|
265
|
+
Convenience wrapper for `clipboard_clear()` + `clipboard_append()`.
|
|
266
|
+
|
|
267
|
+
Args:
|
|
268
|
+
text: Text to set on the clipboard.
|
|
269
|
+
**kw: See `ClipboardKwargs`. Forwarded to both clear and append.
|
|
270
|
+
"""
|
|
271
|
+
self.clipboard_clear(**kw)
|
|
272
|
+
self.clipboard_append(text, **kw)
|
|
273
|
+
|
|
274
|
+
def grid(self, cnf: dict[str, Any] | None = None, **kw: Unpack[GridKwargs]) -> Self:
|
|
275
|
+
"""Position this widget using the grid geometry manager.
|
|
276
|
+
|
|
277
|
+
Args:
|
|
278
|
+
cnf: Optional dict of grid options (same keys as `GridKwargs`).
|
|
279
|
+
**kw: See `GridKwargs`.
|
|
280
|
+
|
|
281
|
+
Returns:
|
|
282
|
+
Self for method chaining.
|
|
283
|
+
"""
|
|
284
|
+
options = cnf or {}
|
|
285
|
+
options.update(kw)
|
|
286
|
+
|
|
287
|
+
parent = self.master # type: ignore[attr-defined]
|
|
288
|
+
if hasattr(parent, "_on_child_grid"):
|
|
289
|
+
parent._on_child_grid(self, **options)
|
|
290
|
+
else:
|
|
291
|
+
super().grid(**options) # type: ignore[misc]
|
|
292
|
+
return self # type: ignore[return-value]
|
|
293
|
+
|
|
294
|
+
def grid_configure(
|
|
295
|
+
self, cnf: dict[str, Any] | None = None, **kw: Unpack[GridKwargs]
|
|
296
|
+
) -> Self:
|
|
297
|
+
"""Alias for `grid()`.
|
|
298
|
+
|
|
299
|
+
Args:
|
|
300
|
+
cnf: Optional dict of grid options.
|
|
301
|
+
**kw: See `GridKwargs`.
|
|
302
|
+
|
|
303
|
+
Returns:
|
|
304
|
+
Self for method chaining.
|
|
305
|
+
"""
|
|
306
|
+
return self.grid(cnf, **kw)
|
|
307
|
+
|
|
308
|
+
def grid_forget(self) -> Self:
|
|
309
|
+
"""Unmap this widget and forget its grid configuration.
|
|
310
|
+
|
|
311
|
+
The widget is removed from the layout, and its previous grid options
|
|
312
|
+
are discarded.
|
|
313
|
+
|
|
314
|
+
Returns:
|
|
315
|
+
Self for method chaining.
|
|
316
|
+
"""
|
|
317
|
+
parent = self.master # type: ignore[attr-defined]
|
|
318
|
+
if hasattr(parent, "_on_child_grid_forget"):
|
|
319
|
+
parent._on_child_grid_forget(self)
|
|
320
|
+
else:
|
|
321
|
+
super().grid_forget() # type: ignore[misc]
|
|
322
|
+
return self # type: ignore[return-value]
|
|
323
|
+
|
|
324
|
+
def grid_remove(self) -> Self:
|
|
325
|
+
"""Unmap this widget but remember its grid configuration.
|
|
326
|
+
|
|
327
|
+
Use `grid()` with no args to restore it to its previous grid location.
|
|
328
|
+
|
|
329
|
+
Returns:
|
|
330
|
+
Self for method chaining.
|
|
331
|
+
"""
|
|
332
|
+
parent = self.master # type: ignore[attr-defined]
|
|
333
|
+
if hasattr(parent, "_on_child_grid_remove"):
|
|
334
|
+
parent._on_child_grid_remove(self)
|
|
335
|
+
else:
|
|
336
|
+
super().grid_remove() # type: ignore[misc]
|
|
337
|
+
return self # type: ignore[return-value]
|
|
338
|
+
|
|
339
|
+
def pack(self, cnf: dict[str, Any] | None = None, **kw: Unpack[PackKwargs]) -> Self:
|
|
340
|
+
"""Position this widget using the pack geometry manager.
|
|
341
|
+
|
|
342
|
+
Args:
|
|
343
|
+
cnf: Optional dict of pack options (same keys as `PackKwargs`).
|
|
344
|
+
**kw: See `PackKwargs`.
|
|
345
|
+
|
|
346
|
+
Returns:
|
|
347
|
+
Self for method chaining.
|
|
348
|
+
"""
|
|
349
|
+
options = cnf or {}
|
|
350
|
+
options.update(kw)
|
|
351
|
+
|
|
352
|
+
parent = self.master # type: ignore[attr-defined]
|
|
353
|
+
if hasattr(parent, "_on_child_pack"):
|
|
354
|
+
parent._on_child_pack(self, **options)
|
|
355
|
+
else:
|
|
356
|
+
super().pack(**options) # type: ignore[misc]
|
|
357
|
+
return self # type: ignore[return-value]
|
|
358
|
+
|
|
359
|
+
def pack_configure(
|
|
360
|
+
self, cnf: dict[str, Any] | None = None, **kw: Unpack[PackKwargs]
|
|
361
|
+
) -> Self:
|
|
362
|
+
"""Alias for `pack()`.
|
|
363
|
+
|
|
364
|
+
Args:
|
|
365
|
+
cnf: Optional dict of pack options.
|
|
366
|
+
**kw: See `PackKwargs`.
|
|
367
|
+
|
|
368
|
+
Returns:
|
|
369
|
+
Self for method chaining.
|
|
370
|
+
"""
|
|
371
|
+
return self.pack(cnf, **kw)
|
|
372
|
+
|
|
373
|
+
def pack_forget(self) -> Self:
|
|
374
|
+
"""Unmap this widget and forget its pack configuration.
|
|
375
|
+
|
|
376
|
+
The widget is removed from the layout, and its previous pack options
|
|
377
|
+
are discarded.
|
|
378
|
+
|
|
379
|
+
Returns:
|
|
380
|
+
Self for method chaining.
|
|
381
|
+
"""
|
|
382
|
+
parent = self.master # type: ignore[attr-defined]
|
|
383
|
+
if hasattr(parent, "_on_child_pack_forget"):
|
|
384
|
+
parent._on_child_pack_forget(self)
|
|
385
|
+
else:
|
|
386
|
+
super().pack_forget() # type: ignore[misc]
|
|
387
|
+
return self # type: ignore[return-value]
|
|
@@ -19,7 +19,6 @@ from typing_extensions import Unpack
|
|
|
19
19
|
from bootstack.constants import *
|
|
20
20
|
from bootstack.i18n.intl_format import detect_locale
|
|
21
21
|
from bootstack.i18n.msgcat import MessageCatalog
|
|
22
|
-
from bootstack._core.publisher import Publisher
|
|
23
22
|
from bootstack._core.mixins.widget import WidgetCapabilitiesMixin
|
|
24
23
|
from bootstack._runtime.base_window import BaseWindow
|
|
25
24
|
from bootstack._runtime.utility import enable_high_dpi_awareness
|
|
@@ -156,7 +155,6 @@ def apply_class_bindings(window: tkinter.Widget | App) -> None:
|
|
|
156
155
|
def apply_all_bindings(window: tkinter.Widget | App) -> None:
|
|
157
156
|
"""Add bindings to all widgets in the application"""
|
|
158
157
|
window.bind_all('<Map>', on_map_child, '+')
|
|
159
|
-
window.bind_all('<Destroy>', lambda e: Publisher.unsubscribe(e.widget))
|
|
160
158
|
|
|
161
159
|
|
|
162
160
|
def on_disabled_readonly_state(event: tkinter.Event) -> None:
|
|
@@ -382,10 +380,6 @@ class App(BaseWindow, WidgetCapabilitiesMixin, tkinter.Tk):
|
|
|
382
380
|
"""The primary application window and entry point.
|
|
383
381
|
|
|
384
382
|
App adds theming, localization, and platform setup on top of `tkinter.Tk`.
|
|
385
|
-
|
|
386
|
-
The standard widget API (events, scheduling, clipboard, geometry managers,
|
|
387
|
-
winfo, etc.) is documented under bootstack capabilities and is available
|
|
388
|
-
on App via inheritance.
|
|
389
383
|
"""
|
|
390
384
|
|
|
391
385
|
def __init__(
|
|
@@ -5,9 +5,6 @@ window management functionality used by both the main App and Toplevel classes.
|
|
|
5
5
|
This eliminates code duplication and ensures consistent behavior across all
|
|
6
6
|
window types.
|
|
7
7
|
|
|
8
|
-
Standard widget APIs (events, scheduling, clipboard, geometry managers, winfo) are documented under capabilities and are
|
|
9
|
-
available through normal Tk/Ttk inheritance.”
|
|
10
|
-
|
|
11
8
|
The BaseWindow mixin provides:
|
|
12
9
|
- Window manager (wm) pass-throughs with modern docstrings
|
|
13
10
|
- Window configuration (size, position, constraints)
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"""Modal grab capture and restore, shared by the dialog and window paths.
|
|
2
|
+
|
|
3
|
+
Tk releases a grab when the window holding it is destroyed, but it does NOT
|
|
4
|
+
restore the grab that window displaced. Anything that takes a modal grab has to
|
|
5
|
+
hand back what it found, or the window underneath is left on screen, still
|
|
6
|
+
blocking its caller, holding nothing (#440 for dialogs, #444 for windows).
|
|
7
|
+
|
|
8
|
+
These live here rather than beside the dialogs because the import direction runs
|
|
9
|
+
dialogs -> _runtime: `dialogs/_impl/dialog.py` imports `Toplevel` from this
|
|
10
|
+
package, so `_runtime` reaching back the other way would be a cycle.
|
|
11
|
+
"""
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import tkinter
|
|
15
|
+
from typing import Any
|
|
16
|
+
|
|
17
|
+
def capture_grab(widget: Any) -> tuple[Any, str | None] | None:
|
|
18
|
+
"""Record who holds the modal grab and HOW, for `restore_grab` to hand back.
|
|
19
|
+
|
|
20
|
+
Returns `None` when nothing holds the grab — the outermost case, which needs
|
|
21
|
+
no restore. Otherwise returns the holder paired with its grab KIND.
|
|
22
|
+
|
|
23
|
+
⚠ Call this BEFORE taking the grab. Once another window grabs, the previous
|
|
24
|
+
holder's `grab_status()` reads `None`, so a kind read afterwards is always
|
|
25
|
+
wrong — measured, and the reason this pairing exists as one function rather
|
|
26
|
+
than two steps a caller has to sequence correctly.
|
|
27
|
+
|
|
28
|
+
The kind matters because Tk has two: `bs.Window(modal="app")` takes a GLOBAL
|
|
29
|
+
grab, and restoring that as a local one silently narrows the window's
|
|
30
|
+
modality (it would block only this application). Reading the kind back from
|
|
31
|
+
Tk rather than assuming it keeps this correct on every window system without
|
|
32
|
+
a platform branch — whatever Tk reported, we hand back.
|
|
33
|
+
|
|
34
|
+
A holder this cannot ADDRESS reads the same as no holder at all. Resolving
|
|
35
|
+
who holds the grab goes through a name lookup that raises for a window the
|
|
36
|
+
toolkit created on its own — a posted combobox popdown is one — and there is
|
|
37
|
+
nothing to hand back to a window we cannot name. This runs on the SETUP path,
|
|
38
|
+
where a raise would escape into the application, so it degrades to `None` and
|
|
39
|
+
logs rather than propagating.
|
|
40
|
+
"""
|
|
41
|
+
try:
|
|
42
|
+
holder = widget.grab_current()
|
|
43
|
+
except (AttributeError, KeyError, tkinter.TclError):
|
|
44
|
+
_log_grab_failure("could not identify the current grab holder")
|
|
45
|
+
return None
|
|
46
|
+
if holder is None:
|
|
47
|
+
return None
|
|
48
|
+
try:
|
|
49
|
+
kind = holder.grab_status()
|
|
50
|
+
except (AttributeError, tkinter.TclError):
|
|
51
|
+
# Fall back to the narrower grab rather than guessing global.
|
|
52
|
+
kind = "local"
|
|
53
|
+
return (holder, kind)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def restore_grab(previous: tuple[Any, str | None] | None) -> None:
|
|
57
|
+
"""Hand the modal grab back to whatever held it before the caller took it.
|
|
58
|
+
|
|
59
|
+
Tk releases a grab when the window holding it is destroyed, but it does NOT
|
|
60
|
+
restore the grab that window displaced. So a modal opened from inside
|
|
61
|
+
another modal — `bs.alert()` from a dialog button command, or a
|
|
62
|
+
`bs.Window(modal=True)` opened from a dialog's "Advanced..." button — took
|
|
63
|
+
the grab over and then dropped it on the floor when it closed. The OUTER
|
|
64
|
+
window was left on screen and still blocking its caller, yet holding no
|
|
65
|
+
grab at all: the user could click straight back into the main window and
|
|
66
|
+
drive the app underneath it, against something that was modal in appearance
|
|
67
|
+
only (issue #440 for dialogs, #444 for windows).
|
|
68
|
+
|
|
69
|
+
Pass the token `capture_grab()` returned. `None` means nothing held the
|
|
70
|
+
grab, which is the outermost case and needs no restore.
|
|
71
|
+
|
|
72
|
+
A failure here is deliberately swallowed. This runs on a teardown path,
|
|
73
|
+
where the previous holder may itself have been destroyed while the inner
|
|
74
|
+
window was up, or the whole interpreter may be going down — and something
|
|
75
|
+
that has already closed must not raise on its way out. It is LOGGED rather
|
|
76
|
+
than passed over in silence, because a failed restore is the very defect
|
|
77
|
+
this function exists to prevent: the outer window stays on screen holding
|
|
78
|
+
nothing.
|
|
79
|
+
|
|
80
|
+
⚠ A global restore can fail where a local one cannot — `grab set -global`
|
|
81
|
+
is the call Tk's viewability rule guards, and on X11 it can also lose to
|
|
82
|
+
another client. That is the one way this is riskier than always restoring
|
|
83
|
+
a local grab, so a failed global restore DEGRADES TO LOCAL rather than to
|
|
84
|
+
nothing: modal within the application is imperfect, but it is not the #440
|
|
85
|
+
symptom.
|
|
86
|
+
"""
|
|
87
|
+
if previous is None:
|
|
88
|
+
return
|
|
89
|
+
holder, kind = previous
|
|
90
|
+
try:
|
|
91
|
+
if not holder.winfo_exists():
|
|
92
|
+
return
|
|
93
|
+
if kind == "global":
|
|
94
|
+
try:
|
|
95
|
+
holder.grab_set_global()
|
|
96
|
+
except tkinter.TclError:
|
|
97
|
+
_log_grab_failure("could not restore a global grab; falling back to local")
|
|
98
|
+
holder.grab_set()
|
|
99
|
+
else:
|
|
100
|
+
holder.grab_set()
|
|
101
|
+
except (AttributeError, tkinter.TclError):
|
|
102
|
+
_log_grab_failure("could not restore the previous grab holder")
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def _log_grab_failure(message: str) -> None:
|
|
106
|
+
"""Report a grab failure without ever raising from a teardown path."""
|
|
107
|
+
from bootstack._runtime.utility import debug_log_exception
|
|
108
|
+
|
|
109
|
+
debug_log_exception(message)
|
|
@@ -7,6 +7,7 @@ from typing import Any, Callable, Literal, Optional, Tuple
|
|
|
7
7
|
|
|
8
8
|
from bootstack._core.mixins.widget import WidgetCapabilitiesMixin
|
|
9
9
|
from bootstack._runtime.base_window import BaseWindow
|
|
10
|
+
from bootstack._runtime.grab import capture_grab, restore_grab
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
class Toplevel(BaseWindow, WidgetCapabilitiesMixin, tkinter.Toplevel):
|
|
@@ -15,10 +16,6 @@ class Toplevel(BaseWindow, WidgetCapabilitiesMixin, tkinter.Toplevel):
|
|
|
15
16
|
This class wraps `tkinter.Toplevel` and adds bootstack window conveniences
|
|
16
17
|
(title/geometry helpers, centering, alpha/topmost/toolwindow helpers, etc.).
|
|
17
18
|
|
|
18
|
-
The standard widget API (events, scheduling, clipboard, geometry managers,
|
|
19
|
-
winfo, etc.) is available through inheritance and is documented under
|
|
20
|
-
bootstack capabilities.
|
|
21
|
-
|
|
22
19
|
For additional information on the underlying Tk/Tkinter behavior, see:
|
|
23
20
|
- Tcl/Tk `toplevel` command documentation
|
|
24
21
|
- Python `tkinter.Toplevel` documentation
|
|
@@ -107,6 +104,10 @@ class Toplevel(BaseWindow, WidgetCapabilitiesMixin, tkinter.Toplevel):
|
|
|
107
104
|
# modal level — stored for use in show()
|
|
108
105
|
self._modal = modal
|
|
109
106
|
|
|
107
|
+
# Grab handed back when this window is destroyed; see show().
|
|
108
|
+
self._previous_grab: tuple[Any, str | None] | None = None
|
|
109
|
+
self._grab_restore_bound = False
|
|
110
|
+
|
|
110
111
|
# Apply Aqua MacWindowStyle BEFORE any setup that might pump the
|
|
111
112
|
# event loop (icons, geometry, update_idletasks). Tk's docs require
|
|
112
113
|
# the style to be set on a freshly-created, never-mapped window;
|
|
@@ -223,15 +224,60 @@ class Toplevel(BaseWindow, WidgetCapabilitiesMixin, tkinter.Toplevel):
|
|
|
223
224
|
"""Show the window and apply modal grab if configured."""
|
|
224
225
|
super().show()
|
|
225
226
|
if self._modal:
|
|
227
|
+
# Remember who held the grab, and how, so it can be handed back when
|
|
228
|
+
# this window goes away. Tk drops a grab on destroy but never
|
|
229
|
+
# restores the one it displaced, so a modal opened from inside
|
|
230
|
+
# another modal used to leave its opener on screen, still blocking
|
|
231
|
+
# its caller, holding nothing at all (#444 — #440 fixed the same
|
|
232
|
+
# defect on the dialog path). Captured BEFORE the grab: once another
|
|
233
|
+
# window grabs, the previous holder's grab_status() reads None.
|
|
234
|
+
#
|
|
235
|
+
# Captured ONCE. show() is re-callable — show(anchor_to=) re-anchors
|
|
236
|
+
# an open window and block_until_closed() shows it itself — and a
|
|
237
|
+
# later capture finds this window already holding the grab, so it
|
|
238
|
+
# would record the window as its own previous holder.
|
|
239
|
+
if not self._grab_restore_bound:
|
|
240
|
+
self._previous_grab = capture_grab(self)
|
|
226
241
|
try:
|
|
227
242
|
if self._modal == "app":
|
|
228
243
|
self.grab_set_global()
|
|
229
244
|
else:
|
|
230
245
|
self.grab_set()
|
|
246
|
+
except tkinter.TclError:
|
|
247
|
+
pass
|
|
248
|
+
else:
|
|
249
|
+
# Owed because the grab was TAKEN, so bound off the grab alone —
|
|
250
|
+
# focus gets its own guard rather than standing between the two.
|
|
251
|
+
self._bind_grab_restore()
|
|
252
|
+
try:
|
|
231
253
|
self.focus_set()
|
|
232
254
|
except tkinter.TclError:
|
|
233
255
|
pass
|
|
234
256
|
|
|
257
|
+
def _bind_grab_restore(self) -> None:
|
|
258
|
+
"""Hand the displaced grab back when this window is destroyed.
|
|
259
|
+
|
|
260
|
+
Bound on destroy rather than paired around `block_until_closed()`,
|
|
261
|
+
because a modal window does not have to block — `show()` followed by a
|
|
262
|
+
later `destroy()` is an ordinary path, and pairing on the blocking one
|
|
263
|
+
alone would leave it unfixed. Measured before choosing it: the restore
|
|
264
|
+
wins its race with Tk's own grab release, so `grab_current()` reads the
|
|
265
|
+
opener again once the dust settles
|
|
266
|
+
(`development/probe_444_grab_restore_ordering.py`).
|
|
267
|
+
"""
|
|
268
|
+
if self._grab_restore_bound:
|
|
269
|
+
return
|
|
270
|
+
self._grab_restore_bound = True
|
|
271
|
+
|
|
272
|
+
def _restore(event: Any) -> None:
|
|
273
|
+
# <Destroy> fires for every descendant, not just the window.
|
|
274
|
+
if event.widget is not self:
|
|
275
|
+
return
|
|
276
|
+
restore_grab(self._previous_grab)
|
|
277
|
+
self._previous_grab = None
|
|
278
|
+
|
|
279
|
+
self.bind("<Destroy>", _restore, add="+")
|
|
280
|
+
|
|
235
281
|
# -------------------------------------------------------------------------
|
|
236
282
|
# result property + block_until_closed()
|
|
237
283
|
# -------------------------------------------------------------------------
|