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,382 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from tkinter import StringVar
|
|
4
|
+
from typing import Any, Callable, Literal, TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
from typing_extensions import TypedDict, Unpack
|
|
7
|
+
|
|
8
|
+
from bootstack.widgets.primitives.radiotoggle import RadioToggle
|
|
9
|
+
from bootstack.widgets.primitives.checktoggle import CheckToggle
|
|
10
|
+
from bootstack.core.variables import SetVar
|
|
11
|
+
from bootstack.widgets.mixins.configure_mixin import configure_delegate
|
|
12
|
+
from bootstack.widgets.primitives import Frame
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from bootstack.core.signals import Signal
|
|
16
|
+
import tkinter as tk
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class ToggleGroupKwargs(TypedDict, total=False):
|
|
20
|
+
mode: Literal['single', 'multi']
|
|
21
|
+
variable: Any
|
|
22
|
+
signal: Signal[Any]
|
|
23
|
+
value: str | set[str]
|
|
24
|
+
orient: Literal['horizontal', 'vertical']
|
|
25
|
+
accent: str
|
|
26
|
+
variant: Literal['outline', 'ghost'] | None
|
|
27
|
+
show_border: bool
|
|
28
|
+
surface: str
|
|
29
|
+
style_options: dict[str, Any]
|
|
30
|
+
# Frame options
|
|
31
|
+
padding: Any
|
|
32
|
+
width: int
|
|
33
|
+
height: int
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class ToggleGroup(Frame):
|
|
37
|
+
"""A group of toggle buttons with single or multi-selection support.
|
|
38
|
+
|
|
39
|
+
The ToggleGroup widget provides a convenient way to create groups of toggle
|
|
40
|
+
buttons with automatic position tracking and styling. It supports both single
|
|
41
|
+
selection (radio button behavior) and multi-selection (checkbox behavior).
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
def __init__(self, master: Any = None, **kwargs: Unpack[ToggleGroupKwargs]):
|
|
45
|
+
"""Initialize the ToggleGroup.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
master: Parent widget. If None, uses the default root window.
|
|
49
|
+
|
|
50
|
+
Other Parameters:
|
|
51
|
+
mode (str): Selection mode - 'single' for radio button behavior (default),
|
|
52
|
+
or 'multi' for checkbox behavior allowing multiple selections.
|
|
53
|
+
orient (str): Layout orientation - 'horizontal' (default) or 'vertical'.
|
|
54
|
+
accent (str): Accent token for styling (e.g., 'primary', 'danger').
|
|
55
|
+
Defaults to 'primary'.
|
|
56
|
+
variant (str): Style variant (e.g., 'outline', 'ghost').
|
|
57
|
+
bootstyle (str): DEPRECATED - Use `accent` and `variant` instead.
|
|
58
|
+
variable (Variable): Optional tk.Variable for controlling the value. For single mode,
|
|
59
|
+
use StringVar; for multi mode, use SetVar.
|
|
60
|
+
signal (Signal): Optional Signal instance for reactive programming.
|
|
61
|
+
value (str | set): Initial value - string for single mode, set for multi mode.
|
|
62
|
+
show_border (bool): If True, draws a border around the group.
|
|
63
|
+
surface (str): Optional surface token; otherwise inherited.
|
|
64
|
+
style_options (dict): Additional style options passed to child buttons.
|
|
65
|
+
padding (int | tuple): Frame padding. Defaults to 1.
|
|
66
|
+
width (int): Requested width in pixels.
|
|
67
|
+
height (int): Requested height in pixels.
|
|
68
|
+
"""
|
|
69
|
+
# Extract ToggleGroup-specific options before super().__init__
|
|
70
|
+
self._mode = kwargs.pop('mode', 'single')
|
|
71
|
+
self._orientation = kwargs.pop('orient', 'horizontal')
|
|
72
|
+
accent = kwargs.pop('accent', None) or 'primary'
|
|
73
|
+
variant = kwargs.pop('variant', None) # None (default), 'outline', or 'ghost'
|
|
74
|
+
|
|
75
|
+
# Handle signal/variable/value similar to CheckToggle pattern
|
|
76
|
+
initial_value = kwargs.pop('value', None)
|
|
77
|
+
|
|
78
|
+
style_options = kwargs.pop('style_options', {})
|
|
79
|
+
|
|
80
|
+
# Initialize internal state
|
|
81
|
+
self._buttons: dict[str, RadioToggle | CheckToggle] = {}
|
|
82
|
+
|
|
83
|
+
# Extract signal/variable before Frame init
|
|
84
|
+
signal_value = kwargs.pop('signal', None)
|
|
85
|
+
variable_value = kwargs.pop('variable', None)
|
|
86
|
+
|
|
87
|
+
# Call super().__init__() - just Frame now
|
|
88
|
+
super().__init__(master, style_options=style_options, padding=1, **kwargs)
|
|
89
|
+
|
|
90
|
+
# Restore accent/variant (super().__init__ overwrites them with None)
|
|
91
|
+
self._accent = accent
|
|
92
|
+
self._variant = variant
|
|
93
|
+
|
|
94
|
+
# Handle variable/signal setup manually
|
|
95
|
+
if signal_value is not None:
|
|
96
|
+
# Signal provided - extract its variable
|
|
97
|
+
self._signal = signal_value
|
|
98
|
+
self._variable = signal_value.var
|
|
99
|
+
elif variable_value is not None:
|
|
100
|
+
# Variable provided - wrap in Signal
|
|
101
|
+
from bootstack.core.signals import Signal
|
|
102
|
+
self._variable = variable_value
|
|
103
|
+
self._signal = Signal.from_variable(variable_value)
|
|
104
|
+
# Set initial value if provided
|
|
105
|
+
if initial_value is not None:
|
|
106
|
+
self._variable.set(initial_value)
|
|
107
|
+
else:
|
|
108
|
+
# Neither provided - create internal variable
|
|
109
|
+
from bootstack.core.signals import Signal
|
|
110
|
+
if self._mode == 'single':
|
|
111
|
+
internal_var = StringVar(value=initial_value or '')
|
|
112
|
+
else:
|
|
113
|
+
internal_var = SetVar(value=initial_value or set())
|
|
114
|
+
self._variable = internal_var
|
|
115
|
+
self._signal = Signal.from_variable(internal_var)
|
|
116
|
+
|
|
117
|
+
@property
|
|
118
|
+
def variable(self) -> 'tk.Variable':
|
|
119
|
+
"""Get the underlying tk.Variable."""
|
|
120
|
+
return self._variable
|
|
121
|
+
|
|
122
|
+
@variable.setter
|
|
123
|
+
def variable(self, value: 'tk.Variable') -> None:
|
|
124
|
+
"""Set the variable."""
|
|
125
|
+
from bootstack.core.signals import Signal
|
|
126
|
+
self._variable = value
|
|
127
|
+
self._signal = Signal.from_variable(value)
|
|
128
|
+
|
|
129
|
+
@property
|
|
130
|
+
def signal(self) -> 'Signal[Any]':
|
|
131
|
+
"""Get the signal."""
|
|
132
|
+
return self._signal
|
|
133
|
+
|
|
134
|
+
@signal.setter
|
|
135
|
+
def signal(self, value: 'Signal[Any]') -> None:
|
|
136
|
+
"""Set the signal."""
|
|
137
|
+
self._signal = value
|
|
138
|
+
self._variable = value.var
|
|
139
|
+
|
|
140
|
+
def add(self, text: str = None, value: Any = None, key: str | None = None, **kwargs: Any) -> RadioToggle | CheckToggle:
|
|
141
|
+
"""Add a toggle button to the group.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
text: Text to display on the button.
|
|
145
|
+
value: Value this button represents (required).
|
|
146
|
+
key: Unique identifier. Defaults to value.
|
|
147
|
+
**kwargs: Additional arguments passed to RadioToggle or CheckToggle.
|
|
148
|
+
|
|
149
|
+
Returns:
|
|
150
|
+
The created button widget.
|
|
151
|
+
"""
|
|
152
|
+
if value is None:
|
|
153
|
+
raise ValueError("The 'value' argument is required.")
|
|
154
|
+
|
|
155
|
+
key = key or value
|
|
156
|
+
if key in self._buttons:
|
|
157
|
+
raise ValueError(f"A button with the key '{key}' already exists.")
|
|
158
|
+
|
|
159
|
+
btn_kwargs = kwargs.copy()
|
|
160
|
+
# Set the ButtonGroup ttk_class - position will be updated by _update_button_positions
|
|
161
|
+
custom_accent = btn_kwargs.pop('accent', None) or self._accent
|
|
162
|
+
btn_kwargs['accent'] = custom_accent
|
|
163
|
+
btn_kwargs['ttk_class'] = 'ButtonGroup'
|
|
164
|
+
# variant can be None (default), 'outline', or 'ghost' - use group's variant if not specified
|
|
165
|
+
if 'variant' not in btn_kwargs:
|
|
166
|
+
btn_kwargs['variant'] = self._variant
|
|
167
|
+
# Merge orient and initial position into style_options
|
|
168
|
+
existing_style_opts = btn_kwargs.get('style_options', {}).copy()
|
|
169
|
+
existing_style_opts['orient'] = self._orientation
|
|
170
|
+
existing_style_opts.setdefault('position', 'before') # Default position, will be corrected later
|
|
171
|
+
btn_kwargs['style_options'] = existing_style_opts
|
|
172
|
+
|
|
173
|
+
if self._mode == 'single':
|
|
174
|
+
button = RadioToggle(self, text=text, value=value, variable=self.variable, **btn_kwargs)
|
|
175
|
+
else: # multi
|
|
176
|
+
button = CheckToggle(self, text=text, **btn_kwargs)
|
|
177
|
+
|
|
178
|
+
# Set initial state based on current SetVar value
|
|
179
|
+
current_set = self.variable.get()
|
|
180
|
+
if not isinstance(current_set, set):
|
|
181
|
+
current_set = set()
|
|
182
|
+
button.variable.set(value in current_set)
|
|
183
|
+
|
|
184
|
+
# Bind command to update SetVar
|
|
185
|
+
# Pop command to avoid double-calling
|
|
186
|
+
original_command = btn_kwargs.pop('command', None)
|
|
187
|
+
|
|
188
|
+
def toggle_command():
|
|
189
|
+
self._on_multi_toggle(value)
|
|
190
|
+
if original_command:
|
|
191
|
+
original_command()
|
|
192
|
+
|
|
193
|
+
button.configure(command=toggle_command)
|
|
194
|
+
|
|
195
|
+
if self._orientation == 'horizontal':
|
|
196
|
+
button.pack(side='left')
|
|
197
|
+
else: # vertical
|
|
198
|
+
button.pack(side='top', fill='x')
|
|
199
|
+
|
|
200
|
+
self._buttons[key] = button
|
|
201
|
+
self._update_button_positions()
|
|
202
|
+
return button
|
|
203
|
+
|
|
204
|
+
def _update_button_positions(self):
|
|
205
|
+
"""Update button styles based on their position in the group.
|
|
206
|
+
|
|
207
|
+
Note: Relies on dictionary insertion order (Python 3.7+) to maintain
|
|
208
|
+
button order based on when they were added.
|
|
209
|
+
"""
|
|
210
|
+
# List conversion maintains insertion order (Python 3.7+)
|
|
211
|
+
button_list = list(self._buttons.values())
|
|
212
|
+
num_buttons = len(button_list)
|
|
213
|
+
|
|
214
|
+
if num_buttons == 0:
|
|
215
|
+
return
|
|
216
|
+
|
|
217
|
+
for idx, button in enumerate(button_list):
|
|
218
|
+
if num_buttons == 1:
|
|
219
|
+
# Single button - use 'before' position (fully rounded on left/top)
|
|
220
|
+
position = 'before'
|
|
221
|
+
elif idx == 0:
|
|
222
|
+
# First button
|
|
223
|
+
position = 'before'
|
|
224
|
+
elif idx == num_buttons - 1:
|
|
225
|
+
# Last button
|
|
226
|
+
position = 'after'
|
|
227
|
+
else:
|
|
228
|
+
# Middle button
|
|
229
|
+
position = 'center'
|
|
230
|
+
|
|
231
|
+
# Update position and rebuild style
|
|
232
|
+
button.configure_style_options(position=position)
|
|
233
|
+
button.rebuild_style()
|
|
234
|
+
|
|
235
|
+
def _on_multi_toggle(self, val: str):
|
|
236
|
+
"""Callback to update the SetVar when a CheckToggle is clicked."""
|
|
237
|
+
current_set = self.get()
|
|
238
|
+
if val in current_set:
|
|
239
|
+
current_set.remove(val)
|
|
240
|
+
else:
|
|
241
|
+
current_set.add(val)
|
|
242
|
+
self.set(current_set)
|
|
243
|
+
|
|
244
|
+
def get(self) -> str | set[str]:
|
|
245
|
+
"""Return the current value (string for single mode, set for multi mode)."""
|
|
246
|
+
return self.variable.get()
|
|
247
|
+
|
|
248
|
+
def set(self, value: str | set[str]) -> None:
|
|
249
|
+
"""Set the value (string for single mode, set for multi mode).
|
|
250
|
+
|
|
251
|
+
Args:
|
|
252
|
+
value: The value to set.
|
|
253
|
+
|
|
254
|
+
Raises:
|
|
255
|
+
TypeError: If value type doesn't match the mode.
|
|
256
|
+
"""
|
|
257
|
+
# Validate value type matches mode
|
|
258
|
+
if self._mode == 'single':
|
|
259
|
+
if not isinstance(value, str):
|
|
260
|
+
raise TypeError(f"Single mode requires a string value, got {type(value).__name__}")
|
|
261
|
+
else: # multi mode
|
|
262
|
+
if not isinstance(value, set):
|
|
263
|
+
raise TypeError(f"Multi mode requires a set value, got {type(value).__name__}")
|
|
264
|
+
|
|
265
|
+
self.variable.set(value)
|
|
266
|
+
|
|
267
|
+
# For multi mode, update CheckToggle states to match new value
|
|
268
|
+
if self._mode == 'multi':
|
|
269
|
+
for key, button in self._buttons.items():
|
|
270
|
+
button.variable.set(key in value)
|
|
271
|
+
|
|
272
|
+
@property
|
|
273
|
+
def value(self) -> str | set[str]:
|
|
274
|
+
"""Get or set the value (string for single mode, set for multi mode)."""
|
|
275
|
+
return self.get()
|
|
276
|
+
|
|
277
|
+
@value.setter
|
|
278
|
+
def value(self, value: str | set[str]) -> None:
|
|
279
|
+
self.set(value)
|
|
280
|
+
|
|
281
|
+
def remove(self, key: str):
|
|
282
|
+
"""Remove a button by its key."""
|
|
283
|
+
if key in self._buttons:
|
|
284
|
+
button = self._buttons.pop(key)
|
|
285
|
+
button.destroy()
|
|
286
|
+
self._update_button_positions()
|
|
287
|
+
|
|
288
|
+
def items(self) -> tuple[RadioToggle | CheckToggle, ...]:
|
|
289
|
+
"""Get all button widgets in the group.
|
|
290
|
+
|
|
291
|
+
Returns:
|
|
292
|
+
A tuple of all button instances in the group.
|
|
293
|
+
"""
|
|
294
|
+
return tuple(self._buttons.values())
|
|
295
|
+
|
|
296
|
+
def item(self, key: str) -> RadioToggle | CheckToggle:
|
|
297
|
+
"""Get a button by its key.
|
|
298
|
+
|
|
299
|
+
Args:
|
|
300
|
+
key: The key of the button to retrieve.
|
|
301
|
+
|
|
302
|
+
Returns:
|
|
303
|
+
The button instance.
|
|
304
|
+
|
|
305
|
+
Raises:
|
|
306
|
+
KeyError: If no button with the given key exists.
|
|
307
|
+
"""
|
|
308
|
+
if key not in self._buttons:
|
|
309
|
+
raise KeyError(f"No button with key '{key}'")
|
|
310
|
+
return self._buttons[key]
|
|
311
|
+
|
|
312
|
+
def configure_item(self, key: str, option: str = None, **kwargs: Any):
|
|
313
|
+
"""Configure a specific button by its key.
|
|
314
|
+
|
|
315
|
+
Args:
|
|
316
|
+
key: The key of the button to configure.
|
|
317
|
+
option: If provided, return the value of this option.
|
|
318
|
+
**kwargs: Configuration options to apply to the button.
|
|
319
|
+
|
|
320
|
+
Returns:
|
|
321
|
+
If option is provided, returns the value of that option.
|
|
322
|
+
"""
|
|
323
|
+
button = self.item(key)
|
|
324
|
+
if option is not None:
|
|
325
|
+
return button.cget(option)
|
|
326
|
+
button.configure(**kwargs)
|
|
327
|
+
|
|
328
|
+
def keys(self) -> tuple[str, ...]:
|
|
329
|
+
"""Get all button keys.
|
|
330
|
+
|
|
331
|
+
Returns:
|
|
332
|
+
A tuple of all button keys in the group.
|
|
333
|
+
"""
|
|
334
|
+
return tuple(self._buttons.keys())
|
|
335
|
+
|
|
336
|
+
def on_changed(self, callback: Callable) -> Any:
|
|
337
|
+
"""Subscribe to value changes. Callback receives `new_value: str | set[str]` directly (str in 'single' mode, set in 'multi' mode)."""
|
|
338
|
+
return self._signal.subscribe(callback)
|
|
339
|
+
|
|
340
|
+
def off_changed(self, bind_id: Any) -> None:
|
|
341
|
+
"""Unsubscribe from value changes."""
|
|
342
|
+
self._signal.unsubscribe(bind_id)
|
|
343
|
+
|
|
344
|
+
@configure_delegate('accent')
|
|
345
|
+
def _delegate_accent(self, value=None):
|
|
346
|
+
"""Get or set the accent. Updates all buttons when changed."""
|
|
347
|
+
if value is None:
|
|
348
|
+
return self._accent
|
|
349
|
+
|
|
350
|
+
self._accent = value
|
|
351
|
+
# Update all buttons with new accent
|
|
352
|
+
self._update_button_positions()
|
|
353
|
+
|
|
354
|
+
@configure_delegate('orient')
|
|
355
|
+
def _delegate_orient(self, value=None):
|
|
356
|
+
"""Get or set orientation ('horizontal' or 'vertical'). Repacks buttons when changed."""
|
|
357
|
+
if value is None:
|
|
358
|
+
return self._orientation
|
|
359
|
+
|
|
360
|
+
if value not in ('horizontal', 'vertical'):
|
|
361
|
+
raise ValueError("orient must be 'horizontal' or 'vertical'")
|
|
362
|
+
|
|
363
|
+
self._orientation = value
|
|
364
|
+
|
|
365
|
+
# Repack all buttons in new orientation
|
|
366
|
+
for button in self._buttons.values():
|
|
367
|
+
button.pack_forget()
|
|
368
|
+
button.configure_style_options(orient=value)
|
|
369
|
+
if self._orientation == 'horizontal':
|
|
370
|
+
button.pack(side='left')
|
|
371
|
+
else:
|
|
372
|
+
button.pack(side='top', fill='x')
|
|
373
|
+
|
|
374
|
+
# Update button styles with new orientation
|
|
375
|
+
self._update_button_positions()
|
|
376
|
+
|
|
377
|
+
@configure_delegate('value')
|
|
378
|
+
def _delegate_value(self, value=None):
|
|
379
|
+
"""Get or set the value via configure."""
|
|
380
|
+
if value is None:
|
|
381
|
+
return self.get()
|
|
382
|
+
self.set(value)
|