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,358 @@
|
|
|
1
|
+
"""FilterDialog - A dialog for filtering and selecting multiple items from a list.
|
|
2
|
+
|
|
3
|
+
This module provides a multi-select dialog with optional search and select-all
|
|
4
|
+
functionality. Items can be displayed with checkboxes, and the dialog supports
|
|
5
|
+
both standard and undecorated (custom-chrome) display modes.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from tkinter import Widget
|
|
9
|
+
from typing import Any, Callable, Literal, Optional, Tuple, Union
|
|
10
|
+
from types import SimpleNamespace
|
|
11
|
+
|
|
12
|
+
from bootstack.widgets._impl.primitives import CheckButton, Frame, Label, Separator
|
|
13
|
+
from bootstack.widgets.types import Master
|
|
14
|
+
from bootstack.widgets._impl.composites.textentry import TextEntry
|
|
15
|
+
from bootstack._runtime.app import Window
|
|
16
|
+
from bootstack.dialogs._impl.dialog import Dialog, DialogButton
|
|
17
|
+
from bootstack.widgets._impl.composites.scrollview import ScrollView
|
|
18
|
+
from bootstack.widgets._impl.primitives.flexframe import FlexFrame
|
|
19
|
+
from bootstack._runtime.window_utilities import AnchorPoint
|
|
20
|
+
|
|
21
|
+
ttk = SimpleNamespace(
|
|
22
|
+
Checkbutton=CheckButton,
|
|
23
|
+
Frame=Frame,
|
|
24
|
+
Label=Label,
|
|
25
|
+
Separator=Separator,
|
|
26
|
+
TextEntry=TextEntry,
|
|
27
|
+
Window=Window,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class FilterDialogContent(ttk.Frame):
|
|
32
|
+
"""Internal content frame for FilterDialog.
|
|
33
|
+
|
|
34
|
+
This frame contains the search box, select-all checkbox, and scrollable
|
|
35
|
+
list of checkboxes for filtering items.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
def __init__(
|
|
39
|
+
self,
|
|
40
|
+
master: Master = None,
|
|
41
|
+
enable_search: bool = False,
|
|
42
|
+
enable_select_all: bool = False,
|
|
43
|
+
items: list[str | dict[str, Any]] = None
|
|
44
|
+
):
|
|
45
|
+
"""Initialize the FilterDialogContent frame.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
master: Parent widget. If None, uses the default root window.
|
|
49
|
+
enable_search: If True, includes a search box to filter items by text.
|
|
50
|
+
enable_select_all: If True, includes a "Select All" checkbox.
|
|
51
|
+
items: List of items to display. Can be strings or dicts with keys:
|
|
52
|
+
- text (str): Display text (required for dict items)
|
|
53
|
+
- value (Any): Value to return when selected (defaults to text)
|
|
54
|
+
- selected (bool): Initial selection state (defaults to False)
|
|
55
|
+
"""
|
|
56
|
+
super().__init__(master)
|
|
57
|
+
self._enable_search = enable_search
|
|
58
|
+
self._enable_select_all = enable_select_all
|
|
59
|
+
self._selected_items = []
|
|
60
|
+
self._items = self._normalize_items(items)
|
|
61
|
+
self._filter: str | None = None
|
|
62
|
+
self._check_buttons: dict[str, ttk.Checkbutton] = {}
|
|
63
|
+
self._select_all_cb: ttk.Checkbutton | None = None
|
|
64
|
+
self._scroll_container: ttk.Frame | None = None
|
|
65
|
+
self._build_content()
|
|
66
|
+
|
|
67
|
+
def _normalize_items(self, items: list[str | dict[str, Any]] | None) -> list[dict[str, Any]]:
|
|
68
|
+
"""Normalize items to a consistent dict format.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
items: List of strings or dicts representing items.
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
List of dicts with 'text', 'value', and 'selected' keys.
|
|
75
|
+
|
|
76
|
+
Raises:
|
|
77
|
+
ValueError: If a dict item is missing the 'text' key.
|
|
78
|
+
"""
|
|
79
|
+
if items is None:
|
|
80
|
+
return []
|
|
81
|
+
|
|
82
|
+
out = []
|
|
83
|
+
for item in items:
|
|
84
|
+
if isinstance(item, str):
|
|
85
|
+
out.append(dict(text=item, value=item, selected=False))
|
|
86
|
+
else:
|
|
87
|
+
if 'text' not in item:
|
|
88
|
+
raise ValueError('Item must have "text" key')
|
|
89
|
+
|
|
90
|
+
if 'selected' not in item:
|
|
91
|
+
item['selected'] = False
|
|
92
|
+
item.setdefault('value', item['text'])
|
|
93
|
+
if item['selected']:
|
|
94
|
+
self._selected_items.append(item['value'])
|
|
95
|
+
out.append(item)
|
|
96
|
+
return out
|
|
97
|
+
|
|
98
|
+
def _build_content(self):
|
|
99
|
+
"""Build and layout all UI components."""
|
|
100
|
+
# Search box
|
|
101
|
+
if self._enable_search:
|
|
102
|
+
search_entry = ttk.TextEntry(self)
|
|
103
|
+
search_entry.insert_addon(ttk.Label, 'before', icon='search')
|
|
104
|
+
search_entry.pack(fill='x')
|
|
105
|
+
search_entry.on_input(self._on_search_input)
|
|
106
|
+
|
|
107
|
+
# Select all checkbox
|
|
108
|
+
if self._enable_select_all:
|
|
109
|
+
self._select_all_cb = ttk.Checkbutton(self, text='edit.select_all')
|
|
110
|
+
self._select_all_cb.invoke()
|
|
111
|
+
self._select_all_cb.invoke()
|
|
112
|
+
self._select_all_cb['command'] = self._handle_select_all
|
|
113
|
+
self._select_all_cb.pack(fill='x', padx=8, pady=(12, 8))
|
|
114
|
+
ttk.Separator(self).pack(fill='x')
|
|
115
|
+
|
|
116
|
+
# Scrollable container for checkboxes
|
|
117
|
+
scroll_view = ScrollView(
|
|
118
|
+
self,
|
|
119
|
+
scroll_direction='vertical',
|
|
120
|
+
scrollbar_visibility='always',
|
|
121
|
+
scrollbar_variant='thin'
|
|
122
|
+
)
|
|
123
|
+
scroll_view.pack(fill='both', expand=False, pady=(8, 0))
|
|
124
|
+
scroll_view.configure(height=230)
|
|
125
|
+
|
|
126
|
+
# Managed flex content frame — the same one the public ScrollView uses
|
|
127
|
+
# (direction='vertical', horizontal_items='stretch'), so rows fill the
|
|
128
|
+
# viewport width and the canvas sizing is handled for us. Replaces the old
|
|
129
|
+
# raw frame, which hand-rolled the width-stretch and clipped at the edge.
|
|
130
|
+
self._scroll_container = FlexFrame(
|
|
131
|
+
scroll_view.canvas, direction='vertical', horizontal_items='stretch'
|
|
132
|
+
)
|
|
133
|
+
scroll_view.add(self._scroll_container)
|
|
134
|
+
|
|
135
|
+
# Add item checkboxes
|
|
136
|
+
for item in self._items:
|
|
137
|
+
cb = ttk.Checkbutton(self._scroll_container, text=item['text'])
|
|
138
|
+
cb.invoke()
|
|
139
|
+
if not item['selected']:
|
|
140
|
+
cb.invoke()
|
|
141
|
+
cb['command'] = lambda value=item['value']: self._on_item_clicked(value)
|
|
142
|
+
self._scroll_container.add_child(cb, {'padx': 8, 'pady': 8})
|
|
143
|
+
self._check_buttons[item['text']] = cb
|
|
144
|
+
|
|
145
|
+
def _handle_select_all(self):
|
|
146
|
+
"""Toggle selection state of all checkboxes."""
|
|
147
|
+
if 'selected' in self._select_all_cb.state():
|
|
148
|
+
for item in self._check_buttons.values():
|
|
149
|
+
item.instate(['!selected'], item.invoke)
|
|
150
|
+
else:
|
|
151
|
+
for item in self._check_buttons.values():
|
|
152
|
+
item.instate(['selected'], item.invoke)
|
|
153
|
+
|
|
154
|
+
def _on_search_input(self, event):
|
|
155
|
+
"""Filter visible checkboxes based on search text."""
|
|
156
|
+
self._filter = (event.data.text or '').lower()
|
|
157
|
+
|
|
158
|
+
# Re-flow only the matching rows, in their original order.
|
|
159
|
+
for cb in self._check_buttons.values():
|
|
160
|
+
self._scroll_container.remove_child(cb)
|
|
161
|
+
for key, cb in self._check_buttons.items():
|
|
162
|
+
if self._filter in key.lower():
|
|
163
|
+
self._scroll_container.add_child(cb, {'padx': 8, 'pady': 8})
|
|
164
|
+
|
|
165
|
+
def _on_item_clicked(self, value):
|
|
166
|
+
"""Update selected items list when a checkbox is clicked."""
|
|
167
|
+
if value in self._selected_items:
|
|
168
|
+
self._selected_items.remove(value)
|
|
169
|
+
else:
|
|
170
|
+
self._selected_items.append(value)
|
|
171
|
+
|
|
172
|
+
def get_selected_items(self):
|
|
173
|
+
"""Return the list of selected item values."""
|
|
174
|
+
return self._selected_items
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
class FilterDialog(ttk.Frame):
|
|
178
|
+
"""A dialog for filtering and selecting multiple items from a list.
|
|
179
|
+
|
|
180
|
+
This dialog displays a list of checkboxes with optional search and select-all
|
|
181
|
+
functionality. When the user clicks OK, the selected values are stored in
|
|
182
|
+
the result property.
|
|
183
|
+
|
|
184
|
+
Attributes:
|
|
185
|
+
result (list[Any] | None): List of selected values after dialog is closed,
|
|
186
|
+
or None if canceled.
|
|
187
|
+
"""
|
|
188
|
+
|
|
189
|
+
def __init__(
|
|
190
|
+
self,
|
|
191
|
+
master: Master = None,
|
|
192
|
+
title: str = "Filter",
|
|
193
|
+
items: list[str | dict[str, Any]] = None,
|
|
194
|
+
enable_search: bool = False,
|
|
195
|
+
enable_select_all: bool = False,
|
|
196
|
+
undecorated: bool = False
|
|
197
|
+
):
|
|
198
|
+
"""Initialize the FilterDialog.
|
|
199
|
+
|
|
200
|
+
Args:
|
|
201
|
+
master: Parent widget. If None, uses the default root window.
|
|
202
|
+
title: Dialog window title.
|
|
203
|
+
items: List of items to display. Can be strings or dicts with keys:
|
|
204
|
+
- text (str): Display text (required for dict items)
|
|
205
|
+
- value (Any): Value to return when selected (defaults to text)
|
|
206
|
+
- selected (bool): Initial selection state (defaults to False)
|
|
207
|
+
enable_search: If True, includes a search box to filter items by text.
|
|
208
|
+
enable_select_all: If True, includes a "Select All" checkbox.
|
|
209
|
+
undecorated: If True, removes window decorations and displays with a
|
|
210
|
+
border frame. Enables dismiss-on-outside-click behavior.
|
|
211
|
+
"""
|
|
212
|
+
super().__init__(master)
|
|
213
|
+
self._master = master if master else self.master
|
|
214
|
+
self._title = title
|
|
215
|
+
self._items = items or []
|
|
216
|
+
self._enable_search = enable_search
|
|
217
|
+
self._enable_select_all = enable_select_all
|
|
218
|
+
self._undecorated = undecorated
|
|
219
|
+
self._content: FilterDialogContent | None = None
|
|
220
|
+
self._dialog: Dialog | None = None
|
|
221
|
+
self.result: list[Any] | None = None
|
|
222
|
+
|
|
223
|
+
def _build_content(self, parent):
|
|
224
|
+
"""Build the dialog content with FilterDialogContent."""
|
|
225
|
+
self._content = FilterDialogContent(
|
|
226
|
+
master=parent,
|
|
227
|
+
enable_search=self._enable_search,
|
|
228
|
+
enable_select_all=self._enable_select_all,
|
|
229
|
+
items=self._items
|
|
230
|
+
)
|
|
231
|
+
padding = 0 if self._undecorated else 10
|
|
232
|
+
self._content.pack(fill='both', expand=True, padx=padding, pady=padding)
|
|
233
|
+
|
|
234
|
+
# Setup dismiss-on-click for undecorated after dialog is built
|
|
235
|
+
if self._undecorated:
|
|
236
|
+
parent.after(10, self._setup_undecorated_dismiss)
|
|
237
|
+
|
|
238
|
+
def _on_ok(self, dialog: Dialog):
|
|
239
|
+
"""Save selected items to result when OK button is clicked."""
|
|
240
|
+
if self._content:
|
|
241
|
+
self.result = self._content.get_selected_items()
|
|
242
|
+
# Generate selection changed event on confirmation
|
|
243
|
+
if self.result is not None:
|
|
244
|
+
self.event_generate('<<SelectionChange>>', data={"selected": self.result.copy()})
|
|
245
|
+
|
|
246
|
+
def on_selection_changed(self, callback: Callable) -> str:
|
|
247
|
+
"""Bind to `<<SelectionChange>>`. Callback receives `event.data = {"selected": list[Any]}`.
|
|
248
|
+
|
|
249
|
+
Returns:
|
|
250
|
+
Binding identifier for use with off_selection_changed().
|
|
251
|
+
"""
|
|
252
|
+
return self.bind('<<SelectionChange>>', callback, add=True)
|
|
253
|
+
|
|
254
|
+
def off_selection_changed(self, bind_id: str = None):
|
|
255
|
+
"""Unbind callback from <<SelectionChange>> event.
|
|
256
|
+
|
|
257
|
+
Args:
|
|
258
|
+
bind_id: Binding identifier from on_selection_changed().
|
|
259
|
+
"""
|
|
260
|
+
self.unbind('<<SelectionChange>>', bind_id)
|
|
261
|
+
|
|
262
|
+
def _on_click(self, event):
|
|
263
|
+
"""Check if click is outside dialog and dismiss if so."""
|
|
264
|
+
if not self._dialog or not self._dialog.toplevel:
|
|
265
|
+
return
|
|
266
|
+
|
|
267
|
+
try:
|
|
268
|
+
# Get dialog window bounds
|
|
269
|
+
x = self._dialog.toplevel.winfo_rootx()
|
|
270
|
+
y = self._dialog.toplevel.winfo_rooty()
|
|
271
|
+
w = self._dialog.toplevel.winfo_width()
|
|
272
|
+
h = self._dialog.toplevel.winfo_height()
|
|
273
|
+
|
|
274
|
+
# Check if click is outside dialog
|
|
275
|
+
if not (x <= event.x_root <= x + w and y <= event.y_root <= y + h):
|
|
276
|
+
self._dialog.toplevel.destroy()
|
|
277
|
+
except:
|
|
278
|
+
pass
|
|
279
|
+
|
|
280
|
+
def _setup_undecorated_dismiss(self):
|
|
281
|
+
"""Setup dismiss-on-outside-click for undecorated dialogs."""
|
|
282
|
+
if self._undecorated and self._dialog and self._dialog.toplevel:
|
|
283
|
+
# Bind to root window to catch all clicks
|
|
284
|
+
root = self._dialog.toplevel.winfo_toplevel()
|
|
285
|
+
while root.master:
|
|
286
|
+
root = root.master.winfo_toplevel()
|
|
287
|
+
root.bind('<Button-1>', self._on_click, add='+')
|
|
288
|
+
|
|
289
|
+
def show(
|
|
290
|
+
self,
|
|
291
|
+
position: Optional[Tuple[int, int]] = None,
|
|
292
|
+
modal: Optional[bool] = None,
|
|
293
|
+
*,
|
|
294
|
+
anchor_to: Optional[Union[Widget, Literal["screen", "cursor", "parent"]]] = None,
|
|
295
|
+
anchor_point: AnchorPoint = 'center',
|
|
296
|
+
window_point: AnchorPoint = 'center',
|
|
297
|
+
offset: Tuple[int, int] = (0, 0),
|
|
298
|
+
auto_flip: Union[bool, Literal['vertical', 'horizontal']] = False
|
|
299
|
+
) -> Optional[list[Any]]:
|
|
300
|
+
"""Show the dialog and return the selected items.
|
|
301
|
+
|
|
302
|
+
Args:
|
|
303
|
+
position: Optional (x, y) coordinates to position the dialog.
|
|
304
|
+
If provided, takes precedence over anchor-based positioning.
|
|
305
|
+
modal: Override the mode's default modality.
|
|
306
|
+
If None, uses True (modal mode).
|
|
307
|
+
anchor_to: Positioning target. Can be:
|
|
308
|
+
- Widget: Anchor to a specific widget
|
|
309
|
+
- "screen": Anchor to screen edges/corners
|
|
310
|
+
- "cursor": Anchor to mouse cursor location
|
|
311
|
+
- "parent": Anchor to parent window (same as widget)
|
|
312
|
+
- None: Centers on parent (default)
|
|
313
|
+
anchor_point: Point on the anchor target (n, s, e, w, ne, nw, se, sw, center).
|
|
314
|
+
Default 'center'.
|
|
315
|
+
window_point: Point on the dialog window (n, s, e, w, ne, nw, se, sw, center).
|
|
316
|
+
Default 'center'.
|
|
317
|
+
offset: Additional (x, y) offset in pixels from the anchor position.
|
|
318
|
+
auto_flip: Smart positioning to keep window on screen.
|
|
319
|
+
- False: No flipping (default)
|
|
320
|
+
- True: Flip both vertically and horizontally as needed
|
|
321
|
+
- 'vertical': Only flip up/down
|
|
322
|
+
- 'horizontal': Only flip left/right
|
|
323
|
+
|
|
324
|
+
Returns:
|
|
325
|
+
List of selected item values, or None if canceled.
|
|
326
|
+
"""
|
|
327
|
+
self._dialog: Dialog = Dialog(
|
|
328
|
+
parent=self._master,
|
|
329
|
+
title=self._title,
|
|
330
|
+
content_builder=self._build_content,
|
|
331
|
+
_raw_content=True,
|
|
332
|
+
buttons=[
|
|
333
|
+
DialogButton(text="button.cancel", role="cancel", result=None),
|
|
334
|
+
DialogButton(
|
|
335
|
+
text="button.ok",
|
|
336
|
+
role="primary",
|
|
337
|
+
result=True,
|
|
338
|
+
default=True,
|
|
339
|
+
command=self._on_ok
|
|
340
|
+
)
|
|
341
|
+
],
|
|
342
|
+
min_size=(250, 200),
|
|
343
|
+
max_size=(250, 380),
|
|
344
|
+
resizable=(False, True),
|
|
345
|
+
mode="modal",
|
|
346
|
+
undecorated=self._undecorated
|
|
347
|
+
)
|
|
348
|
+
|
|
349
|
+
self._dialog.show(
|
|
350
|
+
position=position,
|
|
351
|
+
modal=modal,
|
|
352
|
+
anchor_to=anchor_to,
|
|
353
|
+
anchor_point=anchor_point,
|
|
354
|
+
window_point=window_point,
|
|
355
|
+
offset=offset,
|
|
356
|
+
auto_flip=auto_flip
|
|
357
|
+
)
|
|
358
|
+
return self.result
|