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,459 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import tkinter
|
|
4
|
+
from typing import overload, Any, Callable, Literal, TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
from bootstack.widgets._impl.composites.textarea.textarea import TextArea as _InternalTextArea
|
|
7
|
+
from bootstack.widgets._core.base import PublicWidgetBase, adapt_handler
|
|
8
|
+
from bootstack.widgets._core.events import register_widget_events, resolve_event
|
|
9
|
+
from bootstack.events import ChangeEvent, InputEvent, Subscription, TextModifiedEvent, ValidationEvent
|
|
10
|
+
from bootstack.streams import Stream
|
|
11
|
+
from bootstack.validation import RuleType
|
|
12
|
+
from bootstack.widgets.types import AccentToken, Event
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from bootstack.signals import Signal
|
|
16
|
+
|
|
17
|
+
# Events that fire on the inner tk.Text widget, not the outer frame.
|
|
18
|
+
_INNER_TEXT_SEQUENCES = frozenset({
|
|
19
|
+
"<FocusIn>",
|
|
20
|
+
"<FocusOut>",
|
|
21
|
+
"<<TextModified>>",
|
|
22
|
+
"<<TextUndo>>",
|
|
23
|
+
"<<TextRedo>>",
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
_TEXTAREA_EVENTS: dict[str, str] = {
|
|
27
|
+
"input": "<<Input>>",
|
|
28
|
+
"change": "<<Changed>>",
|
|
29
|
+
"valid": "<<Valid>>",
|
|
30
|
+
"invalid": "<<Invalid>>",
|
|
31
|
+
"validate": "<<Validate>>",
|
|
32
|
+
"focus": "<FocusIn>",
|
|
33
|
+
"blur": "<FocusOut>",
|
|
34
|
+
"modified": "<<TextModified>>",
|
|
35
|
+
"undo": "<<TextUndo>>",
|
|
36
|
+
"redo": "<<TextRedo>>",
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class TextArea(PublicWidgetBase):
|
|
41
|
+
"""A multi-line text input with optional label, placeholder, and scrollbars.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
value: Initial text content.
|
|
45
|
+
textsignal: Reactive `Signal[str]` linked to the text content.
|
|
46
|
+
label: Label displayed above the field.
|
|
47
|
+
message: Hint text displayed below the field.
|
|
48
|
+
required: If True, field cannot be left empty.
|
|
49
|
+
placeholder: Placeholder text shown when the field is empty.
|
|
50
|
+
max_length: Maximum number of characters allowed.
|
|
51
|
+
read_only: If True, text is visible but not editable.
|
|
52
|
+
wrap: If True (default), long lines wrap at the widget boundary.
|
|
53
|
+
height: Visible row count. Default `4`.
|
|
54
|
+
width: Width in character units. Omit to let the widget fill its
|
|
55
|
+
container via layout.
|
|
56
|
+
scrollbars: Scrollbar visibility. Default `'auto'`. Horizontal
|
|
57
|
+
scrolling requires `wrap=False`.
|
|
58
|
+
font: Semantic font token. Default `'body'`. See
|
|
59
|
+
:doc:`/reference/typography`.
|
|
60
|
+
accent: Accent token applied to the focus border. Default `'primary'`.
|
|
61
|
+
show_border: If True (default), wraps the text area in a themed
|
|
62
|
+
border with a focus ring.
|
|
63
|
+
parent: Override the context-stack parent.
|
|
64
|
+
**kwargs: Layout placement options applied by the parent container —
|
|
65
|
+
`fill`, `expand`, `anchor`, `margin`, `row`, `column`, `sticky`.
|
|
66
|
+
See :doc:`/tasks/layout`.
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
def __init__(
|
|
70
|
+
self,
|
|
71
|
+
value: str = "",
|
|
72
|
+
*,
|
|
73
|
+
textsignal: "Signal[str] | None" = None,
|
|
74
|
+
label: str | None = None,
|
|
75
|
+
message: str | None = None,
|
|
76
|
+
required: bool = False,
|
|
77
|
+
placeholder: str | None = None,
|
|
78
|
+
max_length: int | None = None,
|
|
79
|
+
read_only: bool = False,
|
|
80
|
+
wrap: bool = True,
|
|
81
|
+
height: int = 4,
|
|
82
|
+
width: int | None = None,
|
|
83
|
+
scrollbars: Literal["auto", "vertical", "both", "none"] = "auto",
|
|
84
|
+
font: str = "body",
|
|
85
|
+
accent: AccentToken | str = "primary",
|
|
86
|
+
show_border: bool = True,
|
|
87
|
+
parent: Any = None,
|
|
88
|
+
**kwargs: Any,
|
|
89
|
+
) -> None:
|
|
90
|
+
self._parent = self._resolve_parent(parent)
|
|
91
|
+
layout_kw = self._split_layout_kwargs(kwargs)
|
|
92
|
+
|
|
93
|
+
tk_master = self._parent._child_master() if self._parent else None
|
|
94
|
+
|
|
95
|
+
internal_kwargs: dict[str, Any] = {
|
|
96
|
+
"value": value,
|
|
97
|
+
"read_only": read_only,
|
|
98
|
+
"wrap": wrap,
|
|
99
|
+
"height": height,
|
|
100
|
+
"scrollbars": scrollbars,
|
|
101
|
+
**({"width": width} if width is not None else {}),
|
|
102
|
+
"show_border": show_border,
|
|
103
|
+
"font": font,
|
|
104
|
+
"accent": accent,
|
|
105
|
+
}
|
|
106
|
+
if textsignal is not None:
|
|
107
|
+
internal_kwargs["textsignal"] = textsignal
|
|
108
|
+
if label is not None:
|
|
109
|
+
internal_kwargs["label"] = label
|
|
110
|
+
if message is not None:
|
|
111
|
+
internal_kwargs["message"] = message
|
|
112
|
+
if required:
|
|
113
|
+
internal_kwargs["required"] = True
|
|
114
|
+
if placeholder is not None:
|
|
115
|
+
internal_kwargs["placeholder"] = placeholder
|
|
116
|
+
if max_length is not None:
|
|
117
|
+
internal_kwargs["max_length"] = max_length
|
|
118
|
+
|
|
119
|
+
self._internal = _InternalTextArea(tk_master, **internal_kwargs)
|
|
120
|
+
self._attach_to_parent(layout_kw)
|
|
121
|
+
|
|
122
|
+
# ----- Event routing -----
|
|
123
|
+
|
|
124
|
+
def _text_widget(self) -> tkinter.Misc:
|
|
125
|
+
return self._internal._core.text
|
|
126
|
+
|
|
127
|
+
@overload
|
|
128
|
+
def on(self, event: str) -> Stream: ...
|
|
129
|
+
@overload
|
|
130
|
+
def on(self, event: str, handler: Callable[[Event], Any]) -> Subscription: ...
|
|
131
|
+
def on(self, event: str, handler: Callable[[Event], Any] | None = None) -> Stream | Subscription:
|
|
132
|
+
"""Register a callback for an event by name.
|
|
133
|
+
|
|
134
|
+
A generic, string-keyed escape hatch — prefer the typed `on_*`
|
|
135
|
+
shorthands (e.g. `on_change`), which carry the precise payload type.
|
|
136
|
+
Called with no handler, returns a composable `Stream`; with a handler,
|
|
137
|
+
binds it and returns a `Subscription`.
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
event: Event name (for example `'change'` or `'focus'`).
|
|
141
|
+
handler: Called with the event payload. Omit to get a composable
|
|
142
|
+
:class:`~bootstack.streams.Stream` instead.
|
|
143
|
+
|
|
144
|
+
Returns:
|
|
145
|
+
A cancellable :class:`~bootstack.events.Subscription` when a handler
|
|
146
|
+
is given, otherwise a :class:`~bootstack.streams.Stream`.
|
|
147
|
+
"""
|
|
148
|
+
sequence = resolve_event(self, str(event))
|
|
149
|
+
target = self._text_widget() if sequence in _INNER_TEXT_SEQUENCES else self._internal
|
|
150
|
+
if handler is None:
|
|
151
|
+
def _source(h):
|
|
152
|
+
t = self._text_widget() if sequence in _INNER_TEXT_SEQUENCES else self._internal
|
|
153
|
+
bid = t.bind(sequence, adapt_handler(h), add="+")
|
|
154
|
+
return Subscription(t, sequence, bid)
|
|
155
|
+
return Stream(self._internal, _source=_source)
|
|
156
|
+
bid = target.bind(sequence, adapt_handler(handler), add="+")
|
|
157
|
+
return Subscription(target, sequence, bid)
|
|
158
|
+
|
|
159
|
+
# ----- Properties -----
|
|
160
|
+
|
|
161
|
+
@property
|
|
162
|
+
def value(self) -> str:
|
|
163
|
+
"""The current text content."""
|
|
164
|
+
return self._internal.value
|
|
165
|
+
|
|
166
|
+
@value.setter
|
|
167
|
+
def value(self, v: str) -> None:
|
|
168
|
+
self._internal.value = v
|
|
169
|
+
|
|
170
|
+
@property
|
|
171
|
+
def text(self) -> str:
|
|
172
|
+
"""The current display text. Same as `value` for a text area (no
|
|
173
|
+
formatting layer). Read-only — assign to `value` to change it."""
|
|
174
|
+
return self._internal.value
|
|
175
|
+
|
|
176
|
+
@property
|
|
177
|
+
def signal(self) -> "Signal[str] | None":
|
|
178
|
+
"""The reactive `Signal` bound to this field, or `None`."""
|
|
179
|
+
return getattr(self._internal, "signal", None)
|
|
180
|
+
|
|
181
|
+
@property
|
|
182
|
+
def valid(self) -> "Signal[bool]":
|
|
183
|
+
"""Reactive `Signal[bool]` — `True` when all validation rules pass.
|
|
184
|
+
|
|
185
|
+
Starts `True`. Updates after every validation run (blur or manual
|
|
186
|
+
`validate()` call). Subscribe a named handler to react immediately when
|
|
187
|
+
validity changes (a `lambda` cannot assign, so define a function):
|
|
188
|
+
`def on_valid(ok): btn.disabled = not ok` then
|
|
189
|
+
`area.valid.subscribe(on_valid)`.
|
|
190
|
+
"""
|
|
191
|
+
return self._internal._valid_signal
|
|
192
|
+
|
|
193
|
+
@property
|
|
194
|
+
def error(self) -> "Signal[str]":
|
|
195
|
+
"""Reactive `Signal[str]` — current validation error message.
|
|
196
|
+
|
|
197
|
+
Empty string when the field is valid. Updates in lockstep with `valid`.
|
|
198
|
+
"""
|
|
199
|
+
return self._internal._error_signal
|
|
200
|
+
|
|
201
|
+
@property
|
|
202
|
+
def read_only(self) -> bool:
|
|
203
|
+
"""Whether the text area is visible but not editable."""
|
|
204
|
+
return self._internal._core.read_only
|
|
205
|
+
|
|
206
|
+
@read_only.setter
|
|
207
|
+
def read_only(self, v: bool) -> None:
|
|
208
|
+
# Delegate to the core property so its `_read_only` flag stays in sync —
|
|
209
|
+
# the value/insert setters rely on it to apply programmatic writes.
|
|
210
|
+
self._internal._core.read_only = v
|
|
211
|
+
|
|
212
|
+
@property
|
|
213
|
+
def is_dirty(self) -> bool:
|
|
214
|
+
"""True if the content has changed since the last `mark_saved()` call."""
|
|
215
|
+
return self._internal.is_dirty
|
|
216
|
+
|
|
217
|
+
# ----- Methods -----
|
|
218
|
+
|
|
219
|
+
def focus(self) -> None:
|
|
220
|
+
"""Give keyboard focus to the text area."""
|
|
221
|
+
self._text_widget().focus_set()
|
|
222
|
+
|
|
223
|
+
def clear(self) -> None:
|
|
224
|
+
"""Clear all text content."""
|
|
225
|
+
self._internal.value = ""
|
|
226
|
+
|
|
227
|
+
def validate(self) -> bool:
|
|
228
|
+
"""Run validation rules against the current value.
|
|
229
|
+
|
|
230
|
+
Returns:
|
|
231
|
+
`True` if all rules pass, `False` otherwise.
|
|
232
|
+
"""
|
|
233
|
+
return self._internal.validate()
|
|
234
|
+
|
|
235
|
+
def add_validation_rule(self, rule_type: RuleType, **kwargs: Any) -> None:
|
|
236
|
+
"""Attach a validation rule to this field.
|
|
237
|
+
|
|
238
|
+
Args:
|
|
239
|
+
rule_type: The kind of validation rule to apply.
|
|
240
|
+
**kwargs: Rule options such as `message=`, `min=`, `max=`,
|
|
241
|
+
`trigger=`.
|
|
242
|
+
"""
|
|
243
|
+
self._internal.add_validation_rule(rule_type, **kwargs)
|
|
244
|
+
|
|
245
|
+
def insert(self, text: str) -> None:
|
|
246
|
+
"""Insert `text` at the cursor.
|
|
247
|
+
|
|
248
|
+
Read-only blocks *user* edits, not programmatic ones: this applies
|
|
249
|
+
even when `read_only=True`, leaving the area read-only afterward.
|
|
250
|
+
|
|
251
|
+
Args:
|
|
252
|
+
text: Text to insert at the current cursor position.
|
|
253
|
+
"""
|
|
254
|
+
self._internal._core.insert("insert", text)
|
|
255
|
+
|
|
256
|
+
def append(self, text: str) -> None:
|
|
257
|
+
"""Append `text` to the end of the content.
|
|
258
|
+
|
|
259
|
+
Applies even when `read_only=True`, leaving the area read-only
|
|
260
|
+
afterward.
|
|
261
|
+
|
|
262
|
+
Args:
|
|
263
|
+
text: Text to add at the end of the content.
|
|
264
|
+
"""
|
|
265
|
+
self._internal._core.insert("end-1c", text)
|
|
266
|
+
|
|
267
|
+
def select_all(self) -> None:
|
|
268
|
+
"""Select all text content."""
|
|
269
|
+
tw = self._internal._core.text
|
|
270
|
+
tw.focus_set()
|
|
271
|
+
tw.tag_add("sel", "1.0", "end-1c")
|
|
272
|
+
tw.mark_set("insert", "end-1c")
|
|
273
|
+
|
|
274
|
+
def mark_saved(self) -> None:
|
|
275
|
+
"""Reset the dirty flag — call after saving content."""
|
|
276
|
+
self._internal.mark_saved()
|
|
277
|
+
|
|
278
|
+
def undo(self) -> None:
|
|
279
|
+
"""Undo the last edit."""
|
|
280
|
+
self._internal.undo()
|
|
281
|
+
|
|
282
|
+
def redo(self) -> None:
|
|
283
|
+
"""Redo the last undone edit."""
|
|
284
|
+
self._internal.redo()
|
|
285
|
+
|
|
286
|
+
# ----- Event shorthands -----
|
|
287
|
+
|
|
288
|
+
@overload
|
|
289
|
+
def on_input(self) -> Stream: ...
|
|
290
|
+
@overload
|
|
291
|
+
def on_input(self, handler: Callable[[InputEvent], Any]) -> Subscription: ...
|
|
292
|
+
def on_input(self, handler: Callable[[InputEvent], Any] | None = None) -> Stream | Subscription:
|
|
293
|
+
"""Register a callback fired on every edit.
|
|
294
|
+
|
|
295
|
+
Args:
|
|
296
|
+
handler: Called with an :class:`~bootstack.events.InputEvent`. Omit to
|
|
297
|
+
get a composable :class:`~bootstack.streams.Stream` instead.
|
|
298
|
+
|
|
299
|
+
Returns:
|
|
300
|
+
A cancellable :class:`~bootstack.events.Subscription` when a
|
|
301
|
+
handler is given, otherwise a :class:`~bootstack.streams.Stream`.
|
|
302
|
+
"""
|
|
303
|
+
return self.on("input", handler)
|
|
304
|
+
|
|
305
|
+
@overload
|
|
306
|
+
def on_change(self) -> Stream: ...
|
|
307
|
+
@overload
|
|
308
|
+
def on_change(self, handler: Callable[[ChangeEvent], Any]) -> Subscription: ...
|
|
309
|
+
def on_change(self, handler: Callable[[ChangeEvent], Any] | None = None) -> Stream | Subscription:
|
|
310
|
+
"""Register a callback fired when the value is committed (on blur).
|
|
311
|
+
|
|
312
|
+
Args:
|
|
313
|
+
handler: Called with a :class:`~bootstack.events.ChangeEvent`. Omit to
|
|
314
|
+
get a composable :class:`~bootstack.streams.Stream` instead.
|
|
315
|
+
|
|
316
|
+
Returns:
|
|
317
|
+
A cancellable :class:`~bootstack.events.Subscription` when a
|
|
318
|
+
handler is given, otherwise a :class:`~bootstack.streams.Stream`.
|
|
319
|
+
"""
|
|
320
|
+
return self.on("change", handler)
|
|
321
|
+
|
|
322
|
+
@overload
|
|
323
|
+
def on_focus(self) -> Stream: ...
|
|
324
|
+
@overload
|
|
325
|
+
def on_focus(self, handler: Callable[[Event], Any]) -> Subscription: ...
|
|
326
|
+
def on_focus(self, handler: Callable[[Event], Any] | None = None) -> Stream | Subscription:
|
|
327
|
+
"""Register a callback fired when the text area gains focus.
|
|
328
|
+
|
|
329
|
+
Args:
|
|
330
|
+
handler: Called with an :class:`~bootstack.events.Event`. Omit to
|
|
331
|
+
get a composable :class:`~bootstack.streams.Stream` instead.
|
|
332
|
+
|
|
333
|
+
Returns:
|
|
334
|
+
A cancellable :class:`~bootstack.events.Subscription` when a
|
|
335
|
+
handler is given, otherwise a :class:`~bootstack.streams.Stream`.
|
|
336
|
+
"""
|
|
337
|
+
return self.on("focus", handler)
|
|
338
|
+
|
|
339
|
+
@overload
|
|
340
|
+
def on_blur(self) -> Stream: ...
|
|
341
|
+
@overload
|
|
342
|
+
def on_blur(self, handler: Callable[[Event], Any]) -> Subscription: ...
|
|
343
|
+
def on_blur(self, handler: Callable[[Event], Any] | None = None) -> Stream | Subscription:
|
|
344
|
+
"""Register a callback fired when the text area loses focus.
|
|
345
|
+
|
|
346
|
+
Args:
|
|
347
|
+
handler: Called with an :class:`~bootstack.events.Event`. Omit to
|
|
348
|
+
get a composable :class:`~bootstack.streams.Stream` instead.
|
|
349
|
+
|
|
350
|
+
Returns:
|
|
351
|
+
A cancellable :class:`~bootstack.events.Subscription` when a
|
|
352
|
+
handler is given, otherwise a :class:`~bootstack.streams.Stream`.
|
|
353
|
+
"""
|
|
354
|
+
return self.on("blur", handler)
|
|
355
|
+
|
|
356
|
+
@overload
|
|
357
|
+
def on_valid(self) -> Stream: ...
|
|
358
|
+
@overload
|
|
359
|
+
def on_valid(self, handler: Callable[[ValidationEvent], Any]) -> Subscription: ...
|
|
360
|
+
def on_valid(self, handler: Callable[[ValidationEvent], Any] | None = None) -> Stream | Subscription:
|
|
361
|
+
"""Register a callback fired when validation passes.
|
|
362
|
+
|
|
363
|
+
Args:
|
|
364
|
+
handler: Called with a :class:`~bootstack.events.ValidationEvent`. Omit to
|
|
365
|
+
get a composable :class:`~bootstack.streams.Stream` instead.
|
|
366
|
+
|
|
367
|
+
Returns:
|
|
368
|
+
A cancellable :class:`~bootstack.events.Subscription` when a
|
|
369
|
+
handler is given, otherwise a :class:`~bootstack.streams.Stream`.
|
|
370
|
+
"""
|
|
371
|
+
return self.on("valid", handler)
|
|
372
|
+
|
|
373
|
+
@overload
|
|
374
|
+
def on_invalid(self) -> Stream: ...
|
|
375
|
+
@overload
|
|
376
|
+
def on_invalid(self, handler: Callable[[ValidationEvent], Any]) -> Subscription: ...
|
|
377
|
+
def on_invalid(self, handler: Callable[[ValidationEvent], Any] | None = None) -> Stream | Subscription:
|
|
378
|
+
"""Register a callback fired when validation fails.
|
|
379
|
+
|
|
380
|
+
Args:
|
|
381
|
+
handler: Called with a :class:`~bootstack.events.ValidationEvent`. Omit to
|
|
382
|
+
get a composable :class:`~bootstack.streams.Stream` instead.
|
|
383
|
+
|
|
384
|
+
Returns:
|
|
385
|
+
A cancellable :class:`~bootstack.events.Subscription` when a
|
|
386
|
+
handler is given, otherwise a :class:`~bootstack.streams.Stream`.
|
|
387
|
+
"""
|
|
388
|
+
return self.on("invalid", handler)
|
|
389
|
+
|
|
390
|
+
@overload
|
|
391
|
+
def on_validate(self) -> Stream: ...
|
|
392
|
+
@overload
|
|
393
|
+
def on_validate(self, handler: Callable[[ValidationEvent], Any]) -> Subscription: ...
|
|
394
|
+
def on_validate(self, handler: Callable[[ValidationEvent], Any] | None = None) -> Stream | Subscription:
|
|
395
|
+
"""Register a callback fired after any validation run.
|
|
396
|
+
|
|
397
|
+
Args:
|
|
398
|
+
handler: Called with a :class:`~bootstack.events.ValidationEvent`. Omit to
|
|
399
|
+
get a composable :class:`~bootstack.streams.Stream` instead.
|
|
400
|
+
|
|
401
|
+
Returns:
|
|
402
|
+
A cancellable :class:`~bootstack.events.Subscription` when a
|
|
403
|
+
handler is given, otherwise a :class:`~bootstack.streams.Stream`.
|
|
404
|
+
"""
|
|
405
|
+
return self.on("validate", handler)
|
|
406
|
+
|
|
407
|
+
@overload
|
|
408
|
+
def on_modified(self) -> Stream: ...
|
|
409
|
+
@overload
|
|
410
|
+
def on_modified(self, handler: Callable[[TextModifiedEvent], Any]) -> Subscription: ...
|
|
411
|
+
def on_modified(self, handler: Callable[[TextModifiedEvent], Any] | None = None) -> Stream | Subscription:
|
|
412
|
+
"""Register a callback fired when the dirty state changes.
|
|
413
|
+
|
|
414
|
+
Args:
|
|
415
|
+
handler: Called with a :class:`~bootstack.events.TextModifiedEvent`. Omit to
|
|
416
|
+
get a composable :class:`~bootstack.streams.Stream` instead.
|
|
417
|
+
|
|
418
|
+
Returns:
|
|
419
|
+
A cancellable :class:`~bootstack.events.Subscription` when a
|
|
420
|
+
handler is given, otherwise a :class:`~bootstack.streams.Stream`.
|
|
421
|
+
"""
|
|
422
|
+
return self.on("modified", handler)
|
|
423
|
+
|
|
424
|
+
@overload
|
|
425
|
+
def on_undo(self) -> Stream: ...
|
|
426
|
+
@overload
|
|
427
|
+
def on_undo(self, handler: Callable[[InputEvent], Any]) -> Subscription: ...
|
|
428
|
+
def on_undo(self, handler: Callable[[InputEvent], Any] | None = None) -> Stream | Subscription:
|
|
429
|
+
"""Register a callback fired after an undo operation.
|
|
430
|
+
|
|
431
|
+
Args:
|
|
432
|
+
handler: Called with an :class:`~bootstack.events.InputEvent`. Omit to
|
|
433
|
+
get a composable :class:`~bootstack.streams.Stream` instead.
|
|
434
|
+
|
|
435
|
+
Returns:
|
|
436
|
+
A cancellable :class:`~bootstack.events.Subscription` when a
|
|
437
|
+
handler is given, otherwise a :class:`~bootstack.streams.Stream`.
|
|
438
|
+
"""
|
|
439
|
+
return self.on("undo", handler)
|
|
440
|
+
|
|
441
|
+
@overload
|
|
442
|
+
def on_redo(self) -> Stream: ...
|
|
443
|
+
@overload
|
|
444
|
+
def on_redo(self, handler: Callable[[InputEvent], Any]) -> Subscription: ...
|
|
445
|
+
def on_redo(self, handler: Callable[[InputEvent], Any] | None = None) -> Stream | Subscription:
|
|
446
|
+
"""Register a callback fired after a redo operation.
|
|
447
|
+
|
|
448
|
+
Args:
|
|
449
|
+
handler: Called with an :class:`~bootstack.events.InputEvent`. Omit to
|
|
450
|
+
get a composable :class:`~bootstack.streams.Stream` instead.
|
|
451
|
+
|
|
452
|
+
Returns:
|
|
453
|
+
A cancellable :class:`~bootstack.events.Subscription` when a
|
|
454
|
+
handler is given, otherwise a :class:`~bootstack.streams.Stream`.
|
|
455
|
+
"""
|
|
456
|
+
return self.on("redo", handler)
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
register_widget_events(TextArea, _TEXTAREA_EVENTS)
|