bootstack 0.1.0__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 +157 -0
- bootstack/__main__.py +5 -0
- bootstack/_core/__init__.py +21 -0
- bootstack/_core/capabilities/__init__.py +45 -0
- bootstack/_core/capabilities/after.py +103 -0
- bootstack/_core/capabilities/bind.py +192 -0
- bootstack/_core/capabilities/bindtags.py +112 -0
- bootstack/_core/capabilities/busy.py +72 -0
- bootstack/_core/capabilities/clipboard.py +89 -0
- bootstack/_core/capabilities/focus.py +118 -0
- bootstack/_core/capabilities/grab.py +65 -0
- bootstack/_core/capabilities/grid.py +211 -0
- bootstack/_core/capabilities/localization.py +231 -0
- bootstack/_core/capabilities/pack.py +140 -0
- bootstack/_core/capabilities/place.py +113 -0
- bootstack/_core/capabilities/selection.py +136 -0
- bootstack/_core/capabilities/signals.py +244 -0
- bootstack/_core/capabilities/winfo.py +315 -0
- bootstack/_core/colorutils.py +234 -0
- bootstack/_core/exceptions.py +25 -0
- bootstack/_core/images.py +463 -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/paths.py +49 -0
- bootstack/_core/publisher.py +149 -0
- bootstack/_core/variables.py +62 -0
- bootstack/_runtime/__init__.py +3 -0
- bootstack/_runtime/app.py +930 -0
- bootstack/_runtime/base_window.py +945 -0
- bootstack/_runtime/events.py +399 -0
- bootstack/_runtime/shortcuts.py +496 -0
- bootstack/_runtime/tk_patch.py +43 -0
- bootstack/_runtime/toplevel.py +276 -0
- bootstack/_runtime/utility.py +457 -0
- bootstack/_runtime/visual_focus.py +240 -0
- bootstack/_runtime/window_utilities.py +1123 -0
- bootstack/assets/__init__.py +21 -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/button-compact.png +0 -0
- bootstack/assets/elements/button-default.png +0 -0
- bootstack/assets/elements/buttongroup-after-h-compact.png +0 -0
- bootstack/assets/elements/buttongroup-after-h-default.png +0 -0
- bootstack/assets/elements/buttongroup-after-v-compact.png +0 -0
- bootstack/assets/elements/buttongroup-after-v-default.png +0 -0
- bootstack/assets/elements/buttongroup-before-h-compact.png +0 -0
- bootstack/assets/elements/buttongroup-before-h-default.png +0 -0
- bootstack/assets/elements/buttongroup-before-v-compact.png +0 -0
- bootstack/assets/elements/buttongroup-before-v-default.png +0 -0
- bootstack/assets/elements/buttongroup-center-h-compact.png +0 -0
- bootstack/assets/elements/buttongroup-center-h-default.png +0 -0
- bootstack/assets/elements/buttongroup-center-v-compact.png +0 -0
- bootstack/assets/elements/buttongroup-center-v-default.png +0 -0
- bootstack/assets/elements/card.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-addon-compact.png +0 -0
- bootstack/assets/elements/input-addon-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/listrow-compact.png +0 -0
- bootstack/assets/elements/listrow-default.png +0 -0
- bootstack/assets/elements/manifest.toml +361 -0
- bootstack/assets/elements/menu-item.png +0 -0
- bootstack/assets/elements/navitem-compact.png +0 -0
- bootstack/assets/elements/navitem-default.png +0 -0
- bootstack/assets/elements/progressbar-h-compact.png +0 -0
- bootstack/assets/elements/progressbar-h-default.png +0 -0
- bootstack/assets/elements/progressbar-v-compact.png +0 -0
- bootstack/assets/elements/progressbar-v-default.png +0 -0
- bootstack/assets/elements/radiobutton.png +0 -0
- bootstack/assets/elements/scrollbar-horizontal.png +0 -0
- bootstack/assets/elements/scrollbar-vertical.png +0 -0
- bootstack/assets/elements/slider-handle.png +0 -0
- bootstack/assets/elements/slider-track-h.png +0 -0
- bootstack/assets/elements/slider-track-v.png +0 -0
- bootstack/assets/elements/switch-off.png +0 -0
- bootstack/assets/elements/switch-on.png +0 -0
- bootstack/assets/elements/tab-h.png +0 -0
- bootstack/assets/elements/tab-v.png +0 -0
- bootstack/assets/icons/bootstrap.ttf +0 -0
- bootstack/assets/icons/glyphmap.json +2080 -0
- bootstack/assets/icons/icon_metrics.json +12470 -0
- bootstack/assets/locales/ar/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/ar/LC_MESSAGES/bootstack.po +856 -0
- bootstack/assets/locales/bg/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/bg/LC_MESSAGES/bootstack.po +878 -0
- bootstack/assets/locales/cs/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/cs/LC_MESSAGES/bootstack.po +856 -0
- bootstack/assets/locales/da/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/da/LC_MESSAGES/bootstack.po +856 -0
- bootstack/assets/locales/de/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/de/LC_MESSAGES/bootstack.po +856 -0
- bootstack/assets/locales/en/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/en/LC_MESSAGES/bootstack.po +878 -0
- bootstack/assets/locales/es/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/es/LC_MESSAGES/bootstack.po +856 -0
- bootstack/assets/locales/fr/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/fr/LC_MESSAGES/bootstack.po +856 -0
- bootstack/assets/locales/he/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/he/LC_MESSAGES/bootstack.po +854 -0
- bootstack/assets/locales/hi/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/hi/LC_MESSAGES/bootstack.po +845 -0
- bootstack/assets/locales/it/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/it/LC_MESSAGES/bootstack.po +844 -0
- bootstack/assets/locales/ja/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/ja/LC_MESSAGES/bootstack.po +917 -0
- bootstack/assets/locales/ko/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/ko/LC_MESSAGES/bootstack.po +845 -0
- bootstack/assets/locales/nb/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/nb/LC_MESSAGES/bootstack.po +844 -0
- bootstack/assets/locales/nl/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/nl/LC_MESSAGES/bootstack.po +844 -0
- bootstack/assets/locales/pl/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/pl/LC_MESSAGES/bootstack.po +845 -0
- bootstack/assets/locales/pt/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/pt/LC_MESSAGES/bootstack.po +845 -0
- bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.po +845 -0
- bootstack/assets/locales/sl/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/sl/LC_MESSAGES/bootstack.po +845 -0
- bootstack/assets/locales/sv/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/sv/LC_MESSAGES/bootstack.po +845 -0
- bootstack/assets/locales/tr/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/tr/LC_MESSAGES/bootstack.po +845 -0
- bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.po +845 -0
- bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.mo +0 -0
- bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.po +845 -0
- bootstack/cli/__init__.py +133 -0
- bootstack/cli/__main__.py +6 -0
- bootstack/cli/add.py +395 -0
- bootstack/cli/appicon.py +285 -0
- bootstack/cli/build.py +115 -0
- bootstack/cli/config.py +313 -0
- bootstack/cli/demo.py +564 -0
- bootstack/cli/dev.py +153 -0
- bootstack/cli/doctor.py +195 -0
- bootstack/cli/icons.py +98 -0
- bootstack/cli/promote.py +120 -0
- bootstack/cli/pyinstaller.py +268 -0
- bootstack/cli/run.py +95 -0
- bootstack/cli/start.py +117 -0
- bootstack/cli/templates/__init__.py +931 -0
- bootstack/clipboard.py +48 -0
- bootstack/constants.py +318 -0
- bootstack/data/README.md +615 -0
- bootstack/data/__init__.py +78 -0
- bootstack/data/_observable.py +276 -0
- bootstack/data/base.py +780 -0
- bootstack/data/file_source.py +367 -0
- bootstack/data/memory_source.py +450 -0
- bootstack/data/query.py +367 -0
- bootstack/data/readers.py +289 -0
- bootstack/data/sqlite_source.py +869 -0
- bootstack/data/types.py +354 -0
- bootstack/data/writers.py +232 -0
- bootstack/dev/__init__.py +36 -0
- bootstack/dev/_capture.py +141 -0
- bootstack/dev/_env.py +43 -0
- bootstack/dev/_registry.py +140 -0
- bootstack/dev/_reloader.py +351 -0
- bootstack/dev/_reset.py +50 -0
- bootstack/dev/_watcher.py +91 -0
- bootstack/dialogs/__init__.py +948 -0
- bootstack/dialogs/_impl/__init__.py +47 -0
- bootstack/dialogs/_impl/colorchooser.py +588 -0
- bootstack/dialogs/_impl/datedialog.py +450 -0
- bootstack/dialogs/_impl/dialog.py +594 -0
- bootstack/dialogs/_impl/filterdialog.py +358 -0
- bootstack/dialogs/_impl/fontdialog.py +364 -0
- bootstack/dialogs/_impl/formdialog.py +564 -0
- bootstack/dialogs/_impl/message.py +486 -0
- bootstack/dialogs/_impl/query.py +570 -0
- bootstack/errors.py +67 -0
- bootstack/events/__init__.py +111 -0
- bootstack/events/_event.py +135 -0
- bootstack/events/_payloads.py +539 -0
- bootstack/events/_subscription.py +38 -0
- bootstack/i18n/README.md +77 -0
- bootstack/i18n/__init__.py +23 -0
- bootstack/i18n/catalog.py +121 -0
- bootstack/i18n/intl_format.py +584 -0
- bootstack/i18n/msgcat.py +425 -0
- bootstack/i18n/specs.py +156 -0
- bootstack/images.py +563 -0
- bootstack/py.typed +1 -0
- bootstack/scheduling/__init__.py +11 -0
- bootstack/scheduling/_schedule.py +218 -0
- bootstack/shortcuts.py +21 -0
- bootstack/signals/README.md +98 -0
- bootstack/signals/__init__.py +10 -0
- bootstack/signals/integration.py +100 -0
- bootstack/signals/signal.py +353 -0
- bootstack/signals/types.py +6 -0
- bootstack/store.py +286 -0
- bootstack/streams/__init__.py +12 -0
- bootstack/streams/_stream.py +321 -0
- bootstack/style/__init__.py +38 -0
- bootstack/style/builders/__init__.py +51 -0
- bootstack/style/builders/badge.py +46 -0
- bootstack/style/builders/button.py +339 -0
- bootstack/style/builders/buttongroup.py +311 -0
- bootstack/style/builders/calendar.py +271 -0
- bootstack/style/builders/checkbutton.py +110 -0
- bootstack/style/builders/combobox.py +113 -0
- bootstack/style/builders/contextmenu.py +268 -0
- bootstack/style/builders/entry.py +82 -0
- bootstack/style/builders/expander.py +148 -0
- bootstack/style/builders/field.py +335 -0
- bootstack/style/builders/frame.py +50 -0
- bootstack/style/builders/label.py +28 -0
- bootstack/style/builders/labelframe.py +34 -0
- bootstack/style/builders/listview.py +369 -0
- bootstack/style/builders/menubar.py +91 -0
- bootstack/style/builders/menubutton.py +359 -0
- bootstack/style/builders/panedwindow.py +25 -0
- bootstack/style/builders/progressbar.py +67 -0
- bootstack/style/builders/radiobutton.py +99 -0
- bootstack/style/builders/scale.py +64 -0
- bootstack/style/builders/scrollbar.py +225 -0
- bootstack/style/builders/separator.py +49 -0
- bootstack/style/builders/sidenav.py +643 -0
- bootstack/style/builders/sizegrip.py +15 -0
- bootstack/style/builders/spinbox.py +119 -0
- bootstack/style/builders/switch.py +70 -0
- bootstack/style/builders/tabitem.py +204 -0
- bootstack/style/builders/togglegroup.py +294 -0
- bootstack/style/builders/toolbutton.py +275 -0
- bootstack/style/builders/tooltip.py +26 -0
- bootstack/style/builders/treeview.py +193 -0
- bootstack/style/builders/utils.py +455 -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/fonts.py +123 -0
- bootstack/style/style.py +609 -0
- bootstack/style/style_builder_base.py +716 -0
- bootstack/style/style_builder_mixed.py +93 -0
- bootstack/style/style_builder_tk.py +109 -0
- bootstack/style/style_builder_ttk.py +353 -0
- bootstack/style/style_resolver.py +447 -0
- bootstack/style/theme.py +245 -0
- bootstack/style/theme_provider.py +471 -0
- bootstack/style/themes/__init__.py +128 -0
- bootstack/style/tk_patch.py +5 -0
- bootstack/style/token_maps.py +41 -0
- bootstack/style/types.py +32 -0
- bootstack/style/typography.py +523 -0
- bootstack/style/utility.py +746 -0
- bootstack/types.py +39 -0
- bootstack/validation/__init__.py +6 -0
- bootstack/validation/types.py +15 -0
- bootstack/validation/validation_result.py +17 -0
- bootstack/validation/validation_rules.py +205 -0
- bootstack/widgets/__init__.py +74 -0
- bootstack/widgets/_core/__init__.py +31 -0
- bootstack/widgets/_core/app_config.py +266 -0
- bootstack/widgets/_core/base.py +461 -0
- bootstack/widgets/_core/container.py +334 -0
- bootstack/widgets/_core/context.py +35 -0
- bootstack/widgets/_core/events.py +130 -0
- bootstack/widgets/_core/field_mixin.py +353 -0
- bootstack/widgets/_core/icon_image_props.py +72 -0
- bootstack/widgets/_core/image_binding.py +93 -0
- bootstack/widgets/_core/navmodel.py +345 -0
- bootstack/widgets/_core/options.py +210 -0
- bootstack/widgets/_core/selection_group.py +130 -0
- bootstack/widgets/_core/window_controls.py +96 -0
- bootstack/widgets/_core/window_menu.py +246 -0
- bootstack/widgets/_impl/__init__.py +1 -0
- bootstack/widgets/_impl/_internal/__init__.py +0 -0
- bootstack/widgets/_impl/_internal/wrapper_base.py +307 -0
- bootstack/widgets/_impl/_parts/__init__.py +11 -0
- bootstack/widgets/_impl/_parts/numberentry_part.py +385 -0
- bootstack/widgets/_impl/_parts/spinnerentry_part.py +434 -0
- bootstack/widgets/_impl/_parts/textentry_part.py +406 -0
- bootstack/widgets/_impl/composites/__init__.py +33 -0
- bootstack/widgets/_impl/composites/_dateutils.py +33 -0
- bootstack/widgets/_impl/composites/_image_fit.py +105 -0
- bootstack/widgets/_impl/composites/accordion.py +381 -0
- bootstack/widgets/_impl/composites/avatar.py +191 -0
- bootstack/widgets/_impl/composites/buttongroup.py +371 -0
- bootstack/widgets/_impl/composites/calendar.py +972 -0
- bootstack/widgets/_impl/composites/carousel.py +567 -0
- bootstack/widgets/_impl/composites/chart.py +882 -0
- bootstack/widgets/_impl/composites/compositeframe.py +298 -0
- bootstack/widgets/_impl/composites/contextmenu.py +1951 -0
- bootstack/widgets/_impl/composites/dateentry.py +404 -0
- bootstack/widgets/_impl/composites/dropdownbutton.py +325 -0
- bootstack/widgets/_impl/composites/expander.py +515 -0
- bootstack/widgets/_impl/composites/field.py +670 -0
- bootstack/widgets/_impl/composites/form.py +1066 -0
- bootstack/widgets/_impl/composites/gallery.py +551 -0
- bootstack/widgets/_impl/composites/list/__init__.py +15 -0
- bootstack/widgets/_impl/composites/list/listitem.py +802 -0
- bootstack/widgets/_impl/composites/list/listview.py +1433 -0
- bootstack/widgets/_impl/composites/menu/__init__.py +18 -0
- bootstack/widgets/_impl/composites/menu/model.py +358 -0
- bootstack/widgets/_impl/composites/menu/render_native.py +134 -0
- bootstack/widgets/_impl/composites/menu/render_themed.py +134 -0
- bootstack/widgets/_impl/composites/meter.py +860 -0
- bootstack/widgets/_impl/composites/numericentry.py +201 -0
- bootstack/widgets/_impl/composites/pagestack.py +395 -0
- bootstack/widgets/_impl/composites/passwordentry.py +142 -0
- bootstack/widgets/_impl/composites/pathentry.py +168 -0
- bootstack/widgets/_impl/composites/picture.py +289 -0
- bootstack/widgets/_impl/composites/radiogroup.py +511 -0
- bootstack/widgets/_impl/composites/scrolledtext.py +375 -0
- bootstack/widgets/_impl/composites/scrolledtext.pyi +186 -0
- bootstack/widgets/_impl/composites/scrollview.py +764 -0
- bootstack/widgets/_impl/composites/selectbox.py +1026 -0
- bootstack/widgets/_impl/composites/shell/__init__.py +40 -0
- bootstack/widgets/_impl/composites/shell/content_host.py +52 -0
- bootstack/widgets/_impl/composites/shell/layout.py +335 -0
- bootstack/widgets/_impl/composites/shell/nav_panel.py +345 -0
- bootstack/widgets/_impl/composites/shell/providers.py +558 -0
- bootstack/widgets/_impl/composites/shell/rail.py +117 -0
- bootstack/widgets/_impl/composites/shell/shell.py +581 -0
- bootstack/widgets/_impl/composites/shell/workspace.py +273 -0
- bootstack/widgets/_impl/composites/sidenav/__init__.py +16 -0
- bootstack/widgets/_impl/composites/sidenav/header.py +81 -0
- bootstack/widgets/_impl/composites/sidenav/separator.py +44 -0
- bootstack/widgets/_impl/composites/slider/__init__.py +7 -0
- bootstack/widgets/_impl/composites/slider/_shared.py +195 -0
- bootstack/widgets/_impl/composites/slider/rangeslider.py +982 -0
- bootstack/widgets/_impl/composites/slider/slider.py +851 -0
- bootstack/widgets/_impl/composites/spinnerentry.py +185 -0
- bootstack/widgets/_impl/composites/tableview/__init__.py +5 -0
- bootstack/widgets/_impl/composites/tableview/tableview.py +3388 -0
- bootstack/widgets/_impl/composites/tableview/types.py +169 -0
- bootstack/widgets/_impl/composites/tabs/__init__.py +23 -0
- bootstack/widgets/_impl/composites/tabs/tabitem.py +389 -0
- bootstack/widgets/_impl/composites/tabs/tabs.py +974 -0
- bootstack/widgets/_impl/composites/tabs/tabview.py +650 -0
- bootstack/widgets/_impl/composites/textarea/__init__.py +26 -0
- bootstack/widgets/_impl/composites/textarea/change.py +46 -0
- bootstack/widgets/_impl/composites/textarea/codeeditor.py +526 -0
- bootstack/widgets/_impl/composites/textarea/core.py +495 -0
- bootstack/widgets/_impl/composites/textarea/decoration.py +42 -0
- bootstack/widgets/_impl/composites/textarea/diff.py +127 -0
- bootstack/widgets/_impl/composites/textarea/extensions/__init__.py +1 -0
- bootstack/widgets/_impl/composites/textarea/extensions/bracket_matcher.py +138 -0
- bootstack/widgets/_impl/composites/textarea/extensions/indent_guides.py +158 -0
- bootstack/widgets/_impl/composites/textarea/extensions/line_numbers.py +138 -0
- bootstack/widgets/_impl/composites/textarea/extensions/pygments_highlighter.py +312 -0
- bootstack/widgets/_impl/composites/textarea/extensions/smart_indent.py +177 -0
- bootstack/widgets/_impl/composites/textarea/filter.py +171 -0
- bootstack/widgets/_impl/composites/textarea/search_overlay.py +459 -0
- bootstack/widgets/_impl/composites/textarea/sidebar.py +88 -0
- bootstack/widgets/_impl/composites/textarea/style_registry.py +178 -0
- bootstack/widgets/_impl/composites/textarea/textarea.py +606 -0
- bootstack/widgets/_impl/composites/textarea/undo.py +217 -0
- bootstack/widgets/_impl/composites/textentry.py +57 -0
- bootstack/widgets/_impl/composites/timeentry.py +176 -0
- bootstack/widgets/_impl/composites/toast.py +390 -0
- bootstack/widgets/_impl/composites/toast_stack.py +156 -0
- bootstack/widgets/_impl/composites/togglegroup.py +418 -0
- bootstack/widgets/_impl/composites/toolbar.py +608 -0
- bootstack/widgets/_impl/composites/tooltip.py +491 -0
- bootstack/widgets/_impl/composites/tree/__init__.py +7 -0
- bootstack/widgets/_impl/composites/tree/source_binding.py +136 -0
- bootstack/widgets/_impl/composites/tree/treeitem.py +393 -0
- bootstack/widgets/_impl/composites/tree/treenode.py +174 -0
- bootstack/widgets/_impl/composites/tree/treeview.py +841 -0
- bootstack/widgets/_impl/mixins/__init__.py +24 -0
- bootstack/widgets/_impl/mixins/configure_mixin.py +216 -0
- bootstack/widgets/_impl/mixins/entry_mixin.py +134 -0
- bootstack/widgets/_impl/mixins/font_mixin.py +368 -0
- bootstack/widgets/_impl/mixins/icon_mixin.py +61 -0
- bootstack/widgets/_impl/mixins/localization_mixin.py +253 -0
- bootstack/widgets/_impl/mixins/signal_mixin.py +268 -0
- bootstack/widgets/_impl/mixins/validation_mixin.py +226 -0
- bootstack/widgets/_impl/primitives/__init__.py +49 -0
- bootstack/widgets/_impl/primitives/_menubutton.py +107 -0
- bootstack/widgets/_impl/primitives/badge.py +45 -0
- bootstack/widgets/_impl/primitives/button.py +76 -0
- bootstack/widgets/_impl/primitives/card.py +45 -0
- bootstack/widgets/_impl/primitives/checkbutton.py +124 -0
- bootstack/widgets/_impl/primitives/checktoggle.py +62 -0
- bootstack/widgets/_impl/primitives/combobox.py +156 -0
- bootstack/widgets/_impl/primitives/entry.py +87 -0
- bootstack/widgets/_impl/primitives/flexframe.py +448 -0
- bootstack/widgets/_impl/primitives/frame.py +185 -0
- bootstack/widgets/_impl/primitives/gridframe.py +546 -0
- bootstack/widgets/_impl/primitives/label.py +84 -0
- bootstack/widgets/_impl/primitives/labelframe.py +54 -0
- bootstack/widgets/_impl/primitives/optionmenu.py +387 -0
- bootstack/widgets/_impl/primitives/packframe.py +227 -0
- bootstack/widgets/_impl/primitives/panedwindow.py +45 -0
- bootstack/widgets/_impl/primitives/progressbar.py +83 -0
- bootstack/widgets/_impl/primitives/radiobutton.py +115 -0
- bootstack/widgets/_impl/primitives/radiotoggle.py +54 -0
- bootstack/widgets/_impl/primitives/scrollbar.py +42 -0
- bootstack/widgets/_impl/primitives/separator.py +43 -0
- bootstack/widgets/_impl/primitives/sizegrip.py +33 -0
- bootstack/widgets/_impl/primitives/spinbox.py +95 -0
- bootstack/widgets/_impl/primitives/switch.py +44 -0
- bootstack/widgets/_impl/primitives/treeview.py +69 -0
- bootstack/widgets/app.py +371 -0
- bootstack/widgets/appshell.py +1179 -0
- bootstack/widgets/avatar.py +140 -0
- bootstack/widgets/boolean_controls.py +455 -0
- bootstack/widgets/button.py +224 -0
- bootstack/widgets/buttongroup.py +239 -0
- bootstack/widgets/calendar.py +195 -0
- bootstack/widgets/card.py +159 -0
- bootstack/widgets/carousel.py +241 -0
- bootstack/widgets/chart.py +302 -0
- bootstack/widgets/codeeditor.py +675 -0
- bootstack/widgets/contextmenu.py +371 -0
- bootstack/widgets/datatable.py +688 -0
- bootstack/widgets/datefield.py +395 -0
- bootstack/widgets/divider.py +60 -0
- bootstack/widgets/expander.py +579 -0
- bootstack/widgets/form.py +200 -0
- bootstack/widgets/gallery.py +250 -0
- bootstack/widgets/gauge.py +168 -0
- bootstack/widgets/grid.py +121 -0
- bootstack/widgets/groupbox.py +162 -0
- bootstack/widgets/label.py +229 -0
- bootstack/widgets/listview.py +354 -0
- bootstack/widgets/menubutton.py +419 -0
- bootstack/widgets/numberfield.py +431 -0
- bootstack/widgets/pagestack.py +345 -0
- bootstack/widgets/passwordfield.py +383 -0
- bootstack/widgets/pathfield.py +454 -0
- bootstack/widgets/picture.py +251 -0
- bootstack/widgets/progressbar.py +106 -0
- bootstack/widgets/radio_variants.py +271 -0
- bootstack/widgets/radiogroup.py +228 -0
- bootstack/widgets/scrollbar.py +64 -0
- bootstack/widgets/scrollview.py +186 -0
- bootstack/widgets/select.py +302 -0
- bootstack/widgets/selectbutton.py +182 -0
- bootstack/widgets/sidebar_toggle.py +130 -0
- bootstack/widgets/sizegrip.py +42 -0
- bootstack/widgets/slider.py +408 -0
- bootstack/widgets/spinbox.py +147 -0
- bootstack/widgets/spinnerfield.py +413 -0
- bootstack/widgets/splash.py +367 -0
- bootstack/widgets/splitview.py +482 -0
- bootstack/widgets/stacks.py +249 -0
- bootstack/widgets/statusbar.py +189 -0
- bootstack/widgets/tabs.py +425 -0
- bootstack/widgets/textarea.py +459 -0
- bootstack/widgets/textfield.py +410 -0
- bootstack/widgets/theme_toggle.py +92 -0
- bootstack/widgets/timefield.py +340 -0
- bootstack/widgets/toast.py +314 -0
- bootstack/widgets/togglegroup.py +231 -0
- bootstack/widgets/toolbar.py +347 -0
- bootstack/widgets/tooltip.py +94 -0
- bootstack/widgets/tree.py +648 -0
- bootstack/widgets/types.py +305 -0
- bootstack/widgets/window.py +307 -0
- bootstack-0.1.0.dist-info/METADATA +301 -0
- bootstack-0.1.0.dist-info/RECORD +471 -0
- bootstack-0.1.0.dist-info/WHEEL +5 -0
- bootstack-0.1.0.dist-info/entry_points.txt +2 -0
- bootstack-0.1.0.dist-info/licenses/LICENSE +21 -0
- bootstack-0.1.0.dist-info/licenses/NOTICE +10 -0
- bootstack-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any, TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from typing_extensions import TypedDict
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from typing_extensions import Unpack
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class BusyKwargs(TypedDict, total=False):
|
|
12
|
+
"""Keyword options accepted by busy-mode operations."""
|
|
13
|
+
cursor: str
|
|
14
|
+
"""Cursor to display while busy mode is active (e.g., `'wait'`, `'watch'`)."""
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class BusyMixin:
|
|
18
|
+
"""Busy (input-blocking) helpers (busy).
|
|
19
|
+
|
|
20
|
+
Tk's *busy* facility blocks pointer events from reaching a widget/window by
|
|
21
|
+
placing an input-only window above it. This is typically used to prevent
|
|
22
|
+
user interaction during a long-running operation (e.g., loading, saving).
|
|
23
|
+
|
|
24
|
+
Notes:
|
|
25
|
+
- Busy blocks pointer events; it does not guarantee keyboard events are blocked.
|
|
26
|
+
- Always release busy state in a `finally:` block (or use a context manager).
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
def busy_hold(self, **kw: Unpack[BusyKwargs]) -> None:
|
|
30
|
+
"""Activate busy mode for this widget/window.
|
|
31
|
+
|
|
32
|
+
While busy is active, pointer events are intercepted so the user cannot
|
|
33
|
+
interact with the target window (and typically its children).
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
**kw: See `BusyKwargs`. Use `cursor` to set the busy cursor.
|
|
37
|
+
"""
|
|
38
|
+
return super().busy_hold(**kw) # type: ignore[misc]
|
|
39
|
+
|
|
40
|
+
def busy_forget(self) -> None:
|
|
41
|
+
"""Deactivate busy mode for this widget/window."""
|
|
42
|
+
return super().busy_forget() # type: ignore[misc]
|
|
43
|
+
|
|
44
|
+
def busy_status(self) -> bool:
|
|
45
|
+
"""Return True if this widget/window is currently in busy mode."""
|
|
46
|
+
return bool(super().busy_status()) # type: ignore[misc]
|
|
47
|
+
|
|
48
|
+
def busy_configure(self, **kw: Unpack[BusyKwargs]) -> Any:
|
|
49
|
+
"""Query or configure busy options for this widget/window.
|
|
50
|
+
|
|
51
|
+
With no options, returns configuration information (format depends on Tk).
|
|
52
|
+
With options provided, updates the busy configuration.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
**kw: See `BusyKwargs`.
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
The raw Tk result for the configure query/set.
|
|
59
|
+
"""
|
|
60
|
+
return super().busy_configure(**kw) # type: ignore[misc]
|
|
61
|
+
|
|
62
|
+
def busy_cget(self, option: str) -> Any:
|
|
63
|
+
"""Return the current value of a single busy option.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
option: Option name (e.g., `'cursor'` or `'-cursor'`).
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
The option value.
|
|
70
|
+
"""
|
|
71
|
+
opt = option if option.startswith("-") else f"-{option}"
|
|
72
|
+
return super().busy_cget(opt) # type: ignore[misc]
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any, TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from typing_extensions import TypedDict
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from typing_extensions import Unpack
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ClipboardKwargs(TypedDict, total=False):
|
|
12
|
+
"""Keyword options accepted by clipboard operations."""
|
|
13
|
+
displayof: Any
|
|
14
|
+
"""Widget or window whose display to target. Omit for the main application display."""
|
|
15
|
+
type: str
|
|
16
|
+
"""Clipboard type name (e.g., `'STRING'`, `'UTF8_STRING'`). Platform-dependent."""
|
|
17
|
+
format: str
|
|
18
|
+
"""Data format for representing selection data to the X server (e.g., `'STRING'`). Platform-dependent."""
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ClipboardMixin:
|
|
22
|
+
"""Clipboard helpers (clipboard).
|
|
23
|
+
|
|
24
|
+
Tk's `clipboard` command provides access to the system (or Tk-managed) clipboard.
|
|
25
|
+
Tkinter exposes this via the `clipboard_*` methods.
|
|
26
|
+
|
|
27
|
+
Notes:
|
|
28
|
+
- Clipboard behavior can vary by platform and window system.
|
|
29
|
+
- Most apps only need text clipboard operations (clear/append/get).
|
|
30
|
+
- For advanced cases (multiple clipboard types, non-text formats), Tk supports
|
|
31
|
+
additional options passed via `ClipboardKwargs`.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
def clipboard_clear(self, **kw: Unpack[ClipboardKwargs]) -> None:
|
|
35
|
+
"""Clear the clipboard on the target display.
|
|
36
|
+
|
|
37
|
+
This removes all data from the clipboard for the specified display.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
**kw: See `ClipboardKwargs`. The `displayof` key targets a specific display.
|
|
41
|
+
"""
|
|
42
|
+
return super().clipboard_clear(**kw) # type: ignore[misc]
|
|
43
|
+
|
|
44
|
+
def clipboard_append(self, string: str, **kw: Unpack[ClipboardKwargs]) -> None:
|
|
45
|
+
"""Append text to the clipboard.
|
|
46
|
+
|
|
47
|
+
Appends *string* to the clipboard. To replace clipboard contents,
|
|
48
|
+
call `clipboard_clear()` first.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
string: Text to append to the clipboard.
|
|
52
|
+
**kw: See `ClipboardKwargs`. Use `type` and `format` for non-text data.
|
|
53
|
+
"""
|
|
54
|
+
return super().clipboard_append(string, **kw) # type: ignore[misc]
|
|
55
|
+
|
|
56
|
+
def clipboard_get(self, **kw: Unpack[ClipboardKwargs]) -> str:
|
|
57
|
+
"""Return clipboard contents as text.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
**kw: See `ClipboardKwargs`. Use `type="UTF8_STRING"` to retrieve UTF-8 data.
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
The clipboard contents as a string.
|
|
64
|
+
|
|
65
|
+
Raises:
|
|
66
|
+
tkinter.TclError: If the clipboard is empty or cannot be converted to the
|
|
67
|
+
requested type.
|
|
68
|
+
"""
|
|
69
|
+
return super().clipboard_get(**kw) # type: ignore[misc]
|
|
70
|
+
|
|
71
|
+
# -------------------------------------------------------------------------
|
|
72
|
+
# Convenience helpers
|
|
73
|
+
# -------------------------------------------------------------------------
|
|
74
|
+
|
|
75
|
+
def clipboard_set(self, text: str, **kw: Unpack[ClipboardKwargs]) -> None:
|
|
76
|
+
"""Replace clipboard contents with *text*.
|
|
77
|
+
|
|
78
|
+
Convenience wrapper for `clipboard_clear()` + `clipboard_append()`.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
text: Text to set on the clipboard.
|
|
82
|
+
**kw: See `ClipboardKwargs`. Forwarded to both clear and append.
|
|
83
|
+
"""
|
|
84
|
+
self.clipboard_clear(**kw)
|
|
85
|
+
self.clipboard_append(text, **kw)
|
|
86
|
+
|
|
87
|
+
def clipboard_get_text(self, **kw: Unpack[ClipboardKwargs]) -> str:
|
|
88
|
+
"""Return clipboard contents as text (alias for `clipboard_get`)."""
|
|
89
|
+
return self.clipboard_get(**kw)
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"""Focus management capabilities mixin for bootstack widgets."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class FocusMixin:
|
|
8
|
+
"""Keyboard focus helpers (focus).
|
|
9
|
+
|
|
10
|
+
Tk's *input focus* determines which widget receives key press/release events.
|
|
11
|
+
Focus is typically managed by the window manager at the top-level window level,
|
|
12
|
+
and then by the application within the top-level.
|
|
13
|
+
|
|
14
|
+
Tk remembers the most recent focused descendant for each top-level. When the
|
|
15
|
+
window manager gives focus to a top-level, Tk redirects it to that remembered
|
|
16
|
+
widget automatically.
|
|
17
|
+
|
|
18
|
+
Notes:
|
|
19
|
+
- Prefer `focus_set()` for normal use.
|
|
20
|
+
- `focus_force()` can steal focus and should be used sparingly.
|
|
21
|
+
- Tab/Shift-Tab traversal typically uses `tk_focusNext()` / `tk_focusPrev()`.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
# -------------------------------------------------------------------------
|
|
25
|
+
# Core focus operations
|
|
26
|
+
# -------------------------------------------------------------------------
|
|
27
|
+
|
|
28
|
+
def focus_get(self) -> Any:
|
|
29
|
+
"""Return the widget in this application that currently has focus.
|
|
30
|
+
|
|
31
|
+
This queries the focus window on the display containing the application's
|
|
32
|
+
main window. If no window in this application has focus on that display,
|
|
33
|
+
the return value is None / empty (depending on Tkinter/Tk behavior).
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
The focused widget instance, or None if no widget in this application
|
|
37
|
+
currently has focus on the relevant display.
|
|
38
|
+
"""
|
|
39
|
+
return super().focus_get() # type: ignore[misc]
|
|
40
|
+
|
|
41
|
+
def focus_set(self, *, visual_focus: bool = False) -> None:
|
|
42
|
+
"""Request focus for this widget.
|
|
43
|
+
|
|
44
|
+
If this application currently has the focus on the widget's display, this
|
|
45
|
+
resets the focus for that display to this widget. Otherwise, Tk remembers
|
|
46
|
+
this widget as the focus for its top-level and will redirect focus to it
|
|
47
|
+
the next time the top-level receives focus.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
visual_focus: If True, show focus ring as if focused via keyboard
|
|
51
|
+
(Tab navigation). Default is False, which shows no focus ring
|
|
52
|
+
for programmatic focus. Useful for validation errors where you
|
|
53
|
+
want to draw attention to a field.
|
|
54
|
+
"""
|
|
55
|
+
return super().focus_set(visual_focus=visual_focus) # type: ignore[misc]
|
|
56
|
+
|
|
57
|
+
def focus_force(self, *, visual_focus: bool = False) -> None:
|
|
58
|
+
"""Force focus to this widget (use sparingly).
|
|
59
|
+
|
|
60
|
+
This attempts to set the focus for the widget's display even if the
|
|
61
|
+
application does not currently have the input focus for that display.
|
|
62
|
+
In normal usage, applications should not claim focus; they should wait
|
|
63
|
+
for the window manager/user to give it focus.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
visual_focus: If True, show focus ring as if focused via keyboard
|
|
67
|
+
(Tab navigation). Default is False, which shows no focus ring
|
|
68
|
+
for programmatic focus.
|
|
69
|
+
"""
|
|
70
|
+
return super().focus_force(visual_focus=visual_focus) # type: ignore[misc]
|
|
71
|
+
|
|
72
|
+
def focus_displayof(self) -> Any:
|
|
73
|
+
"""Return the focused widget for the display containing this widget.
|
|
74
|
+
|
|
75
|
+
If the focus window for this widget's display is not in this application,
|
|
76
|
+
the return value is None / empty (depending on Tkinter/Tk behavior).
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
The focused widget instance for this display, or None.
|
|
80
|
+
"""
|
|
81
|
+
return super().focus_displayof() # type: ignore[misc]
|
|
82
|
+
|
|
83
|
+
def focus_lastfor(self) -> Any:
|
|
84
|
+
"""Return the most recent focused widget within this widget's top-level.
|
|
85
|
+
|
|
86
|
+
Tk tracks the most recent focus window for each top-level. This returns
|
|
87
|
+
the widget that will receive focus the next time the top-level gets focus
|
|
88
|
+
from the window manager. If none has ever had focus (or it was deleted),
|
|
89
|
+
Tk returns the top-level itself.
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
The most recent focused widget in the same top-level, or the top-level.
|
|
93
|
+
"""
|
|
94
|
+
return super().focus_lastfor() # type: ignore[misc]
|
|
95
|
+
|
|
96
|
+
# -------------------------------------------------------------------------
|
|
97
|
+
# Focus traversal (Tab order utilities)
|
|
98
|
+
# -------------------------------------------------------------------------
|
|
99
|
+
|
|
100
|
+
def tk_focusNext(self) -> Any:
|
|
101
|
+
"""Return the next widget in the focus traversal order.
|
|
102
|
+
|
|
103
|
+
This is used by default bindings for Tab traversal in many Tk widgets.
|
|
104
|
+
|
|
105
|
+
Returns:
|
|
106
|
+
The next widget in focus order, or this widget if no other is eligible.
|
|
107
|
+
"""
|
|
108
|
+
return super().tk_focusNext() # type: ignore[misc]
|
|
109
|
+
|
|
110
|
+
def tk_focusPrev(self) -> Any:
|
|
111
|
+
"""Return the previous widget in the focus traversal order.
|
|
112
|
+
|
|
113
|
+
This is used by default bindings for Shift-Tab traversal in many Tk widgets.
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
The previous widget in focus order, or this widget if no other is eligible.
|
|
117
|
+
"""
|
|
118
|
+
return super().tk_focusPrev() # type: ignore[misc]
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class GrabMixin:
|
|
7
|
+
"""Pointer/keyboard grab helpers (grab).
|
|
8
|
+
|
|
9
|
+
A *grab* confines mouse and keyboard events to a particular widget subtree.
|
|
10
|
+
|
|
11
|
+
When a grab is active:
|
|
12
|
+
- Pointer events are delivered only to the grab window and its descendants.
|
|
13
|
+
- Keyboard events are also directed to the grab window (effectively focusing input).
|
|
14
|
+
- This is the foundation for *modal* interactions (e.g., modal dialogs).
|
|
15
|
+
|
|
16
|
+
Tk supports two kinds of grabs:
|
|
17
|
+
- **Local (application) grab**: confines events within the current Tk application.
|
|
18
|
+
- **Global grab**: confines events at the window system level (more intrusive).
|
|
19
|
+
|
|
20
|
+
Notes:
|
|
21
|
+
- Grabs should be released when you are done (typically in a `finally:` block).
|
|
22
|
+
- Global grabs can make the entire desktop feel “stuck” if misused; prefer local grabs
|
|
23
|
+
unless you specifically need global behavior.
|
|
24
|
+
- A grab does not automatically make a window modal; typical modal patterns also:
|
|
25
|
+
`transient(parent)`, `focus_set()`, and `wait_window()` / `wait_visibility()`.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def grab_set(self) -> None:
|
|
29
|
+
"""Set a local (application) grab on this widget.
|
|
30
|
+
|
|
31
|
+
With a local grab, events are confined within the current Tk application.
|
|
32
|
+
This is the preferred grab type for modal dialogs inside an application.
|
|
33
|
+
"""
|
|
34
|
+
return super().grab_set() # type: ignore[misc]
|
|
35
|
+
|
|
36
|
+
def grab_set_global(self) -> None:
|
|
37
|
+
"""Set a global grab on this widget.
|
|
38
|
+
|
|
39
|
+
A global grab confines events at the window system level. This is more
|
|
40
|
+
intrusive than a local grab and should be used with care.
|
|
41
|
+
"""
|
|
42
|
+
return super().grab_set_global() # type: ignore[misc]
|
|
43
|
+
|
|
44
|
+
def grab_release(self) -> None:
|
|
45
|
+
"""Release a grab held by this widget (if any)."""
|
|
46
|
+
return super().grab_release() # type: ignore[misc]
|
|
47
|
+
|
|
48
|
+
def grab_current(self) -> Any:
|
|
49
|
+
"""Return the widget in this application that currently holds the grab.
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
The widget instance that currently holds the grab, or None if
|
|
53
|
+
no grab is held by this application.
|
|
54
|
+
"""
|
|
55
|
+
return super().grab_current() # type: ignore[misc]
|
|
56
|
+
|
|
57
|
+
def grab_status(self) -> str | None:
|
|
58
|
+
"""Return the grab status for this widget.
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
The grab status: "local" if this widget holds a local grab,
|
|
62
|
+
"global" if this widget holds a global grab, or None if
|
|
63
|
+
this widget does not hold the grab.
|
|
64
|
+
"""
|
|
65
|
+
return super().grab_status() # type: ignore[misc]
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
"""Grid geometry manager capabilities mixin for bootstack widgets."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from typing import Any, TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
from typing_extensions import TypedDict
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from typing_extensions import Self, Unpack
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class GridKwargs(TypedDict, total=False):
|
|
13
|
+
"""Keyword options for `grid()` and `grid_configure()`."""
|
|
14
|
+
row: int
|
|
15
|
+
"""Row index (0-based). Defaults to the next available row."""
|
|
16
|
+
column: int
|
|
17
|
+
"""Column index (0-based). Defaults to 0."""
|
|
18
|
+
rowspan: int
|
|
19
|
+
"""Number of rows to span. Defaults to 1."""
|
|
20
|
+
columnspan: int
|
|
21
|
+
"""Number of columns to span. Defaults to 1."""
|
|
22
|
+
sticky: str
|
|
23
|
+
"""How the widget expands within its cell (e.g., `'nsew'`, `'ew'`, `'n'`). Defaults to `''`."""
|
|
24
|
+
padx: int | tuple[int, int]
|
|
25
|
+
"""Horizontal external padding in pixels. A tuple sets (left, right) independently."""
|
|
26
|
+
pady: int | tuple[int, int]
|
|
27
|
+
"""Vertical external padding in pixels. A tuple sets (top, bottom) independently."""
|
|
28
|
+
ipadx: int
|
|
29
|
+
"""Horizontal internal padding in pixels."""
|
|
30
|
+
ipady: int
|
|
31
|
+
"""Vertical internal padding in pixels."""
|
|
32
|
+
in_: Any
|
|
33
|
+
"""Parent widget to grid into (rarely needed — defaults to the widget's own master)."""
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class GridRowColumnKwargs(TypedDict, total=False):
|
|
37
|
+
"""Keyword options for `grid_rowconfigure()` and `grid_columnconfigure()`."""
|
|
38
|
+
weight: int
|
|
39
|
+
"""How extra space is distributed among rows/columns. 0 means no expansion. Defaults to 0."""
|
|
40
|
+
minsize: int
|
|
41
|
+
"""Minimum row/column size in pixels. Defaults to 0."""
|
|
42
|
+
pad: int
|
|
43
|
+
"""Extra padding added to the row/column in pixels. Defaults to 0."""
|
|
44
|
+
uniform: str
|
|
45
|
+
"""Group name — rows/columns sharing a group are given equal size."""
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class GridMixin:
|
|
49
|
+
"""Grid geometry manager helpers (grid).
|
|
50
|
+
|
|
51
|
+
Tk's `grid` geometry manager arranges widgets in a table of rows and columns.
|
|
52
|
+
|
|
53
|
+
In bootstack v2 you may prefer higher-level layout containers (e.g. `GridFrame`)
|
|
54
|
+
for most UI layout. This mixin documents the underlying Tkinter `grid_*` API
|
|
55
|
+
as an escape hatch and for interoperability with existing Tk code.
|
|
56
|
+
|
|
57
|
+
Notes:
|
|
58
|
+
- `grid()` attaches a widget to a parent container that is using grid.
|
|
59
|
+
- `grid_rowconfigure()` / `grid_columnconfigure()` set sizing behavior.
|
|
60
|
+
- `grid_propagate(False)` prevents a container from resizing to fit its children.
|
|
61
|
+
- If the parent has a `_on_child_grid` hook (e.g. GridFrame), layout defaults
|
|
62
|
+
are applied automatically.
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
# -------------------------------------------------------------------------
|
|
66
|
+
# Core widget methods
|
|
67
|
+
# -------------------------------------------------------------------------
|
|
68
|
+
|
|
69
|
+
def grid(self, cnf: dict[str, Any] | None = None, **kw: Unpack[GridKwargs]) -> Self:
|
|
70
|
+
"""Position this widget using the grid geometry manager.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
cnf: Optional dict of grid options (same keys as `GridKwargs`).
|
|
74
|
+
**kw: See `GridKwargs`.
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
Self for method chaining.
|
|
78
|
+
"""
|
|
79
|
+
options = cnf or {}
|
|
80
|
+
options.update(kw)
|
|
81
|
+
|
|
82
|
+
parent = self.master # type: ignore[attr-defined]
|
|
83
|
+
if hasattr(parent, '_on_child_grid'):
|
|
84
|
+
parent._on_child_grid(self, **options)
|
|
85
|
+
else:
|
|
86
|
+
super().grid(**options) # type: ignore[misc]
|
|
87
|
+
return self # type: ignore[return-value]
|
|
88
|
+
|
|
89
|
+
def grid_configure(self, cnf: dict[str, Any] | None = None, **kw: Unpack[GridKwargs]) -> Self:
|
|
90
|
+
"""Alias for `grid()`.
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
cnf: Optional dict of grid options.
|
|
94
|
+
**kw: See `GridKwargs`.
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
Self for method chaining.
|
|
98
|
+
"""
|
|
99
|
+
return self.grid(cnf, **kw)
|
|
100
|
+
|
|
101
|
+
def grid_forget(self) -> Self:
|
|
102
|
+
"""Unmap this widget and forget its grid configuration.
|
|
103
|
+
|
|
104
|
+
The widget is removed from the layout, and its previous grid options
|
|
105
|
+
are discarded.
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
Self for method chaining.
|
|
109
|
+
"""
|
|
110
|
+
parent = self.master # type: ignore[attr-defined]
|
|
111
|
+
if hasattr(parent, '_on_child_grid_forget'):
|
|
112
|
+
parent._on_child_grid_forget(self)
|
|
113
|
+
else:
|
|
114
|
+
super().grid_forget() # type: ignore[misc]
|
|
115
|
+
return self # type: ignore[return-value]
|
|
116
|
+
|
|
117
|
+
def grid_remove(self) -> Self:
|
|
118
|
+
"""Unmap this widget but remember its grid configuration.
|
|
119
|
+
|
|
120
|
+
Use `grid()` with no args to restore it to its previous grid location.
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
Self for method chaining.
|
|
124
|
+
"""
|
|
125
|
+
parent = self.master # type: ignore[attr-defined]
|
|
126
|
+
if hasattr(parent, '_on_child_grid_remove'):
|
|
127
|
+
parent._on_child_grid_remove(self)
|
|
128
|
+
else:
|
|
129
|
+
super().grid_remove() # type: ignore[misc]
|
|
130
|
+
return self # type: ignore[return-value]
|
|
131
|
+
|
|
132
|
+
def grid_info(self) -> dict[str, Any]:
|
|
133
|
+
"""Return this widget's current grid configuration.
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
A dict containing the current grid options for this widget
|
|
137
|
+
(row, column, sticky, padx, pady, etc.).
|
|
138
|
+
"""
|
|
139
|
+
return super().grid_info() # type: ignore[misc]
|
|
140
|
+
|
|
141
|
+
# -------------------------------------------------------------------------
|
|
142
|
+
# Container methods (applied to the grid parent container)
|
|
143
|
+
# -------------------------------------------------------------------------
|
|
144
|
+
|
|
145
|
+
def grid_propagate(self, flag: bool | None = None) -> bool | None:
|
|
146
|
+
"""Get or set grid geometry propagation for this container.
|
|
147
|
+
|
|
148
|
+
When propagation is enabled (default), the container may resize itself
|
|
149
|
+
to fit the size requests of its children.
|
|
150
|
+
|
|
151
|
+
Args:
|
|
152
|
+
flag: True/False to enable/disable propagation. If None, acts as a getter.
|
|
153
|
+
|
|
154
|
+
Returns:
|
|
155
|
+
When queried, returns the current propagation flag. When set, returns None.
|
|
156
|
+
"""
|
|
157
|
+
return super().grid_propagate(flag) # type: ignore[misc]
|
|
158
|
+
|
|
159
|
+
def grid_rowconfigure(self, index: int, cnf: dict[str, Any] | None = None, **kw: Unpack[GridRowColumnKwargs]) -> None:
|
|
160
|
+
"""Configure sizing behavior for a grid row in this container.
|
|
161
|
+
|
|
162
|
+
Args:
|
|
163
|
+
index: Row index (0-based).
|
|
164
|
+
cnf: Optional dict of configuration options (same keys as `GridRowColumnKwargs`).
|
|
165
|
+
**kw: See `GridRowColumnKwargs`.
|
|
166
|
+
"""
|
|
167
|
+
if cnf is None:
|
|
168
|
+
return super().grid_rowconfigure(index, **kw) # type: ignore[misc]
|
|
169
|
+
return super().grid_rowconfigure(index, cnf, **kw) # type: ignore[misc]
|
|
170
|
+
|
|
171
|
+
def grid_columnconfigure(self, index: int, cnf: dict[str, Any] | None = None, **kw: Unpack[GridRowColumnKwargs]) -> None:
|
|
172
|
+
"""Configure sizing behavior for a grid column in this container.
|
|
173
|
+
|
|
174
|
+
Args:
|
|
175
|
+
index: Column index (0-based).
|
|
176
|
+
cnf: Optional dict of configuration options (same keys as `GridRowColumnKwargs`).
|
|
177
|
+
**kw: See `GridRowColumnKwargs`.
|
|
178
|
+
"""
|
|
179
|
+
if cnf is None:
|
|
180
|
+
return super().grid_columnconfigure(index, **kw) # type: ignore[misc]
|
|
181
|
+
return super().grid_columnconfigure(index, cnf, **kw) # type: ignore[misc]
|
|
182
|
+
|
|
183
|
+
def grid_size(self) -> tuple[int, int]:
|
|
184
|
+
"""Return the grid size (columns, rows) used in this container.
|
|
185
|
+
|
|
186
|
+
Returns:
|
|
187
|
+
A tuple (num_columns, num_rows).
|
|
188
|
+
"""
|
|
189
|
+
return super().grid_size() # type: ignore[misc]
|
|
190
|
+
|
|
191
|
+
def grid_slaves(
|
|
192
|
+
self,
|
|
193
|
+
row: int | None = None,
|
|
194
|
+
column: int | None = None,
|
|
195
|
+
) -> list[Any]:
|
|
196
|
+
"""Return the widgets managed by grid in this container.
|
|
197
|
+
|
|
198
|
+
Args:
|
|
199
|
+
row: If provided, return only widgets in the given row.
|
|
200
|
+
column: If provided, return only widgets in the given column.
|
|
201
|
+
|
|
202
|
+
Returns:
|
|
203
|
+
A list of child widgets managed by grid.
|
|
204
|
+
"""
|
|
205
|
+
if row is None and column is None:
|
|
206
|
+
return super().grid_slaves() # type: ignore[misc]
|
|
207
|
+
if row is None:
|
|
208
|
+
return super().grid_slaves(column=column) # type: ignore[misc]
|
|
209
|
+
if column is None:
|
|
210
|
+
return super().grid_slaves(row=row) # type: ignore[misc]
|
|
211
|
+
return super().grid_slaves(row=row, column=column) # type: ignore[misc]
|