bootstack 0.1.5__tar.gz → 0.1.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {bootstack-0.1.5/src/bootstack.egg-info → bootstack-0.1.7}/PKG-INFO +4 -5
- {bootstack-0.1.5 → bootstack-0.1.7}/README.md +3 -4
- {bootstack-0.1.5 → bootstack-0.1.7}/pyproject.toml +2 -2
- bootstack-0.1.7/src/bootstack/_runtime/wheel.py +152 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/i18n/intl_format.py +7 -3
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/validation/validation_rules.py +20 -2
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_core/base.py +24 -0
- bootstack-0.1.7/src/bootstack/widgets/_core/kwargs.py +85 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_core/selection_group.py +7 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/_parts/numberentry_part.py +29 -28
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/_parts/textentry_part.py +8 -2
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/dropdownbutton.py +15 -2
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/field.py +7 -2
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/form.py +71 -29
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/gallery.py +22 -10
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/list/listview.py +46 -32
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/scrolledtext.py +34 -36
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/scrollview.py +41 -36
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/selectbox.py +89 -12
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/tabs/tabs.py +23 -18
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/textarea/core.py +18 -19
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/tree/treeview.py +33 -16
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/primitives/spinbox.py +24 -7
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/buttongroup.py +23 -9
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/menubutton.py +4 -1
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/passwordfield.py +3 -1
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/pathfield.py +3 -1
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/radiogroup.py +9 -2
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/select.py +14 -3
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/statusbar.py +5 -1
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/textfield.py +3 -1
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/togglegroup.py +9 -2
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/toolbar.py +8 -3
- {bootstack-0.1.5 → bootstack-0.1.7/src/bootstack.egg-info}/PKG-INFO +4 -5
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack.egg-info/SOURCES.txt +2 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/tests/test_intl_format.py +25 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/tests/test_validation_rules.py +61 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/LICENSE +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/MANIFEST.in +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/NOTICE +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/setup.cfg +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/__main__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/_core/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/_core/capabilities/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/_core/capabilities/after.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/_core/capabilities/bind.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/_core/capabilities/bindtags.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/_core/capabilities/busy.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/_core/capabilities/clipboard.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/_core/capabilities/focus.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/_core/capabilities/grab.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/_core/capabilities/grid.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/_core/capabilities/localization.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/_core/capabilities/pack.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/_core/capabilities/place.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/_core/capabilities/selection.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/_core/capabilities/signals.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/_core/capabilities/winfo.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/_core/colorutils.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/_core/exceptions.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/_core/images.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/_core/mixins/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/_core/mixins/ttk_state.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/_core/mixins/widget.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/_core/paths.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/_core/publisher.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/_core/variables.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/_runtime/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/_runtime/app.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/_runtime/base_window.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/_runtime/events.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/_runtime/shortcuts.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/_runtime/tk_patch.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/_runtime/toplevel.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/_runtime/utility.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/_runtime/visual_focus.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/_runtime/window_utilities.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/bootstack.ico +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/bootstack.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/badge-pill.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/badge-square.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/button-compact.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/button-default.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/buttongroup-after-h-compact.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/buttongroup-after-h-default.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/buttongroup-after-v-compact.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/buttongroup-after-v-default.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/buttongroup-before-h-compact.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/buttongroup-before-h-default.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/buttongroup-before-v-compact.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/buttongroup-before-v-default.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/buttongroup-center-h-compact.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/buttongroup-center-h-default.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/buttongroup-center-v-compact.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/buttongroup-center-v-default.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/card.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/checkbox-checked.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/checkbox-indeterminate.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/checkbox-unchecked.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/field.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/input-addon-compact.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/input-addon-default.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/input-compact.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/input-default.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/list-item-separated.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/list-item.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/listrow-compact.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/listrow-default.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/manifest.toml +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/menu-item.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/navitem-compact.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/navitem-default.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/progressbar-h-compact.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/progressbar-h-default.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/progressbar-v-compact.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/progressbar-v-default.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/radiobutton.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/scrollbar-horizontal.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/scrollbar-vertical.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/slider-handle.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/slider-track-h.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/slider-track-v.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/switch-off.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/switch-on.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/tab-h.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/elements/tab-v.png +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/icons/bootstrap.ttf +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/icons/glyphmap.json +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/icons/icon_metrics.json +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/ar/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/ar/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/bg/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/bg/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/cs/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/cs/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/da/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/da/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/de/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/de/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/en/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/en/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/es/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/es/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/fr/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/fr/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/he/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/he/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/hi/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/hi/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/it/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/it/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/ja/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/ja/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/ko/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/ko/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/nb/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/nb/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/nl/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/nl/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/pl/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/pl/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/pt/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/pt/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/sl/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/sl/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/sv/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/sv/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/tr/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/tr/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.mo +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.po +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/cli/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/cli/__main__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/cli/add.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/cli/appicon.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/cli/build.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/cli/config.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/cli/demo.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/cli/dev.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/cli/doctor.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/cli/icons.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/cli/promote.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/cli/pyinstaller.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/cli/run.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/cli/start.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/cli/templates/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/clipboard.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/constants.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/data/README.md +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/data/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/data/_observable.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/data/base.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/data/file_source.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/data/memory_source.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/data/query.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/data/readers.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/data/sqlite_source.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/data/types.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/data/writers.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/dev/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/dev/_capture.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/dev/_env.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/dev/_registry.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/dev/_reloader.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/dev/_reset.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/dev/_watcher.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/dialogs/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/dialogs/_impl/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/dialogs/_impl/colorchooser.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/dialogs/_impl/datedialog.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/dialogs/_impl/dialog.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/dialogs/_impl/filterdialog.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/dialogs/_impl/fontdialog.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/dialogs/_impl/formdialog.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/dialogs/_impl/message.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/dialogs/_impl/query.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/errors.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/events/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/events/_event.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/events/_payloads.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/events/_subscription.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/i18n/README.md +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/i18n/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/i18n/catalog.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/i18n/msgcat.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/i18n/specs.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/images.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/py.typed +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/scheduling/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/scheduling/_schedule.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/shortcuts.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/signals/README.md +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/signals/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/signals/integration.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/signals/signal.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/signals/types.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/store.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/streams/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/streams/_stream.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/builders/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/builders/badge.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/builders/button.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/builders/buttongroup.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/builders/calendar.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/builders/checkbutton.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/builders/combobox.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/builders/contextmenu.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/builders/entry.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/builders/expander.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/builders/field.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/builders/frame.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/builders/label.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/builders/labelframe.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/builders/listview.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/builders/menubar.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/builders/menubutton.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/builders/panedwindow.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/builders/progressbar.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/builders/radiobutton.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/builders/scale.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/builders/scrollbar.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/builders/separator.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/builders/sidenav.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/builders/sizegrip.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/builders/spinbox.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/builders/switch.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/builders/tabitem.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/builders/togglegroup.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/builders/toolbutton.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/builders/tooltip.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/builders/treeview.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/builders/utils.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/builders_tk/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/builders_tk/defaults.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/element.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/fonts.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/style.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/style_builder_base.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/style_builder_mixed.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/style_builder_tk.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/style_builder_ttk.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/style_resolver.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/theme.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/theme_provider.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/themes/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/tk_patch.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/token_maps.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/types.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/typography.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/style/utility.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/types.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/validation/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/validation/types.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/validation/validation_result.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_core/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_core/app_config.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_core/container.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_core/context.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_core/events.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_core/field_mixin.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_core/icon_image_props.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_core/image_binding.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_core/navmodel.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_core/options.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_core/window_controls.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_core/window_menu.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/_internal/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/_internal/wrapper_base.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/_parts/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/_parts/spinnerentry_part.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/_dateutils.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/_image_fit.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/accordion.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/avatar.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/buttongroup.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/calendar.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/carousel.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/chart.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/compositeframe.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/contextmenu.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/dateentry.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/expander.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/list/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/list/listitem.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/menu/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/menu/model.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/menu/render_native.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/menu/render_themed.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/meter.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/numericentry.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/pagestack.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/passwordentry.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/pathentry.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/picture.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/radiogroup.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/scrolledtext.pyi +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/shell/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/shell/content_host.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/shell/layout.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/shell/nav_panel.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/shell/providers.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/shell/rail.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/shell/shell.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/shell/workspace.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/sidenav/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/sidenav/header.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/sidenav/separator.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/slider/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/slider/_shared.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/slider/rangeslider.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/slider/slider.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/spinnerentry.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/tableview/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/tableview/tableview.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/tableview/types.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/tabs/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/tabs/tabitem.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/tabs/tabview.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/textarea/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/textarea/change.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/textarea/codeeditor.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/textarea/decoration.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/textarea/diff.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/textarea/extensions/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/textarea/extensions/bracket_matcher.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/textarea/extensions/indent_guides.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/textarea/extensions/line_numbers.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/textarea/extensions/pygments_highlighter.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/textarea/extensions/smart_indent.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/textarea/filter.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/textarea/search_overlay.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/textarea/sidebar.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/textarea/style_registry.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/textarea/textarea.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/textarea/undo.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/textentry.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/timeentry.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/toast.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/toast_stack.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/togglegroup.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/toolbar.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/tooltip.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/tree/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/tree/source_binding.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/tree/treeitem.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/tree/treenode.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/mixins/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/mixins/configure_mixin.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/mixins/entry_mixin.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/mixins/font_mixin.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/mixins/icon_mixin.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/mixins/localization_mixin.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/mixins/signal_mixin.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/mixins/validation_mixin.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/primitives/__init__.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/primitives/_menubutton.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/primitives/badge.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/primitives/button.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/primitives/card.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/primitives/checkbutton.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/primitives/checktoggle.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/primitives/combobox.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/primitives/entry.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/primitives/flexframe.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/primitives/frame.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/primitives/gridframe.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/primitives/label.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/primitives/labelframe.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/primitives/optionmenu.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/primitives/packframe.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/primitives/panedwindow.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/primitives/progressbar.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/primitives/radiobutton.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/primitives/radiotoggle.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/primitives/scrollbar.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/primitives/separator.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/primitives/sizegrip.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/primitives/switch.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/primitives/treeview.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/app.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/appshell.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/avatar.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/boolean_controls.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/button.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/calendar.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/card.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/carousel.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/chart.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/codeeditor.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/contextmenu.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/datatable.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/datefield.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/divider.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/expander.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/form.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/gallery.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/gauge.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/grid.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/groupbox.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/label.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/listview.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/numberfield.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/pagestack.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/picture.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/progressbar.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/radio_variants.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/scrollbar.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/scrollview.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/selectbutton.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/sidebar_toggle.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/sizegrip.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/slider.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/spinbox.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/spinnerfield.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/splash.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/splitview.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/stacks.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/tabs.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/textarea.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/theme_toggle.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/timefield.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/toast.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/tooltip.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/tree.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/types.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/window.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack.egg-info/dependency_links.txt +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack.egg-info/entry_points.txt +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack.egg-info/requires.txt +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack.egg-info/top_level.txt +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/tests/test_dialog_anchor.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/tests/test_events_doc_coverage.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/tests/test_hot_reload.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/tests/test_images.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/tests/test_images_gui.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/tests/test_navmodel.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/tests/test_on_color_contrast.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/tests/test_public_surface.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/tests/test_store.py +0 -0
- {bootstack-0.1.5 → bootstack-0.1.7}/tests/test_theme_from_existing.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bootstack
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.7
|
|
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
|
|
@@ -66,10 +66,9 @@ Dynamic: license-file
|
|
|
66
66
|
|
|
67
67
|
### Desktop apps in pure Python — Tk underneath, none of the boilerplate.
|
|
68
68
|
|
|
69
|
-
bootstack is built on Tk, so the install is light
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
and a CLI that scaffolds and packages the whole thing.
|
|
69
|
+
bootstack is built on Tk, so the install is light and your app ships as a small standalone executable. But you'll never
|
|
70
|
+
write a `StringVar` or call `.pack()` — the API is its own. 60+ widgets, reactive state, and a CLI that scaffolds and
|
|
71
|
+
packages the whole thing.
|
|
73
72
|
|
|
74
73
|
<p align="center">
|
|
75
74
|
<picture>
|
|
@@ -13,10 +13,9 @@
|
|
|
13
13
|
|
|
14
14
|
### Desktop apps in pure Python — Tk underneath, none of the boilerplate.
|
|
15
15
|
|
|
16
|
-
bootstack is built on Tk, so the install is light
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
and a CLI that scaffolds and packages the whole thing.
|
|
16
|
+
bootstack is built on Tk, so the install is light and your app ships as a small standalone executable. But you'll never
|
|
17
|
+
write a `StringVar` or call `.pack()` — the API is its own. 60+ widgets, reactive state, and a CLI that scaffolds and
|
|
18
|
+
packages the whole thing.
|
|
20
19
|
|
|
21
20
|
<p align="center">
|
|
22
21
|
<picture>
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "bootstack"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.7"
|
|
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.1.
|
|
117
|
+
current_version = "0.1.7"
|
|
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}",
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"""Scroll-gesture normalization across Tk 8.6 and Tk 9.
|
|
2
|
+
|
|
3
|
+
Tk 9 changed the scroll-event contract in two ways that break code written
|
|
4
|
+
against Tk 8.6:
|
|
5
|
+
|
|
6
|
+
* A precise-delta device — every Apple trackpad, Magic Mouse and Magic
|
|
7
|
+
Trackpad — now fires `<TouchpadScroll>` and **never** `<MouseWheel>`.
|
|
8
|
+
Binding only `<MouseWheel>` leaves those devices completely dead.
|
|
9
|
+
* Wheel deltas are normalized to multiples of 120 on every windowing
|
|
10
|
+
system. On Aqua a notch used to report 1; it now reports 120.
|
|
11
|
+
|
|
12
|
+
On X11, `<Button-4>`/`<Button-5>` are no longer delivered to scripts at
|
|
13
|
+
all — Tk translates them to `<MouseWheel>` internally.
|
|
14
|
+
|
|
15
|
+
This module hides all of that behind one vocabulary. Callers ask for the
|
|
16
|
+
sequences to bind, then convert an incoming event to either wheel
|
|
17
|
+
*notches* or precise *pixels*.
|
|
18
|
+
|
|
19
|
+
Sign convention (matching Tk's own bindings): a positive value means the
|
|
20
|
+
wheel rolled away from the user, i.e. the view should move toward the
|
|
21
|
+
*start* of the content. Callers therefore negate to get a scroll amount.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
import tkinter as tk
|
|
27
|
+
|
|
28
|
+
TOUCHPAD_SCROLL = "<TouchpadScroll>"
|
|
29
|
+
"""Sequence for precise-delta scroll gestures. Tk 8.7+ only."""
|
|
30
|
+
|
|
31
|
+
_WHEEL_UNITS = 120.0
|
|
32
|
+
"""Delta reported for one wheel notch on a normalized (Tk 8.7+) build."""
|
|
33
|
+
|
|
34
|
+
_TOUCHPAD_TK = 8.7
|
|
35
|
+
"""First Tk release generating `<TouchpadScroll>` and normalized deltas."""
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _windowingsystem(widget: tk.Misc) -> str:
|
|
39
|
+
try:
|
|
40
|
+
return str(widget.tk.call("tk", "windowingsystem")).lower()
|
|
41
|
+
except Exception:
|
|
42
|
+
return ""
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def has_touchpad_scroll() -> bool:
|
|
46
|
+
"""Whether the running Tk generates `<TouchpadScroll>` events."""
|
|
47
|
+
return tk.TkVersion >= _TOUCHPAD_TK
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def uses_x11_buttons(widget: tk.Misc) -> bool:
|
|
51
|
+
"""Whether wheel input arrives as `<Button-4>`/`<Button-5>` here.
|
|
52
|
+
|
|
53
|
+
True only on legacy X11 builds. Tk 8.7+ translates those buttons to
|
|
54
|
+
`<MouseWheel>` and stops delivering them to scripts.
|
|
55
|
+
"""
|
|
56
|
+
return not has_touchpad_scroll() and _windowingsystem(widget) == "x11"
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def wheel_sequences(widget: tk.Misc, *, shift: bool = False) -> tuple[str, ...]:
|
|
60
|
+
"""Event sequences carrying wheel notches for `widget`.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
widget: Any widget; used to resolve the windowing system.
|
|
64
|
+
shift: Request the horizontal (Shift-modified) sequences.
|
|
65
|
+
"""
|
|
66
|
+
if uses_x11_buttons(widget):
|
|
67
|
+
if shift:
|
|
68
|
+
return ("<Shift-Button-4>", "<Shift-Button-5>")
|
|
69
|
+
return ("<Button-4>", "<Button-5>")
|
|
70
|
+
return ("<Shift-MouseWheel>",) if shift else ("<MouseWheel>",)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def wheel_notches(widget: tk.Misc, event: tk.Event) -> float:
|
|
74
|
+
"""Signed notch count for a wheel event.
|
|
75
|
+
|
|
76
|
+
Returns a positive value when the wheel rolled away from the user.
|
|
77
|
+
One physical notch is 1.0 on every platform and Tk version.
|
|
78
|
+
"""
|
|
79
|
+
num = getattr(event, "num", None)
|
|
80
|
+
if num in (4, 6):
|
|
81
|
+
return 1.0
|
|
82
|
+
if num in (5, 7):
|
|
83
|
+
return -1.0
|
|
84
|
+
|
|
85
|
+
try:
|
|
86
|
+
delta = float(event.delta)
|
|
87
|
+
except (AttributeError, TypeError, ValueError):
|
|
88
|
+
return 0.0
|
|
89
|
+
if not delta:
|
|
90
|
+
return 0.0
|
|
91
|
+
|
|
92
|
+
# Tk 8.6 on Aqua reported one notch as 1; everything else uses 120.
|
|
93
|
+
if not has_touchpad_scroll() and _windowingsystem(widget) == "aqua":
|
|
94
|
+
return delta
|
|
95
|
+
return delta / _WHEEL_UNITS
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def precise_deltas(event: tk.Event) -> tuple[int, int]:
|
|
99
|
+
"""Unpack a `<TouchpadScroll>` event into `(dx, dy)` pixels.
|
|
100
|
+
|
|
101
|
+
Tk packs both axes into the delta field as two signed 16-bit values.
|
|
102
|
+
This mirrors Tcl's `::tk::PreciseScrollDeltas`.
|
|
103
|
+
"""
|
|
104
|
+
try:
|
|
105
|
+
packed = int(event.delta)
|
|
106
|
+
except (AttributeError, TypeError, ValueError):
|
|
107
|
+
return (0, 0)
|
|
108
|
+
dx = packed >> 16
|
|
109
|
+
low = packed & 0xFFFF
|
|
110
|
+
dy = low if low < 0x8000 else low - 0x10000
|
|
111
|
+
return (dx, dy)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def scale_num(widget: tk.Misc, value: float) -> int:
|
|
115
|
+
"""Scale a pixel amount for display density, like `::tk::ScaleNum`."""
|
|
116
|
+
try:
|
|
117
|
+
scaling = float(widget.tk.call("tk", "scaling"))
|
|
118
|
+
except Exception:
|
|
119
|
+
scaling = 1.0
|
|
120
|
+
return round(value * scaling * 0.75)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class PixelAccumulator:
|
|
124
|
+
"""Converts precise pixel deltas into whole discrete scroll steps.
|
|
125
|
+
|
|
126
|
+
A touchpad reports small deltas roughly sixty times a second. Widgets
|
|
127
|
+
that scroll by rows or canvas units cannot act on each one, so the
|
|
128
|
+
fractional remainder is carried forward until it adds up to a step.
|
|
129
|
+
"""
|
|
130
|
+
|
|
131
|
+
__slots__ = ("_x", "_y")
|
|
132
|
+
|
|
133
|
+
def __init__(self) -> None:
|
|
134
|
+
self._x = 0.0
|
|
135
|
+
self._y = 0.0
|
|
136
|
+
|
|
137
|
+
def add(self, dx: float, dy: float, step_x: float, step_y: float) -> tuple[int, int]:
|
|
138
|
+
"""Add a delta and return the whole `(x, y)` steps it completes."""
|
|
139
|
+
step_x = step_x if step_x and step_x > 0 else 1.0
|
|
140
|
+
step_y = step_y if step_y and step_y > 0 else 1.0
|
|
141
|
+
self._x += dx
|
|
142
|
+
self._y += dy
|
|
143
|
+
out_x = int(self._x / step_x)
|
|
144
|
+
out_y = int(self._y / step_y)
|
|
145
|
+
self._x -= out_x * step_x
|
|
146
|
+
self._y -= out_y * step_y
|
|
147
|
+
return (out_x, out_y)
|
|
148
|
+
|
|
149
|
+
def reset(self) -> None:
|
|
150
|
+
"""Drop any carried remainder."""
|
|
151
|
+
self._x = 0.0
|
|
152
|
+
self._y = 0.0
|
|
@@ -12,6 +12,7 @@ import locale
|
|
|
12
12
|
import re
|
|
13
13
|
import warnings
|
|
14
14
|
from dataclasses import dataclass
|
|
15
|
+
from decimal import Decimal
|
|
15
16
|
from datetime import date, datetime, time
|
|
16
17
|
from typing import Any, Literal, Mapping, Optional, TypedDict, Union, cast
|
|
17
18
|
|
|
@@ -148,7 +149,10 @@ SUFFIXES_EN = (
|
|
|
148
149
|
Suffix(1_000, "K"),
|
|
149
150
|
)
|
|
150
151
|
_SUFFIX_TO_FACTOR = {"K": 1_000, "M": 1_000_000, "B": 1_000_000_000, "T": 1_000_000_000_000}
|
|
151
|
-
|
|
152
|
+
# Values formatted as numbers. `Decimal` is passed to Babel as-is rather than
|
|
153
|
+
# coerced: Babel formats it natively, and going through `float` would round
|
|
154
|
+
# away the precision a caller chose `Decimal` to keep.
|
|
155
|
+
_NUMBERISH = (int, float, Decimal)
|
|
152
156
|
|
|
153
157
|
|
|
154
158
|
def _locale_to_languages(loc: str) -> list[str]:
|
|
@@ -208,7 +212,7 @@ class IntlFormatter:
|
|
|
208
212
|
if value is None:
|
|
209
213
|
return ""
|
|
210
214
|
if isinstance(value, _NUMBERISH):
|
|
211
|
-
return self._format_number(float(value), spec)
|
|
215
|
+
return self._format_number(value if isinstance(value, Decimal) else float(value), spec)
|
|
212
216
|
if isinstance(value, datetime):
|
|
213
217
|
return self._format_datetime(value, spec)
|
|
214
218
|
if isinstance(value, date):
|
|
@@ -238,7 +242,7 @@ class IntlFormatter:
|
|
|
238
242
|
return self._parse_temporal(s, spec)
|
|
239
243
|
|
|
240
244
|
# ---------- Numbers ----------
|
|
241
|
-
def _format_number(self, x: float, spec: LooseSpec) -> str:
|
|
245
|
+
def _format_number(self, x: float | Decimal, spec: LooseSpec) -> str:
|
|
242
246
|
opt = self._normalize_number_spec(spec)
|
|
243
247
|
|
|
244
248
|
if opt["type"] == "custom":
|
|
@@ -33,6 +33,16 @@ def rule_applies_to_kind(rule_type: str, kind: str) -> bool:
|
|
|
33
33
|
return True
|
|
34
34
|
|
|
35
35
|
|
|
36
|
+
def _is_empty(value: object) -> bool:
|
|
37
|
+
"""Whether a field holds nothing, for rules that only shape a value.
|
|
38
|
+
|
|
39
|
+
Matches the emptiness test `range` uses: `None` or the empty string. A
|
|
40
|
+
whitespace-only entry is real input — `stringLength` should still measure
|
|
41
|
+
it — so only `required` treats blank text as absent.
|
|
42
|
+
"""
|
|
43
|
+
return value is None or value == ""
|
|
44
|
+
|
|
45
|
+
|
|
36
46
|
def _as_text(value: object) -> str:
|
|
37
47
|
"""Coerce a value to text for the string rules.
|
|
38
48
|
|
|
@@ -104,7 +114,15 @@ class ValidationRule:
|
|
|
104
114
|
# Everything else is valid (non-empty string, number, date, etc.)
|
|
105
115
|
return ValidationResult(True, "")
|
|
106
116
|
|
|
107
|
-
|
|
117
|
+
# A rule other than `required` describes what a value must look like,
|
|
118
|
+
# not that one must be present. An untouched optional field has nothing
|
|
119
|
+
# to check, so it passes — otherwise leaving it blank would block a
|
|
120
|
+
# submit with no way forward. Use `required` for presence, the same
|
|
121
|
+
# contract `range` states below.
|
|
122
|
+
if self.type in TEXT_RULES and _is_empty(value):
|
|
123
|
+
return ValidationResult(True, "")
|
|
124
|
+
|
|
125
|
+
if self.type == "email":
|
|
108
126
|
if not re.match(r"[^@]+@[^@]+\.[^@]+", _as_text(value)):
|
|
109
127
|
return ValidationResult(False, msg)
|
|
110
128
|
elif self.type == "stringLength":
|
|
@@ -119,7 +137,7 @@ class ValidationRule:
|
|
|
119
137
|
elif self.type == "range":
|
|
120
138
|
# Bounds on an ordered value (number/date/time). An empty field is
|
|
121
139
|
# not out of range — use 'required' for presence.
|
|
122
|
-
if value
|
|
140
|
+
if _is_empty(value):
|
|
123
141
|
return ValidationResult(True)
|
|
124
142
|
lo = self.params.get("min")
|
|
125
143
|
hi = self.params.get("max")
|
|
@@ -355,6 +355,7 @@ class PublicWidgetBase:
|
|
|
355
355
|
options.update(_flex_child_opts(self, kwargs))
|
|
356
356
|
master.add_child(self._internal, options, index=index)
|
|
357
357
|
placement.options = options
|
|
358
|
+
self._recolor_on_attach()
|
|
358
359
|
return
|
|
359
360
|
|
|
360
361
|
if kwargs:
|
|
@@ -376,6 +377,29 @@ class PublicWidgetBase:
|
|
|
376
377
|
options.update({k: v for k, v in kwargs.items() if k in PLACE_KEYS})
|
|
377
378
|
self._internal.place(in_=master, **options)
|
|
378
379
|
placement.options = options
|
|
380
|
+
self._recolor_on_attach()
|
|
381
|
+
|
|
382
|
+
def _recolor_on_attach(self) -> None:
|
|
383
|
+
"""Recolor after a theme change that arrived while detached.
|
|
384
|
+
|
|
385
|
+
The theme walk skips off-screen widgets, so a widget detached across a
|
|
386
|
+
theme change comes back carrying the old palette. Attaching is the
|
|
387
|
+
genuine "now visible" trigger, matching PageStack navigation and
|
|
388
|
+
Expander expansion. Deferred to idle so the widget is mapped first.
|
|
389
|
+
"""
|
|
390
|
+
widget = self._internal
|
|
391
|
+
|
|
392
|
+
def _recolor() -> None:
|
|
393
|
+
from bootstack.style.style import get_style
|
|
394
|
+
try:
|
|
395
|
+
get_style().apply_theme_walk(widget, only_stale=True)
|
|
396
|
+
except tkinter.TclError:
|
|
397
|
+
pass # destroyed between attach and the idle callback
|
|
398
|
+
|
|
399
|
+
try:
|
|
400
|
+
widget.after_idle(_recolor)
|
|
401
|
+
except tkinter.TclError:
|
|
402
|
+
pass
|
|
379
403
|
|
|
380
404
|
@overload
|
|
381
405
|
def on_destroy(self) -> "Stream": ...
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""Merging a caller's options dict over framework-built keyword arguments.
|
|
2
|
+
|
|
3
|
+
Several widgets accept a bag of options aimed at a widget they build for you —
|
|
4
|
+
`Form`'s `editor_options`, `MenuButton`'s `menu_options`, the keyword
|
|
5
|
+
passthrough on `ButtonGroup.add` / `RadioGroup.add` / `Toolbar.add_widget`.
|
|
6
|
+
Those bags name the built widget's own public keyword arguments, so a caller
|
|
7
|
+
may name a parameter the framework also fills.
|
|
8
|
+
|
|
9
|
+
Splatting both into one call raises `TypeError: got multiple values for
|
|
10
|
+
keyword argument`, which names an internal class the caller never wrote.
|
|
11
|
+
`merge_kwargs` gives that meeting point one rule instead:
|
|
12
|
+
|
|
13
|
+
- The caller's options WIN over the framework's defaults. Naming a parameter
|
|
14
|
+
the framework also fills is how you override it.
|
|
15
|
+
- A short list of keys is structural — the widget cannot do its job if they
|
|
16
|
+
are replaced (it would be parented elsewhere, or lose the command that emits
|
|
17
|
+
its events). Supplying one raises `BootstackError` naming the API you called
|
|
18
|
+
and what to use instead.
|
|
19
|
+
"""
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
from typing import Any, Mapping
|
|
23
|
+
|
|
24
|
+
from bootstack.errors import BootstackError
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def reject_reserved(
|
|
28
|
+
user: Mapping[str, Any] | None,
|
|
29
|
+
reserved: Mapping[str, str] | None,
|
|
30
|
+
context: str,
|
|
31
|
+
) -> None:
|
|
32
|
+
"""Raise if the caller set a key the framework owns.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
user: The caller's options. `None` is treated as empty.
|
|
36
|
+
reserved: Structural keys the caller may not set, mapped to the
|
|
37
|
+
guidance shown when they try.
|
|
38
|
+
context: The API the caller invoked, e.g. `'ButtonGroup.add()'`.
|
|
39
|
+
|
|
40
|
+
Raises:
|
|
41
|
+
BootstackError: If `user` contains a key listed in `reserved`.
|
|
42
|
+
"""
|
|
43
|
+
if not user or not reserved:
|
|
44
|
+
return
|
|
45
|
+
for key in user:
|
|
46
|
+
if key in reserved:
|
|
47
|
+
raise BootstackError(f"{context} does not accept {key}= — {reserved[key]}")
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def merge_kwargs(
|
|
51
|
+
defaults: Mapping[str, Any],
|
|
52
|
+
user: Mapping[str, Any] | None,
|
|
53
|
+
*,
|
|
54
|
+
reserved: Mapping[str, str] | None = None,
|
|
55
|
+
context: str = "this call",
|
|
56
|
+
) -> dict[str, Any]:
|
|
57
|
+
"""Merge a caller's options over framework-built keyword arguments.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
defaults: Keyword arguments the framework derived for the call. Any
|
|
61
|
+
key also present in `user` is overridden.
|
|
62
|
+
reserved: Structural keys the caller may not set, mapped to the
|
|
63
|
+
guidance shown when they try.
|
|
64
|
+
context: The API the caller invoked, used in the error message.
|
|
65
|
+
user: The caller's options. `None` is treated as empty.
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
The merged keyword arguments.
|
|
69
|
+
|
|
70
|
+
Raises:
|
|
71
|
+
BootstackError: If `user` contains a key listed in `reserved`.
|
|
72
|
+
"""
|
|
73
|
+
merged = dict(defaults)
|
|
74
|
+
if not user:
|
|
75
|
+
return merged
|
|
76
|
+
reject_reserved(user, reserved, context)
|
|
77
|
+
merged.update(user)
|
|
78
|
+
return merged
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
# Structural keys a bar's widget-options passthrough may not set — a toolbar or
|
|
82
|
+
# status bar places every widget it builds.
|
|
83
|
+
RESERVED_BAR_KWARGS = {
|
|
84
|
+
'parent': 'the bar places the widgets it builds.',
|
|
85
|
+
}
|
|
@@ -4,6 +4,13 @@ from typing import Any
|
|
|
4
4
|
|
|
5
5
|
from bootstack.widgets._core.options import OptionRecord, record_to_dict, option_localize
|
|
6
6
|
|
|
7
|
+
# Structural keys a per-option kwargs passthrough may not set — the group owns
|
|
8
|
+
# each option's identity and tracks its own selection.
|
|
9
|
+
RESERVED_OPTION_KWARGS = {
|
|
10
|
+
'text': 'set the caption with the label argument.',
|
|
11
|
+
'variable': 'the group tracks its own selection.',
|
|
12
|
+
}
|
|
13
|
+
|
|
7
14
|
|
|
8
15
|
class SelectionGroupMixin:
|
|
9
16
|
"""Shared item-management surface for the option-group widgets.
|
|
@@ -6,10 +6,14 @@ wheel support.
|
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
8
|
|
|
9
|
+
from bootstack._runtime import wheel
|
|
9
10
|
from bootstack.events import ChangeEvent
|
|
10
11
|
from bootstack.widgets._impl.mixins.configure_mixin import configure_delegate
|
|
11
12
|
from bootstack.widgets._impl._parts.textentry_part import TextEntryPart
|
|
12
13
|
|
|
14
|
+
_TOUCHPAD_STEP_PX = 40
|
|
15
|
+
"""Trackpad travel, in pixels, that advances a stepper by one increment."""
|
|
16
|
+
|
|
13
17
|
|
|
14
18
|
class NumberEntryPart(TextEntryPart):
|
|
15
19
|
"""Numeric entry widget with stepping and bounds validation.
|
|
@@ -111,12 +115,13 @@ class NumberEntryPart(TextEntryPart):
|
|
|
111
115
|
self.bind('<Up>', self._handle_up_key, add=True)
|
|
112
116
|
self.bind('<Down>', self._handle_down_key, add=True)
|
|
113
117
|
|
|
114
|
-
# Bind
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
118
|
+
# Bind wheel stepping. A wheel arrives as <MouseWheel> everywhere
|
|
119
|
+
# except legacy X11; a trackpad fires <TouchpadScroll> on Tk 8.7+.
|
|
120
|
+
for seq in wheel.wheel_sequences(self):
|
|
121
|
+
self.bind(seq, self._handle_mouse_wheel, add=True)
|
|
122
|
+
if wheel.has_touchpad_scroll():
|
|
123
|
+
self._touchpad = wheel.PixelAccumulator()
|
|
124
|
+
self.bind(wheel.TOUCHPAD_SCROLL, self._handle_touchpad_scroll, add=True)
|
|
120
125
|
|
|
121
126
|
# Listen for increment/decrement events to invoke step
|
|
122
127
|
self.bind('<<Increment>>', self._handle_increment_event, add=True)
|
|
@@ -137,33 +142,28 @@ class NumberEntryPart(TextEntryPart):
|
|
|
137
142
|
return 'break' # Prevent default behavior
|
|
138
143
|
|
|
139
144
|
def _handle_mouse_wheel(self, event):
|
|
140
|
-
"""Handle
|
|
145
|
+
"""Handle a wheel notch by stepping the value once."""
|
|
141
146
|
if not self._is_interactive():
|
|
142
147
|
return 'break'
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
if delta != 0:
|
|
149
|
-
if delta > 0:
|
|
150
|
-
self.event_generate('<<Increment>>', data={'value': self._value})
|
|
151
|
-
else:
|
|
152
|
-
self.event_generate('<<Decrement>>', data={'value': self._value})
|
|
148
|
+
notches = wheel.wheel_notches(self, event)
|
|
149
|
+
if notches:
|
|
150
|
+
name = '<<Increment>>' if notches > 0 else '<<Decrement>>'
|
|
151
|
+
self.event_generate(name, data={'value': self._value})
|
|
153
152
|
return 'break'
|
|
154
153
|
|
|
155
|
-
def
|
|
156
|
-
"""
|
|
157
|
-
if not self._is_interactive():
|
|
158
|
-
return 'break'
|
|
159
|
-
self.event_generate('<<Increment>>', data={'value': self._value})
|
|
160
|
-
return 'break'
|
|
154
|
+
def _handle_touchpad_scroll(self, event):
|
|
155
|
+
"""Step once per `_TOUCHPAD_STEP_PX` of trackpad travel.
|
|
161
156
|
|
|
162
|
-
|
|
163
|
-
|
|
157
|
+
A trackpad reports around sixty events a second; stepping on each
|
|
158
|
+
one would run the value away from the user.
|
|
159
|
+
"""
|
|
164
160
|
if not self._is_interactive():
|
|
165
161
|
return 'break'
|
|
166
|
-
|
|
162
|
+
_dx, dy = wheel.precise_deltas(event)
|
|
163
|
+
_sx, steps = self._touchpad.add(0, dy, 1, _TOUCHPAD_STEP_PX)
|
|
164
|
+
name = '<<Increment>>' if steps > 0 else '<<Decrement>>'
|
|
165
|
+
for _ in range(abs(steps)):
|
|
166
|
+
self.event_generate(name, data={'value': self._value})
|
|
167
167
|
return 'break'
|
|
168
168
|
|
|
169
169
|
def _handle_increment_event(self, event):
|
|
@@ -272,9 +272,10 @@ class NumberEntryPart(TextEntryPart):
|
|
|
272
272
|
A plain numeric field parses to a string when no display format is set,
|
|
273
273
|
so coerce it the same way the public value does — validation rules and a
|
|
274
274
|
`custom` func receive a real `int`/`float` (or `None` for empty/invalid
|
|
275
|
-
input), never the display string.
|
|
275
|
+
input), never the display string. A visible placeholder is not input,
|
|
276
|
+
so it reads as empty here — same rule as the text field this overrides.
|
|
276
277
|
"""
|
|
277
|
-
text = self.get()
|
|
278
|
+
text = '' if self._showing_placeholder else self.get()
|
|
278
279
|
try:
|
|
279
280
|
raw = self._parse_or_none(text)
|
|
280
281
|
except Exception:
|
|
@@ -288,11 +288,17 @@ class TextEntryPart(ValidationMixin, Entry):
|
|
|
288
288
|
last-committed value. This keeps a manual `validate()`, the automatic
|
|
289
289
|
blur/key validation, and a form-level validate in agreement on the same
|
|
290
290
|
live, typed input.
|
|
291
|
+
|
|
292
|
+
A visible placeholder is not input. It is inserted into the entry to
|
|
293
|
+
render it, so reading the raw text would hand the placeholder string to
|
|
294
|
+
the rules and `required` would pass on an untouched field — the field
|
|
295
|
+
reads as empty here, exactly as it does through `value`.
|
|
291
296
|
"""
|
|
297
|
+
text = "" if self._showing_placeholder else self.get()
|
|
292
298
|
try:
|
|
293
|
-
return self._parse_or_none(
|
|
299
|
+
return self._parse_or_none(text)
|
|
294
300
|
except Exception:
|
|
295
|
-
return
|
|
301
|
+
return text
|
|
296
302
|
|
|
297
303
|
def text(self, value=None):
|
|
298
304
|
"""Get or set the raw display text without committing.
|
{bootstack-0.1.5 → bootstack-0.1.7}/src/bootstack/widgets/_impl/composites/dropdownbutton.py
RENAMED
|
@@ -7,8 +7,18 @@ from typing_extensions import Unpack
|
|
|
7
7
|
from bootstack.widgets._impl.composites.contextmenu import ContextMenu, ContextMenuItem, ContextMenuItemResult
|
|
8
8
|
from bootstack.widgets._impl.primitives._menubutton import MenuButton
|
|
9
9
|
from bootstack.widgets._impl.mixins import configure_delegate
|
|
10
|
+
from bootstack.widgets._core.kwargs import merge_kwargs
|
|
10
11
|
from bootstack.widgets.types import Master, StyledKwargs, CompoundMode, WidgetState, WidgetDensity
|
|
11
12
|
|
|
13
|
+
# Structural keys a menu_options bag may not set — the button owns the menu's
|
|
14
|
+
# contents and the callback that emits its selection events.
|
|
15
|
+
_RESERVED_MENU_OPTIONS = {
|
|
16
|
+
'items': 'pass the menu items to the button itself.',
|
|
17
|
+
'command': "use the button's on_select event.",
|
|
18
|
+
'trigger': 'the button opens its own menu when clicked.',
|
|
19
|
+
'target': 'the menu belongs to the button that opens it.',
|
|
20
|
+
}
|
|
21
|
+
|
|
12
22
|
if TYPE_CHECKING:
|
|
13
23
|
from bootstack.signals import Signal
|
|
14
24
|
|
|
@@ -122,10 +132,13 @@ class DropdownButton(MenuButton):
|
|
|
122
132
|
"offset": (offset_x, 0),
|
|
123
133
|
"density": density,
|
|
124
134
|
}
|
|
125
|
-
options.update(self._popdown_options)
|
|
126
135
|
# DropdownButton manages its own activation (left-click, Return/
|
|
127
136
|
# KP_Enter via show_menu), so opt out of ContextMenu's auto-trigger.
|
|
128
|
-
|
|
137
|
+
options["trigger"] = None
|
|
138
|
+
options = merge_kwargs(options, self._popdown_options,
|
|
139
|
+
reserved=_RESERVED_MENU_OPTIONS,
|
|
140
|
+
context='MenuButton menu_options')
|
|
141
|
+
cm = ContextMenu(self, target=self, items=self._items, command=self._command, **options)
|
|
129
142
|
return cm
|
|
130
143
|
|
|
131
144
|
@property
|
|
@@ -273,8 +273,13 @@ class Field(EntryMixin, Frame):
|
|
|
273
273
|
self._entry.value(value)
|
|
274
274
|
|
|
275
275
|
def get(self) -> str:
|
|
276
|
-
"""Return the
|
|
277
|
-
|
|
276
|
+
"""Return the display text from the underlying entry widget.
|
|
277
|
+
|
|
278
|
+
Reads the entry's own text rather than its raw contents, so a field
|
|
279
|
+
showing only its placeholder reports an empty string — `text` and
|
|
280
|
+
`value` are a pair and must agree on whether the field is empty.
|
|
281
|
+
"""
|
|
282
|
+
return self._entry.text()
|
|
278
283
|
|
|
279
284
|
@property
|
|
280
285
|
def entry_widget(self) -> EntryWidget:
|