bootstack 0.1.0a1__py3-none-any.whl
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/__init__.py +249 -0
- bootstack/__main__.py +5 -0
- bootstack/api/__init__.py +127 -0
- bootstack/api/app.py +30 -0
- bootstack/api/constants.py +3 -0
- bootstack/api/data.py +23 -0
- bootstack/api/dialogs.py +44 -0
- bootstack/api/i18n.py +17 -0
- bootstack/api/localization.py +16 -0
- bootstack/api/menu.py +7 -0
- bootstack/api/style.py +23 -0
- bootstack/api/utils.py +24 -0
- bootstack/api/widgets.py +137 -0
- bootstack/assets/__init__.py +24 -0
- bootstack/assets/bootstack-transparent.png +0 -0
- bootstack/assets/bootstack.ico +0 -0
- bootstack/assets/bootstack.png +0 -0
- bootstack/assets/elements/__init__.py +0 -0
- bootstack/assets/elements/badge-pill.png +0 -0
- bootstack/assets/elements/badge-square.png +0 -0
- bootstack/assets/elements/border.png +0 -0
- bootstack/assets/elements/button-compact.png +0 -0
- bootstack/assets/elements/button-default.png +0 -0
- bootstack/assets/elements/button-group-horizontal-after-compact.png +0 -0
- bootstack/assets/elements/button-group-horizontal-after-default.png +0 -0
- bootstack/assets/elements/button-group-horizontal-before-compact.png +0 -0
- bootstack/assets/elements/button-group-horizontal-before-default.png +0 -0
- bootstack/assets/elements/button-group-horizontal-center-compact.png +0 -0
- bootstack/assets/elements/button-group-horizontal-center-default.png +0 -0
- bootstack/assets/elements/button-group-vertical-after-compact.png +0 -0
- bootstack/assets/elements/button-group-vertical-after-default.png +0 -0
- bootstack/assets/elements/button-group-vertical-before-compact.png +0 -0
- bootstack/assets/elements/button-group-vertical-before-default.png +0 -0
- bootstack/assets/elements/button-group-vertical-center-compact.png +0 -0
- bootstack/assets/elements/button-group-vertical-center-default.png +0 -0
- bootstack/assets/elements/checkbox-checked.png +0 -0
- bootstack/assets/elements/checkbox-indeterminate.png +0 -0
- bootstack/assets/elements/checkbox-unchecked.png +0 -0
- bootstack/assets/elements/field.png +0 -0
- bootstack/assets/elements/input-after-compact.png +0 -0
- bootstack/assets/elements/input-after-default.png +0 -0
- bootstack/assets/elements/input-before-compact.png +0 -0
- bootstack/assets/elements/input-before-default.png +0 -0
- bootstack/assets/elements/input-compact.png +0 -0
- bootstack/assets/elements/input-default.png +0 -0
- bootstack/assets/elements/list-item-separated.png +0 -0
- bootstack/assets/elements/list-item.png +0 -0
- bootstack/assets/elements/manifest.toml +480 -0
- bootstack/assets/elements/menu-item.png +0 -0
- bootstack/assets/elements/nav-button-compact.png +0 -0
- bootstack/assets/elements/nav-button-default.png +0 -0
- bootstack/assets/elements/nav-icon-button-compact.png +0 -0
- bootstack/assets/elements/nav-icon-button-default.png +0 -0
- bootstack/assets/elements/notebook-client-border.png +0 -0
- bootstack/assets/elements/notebook-tab-active.png +0 -0
- bootstack/assets/elements/notebook-tab-bar.png +0 -0
- bootstack/assets/elements/notebook-tab-normal.png +0 -0
- bootstack/assets/elements/notebook-tab-pill.png +0 -0
- bootstack/assets/elements/progress-bar-horizontal-striped.png +0 -0
- bootstack/assets/elements/progress-bar-solid.png +0 -0
- bootstack/assets/elements/progress-bar-thin.png +0 -0
- bootstack/assets/elements/progress-bar-vertical-striped.png +0 -0
- bootstack/assets/elements/radio-selected.png +0 -0
- bootstack/assets/elements/radio-unselected.png +0 -0
- bootstack/assets/elements/scrollbar-horizontal.png +0 -0
- bootstack/assets/elements/scrollbar-vertical.png +0 -0
- bootstack/assets/elements/slider-handle-focus.png +0 -0
- bootstack/assets/elements/slider-handle.png +0 -0
- bootstack/assets/elements/slider-track-horizontal.png +0 -0
- bootstack/assets/elements/slider-track-vertical.png +0 -0
- bootstack/assets/elements/switch-off.png +0 -0
- bootstack/assets/elements/switch-on.png +0 -0
- bootstack/assets/elements/tabs-bar-horizontal.png +0 -0
- bootstack/assets/elements/tabs-bar-vertical.png +0 -0
- bootstack/assets/elements/tabs-pill.png +0 -0
- bootstack/assets/locales/ar/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/ar/LC_MESSAGES/bootstack.po +853 -0
- bootstack/assets/locales/bg/LC_MESSAGES/bootstack.po +875 -0
- bootstack/assets/locales/cs/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/cs/LC_MESSAGES/bootstack.po +853 -0
- bootstack/assets/locales/da/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/da/LC_MESSAGES/bootstack.po +853 -0
- bootstack/assets/locales/de/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/de/LC_MESSAGES/bootstack.po +853 -0
- bootstack/assets/locales/en/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/en/LC_MESSAGES/bootstack.po +875 -0
- bootstack/assets/locales/es/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/es/LC_MESSAGES/bootstack.po +853 -0
- bootstack/assets/locales/fr/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/fr/LC_MESSAGES/bootstack.po +853 -0
- bootstack/assets/locales/he/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/he/LC_MESSAGES/bootstack.po +851 -0
- bootstack/assets/locales/hi/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/hi/LC_MESSAGES/bootstack.po +842 -0
- bootstack/assets/locales/it/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/it/LC_MESSAGES/bootstack.po +841 -0
- bootstack/assets/locales/ja/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/ja/LC_MESSAGES/bootstack.po +914 -0
- bootstack/assets/locales/ko/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/ko/LC_MESSAGES/bootstack.po +842 -0
- bootstack/assets/locales/nb/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/nb/LC_MESSAGES/bootstack.po +841 -0
- bootstack/assets/locales/nl/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/nl/LC_MESSAGES/bootstack.po +841 -0
- bootstack/assets/locales/pl/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/pl/LC_MESSAGES/bootstack.po +842 -0
- bootstack/assets/locales/pt/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/pt/LC_MESSAGES/bootstack.po +842 -0
- bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.po +842 -0
- bootstack/assets/locales/sl/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/sl/LC_MESSAGES/bootstack.po +842 -0
- bootstack/assets/locales/sv/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/sv/LC_MESSAGES/bootstack.po +842 -0
- bootstack/assets/locales/tr/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/tr/LC_MESSAGES/bootstack.po +842 -0
- bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.po +842 -0
- bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.po +842 -0
- bootstack/assets/themes/__init__.py +0 -0
- bootstack/assets/themes/amber-dark.json +32 -0
- bootstack/assets/themes/amber-light.json +32 -0
- bootstack/assets/themes/aurora-dark.json +32 -0
- bootstack/assets/themes/aurora-light.json +32 -0
- bootstack/assets/themes/bootstrap-dark.json +32 -0
- bootstack/assets/themes/bootstrap-light.json +32 -0
- bootstack/assets/themes/classic-dark.json +32 -0
- bootstack/assets/themes/classic-light.json +32 -0
- bootstack/assets/themes/docs-dark.json +32 -0
- bootstack/assets/themes/docs-light.json +32 -0
- bootstack/assets/themes/forest-dark.json +32 -0
- bootstack/assets/themes/forest-light.json +32 -0
- bootstack/assets/themes/ocean-dark.json +32 -0
- bootstack/assets/themes/ocean-light.json +32 -0
- bootstack/assets/themes/rose-dark.json +32 -0
- bootstack/assets/themes/rose-light.json +32 -0
- bootstack/assets/widgets/__init__.py +0 -0
- bootstack/assets/widgets/badge-default.png +0 -0
- bootstack/assets/widgets/badge-pill.png +0 -0
- bootstack/assets/widgets/border.png +0 -0
- bootstack/assets/widgets/button-group-horizontal-after.png +0 -0
- bootstack/assets/widgets/button-group-horizontal-before.png +0 -0
- bootstack/assets/widgets/button-group-horizontal-center.png +0 -0
- bootstack/assets/widgets/button-group-vertical-after.png +0 -0
- bootstack/assets/widgets/button-group-vertical-before.png +0 -0
- bootstack/assets/widgets/button-group-vertical-center.png +0 -0
- bootstack/assets/widgets/button.png +0 -0
- bootstack/assets/widgets/checkbox-checked.png +0 -0
- bootstack/assets/widgets/checkbox-indeterminate.png +0 -0
- bootstack/assets/widgets/checkbox-unchecked.png +0 -0
- bootstack/assets/widgets/field.png +0 -0
- bootstack/assets/widgets/icon-button.png +0 -0
- bootstack/assets/widgets/input-inner.png +0 -0
- bootstack/assets/widgets/input-prefix.png +0 -0
- bootstack/assets/widgets/input-suffix.png +0 -0
- bootstack/assets/widgets/input.png +0 -0
- bootstack/assets/widgets/list-item-focus.png +0 -0
- bootstack/assets/widgets/list-item-separated.png +0 -0
- bootstack/assets/widgets/menu-item-separated.png +0 -0
- bootstack/assets/widgets/notebook-client-border.png +0 -0
- bootstack/assets/widgets/notebook-pill-active.png +0 -0
- bootstack/assets/widgets/notebook-pill-inactive.png +0 -0
- bootstack/assets/widgets/notebook-tab-active.png +0 -0
- bootstack/assets/widgets/notebook-tab-border.png +0 -0
- bootstack/assets/widgets/notebook-tab-normal.png +0 -0
- bootstack/assets/widgets/notebook-underline.png +0 -0
- bootstack/assets/widgets/progress-bar-horizontal-default.png +0 -0
- bootstack/assets/widgets/progress-bar-horizontal-striped.png +0 -0
- bootstack/assets/widgets/progress-bar-vertical-default.png +0 -0
- bootstack/assets/widgets/progress-bar-vertical-striped.png +0 -0
- bootstack/assets/widgets/progress-trough-horizontal.png +0 -0
- bootstack/assets/widgets/progress-trough-vertical.png +0 -0
- bootstack/assets/widgets/radio-selected.png +0 -0
- bootstack/assets/widgets/radio-unselected.png +0 -0
- bootstack/assets/widgets/scrollbar-horizontal-rounded.png +0 -0
- bootstack/assets/widgets/scrollbar-vertical-rounded.png +0 -0
- bootstack/assets/widgets/separator-horizontal.png +0 -0
- bootstack/assets/widgets/separator-vertical.png +0 -0
- bootstack/assets/widgets/slider-handle-focus.png +0 -0
- bootstack/assets/widgets/slider-handle.png +0 -0
- bootstack/assets/widgets/slider-track-horizontal.png +0 -0
- bootstack/assets/widgets/slider-track-vertical.png +0 -0
- bootstack/assets/widgets/switch-off.png +0 -0
- bootstack/assets/widgets/switch-on.png +0 -0
- bootstack/assets/widgets/tabs-bar-horizontal.png +0 -0
- bootstack/assets/widgets/tabs-bar-vertical.png +0 -0
- bootstack/assets/widgets/tabs-pill.png +0 -0
- bootstack/cli/__init__.py +124 -0
- bootstack/cli/__main__.py +6 -0
- bootstack/cli/add.py +439 -0
- bootstack/cli/build.py +115 -0
- bootstack/cli/config.py +287 -0
- bootstack/cli/demo.py +1267 -0
- bootstack/cli/doctor.py +195 -0
- bootstack/cli/list_cmd.py +71 -0
- bootstack/cli/promote.py +120 -0
- bootstack/cli/pyinstaller.py +246 -0
- bootstack/cli/run.py +99 -0
- bootstack/cli/start.py +105 -0
- bootstack/cli/templates/__init__.py +861 -0
- bootstack/constants.py +325 -0
- bootstack/core/__init__.py +34 -0
- bootstack/core/capabilities/__init__.py +45 -0
- bootstack/core/capabilities/after.py +103 -0
- bootstack/core/capabilities/bind.py +154 -0
- bootstack/core/capabilities/bindtags.py +112 -0
- bootstack/core/capabilities/busy.py +61 -0
- bootstack/core/capabilities/clipboard.py +88 -0
- bootstack/core/capabilities/focus.py +118 -0
- bootstack/core/capabilities/grab.py +65 -0
- bootstack/core/capabilities/grid.py +188 -0
- bootstack/core/capabilities/localization.py +231 -0
- bootstack/core/capabilities/pack.py +119 -0
- bootstack/core/capabilities/place.py +92 -0
- bootstack/core/capabilities/selection.py +136 -0
- bootstack/core/capabilities/signals.py +242 -0
- bootstack/core/capabilities/winfo.py +315 -0
- bootstack/core/colorutils.py +234 -0
- bootstack/core/exceptions.py +95 -0
- bootstack/core/images.py +283 -0
- bootstack/core/localization/README.md +90 -0
- bootstack/core/localization/__init__.py +13 -0
- bootstack/core/localization/intl_format.py +580 -0
- bootstack/core/localization/msgcat.py +425 -0
- bootstack/core/localization/specs.py +143 -0
- bootstack/core/mixins/__init__.py +1 -0
- bootstack/core/mixins/ttk_state.py +35 -0
- bootstack/core/mixins/widget.py +132 -0
- bootstack/core/publisher.py +147 -0
- bootstack/core/signals/README.md +112 -0
- bootstack/core/signals/__init__.py +8 -0
- bootstack/core/signals/integration.py +100 -0
- bootstack/core/signals/signal.py +317 -0
- bootstack/core/signals/types.py +4 -0
- bootstack/core/validation/__init__.py +5 -0
- bootstack/core/validation/types.py +13 -0
- bootstack/core/validation/validation_result.py +17 -0
- bootstack/core/validation/validation_rules.py +112 -0
- bootstack/core/variables.py +62 -0
- bootstack/datasource/README.md +607 -0
- bootstack/datasource/__init__.py +51 -0
- bootstack/datasource/base.py +474 -0
- bootstack/datasource/file_source.py +541 -0
- bootstack/datasource/memory_source.py +482 -0
- bootstack/datasource/sqlite_source.py +453 -0
- bootstack/datasource/types.py +259 -0
- bootstack/dialogs/__init__.py +56 -0
- bootstack/dialogs/colorchooser.py +674 -0
- bootstack/dialogs/colordropper.py +257 -0
- bootstack/dialogs/datedialog.py +404 -0
- bootstack/dialogs/dialog.py +514 -0
- bootstack/dialogs/filterdialog.py +358 -0
- bootstack/dialogs/fontdialog.py +339 -0
- bootstack/dialogs/formdialog.py +541 -0
- bootstack/dialogs/message.py +489 -0
- bootstack/dialogs/query.py +561 -0
- bootstack/py.typed +1 -0
- bootstack/runtime/__init__.py +3 -0
- bootstack/runtime/app.py +879 -0
- bootstack/runtime/base_window.py +786 -0
- bootstack/runtime/events.py +399 -0
- bootstack/runtime/menu.py +510 -0
- bootstack/runtime/shortcuts.py +423 -0
- bootstack/runtime/tk_patch.py +31 -0
- bootstack/runtime/toplevel.py +131 -0
- bootstack/runtime/utility.py +371 -0
- bootstack/runtime/visual_focus.py +228 -0
- bootstack/runtime/window_utilities.py +1043 -0
- bootstack/style/__init__.py +5498 -0
- bootstack/style/bootstyle.py +507 -0
- bootstack/style/bootstyle_builder_base.py +752 -0
- bootstack/style/bootstyle_builder_mixed.py +93 -0
- bootstack/style/bootstyle_builder_tk.py +109 -0
- bootstack/style/bootstyle_builder_ttk.py +354 -0
- bootstack/style/builders/__init__.py +51 -0
- bootstack/style/builders/badge.py +44 -0
- bootstack/style/builders/button.py +453 -0
- bootstack/style/builders/buttongroup.py +344 -0
- bootstack/style/builders/calendar.py +271 -0
- bootstack/style/builders/checkbutton.py +95 -0
- bootstack/style/builders/combobox.py +112 -0
- bootstack/style/builders/contextmenu.py +268 -0
- bootstack/style/builders/entry.py +83 -0
- bootstack/style/builders/expander.py +171 -0
- bootstack/style/builders/field.py +312 -0
- bootstack/style/builders/frame.py +27 -0
- bootstack/style/builders/label.py +28 -0
- bootstack/style/builders/labelframe.py +41 -0
- bootstack/style/builders/listview.py +267 -0
- bootstack/style/builders/menubar.py +74 -0
- bootstack/style/builders/menubutton.py +408 -0
- bootstack/style/builders/notebook.py +316 -0
- bootstack/style/builders/panedwindow.py +25 -0
- bootstack/style/builders/progressbar.py +71 -0
- bootstack/style/builders/radiobutton.py +68 -0
- bootstack/style/builders/scale.py +66 -0
- bootstack/style/builders/scrollbar.py +360 -0
- bootstack/style/builders/separator.py +45 -0
- bootstack/style/builders/sidenav.py +313 -0
- bootstack/style/builders/sizegrip.py +15 -0
- bootstack/style/builders/spinbox.py +119 -0
- bootstack/style/builders/switch.py +67 -0
- bootstack/style/builders/tabitem.py +205 -0
- bootstack/style/builders/toolbutton.py +260 -0
- bootstack/style/builders/tooltip.py +26 -0
- bootstack/style/builders/treeview.py +269 -0
- bootstack/style/builders/utils.py +404 -0
- bootstack/style/builders_tk/__init__.py +16 -0
- bootstack/style/builders_tk/defaults.py +229 -0
- bootstack/style/element.py +173 -0
- bootstack/style/style.py +499 -0
- bootstack/style/theme_provider.py +449 -0
- bootstack/style/tk_patch.py +5 -0
- bootstack/style/token_maps.py +42 -0
- bootstack/style/types.py +32 -0
- bootstack/style/typography.py +527 -0
- bootstack/style/utility.py +696 -0
- bootstack/themes/__init__.py +12 -0
- bootstack/themes/standard.py +415 -0
- bootstack/themes/user.py +45 -0
- bootstack/widgets/__init__.py +53 -0
- bootstack/widgets/composites/__init__.py +38 -0
- bootstack/widgets/composites/accordion.py +385 -0
- bootstack/widgets/composites/appshell.py +445 -0
- bootstack/widgets/composites/buttongroup.py +391 -0
- bootstack/widgets/composites/calendar.py +914 -0
- bootstack/widgets/composites/compositeframe.py +282 -0
- bootstack/widgets/composites/contextmenu.py +1754 -0
- bootstack/widgets/composites/dateentry.py +261 -0
- bootstack/widgets/composites/dropdownbutton.py +190 -0
- bootstack/widgets/composites/expander.py +508 -0
- bootstack/widgets/composites/field.py +448 -0
- bootstack/widgets/composites/floodgauge.py +434 -0
- bootstack/widgets/composites/form.py +983 -0
- bootstack/widgets/composites/labeledscale.py +209 -0
- bootstack/widgets/composites/list/__init__.py +15 -0
- bootstack/widgets/composites/list/listitem.py +733 -0
- bootstack/widgets/composites/list/listview.py +1507 -0
- bootstack/widgets/composites/menubar.py +303 -0
- bootstack/widgets/composites/meter.py +882 -0
- bootstack/widgets/composites/numericentry.py +183 -0
- bootstack/widgets/composites/pagestack.py +330 -0
- bootstack/widgets/composites/passwordentry.py +149 -0
- bootstack/widgets/composites/pathentry.py +223 -0
- bootstack/widgets/composites/radiogroup.py +466 -0
- bootstack/widgets/composites/scrolledtext.py +388 -0
- bootstack/widgets/composites/scrolledtext.pyi +186 -0
- bootstack/widgets/composites/scrollview.py +675 -0
- bootstack/widgets/composites/selectbox.py +544 -0
- bootstack/widgets/composites/sidenav/__init__.py +24 -0
- bootstack/widgets/composites/sidenav/group.py +485 -0
- bootstack/widgets/composites/sidenav/header.py +83 -0
- bootstack/widgets/composites/sidenav/item.py +413 -0
- bootstack/widgets/composites/sidenav/separator.py +51 -0
- bootstack/widgets/composites/sidenav/view.py +919 -0
- bootstack/widgets/composites/spinnerentry.py +232 -0
- bootstack/widgets/composites/tableview/__init__.py +5 -0
- bootstack/widgets/composites/tableview/tableview.py +2254 -0
- bootstack/widgets/composites/tableview/types.py +169 -0
- bootstack/widgets/composites/tabs/__init__.py +6 -0
- bootstack/widgets/composites/tabs/tabitem.py +372 -0
- bootstack/widgets/composites/tabs/tabs.py +478 -0
- bootstack/widgets/composites/tabs/tabview.py +352 -0
- bootstack/widgets/composites/textentry.py +90 -0
- bootstack/widgets/composites/timeentry.py +189 -0
- bootstack/widgets/composites/toast.py +364 -0
- bootstack/widgets/composites/togglegroup.py +382 -0
- bootstack/widgets/composites/toolbar.py +393 -0
- bootstack/widgets/composites/tooltip.py +404 -0
- bootstack/widgets/internal/__init__.py +0 -0
- bootstack/widgets/internal/wrapper_base.py +304 -0
- bootstack/widgets/mixins/__init__.py +25 -0
- bootstack/widgets/mixins/configure_mixin.py +186 -0
- bootstack/widgets/mixins/entry_mixin.py +70 -0
- bootstack/widgets/mixins/font_mixin.py +346 -0
- bootstack/widgets/mixins/icon_mixin.py +38 -0
- bootstack/widgets/mixins/localization_mixin.py +255 -0
- bootstack/widgets/mixins/signal_mixin.py +272 -0
- bootstack/widgets/mixins/validation_mixin.py +204 -0
- bootstack/widgets/parts/__init__.py +11 -0
- bootstack/widgets/parts/numberentry_part.py +345 -0
- bootstack/widgets/parts/spinnerentry_part.py +394 -0
- bootstack/widgets/parts/textentry_part.py +344 -0
- bootstack/widgets/primitives/__init__.py +55 -0
- bootstack/widgets/primitives/badge.py +44 -0
- bootstack/widgets/primitives/button.py +89 -0
- bootstack/widgets/primitives/card.py +66 -0
- bootstack/widgets/primitives/checkbutton.py +124 -0
- bootstack/widgets/primitives/checktoggle.py +53 -0
- bootstack/widgets/primitives/combobox.py +165 -0
- bootstack/widgets/primitives/entry.py +98 -0
- bootstack/widgets/primitives/frame.py +206 -0
- bootstack/widgets/primitives/gridframe.py +479 -0
- bootstack/widgets/primitives/label.py +95 -0
- bootstack/widgets/primitives/labelframe.py +63 -0
- bootstack/widgets/primitives/menubutton.py +118 -0
- bootstack/widgets/primitives/notebook.py +551 -0
- bootstack/widgets/primitives/optionmenu.py +248 -0
- bootstack/widgets/primitives/packframe.py +228 -0
- bootstack/widgets/primitives/panedwindow.py +58 -0
- bootstack/widgets/primitives/progressbar.py +95 -0
- bootstack/widgets/primitives/radiobutton.py +115 -0
- bootstack/widgets/primitives/radiotoggle.py +50 -0
- bootstack/widgets/primitives/scale.py +85 -0
- bootstack/widgets/primitives/scrollbar.py +56 -0
- bootstack/widgets/primitives/separator.py +56 -0
- bootstack/widgets/primitives/sizegrip.py +47 -0
- bootstack/widgets/primitives/spinbox.py +91 -0
- bootstack/widgets/primitives/switch.py +41 -0
- bootstack/widgets/primitives/treeview.py +77 -0
- bootstack/widgets/types.py +20 -0
- bootstack-0.1.0a1.dist-info/METADATA +196 -0
- bootstack-0.1.0a1.dist-info/RECORD +419 -0
- bootstack-0.1.0a1.dist-info/WHEEL +5 -0
- bootstack-0.1.0a1.dist-info/entry_points.txt +2 -0
- bootstack-0.1.0a1.dist-info/licenses/LICENSE +22 -0
- bootstack-0.1.0a1.dist-info/licenses/NOTICE +10 -0
- bootstack-0.1.0a1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
"""Enhanced event system for bootstack.
|
|
2
|
+
|
|
3
|
+
This module patches the standard tkinter event system to enable passing custom
|
|
4
|
+
data with virtual events. This provides a more powerful and flexible event
|
|
5
|
+
handling mechanism than the default tkinter implementation.
|
|
6
|
+
|
|
7
|
+
Features:
|
|
8
|
+
- Pass custom Python objects as data with virtual events
|
|
9
|
+
- Automatic memory management with LRU cache to prevent leaks
|
|
10
|
+
- Consistent Event objects for both regular and virtual events
|
|
11
|
+
- All standard event attributes preserved (x, y, widget, etc.)
|
|
12
|
+
- Backwards compatible with existing tkinter code
|
|
13
|
+
|
|
14
|
+
Examples:
|
|
15
|
+
```python
|
|
16
|
+
import tkinter as tk
|
|
17
|
+
import bootstack as bs
|
|
18
|
+
|
|
19
|
+
root = bs.Window()
|
|
20
|
+
|
|
21
|
+
def handler(event):
|
|
22
|
+
print(f"Received: {event.data}")
|
|
23
|
+
|
|
24
|
+
root.bind('<<CustomEvent>>', handler)
|
|
25
|
+
root.event_generate('<<CustomEvent>>', data={'key': 'value', 'items': [1, 2, 3]})
|
|
26
|
+
|
|
27
|
+
root.mainloop()
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Note:
|
|
31
|
+
This module automatically patches tkinter when imported. The patches are
|
|
32
|
+
applied globally and affect all tkinter widgets in the application.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
import tkinter as tk
|
|
36
|
+
import uuid
|
|
37
|
+
import weakref
|
|
38
|
+
from collections import OrderedDict
|
|
39
|
+
from typing import Any, Callable, Optional, Union
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# Global storage for event data with LRU cache behavior
|
|
43
|
+
_event_data_cache: OrderedDict[str, Any] = OrderedDict()
|
|
44
|
+
_MAX_CACHE_SIZE = 100 # Prevent unbounded growth
|
|
45
|
+
|
|
46
|
+
# Store original tkinter methods before patching
|
|
47
|
+
_original_event_generate: Callable = tk.Misc.event_generate
|
|
48
|
+
_original_bind: Callable = tk.Misc.bind
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _patched_event_generate(
|
|
52
|
+
self: tk.Misc,
|
|
53
|
+
sequence: str,
|
|
54
|
+
data: Optional[Any] = None,
|
|
55
|
+
**kw
|
|
56
|
+
) -> None:
|
|
57
|
+
"""Enhanced event_generate that supports custom data parameter.
|
|
58
|
+
|
|
59
|
+
This patched version of tkinter's event_generate method allows passing
|
|
60
|
+
arbitrary Python objects as event data. The data is stored in a cache
|
|
61
|
+
with a unique identifier that is passed through the event system.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
self: The widget instance (automatically provided)
|
|
65
|
+
sequence: Virtual event name (e.g., '<<MyEvent>>')
|
|
66
|
+
data: Optional custom data to attach to the event. Can be any Python object.
|
|
67
|
+
**kw: Additional keyword arguments passed to the original event_generate
|
|
68
|
+
|
|
69
|
+
Examples:
|
|
70
|
+
```python
|
|
71
|
+
widget.event_generate('<<Save>>', data={'filename': 'doc.txt', 'author': 'John'})
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Note:
|
|
75
|
+
The cache uses LRU eviction to prevent memory leaks. Old entries are
|
|
76
|
+
automatically removed when the cache exceeds _MAX_CACHE_SIZE.
|
|
77
|
+
"""
|
|
78
|
+
if data is not None:
|
|
79
|
+
# Generate unique identifier for this data
|
|
80
|
+
guid = str(uuid.uuid4())
|
|
81
|
+
_event_data_cache[guid] = data
|
|
82
|
+
|
|
83
|
+
# Limit cache size using LRU eviction
|
|
84
|
+
if len(_event_data_cache) > _MAX_CACHE_SIZE:
|
|
85
|
+
# Remove oldest entry (FIFO from OrderedDict)
|
|
86
|
+
_event_data_cache.popitem(last=False)
|
|
87
|
+
|
|
88
|
+
# Pass GUID through tkinter's event system
|
|
89
|
+
kw['data'] = guid
|
|
90
|
+
|
|
91
|
+
return _original_event_generate(self, sequence, **kw)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _patched_bind(
|
|
95
|
+
self: tk.Misc,
|
|
96
|
+
sequence: Optional[str] = None,
|
|
97
|
+
func: Optional[Callable] = None,
|
|
98
|
+
add: Optional[Union[bool, str]] = None
|
|
99
|
+
) -> Optional[str]:
|
|
100
|
+
"""Enhanced bind that supports data attribute on all events.
|
|
101
|
+
|
|
102
|
+
This patched version of tkinter's bind method ensures that:
|
|
103
|
+
1. Virtual events (<<EventName>>) receive custom data if provided
|
|
104
|
+
2. All event objects have a 'data' attribute (None for regular events)
|
|
105
|
+
3. Virtual events get properly formatted Event objects with __str__
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
self: The widget instance (automatically provided)
|
|
109
|
+
sequence: Event sequence (e.g., '<Button-1>', '<<MyEvent>>')
|
|
110
|
+
func: Callback function to handle the event
|
|
111
|
+
add: If True/'+', add binding without removing existing ones
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
Tkinter function name string if binding was created, None otherwise
|
|
115
|
+
|
|
116
|
+
Examples:
|
|
117
|
+
```python
|
|
118
|
+
def handler(event):
|
|
119
|
+
print(f"Event: {event}, Data: {event.data}")
|
|
120
|
+
|
|
121
|
+
widget.bind('<<CustomEvent>>', handler)
|
|
122
|
+
```
|
|
123
|
+
"""
|
|
124
|
+
if func is not None and sequence is not None:
|
|
125
|
+
is_virtual = sequence and sequence.startswith('<<')
|
|
126
|
+
|
|
127
|
+
if is_virtual:
|
|
128
|
+
# Create wrapper for virtual events to handle data retrieval
|
|
129
|
+
widget_ref = weakref.ref(self) # Avoid circular references
|
|
130
|
+
|
|
131
|
+
def wrapper(
|
|
132
|
+
data_guid, serial, num, height, width, keycode, state, time,
|
|
133
|
+
x, y, x_root, y_root, char, keysym, keysym_num, event_type,
|
|
134
|
+
send_event, delta
|
|
135
|
+
):
|
|
136
|
+
"""Internal wrapper that constructs Event objects for virtual events.
|
|
137
|
+
|
|
138
|
+
This function is called by tkinter's event system with all the
|
|
139
|
+
standard event substitution values plus our custom data GUID.
|
|
140
|
+
"""
|
|
141
|
+
|
|
142
|
+
class VirtualEvent:
|
|
143
|
+
"""Event object for virtual events with enhanced functionality.
|
|
144
|
+
|
|
145
|
+
This class mimics tkinter's Event class but adds:
|
|
146
|
+
- Custom data attribute from event_generate
|
|
147
|
+
- Proper __str__ representation showing event details
|
|
148
|
+
- All standard tkinter event attributes
|
|
149
|
+
"""
|
|
150
|
+
|
|
151
|
+
def __init__(self, widget: tk.Misc) -> None:
|
|
152
|
+
"""Initialize event with standard tkinter attributes.
|
|
153
|
+
|
|
154
|
+
Args:
|
|
155
|
+
widget: The widget that received the event
|
|
156
|
+
"""
|
|
157
|
+
self.serial = serial
|
|
158
|
+
self.num = num
|
|
159
|
+
self.height = height
|
|
160
|
+
self.width = width
|
|
161
|
+
self.keycode = keycode
|
|
162
|
+
self.state = state
|
|
163
|
+
self.time = time
|
|
164
|
+
self.x = x
|
|
165
|
+
self.y = y
|
|
166
|
+
self.x_root = x_root
|
|
167
|
+
self.y_root = y_root
|
|
168
|
+
self.char = char
|
|
169
|
+
self.keysym = keysym
|
|
170
|
+
self.keysym_num = keysym_num
|
|
171
|
+
self.type = event_type
|
|
172
|
+
self.send_event = send_event
|
|
173
|
+
self.delta = delta
|
|
174
|
+
self.widget = widget
|
|
175
|
+
self.data: Optional[Any] = None
|
|
176
|
+
|
|
177
|
+
def __str__(self) -> str:
|
|
178
|
+
"""Return human-readable event representation.
|
|
179
|
+
|
|
180
|
+
Returns:
|
|
181
|
+
Formatted string like: <VirtualEvent type=MyEvent x=10 y=20 data={'key': 'value'}>
|
|
182
|
+
"""
|
|
183
|
+
# Extract event name from sequence (remove << and >>)
|
|
184
|
+
event_name = sequence.strip('<').strip('>')
|
|
185
|
+
parts = [f"type={event_name}"]
|
|
186
|
+
|
|
187
|
+
# Add position if available
|
|
188
|
+
if self.x is not None and self.x != '??':
|
|
189
|
+
parts.append(f"x={self.x}")
|
|
190
|
+
if self.y is not None and self.y != '??':
|
|
191
|
+
parts.append(f"y={self.y}")
|
|
192
|
+
|
|
193
|
+
# Add data if present (truncate if too long)
|
|
194
|
+
if self.data is not None:
|
|
195
|
+
data_repr = repr(self.data)
|
|
196
|
+
max_length = 50
|
|
197
|
+
if len(data_repr) > max_length:
|
|
198
|
+
parts.append(f"data={data_repr[:max_length]}...")
|
|
199
|
+
else:
|
|
200
|
+
parts.append(f"data={data_repr}")
|
|
201
|
+
|
|
202
|
+
return f"<VirtualEvent {' '.join(parts)}>"
|
|
203
|
+
|
|
204
|
+
def __repr__(self) -> str:
|
|
205
|
+
"""Return repr string (same as __str__)."""
|
|
206
|
+
return self.__str__()
|
|
207
|
+
|
|
208
|
+
# Retrieve widget from weakref
|
|
209
|
+
widget = widget_ref()
|
|
210
|
+
if widget is None:
|
|
211
|
+
# Widget was destroyed, clean up cache entry if present
|
|
212
|
+
if data_guid and data_guid in _event_data_cache:
|
|
213
|
+
_event_data_cache.pop(data_guid)
|
|
214
|
+
return
|
|
215
|
+
|
|
216
|
+
# Create event object
|
|
217
|
+
event = VirtualEvent(widget)
|
|
218
|
+
|
|
219
|
+
# Attach custom data (don't pop yet - multiple handlers may need it)
|
|
220
|
+
if data_guid and data_guid in _event_data_cache:
|
|
221
|
+
event.data = _event_data_cache[data_guid]
|
|
222
|
+
# Schedule cleanup after all handlers have run
|
|
223
|
+
widget.after_idle(lambda: _event_data_cache.pop(data_guid, None))
|
|
224
|
+
else:
|
|
225
|
+
# Data might have been evicted from cache already
|
|
226
|
+
event.data = None
|
|
227
|
+
|
|
228
|
+
return func(event)
|
|
229
|
+
|
|
230
|
+
# Register wrapper function with tkinter
|
|
231
|
+
name = self._register(wrapper)
|
|
232
|
+
|
|
233
|
+
# Build command with all substitutions including %d for data GUID
|
|
234
|
+
# Substitution codes: https://tcl.tk/man/tcl8.6/TkCmd/bind.htm
|
|
235
|
+
cmd = f'{name} %d %# %b %h %w %k %s %t %x %y %X %Y %A %K %N %T %E %D'
|
|
236
|
+
|
|
237
|
+
# Bind to widget
|
|
238
|
+
self.tk.call('bind', self._w, sequence, cmd if not add else '+' + cmd)
|
|
239
|
+
|
|
240
|
+
return name
|
|
241
|
+
else:
|
|
242
|
+
# For regular events, wrap to add data=None attribute
|
|
243
|
+
def regular_wrapper(event):
|
|
244
|
+
"""Wrapper for regular events to add consistent data attribute."""
|
|
245
|
+
if not hasattr(event, 'data'):
|
|
246
|
+
event.data = None
|
|
247
|
+
return func(event)
|
|
248
|
+
|
|
249
|
+
return _original_bind(self, sequence, regular_wrapper, add)
|
|
250
|
+
|
|
251
|
+
# No function or sequence provided, pass through to original
|
|
252
|
+
return _original_bind(self, sequence, func, add)
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def cleanup_event_cache() -> None:
|
|
256
|
+
"""Manually clear the entire event data cache.
|
|
257
|
+
|
|
258
|
+
This function removes all cached event data. It's useful for:
|
|
259
|
+
- Forcing memory cleanup in long-running applications
|
|
260
|
+
- Resetting state during testing
|
|
261
|
+
- Manual intervention when cache grows unexpectedly
|
|
262
|
+
|
|
263
|
+
Note:
|
|
264
|
+
Normally cache cleanup is automatic via LRU eviction. Manual cleanup
|
|
265
|
+
should rarely be needed in production code.
|
|
266
|
+
|
|
267
|
+
Examples:
|
|
268
|
+
```python
|
|
269
|
+
from bootstack.events import cleanup_event_cache
|
|
270
|
+
|
|
271
|
+
# After processing many events
|
|
272
|
+
cleanup_event_cache()
|
|
273
|
+
```
|
|
274
|
+
"""
|
|
275
|
+
_event_data_cache.clear()
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
def enable_periodic_cache_cleanup(
|
|
279
|
+
root: tk.Misc,
|
|
280
|
+
interval: int = 60000,
|
|
281
|
+
threshold: int = 10
|
|
282
|
+
) -> None:
|
|
283
|
+
"""Enable automatic periodic cleanup of the event cache.
|
|
284
|
+
|
|
285
|
+
This function sets up a recurring timer that checks the cache size
|
|
286
|
+
and performs cleanup when it exceeds a threshold. This helps prevent
|
|
287
|
+
cache growth in long-running applications that generate many events.
|
|
288
|
+
|
|
289
|
+
Args:
|
|
290
|
+
root: Root window or any widget (needed for .after() scheduling)
|
|
291
|
+
interval: Cleanup check interval in milliseconds (default: 60000 = 1 minute)
|
|
292
|
+
threshold: Only clean if cache has more than this many entries (default: 10)
|
|
293
|
+
|
|
294
|
+
Examples:
|
|
295
|
+
```python
|
|
296
|
+
import bootstack as bs
|
|
297
|
+
from bootstack.events import enable_periodic_cache_cleanup
|
|
298
|
+
|
|
299
|
+
root = bs.Window()
|
|
300
|
+
enable_periodic_cache_cleanup(root, interval=30000) # Check every 30 seconds
|
|
301
|
+
root.mainloop()
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
Note:
|
|
305
|
+
This is optional. The LRU cache already prevents unbounded growth.
|
|
306
|
+
Periodic cleanup is only needed for applications that generate
|
|
307
|
+
thousands of events and want more aggressive memory management.
|
|
308
|
+
"""
|
|
309
|
+
def cleanup_task():
|
|
310
|
+
"""Internal task that performs conditional cache cleanup."""
|
|
311
|
+
if len(_event_data_cache) > threshold:
|
|
312
|
+
# Remove half of the oldest entries
|
|
313
|
+
to_remove = list(_event_data_cache.keys())[:len(_event_data_cache) // 2]
|
|
314
|
+
for key in to_remove:
|
|
315
|
+
_event_data_cache.pop(key, None)
|
|
316
|
+
|
|
317
|
+
# Schedule next cleanup
|
|
318
|
+
root.after(interval, cleanup_task)
|
|
319
|
+
|
|
320
|
+
# Start the cleanup cycle
|
|
321
|
+
cleanup_task()
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
def get_cache_size() -> int:
|
|
325
|
+
"""Get the current number of entries in the event data cache.
|
|
326
|
+
|
|
327
|
+
This is primarily useful for debugging and monitoring cache behavior.
|
|
328
|
+
|
|
329
|
+
Returns:
|
|
330
|
+
Number of cached event data objects
|
|
331
|
+
|
|
332
|
+
Examples:
|
|
333
|
+
```python
|
|
334
|
+
from bootstack.events import get_cache_size
|
|
335
|
+
|
|
336
|
+
print(f"Current cache size: {get_cache_size()}")
|
|
337
|
+
```
|
|
338
|
+
"""
|
|
339
|
+
return len(_event_data_cache)
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
def install_enhanced_events() -> None:
|
|
343
|
+
"""Install the enhanced event system by patching tkinter methods.
|
|
344
|
+
|
|
345
|
+
This function applies monkey patches to tkinter's Misc class,
|
|
346
|
+
replacing event_generate and bind with enhanced versions that
|
|
347
|
+
support passing custom data through virtual events.
|
|
348
|
+
|
|
349
|
+
The patches are applied globally and affect all tkinter widgets
|
|
350
|
+
in the application. This function is called automatically when
|
|
351
|
+
bootstack is imported.
|
|
352
|
+
|
|
353
|
+
Note:
|
|
354
|
+
You should not need to call this manually unless you've explicitly
|
|
355
|
+
uninstalled the patches and need to reinstall them.
|
|
356
|
+
|
|
357
|
+
Examples:
|
|
358
|
+
```python
|
|
359
|
+
from bootstack.events import install_enhanced_events
|
|
360
|
+
|
|
361
|
+
# Reinstall if needed
|
|
362
|
+
install_enhanced_events()
|
|
363
|
+
```
|
|
364
|
+
"""
|
|
365
|
+
tk.Misc.event_generate = _patched_event_generate
|
|
366
|
+
tk.Misc.bind = _patched_bind
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
def uninstall_enhanced_events() -> None:
|
|
370
|
+
"""Restore original tkinter event methods.
|
|
371
|
+
|
|
372
|
+
This function removes the patches and restores tkinter to its
|
|
373
|
+
original behavior. Useful for testing or if conflicts arise.
|
|
374
|
+
|
|
375
|
+
Warning:
|
|
376
|
+
After calling this, event_generate will no longer accept
|
|
377
|
+
the 'data' parameter, and existing bindings may not work
|
|
378
|
+
as expected.
|
|
379
|
+
|
|
380
|
+
Examples:
|
|
381
|
+
```python
|
|
382
|
+
from bootstack.events import uninstall_enhanced_events
|
|
383
|
+
|
|
384
|
+
# Restore original tkinter behavior
|
|
385
|
+
uninstall_enhanced_events()
|
|
386
|
+
```
|
|
387
|
+
"""
|
|
388
|
+
tk.Misc.event_generate = _original_event_generate
|
|
389
|
+
tk.Misc.bind = _original_bind
|
|
390
|
+
cleanup_event_cache()
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
__all__ = [
|
|
394
|
+
'cleanup_event_cache',
|
|
395
|
+
'enable_periodic_cache_cleanup',
|
|
396
|
+
'get_cache_size',
|
|
397
|
+
'install_enhanced_events',
|
|
398
|
+
'uninstall_enhanced_events',
|
|
399
|
+
]
|