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,367 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import tkinter
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Callable, Literal, overload
|
|
5
|
+
|
|
6
|
+
from bootstack.errors import BootstackError
|
|
7
|
+
from bootstack.events import Subscription
|
|
8
|
+
from bootstack.events._payloads import SplashDismissEvent
|
|
9
|
+
from bootstack.widgets._core.container import FlexContainer
|
|
10
|
+
from bootstack.widgets._core.events import register_widget_events
|
|
11
|
+
from bootstack.widgets._impl.primitives.flexframe import FlexFrame
|
|
12
|
+
from bootstack.widgets._impl.primitives.frame import Frame
|
|
13
|
+
from bootstack.widgets.types import Padding, SurfaceToken
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from bootstack.streams import Stream
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# Fade ramp: ~250ms over 12 steps. Tuned for a soft, quick in/out that never
|
|
20
|
+
# feels like a stall; degrades to an instant snap where alpha isn't honored.
|
|
21
|
+
_FADE_STEPS = 12
|
|
22
|
+
_FADE_INTERVAL_MS = 20
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class Splash(FlexContainer):
|
|
26
|
+
"""A borderless app intro screen shown while the main window is built.
|
|
27
|
+
|
|
28
|
+
Constructing a `Splash` inside an `App` context registers it with that app
|
|
29
|
+
and shows it; the app then defers revealing its own window until the splash
|
|
30
|
+
dismisses. Author the splash's contents — a logo, a title, a status line —
|
|
31
|
+
inside its `with` block exactly as you would the app body::
|
|
32
|
+
|
|
33
|
+
with bs.App(title="My App") as app:
|
|
34
|
+
with bs.Splash(min_duration=1.0):
|
|
35
|
+
bs.Picture(logo)
|
|
36
|
+
bs.Label("My App", font="heading-lg")
|
|
37
|
+
bs.Label("Loading…", textsignal=status)
|
|
38
|
+
# ...build the heavy app body — the splash covers this cost...
|
|
39
|
+
app.run()
|
|
40
|
+
|
|
41
|
+
Where you write the `Splash` determines how much of startup it covers: put
|
|
42
|
+
it first to cover the most. The `with` block scopes content authoring only —
|
|
43
|
+
it does not bound the splash's lifetime, which is governed by `until`,
|
|
44
|
+
`min_duration`, `skippable`, and `dismiss()`.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
until: What automatically closes the splash. `'ready'` (default) closes
|
|
48
|
+
it when the app finishes building. A number of seconds closes it
|
|
49
|
+
after that delay (app-ready does not auto-close it). `'manual'` never
|
|
50
|
+
auto-closes — use `skippable`, an authored button, or `dismiss()`.
|
|
51
|
+
skippable: When `True`, a click or the Escape key dismisses the splash.
|
|
52
|
+
min_duration: A floor in seconds — the splash never closes before this
|
|
53
|
+
has elapsed, even if its trigger fires sooner (prevents a blink on a
|
|
54
|
+
fast startup).
|
|
55
|
+
fade: Fade the window in and out where the platform supports window
|
|
56
|
+
alpha; snap instantly where it does not.
|
|
57
|
+
size: Fixed size as `(width, height)`. Defaults to auto-fitting the
|
|
58
|
+
content. Either way the splash is centered on screen.
|
|
59
|
+
surface: Surface token for the panel background.
|
|
60
|
+
padding: Inner content padding.
|
|
61
|
+
gap: Spacing between content items.
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
_auto_place = False # its own top-level window — no parent manages it
|
|
65
|
+
|
|
66
|
+
def __init__(
|
|
67
|
+
self,
|
|
68
|
+
*,
|
|
69
|
+
until: float | Literal["ready", "manual"] = "ready",
|
|
70
|
+
skippable: bool = False,
|
|
71
|
+
min_duration: float = 0.0,
|
|
72
|
+
fade: bool = True,
|
|
73
|
+
size: tuple[int, int] | None = None,
|
|
74
|
+
surface: SurfaceToken | str = "card",
|
|
75
|
+
padding: Padding = 24,
|
|
76
|
+
gap: int = 12,
|
|
77
|
+
) -> None:
|
|
78
|
+
from bootstack._runtime.app import get_current_app
|
|
79
|
+
from bootstack._runtime.toplevel import Toplevel as _InternalToplevel
|
|
80
|
+
|
|
81
|
+
self._parent = None
|
|
82
|
+
|
|
83
|
+
# ----- Resolve & register on the ambient app -----
|
|
84
|
+
try:
|
|
85
|
+
app = get_current_app()
|
|
86
|
+
except RuntimeError:
|
|
87
|
+
app = None
|
|
88
|
+
if app is None:
|
|
89
|
+
raise BootstackError(
|
|
90
|
+
"Splash requires an App — construct it inside a "
|
|
91
|
+
"`with bs.App(...) as app:` block."
|
|
92
|
+
)
|
|
93
|
+
if getattr(app, "_splash", None) is not None:
|
|
94
|
+
raise BootstackError(
|
|
95
|
+
"An app can show only one Splash. A second Splash was "
|
|
96
|
+
"constructed before the first dismissed."
|
|
97
|
+
)
|
|
98
|
+
self._app = app
|
|
99
|
+
app._splash = self
|
|
100
|
+
|
|
101
|
+
# ----- Dismiss model -----
|
|
102
|
+
if isinstance(until, bool): # bool is an int subclass — reject explicitly
|
|
103
|
+
raise BootstackError(
|
|
104
|
+
f"Splash until= must be 'ready', 'manual', or a number of "
|
|
105
|
+
f"seconds; got {until!r}."
|
|
106
|
+
)
|
|
107
|
+
if isinstance(until, (int, float)):
|
|
108
|
+
self._until: str = "timer"
|
|
109
|
+
self._until_seconds: float | None = float(until)
|
|
110
|
+
elif until in ("ready", "manual"):
|
|
111
|
+
self._until = until
|
|
112
|
+
self._until_seconds = None
|
|
113
|
+
else:
|
|
114
|
+
raise BootstackError(
|
|
115
|
+
f"Splash until= must be 'ready', 'manual', or a number of "
|
|
116
|
+
f"seconds; got {until!r}."
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
self._skippable = skippable
|
|
120
|
+
self._min_duration = max(0.0, float(min_duration))
|
|
121
|
+
self._fade = fade
|
|
122
|
+
self._size = size
|
|
123
|
+
|
|
124
|
+
# ----- Lifecycle state -----
|
|
125
|
+
self._shown = False # _reveal() has run (idempotent guard)
|
|
126
|
+
self._is_showing = False # mapped and not yet dismissed
|
|
127
|
+
self._dismissing = False # _begin_dismiss() has run
|
|
128
|
+
self._min_elapsed = self._min_duration <= 0.0
|
|
129
|
+
self._pending_reason: str | None = None
|
|
130
|
+
self._app_reveal: Callable[[], Any] | None = None
|
|
131
|
+
|
|
132
|
+
# ----- Build the borderless top-level -----
|
|
133
|
+
# windowtype='splash' is the single cross-platform switch (#308):
|
|
134
|
+
# overrideredirect on Windows, MacWindowStyle on macOS, -type on X11.
|
|
135
|
+
# topmost keeps it above the (still-hidden) app window.
|
|
136
|
+
self._tk_toplevel = _InternalToplevel(
|
|
137
|
+
title="",
|
|
138
|
+
windowtype="splash",
|
|
139
|
+
overrideredirect=True,
|
|
140
|
+
topmost=True,
|
|
141
|
+
)
|
|
142
|
+
self._internal = self._tk_toplevel
|
|
143
|
+
|
|
144
|
+
# A 1px themed border frames the panel so it reads as an intentional
|
|
145
|
+
# surface rather than blending into a same-colored desktop.
|
|
146
|
+
self._region_root = Frame(self._tk_toplevel, show_border=True, padding=1)
|
|
147
|
+
self._region_root.pack(fill="both", expand=True)
|
|
148
|
+
|
|
149
|
+
# Content is centered both ways — the classic splash composition.
|
|
150
|
+
self._content_frame = FlexFrame(
|
|
151
|
+
self._region_root,
|
|
152
|
+
direction="vertical",
|
|
153
|
+
padding=padding,
|
|
154
|
+
gap=gap,
|
|
155
|
+
horizontal_items="center",
|
|
156
|
+
vertical_items="center",
|
|
157
|
+
surface=surface,
|
|
158
|
+
)
|
|
159
|
+
self._content_frame.pack(fill="both", expand=True)
|
|
160
|
+
|
|
161
|
+
if self._skippable:
|
|
162
|
+
self._tk_toplevel.bind("<Escape>", self._on_skip, add="+")
|
|
163
|
+
self._tk_toplevel.bind("<Button-1>", self._on_skip, add="+")
|
|
164
|
+
|
|
165
|
+
@property
|
|
166
|
+
def _flex_frame(self) -> Any:
|
|
167
|
+
return self._content_frame
|
|
168
|
+
|
|
169
|
+
# ----- Context manager: author content, then reveal -----------------------
|
|
170
|
+
|
|
171
|
+
def __exit__(self, exc_type, exc, tb) -> None:
|
|
172
|
+
super().__exit__(exc_type, exc, tb)
|
|
173
|
+
# Reveal AFTER the content is authored so centering uses the real size.
|
|
174
|
+
# Showing here (not at construction) means the splash is painted before
|
|
175
|
+
# the synchronous body build that follows the block — so it genuinely
|
|
176
|
+
# covers that cost.
|
|
177
|
+
if exc_type is None:
|
|
178
|
+
self._reveal()
|
|
179
|
+
return None
|
|
180
|
+
|
|
181
|
+
# ----- Public surface ------------------------------------------------------
|
|
182
|
+
|
|
183
|
+
@property
|
|
184
|
+
def is_showing(self) -> bool:
|
|
185
|
+
"""Whether the splash is currently on screen."""
|
|
186
|
+
return self._is_showing
|
|
187
|
+
|
|
188
|
+
def dismiss(self) -> None:
|
|
189
|
+
"""Dismiss the splash now, fading out and revealing the app.
|
|
190
|
+
|
|
191
|
+
Respects `min_duration` — if the floor has not elapsed, the dismissal is
|
|
192
|
+
deferred until it has. Safe to call more than once; later calls are
|
|
193
|
+
ignored once a dismissal is under way.
|
|
194
|
+
"""
|
|
195
|
+
self._request_dismiss("manual")
|
|
196
|
+
|
|
197
|
+
@overload
|
|
198
|
+
def on_dismiss(self) -> "Stream": ...
|
|
199
|
+
@overload
|
|
200
|
+
def on_dismiss(self, handler: Callable[[SplashDismissEvent], Any]) -> Subscription: ...
|
|
201
|
+
def on_dismiss(
|
|
202
|
+
self,
|
|
203
|
+
handler: Callable[[SplashDismissEvent], Any] | None = None,
|
|
204
|
+
) -> "Stream | Subscription":
|
|
205
|
+
"""Register a callback fired when the splash begins dismissing.
|
|
206
|
+
|
|
207
|
+
The handler receives a :class:`~bootstack.events.SplashDismissEvent`
|
|
208
|
+
whose `reason` says why it closed (`'ready'`, `'timer'`, `'manual'`, or
|
|
209
|
+
`'skip'`). Fires once, as the fade-out starts.
|
|
210
|
+
|
|
211
|
+
Args:
|
|
212
|
+
handler: Called with the dismiss event. Omit to get a composable
|
|
213
|
+
:class:`~bootstack.streams.Stream`.
|
|
214
|
+
|
|
215
|
+
Returns:
|
|
216
|
+
A cancellable :class:`~bootstack.events.Subscription` when a handler
|
|
217
|
+
is given, otherwise a :class:`~bootstack.streams.Stream`.
|
|
218
|
+
"""
|
|
219
|
+
return self.on("dismiss", handler)
|
|
220
|
+
|
|
221
|
+
# ----- App integration -----------------------------------------------------
|
|
222
|
+
|
|
223
|
+
def _notify_app_ready(self, reveal: Callable[[], Any]) -> None:
|
|
224
|
+
"""Called by the app when it is built and ready to be revealed.
|
|
225
|
+
|
|
226
|
+
Stores the reveal callback so the splash can trigger it when it
|
|
227
|
+
dismisses. Under `until='ready'` this also kicks off the dismissal.
|
|
228
|
+
"""
|
|
229
|
+
if not self._is_showing:
|
|
230
|
+
# Never shown (constructed without a `with` block) or already gone —
|
|
231
|
+
# don't strand the app; reveal it now and drop any orphan splash.
|
|
232
|
+
self._app_reveal = None
|
|
233
|
+
self._clear_registration()
|
|
234
|
+
try:
|
|
235
|
+
self._tk_toplevel.destroy()
|
|
236
|
+
except tkinter.TclError:
|
|
237
|
+
pass
|
|
238
|
+
reveal()
|
|
239
|
+
return
|
|
240
|
+
self._app_reveal = reveal
|
|
241
|
+
if self._until == "ready":
|
|
242
|
+
self._request_dismiss("ready")
|
|
243
|
+
|
|
244
|
+
# ----- Reveal --------------------------------------------------------------
|
|
245
|
+
|
|
246
|
+
def _reveal(self) -> None:
|
|
247
|
+
if self._shown:
|
|
248
|
+
return
|
|
249
|
+
self._shown = True
|
|
250
|
+
top = self._tk_toplevel
|
|
251
|
+
top.update_idletasks()
|
|
252
|
+
|
|
253
|
+
if self._size is not None:
|
|
254
|
+
top.geometry(f"{int(self._size[0])}x{int(self._size[1])}")
|
|
255
|
+
top.update_idletasks()
|
|
256
|
+
|
|
257
|
+
from bootstack._runtime.window_utilities import WindowPositioning
|
|
258
|
+
|
|
259
|
+
x, y = WindowPositioning.center_on_screen(top)
|
|
260
|
+
x, y = WindowPositioning.ensure_on_screen(top, x, y)
|
|
261
|
+
top.geometry(f"+{x}+{y}")
|
|
262
|
+
|
|
263
|
+
if self._fade:
|
|
264
|
+
try:
|
|
265
|
+
top.attributes("-alpha", 0.0)
|
|
266
|
+
except tkinter.TclError:
|
|
267
|
+
self._fade = False
|
|
268
|
+
|
|
269
|
+
top.deiconify()
|
|
270
|
+
top.lift()
|
|
271
|
+
try:
|
|
272
|
+
top.focus_set()
|
|
273
|
+
except tkinter.TclError:
|
|
274
|
+
pass
|
|
275
|
+
# Force a paint now so the splash is on screen before the synchronous
|
|
276
|
+
# body build that follows the `with` block.
|
|
277
|
+
top.update()
|
|
278
|
+
self._is_showing = True
|
|
279
|
+
|
|
280
|
+
if self._fade:
|
|
281
|
+
self._fade_in(1)
|
|
282
|
+
self._start_timers()
|
|
283
|
+
|
|
284
|
+
def _start_timers(self) -> None:
|
|
285
|
+
top = self._tk_toplevel
|
|
286
|
+
if self._min_duration > 0:
|
|
287
|
+
top.after(int(self._min_duration * 1000), self._on_min_elapsed)
|
|
288
|
+
if self._until_seconds is not None:
|
|
289
|
+
top.after(int(self._until_seconds * 1000),
|
|
290
|
+
lambda: self._request_dismiss("timer"))
|
|
291
|
+
|
|
292
|
+
# ----- Fade ramps ----------------------------------------------------------
|
|
293
|
+
|
|
294
|
+
def _fade_in(self, step: int) -> None:
|
|
295
|
+
if not self._is_showing or self._dismissing:
|
|
296
|
+
return
|
|
297
|
+
alpha = min(1.0, step / _FADE_STEPS)
|
|
298
|
+
try:
|
|
299
|
+
self._tk_toplevel.attributes("-alpha", alpha)
|
|
300
|
+
except tkinter.TclError:
|
|
301
|
+
return
|
|
302
|
+
if step < _FADE_STEPS:
|
|
303
|
+
self._tk_toplevel.after(_FADE_INTERVAL_MS, lambda: self._fade_in(step + 1))
|
|
304
|
+
|
|
305
|
+
def _fade_out(self, step: int) -> None:
|
|
306
|
+
alpha = max(0.0, 1.0 - step / _FADE_STEPS)
|
|
307
|
+
try:
|
|
308
|
+
self._tk_toplevel.attributes("-alpha", alpha)
|
|
309
|
+
except tkinter.TclError:
|
|
310
|
+
self._finalize()
|
|
311
|
+
return
|
|
312
|
+
if step < _FADE_STEPS:
|
|
313
|
+
self._tk_toplevel.after(_FADE_INTERVAL_MS, lambda: self._fade_out(step + 1))
|
|
314
|
+
else:
|
|
315
|
+
self._finalize()
|
|
316
|
+
|
|
317
|
+
# ----- Dismiss flow --------------------------------------------------------
|
|
318
|
+
|
|
319
|
+
def _on_skip(self, _event: Any = None) -> None:
|
|
320
|
+
self._request_dismiss("skip")
|
|
321
|
+
|
|
322
|
+
def _on_min_elapsed(self) -> None:
|
|
323
|
+
self._min_elapsed = True
|
|
324
|
+
if self._pending_reason is not None:
|
|
325
|
+
self._begin_dismiss(self._pending_reason)
|
|
326
|
+
|
|
327
|
+
def _request_dismiss(self, reason: str) -> None:
|
|
328
|
+
if self._dismissing or not self._is_showing:
|
|
329
|
+
return
|
|
330
|
+
if not self._min_elapsed:
|
|
331
|
+
# Hold the first requested reason until the floor passes.
|
|
332
|
+
if self._pending_reason is None:
|
|
333
|
+
self._pending_reason = reason
|
|
334
|
+
return
|
|
335
|
+
self._begin_dismiss(reason)
|
|
336
|
+
|
|
337
|
+
def _begin_dismiss(self, reason: str) -> None:
|
|
338
|
+
if self._dismissing:
|
|
339
|
+
return
|
|
340
|
+
self._dismissing = True
|
|
341
|
+
self.emit("dismiss", data=SplashDismissEvent(reason=reason)) # type: ignore[arg-type]
|
|
342
|
+
# Reveal the app now so it is painted behind the (topmost) fading splash.
|
|
343
|
+
if self._app_reveal is not None:
|
|
344
|
+
reveal, self._app_reveal = self._app_reveal, None
|
|
345
|
+
try:
|
|
346
|
+
reveal()
|
|
347
|
+
except Exception:
|
|
348
|
+
pass
|
|
349
|
+
if self._fade and self._is_showing:
|
|
350
|
+
self._fade_out(1)
|
|
351
|
+
else:
|
|
352
|
+
self._finalize()
|
|
353
|
+
|
|
354
|
+
def _finalize(self) -> None:
|
|
355
|
+
self._is_showing = False
|
|
356
|
+
self._clear_registration()
|
|
357
|
+
try:
|
|
358
|
+
self._tk_toplevel.destroy()
|
|
359
|
+
except tkinter.TclError:
|
|
360
|
+
pass
|
|
361
|
+
|
|
362
|
+
def _clear_registration(self) -> None:
|
|
363
|
+
if getattr(self._app, "_splash", None) is self:
|
|
364
|
+
self._app._splash = None
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
register_widget_events(Splash, {"dismiss": "<<SplashDismiss>>"})
|