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.
Files changed (471) hide show
  1. bootstack/__init__.py +157 -0
  2. bootstack/__main__.py +5 -0
  3. bootstack/_core/__init__.py +21 -0
  4. bootstack/_core/capabilities/__init__.py +45 -0
  5. bootstack/_core/capabilities/after.py +103 -0
  6. bootstack/_core/capabilities/bind.py +192 -0
  7. bootstack/_core/capabilities/bindtags.py +112 -0
  8. bootstack/_core/capabilities/busy.py +72 -0
  9. bootstack/_core/capabilities/clipboard.py +89 -0
  10. bootstack/_core/capabilities/focus.py +118 -0
  11. bootstack/_core/capabilities/grab.py +65 -0
  12. bootstack/_core/capabilities/grid.py +211 -0
  13. bootstack/_core/capabilities/localization.py +231 -0
  14. bootstack/_core/capabilities/pack.py +140 -0
  15. bootstack/_core/capabilities/place.py +113 -0
  16. bootstack/_core/capabilities/selection.py +136 -0
  17. bootstack/_core/capabilities/signals.py +244 -0
  18. bootstack/_core/capabilities/winfo.py +315 -0
  19. bootstack/_core/colorutils.py +234 -0
  20. bootstack/_core/exceptions.py +25 -0
  21. bootstack/_core/images.py +463 -0
  22. bootstack/_core/mixins/__init__.py +1 -0
  23. bootstack/_core/mixins/ttk_state.py +35 -0
  24. bootstack/_core/mixins/widget.py +132 -0
  25. bootstack/_core/paths.py +49 -0
  26. bootstack/_core/publisher.py +149 -0
  27. bootstack/_core/variables.py +62 -0
  28. bootstack/_runtime/__init__.py +3 -0
  29. bootstack/_runtime/app.py +930 -0
  30. bootstack/_runtime/base_window.py +945 -0
  31. bootstack/_runtime/events.py +399 -0
  32. bootstack/_runtime/shortcuts.py +496 -0
  33. bootstack/_runtime/tk_patch.py +43 -0
  34. bootstack/_runtime/toplevel.py +276 -0
  35. bootstack/_runtime/utility.py +457 -0
  36. bootstack/_runtime/visual_focus.py +240 -0
  37. bootstack/_runtime/window_utilities.py +1123 -0
  38. bootstack/assets/__init__.py +21 -0
  39. bootstack/assets/bootstack.ico +0 -0
  40. bootstack/assets/bootstack.png +0 -0
  41. bootstack/assets/elements/__init__.py +0 -0
  42. bootstack/assets/elements/badge-pill.png +0 -0
  43. bootstack/assets/elements/badge-square.png +0 -0
  44. bootstack/assets/elements/button-compact.png +0 -0
  45. bootstack/assets/elements/button-default.png +0 -0
  46. bootstack/assets/elements/buttongroup-after-h-compact.png +0 -0
  47. bootstack/assets/elements/buttongroup-after-h-default.png +0 -0
  48. bootstack/assets/elements/buttongroup-after-v-compact.png +0 -0
  49. bootstack/assets/elements/buttongroup-after-v-default.png +0 -0
  50. bootstack/assets/elements/buttongroup-before-h-compact.png +0 -0
  51. bootstack/assets/elements/buttongroup-before-h-default.png +0 -0
  52. bootstack/assets/elements/buttongroup-before-v-compact.png +0 -0
  53. bootstack/assets/elements/buttongroup-before-v-default.png +0 -0
  54. bootstack/assets/elements/buttongroup-center-h-compact.png +0 -0
  55. bootstack/assets/elements/buttongroup-center-h-default.png +0 -0
  56. bootstack/assets/elements/buttongroup-center-v-compact.png +0 -0
  57. bootstack/assets/elements/buttongroup-center-v-default.png +0 -0
  58. bootstack/assets/elements/card.png +0 -0
  59. bootstack/assets/elements/checkbox-checked.png +0 -0
  60. bootstack/assets/elements/checkbox-indeterminate.png +0 -0
  61. bootstack/assets/elements/checkbox-unchecked.png +0 -0
  62. bootstack/assets/elements/field.png +0 -0
  63. bootstack/assets/elements/input-addon-compact.png +0 -0
  64. bootstack/assets/elements/input-addon-default.png +0 -0
  65. bootstack/assets/elements/input-compact.png +0 -0
  66. bootstack/assets/elements/input-default.png +0 -0
  67. bootstack/assets/elements/list-item-separated.png +0 -0
  68. bootstack/assets/elements/list-item.png +0 -0
  69. bootstack/assets/elements/listrow-compact.png +0 -0
  70. bootstack/assets/elements/listrow-default.png +0 -0
  71. bootstack/assets/elements/manifest.toml +361 -0
  72. bootstack/assets/elements/menu-item.png +0 -0
  73. bootstack/assets/elements/navitem-compact.png +0 -0
  74. bootstack/assets/elements/navitem-default.png +0 -0
  75. bootstack/assets/elements/progressbar-h-compact.png +0 -0
  76. bootstack/assets/elements/progressbar-h-default.png +0 -0
  77. bootstack/assets/elements/progressbar-v-compact.png +0 -0
  78. bootstack/assets/elements/progressbar-v-default.png +0 -0
  79. bootstack/assets/elements/radiobutton.png +0 -0
  80. bootstack/assets/elements/scrollbar-horizontal.png +0 -0
  81. bootstack/assets/elements/scrollbar-vertical.png +0 -0
  82. bootstack/assets/elements/slider-handle.png +0 -0
  83. bootstack/assets/elements/slider-track-h.png +0 -0
  84. bootstack/assets/elements/slider-track-v.png +0 -0
  85. bootstack/assets/elements/switch-off.png +0 -0
  86. bootstack/assets/elements/switch-on.png +0 -0
  87. bootstack/assets/elements/tab-h.png +0 -0
  88. bootstack/assets/elements/tab-v.png +0 -0
  89. bootstack/assets/icons/bootstrap.ttf +0 -0
  90. bootstack/assets/icons/glyphmap.json +2080 -0
  91. bootstack/assets/icons/icon_metrics.json +12470 -0
  92. bootstack/assets/locales/ar/LC_MESSAGES/bootstack.mo +0 -0
  93. bootstack/assets/locales/ar/LC_MESSAGES/bootstack.po +856 -0
  94. bootstack/assets/locales/bg/LC_MESSAGES/bootstack.mo +0 -0
  95. bootstack/assets/locales/bg/LC_MESSAGES/bootstack.po +878 -0
  96. bootstack/assets/locales/cs/LC_MESSAGES/bootstack.mo +0 -0
  97. bootstack/assets/locales/cs/LC_MESSAGES/bootstack.po +856 -0
  98. bootstack/assets/locales/da/LC_MESSAGES/bootstack.mo +0 -0
  99. bootstack/assets/locales/da/LC_MESSAGES/bootstack.po +856 -0
  100. bootstack/assets/locales/de/LC_MESSAGES/bootstack.mo +0 -0
  101. bootstack/assets/locales/de/LC_MESSAGES/bootstack.po +856 -0
  102. bootstack/assets/locales/en/LC_MESSAGES/bootstack.mo +0 -0
  103. bootstack/assets/locales/en/LC_MESSAGES/bootstack.po +878 -0
  104. bootstack/assets/locales/es/LC_MESSAGES/bootstack.mo +0 -0
  105. bootstack/assets/locales/es/LC_MESSAGES/bootstack.po +856 -0
  106. bootstack/assets/locales/fr/LC_MESSAGES/bootstack.mo +0 -0
  107. bootstack/assets/locales/fr/LC_MESSAGES/bootstack.po +856 -0
  108. bootstack/assets/locales/he/LC_MESSAGES/bootstack.mo +0 -0
  109. bootstack/assets/locales/he/LC_MESSAGES/bootstack.po +854 -0
  110. bootstack/assets/locales/hi/LC_MESSAGES/bootstack.mo +0 -0
  111. bootstack/assets/locales/hi/LC_MESSAGES/bootstack.po +845 -0
  112. bootstack/assets/locales/it/LC_MESSAGES/bootstack.mo +0 -0
  113. bootstack/assets/locales/it/LC_MESSAGES/bootstack.po +844 -0
  114. bootstack/assets/locales/ja/LC_MESSAGES/bootstack.mo +0 -0
  115. bootstack/assets/locales/ja/LC_MESSAGES/bootstack.po +917 -0
  116. bootstack/assets/locales/ko/LC_MESSAGES/bootstack.mo +0 -0
  117. bootstack/assets/locales/ko/LC_MESSAGES/bootstack.po +845 -0
  118. bootstack/assets/locales/nb/LC_MESSAGES/bootstack.mo +0 -0
  119. bootstack/assets/locales/nb/LC_MESSAGES/bootstack.po +844 -0
  120. bootstack/assets/locales/nl/LC_MESSAGES/bootstack.mo +0 -0
  121. bootstack/assets/locales/nl/LC_MESSAGES/bootstack.po +844 -0
  122. bootstack/assets/locales/pl/LC_MESSAGES/bootstack.mo +0 -0
  123. bootstack/assets/locales/pl/LC_MESSAGES/bootstack.po +845 -0
  124. bootstack/assets/locales/pt/LC_MESSAGES/bootstack.mo +0 -0
  125. bootstack/assets/locales/pt/LC_MESSAGES/bootstack.po +845 -0
  126. bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.mo +0 -0
  127. bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.po +845 -0
  128. bootstack/assets/locales/sl/LC_MESSAGES/bootstack.mo +0 -0
  129. bootstack/assets/locales/sl/LC_MESSAGES/bootstack.po +845 -0
  130. bootstack/assets/locales/sv/LC_MESSAGES/bootstack.mo +0 -0
  131. bootstack/assets/locales/sv/LC_MESSAGES/bootstack.po +845 -0
  132. bootstack/assets/locales/tr/LC_MESSAGES/bootstack.mo +0 -0
  133. bootstack/assets/locales/tr/LC_MESSAGES/bootstack.po +845 -0
  134. bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.mo +0 -0
  135. bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.po +845 -0
  136. bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.mo +0 -0
  137. bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.po +845 -0
  138. bootstack/cli/__init__.py +133 -0
  139. bootstack/cli/__main__.py +6 -0
  140. bootstack/cli/add.py +395 -0
  141. bootstack/cli/appicon.py +285 -0
  142. bootstack/cli/build.py +115 -0
  143. bootstack/cli/config.py +313 -0
  144. bootstack/cli/demo.py +564 -0
  145. bootstack/cli/dev.py +153 -0
  146. bootstack/cli/doctor.py +195 -0
  147. bootstack/cli/icons.py +98 -0
  148. bootstack/cli/promote.py +120 -0
  149. bootstack/cli/pyinstaller.py +268 -0
  150. bootstack/cli/run.py +95 -0
  151. bootstack/cli/start.py +117 -0
  152. bootstack/cli/templates/__init__.py +931 -0
  153. bootstack/clipboard.py +48 -0
  154. bootstack/constants.py +318 -0
  155. bootstack/data/README.md +615 -0
  156. bootstack/data/__init__.py +78 -0
  157. bootstack/data/_observable.py +276 -0
  158. bootstack/data/base.py +780 -0
  159. bootstack/data/file_source.py +367 -0
  160. bootstack/data/memory_source.py +450 -0
  161. bootstack/data/query.py +367 -0
  162. bootstack/data/readers.py +289 -0
  163. bootstack/data/sqlite_source.py +869 -0
  164. bootstack/data/types.py +354 -0
  165. bootstack/data/writers.py +232 -0
  166. bootstack/dev/__init__.py +36 -0
  167. bootstack/dev/_capture.py +141 -0
  168. bootstack/dev/_env.py +43 -0
  169. bootstack/dev/_registry.py +140 -0
  170. bootstack/dev/_reloader.py +351 -0
  171. bootstack/dev/_reset.py +50 -0
  172. bootstack/dev/_watcher.py +91 -0
  173. bootstack/dialogs/__init__.py +948 -0
  174. bootstack/dialogs/_impl/__init__.py +47 -0
  175. bootstack/dialogs/_impl/colorchooser.py +588 -0
  176. bootstack/dialogs/_impl/datedialog.py +450 -0
  177. bootstack/dialogs/_impl/dialog.py +594 -0
  178. bootstack/dialogs/_impl/filterdialog.py +358 -0
  179. bootstack/dialogs/_impl/fontdialog.py +364 -0
  180. bootstack/dialogs/_impl/formdialog.py +564 -0
  181. bootstack/dialogs/_impl/message.py +486 -0
  182. bootstack/dialogs/_impl/query.py +570 -0
  183. bootstack/errors.py +67 -0
  184. bootstack/events/__init__.py +111 -0
  185. bootstack/events/_event.py +135 -0
  186. bootstack/events/_payloads.py +539 -0
  187. bootstack/events/_subscription.py +38 -0
  188. bootstack/i18n/README.md +77 -0
  189. bootstack/i18n/__init__.py +23 -0
  190. bootstack/i18n/catalog.py +121 -0
  191. bootstack/i18n/intl_format.py +584 -0
  192. bootstack/i18n/msgcat.py +425 -0
  193. bootstack/i18n/specs.py +156 -0
  194. bootstack/images.py +563 -0
  195. bootstack/py.typed +1 -0
  196. bootstack/scheduling/__init__.py +11 -0
  197. bootstack/scheduling/_schedule.py +218 -0
  198. bootstack/shortcuts.py +21 -0
  199. bootstack/signals/README.md +98 -0
  200. bootstack/signals/__init__.py +10 -0
  201. bootstack/signals/integration.py +100 -0
  202. bootstack/signals/signal.py +353 -0
  203. bootstack/signals/types.py +6 -0
  204. bootstack/store.py +286 -0
  205. bootstack/streams/__init__.py +12 -0
  206. bootstack/streams/_stream.py +321 -0
  207. bootstack/style/__init__.py +38 -0
  208. bootstack/style/builders/__init__.py +51 -0
  209. bootstack/style/builders/badge.py +46 -0
  210. bootstack/style/builders/button.py +339 -0
  211. bootstack/style/builders/buttongroup.py +311 -0
  212. bootstack/style/builders/calendar.py +271 -0
  213. bootstack/style/builders/checkbutton.py +110 -0
  214. bootstack/style/builders/combobox.py +113 -0
  215. bootstack/style/builders/contextmenu.py +268 -0
  216. bootstack/style/builders/entry.py +82 -0
  217. bootstack/style/builders/expander.py +148 -0
  218. bootstack/style/builders/field.py +335 -0
  219. bootstack/style/builders/frame.py +50 -0
  220. bootstack/style/builders/label.py +28 -0
  221. bootstack/style/builders/labelframe.py +34 -0
  222. bootstack/style/builders/listview.py +369 -0
  223. bootstack/style/builders/menubar.py +91 -0
  224. bootstack/style/builders/menubutton.py +359 -0
  225. bootstack/style/builders/panedwindow.py +25 -0
  226. bootstack/style/builders/progressbar.py +67 -0
  227. bootstack/style/builders/radiobutton.py +99 -0
  228. bootstack/style/builders/scale.py +64 -0
  229. bootstack/style/builders/scrollbar.py +225 -0
  230. bootstack/style/builders/separator.py +49 -0
  231. bootstack/style/builders/sidenav.py +643 -0
  232. bootstack/style/builders/sizegrip.py +15 -0
  233. bootstack/style/builders/spinbox.py +119 -0
  234. bootstack/style/builders/switch.py +70 -0
  235. bootstack/style/builders/tabitem.py +204 -0
  236. bootstack/style/builders/togglegroup.py +294 -0
  237. bootstack/style/builders/toolbutton.py +275 -0
  238. bootstack/style/builders/tooltip.py +26 -0
  239. bootstack/style/builders/treeview.py +193 -0
  240. bootstack/style/builders/utils.py +455 -0
  241. bootstack/style/builders_tk/__init__.py +16 -0
  242. bootstack/style/builders_tk/defaults.py +229 -0
  243. bootstack/style/element.py +173 -0
  244. bootstack/style/fonts.py +123 -0
  245. bootstack/style/style.py +609 -0
  246. bootstack/style/style_builder_base.py +716 -0
  247. bootstack/style/style_builder_mixed.py +93 -0
  248. bootstack/style/style_builder_tk.py +109 -0
  249. bootstack/style/style_builder_ttk.py +353 -0
  250. bootstack/style/style_resolver.py +447 -0
  251. bootstack/style/theme.py +245 -0
  252. bootstack/style/theme_provider.py +471 -0
  253. bootstack/style/themes/__init__.py +128 -0
  254. bootstack/style/tk_patch.py +5 -0
  255. bootstack/style/token_maps.py +41 -0
  256. bootstack/style/types.py +32 -0
  257. bootstack/style/typography.py +523 -0
  258. bootstack/style/utility.py +746 -0
  259. bootstack/types.py +39 -0
  260. bootstack/validation/__init__.py +6 -0
  261. bootstack/validation/types.py +15 -0
  262. bootstack/validation/validation_result.py +17 -0
  263. bootstack/validation/validation_rules.py +205 -0
  264. bootstack/widgets/__init__.py +74 -0
  265. bootstack/widgets/_core/__init__.py +31 -0
  266. bootstack/widgets/_core/app_config.py +266 -0
  267. bootstack/widgets/_core/base.py +461 -0
  268. bootstack/widgets/_core/container.py +334 -0
  269. bootstack/widgets/_core/context.py +35 -0
  270. bootstack/widgets/_core/events.py +130 -0
  271. bootstack/widgets/_core/field_mixin.py +353 -0
  272. bootstack/widgets/_core/icon_image_props.py +72 -0
  273. bootstack/widgets/_core/image_binding.py +93 -0
  274. bootstack/widgets/_core/navmodel.py +345 -0
  275. bootstack/widgets/_core/options.py +210 -0
  276. bootstack/widgets/_core/selection_group.py +130 -0
  277. bootstack/widgets/_core/window_controls.py +96 -0
  278. bootstack/widgets/_core/window_menu.py +246 -0
  279. bootstack/widgets/_impl/__init__.py +1 -0
  280. bootstack/widgets/_impl/_internal/__init__.py +0 -0
  281. bootstack/widgets/_impl/_internal/wrapper_base.py +307 -0
  282. bootstack/widgets/_impl/_parts/__init__.py +11 -0
  283. bootstack/widgets/_impl/_parts/numberentry_part.py +385 -0
  284. bootstack/widgets/_impl/_parts/spinnerentry_part.py +434 -0
  285. bootstack/widgets/_impl/_parts/textentry_part.py +406 -0
  286. bootstack/widgets/_impl/composites/__init__.py +33 -0
  287. bootstack/widgets/_impl/composites/_dateutils.py +33 -0
  288. bootstack/widgets/_impl/composites/_image_fit.py +105 -0
  289. bootstack/widgets/_impl/composites/accordion.py +381 -0
  290. bootstack/widgets/_impl/composites/avatar.py +191 -0
  291. bootstack/widgets/_impl/composites/buttongroup.py +371 -0
  292. bootstack/widgets/_impl/composites/calendar.py +972 -0
  293. bootstack/widgets/_impl/composites/carousel.py +567 -0
  294. bootstack/widgets/_impl/composites/chart.py +882 -0
  295. bootstack/widgets/_impl/composites/compositeframe.py +298 -0
  296. bootstack/widgets/_impl/composites/contextmenu.py +1951 -0
  297. bootstack/widgets/_impl/composites/dateentry.py +404 -0
  298. bootstack/widgets/_impl/composites/dropdownbutton.py +325 -0
  299. bootstack/widgets/_impl/composites/expander.py +515 -0
  300. bootstack/widgets/_impl/composites/field.py +670 -0
  301. bootstack/widgets/_impl/composites/form.py +1066 -0
  302. bootstack/widgets/_impl/composites/gallery.py +551 -0
  303. bootstack/widgets/_impl/composites/list/__init__.py +15 -0
  304. bootstack/widgets/_impl/composites/list/listitem.py +802 -0
  305. bootstack/widgets/_impl/composites/list/listview.py +1433 -0
  306. bootstack/widgets/_impl/composites/menu/__init__.py +18 -0
  307. bootstack/widgets/_impl/composites/menu/model.py +358 -0
  308. bootstack/widgets/_impl/composites/menu/render_native.py +134 -0
  309. bootstack/widgets/_impl/composites/menu/render_themed.py +134 -0
  310. bootstack/widgets/_impl/composites/meter.py +860 -0
  311. bootstack/widgets/_impl/composites/numericentry.py +201 -0
  312. bootstack/widgets/_impl/composites/pagestack.py +395 -0
  313. bootstack/widgets/_impl/composites/passwordentry.py +142 -0
  314. bootstack/widgets/_impl/composites/pathentry.py +168 -0
  315. bootstack/widgets/_impl/composites/picture.py +289 -0
  316. bootstack/widgets/_impl/composites/radiogroup.py +511 -0
  317. bootstack/widgets/_impl/composites/scrolledtext.py +375 -0
  318. bootstack/widgets/_impl/composites/scrolledtext.pyi +186 -0
  319. bootstack/widgets/_impl/composites/scrollview.py +764 -0
  320. bootstack/widgets/_impl/composites/selectbox.py +1026 -0
  321. bootstack/widgets/_impl/composites/shell/__init__.py +40 -0
  322. bootstack/widgets/_impl/composites/shell/content_host.py +52 -0
  323. bootstack/widgets/_impl/composites/shell/layout.py +335 -0
  324. bootstack/widgets/_impl/composites/shell/nav_panel.py +345 -0
  325. bootstack/widgets/_impl/composites/shell/providers.py +558 -0
  326. bootstack/widgets/_impl/composites/shell/rail.py +117 -0
  327. bootstack/widgets/_impl/composites/shell/shell.py +581 -0
  328. bootstack/widgets/_impl/composites/shell/workspace.py +273 -0
  329. bootstack/widgets/_impl/composites/sidenav/__init__.py +16 -0
  330. bootstack/widgets/_impl/composites/sidenav/header.py +81 -0
  331. bootstack/widgets/_impl/composites/sidenav/separator.py +44 -0
  332. bootstack/widgets/_impl/composites/slider/__init__.py +7 -0
  333. bootstack/widgets/_impl/composites/slider/_shared.py +195 -0
  334. bootstack/widgets/_impl/composites/slider/rangeslider.py +982 -0
  335. bootstack/widgets/_impl/composites/slider/slider.py +851 -0
  336. bootstack/widgets/_impl/composites/spinnerentry.py +185 -0
  337. bootstack/widgets/_impl/composites/tableview/__init__.py +5 -0
  338. bootstack/widgets/_impl/composites/tableview/tableview.py +3388 -0
  339. bootstack/widgets/_impl/composites/tableview/types.py +169 -0
  340. bootstack/widgets/_impl/composites/tabs/__init__.py +23 -0
  341. bootstack/widgets/_impl/composites/tabs/tabitem.py +389 -0
  342. bootstack/widgets/_impl/composites/tabs/tabs.py +974 -0
  343. bootstack/widgets/_impl/composites/tabs/tabview.py +650 -0
  344. bootstack/widgets/_impl/composites/textarea/__init__.py +26 -0
  345. bootstack/widgets/_impl/composites/textarea/change.py +46 -0
  346. bootstack/widgets/_impl/composites/textarea/codeeditor.py +526 -0
  347. bootstack/widgets/_impl/composites/textarea/core.py +495 -0
  348. bootstack/widgets/_impl/composites/textarea/decoration.py +42 -0
  349. bootstack/widgets/_impl/composites/textarea/diff.py +127 -0
  350. bootstack/widgets/_impl/composites/textarea/extensions/__init__.py +1 -0
  351. bootstack/widgets/_impl/composites/textarea/extensions/bracket_matcher.py +138 -0
  352. bootstack/widgets/_impl/composites/textarea/extensions/indent_guides.py +158 -0
  353. bootstack/widgets/_impl/composites/textarea/extensions/line_numbers.py +138 -0
  354. bootstack/widgets/_impl/composites/textarea/extensions/pygments_highlighter.py +312 -0
  355. bootstack/widgets/_impl/composites/textarea/extensions/smart_indent.py +177 -0
  356. bootstack/widgets/_impl/composites/textarea/filter.py +171 -0
  357. bootstack/widgets/_impl/composites/textarea/search_overlay.py +459 -0
  358. bootstack/widgets/_impl/composites/textarea/sidebar.py +88 -0
  359. bootstack/widgets/_impl/composites/textarea/style_registry.py +178 -0
  360. bootstack/widgets/_impl/composites/textarea/textarea.py +606 -0
  361. bootstack/widgets/_impl/composites/textarea/undo.py +217 -0
  362. bootstack/widgets/_impl/composites/textentry.py +57 -0
  363. bootstack/widgets/_impl/composites/timeentry.py +176 -0
  364. bootstack/widgets/_impl/composites/toast.py +390 -0
  365. bootstack/widgets/_impl/composites/toast_stack.py +156 -0
  366. bootstack/widgets/_impl/composites/togglegroup.py +418 -0
  367. bootstack/widgets/_impl/composites/toolbar.py +608 -0
  368. bootstack/widgets/_impl/composites/tooltip.py +491 -0
  369. bootstack/widgets/_impl/composites/tree/__init__.py +7 -0
  370. bootstack/widgets/_impl/composites/tree/source_binding.py +136 -0
  371. bootstack/widgets/_impl/composites/tree/treeitem.py +393 -0
  372. bootstack/widgets/_impl/composites/tree/treenode.py +174 -0
  373. bootstack/widgets/_impl/composites/tree/treeview.py +841 -0
  374. bootstack/widgets/_impl/mixins/__init__.py +24 -0
  375. bootstack/widgets/_impl/mixins/configure_mixin.py +216 -0
  376. bootstack/widgets/_impl/mixins/entry_mixin.py +134 -0
  377. bootstack/widgets/_impl/mixins/font_mixin.py +368 -0
  378. bootstack/widgets/_impl/mixins/icon_mixin.py +61 -0
  379. bootstack/widgets/_impl/mixins/localization_mixin.py +253 -0
  380. bootstack/widgets/_impl/mixins/signal_mixin.py +268 -0
  381. bootstack/widgets/_impl/mixins/validation_mixin.py +226 -0
  382. bootstack/widgets/_impl/primitives/__init__.py +49 -0
  383. bootstack/widgets/_impl/primitives/_menubutton.py +107 -0
  384. bootstack/widgets/_impl/primitives/badge.py +45 -0
  385. bootstack/widgets/_impl/primitives/button.py +76 -0
  386. bootstack/widgets/_impl/primitives/card.py +45 -0
  387. bootstack/widgets/_impl/primitives/checkbutton.py +124 -0
  388. bootstack/widgets/_impl/primitives/checktoggle.py +62 -0
  389. bootstack/widgets/_impl/primitives/combobox.py +156 -0
  390. bootstack/widgets/_impl/primitives/entry.py +87 -0
  391. bootstack/widgets/_impl/primitives/flexframe.py +448 -0
  392. bootstack/widgets/_impl/primitives/frame.py +185 -0
  393. bootstack/widgets/_impl/primitives/gridframe.py +546 -0
  394. bootstack/widgets/_impl/primitives/label.py +84 -0
  395. bootstack/widgets/_impl/primitives/labelframe.py +54 -0
  396. bootstack/widgets/_impl/primitives/optionmenu.py +387 -0
  397. bootstack/widgets/_impl/primitives/packframe.py +227 -0
  398. bootstack/widgets/_impl/primitives/panedwindow.py +45 -0
  399. bootstack/widgets/_impl/primitives/progressbar.py +83 -0
  400. bootstack/widgets/_impl/primitives/radiobutton.py +115 -0
  401. bootstack/widgets/_impl/primitives/radiotoggle.py +54 -0
  402. bootstack/widgets/_impl/primitives/scrollbar.py +42 -0
  403. bootstack/widgets/_impl/primitives/separator.py +43 -0
  404. bootstack/widgets/_impl/primitives/sizegrip.py +33 -0
  405. bootstack/widgets/_impl/primitives/spinbox.py +95 -0
  406. bootstack/widgets/_impl/primitives/switch.py +44 -0
  407. bootstack/widgets/_impl/primitives/treeview.py +69 -0
  408. bootstack/widgets/app.py +371 -0
  409. bootstack/widgets/appshell.py +1179 -0
  410. bootstack/widgets/avatar.py +140 -0
  411. bootstack/widgets/boolean_controls.py +455 -0
  412. bootstack/widgets/button.py +224 -0
  413. bootstack/widgets/buttongroup.py +239 -0
  414. bootstack/widgets/calendar.py +195 -0
  415. bootstack/widgets/card.py +159 -0
  416. bootstack/widgets/carousel.py +241 -0
  417. bootstack/widgets/chart.py +302 -0
  418. bootstack/widgets/codeeditor.py +675 -0
  419. bootstack/widgets/contextmenu.py +371 -0
  420. bootstack/widgets/datatable.py +688 -0
  421. bootstack/widgets/datefield.py +395 -0
  422. bootstack/widgets/divider.py +60 -0
  423. bootstack/widgets/expander.py +579 -0
  424. bootstack/widgets/form.py +200 -0
  425. bootstack/widgets/gallery.py +250 -0
  426. bootstack/widgets/gauge.py +168 -0
  427. bootstack/widgets/grid.py +121 -0
  428. bootstack/widgets/groupbox.py +162 -0
  429. bootstack/widgets/label.py +229 -0
  430. bootstack/widgets/listview.py +354 -0
  431. bootstack/widgets/menubutton.py +419 -0
  432. bootstack/widgets/numberfield.py +431 -0
  433. bootstack/widgets/pagestack.py +345 -0
  434. bootstack/widgets/passwordfield.py +383 -0
  435. bootstack/widgets/pathfield.py +454 -0
  436. bootstack/widgets/picture.py +251 -0
  437. bootstack/widgets/progressbar.py +106 -0
  438. bootstack/widgets/radio_variants.py +271 -0
  439. bootstack/widgets/radiogroup.py +228 -0
  440. bootstack/widgets/scrollbar.py +64 -0
  441. bootstack/widgets/scrollview.py +186 -0
  442. bootstack/widgets/select.py +302 -0
  443. bootstack/widgets/selectbutton.py +182 -0
  444. bootstack/widgets/sidebar_toggle.py +130 -0
  445. bootstack/widgets/sizegrip.py +42 -0
  446. bootstack/widgets/slider.py +408 -0
  447. bootstack/widgets/spinbox.py +147 -0
  448. bootstack/widgets/spinnerfield.py +413 -0
  449. bootstack/widgets/splash.py +367 -0
  450. bootstack/widgets/splitview.py +482 -0
  451. bootstack/widgets/stacks.py +249 -0
  452. bootstack/widgets/statusbar.py +189 -0
  453. bootstack/widgets/tabs.py +425 -0
  454. bootstack/widgets/textarea.py +459 -0
  455. bootstack/widgets/textfield.py +410 -0
  456. bootstack/widgets/theme_toggle.py +92 -0
  457. bootstack/widgets/timefield.py +340 -0
  458. bootstack/widgets/toast.py +314 -0
  459. bootstack/widgets/togglegroup.py +231 -0
  460. bootstack/widgets/toolbar.py +347 -0
  461. bootstack/widgets/tooltip.py +94 -0
  462. bootstack/widgets/tree.py +648 -0
  463. bootstack/widgets/types.py +305 -0
  464. bootstack/widgets/window.py +307 -0
  465. bootstack-0.1.0.dist-info/METADATA +301 -0
  466. bootstack-0.1.0.dist-info/RECORD +471 -0
  467. bootstack-0.1.0.dist-info/WHEEL +5 -0
  468. bootstack-0.1.0.dist-info/entry_points.txt +2 -0
  469. bootstack-0.1.0.dist-info/licenses/LICENSE +21 -0
  470. bootstack-0.1.0.dist-info/licenses/NOTICE +10 -0
  471. bootstack-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,218 @@
1
+ from __future__ import annotations
2
+
3
+ import time
4
+ import tkinter as tk
5
+ from datetime import datetime
6
+ from typing import Any, Callable, Optional
7
+
8
+
9
+ class Job:
10
+ """Handle for a scheduled task.
11
+
12
+ Returned by every `Schedule` method. Call `.cancel()` to stop a pending
13
+ job before it fires. Truthy while active, falsy once cancelled or complete.
14
+ """
15
+
16
+ __slots__ = ("_owner", "_after_id", "_active", "_discard")
17
+
18
+ def __init__(self, owner: tk.Misc, discard: Callable[[], None]) -> None:
19
+ self._owner = owner
20
+ self._after_id: Optional[str] = None
21
+ self._active: bool = True
22
+ self._discard = discard
23
+
24
+ def cancel(self) -> None:
25
+ """Cancel the job if it has not already fired or been cancelled."""
26
+ if not self._active:
27
+ return
28
+ try:
29
+ if self._after_id is not None:
30
+ self._owner.after_cancel(self._after_id)
31
+ except Exception:
32
+ pass
33
+ finally:
34
+ self._after_id = None
35
+ self._active = False
36
+ self._discard()
37
+
38
+ def __bool__(self) -> bool:
39
+ return self._active
40
+
41
+ def __repr__(self) -> str:
42
+ state = "active" if self._active else "cancelled"
43
+ return f"<Job {state}>"
44
+
45
+
46
+ class Schedule:
47
+ """Timed task scheduler tied to a widget's lifetime.
48
+
49
+ Runs callbacks after a delay, at idle, at an absolute time, or on a repeat,
50
+ with automatic cleanup: all pending jobs are cancelled when the owner widget
51
+ is destroyed.
52
+
53
+ Usage::
54
+
55
+ sched = widget.schedule # property on every public widget
56
+ sched = Schedule(widget) # or construct directly
57
+
58
+ job = sched.delay(500, callback) # one-shot after delay
59
+ sched.idle(callback) # one-shot at next idle
60
+ sched.at(datetime(...), callback) # one-shot at absolute time
61
+ job = sched.every(1000, tick) # repeating every 1 second
62
+
63
+ job.cancel() # cancel one job
64
+ sched.cancel_all() # cancel everything
65
+
66
+ All jobs are automatically cancelled when `owner` is destroyed.
67
+
68
+ Args:
69
+ owner: Widget that owns this scheduler. Its lifetime bounds all created
70
+ jobs.
71
+ """
72
+
73
+ __slots__ = ("_owner", "_jobs")
74
+
75
+ def __init__(self, owner: Any) -> None:
76
+ # Accept both public wrapper widgets and the underlying widget object.
77
+ if hasattr(owner, "_internal"):
78
+ owner = owner._internal
79
+ self._owner: tk.Misc = owner
80
+ self._jobs: set[Job] = set()
81
+ try:
82
+ owner.bind("<Destroy>", self._on_destroy, add=True)
83
+ except Exception:
84
+ pass
85
+
86
+ # ----- public API --------------------------------------------------------
87
+
88
+ def delay(self, ms: int, fn: Callable, *args: Any, **kwargs: Any) -> Job:
89
+ """Schedule `fn` to run once after `ms` milliseconds.
90
+
91
+ Args:
92
+ ms: Delay in milliseconds (clamped to 0).
93
+ fn: Callable to invoke.
94
+ *args: Positional arguments forwarded to `fn`.
95
+ **kwargs: Keyword arguments forwarded to `fn`.
96
+
97
+ Returns:
98
+ Job handle — call `.cancel()` to prevent execution.
99
+ """
100
+ ms = max(0, int(ms))
101
+ job = Job(self._owner, lambda: self._jobs.discard(job))
102
+
103
+ def _run():
104
+ job._after_id = None
105
+ if job._active:
106
+ job._active = False
107
+ self._jobs.discard(job)
108
+ fn(*args, **kwargs)
109
+
110
+ job._after_id = self._owner.after(ms, _run)
111
+ self._jobs.add(job)
112
+ return job
113
+
114
+ def idle(self, fn: Callable, *args: Any, **kwargs: Any) -> Job:
115
+ """Schedule `fn` to run once when the event loop is next idle.
116
+
117
+ Args:
118
+ fn: Callable to invoke.
119
+ *args: Positional arguments forwarded to `fn`.
120
+ **kwargs: Keyword arguments forwarded to `fn`.
121
+
122
+ Returns:
123
+ Job handle — call `.cancel()` to prevent execution.
124
+ """
125
+ job = Job(self._owner, lambda: self._jobs.discard(job))
126
+
127
+ def _run():
128
+ job._after_id = None
129
+ if job._active:
130
+ job._active = False
131
+ self._jobs.discard(job)
132
+ fn(*args, **kwargs)
133
+
134
+ job._after_id = self._owner.after_idle(_run)
135
+ self._jobs.add(job)
136
+ return job
137
+
138
+ def at(self, when: datetime, fn: Callable, *args: Any, **kwargs: Any) -> Job:
139
+ """Schedule `fn` to run at an absolute `datetime`.
140
+
141
+ If `when` is in the past the job runs as soon as possible.
142
+
143
+ Args:
144
+ when: Target `datetime` (local time).
145
+ fn: Callable to invoke.
146
+ *args: Positional arguments forwarded to `fn`.
147
+ **kwargs: Keyword arguments forwarded to `fn`.
148
+
149
+ Returns:
150
+ Job handle.
151
+ """
152
+ delay_ms = max(0, int((when - datetime.now()).total_seconds() * 1000))
153
+ return self.delay(delay_ms, fn, *args, **kwargs)
154
+
155
+ def every(self, ms: int, fn: Callable, *args: Any, **kwargs: Any) -> Job:
156
+ """Schedule `fn` to run repeatedly every `ms` milliseconds.
157
+
158
+ Compensates for callback execution time to reduce drift. If the
159
+ callback raises an exception the interval is stopped and the exception
160
+ is re-raised into the application's error handler.
161
+
162
+ Args:
163
+ ms: Period in milliseconds (minimum 1).
164
+ fn: Callable to invoke on each tick.
165
+ *args: Positional arguments forwarded to `fn`.
166
+ **kwargs: Keyword arguments forwarded to `fn`.
167
+
168
+ Returns:
169
+ Job handle — call `.cancel()` to stop the repeating task.
170
+ """
171
+ period = max(1, int(ms))
172
+ job = Job(self._owner, lambda: self._jobs.discard(job))
173
+
174
+ def _tick():
175
+ if not job._active:
176
+ return
177
+ start = time.perf_counter()
178
+ try:
179
+ fn(*args, **kwargs)
180
+ except Exception:
181
+ # Stop the interval cleanly before re-raising.
182
+ job._active = False
183
+ job._after_id = None
184
+ self._jobs.discard(job)
185
+ raise
186
+ if job._active:
187
+ elapsed = int((time.perf_counter() - start) * 1000)
188
+ next_ms = max(0, period - elapsed)
189
+ try:
190
+ job._after_id = self._owner.after(next_ms, _tick)
191
+ except Exception:
192
+ job._active = False
193
+ job._after_id = None
194
+ self._jobs.discard(job)
195
+
196
+ job._after_id = self._owner.after(period, _tick)
197
+ self._jobs.add(job)
198
+ return job
199
+
200
+ def cancel_all(self) -> None:
201
+ """Cancel all pending jobs created by this `Schedule`."""
202
+ for j in list(self._jobs):
203
+ try:
204
+ j.cancel()
205
+ except Exception:
206
+ pass
207
+ self._jobs.clear()
208
+
209
+ # ----- internal ----------------------------------------------------------
210
+
211
+ def _on_destroy(self, event: Any = None) -> None:
212
+ # `<Destroy>` propagates up from descendants, so this handler fires
213
+ # whenever any child of the owner is destroyed. Only cancel the owner's
214
+ # jobs when the owner itself is going away — otherwise destroying a child
215
+ # widget would wipe out unrelated scheduled work on its ancestors.
216
+ if event is not None and getattr(event, "widget", None) is not self._owner:
217
+ return
218
+ self.cancel_all()
bootstack/shortcuts.py ADDED
@@ -0,0 +1,21 @@
1
+ """Cross-platform keyboard shortcuts — the public home for the shortcut service.
2
+
3
+ Register named shortcuts with platform-agnostic patterns (`Mod+S` becomes
4
+ `Ctrl+S` on Windows/Linux and `⌘S` on macOS), bind them to an app, and let
5
+ menus display the resolved shortcut text automatically.
6
+
7
+ Usage::
8
+
9
+ from bootstack.shortcuts import get_shortcuts
10
+
11
+ shortcuts = get_shortcuts()
12
+ shortcuts.register("save", "Mod+S", save_file)
13
+ shortcuts.bind_to(app)
14
+ """
15
+ from bootstack._runtime.shortcuts import Shortcut, Shortcuts, get_shortcuts
16
+
17
+ __all__ = [
18
+ "Shortcuts",
19
+ "Shortcut",
20
+ "get_shortcuts",
21
+ ]
@@ -0,0 +1,98 @@
1
+ Signals for bootstack
2
+ =====================
3
+
4
+ Lightweight reactive state. A ``Signal[T]`` holds a value, notifies subscribers
5
+ when it changes, and can be bound two-way to widgets. It is backed by a Tk
6
+ variable, but that variable is created lazily, so the Tk surface never leaks
7
+ into the public API.
8
+
9
+ > The user-facing guide is ``docs/reference/signals.rst`` (teaching) and the
10
+ > API Reference page for ``bootstack.signals`` (lookup). This README covers the
11
+ > package internals; keep it in sync with ``signal.py``.
12
+
13
+ Architecture
14
+ - ``Signal[T]`` (public): the reactive cell — ``signal()`` to read, ``set()`` to
15
+ write, ``subscribe()`` to observe, ``map()`` to derive.
16
+ - Lazy Tk-var realization: ``Signal(...)`` creates **no** Tk variable at
17
+ construction, so a signal can be created at module level (before any ``App``).
18
+ The backing variable is realized on first bind/escape-hatch access against the
19
+ running interpreter, and re-realized cleanly across ``App`` lifecycles.
20
+ - Object mode: values that are not Tk-native (anything other than
21
+ ``bool``/``int``/``float``/``str``/``set`` — e.g. a ``date`` or a dataclass)
22
+ are held as the authoritative Python object; the Tk variable is used only as a
23
+ change-notification bus. Native values are stored in the Tk variable directly.
24
+ - ``_SignalTrace`` (internal): manages the Tcl variable trace
25
+ (``trace_add``/``trace_remove``).
26
+
27
+ Key behaviors
28
+ - Read / write: ``signal()`` returns the current value; ``signal.set(v)`` updates
29
+ it. A ``set()`` to an equal value is a no-op (no notification).
30
+ - Subscriptions: ``subscribe(callback, *, immediate=False)`` returns a
31
+ ``streams.Handle``; call ``handle.cancel()`` to unsubscribe. ``immediate=True``
32
+ fires the callback once with the current value at subscribe time.
33
+ - Derived signals: ``map(transform)`` returns a new signal that follows this one.
34
+ A weak reference keeps the parent from holding the derived signal alive.
35
+ - Robustness: the last value is cached and returned even if the backing variable
36
+ has been dropped (e.g. between ``App`` lifecycles).
37
+ - Escape hatch: ``Signal.from_variable(tk_var)`` wraps an existing Tk variable,
38
+ and ``signal.var`` exposes the backing variable. These are the only Tk-aware
39
+ paths; everything else stays Tk-free.
40
+
41
+ Usage
42
+ 1) Quick start (works at module level — no ``App`` required)
43
+ ```python
44
+ from bootstack.signals import Signal
45
+
46
+ count = Signal(0)
47
+ print(count()) # -> 0
48
+ count.set(1)
49
+ print(count()) # -> 1
50
+ ```
51
+
52
+ 2) Two-way binding to a widget
53
+ ```python
54
+ import bootstack as bs
55
+
56
+ with bs.App() as app:
57
+ name = bs.Signal("")
58
+ bs.TextField(textsignal=name) # edits flow into the signal
59
+ bs.Label(textsignal=name.map(lambda v: f"Hello, {v}!")) # derived display
60
+ app.run()
61
+ ```
62
+
63
+ 3) Subscribing and unsubscribing
64
+ ```python
65
+ import bootstack as bs
66
+
67
+ with bs.App() as app:
68
+ flag = bs.Signal(False)
69
+
70
+ def on_flag(value):
71
+ print("flag:", value)
72
+
73
+ handle = flag.subscribe(on_flag, immediate=True) # prints: flag: False
74
+ flag.set(True) # prints: flag: True
75
+ handle.cancel() # stop observing
76
+ app.run()
77
+ ```
78
+
79
+ 4) Typed (object-mode) values
80
+ ```python
81
+ from datetime import date
82
+ import bootstack as bs
83
+
84
+ with bs.App():
85
+ due = bs.Signal(date.today())
86
+ bs.DateField(signal=due) # binds the typed value
87
+ print(type(due())) # -> <class 'datetime.date'> (not str)
88
+ ```
89
+
90
+ Import path
91
+ - ``import bootstack as bs; bs.Signal``
92
+ - ``from bootstack.signals import Signal``
93
+
94
+ Notes
95
+ - The UI toolkit is not thread-safe. Marshal cross-thread updates onto the UI
96
+ via the framework's scheduling, not by touching the signal from a worker
97
+ thread.
98
+ - Keep subscriber callbacks fast; offload long-running work.
@@ -0,0 +1,10 @@
1
+ """Reactive signal primitives for bootstack widgets."""
2
+ from .signal import Signal
3
+
4
+ __all__ = [
5
+ "Signal",
6
+ ]
7
+
8
+ # TraceOperation is an internal low-level type for variable-trace callbacks
9
+ # (no public Signal method exposes it). Import it from `bootstack.signals.types`
10
+ # if internal code needs it.
@@ -0,0 +1,100 @@
1
+ """Integration helpers for using Signal with tkinter/ttk widgets.
2
+
3
+ Call `enable_widget_integration()` once early (after creating your Tk/Window)
4
+ to allow passing `Signal` objects directly to widget constructors and
5
+ `configure(...)` for options like `textvariable` and `variable`.
6
+
7
+ Without this, some environments/widgets may not coerce custom objects to the
8
+ required Tcl variable name automatically.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ from typing import Any, Iterable, Tuple
14
+
15
+ import tkinter as tk
16
+ import tkinter.ttk as ttk
17
+
18
+
19
+ def _is_signal(obj: Any) -> bool:
20
+ try:
21
+ # Cheap duck-typing to avoid hard import dependency
22
+ m = type(obj).__module__
23
+ return (
24
+ (m.startswith("bootstack.signals") or m.startswith("bootstack.signals"))
25
+ and hasattr(obj, "name")
26
+ and hasattr(obj, "var")
27
+ )
28
+ except Exception:
29
+ return False
30
+
31
+
32
+ def _coerce_kwargs(kwargs: dict[str, Any]) -> None:
33
+ for key in ("textvariable", "variable"):
34
+ if key in kwargs:
35
+ val = kwargs[key]
36
+ if _is_signal(val):
37
+ kwargs[key] = str(val)
38
+
39
+
40
+ def _wrap_init(cls: type) -> None:
41
+ orig_init = cls.__init__ # type: ignore[attr-defined]
42
+
43
+ def __init__(self, *args: Any, **kwargs: Any) -> None: # type: ignore[override]
44
+ _coerce_kwargs(kwargs)
45
+ orig_init(self, *args, **kwargs) # type: ignore[misc]
46
+
47
+ cls.__init__ = __init__ # type: ignore[assignment]
48
+
49
+
50
+ def _wrap_configure(cls: type) -> None:
51
+ orig_config = cls.configure # type: ignore[attr-defined]
52
+
53
+ def configure(self, cnf: Any = None, **kwargs: Any): # type: ignore[override]
54
+ if isinstance(cnf, dict):
55
+ _coerce_kwargs(cnf)
56
+ _coerce_kwargs(kwargs)
57
+ return orig_config(self, cnf, **kwargs) # type: ignore[misc]
58
+
59
+ cls.configure = configure # type: ignore[assignment]
60
+ cls.config = configure # type: ignore[assignment]
61
+
62
+
63
+ def _patch(classes: Iterable[type]) -> None:
64
+ for cls in classes:
65
+ _wrap_init(cls)
66
+ _wrap_configure(cls)
67
+
68
+
69
+ def enable_widget_integration() -> None:
70
+ """Enable passing `Signal` directly to widget options.
71
+
72
+ Patches common tk/ttk widget classes so that when you pass a `Signal`
73
+ instance to `textvariable` or `variable` in the constructor or in
74
+ `configure(...)`, it is automatically converted to its Tcl name.
75
+ """
76
+
77
+ ttk_classes: Tuple[type, ...] = (
78
+ ttk.Entry,
79
+ ttk.Label,
80
+ ttk.Button,
81
+ ttk.Checkbutton,
82
+ ttk.Radiobutton,
83
+ ttk.Combobox,
84
+ ttk.Spinbox,
85
+ ttk.Progressbar,
86
+ ttk.Scale,
87
+ ttk.OptionMenu,
88
+ )
89
+
90
+ tk_classes: Tuple[type, ...] = (
91
+ tk.Entry,
92
+ tk.Label,
93
+ tk.Button,
94
+ tk.Checkbutton,
95
+ tk.Radiobutton,
96
+ )
97
+
98
+ _patch(ttk_classes)
99
+ _patch(tk_classes)
100
+