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,419 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any, Callable, TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from bootstack.widgets._impl.composites.dropdownbutton import DropdownButton as _InternalDropdownButton
|
|
6
|
+
from bootstack.widgets._core.base import PublicWidgetBase
|
|
7
|
+
from bootstack.widgets._core.icon_image_props import IconProperty
|
|
8
|
+
from bootstack.widgets.types import AccentToken, WidgetDensity, ButtonVariant, IconSpec, LocalizeMode
|
|
9
|
+
from bootstack.events import MenuSelectEvent
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from bootstack.signals import Signal
|
|
13
|
+
|
|
14
|
+
# Public item type names → internal ContextMenu type strings.
|
|
15
|
+
_ITEM_TYPE_MAP: dict[str, str] = {
|
|
16
|
+
"command": "command",
|
|
17
|
+
"check": "checkbutton",
|
|
18
|
+
"radio": "radiobutton",
|
|
19
|
+
"divider": "separator",
|
|
20
|
+
# accept legacy/internal names so existing code doesn't break
|
|
21
|
+
"checkbutton": "checkbutton",
|
|
22
|
+
"radiobutton": "radiobutton",
|
|
23
|
+
"separator": "separator",
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _resolve_item_type(type_: str) -> str:
|
|
28
|
+
resolved = _ITEM_TYPE_MAP.get(type_)
|
|
29
|
+
if resolved is None:
|
|
30
|
+
raise ValueError(
|
|
31
|
+
f"Unknown item type {type_!r}. "
|
|
32
|
+
f"Use 'command', 'check', 'radio', or 'divider'."
|
|
33
|
+
)
|
|
34
|
+
return resolved
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _translate_item(item: dict[str, Any]) -> dict[str, Any]:
|
|
38
|
+
"""Translate a public item dict to the internal ContextMenu shape.
|
|
39
|
+
|
|
40
|
+
Maps the public `type` name to its internal string and the public `on_click`
|
|
41
|
+
callback key to the toolkit's `command`, so item dicts never need toolkit
|
|
42
|
+
names. Returns a copy; the input is left untouched.
|
|
43
|
+
"""
|
|
44
|
+
item = dict(item)
|
|
45
|
+
if "type" in item:
|
|
46
|
+
item["type"] = _resolve_item_type(item["type"])
|
|
47
|
+
if "on_click" in item:
|
|
48
|
+
item["command"] = item.pop("on_click")
|
|
49
|
+
return item
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
# Keys that map to explicit constructor parameters — user **kwargs must not
|
|
53
|
+
# override these silently.
|
|
54
|
+
_RESERVED_INTERNAL_KEYS = frozenset({
|
|
55
|
+
"show_dropdown_button", "popdown_options", "text", "items", "command",
|
|
56
|
+
"icon", "icon_only", "state", "accent", "variant", "density",
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class MenuButton(IconProperty, PublicWidgetBase):
|
|
61
|
+
"""A button that opens a dropdown menu when clicked.
|
|
62
|
+
|
|
63
|
+
Items are added at construction via `items=` or dynamically with
|
|
64
|
+
`add_item()`. The `on_select` callback fires for every item click,
|
|
65
|
+
receiving a dict with `type`, `text`, and `value` keys.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
text: Button text. Defaults to an empty string.
|
|
69
|
+
items: Initial list of item dicts. Each dict must have a `type`
|
|
70
|
+
key (`'command'`, `'check'`, `'radio'`, or
|
|
71
|
+
`'divider'`) plus item-specific keys such as `text`,
|
|
72
|
+
`icon`, `value`, and `on_click` (the per-item callback).
|
|
73
|
+
on_select: Callback fired when any menu item is activated. Called with
|
|
74
|
+
a :class:`~bootstack.events.MenuSelectEvent` (`type`, `text`,
|
|
75
|
+
`value` of the activated item).
|
|
76
|
+
icon: Icon name shown on the button face.
|
|
77
|
+
icon_only: If `True`, hides the label and shows only the icon.
|
|
78
|
+
Inferred automatically when `icon=` is set and `label` is
|
|
79
|
+
empty. Defaults to `False`.
|
|
80
|
+
show_arrow: If `True` (default), shows the dropdown chevron arrow.
|
|
81
|
+
Pass `False` to hide it (useful when the icon implies the action).
|
|
82
|
+
menu_options: Extra options forwarded to the underlying `ContextMenu`
|
|
83
|
+
at construction (e.g. `{'anchor': 'se', 'offset': 4}`).
|
|
84
|
+
disabled: If `True`, button is shown but non-interactive. Defaults
|
|
85
|
+
to `False`.
|
|
86
|
+
accent: Color intent token. Defaults to the theme default.
|
|
87
|
+
variant: Style variant. Default `'ghost'`.
|
|
88
|
+
density: Layout density.
|
|
89
|
+
textsignal: `Signal[str]` bound to the button label text.
|
|
90
|
+
localize: Whether the button text is translated through the catalog —
|
|
91
|
+
`True`, `False`, or `'auto'`. Defaults to the app's `localize_mode`.
|
|
92
|
+
parent: Override the context-stack parent widget.
|
|
93
|
+
**kwargs: Layout placement options applied by the parent container —
|
|
94
|
+
`fill`, `expand`, `anchor`, `margin`, `row`, `column`, `sticky`.
|
|
95
|
+
See :doc:`/tasks/layout`.
|
|
96
|
+
"""
|
|
97
|
+
|
|
98
|
+
def __init__(
|
|
99
|
+
self,
|
|
100
|
+
text: str = "",
|
|
101
|
+
*,
|
|
102
|
+
items: list[Any] | None = None,
|
|
103
|
+
on_select: Callable[[MenuSelectEvent], Any] | None = None,
|
|
104
|
+
icon: str | IconSpec | None = None,
|
|
105
|
+
icon_only: bool = False,
|
|
106
|
+
show_arrow: bool = True,
|
|
107
|
+
menu_options: dict[str, Any] | None = None,
|
|
108
|
+
disabled: bool = False,
|
|
109
|
+
accent: AccentToken | str | None = None,
|
|
110
|
+
variant: ButtonVariant = "default",
|
|
111
|
+
density: WidgetDensity | None = None,
|
|
112
|
+
textsignal: "Signal[str] | None" = None,
|
|
113
|
+
localize: LocalizeMode | None = None,
|
|
114
|
+
parent: Any = None,
|
|
115
|
+
**kwargs: Any,
|
|
116
|
+
) -> None:
|
|
117
|
+
self._reject_signal_text(text)
|
|
118
|
+
self._parent = self._resolve_parent(parent)
|
|
119
|
+
layout_kw = self._split_layout_kwargs(kwargs)
|
|
120
|
+
tk_master = self._parent._child_master() if self._parent else None
|
|
121
|
+
|
|
122
|
+
# Build internal kwargs from explicit params first, then let **kwargs
|
|
123
|
+
# add extras — but never let **kwargs clobber an explicitly-set key.
|
|
124
|
+
internal_kwargs: dict[str, Any] = {
|
|
125
|
+
"show_dropdown_button": show_arrow,
|
|
126
|
+
}
|
|
127
|
+
if menu_options is not None:
|
|
128
|
+
internal_kwargs["popdown_options"] = menu_options
|
|
129
|
+
if text:
|
|
130
|
+
internal_kwargs["text"] = text
|
|
131
|
+
if items is not None:
|
|
132
|
+
internal_kwargs["items"] = [_translate_item(it) for it in items]
|
|
133
|
+
if on_select is not None:
|
|
134
|
+
_user_on_select = on_select
|
|
135
|
+
def _on_select(data: dict[str, Any]) -> None:
|
|
136
|
+
_user_on_select(MenuSelectEvent(
|
|
137
|
+
type=data.get("type", ""),
|
|
138
|
+
text=data.get("text", ""),
|
|
139
|
+
value=data.get("value"),
|
|
140
|
+
))
|
|
141
|
+
internal_kwargs["command"] = _on_select
|
|
142
|
+
if icon is not None:
|
|
143
|
+
internal_kwargs["icon"] = icon
|
|
144
|
+
if icon_only:
|
|
145
|
+
internal_kwargs["icon_only"] = True
|
|
146
|
+
if disabled:
|
|
147
|
+
internal_kwargs["state"] = "disabled"
|
|
148
|
+
if accent is not None:
|
|
149
|
+
internal_kwargs["accent"] = accent
|
|
150
|
+
if variant is not None:
|
|
151
|
+
internal_kwargs["variant"] = variant
|
|
152
|
+
if density is not None:
|
|
153
|
+
internal_kwargs["density"] = density
|
|
154
|
+
if textsignal is not None:
|
|
155
|
+
internal_kwargs["textsignal"] = textsignal
|
|
156
|
+
if localize is not None:
|
|
157
|
+
internal_kwargs["localize"] = localize
|
|
158
|
+
|
|
159
|
+
# Merge extra kwargs, skipping any that would override an explicit param.
|
|
160
|
+
for k, v in kwargs.items():
|
|
161
|
+
if k not in _RESERVED_INTERNAL_KEYS:
|
|
162
|
+
internal_kwargs[k] = v
|
|
163
|
+
|
|
164
|
+
self._internal = _InternalDropdownButton(tk_master, **internal_kwargs)
|
|
165
|
+
self._attach_to_parent(layout_kw)
|
|
166
|
+
|
|
167
|
+
# ----- Item management -----
|
|
168
|
+
|
|
169
|
+
def add_item(
|
|
170
|
+
self,
|
|
171
|
+
label: str,
|
|
172
|
+
*,
|
|
173
|
+
on_click: Callable[[], Any] | None = None,
|
|
174
|
+
icon: str | None = None,
|
|
175
|
+
shortcut: str | None = None,
|
|
176
|
+
disabled: bool = False,
|
|
177
|
+
key: str | None = None,
|
|
178
|
+
) -> str:
|
|
179
|
+
"""Add a command item to the dropdown.
|
|
180
|
+
|
|
181
|
+
Args:
|
|
182
|
+
label: Item label text.
|
|
183
|
+
on_click: Callback fired when the item is clicked.
|
|
184
|
+
icon: Icon name shown beside the label.
|
|
185
|
+
shortcut: Keyboard shortcut hint displayed on the right. Accepts a
|
|
186
|
+
modifier pattern (`"Mod+S"` → `"Ctrl+S"` / `"⌘S"`), a
|
|
187
|
+
registered shortcut key name, or a literal display string.
|
|
188
|
+
disabled: If True, item is shown but non-interactive.
|
|
189
|
+
key: Unique string key. Auto-generated if omitted.
|
|
190
|
+
|
|
191
|
+
Returns:
|
|
192
|
+
The key assigned to this item.
|
|
193
|
+
"""
|
|
194
|
+
kw: dict[str, Any] = {"text": label, "disabled": disabled}
|
|
195
|
+
if on_click is not None:
|
|
196
|
+
kw["command"] = on_click
|
|
197
|
+
if icon is not None:
|
|
198
|
+
kw["icon"] = icon
|
|
199
|
+
if shortcut is not None:
|
|
200
|
+
kw["shortcut"] = shortcut
|
|
201
|
+
if key is not None:
|
|
202
|
+
kw["key"] = key
|
|
203
|
+
result = self._internal.add_command(**kw)
|
|
204
|
+
return result.key if hasattr(result, "key") else key or label
|
|
205
|
+
|
|
206
|
+
def add_check_item(
|
|
207
|
+
self,
|
|
208
|
+
label: str,
|
|
209
|
+
*,
|
|
210
|
+
value: bool = False,
|
|
211
|
+
on_click: Callable[[], Any] | None = None,
|
|
212
|
+
key: str | None = None,
|
|
213
|
+
) -> str:
|
|
214
|
+
"""Add a checkbutton item to the dropdown.
|
|
215
|
+
|
|
216
|
+
Args:
|
|
217
|
+
label: Item label text.
|
|
218
|
+
value: Initial checked state.
|
|
219
|
+
on_click: Callback fired on toggle.
|
|
220
|
+
key: Unique string key. Auto-generated if omitted.
|
|
221
|
+
|
|
222
|
+
Returns:
|
|
223
|
+
The key assigned to this item.
|
|
224
|
+
"""
|
|
225
|
+
kw: dict[str, Any] = {"text": label, "value": value}
|
|
226
|
+
if on_click is not None:
|
|
227
|
+
kw["command"] = on_click
|
|
228
|
+
if key is not None:
|
|
229
|
+
kw["key"] = key
|
|
230
|
+
result = self._internal.add_checkbutton(**kw)
|
|
231
|
+
return result.key if hasattr(result, "key") else key or label
|
|
232
|
+
|
|
233
|
+
def add_radio_item(
|
|
234
|
+
self,
|
|
235
|
+
label: str,
|
|
236
|
+
*,
|
|
237
|
+
value: Any = None,
|
|
238
|
+
selected: bool = False,
|
|
239
|
+
on_click: Callable[[], Any] | None = None,
|
|
240
|
+
key: str | None = None,
|
|
241
|
+
) -> str:
|
|
242
|
+
"""Add a radio-button item to the dropdown.
|
|
243
|
+
|
|
244
|
+
All radio items in a `MenuButton` share one group variable
|
|
245
|
+
automatically. Pass `selected=True` on the item that should be
|
|
246
|
+
pre-selected on first open.
|
|
247
|
+
|
|
248
|
+
Note:
|
|
249
|
+
Values are stored as strings internally. Pass string values
|
|
250
|
+
(e.g. `value="100%"`) for predictable comparisons when reading
|
|
251
|
+
the group selection via `menu`.
|
|
252
|
+
|
|
253
|
+
Args:
|
|
254
|
+
label: Item label text.
|
|
255
|
+
value: Value associated with this radio item. Stored as a string
|
|
256
|
+
internally; defaults to `label` when omitted.
|
|
257
|
+
selected: If `True`, this item is the initial selection.
|
|
258
|
+
Defaults to `False`.
|
|
259
|
+
on_click: Callback fired on selection.
|
|
260
|
+
key: Unique string key. Auto-generated if omitted.
|
|
261
|
+
|
|
262
|
+
Returns:
|
|
263
|
+
The key assigned to this item.
|
|
264
|
+
"""
|
|
265
|
+
from tkinter import StringVar
|
|
266
|
+
if not hasattr(self, "_radio_variable"):
|
|
267
|
+
self._radio_variable = StringVar(master=self._internal)
|
|
268
|
+
str_value = str(value) if value is not None else label
|
|
269
|
+
if selected:
|
|
270
|
+
self._radio_variable.set(str_value)
|
|
271
|
+
kw: dict[str, Any] = {
|
|
272
|
+
"text": label,
|
|
273
|
+
"value": str_value,
|
|
274
|
+
"variable": self._radio_variable,
|
|
275
|
+
}
|
|
276
|
+
if on_click is not None:
|
|
277
|
+
kw["command"] = on_click
|
|
278
|
+
if key is not None:
|
|
279
|
+
kw["key"] = key
|
|
280
|
+
result = self._internal.add_radiobutton(**kw)
|
|
281
|
+
return result.key if hasattr(result, "key") else key or label
|
|
282
|
+
|
|
283
|
+
def add_divider(self, *, key: str | None = None) -> None:
|
|
284
|
+
"""Add a horizontal divider to the dropdown."""
|
|
285
|
+
kw: dict[str, Any] = {}
|
|
286
|
+
if key is not None:
|
|
287
|
+
kw["key"] = key
|
|
288
|
+
self._internal.add_separator(**kw)
|
|
289
|
+
|
|
290
|
+
def add_items(self, items: list[Any]) -> None:
|
|
291
|
+
"""Add multiple items at once from a list of item dicts.
|
|
292
|
+
|
|
293
|
+
Each dict must have a `type` key plus item-specific keys:
|
|
294
|
+
|
|
295
|
+
.. code-block:: python
|
|
296
|
+
|
|
297
|
+
mb.add_items([
|
|
298
|
+
{"type": "command", "text": "Edit", "icon": "pencil", "on_click": edit},
|
|
299
|
+
{"type": "command", "text": "Delete", "icon": "trash", "on_click": delete},
|
|
300
|
+
{"type": "divider"},
|
|
301
|
+
{"type": "check", "text": "Pinned", "value": True},
|
|
302
|
+
{"type": "radio", "text": "Small", "value": "sm"},
|
|
303
|
+
])
|
|
304
|
+
|
|
305
|
+
Args:
|
|
306
|
+
items: List of item dicts. `type` accepts `'command'`,
|
|
307
|
+
`'check'`, `'radio'`, or `'divider'`; an item's
|
|
308
|
+
`on_click` key sets its per-item callback.
|
|
309
|
+
"""
|
|
310
|
+
self._internal.add_items([_translate_item(it) for it in items])
|
|
311
|
+
|
|
312
|
+
def insert_item(self, index: int, type: str, **kwargs: Any) -> str:
|
|
313
|
+
"""Insert a new item at a specific position.
|
|
314
|
+
|
|
315
|
+
Args:
|
|
316
|
+
index: Zero-based position to insert at.
|
|
317
|
+
type: Item type — `'command'`, `'check'`, `'radio'`,
|
|
318
|
+
or `'divider'`.
|
|
319
|
+
**kwargs: Forwarded to the matching `add_*` method.
|
|
320
|
+
|
|
321
|
+
Returns:
|
|
322
|
+
The key assigned to the new item.
|
|
323
|
+
"""
|
|
324
|
+
if "on_click" in kwargs:
|
|
325
|
+
kwargs["command"] = kwargs.pop("on_click")
|
|
326
|
+
result = self._internal.insert_item(index, _resolve_item_type(type), **kwargs)
|
|
327
|
+
return result.key if hasattr(result, "key") else result
|
|
328
|
+
|
|
329
|
+
def move_item(self, key: str, to_index: int) -> None:
|
|
330
|
+
"""Move an existing item to a new position.
|
|
331
|
+
|
|
332
|
+
Args:
|
|
333
|
+
key: Key of the item to move.
|
|
334
|
+
to_index: Target zero-based index.
|
|
335
|
+
"""
|
|
336
|
+
self._internal.move_item(key, to_index)
|
|
337
|
+
|
|
338
|
+
def update_item(self, key: str, **kwargs: Any) -> None:
|
|
339
|
+
"""Reconfigure a dropdown item after creation.
|
|
340
|
+
|
|
341
|
+
Args:
|
|
342
|
+
key: Key returned by an `add_*` method.
|
|
343
|
+
**kwargs: Options forwarded to the item's configure method.
|
|
344
|
+
"""
|
|
345
|
+
self._internal.configure_item(key, **kwargs)
|
|
346
|
+
|
|
347
|
+
def remove_item(self, key: str) -> None:
|
|
348
|
+
"""Remove a dropdown item by key.
|
|
349
|
+
|
|
350
|
+
Args:
|
|
351
|
+
key: Key returned by an `add_*` method.
|
|
352
|
+
"""
|
|
353
|
+
self._internal.remove_item(key)
|
|
354
|
+
|
|
355
|
+
def show_menu(self) -> None:
|
|
356
|
+
"""Open the dropdown menu programmatically.
|
|
357
|
+
|
|
358
|
+
Has no effect if the button is disabled or read-only.
|
|
359
|
+
"""
|
|
360
|
+
if not self._internal.instate(("!disabled", "!readonly")):
|
|
361
|
+
return
|
|
362
|
+
self._internal.show_menu()
|
|
363
|
+
|
|
364
|
+
# ----- Properties -----
|
|
365
|
+
|
|
366
|
+
def item(self, key: str) -> Any:
|
|
367
|
+
"""Return the item object for `key`.
|
|
368
|
+
|
|
369
|
+
Args:
|
|
370
|
+
key: Key returned by an `add_*` method.
|
|
371
|
+
"""
|
|
372
|
+
return self._internal.context_menu.item(key)
|
|
373
|
+
|
|
374
|
+
@property
|
|
375
|
+
def items(self) -> list[Any]:
|
|
376
|
+
"""All menu items in insertion order."""
|
|
377
|
+
return self._internal.items() or []
|
|
378
|
+
|
|
379
|
+
@property
|
|
380
|
+
def keys(self) -> tuple[str, ...]:
|
|
381
|
+
"""Keys of all menu items in insertion order."""
|
|
382
|
+
return self._internal.keys()
|
|
383
|
+
|
|
384
|
+
@property
|
|
385
|
+
def menu(self) -> Any:
|
|
386
|
+
"""The underlying `ContextMenu` — for advanced programmatic access."""
|
|
387
|
+
return self._internal.context_menu
|
|
388
|
+
|
|
389
|
+
@property
|
|
390
|
+
def text(self) -> str:
|
|
391
|
+
"""The button's label text.
|
|
392
|
+
|
|
393
|
+
Reading reflects a bound `textsignal` (the option stays synced from
|
|
394
|
+
the variable). Setting writes through the bound variable when one
|
|
395
|
+
owns the text — keeping the signal in sync — and falls back to the
|
|
396
|
+
option otherwise. On an icon-only button the label stays hidden;
|
|
397
|
+
the setter still updates the underlying text.
|
|
398
|
+
"""
|
|
399
|
+
return str(self._internal.cget("text"))
|
|
400
|
+
|
|
401
|
+
@text.setter
|
|
402
|
+
def text(self, value: str) -> None:
|
|
403
|
+
# When a textsignal/textvariable owns the text, ttk ignores the `text`
|
|
404
|
+
# option — write through the variable instead (which also keeps the
|
|
405
|
+
# bound signal in sync). Falls back to the option when unbound.
|
|
406
|
+
textvar = getattr(self._internal, "_textvariable", None)
|
|
407
|
+
if textvar is not None:
|
|
408
|
+
textvar.set(value)
|
|
409
|
+
else:
|
|
410
|
+
self._internal.configure(text=value)
|
|
411
|
+
|
|
412
|
+
@property
|
|
413
|
+
def disabled(self) -> bool:
|
|
414
|
+
"""Whether the button is non-interactive."""
|
|
415
|
+
return self._internal.instate(("disabled",))
|
|
416
|
+
|
|
417
|
+
@disabled.setter
|
|
418
|
+
def disabled(self, v: bool) -> None:
|
|
419
|
+
self._internal.configure(state="disabled" if v else "normal")
|