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,486 @@
1
+ """Message dialogs and messagebox facade for bootstack."""
2
+
3
+ import logging
4
+ import textwrap
5
+ import tkinter
6
+ from types import SimpleNamespace
7
+ from typing import Any, Callable, List, Optional
8
+
9
+ from bootstack.widgets._impl.primitives import Frame, Label
10
+ from bootstack._core.images import _ImageService
11
+ from bootstack.constants import *
12
+ from bootstack.i18n import MessageCatalog
13
+ from .dialog import ButtonRole, Dialog, DialogButton
14
+
15
+ ttk = SimpleNamespace(Frame=Frame, Label=Label)
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+
20
+ class MessageDialog:
21
+ """A simple modal dialog class that can be used to build simple
22
+ message dialogs.
23
+
24
+ Displays a message and a set of buttons. Each of the buttons in the
25
+ message window is identified by a unique symbolic name. After the
26
+ message window is popped up, the message box awaits for the user to
27
+ select one of the buttons. Then it returns the symbolic name of the
28
+ selected button. Use a `Toplevel` widget for more advanced modal
29
+ dialog designs.
30
+
31
+ """
32
+
33
+ def __init__(
34
+ self,
35
+ message: str,
36
+ title: str = " ",
37
+ buttons: Optional[List[str]] = None,
38
+ command: Optional[Callable[[], None]] = None,
39
+ width: int = 50,
40
+ master: Optional[tkinter.Misc] = None,
41
+ alert: bool = False,
42
+ default: Optional[str] = None,
43
+ padding: tuple[int, int] | int = (20, 20),
44
+ icon: Optional[str | dict] = None,
45
+ **kwargs: Any,
46
+ ) -> None:
47
+ """Create a message dialog.
48
+
49
+ Args:
50
+ message: The message text to display. Supports multiline strings.
51
+ title: The dialog window title.
52
+ buttons: List of button labels. Can specify an accent as
53
+ "label:accent" (e.g., "OK:primary"). If None, defaults to
54
+ ["Cancel", "OK"].
55
+ command: Optional callback function to execute when any button is pressed.
56
+ width: Maximum width in characters for text wrapping.
57
+ master: Parent widget for the dialog.
58
+ alert: If True, rings the system bell when shown.
59
+ default: The button label to use as default. Receives the primary accent and focus.
60
+ padding: Padding around the message content.
61
+ icon: Optional icon specification. Can be a string (icon name) or dict with
62
+ keys: 'name' (required), 'size' (default 32), 'color' (optional).
63
+ **kwargs: Additional keyword arguments. Supports 'localize' to enable translation.
64
+ """
65
+ self._message = message
66
+ self._command = command
67
+ self._width = width
68
+ self._padding = padding
69
+ self._icon = icon
70
+ self._localize = kwargs.get("localize")
71
+ self._img = None # Store icon image to prevent garbage collection
72
+
73
+ if buttons is None:
74
+ # Use semantic keys - widgets now have built-in localization
75
+ button_labels = [
76
+ "button.cancel",
77
+ "button.ok",
78
+ ]
79
+ else:
80
+ button_labels = buttons
81
+
82
+ # Parse button labels and create DialogButton specs
83
+ button_specs = self._parse_buttons(button_labels, default)
84
+
85
+ # Create the underlying dialog
86
+ self._dialog = Dialog(
87
+ title=title,
88
+ content_builder=self._create_content,
89
+ _raw_content=True,
90
+ buttons=button_specs,
91
+ alert=alert,
92
+ min_size=(300, 100),
93
+ parent=master,
94
+ )
95
+ self._master = master
96
+
97
+ def _create_content(self, parent: tkinter.Widget) -> None:
98
+ """Create the message body with optional icon."""
99
+ container = ttk.Frame(parent, padding=self._padding)
100
+
101
+ if self._icon:
102
+ try:
103
+ # Parse icon specification - initialize variables
104
+ icon_name: Optional[str] = None
105
+ icon_size: int = 32
106
+ icon_color: Optional[str] = None
107
+
108
+ if isinstance(self._icon, str):
109
+ icon_name = self._icon
110
+ elif isinstance(self._icon, dict):
111
+ icon_name = self._icon.get("name")
112
+ icon_size = self._icon.get("size", 32)
113
+ icon_color = self._icon.get("color")
114
+ else:
115
+ logger.warning("Invalid icon specification: %s", self._icon)
116
+
117
+ # Generate icon image
118
+ if icon_name:
119
+ if icon_color:
120
+ icon_image = _ImageService.get_icon(icon_name, icon_size, icon_color)
121
+ else:
122
+ icon_image = _ImageService.get_icon(icon_name, icon_size, "#000000")
123
+
124
+ self._img = icon_image
125
+ icon_lbl = ttk.Label(container, image=self._img)
126
+ icon_lbl.pack(side=LEFT, anchor=N, padx=(0, 10))
127
+
128
+ except Exception as e:
129
+ logger.warning("Failed to create icon: %s", e)
130
+
131
+ if self._message:
132
+ for msg in self._message.split("\n"):
133
+ message = "\n".join(textwrap.wrap(msg, width=self._width))
134
+ message_label = ttk.Label(container, text=message)
135
+ message_label.pack(pady=(0, 3), fill=X, anchor=N)
136
+ container.pack(fill=X, expand=True)
137
+
138
+ def _parse_buttons(self, button_labels: List[str], default: Optional[str]) -> List[DialogButton]:
139
+ """Parse button label strings into DialogButton specifications."""
140
+ button_specs: List[DialogButton] = []
141
+
142
+ for i, button in enumerate(button_labels):
143
+ # Parse "text:accent" format
144
+ cnf = button.split(":")
145
+ text = cnf[0]
146
+
147
+ # Apply localization if enabled
148
+ if self._localize:
149
+ text = MessageCatalog.translate(text)
150
+
151
+ # Determine if this is the default button
152
+ is_default = (text == default) if default else (i == len(button_labels) - 1)
153
+
154
+ # Determine accent
155
+ if len(cnf) == 2:
156
+ accent = cnf[1]
157
+ elif is_default:
158
+ accent = "primary"
159
+ else:
160
+ accent = "default"
161
+
162
+ # Determine button role
163
+ role: ButtonRole
164
+ if accent == "primary":
165
+ role = "primary"
166
+ elif i == 0 and "cancel" in text.lower():
167
+ role = "cancel"
168
+ else:
169
+ role = "secondary"
170
+
171
+ # Create button specification
172
+ button_specs.append(
173
+ DialogButton(
174
+ text=text,
175
+ role=role,
176
+ result=text,
177
+ accent=accent if accent != role else None,
178
+ default=is_default,
179
+ command=self._make_command_callback() if self._command else None,
180
+ )
181
+ )
182
+
183
+ return button_specs
184
+
185
+ def _make_command_callback(self) -> Callable[[Dialog], None]:
186
+ """Create a callback wrapper for the custom command."""
187
+
188
+ def callback(dialog: Dialog) -> None:
189
+ if self._command:
190
+ self._command()
191
+
192
+ return callback
193
+
194
+ def show(self, position: Optional[tuple[int, int]] = None) -> None:
195
+ """Show the dialog.
196
+
197
+ Args:
198
+ position: x and y coordinates to position the dialog. If None, centers on parent.
199
+ """
200
+ self._dialog.show(position=position, modal=True)
201
+ target = self._dialog.toplevel or self._master
202
+ if target:
203
+ payload = {"result": self._dialog.result, "confirmed": self._dialog.result is not None}
204
+ try:
205
+ target.event_generate("<<DialogResult>>", data=payload)
206
+ except Exception:
207
+ try:
208
+ target.event_generate("<<DialogResult>>")
209
+ except Exception:
210
+ pass
211
+
212
+ @property
213
+ def result(self) -> Any:
214
+ """The dialog result value (the text of the button pressed)."""
215
+ return self._dialog.result
216
+
217
+ def on_dialog_result(self, callback: Callable[[Any], None]) -> Optional[str]:
218
+ """Bind a callback fired when the dialog produces a result.
219
+
220
+ The callback receives `event.data["result"]` when available.
221
+
222
+ Args:
223
+ callback: Callable that receives the result payload.
224
+
225
+ Returns:
226
+ Binding identifier for use with `off_dialog_result`.
227
+ """
228
+ target = self._dialog.toplevel or self._master
229
+ if target is None:
230
+ return None
231
+
232
+ def handler(event):
233
+ callback(getattr(event, "data", None))
234
+
235
+ return target.bind("<<DialogResult>>", handler, add="+")
236
+
237
+ def off_dialog_result(self, funcid: str) -> None:
238
+ """Unbind a previously bound dialog result callback."""
239
+ target = self._dialog.toplevel or self._master
240
+ if target is None:
241
+ return
242
+ target.unbind("<<DialogResult>>", funcid)
243
+
244
+
245
+ class MessageBox:
246
+ """Static methods for displaying standard message dialogs."""
247
+
248
+ @staticmethod
249
+ def _show(
250
+ message: str,
251
+ title: str = " ",
252
+ master: Optional[tkinter.Misc] = None,
253
+ alert: bool = False,
254
+ buttons: Optional[List[str]] = None,
255
+ icon: Optional[str] = None,
256
+ on_result: Optional[Callable[[Any], None]] = None,
257
+ **kwargs: Any,
258
+ ) -> Optional[str]:
259
+ """Internal helper to show a message dialog.
260
+
261
+ Args:
262
+ message: The message text to display.
263
+ title: The dialog window title.
264
+ master: Parent widget for the dialog.
265
+ alert: If True, rings the system bell.
266
+ buttons: List of button labels.
267
+ icon: Optional icon to display.
268
+ on_result: Optional callback receiving the dialog result payload.
269
+ **kwargs: Additional arguments including 'position'.
270
+
271
+ Returns:
272
+ The text of the button pressed, or None.
273
+ """
274
+ position = kwargs.pop("position", None)
275
+ dialog = MessageDialog(
276
+ message=message,
277
+ title=title,
278
+ master=master,
279
+ alert=alert,
280
+ buttons=buttons,
281
+ icon=icon,
282
+ localize=True,
283
+ **kwargs,
284
+ )
285
+ if on_result:
286
+ dialog.on_dialog_result(on_result)
287
+ dialog.show(position)
288
+ return dialog.result
289
+
290
+ @staticmethod
291
+ def show_info(
292
+ message: str,
293
+ title: str = " ",
294
+ master: Optional[tkinter.Misc] = None,
295
+ alert: bool = False,
296
+ **kwargs: Any,
297
+ ) -> Optional[str]:
298
+ """Display an info dialog with OK button and info icon.
299
+
300
+ Args:
301
+ message: The message text to display.
302
+ title: The dialog window title.
303
+ master: Parent widget for the dialog.
304
+ alert: If True, rings the system bell.
305
+ **kwargs: Additional arguments including 'position'.
306
+
307
+ Returns:
308
+ The text of the button pressed.
309
+ """
310
+ return MessageBox._show(message, title, master, alert, ["OK:primary"], "info-circle-fill", **kwargs)
311
+
312
+ @staticmethod
313
+ def show_warning(
314
+ message: str,
315
+ title: str = " ",
316
+ master: Optional[tkinter.Misc] = None,
317
+ alert: bool = True,
318
+ **kwargs: Any,
319
+ ) -> Optional[str]:
320
+ """Display a warning dialog with OK button and warning icon.
321
+
322
+ Args:
323
+ message: The message text to display.
324
+ title: The dialog window title.
325
+ master: Parent widget for the dialog.
326
+ alert: If True, rings the system bell.
327
+ **kwargs: Additional arguments including 'position'.
328
+
329
+ Returns:
330
+ The text of the button pressed.
331
+ """
332
+ return MessageBox._show(message, title, master, alert, ["OK:primary"], "exclamation-triangle-fill", **kwargs)
333
+
334
+ @staticmethod
335
+ def show_error(
336
+ message: str,
337
+ title: str = " ",
338
+ master: Optional[tkinter.Misc] = None,
339
+ alert: bool = True,
340
+ **kwargs: Any,
341
+ ) -> Optional[str]:
342
+ """Display an error dialog with OK button and error icon.
343
+
344
+ Args:
345
+ message: The message text to display.
346
+ title: The dialog window title.
347
+ master: Parent widget for the dialog.
348
+ alert: If True, rings the system bell.
349
+ **kwargs: Additional arguments including 'position'.
350
+
351
+ Returns:
352
+ The text of the button pressed.
353
+ """
354
+ return MessageBox._show(message, title, master, alert, ["OK:primary"], "x-circle-fill", **kwargs)
355
+
356
+ @staticmethod
357
+ def show_question(
358
+ message: str,
359
+ title: str = " ",
360
+ master: Optional[tkinter.Misc] = None,
361
+ alert: bool = False,
362
+ **kwargs: Any,
363
+ ) -> Optional[str]:
364
+ """Display a question dialog with OK button and question icon.
365
+
366
+ Args:
367
+ message: The message text to display.
368
+ title: The dialog window title.
369
+ master: Parent widget for the dialog.
370
+ alert: If True, rings the system bell.
371
+ **kwargs: Additional arguments including 'position'.
372
+
373
+ Returns:
374
+ The text of the button pressed.
375
+ """
376
+ return MessageBox._show(message, title, master, alert, ["OK:primary"], "question-circle-fill", **kwargs)
377
+
378
+ @staticmethod
379
+ def ok(
380
+ message: str,
381
+ title: str = " ",
382
+ master: Optional[tkinter.Misc] = None,
383
+ alert: bool = False,
384
+ **kwargs: Any,
385
+ ) -> Optional[str]:
386
+ """Display a dialog with an OK button.
387
+
388
+ Args:
389
+ message: The message text to display.
390
+ title: The dialog window title.
391
+ master: Parent widget for the dialog.
392
+ alert: If True, rings the system bell.
393
+ **kwargs: Additional arguments including 'position'.
394
+
395
+ Returns:
396
+ The text of the button pressed.
397
+ """
398
+ return MessageBox._show(message, title, master, alert, ["OK:primary"], None, **kwargs)
399
+
400
+ @staticmethod
401
+ def okcancel(
402
+ message: str,
403
+ title: str = " ",
404
+ master: Optional[tkinter.Misc] = None,
405
+ alert: bool = False,
406
+ **kwargs: Any,
407
+ ) -> Optional[str]:
408
+ """Display a dialog with OK and Cancel buttons.
409
+
410
+ Args:
411
+ message: The message text to display.
412
+ title: The dialog window title.
413
+ master: Parent widget for the dialog.
414
+ alert: If True, rings the system bell.
415
+ **kwargs: Additional arguments including 'position'.
416
+
417
+ Returns:
418
+ The text of the button pressed.
419
+ """
420
+ return MessageBox._show(message, title, master, alert, ["Cancel", "OK"], None, **kwargs)
421
+
422
+ @staticmethod
423
+ def yesno(
424
+ message: str,
425
+ title: str = " ",
426
+ master: Optional[tkinter.Misc] = None,
427
+ alert: bool = False,
428
+ **kwargs: Any,
429
+ ) -> Optional[str]:
430
+ """Display a dialog with Yes and No buttons.
431
+
432
+ Args:
433
+ message: The message text to display.
434
+ title: The dialog window title.
435
+ master: Parent widget for the dialog.
436
+ alert: If True, rings the system bell.
437
+ **kwargs: Additional arguments including 'position'.
438
+
439
+ Returns:
440
+ The text of the button pressed.
441
+ """
442
+ return MessageBox._show(message, title, master, alert, ["No", "Yes"], None, **kwargs)
443
+
444
+ @staticmethod
445
+ def yesnocancel(
446
+ message: str,
447
+ title: str = " ",
448
+ master: Optional[tkinter.Misc] = None,
449
+ alert: bool = False,
450
+ **kwargs: Any,
451
+ ) -> Optional[str]:
452
+ """Display a dialog with Yes, No, and Cancel buttons.
453
+
454
+ Args:
455
+ message: The message text to display.
456
+ title: The dialog window title.
457
+ master: Parent widget for the dialog.
458
+ alert: If True, rings the system bell.
459
+ **kwargs: Additional arguments including 'position'.
460
+
461
+ Returns:
462
+ The text of the button pressed.
463
+ """
464
+ return MessageBox._show(message, title, master, alert, ["Cancel", "No", "Yes"], None, **kwargs)
465
+
466
+ @staticmethod
467
+ def retrycancel(
468
+ message: str,
469
+ title: str = " ",
470
+ master: Optional[tkinter.Misc] = None,
471
+ alert: bool = False,
472
+ **kwargs: Any,
473
+ ) -> Optional[str]:
474
+ """Display a dialog with Retry and Cancel buttons.
475
+
476
+ Args:
477
+ message: The message text to display.
478
+ title: The dialog window title.
479
+ master: Parent widget for the dialog.
480
+ alert: If True, rings the system bell.
481
+ **kwargs: Additional arguments including 'position'.
482
+
483
+ Returns:
484
+ The text of the button pressed.
485
+ """
486
+ return MessageBox._show(message, title, master, alert, ["Cancel", "Retry"], None, **kwargs)