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,124 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from tkinter import ttk
|
|
4
|
+
from typing import Any, Callable, Literal, Optional, TYPE_CHECKING, TypedDict
|
|
5
|
+
|
|
6
|
+
from typing_extensions import Unpack
|
|
7
|
+
|
|
8
|
+
from bootstack.core.mixins.ttk_state import TtkStateMixin
|
|
9
|
+
from bootstack.core.mixins.widget import WidgetCapabilitiesMixin
|
|
10
|
+
from bootstack.widgets.internal.wrapper_base import TTKWrapperBase
|
|
11
|
+
from bootstack.widgets.mixins import IconMixin, LocalizationMixin, SignalMixin, TextSignalMixin
|
|
12
|
+
from bootstack.widgets.mixins.configure_mixin import configure_delegate
|
|
13
|
+
from bootstack.widgets.types import Master
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from bootstack.core.signals import Signal
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class CheckButtonKwargs(TypedDict, total=False):
|
|
20
|
+
# Standard ttk.Checkbutton options
|
|
21
|
+
text: Any
|
|
22
|
+
command: Optional[Callable[[], Any]]
|
|
23
|
+
image: Any
|
|
24
|
+
icon: Any
|
|
25
|
+
icon_only: bool
|
|
26
|
+
compound: Literal['text', 'image', 'top', 'bottom', 'left', 'right', 'center', 'none'] | str
|
|
27
|
+
variable: Any
|
|
28
|
+
signal: Signal[Any]
|
|
29
|
+
value: Any
|
|
30
|
+
onvalue: Any
|
|
31
|
+
offvalue: Any
|
|
32
|
+
padding: Any
|
|
33
|
+
anchor: str
|
|
34
|
+
width: int
|
|
35
|
+
underline: int
|
|
36
|
+
state: Literal['normal', 'active', 'disabled', 'readonly'] | str
|
|
37
|
+
takefocus: Any
|
|
38
|
+
style: str
|
|
39
|
+
class_: str
|
|
40
|
+
cursor: str
|
|
41
|
+
name: str
|
|
42
|
+
textvariable: Any
|
|
43
|
+
textsignal: Signal[str]
|
|
44
|
+
|
|
45
|
+
# bootstack-specific extensions
|
|
46
|
+
bootstyle: str # DEPRECATED: Use accent and variant instead
|
|
47
|
+
accent: str
|
|
48
|
+
variant: str
|
|
49
|
+
surface: str
|
|
50
|
+
style_options: dict[str, Any]
|
|
51
|
+
localize: bool | Literal['auto']
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class CheckButton(LocalizationMixin, SignalMixin, TextSignalMixin, IconMixin, TTKWrapperBase, WidgetCapabilitiesMixin, TtkStateMixin, ttk.Checkbutton):
|
|
55
|
+
"""bootstack wrapper for `ttk.Checkbutton` with bootstyle and icon support."""
|
|
56
|
+
|
|
57
|
+
_ttk_base = ttk.Checkbutton
|
|
58
|
+
|
|
59
|
+
def __init__(self, master: Master = None, **kwargs: Unpack[CheckButtonKwargs]) -> None:
|
|
60
|
+
"""Create a themed bootstack Checkbutton.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
master: Parent widget. If None, uses the default root window.
|
|
64
|
+
|
|
65
|
+
Other Parameters:
|
|
66
|
+
text (str): Text to display.
|
|
67
|
+
textvariable (Variable): Tk variable linked to the text.
|
|
68
|
+
textsignal (Signal[str]): Reactive Signal linked to the text (auto-synced with textvariable).
|
|
69
|
+
command (Callable): Callable invoked when the value toggles.
|
|
70
|
+
image (PhotoImage): Image to display.
|
|
71
|
+
icon (str | dict): Theme-aware icon spec handled by the style system.
|
|
72
|
+
icon_only (bool): If True, removes the additional padding reserved for text.
|
|
73
|
+
compound (str): Placement of the image relative to text.
|
|
74
|
+
variable (Variable): Linked variable controlling the on/off state.
|
|
75
|
+
localize (bool | Literal['auto']): Determines the widget's localization mode.
|
|
76
|
+
signal (Signal): Reactive Signal controlling the on/off state (auto-synced with variable).
|
|
77
|
+
value (Any): Initial state for the widget's associated variable (defaults to None when unset).
|
|
78
|
+
onvalue (Any): Value set in `variable` when selected.
|
|
79
|
+
offvalue (Any): Value set in `variable` when deselected.
|
|
80
|
+
padding (int | tuple): Extra space around the content.
|
|
81
|
+
anchor (str): Determines how the content is aligned in the container. Combination of 'n', 's', 'e', 'w', or 'center' (default).
|
|
82
|
+
width (int): Width of the control in characters.
|
|
83
|
+
underline (int): Index of character to underline in `text`.
|
|
84
|
+
state (str): Widget state.
|
|
85
|
+
takefocus (bool): Whether the widget participates in focus traversal.
|
|
86
|
+
style (str): Explicit ttk style name (overrides accent/variant).
|
|
87
|
+
accent (str): Accent token for styling, e.g. 'primary', 'success', 'danger'.
|
|
88
|
+
variant (str): Style variant, e.g. 'default', 'round', 'square'.
|
|
89
|
+
bootstyle (str): DEPRECATED - Use `accent` and `variant` instead.
|
|
90
|
+
Combined style tokens (e.g., 'primary', 'success').
|
|
91
|
+
surface (str): Optional surface token; otherwise inherited.
|
|
92
|
+
style_options (dict): Optional dict forwarded to the style builder.
|
|
93
|
+
"""
|
|
94
|
+
signal_provided = 'signal' in kwargs
|
|
95
|
+
variable_provided = 'variable' in kwargs
|
|
96
|
+
initial_value = kwargs.pop('value', None)
|
|
97
|
+
kwargs.update(style_options=self._capture_style_options(['icon_only', 'icon', 'anchor'], kwargs))
|
|
98
|
+
super().__init__(master, **kwargs)
|
|
99
|
+
if initial_value is not None and not signal_provided and not variable_provided:
|
|
100
|
+
self.variable.set(initial_value)
|
|
101
|
+
|
|
102
|
+
def get(self) -> Any:
|
|
103
|
+
"""Return the current value of the checkbutton."""
|
|
104
|
+
return self.variable.get()
|
|
105
|
+
|
|
106
|
+
def set(self, value: Any) -> None:
|
|
107
|
+
"""Set the value of the checkbutton."""
|
|
108
|
+
self.variable.set(value)
|
|
109
|
+
|
|
110
|
+
@property
|
|
111
|
+
def value(self) -> Any:
|
|
112
|
+
"""Get or set the checkbutton's value."""
|
|
113
|
+
return self.get()
|
|
114
|
+
|
|
115
|
+
@value.setter
|
|
116
|
+
def value(self, value: Any) -> None:
|
|
117
|
+
self.set(value)
|
|
118
|
+
|
|
119
|
+
@configure_delegate('value')
|
|
120
|
+
def _delegate_value(self, value=None):
|
|
121
|
+
"""Get or set the value via configure."""
|
|
122
|
+
if value is None:
|
|
123
|
+
return self.get()
|
|
124
|
+
self.set(value)
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
from typing import Literal
|
|
2
|
+
|
|
3
|
+
from bootstack.widgets.primitives.checkbutton import CheckButton
|
|
4
|
+
from bootstack.widgets.types import Master
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class CheckToggle(CheckButton):
|
|
8
|
+
"""bootstack wrapper for `ttk.Checkbutton` that renders with a ToolButton style"""
|
|
9
|
+
|
|
10
|
+
def __init__(self, master: Master = None, **kwargs):
|
|
11
|
+
"""Create a themed bootstack CheckToggle.
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
master: Parent widget. If None, uses the default root window.
|
|
15
|
+
|
|
16
|
+
Other Parameters:
|
|
17
|
+
text (str): Text to display on the toggle.
|
|
18
|
+
textvariable (Variable): Tk variable linked to the text.
|
|
19
|
+
textsignal (Signal[str]): Reactive Signal linked to the text (auto-synced with textvariable).
|
|
20
|
+
command (Callable): Callable invoked when the toggle changes state.
|
|
21
|
+
image (PhotoImage): Image to display.
|
|
22
|
+
icon (str | dict): Theme-aware icon spec handled by the style system.
|
|
23
|
+
icon_only (bool): If True, removes the additional padding reserved for text.
|
|
24
|
+
compound (str): Placement of the image relative to text.
|
|
25
|
+
variable (Variable): Linked variable controlling the on/off state.
|
|
26
|
+
signal (Signal): Reactive Signal controlling the on/off state (auto-synced with variable).
|
|
27
|
+
value (Any): Initial state for the widget's associated variable (defaults to None when unset).
|
|
28
|
+
onvalue (Any): Value set in `variable` when selected.
|
|
29
|
+
offvalue (Any): Value set in `variable` when deselected.
|
|
30
|
+
padding (int | tuple): Extra space around the content.
|
|
31
|
+
anchor (str): Determines how the content is aligned in the container. Combination of 'n', 's', 'e', 'w', or 'center' (default).
|
|
32
|
+
density (str): The vertical and horizontal compactness of widget content, e.g. 'default', 'compact'.
|
|
33
|
+
width (int): Width of the control in characters.
|
|
34
|
+
underline (int): Index of character to underline in `text`.
|
|
35
|
+
state (str): Widget state ('normal', 'active', 'disabled', 'readonly').
|
|
36
|
+
takefocus (bool): Whether the widget participates in focus traversal.
|
|
37
|
+
accent (str): Accent token for styling, e.g. 'primary', 'success', 'danger'.
|
|
38
|
+
variant (str): Style variant (coerced to 'toolbutton').
|
|
39
|
+
surface (str): Optional surface token; otherwise inherited.
|
|
40
|
+
style_options (dict): Optional dict forwarded to the style builder.
|
|
41
|
+
localize (bool | Literal['auto']): Determines the widget's localization mode.
|
|
42
|
+
"""
|
|
43
|
+
self._capture_density_option(kwargs)
|
|
44
|
+
kwargs.setdefault('class_', 'Toolbutton')
|
|
45
|
+
super().__init__(master, **kwargs)
|
|
46
|
+
|
|
47
|
+
@staticmethod
|
|
48
|
+
def _capture_density_option(kwargs: dict) -> None:
|
|
49
|
+
"""Capture density from kwargs into style_options."""
|
|
50
|
+
density: Literal['default', 'compact'] | None = kwargs.pop('density', None)
|
|
51
|
+
if density is not None:
|
|
52
|
+
style_options = kwargs.setdefault('style_options', {})
|
|
53
|
+
style_options['density'] = density
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from tkinter import ttk
|
|
4
|
+
from typing import Any, Literal, TypedDict, TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
from typing_extensions import Unpack
|
|
7
|
+
|
|
8
|
+
from bootstack.core.mixins.ttk_state import TtkStateMixin
|
|
9
|
+
from bootstack.core.mixins.widget import WidgetCapabilitiesMixin
|
|
10
|
+
from bootstack.widgets.internal.wrapper_base import TTKWrapperBase
|
|
11
|
+
from bootstack.widgets.types import Master
|
|
12
|
+
from ..mixins import TextSignalMixin, configure_delegate
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from bootstack.core.signals import Signal
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class ComboboxKwargs(TypedDict, total=False):
|
|
19
|
+
# Standard ttk.Combobox options
|
|
20
|
+
values: Any
|
|
21
|
+
textvariable: Any
|
|
22
|
+
textsignal: Signal[Any]
|
|
23
|
+
state: Literal['normal', 'readonly', 'disabled'] | str
|
|
24
|
+
width: int
|
|
25
|
+
height: int
|
|
26
|
+
postcommand: Any
|
|
27
|
+
justify: Any
|
|
28
|
+
exportselection: bool
|
|
29
|
+
xscrollcommand: Any
|
|
30
|
+
font: Any
|
|
31
|
+
foreground: str
|
|
32
|
+
background: str
|
|
33
|
+
style: str
|
|
34
|
+
class_: str
|
|
35
|
+
cursor: str
|
|
36
|
+
name: str
|
|
37
|
+
|
|
38
|
+
# bootstack-specific extensions
|
|
39
|
+
bootstyle: str # DEPRECATED: Use accent and variant instead
|
|
40
|
+
accent: str
|
|
41
|
+
density: Literal['default', 'compact']
|
|
42
|
+
surface: str
|
|
43
|
+
style_options: dict[str, Any]
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class Combobox(TextSignalMixin, TTKWrapperBase, WidgetCapabilitiesMixin, TtkStateMixin, ttk.Combobox):
|
|
47
|
+
"""bootstack wrapper for `ttk.Combobox` with bootstyle support."""
|
|
48
|
+
|
|
49
|
+
_ttk_base = ttk.Combobox
|
|
50
|
+
|
|
51
|
+
def __init__(self, master: Master = None, **kwargs: Unpack[ComboboxKwargs]) -> None:
|
|
52
|
+
"""Create a themed bootstack Combobox.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
master: Parent widget. If None, uses the default root window.
|
|
56
|
+
|
|
57
|
+
Other Parameters:
|
|
58
|
+
values (list): Sequence of values to display.
|
|
59
|
+
textvariable (Variable): Tk variable linked to the selected value.
|
|
60
|
+
textsignal (Signal): Reactive Signal linked to the text (auto-synced with textvariable).
|
|
61
|
+
state (str): Widget state; 'readonly' restricts to list items.
|
|
62
|
+
width (int): Width in characters.
|
|
63
|
+
height (int): Maximum rows shown in the drop-down list.
|
|
64
|
+
postcommand (Callable): Callback executed before showing the drop-down.
|
|
65
|
+
justify (str): Text justification within the entry field.
|
|
66
|
+
exportselection (bool): Whether selection is exported to X clipboard.
|
|
67
|
+
xscrollcommand (Callable): Scroll callback for horizontal scrolling.
|
|
68
|
+
font (str | Font): Font for the entry field.
|
|
69
|
+
foreground (str): Text color.
|
|
70
|
+
background (str): Background color for the entry field.
|
|
71
|
+
style (str): Explicit ttk style name (overrides accent/variant).
|
|
72
|
+
accent (str): Accent token for styling, e.g. 'primary', 'danger', 'success'.
|
|
73
|
+
density (str): The vertical and horizontal compactness, e.g. 'default', 'compact'.
|
|
74
|
+
bootstyle (str): DEPRECATED - Use `accent` and `variant` instead.
|
|
75
|
+
Combined style tokens (e.g., 'primary').
|
|
76
|
+
surface (str): Optional surface token; otherwise inherited.
|
|
77
|
+
style_options (dict): Optional dict forwarded to the style builder.
|
|
78
|
+
"""
|
|
79
|
+
# Store density for popdown positioning
|
|
80
|
+
if kwargs.get('density') == 'compact':
|
|
81
|
+
kwargs['font'] = 'caption'
|
|
82
|
+
kwargs.update(style_options=self._capture_style_options(['density'], kwargs))
|
|
83
|
+
super().__init__(master, **kwargs)
|
|
84
|
+
|
|
85
|
+
# Store original postcommand if provided
|
|
86
|
+
self._original_postcommand = kwargs.get('postcommand')
|
|
87
|
+
|
|
88
|
+
# Set up popdown styling (also bound to theme changes)
|
|
89
|
+
self._setup_postcommand()
|
|
90
|
+
self._subscribe_theme_changes()
|
|
91
|
+
|
|
92
|
+
@configure_delegate('density')
|
|
93
|
+
def _delegate_density(self, value=None):
|
|
94
|
+
if value is None:
|
|
95
|
+
return self.configure_style_options(value)
|
|
96
|
+
else:
|
|
97
|
+
if value == 'compact':
|
|
98
|
+
self.configure(font='caption')
|
|
99
|
+
else:
|
|
100
|
+
self.configure(font='body')
|
|
101
|
+
return self.configure_style_options(density=value)
|
|
102
|
+
|
|
103
|
+
def _setup_postcommand(self) -> None:
|
|
104
|
+
"""Re-style the popdown each time it opens.
|
|
105
|
+
|
|
106
|
+
The popdown is created lazily on first open and reused. Re-styling on
|
|
107
|
+
every open ensures it picks up the current theme's colors, since the
|
|
108
|
+
embedded Tk listbox/scrollbar aren't rebuilt by the ttk style engine.
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
def on_popdown():
|
|
112
|
+
self._apply_popdown_style(create_if_missing=True)
|
|
113
|
+
|
|
114
|
+
if self._original_postcommand:
|
|
115
|
+
if callable(self._original_postcommand):
|
|
116
|
+
self._original_postcommand()
|
|
117
|
+
else:
|
|
118
|
+
self.tk.eval(str(self._original_postcommand))
|
|
119
|
+
|
|
120
|
+
self.configure(postcommand=on_popdown)
|
|
121
|
+
|
|
122
|
+
def _apply_popdown_style(self, create_if_missing: bool = False) -> None:
|
|
123
|
+
"""Apply theme colors and density font to the embedded popdown.
|
|
124
|
+
|
|
125
|
+
Args:
|
|
126
|
+
create_if_missing: If True, force-create the popdown so we can
|
|
127
|
+
style it before it's mapped (used from the postcommand). If
|
|
128
|
+
False, no-op when the popdown doesn't exist yet (used from
|
|
129
|
+
the theme-change subscriber).
|
|
130
|
+
"""
|
|
131
|
+
popdown_path = f"{self}.popdown"
|
|
132
|
+
try:
|
|
133
|
+
popdown_exists = bool(int(self.tk.eval(f"winfo exists {popdown_path}")))
|
|
134
|
+
except Exception:
|
|
135
|
+
return
|
|
136
|
+
|
|
137
|
+
if not popdown_exists:
|
|
138
|
+
if not create_if_missing:
|
|
139
|
+
return
|
|
140
|
+
try:
|
|
141
|
+
self.tk.eval(f"ttk::combobox::PopdownWindow {self}")
|
|
142
|
+
except Exception:
|
|
143
|
+
return
|
|
144
|
+
|
|
145
|
+
try:
|
|
146
|
+
from bootstack.style.bootstyle_builder_mixed import BootstyleBuilderMixed
|
|
147
|
+
BootstyleBuilderMixed().update_combobox_popdown_style(self)
|
|
148
|
+
except Exception:
|
|
149
|
+
pass
|
|
150
|
+
|
|
151
|
+
try:
|
|
152
|
+
density = self.configure_style_options('density') or 'default'
|
|
153
|
+
from bootstack.style.typography import get_font
|
|
154
|
+
font_token = 'caption' if density == 'compact' else 'body'
|
|
155
|
+
self.tk.call(f"{popdown_path}.f.l", "configure", "-font", str(get_font(font_token)))
|
|
156
|
+
except Exception:
|
|
157
|
+
pass
|
|
158
|
+
|
|
159
|
+
def _subscribe_theme_changes(self) -> None:
|
|
160
|
+
"""Re-style any already-created popdown when the theme changes."""
|
|
161
|
+
from bootstack.core.publisher import Channel, Publisher
|
|
162
|
+
name = str(self)
|
|
163
|
+
Publisher.subscribe(name=name, func=self._apply_popdown_style, channel=Channel.STD)
|
|
164
|
+
self.bind('<Destroy>', lambda _e, n=name: Publisher.unsubscribe(n), '+')
|
|
165
|
+
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from tkinter import ttk
|
|
4
|
+
from typing import Any, Literal, Optional, TypedDict, TYPE_CHECKING
|
|
5
|
+
from typing_extensions import Unpack
|
|
6
|
+
|
|
7
|
+
from bootstack.core.mixins.ttk_state import TtkStateMixin
|
|
8
|
+
from bootstack.core.mixins.widget import WidgetCapabilitiesMixin
|
|
9
|
+
from bootstack.widgets.internal.wrapper_base import TTKWrapperBase
|
|
10
|
+
from bootstack.widgets.types import Master
|
|
11
|
+
from ..mixins import TextSignalMixin, configure_delegate
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from bootstack.core.signals import Signal
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class EntryKwargs(TypedDict, total=False):
|
|
18
|
+
# Standard ttk.Entry options
|
|
19
|
+
textvariable: Any
|
|
20
|
+
textsignal: Signal[str]
|
|
21
|
+
show: Any
|
|
22
|
+
width: int
|
|
23
|
+
exportselection: bool
|
|
24
|
+
justify: Any
|
|
25
|
+
validate: Any
|
|
26
|
+
validatecommand: Any
|
|
27
|
+
invalidcommand: Any
|
|
28
|
+
xscrollcommand: Any
|
|
29
|
+
font: Any
|
|
30
|
+
foreground: str
|
|
31
|
+
background: str
|
|
32
|
+
state: Literal['normal', 'disabled', 'readonly'] | str
|
|
33
|
+
takefocus: Any
|
|
34
|
+
style: str
|
|
35
|
+
class_: str
|
|
36
|
+
cursor: str
|
|
37
|
+
name: str
|
|
38
|
+
|
|
39
|
+
# bootstack-specific extensions
|
|
40
|
+
bootstyle: str # DEPRECATED: Use accent and variant instead
|
|
41
|
+
accent: str
|
|
42
|
+
density: Literal['default', 'compact']
|
|
43
|
+
variant: str
|
|
44
|
+
surface: str
|
|
45
|
+
style_options: dict[str, Any]
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class Entry(TextSignalMixin, TTKWrapperBase, WidgetCapabilitiesMixin, TtkStateMixin, ttk.Entry):
|
|
49
|
+
"""bootstack wrapper for `ttk.Entry` with bootstyle support."""
|
|
50
|
+
|
|
51
|
+
_ttk_base = ttk.Entry
|
|
52
|
+
|
|
53
|
+
def __init__(self, master: Master = None, **kwargs: Unpack[EntryKwargs]) -> None:
|
|
54
|
+
"""Create a themed bootstack Entry.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
master: Parent widget. If None, uses the default root window.
|
|
58
|
+
|
|
59
|
+
Other Parameters:
|
|
60
|
+
textvariable (Variable): Tk variable linked to the entry text.
|
|
61
|
+
textsignal (Signal[str]): Reactive Signal linked to the entry text (auto-synced with textvariable).
|
|
62
|
+
show (str): Substitute character for masked input.
|
|
63
|
+
width (int): Width in characters.
|
|
64
|
+
exportselection (bool): Whether selection is exported to X clipboard.
|
|
65
|
+
justify (str): Text alignment inside the entry.
|
|
66
|
+
validate (str): Validation mode.
|
|
67
|
+
validatecommand (Callable): Validation callback.
|
|
68
|
+
invalidcommand (Callable): Callback executed on validation failure.
|
|
69
|
+
xscrollcommand (Callable): Horizontal scroll callback.
|
|
70
|
+
font (str | Font): Font for the entry text.
|
|
71
|
+
foreground (str): Text color.
|
|
72
|
+
background (str): Background color.
|
|
73
|
+
state (str): Widget state.
|
|
74
|
+
takefocus (bool): Whether the widget participates in focus traversal.
|
|
75
|
+
style (str): Explicit ttk style name (overrides accent/variant).
|
|
76
|
+
accent (str): Accent token for styling, e.g. 'primary', 'danger', 'success'.
|
|
77
|
+
variant (str): Style variant, e.g. 'default'.
|
|
78
|
+
density (str): The vertical and horizontal compactness, e.g. 'default', 'compact'.
|
|
79
|
+
bootstyle (str): DEPRECATED - Use `accent` and `variant` instead.
|
|
80
|
+
Combined style tokens (e.g., 'primary').
|
|
81
|
+
surface (str): Optional surface token; otherwise inherited.
|
|
82
|
+
style_options (dict): Optional dict forwarded to the style builder.
|
|
83
|
+
"""
|
|
84
|
+
if kwargs.get('density') == 'compact':
|
|
85
|
+
kwargs['font'] = 'caption'
|
|
86
|
+
kwargs.update(style_options=self._capture_style_options(['density'], kwargs))
|
|
87
|
+
super().__init__(master, **kwargs)
|
|
88
|
+
|
|
89
|
+
@configure_delegate('density')
|
|
90
|
+
def _delegate_density(self, value=None):
|
|
91
|
+
if value is None:
|
|
92
|
+
return self.configure_style_options(value)
|
|
93
|
+
else:
|
|
94
|
+
if value == 'compact':
|
|
95
|
+
self.configure(font='caption')
|
|
96
|
+
else:
|
|
97
|
+
self.configure(font='body')
|
|
98
|
+
return self.configure_style_options(density=value)
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from tkinter import ttk
|
|
4
|
+
from typing import Any, TypedDict
|
|
5
|
+
|
|
6
|
+
from typing_extensions import Unpack
|
|
7
|
+
|
|
8
|
+
from bootstack.core.mixins.ttk_state import TtkStateMixin
|
|
9
|
+
from bootstack.core.mixins.widget import WidgetCapabilitiesMixin
|
|
10
|
+
from bootstack.widgets.internal.wrapper_base import TTKWrapperBase
|
|
11
|
+
from bootstack.widgets.types import Master
|
|
12
|
+
from bootstack.style.style import get_style
|
|
13
|
+
from bootstack.style.bootstyle_builder_tk import BootstyleBuilderBuilderTk
|
|
14
|
+
from ..mixins import configure_delegate
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class FrameKwargs(TypedDict, total=False):
|
|
18
|
+
# Standard ttk.Frame options
|
|
19
|
+
padding: Any
|
|
20
|
+
width: int
|
|
21
|
+
height: int
|
|
22
|
+
style: str
|
|
23
|
+
cursor: str
|
|
24
|
+
name: str
|
|
25
|
+
takefocus: bool
|
|
26
|
+
class_: str
|
|
27
|
+
|
|
28
|
+
# bootstack-specific extensions
|
|
29
|
+
accent: str
|
|
30
|
+
variant: str
|
|
31
|
+
surface: str
|
|
32
|
+
input_background: str
|
|
33
|
+
show_border: bool
|
|
34
|
+
style_options: dict[str, Any]
|
|
35
|
+
bootstyle: str # DEPRECATED: Use accent and variant instead
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class Frame(TTKWrapperBase, WidgetCapabilitiesMixin, TtkStateMixin, ttk.Frame):
|
|
39
|
+
"""bootstack wrapper for `ttk.Frame` with bootstyle support."""
|
|
40
|
+
|
|
41
|
+
_ttk_base = ttk.Frame
|
|
42
|
+
|
|
43
|
+
def __init__(self, master: Master = None, **kwargs: Unpack[FrameKwargs]) -> None:
|
|
44
|
+
"""Create a themed bootstack Frame.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
master: Parent widget. If None, uses the default root window.
|
|
48
|
+
|
|
49
|
+
Other Parameters:
|
|
50
|
+
padding (int | tuple): Extra padding inside the frame.
|
|
51
|
+
relief (str): Border style.
|
|
52
|
+
borderwidth (int): Border width.
|
|
53
|
+
width (int): Requested width in pixels.
|
|
54
|
+
height (int): Requested height in pixels.
|
|
55
|
+
takefocus (bool): Widget accepts focus during keyboard traversal.
|
|
56
|
+
style (str): Explicit ttk style name (overrides accent/variant).
|
|
57
|
+
accent (str): Accent token for styling, e.g. 'primary', 'secondary', 'success'.
|
|
58
|
+
variant (str): Style variant (if applicable).
|
|
59
|
+
bootstyle (str): DEPRECATED - Use `accent` and `variant` instead.
|
|
60
|
+
Combined style tokens (e.g., 'secondary').
|
|
61
|
+
surface (str): Optional surface token; otherwise inherited.
|
|
62
|
+
input_background (str): Surface token used as the fill color for all input
|
|
63
|
+
widgets (Entry, Combobox, Spinbox, Field) inside this container. Cascades
|
|
64
|
+
to descendants the same way `surface` does. Input foreground, border,
|
|
65
|
+
and focus-ring colors are all derived from this fill so contrast is always
|
|
66
|
+
correct. Defaults to `'content'` (the app background), which keeps
|
|
67
|
+
inputs visually distinct regardless of the container surface. Override
|
|
68
|
+
with any surface token (e.g. `'card'`) to match the container.
|
|
69
|
+
show_border (bool): Draw a border around the frame.
|
|
70
|
+
style_options (dict): Optional dict forwarded to the style builder.
|
|
71
|
+
"""
|
|
72
|
+
kwargs.update(style_options=self._capture_style_options(['show_border'], kwargs))
|
|
73
|
+
super().__init__(master, **kwargs)
|
|
74
|
+
|
|
75
|
+
def configure_style_options(self, value=None, **kwargs):
|
|
76
|
+
"""Set style options and refresh descendant surfaces if needed."""
|
|
77
|
+
old_surface = getattr(self, "_surface", "background")
|
|
78
|
+
old_input_bg = getattr(self, "_input_background", None)
|
|
79
|
+
result = super().configure_style_options(value, **kwargs)
|
|
80
|
+
if value is None:
|
|
81
|
+
if "surface" in kwargs:
|
|
82
|
+
new_surface = getattr(self, "_surface", "background")
|
|
83
|
+
if old_surface != new_surface:
|
|
84
|
+
self.rebuild_style()
|
|
85
|
+
self._refresh_descendant_surfaces(old_surface, new_surface)
|
|
86
|
+
if "input_background" in kwargs:
|
|
87
|
+
new_input_bg = getattr(self, "_input_background", None)
|
|
88
|
+
if old_input_bg != new_input_bg:
|
|
89
|
+
self._refresh_descendant_input_backgrounds(old_input_bg, new_input_bg)
|
|
90
|
+
return result
|
|
91
|
+
|
|
92
|
+
@configure_delegate("bootstyle")
|
|
93
|
+
def _delegate_bootstyle(self, value: Any = None):
|
|
94
|
+
old_surface = getattr(self, "_surface", "background")
|
|
95
|
+
result = super()._delegate_bootstyle(value)
|
|
96
|
+
new_surface = getattr(self, "_surface", "background")
|
|
97
|
+
if value is not None and old_surface != new_surface:
|
|
98
|
+
self._refresh_descendant_surfaces(old_surface, new_surface)
|
|
99
|
+
return result
|
|
100
|
+
|
|
101
|
+
def _refresh_descendant_surfaces(self, old_surface: str, new_surface: str) -> None:
|
|
102
|
+
if old_surface == new_surface:
|
|
103
|
+
return
|
|
104
|
+
|
|
105
|
+
style = get_style()
|
|
106
|
+
builder_tk = BootstyleBuilderBuilderTk(
|
|
107
|
+
theme_provider=style.theme_provider if style else None,
|
|
108
|
+
style_instance=style,
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
for child in self._iter_descendants():
|
|
112
|
+
try:
|
|
113
|
+
child_surface = getattr(child, "_surface", None)
|
|
114
|
+
except Exception:
|
|
115
|
+
child_surface = None
|
|
116
|
+
|
|
117
|
+
explicit_surface = None
|
|
118
|
+
try:
|
|
119
|
+
explicit_surface = getattr(child, "_style_options", {}).get("surface")
|
|
120
|
+
except Exception:
|
|
121
|
+
explicit_surface = None
|
|
122
|
+
|
|
123
|
+
if explicit_surface and explicit_surface != old_surface:
|
|
124
|
+
continue
|
|
125
|
+
|
|
126
|
+
if child_surface != old_surface:
|
|
127
|
+
continue
|
|
128
|
+
|
|
129
|
+
try:
|
|
130
|
+
setattr(child, "_surface", new_surface)
|
|
131
|
+
except Exception:
|
|
132
|
+
continue
|
|
133
|
+
|
|
134
|
+
if hasattr(child, "rebuild_style"):
|
|
135
|
+
try:
|
|
136
|
+
child.rebuild_style()
|
|
137
|
+
except Exception:
|
|
138
|
+
pass
|
|
139
|
+
else:
|
|
140
|
+
try:
|
|
141
|
+
builder_tk.call_builder(child, surface=new_surface)
|
|
142
|
+
except Exception:
|
|
143
|
+
pass
|
|
144
|
+
|
|
145
|
+
def _refresh_descendant_input_backgrounds(self, old_bg: str | None, new_bg: str | None) -> None:
|
|
146
|
+
if old_bg == new_bg:
|
|
147
|
+
return
|
|
148
|
+
|
|
149
|
+
style = get_style()
|
|
150
|
+
builder_tk = BootstyleBuilderBuilderTk(
|
|
151
|
+
theme_provider=style.theme_provider if style else None,
|
|
152
|
+
style_instance=style,
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
for child in self._iter_descendants():
|
|
156
|
+
try:
|
|
157
|
+
child_input_bg = getattr(child, "_input_background", None)
|
|
158
|
+
except Exception:
|
|
159
|
+
child_input_bg = None
|
|
160
|
+
|
|
161
|
+
explicit_input_bg = None
|
|
162
|
+
try:
|
|
163
|
+
explicit_input_bg = getattr(child, "_style_options", {}).get("input_background")
|
|
164
|
+
except Exception:
|
|
165
|
+
explicit_input_bg = None
|
|
166
|
+
|
|
167
|
+
if explicit_input_bg and explicit_input_bg != old_bg:
|
|
168
|
+
continue
|
|
169
|
+
|
|
170
|
+
if child_input_bg != old_bg:
|
|
171
|
+
continue
|
|
172
|
+
|
|
173
|
+
try:
|
|
174
|
+
setattr(child, "_input_background", new_bg)
|
|
175
|
+
except Exception:
|
|
176
|
+
continue
|
|
177
|
+
|
|
178
|
+
if hasattr(child, "rebuild_style"):
|
|
179
|
+
try:
|
|
180
|
+
child.rebuild_style()
|
|
181
|
+
except Exception:
|
|
182
|
+
pass
|
|
183
|
+
else:
|
|
184
|
+
try:
|
|
185
|
+
builder_tk.call_builder(child, input_background=new_bg)
|
|
186
|
+
except Exception:
|
|
187
|
+
pass
|
|
188
|
+
|
|
189
|
+
def _iter_descendants(self):
|
|
190
|
+
stack = list(self.winfo_children())
|
|
191
|
+
while stack:
|
|
192
|
+
widget = stack.pop()
|
|
193
|
+
yield widget
|
|
194
|
+
try:
|
|
195
|
+
stack.extend(widget.winfo_children())
|
|
196
|
+
except Exception:
|
|
197
|
+
pass
|
|
198
|
+
|
|
199
|
+
@configure_delegate('show_border')
|
|
200
|
+
def _delegate_show_border(self, value=None):
|
|
201
|
+
if value is not None:
|
|
202
|
+
return self.configure_style_options('show_border')
|
|
203
|
+
else:
|
|
204
|
+
self.configure_style_options(show_border=True)
|
|
205
|
+
return self.rebuild_style()
|
|
206
|
+
|