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,445 @@
|
|
|
1
|
+
"""AppShell - a top-level application window with built-in navigation.
|
|
2
|
+
|
|
3
|
+
Provides a convenient way to scaffold the standard desktop app layout:
|
|
4
|
+
toolbar at top, sidebar navigation on the left, and page content on the right.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import Any, Callable, Literal
|
|
10
|
+
|
|
11
|
+
from typing_extensions import TypedDict, Unpack
|
|
12
|
+
|
|
13
|
+
from bootstack.widgets.primitives.frame import Frame
|
|
14
|
+
from bootstack.widgets.composites.toolbar import Toolbar
|
|
15
|
+
from bootstack.widgets.composites.sidenav import SideNav
|
|
16
|
+
from bootstack.widgets.composites.pagestack import PageStack
|
|
17
|
+
from bootstack.widgets.composites.scrollview import ScrollView
|
|
18
|
+
from bootstack.widgets.mixins import configure_delegate
|
|
19
|
+
from bootstack.runtime.app import App
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class AppShellKwargs(TypedDict, total=False):
|
|
23
|
+
title: str
|
|
24
|
+
theme: str
|
|
25
|
+
size: tuple[int, int]
|
|
26
|
+
position: tuple[int, int]
|
|
27
|
+
minsize: tuple[int, int]
|
|
28
|
+
maxsize: tuple[int, int]
|
|
29
|
+
resizable: tuple[bool, bool]
|
|
30
|
+
frameless: bool
|
|
31
|
+
show_toolbar: bool
|
|
32
|
+
show_window_controls: bool
|
|
33
|
+
draggable: bool
|
|
34
|
+
toolbar_density: Literal['default', 'compact']
|
|
35
|
+
show_nav: bool
|
|
36
|
+
nav_display_mode: Literal['expanded', 'compact', 'minimal']
|
|
37
|
+
nav_accent: str
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class AppShell(App):
|
|
41
|
+
"""A top-level application window with built-in navigation.
|
|
42
|
+
|
|
43
|
+
AppShell extends `App` and wires together a `Toolbar`,
|
|
44
|
+
`SideNav`, and `PageStack` into the common
|
|
45
|
+
toolbar + sidebar + content layout. Each component is optional
|
|
46
|
+
and exposed as a property for customization.
|
|
47
|
+
|
|
48
|
+
Example:
|
|
49
|
+
```python
|
|
50
|
+
import bootstack as bs
|
|
51
|
+
|
|
52
|
+
shell = bs.AppShell(title='My App', size=(1000, 650))
|
|
53
|
+
|
|
54
|
+
home = shell.add_page('home', text='Home', icon='house')
|
|
55
|
+
bs.Label(home, text='Welcome!').pack(padx=20, pady=20)
|
|
56
|
+
|
|
57
|
+
docs = shell.add_page('docs', text='Documents', icon='file-earmark-text')
|
|
58
|
+
bs.Label(docs, text='Your documents.').pack(padx=20, pady=20)
|
|
59
|
+
|
|
60
|
+
shell.mainloop()
|
|
61
|
+
```
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
def __init__(
|
|
65
|
+
self,
|
|
66
|
+
title: str = '',
|
|
67
|
+
theme: str | None = None,
|
|
68
|
+
size: tuple[int, int] | None = None,
|
|
69
|
+
position: tuple[int, int] | None = None,
|
|
70
|
+
minsize: tuple[int, int] | None = None,
|
|
71
|
+
maxsize: tuple[int, int] | None = None,
|
|
72
|
+
resizable: tuple[bool, bool] | None = None,
|
|
73
|
+
frameless: bool = False,
|
|
74
|
+
show_toolbar: bool = True,
|
|
75
|
+
show_window_controls: bool = False,
|
|
76
|
+
draggable: bool = False,
|
|
77
|
+
toolbar_density: Literal['default', 'compact'] = 'default',
|
|
78
|
+
show_nav: bool = True,
|
|
79
|
+
nav_display_mode: Literal['expanded', 'compact', 'minimal'] = 'expanded',
|
|
80
|
+
nav_accent: str = 'primary',
|
|
81
|
+
**kwargs: Unpack[AppShellKwargs],
|
|
82
|
+
):
|
|
83
|
+
"""Initialize an AppShell.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
title: Title displayed in the toolbar and window title bar.
|
|
87
|
+
theme: Theme name. If None, uses the default theme.
|
|
88
|
+
size: Initial window size as (width, height).
|
|
89
|
+
position: Initial window position as (x, y).
|
|
90
|
+
minsize: Minimum window size as (width, height).
|
|
91
|
+
maxsize: Maximum window size as (width, height).
|
|
92
|
+
resizable: Whether the window is resizable as (width, height).
|
|
93
|
+
frameless: If True, remove OS window chrome (title bar, borders)
|
|
94
|
+
and rely on the toolbar for window controls and dragging.
|
|
95
|
+
Automatically enables `show_window_controls` and
|
|
96
|
+
`draggable` when True. Default False.
|
|
97
|
+
show_toolbar: Include the toolbar at the top. Default True.
|
|
98
|
+
show_window_controls: Show minimize/maximize/close buttons
|
|
99
|
+
in the toolbar. Default False.
|
|
100
|
+
draggable: Enable window dragging via the toolbar. Default False.
|
|
101
|
+
toolbar_density: Toolbar button density ('default' or 'compact').
|
|
102
|
+
show_nav: Include the sidebar navigation. Default True.
|
|
103
|
+
nav_display_mode: Initial SideNav display mode
|
|
104
|
+
('expanded', 'compact', or 'minimal'). Default 'expanded'.
|
|
105
|
+
nav_accent: Accent color for navigation selection. Default 'primary'.
|
|
106
|
+
**kwargs: Additional arguments passed to App.
|
|
107
|
+
"""
|
|
108
|
+
# Frameless mode: remove OS chrome and enable toolbar controls
|
|
109
|
+
if frameless:
|
|
110
|
+
show_window_controls = True
|
|
111
|
+
draggable = True
|
|
112
|
+
|
|
113
|
+
super().__init__(
|
|
114
|
+
title=title,
|
|
115
|
+
theme=theme,
|
|
116
|
+
size=size,
|
|
117
|
+
position=position,
|
|
118
|
+
minsize=minsize,
|
|
119
|
+
maxsize=maxsize,
|
|
120
|
+
resizable=resizable,
|
|
121
|
+
override_redirect=frameless,
|
|
122
|
+
**kwargs,
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
self._shell_title = title
|
|
126
|
+
self._show_toolbar = show_toolbar
|
|
127
|
+
self._show_nav = show_nav
|
|
128
|
+
|
|
129
|
+
# Track which nav keys have associated pages
|
|
130
|
+
self._page_keys: set[str] = set()
|
|
131
|
+
self._first_page_added = False
|
|
132
|
+
self._navigating = False # Guard against re-entrant navigation
|
|
133
|
+
|
|
134
|
+
# Build components
|
|
135
|
+
self._toolbar: Toolbar | None = None
|
|
136
|
+
self._nav: SideNav | None = None
|
|
137
|
+
self._pages: PageStack | None = None
|
|
138
|
+
|
|
139
|
+
self._build_shell(
|
|
140
|
+
show_toolbar=show_toolbar,
|
|
141
|
+
show_window_controls=show_window_controls,
|
|
142
|
+
draggable=draggable,
|
|
143
|
+
toolbar_density=toolbar_density,
|
|
144
|
+
show_nav=show_nav,
|
|
145
|
+
nav_display_mode=nav_display_mode,
|
|
146
|
+
nav_accent=nav_accent,
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
def _build_shell(
|
|
150
|
+
self,
|
|
151
|
+
*,
|
|
152
|
+
show_toolbar: bool,
|
|
153
|
+
show_window_controls: bool,
|
|
154
|
+
draggable: bool,
|
|
155
|
+
toolbar_density: str,
|
|
156
|
+
show_nav: bool,
|
|
157
|
+
nav_display_mode: str,
|
|
158
|
+
nav_accent: str,
|
|
159
|
+
):
|
|
160
|
+
"""Build the internal widget structure."""
|
|
161
|
+
# --- Toolbar ---
|
|
162
|
+
if show_toolbar:
|
|
163
|
+
self._toolbar = Toolbar(
|
|
164
|
+
self,
|
|
165
|
+
surface='chrome',
|
|
166
|
+
density=toolbar_density,
|
|
167
|
+
show_window_controls=show_window_controls,
|
|
168
|
+
draggable=draggable,
|
|
169
|
+
)
|
|
170
|
+
self._toolbar.pack(side='top', fill='x')
|
|
171
|
+
|
|
172
|
+
# Hamburger button (only when nav is present)
|
|
173
|
+
if show_nav:
|
|
174
|
+
self._toolbar.add_button(
|
|
175
|
+
icon='list',
|
|
176
|
+
command=self._toggle_nav,
|
|
177
|
+
)
|
|
178
|
+
self._toolbar.add_separator()
|
|
179
|
+
|
|
180
|
+
# Title label
|
|
181
|
+
self._title_label = None
|
|
182
|
+
if self._shell_title:
|
|
183
|
+
self._title_label = self._toolbar.add_label(text=self._shell_title, font='heading-md')
|
|
184
|
+
|
|
185
|
+
# Spacer pushes subsequent user-added buttons to the right
|
|
186
|
+
self._toolbar.add_spacer()
|
|
187
|
+
|
|
188
|
+
# --- Body (nav + pages) ---
|
|
189
|
+
body = Frame(self)
|
|
190
|
+
body.pack(side='top', fill='both', expand=True)
|
|
191
|
+
|
|
192
|
+
# --- SideNav ---
|
|
193
|
+
if show_nav:
|
|
194
|
+
# When toolbar is present, nav hides its own header and hamburger;
|
|
195
|
+
# AppShell puts the hamburger in the toolbar instead.
|
|
196
|
+
# When toolbar is absent, nav manages its own toggle.
|
|
197
|
+
self._nav = SideNav(
|
|
198
|
+
body,
|
|
199
|
+
show_header=False,
|
|
200
|
+
collapsible=not show_toolbar,
|
|
201
|
+
display_mode=nav_display_mode,
|
|
202
|
+
accent=nav_accent,
|
|
203
|
+
)
|
|
204
|
+
self._nav.pack(side='left', fill='y')
|
|
205
|
+
|
|
206
|
+
# Wire selection changes to page navigation
|
|
207
|
+
self._nav.on_selection_changed(self._on_nav_selection_changed)
|
|
208
|
+
|
|
209
|
+
# --- PageStack ---
|
|
210
|
+
self._pages = PageStack(body)
|
|
211
|
+
self._pages.pack(side='left', fill='both', expand=True)
|
|
212
|
+
|
|
213
|
+
# --- Internal Handlers ---
|
|
214
|
+
|
|
215
|
+
def _toggle_nav(self):
|
|
216
|
+
"""Toggle the SideNav pane."""
|
|
217
|
+
if self._nav is not None:
|
|
218
|
+
self._nav.toggle_pane()
|
|
219
|
+
|
|
220
|
+
def _on_nav_selection_changed(self, event):
|
|
221
|
+
"""Handle SideNav selection changes."""
|
|
222
|
+
key = event.data.get('key', '')
|
|
223
|
+
if not key or key not in self._page_keys:
|
|
224
|
+
return # Not a page item (e.g. action-only item)
|
|
225
|
+
|
|
226
|
+
if self._navigating:
|
|
227
|
+
return # Guard against re-entrant calls
|
|
228
|
+
|
|
229
|
+
self._navigating = True
|
|
230
|
+
try:
|
|
231
|
+
self._pages.navigate(key)
|
|
232
|
+
finally:
|
|
233
|
+
self._navigating = False
|
|
234
|
+
|
|
235
|
+
# --- Public API: Adding Content ---
|
|
236
|
+
|
|
237
|
+
def add_page(
|
|
238
|
+
self,
|
|
239
|
+
key: str,
|
|
240
|
+
text: str = '',
|
|
241
|
+
icon: str | dict = None,
|
|
242
|
+
page=None,
|
|
243
|
+
group: str = None,
|
|
244
|
+
is_footer: bool = False,
|
|
245
|
+
scrollable: bool = False,
|
|
246
|
+
**nav_kwargs,
|
|
247
|
+
):
|
|
248
|
+
"""Add a navigation item and its corresponding page in one call.
|
|
249
|
+
|
|
250
|
+
Args:
|
|
251
|
+
key: Unique identifier for both the nav item and the page.
|
|
252
|
+
text: Display text for the nav item.
|
|
253
|
+
icon: Icon name or configuration for the nav item.
|
|
254
|
+
page: An existing widget to use as the page. If None, a Frame
|
|
255
|
+
is created automatically.
|
|
256
|
+
group: Key of the nav group to add this item to.
|
|
257
|
+
is_footer: If True, add the nav item to the footer section.
|
|
258
|
+
scrollable: If True, the page is wrapped in a ScrollView with
|
|
259
|
+
vertical scrolling. The returned widget is the ScrollView
|
|
260
|
+
content frame, so widgets can be packed into it as usual.
|
|
261
|
+
**nav_kwargs: Additional arguments passed to the nav item.
|
|
262
|
+
|
|
263
|
+
Returns:
|
|
264
|
+
The page widget (passed or auto-created Frame). When
|
|
265
|
+
`scrollable=True`, returns the ScrollView so that children
|
|
266
|
+
are packed into the scrollable area.
|
|
267
|
+
|
|
268
|
+
Raises:
|
|
269
|
+
RuntimeError: If `show_nav=False` was set. Use
|
|
270
|
+
`shell.pages.add()` directly instead.
|
|
271
|
+
"""
|
|
272
|
+
if self._nav is None:
|
|
273
|
+
raise RuntimeError(
|
|
274
|
+
"Cannot use add_page() when show_nav=False. "
|
|
275
|
+
"Use shell.pages.add() directly instead."
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
# Add nav item
|
|
279
|
+
if is_footer:
|
|
280
|
+
self._nav.add_footer_item(key, text=text, icon=icon, **nav_kwargs)
|
|
281
|
+
elif group is not None:
|
|
282
|
+
self._nav.add_item(key, text=text, icon=icon, group=group, **nav_kwargs)
|
|
283
|
+
else:
|
|
284
|
+
self._nav.add_item(key, text=text, icon=icon, **nav_kwargs)
|
|
285
|
+
|
|
286
|
+
# Add page
|
|
287
|
+
page_widget = self._pages.add(key, page=page)
|
|
288
|
+
self._page_keys.add(key)
|
|
289
|
+
|
|
290
|
+
# Wrap in ScrollView when requested
|
|
291
|
+
if scrollable:
|
|
292
|
+
sv = ScrollView(
|
|
293
|
+
page_widget,
|
|
294
|
+
scroll_direction="vertical",
|
|
295
|
+
scrollbar_visibility="hover",
|
|
296
|
+
)
|
|
297
|
+
sv.pack(fill="both", expand=True)
|
|
298
|
+
page_widget = sv.add()
|
|
299
|
+
|
|
300
|
+
# Stretch content frame to canvas width so fill=X works
|
|
301
|
+
def _on_canvas_resize(event, _sv=sv):
|
|
302
|
+
_sv.canvas.itemconfigure(_sv._window_id, width=event.width)
|
|
303
|
+
sv.canvas.bind('<Configure>', _on_canvas_resize, add='+')
|
|
304
|
+
|
|
305
|
+
# Auto-navigate to the first page added
|
|
306
|
+
if not self._first_page_added:
|
|
307
|
+
self._first_page_added = True
|
|
308
|
+
self.navigate(key)
|
|
309
|
+
|
|
310
|
+
return page_widget
|
|
311
|
+
|
|
312
|
+
def add_group(
|
|
313
|
+
self,
|
|
314
|
+
key: str,
|
|
315
|
+
text: str = '',
|
|
316
|
+
icon: str | dict = None,
|
|
317
|
+
is_expanded: bool = False,
|
|
318
|
+
**kwargs,
|
|
319
|
+
):
|
|
320
|
+
"""Add a navigation group.
|
|
321
|
+
|
|
322
|
+
Passthrough to `nav.add_group()`.
|
|
323
|
+
|
|
324
|
+
Args:
|
|
325
|
+
key: Unique identifier for the group.
|
|
326
|
+
text: Display text.
|
|
327
|
+
icon: Icon name or configuration.
|
|
328
|
+
is_expanded: Initial expansion state.
|
|
329
|
+
**kwargs: Additional arguments passed to SideNavGroup.
|
|
330
|
+
|
|
331
|
+
Returns:
|
|
332
|
+
SideNavGroup: The created group.
|
|
333
|
+
"""
|
|
334
|
+
if self._nav is None:
|
|
335
|
+
raise RuntimeError("Cannot add groups when show_nav=False.")
|
|
336
|
+
return self._nav.add_group(key, text=text, icon=icon, is_expanded=is_expanded, **kwargs)
|
|
337
|
+
|
|
338
|
+
def add_header(self, text: str, **kwargs):
|
|
339
|
+
"""Add a section header to the navigation.
|
|
340
|
+
|
|
341
|
+
Passthrough to `nav.add_header()`.
|
|
342
|
+
|
|
343
|
+
Args:
|
|
344
|
+
text: Header text.
|
|
345
|
+
**kwargs: Additional arguments passed to SideNavHeader.
|
|
346
|
+
|
|
347
|
+
Returns:
|
|
348
|
+
SideNavHeader: The created header.
|
|
349
|
+
"""
|
|
350
|
+
if self._nav is None:
|
|
351
|
+
raise RuntimeError("Cannot add headers when show_nav=False.")
|
|
352
|
+
return self._nav.add_header(text, **kwargs)
|
|
353
|
+
|
|
354
|
+
def add_separator(self, **kwargs):
|
|
355
|
+
"""Add a separator to the navigation.
|
|
356
|
+
|
|
357
|
+
Passthrough to `nav.add_separator()`.
|
|
358
|
+
|
|
359
|
+
Args:
|
|
360
|
+
**kwargs: Additional arguments passed to SideNavSeparator.
|
|
361
|
+
|
|
362
|
+
Returns:
|
|
363
|
+
SideNavSeparator: The created separator.
|
|
364
|
+
"""
|
|
365
|
+
if self._nav is None:
|
|
366
|
+
raise RuntimeError("Cannot add separators when show_nav=False.")
|
|
367
|
+
return self._nav.add_separator(**kwargs)
|
|
368
|
+
|
|
369
|
+
# --- Public API: Navigation ---
|
|
370
|
+
|
|
371
|
+
def navigate(self, key: str, data: dict = None):
|
|
372
|
+
"""Programmatic navigation: updates nav selection and navigates PageStack.
|
|
373
|
+
|
|
374
|
+
Args:
|
|
375
|
+
key: The page key to navigate to.
|
|
376
|
+
data: Optional data to pass to the page.
|
|
377
|
+
"""
|
|
378
|
+
if self._navigating:
|
|
379
|
+
return
|
|
380
|
+
|
|
381
|
+
self._navigating = True
|
|
382
|
+
try:
|
|
383
|
+
# Update nav selection (which will NOT re-trigger navigation
|
|
384
|
+
# because we set the guard)
|
|
385
|
+
if self._nav is not None and key in self._page_keys:
|
|
386
|
+
self._nav.select(key)
|
|
387
|
+
|
|
388
|
+
# Navigate the page stack
|
|
389
|
+
if key in self._page_keys:
|
|
390
|
+
self._pages.navigate(key, data=data)
|
|
391
|
+
finally:
|
|
392
|
+
self._navigating = False
|
|
393
|
+
|
|
394
|
+
def select(self, key: str, data: dict = None):
|
|
395
|
+
"""Alias for `navigate()`.
|
|
396
|
+
|
|
397
|
+
Args:
|
|
398
|
+
key: The page key to navigate to.
|
|
399
|
+
data: Optional data to pass to the page.
|
|
400
|
+
"""
|
|
401
|
+
self.navigate(key, data=data)
|
|
402
|
+
|
|
403
|
+
# --- Public API: Event Binding ---
|
|
404
|
+
|
|
405
|
+
def on_page_changed(self, callback: Callable) -> str:
|
|
406
|
+
"""Bind to page change events on the PageStack.
|
|
407
|
+
|
|
408
|
+
Args:
|
|
409
|
+
callback: Function to call when the page changes.
|
|
410
|
+
|
|
411
|
+
Returns:
|
|
412
|
+
Binding identifier for use with `off_page_changed()`.
|
|
413
|
+
"""
|
|
414
|
+
return self._pages.on_page_changed(callback)
|
|
415
|
+
|
|
416
|
+
def off_page_changed(self, bind_id: str = None):
|
|
417
|
+
"""Unbind from page change events.
|
|
418
|
+
|
|
419
|
+
Args:
|
|
420
|
+
bind_id: The binding identifier returned by `on_page_changed()`.
|
|
421
|
+
"""
|
|
422
|
+
self._pages.off_page_changed(bind_id)
|
|
423
|
+
|
|
424
|
+
# --- Properties ---
|
|
425
|
+
|
|
426
|
+
@property
|
|
427
|
+
def toolbar(self) -> Toolbar | None:
|
|
428
|
+
"""The Toolbar widget, or None if `show_toolbar=False`."""
|
|
429
|
+
return self._toolbar
|
|
430
|
+
|
|
431
|
+
@property
|
|
432
|
+
def nav(self) -> SideNav | None:
|
|
433
|
+
"""The SideNav widget, or None if `show_nav=False`."""
|
|
434
|
+
return self._nav
|
|
435
|
+
|
|
436
|
+
@property
|
|
437
|
+
def pages(self) -> PageStack:
|
|
438
|
+
"""The PageStack widget (always present)."""
|
|
439
|
+
return self._pages
|
|
440
|
+
|
|
441
|
+
@property
|
|
442
|
+
def current_page(self) -> str | None:
|
|
443
|
+
"""The key of the currently displayed page, or None."""
|
|
444
|
+
result = self._pages.current()
|
|
445
|
+
return result[0] if result else None
|