bootstack 0.1.0a1__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 (419) hide show
  1. bootstack/__init__.py +249 -0
  2. bootstack/__main__.py +5 -0
  3. bootstack/api/__init__.py +127 -0
  4. bootstack/api/app.py +30 -0
  5. bootstack/api/constants.py +3 -0
  6. bootstack/api/data.py +23 -0
  7. bootstack/api/dialogs.py +44 -0
  8. bootstack/api/i18n.py +17 -0
  9. bootstack/api/localization.py +16 -0
  10. bootstack/api/menu.py +7 -0
  11. bootstack/api/style.py +23 -0
  12. bootstack/api/utils.py +24 -0
  13. bootstack/api/widgets.py +137 -0
  14. bootstack/assets/__init__.py +24 -0
  15. bootstack/assets/bootstack-transparent.png +0 -0
  16. bootstack/assets/bootstack.ico +0 -0
  17. bootstack/assets/bootstack.png +0 -0
  18. bootstack/assets/elements/__init__.py +0 -0
  19. bootstack/assets/elements/badge-pill.png +0 -0
  20. bootstack/assets/elements/badge-square.png +0 -0
  21. bootstack/assets/elements/border.png +0 -0
  22. bootstack/assets/elements/button-compact.png +0 -0
  23. bootstack/assets/elements/button-default.png +0 -0
  24. bootstack/assets/elements/button-group-horizontal-after-compact.png +0 -0
  25. bootstack/assets/elements/button-group-horizontal-after-default.png +0 -0
  26. bootstack/assets/elements/button-group-horizontal-before-compact.png +0 -0
  27. bootstack/assets/elements/button-group-horizontal-before-default.png +0 -0
  28. bootstack/assets/elements/button-group-horizontal-center-compact.png +0 -0
  29. bootstack/assets/elements/button-group-horizontal-center-default.png +0 -0
  30. bootstack/assets/elements/button-group-vertical-after-compact.png +0 -0
  31. bootstack/assets/elements/button-group-vertical-after-default.png +0 -0
  32. bootstack/assets/elements/button-group-vertical-before-compact.png +0 -0
  33. bootstack/assets/elements/button-group-vertical-before-default.png +0 -0
  34. bootstack/assets/elements/button-group-vertical-center-compact.png +0 -0
  35. bootstack/assets/elements/button-group-vertical-center-default.png +0 -0
  36. bootstack/assets/elements/checkbox-checked.png +0 -0
  37. bootstack/assets/elements/checkbox-indeterminate.png +0 -0
  38. bootstack/assets/elements/checkbox-unchecked.png +0 -0
  39. bootstack/assets/elements/field.png +0 -0
  40. bootstack/assets/elements/input-after-compact.png +0 -0
  41. bootstack/assets/elements/input-after-default.png +0 -0
  42. bootstack/assets/elements/input-before-compact.png +0 -0
  43. bootstack/assets/elements/input-before-default.png +0 -0
  44. bootstack/assets/elements/input-compact.png +0 -0
  45. bootstack/assets/elements/input-default.png +0 -0
  46. bootstack/assets/elements/list-item-separated.png +0 -0
  47. bootstack/assets/elements/list-item.png +0 -0
  48. bootstack/assets/elements/manifest.toml +480 -0
  49. bootstack/assets/elements/menu-item.png +0 -0
  50. bootstack/assets/elements/nav-button-compact.png +0 -0
  51. bootstack/assets/elements/nav-button-default.png +0 -0
  52. bootstack/assets/elements/nav-icon-button-compact.png +0 -0
  53. bootstack/assets/elements/nav-icon-button-default.png +0 -0
  54. bootstack/assets/elements/notebook-client-border.png +0 -0
  55. bootstack/assets/elements/notebook-tab-active.png +0 -0
  56. bootstack/assets/elements/notebook-tab-bar.png +0 -0
  57. bootstack/assets/elements/notebook-tab-normal.png +0 -0
  58. bootstack/assets/elements/notebook-tab-pill.png +0 -0
  59. bootstack/assets/elements/progress-bar-horizontal-striped.png +0 -0
  60. bootstack/assets/elements/progress-bar-solid.png +0 -0
  61. bootstack/assets/elements/progress-bar-thin.png +0 -0
  62. bootstack/assets/elements/progress-bar-vertical-striped.png +0 -0
  63. bootstack/assets/elements/radio-selected.png +0 -0
  64. bootstack/assets/elements/radio-unselected.png +0 -0
  65. bootstack/assets/elements/scrollbar-horizontal.png +0 -0
  66. bootstack/assets/elements/scrollbar-vertical.png +0 -0
  67. bootstack/assets/elements/slider-handle-focus.png +0 -0
  68. bootstack/assets/elements/slider-handle.png +0 -0
  69. bootstack/assets/elements/slider-track-horizontal.png +0 -0
  70. bootstack/assets/elements/slider-track-vertical.png +0 -0
  71. bootstack/assets/elements/switch-off.png +0 -0
  72. bootstack/assets/elements/switch-on.png +0 -0
  73. bootstack/assets/elements/tabs-bar-horizontal.png +0 -0
  74. bootstack/assets/elements/tabs-bar-vertical.png +0 -0
  75. bootstack/assets/elements/tabs-pill.png +0 -0
  76. bootstack/assets/locales/ar/LC_MESSAGES/bootstack.mo +0 -0
  77. bootstack/assets/locales/ar/LC_MESSAGES/bootstack.po +853 -0
  78. bootstack/assets/locales/bg/LC_MESSAGES/bootstack.po +875 -0
  79. bootstack/assets/locales/cs/LC_MESSAGES/bootstack.mo +0 -0
  80. bootstack/assets/locales/cs/LC_MESSAGES/bootstack.po +853 -0
  81. bootstack/assets/locales/da/LC_MESSAGES/bootstack.mo +0 -0
  82. bootstack/assets/locales/da/LC_MESSAGES/bootstack.po +853 -0
  83. bootstack/assets/locales/de/LC_MESSAGES/bootstack.mo +0 -0
  84. bootstack/assets/locales/de/LC_MESSAGES/bootstack.po +853 -0
  85. bootstack/assets/locales/en/LC_MESSAGES/bootstack.mo +0 -0
  86. bootstack/assets/locales/en/LC_MESSAGES/bootstack.po +875 -0
  87. bootstack/assets/locales/es/LC_MESSAGES/bootstack.mo +0 -0
  88. bootstack/assets/locales/es/LC_MESSAGES/bootstack.po +853 -0
  89. bootstack/assets/locales/fr/LC_MESSAGES/bootstack.mo +0 -0
  90. bootstack/assets/locales/fr/LC_MESSAGES/bootstack.po +853 -0
  91. bootstack/assets/locales/he/LC_MESSAGES/bootstack.mo +0 -0
  92. bootstack/assets/locales/he/LC_MESSAGES/bootstack.po +851 -0
  93. bootstack/assets/locales/hi/LC_MESSAGES/bootstack.mo +0 -0
  94. bootstack/assets/locales/hi/LC_MESSAGES/bootstack.po +842 -0
  95. bootstack/assets/locales/it/LC_MESSAGES/bootstack.mo +0 -0
  96. bootstack/assets/locales/it/LC_MESSAGES/bootstack.po +841 -0
  97. bootstack/assets/locales/ja/LC_MESSAGES/bootstack.mo +0 -0
  98. bootstack/assets/locales/ja/LC_MESSAGES/bootstack.po +914 -0
  99. bootstack/assets/locales/ko/LC_MESSAGES/bootstack.mo +0 -0
  100. bootstack/assets/locales/ko/LC_MESSAGES/bootstack.po +842 -0
  101. bootstack/assets/locales/nb/LC_MESSAGES/bootstack.mo +0 -0
  102. bootstack/assets/locales/nb/LC_MESSAGES/bootstack.po +841 -0
  103. bootstack/assets/locales/nl/LC_MESSAGES/bootstack.mo +0 -0
  104. bootstack/assets/locales/nl/LC_MESSAGES/bootstack.po +841 -0
  105. bootstack/assets/locales/pl/LC_MESSAGES/bootstack.mo +0 -0
  106. bootstack/assets/locales/pl/LC_MESSAGES/bootstack.po +842 -0
  107. bootstack/assets/locales/pt/LC_MESSAGES/bootstack.mo +0 -0
  108. bootstack/assets/locales/pt/LC_MESSAGES/bootstack.po +842 -0
  109. bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.mo +0 -0
  110. bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.po +842 -0
  111. bootstack/assets/locales/sl/LC_MESSAGES/bootstack.mo +0 -0
  112. bootstack/assets/locales/sl/LC_MESSAGES/bootstack.po +842 -0
  113. bootstack/assets/locales/sv/LC_MESSAGES/bootstack.mo +0 -0
  114. bootstack/assets/locales/sv/LC_MESSAGES/bootstack.po +842 -0
  115. bootstack/assets/locales/tr/LC_MESSAGES/bootstack.mo +0 -0
  116. bootstack/assets/locales/tr/LC_MESSAGES/bootstack.po +842 -0
  117. bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.mo +0 -0
  118. bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.po +842 -0
  119. bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.mo +0 -0
  120. bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.po +842 -0
  121. bootstack/assets/themes/__init__.py +0 -0
  122. bootstack/assets/themes/amber-dark.json +32 -0
  123. bootstack/assets/themes/amber-light.json +32 -0
  124. bootstack/assets/themes/aurora-dark.json +32 -0
  125. bootstack/assets/themes/aurora-light.json +32 -0
  126. bootstack/assets/themes/bootstrap-dark.json +32 -0
  127. bootstack/assets/themes/bootstrap-light.json +32 -0
  128. bootstack/assets/themes/classic-dark.json +32 -0
  129. bootstack/assets/themes/classic-light.json +32 -0
  130. bootstack/assets/themes/docs-dark.json +32 -0
  131. bootstack/assets/themes/docs-light.json +32 -0
  132. bootstack/assets/themes/forest-dark.json +32 -0
  133. bootstack/assets/themes/forest-light.json +32 -0
  134. bootstack/assets/themes/ocean-dark.json +32 -0
  135. bootstack/assets/themes/ocean-light.json +32 -0
  136. bootstack/assets/themes/rose-dark.json +32 -0
  137. bootstack/assets/themes/rose-light.json +32 -0
  138. bootstack/assets/widgets/__init__.py +0 -0
  139. bootstack/assets/widgets/badge-default.png +0 -0
  140. bootstack/assets/widgets/badge-pill.png +0 -0
  141. bootstack/assets/widgets/border.png +0 -0
  142. bootstack/assets/widgets/button-group-horizontal-after.png +0 -0
  143. bootstack/assets/widgets/button-group-horizontal-before.png +0 -0
  144. bootstack/assets/widgets/button-group-horizontal-center.png +0 -0
  145. bootstack/assets/widgets/button-group-vertical-after.png +0 -0
  146. bootstack/assets/widgets/button-group-vertical-before.png +0 -0
  147. bootstack/assets/widgets/button-group-vertical-center.png +0 -0
  148. bootstack/assets/widgets/button.png +0 -0
  149. bootstack/assets/widgets/checkbox-checked.png +0 -0
  150. bootstack/assets/widgets/checkbox-indeterminate.png +0 -0
  151. bootstack/assets/widgets/checkbox-unchecked.png +0 -0
  152. bootstack/assets/widgets/field.png +0 -0
  153. bootstack/assets/widgets/icon-button.png +0 -0
  154. bootstack/assets/widgets/input-inner.png +0 -0
  155. bootstack/assets/widgets/input-prefix.png +0 -0
  156. bootstack/assets/widgets/input-suffix.png +0 -0
  157. bootstack/assets/widgets/input.png +0 -0
  158. bootstack/assets/widgets/list-item-focus.png +0 -0
  159. bootstack/assets/widgets/list-item-separated.png +0 -0
  160. bootstack/assets/widgets/menu-item-separated.png +0 -0
  161. bootstack/assets/widgets/notebook-client-border.png +0 -0
  162. bootstack/assets/widgets/notebook-pill-active.png +0 -0
  163. bootstack/assets/widgets/notebook-pill-inactive.png +0 -0
  164. bootstack/assets/widgets/notebook-tab-active.png +0 -0
  165. bootstack/assets/widgets/notebook-tab-border.png +0 -0
  166. bootstack/assets/widgets/notebook-tab-normal.png +0 -0
  167. bootstack/assets/widgets/notebook-underline.png +0 -0
  168. bootstack/assets/widgets/progress-bar-horizontal-default.png +0 -0
  169. bootstack/assets/widgets/progress-bar-horizontal-striped.png +0 -0
  170. bootstack/assets/widgets/progress-bar-vertical-default.png +0 -0
  171. bootstack/assets/widgets/progress-bar-vertical-striped.png +0 -0
  172. bootstack/assets/widgets/progress-trough-horizontal.png +0 -0
  173. bootstack/assets/widgets/progress-trough-vertical.png +0 -0
  174. bootstack/assets/widgets/radio-selected.png +0 -0
  175. bootstack/assets/widgets/radio-unselected.png +0 -0
  176. bootstack/assets/widgets/scrollbar-horizontal-rounded.png +0 -0
  177. bootstack/assets/widgets/scrollbar-vertical-rounded.png +0 -0
  178. bootstack/assets/widgets/separator-horizontal.png +0 -0
  179. bootstack/assets/widgets/separator-vertical.png +0 -0
  180. bootstack/assets/widgets/slider-handle-focus.png +0 -0
  181. bootstack/assets/widgets/slider-handle.png +0 -0
  182. bootstack/assets/widgets/slider-track-horizontal.png +0 -0
  183. bootstack/assets/widgets/slider-track-vertical.png +0 -0
  184. bootstack/assets/widgets/switch-off.png +0 -0
  185. bootstack/assets/widgets/switch-on.png +0 -0
  186. bootstack/assets/widgets/tabs-bar-horizontal.png +0 -0
  187. bootstack/assets/widgets/tabs-bar-vertical.png +0 -0
  188. bootstack/assets/widgets/tabs-pill.png +0 -0
  189. bootstack/cli/__init__.py +124 -0
  190. bootstack/cli/__main__.py +6 -0
  191. bootstack/cli/add.py +439 -0
  192. bootstack/cli/build.py +115 -0
  193. bootstack/cli/config.py +287 -0
  194. bootstack/cli/demo.py +1267 -0
  195. bootstack/cli/doctor.py +195 -0
  196. bootstack/cli/list_cmd.py +71 -0
  197. bootstack/cli/promote.py +120 -0
  198. bootstack/cli/pyinstaller.py +246 -0
  199. bootstack/cli/run.py +99 -0
  200. bootstack/cli/start.py +105 -0
  201. bootstack/cli/templates/__init__.py +861 -0
  202. bootstack/constants.py +325 -0
  203. bootstack/core/__init__.py +34 -0
  204. bootstack/core/capabilities/__init__.py +45 -0
  205. bootstack/core/capabilities/after.py +103 -0
  206. bootstack/core/capabilities/bind.py +154 -0
  207. bootstack/core/capabilities/bindtags.py +112 -0
  208. bootstack/core/capabilities/busy.py +61 -0
  209. bootstack/core/capabilities/clipboard.py +88 -0
  210. bootstack/core/capabilities/focus.py +118 -0
  211. bootstack/core/capabilities/grab.py +65 -0
  212. bootstack/core/capabilities/grid.py +188 -0
  213. bootstack/core/capabilities/localization.py +231 -0
  214. bootstack/core/capabilities/pack.py +119 -0
  215. bootstack/core/capabilities/place.py +92 -0
  216. bootstack/core/capabilities/selection.py +136 -0
  217. bootstack/core/capabilities/signals.py +242 -0
  218. bootstack/core/capabilities/winfo.py +315 -0
  219. bootstack/core/colorutils.py +234 -0
  220. bootstack/core/exceptions.py +95 -0
  221. bootstack/core/images.py +283 -0
  222. bootstack/core/localization/README.md +90 -0
  223. bootstack/core/localization/__init__.py +13 -0
  224. bootstack/core/localization/intl_format.py +580 -0
  225. bootstack/core/localization/msgcat.py +425 -0
  226. bootstack/core/localization/specs.py +143 -0
  227. bootstack/core/mixins/__init__.py +1 -0
  228. bootstack/core/mixins/ttk_state.py +35 -0
  229. bootstack/core/mixins/widget.py +132 -0
  230. bootstack/core/publisher.py +147 -0
  231. bootstack/core/signals/README.md +112 -0
  232. bootstack/core/signals/__init__.py +8 -0
  233. bootstack/core/signals/integration.py +100 -0
  234. bootstack/core/signals/signal.py +317 -0
  235. bootstack/core/signals/types.py +4 -0
  236. bootstack/core/validation/__init__.py +5 -0
  237. bootstack/core/validation/types.py +13 -0
  238. bootstack/core/validation/validation_result.py +17 -0
  239. bootstack/core/validation/validation_rules.py +112 -0
  240. bootstack/core/variables.py +62 -0
  241. bootstack/datasource/README.md +607 -0
  242. bootstack/datasource/__init__.py +51 -0
  243. bootstack/datasource/base.py +474 -0
  244. bootstack/datasource/file_source.py +541 -0
  245. bootstack/datasource/memory_source.py +482 -0
  246. bootstack/datasource/sqlite_source.py +453 -0
  247. bootstack/datasource/types.py +259 -0
  248. bootstack/dialogs/__init__.py +56 -0
  249. bootstack/dialogs/colorchooser.py +674 -0
  250. bootstack/dialogs/colordropper.py +257 -0
  251. bootstack/dialogs/datedialog.py +404 -0
  252. bootstack/dialogs/dialog.py +514 -0
  253. bootstack/dialogs/filterdialog.py +358 -0
  254. bootstack/dialogs/fontdialog.py +339 -0
  255. bootstack/dialogs/formdialog.py +541 -0
  256. bootstack/dialogs/message.py +489 -0
  257. bootstack/dialogs/query.py +561 -0
  258. bootstack/py.typed +1 -0
  259. bootstack/runtime/__init__.py +3 -0
  260. bootstack/runtime/app.py +879 -0
  261. bootstack/runtime/base_window.py +786 -0
  262. bootstack/runtime/events.py +399 -0
  263. bootstack/runtime/menu.py +510 -0
  264. bootstack/runtime/shortcuts.py +423 -0
  265. bootstack/runtime/tk_patch.py +31 -0
  266. bootstack/runtime/toplevel.py +131 -0
  267. bootstack/runtime/utility.py +371 -0
  268. bootstack/runtime/visual_focus.py +228 -0
  269. bootstack/runtime/window_utilities.py +1043 -0
  270. bootstack/style/__init__.py +5498 -0
  271. bootstack/style/bootstyle.py +507 -0
  272. bootstack/style/bootstyle_builder_base.py +752 -0
  273. bootstack/style/bootstyle_builder_mixed.py +93 -0
  274. bootstack/style/bootstyle_builder_tk.py +109 -0
  275. bootstack/style/bootstyle_builder_ttk.py +354 -0
  276. bootstack/style/builders/__init__.py +51 -0
  277. bootstack/style/builders/badge.py +44 -0
  278. bootstack/style/builders/button.py +453 -0
  279. bootstack/style/builders/buttongroup.py +344 -0
  280. bootstack/style/builders/calendar.py +271 -0
  281. bootstack/style/builders/checkbutton.py +95 -0
  282. bootstack/style/builders/combobox.py +112 -0
  283. bootstack/style/builders/contextmenu.py +268 -0
  284. bootstack/style/builders/entry.py +83 -0
  285. bootstack/style/builders/expander.py +171 -0
  286. bootstack/style/builders/field.py +312 -0
  287. bootstack/style/builders/frame.py +27 -0
  288. bootstack/style/builders/label.py +28 -0
  289. bootstack/style/builders/labelframe.py +41 -0
  290. bootstack/style/builders/listview.py +267 -0
  291. bootstack/style/builders/menubar.py +74 -0
  292. bootstack/style/builders/menubutton.py +408 -0
  293. bootstack/style/builders/notebook.py +316 -0
  294. bootstack/style/builders/panedwindow.py +25 -0
  295. bootstack/style/builders/progressbar.py +71 -0
  296. bootstack/style/builders/radiobutton.py +68 -0
  297. bootstack/style/builders/scale.py +66 -0
  298. bootstack/style/builders/scrollbar.py +360 -0
  299. bootstack/style/builders/separator.py +45 -0
  300. bootstack/style/builders/sidenav.py +313 -0
  301. bootstack/style/builders/sizegrip.py +15 -0
  302. bootstack/style/builders/spinbox.py +119 -0
  303. bootstack/style/builders/switch.py +67 -0
  304. bootstack/style/builders/tabitem.py +205 -0
  305. bootstack/style/builders/toolbutton.py +260 -0
  306. bootstack/style/builders/tooltip.py +26 -0
  307. bootstack/style/builders/treeview.py +269 -0
  308. bootstack/style/builders/utils.py +404 -0
  309. bootstack/style/builders_tk/__init__.py +16 -0
  310. bootstack/style/builders_tk/defaults.py +229 -0
  311. bootstack/style/element.py +173 -0
  312. bootstack/style/style.py +499 -0
  313. bootstack/style/theme_provider.py +449 -0
  314. bootstack/style/tk_patch.py +5 -0
  315. bootstack/style/token_maps.py +42 -0
  316. bootstack/style/types.py +32 -0
  317. bootstack/style/typography.py +527 -0
  318. bootstack/style/utility.py +696 -0
  319. bootstack/themes/__init__.py +12 -0
  320. bootstack/themes/standard.py +415 -0
  321. bootstack/themes/user.py +45 -0
  322. bootstack/widgets/__init__.py +53 -0
  323. bootstack/widgets/composites/__init__.py +38 -0
  324. bootstack/widgets/composites/accordion.py +385 -0
  325. bootstack/widgets/composites/appshell.py +445 -0
  326. bootstack/widgets/composites/buttongroup.py +391 -0
  327. bootstack/widgets/composites/calendar.py +914 -0
  328. bootstack/widgets/composites/compositeframe.py +282 -0
  329. bootstack/widgets/composites/contextmenu.py +1754 -0
  330. bootstack/widgets/composites/dateentry.py +261 -0
  331. bootstack/widgets/composites/dropdownbutton.py +190 -0
  332. bootstack/widgets/composites/expander.py +508 -0
  333. bootstack/widgets/composites/field.py +448 -0
  334. bootstack/widgets/composites/floodgauge.py +434 -0
  335. bootstack/widgets/composites/form.py +983 -0
  336. bootstack/widgets/composites/labeledscale.py +209 -0
  337. bootstack/widgets/composites/list/__init__.py +15 -0
  338. bootstack/widgets/composites/list/listitem.py +733 -0
  339. bootstack/widgets/composites/list/listview.py +1507 -0
  340. bootstack/widgets/composites/menubar.py +303 -0
  341. bootstack/widgets/composites/meter.py +882 -0
  342. bootstack/widgets/composites/numericentry.py +183 -0
  343. bootstack/widgets/composites/pagestack.py +330 -0
  344. bootstack/widgets/composites/passwordentry.py +149 -0
  345. bootstack/widgets/composites/pathentry.py +223 -0
  346. bootstack/widgets/composites/radiogroup.py +466 -0
  347. bootstack/widgets/composites/scrolledtext.py +388 -0
  348. bootstack/widgets/composites/scrolledtext.pyi +186 -0
  349. bootstack/widgets/composites/scrollview.py +675 -0
  350. bootstack/widgets/composites/selectbox.py +544 -0
  351. bootstack/widgets/composites/sidenav/__init__.py +24 -0
  352. bootstack/widgets/composites/sidenav/group.py +485 -0
  353. bootstack/widgets/composites/sidenav/header.py +83 -0
  354. bootstack/widgets/composites/sidenav/item.py +413 -0
  355. bootstack/widgets/composites/sidenav/separator.py +51 -0
  356. bootstack/widgets/composites/sidenav/view.py +919 -0
  357. bootstack/widgets/composites/spinnerentry.py +232 -0
  358. bootstack/widgets/composites/tableview/__init__.py +5 -0
  359. bootstack/widgets/composites/tableview/tableview.py +2254 -0
  360. bootstack/widgets/composites/tableview/types.py +169 -0
  361. bootstack/widgets/composites/tabs/__init__.py +6 -0
  362. bootstack/widgets/composites/tabs/tabitem.py +372 -0
  363. bootstack/widgets/composites/tabs/tabs.py +478 -0
  364. bootstack/widgets/composites/tabs/tabview.py +352 -0
  365. bootstack/widgets/composites/textentry.py +90 -0
  366. bootstack/widgets/composites/timeentry.py +189 -0
  367. bootstack/widgets/composites/toast.py +364 -0
  368. bootstack/widgets/composites/togglegroup.py +382 -0
  369. bootstack/widgets/composites/toolbar.py +393 -0
  370. bootstack/widgets/composites/tooltip.py +404 -0
  371. bootstack/widgets/internal/__init__.py +0 -0
  372. bootstack/widgets/internal/wrapper_base.py +304 -0
  373. bootstack/widgets/mixins/__init__.py +25 -0
  374. bootstack/widgets/mixins/configure_mixin.py +186 -0
  375. bootstack/widgets/mixins/entry_mixin.py +70 -0
  376. bootstack/widgets/mixins/font_mixin.py +346 -0
  377. bootstack/widgets/mixins/icon_mixin.py +38 -0
  378. bootstack/widgets/mixins/localization_mixin.py +255 -0
  379. bootstack/widgets/mixins/signal_mixin.py +272 -0
  380. bootstack/widgets/mixins/validation_mixin.py +204 -0
  381. bootstack/widgets/parts/__init__.py +11 -0
  382. bootstack/widgets/parts/numberentry_part.py +345 -0
  383. bootstack/widgets/parts/spinnerentry_part.py +394 -0
  384. bootstack/widgets/parts/textentry_part.py +344 -0
  385. bootstack/widgets/primitives/__init__.py +55 -0
  386. bootstack/widgets/primitives/badge.py +44 -0
  387. bootstack/widgets/primitives/button.py +89 -0
  388. bootstack/widgets/primitives/card.py +66 -0
  389. bootstack/widgets/primitives/checkbutton.py +124 -0
  390. bootstack/widgets/primitives/checktoggle.py +53 -0
  391. bootstack/widgets/primitives/combobox.py +165 -0
  392. bootstack/widgets/primitives/entry.py +98 -0
  393. bootstack/widgets/primitives/frame.py +206 -0
  394. bootstack/widgets/primitives/gridframe.py +479 -0
  395. bootstack/widgets/primitives/label.py +95 -0
  396. bootstack/widgets/primitives/labelframe.py +63 -0
  397. bootstack/widgets/primitives/menubutton.py +118 -0
  398. bootstack/widgets/primitives/notebook.py +551 -0
  399. bootstack/widgets/primitives/optionmenu.py +248 -0
  400. bootstack/widgets/primitives/packframe.py +228 -0
  401. bootstack/widgets/primitives/panedwindow.py +58 -0
  402. bootstack/widgets/primitives/progressbar.py +95 -0
  403. bootstack/widgets/primitives/radiobutton.py +115 -0
  404. bootstack/widgets/primitives/radiotoggle.py +50 -0
  405. bootstack/widgets/primitives/scale.py +85 -0
  406. bootstack/widgets/primitives/scrollbar.py +56 -0
  407. bootstack/widgets/primitives/separator.py +56 -0
  408. bootstack/widgets/primitives/sizegrip.py +47 -0
  409. bootstack/widgets/primitives/spinbox.py +91 -0
  410. bootstack/widgets/primitives/switch.py +41 -0
  411. bootstack/widgets/primitives/treeview.py +77 -0
  412. bootstack/widgets/types.py +20 -0
  413. bootstack-0.1.0a1.dist-info/METADATA +196 -0
  414. bootstack-0.1.0a1.dist-info/RECORD +419 -0
  415. bootstack-0.1.0a1.dist-info/WHEEL +5 -0
  416. bootstack-0.1.0a1.dist-info/entry_points.txt +2 -0
  417. bootstack-0.1.0a1.dist-info/licenses/LICENSE +22 -0
  418. bootstack-0.1.0a1.dist-info/licenses/NOTICE +10 -0
  419. bootstack-0.1.0a1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,489 @@
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.primitives import Frame, Label
10
+ from ttkbootstrap_icons_bs import BootstrapIcon
11
+ from bootstack.constants import *
12
+ from bootstack.core.localization 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
+ !!! note "Events"
32
+
33
+ `<<DialogResult>>`: Fired when dialog closes.
34
+ Provides `event.data` with keys: `result` (str), `confirmed` (bool).
35
+ """
36
+
37
+ def __init__(
38
+ self,
39
+ message: str,
40
+ title: str = " ",
41
+ buttons: Optional[List[str]] = None,
42
+ command: Optional[Callable[[], None]] = None,
43
+ width: int = 50,
44
+ master: Optional[tkinter.Misc] = None,
45
+ alert: bool = False,
46
+ default: Optional[str] = None,
47
+ padding: tuple[int, int] | int = (20, 20),
48
+ icon: Optional[str | dict] = None,
49
+ **kwargs: Any,
50
+ ) -> None:
51
+ """Create a message dialog.
52
+
53
+ Args:
54
+ message: The message text to display. Supports multiline strings.
55
+ title: The dialog window title.
56
+ buttons: List of button labels. Can specify color as "label:color".
57
+ If None, defaults to ["Cancel", "OK"]. Legacy "bootstyle" syntax
58
+ is still supported (e.g., "OK:primary").
59
+ command: Optional callback function to execute when any button is pressed.
60
+ width: Maximum width in characters for text wrapping.
61
+ master: Parent widget for the dialog.
62
+ alert: If True, rings the system bell when shown.
63
+ default: The button label to use as default. Receives primary bootstyle and focus.
64
+ padding: Padding around the message content.
65
+ icon: Optional icon specification. Can be a string (icon name) or dict with
66
+ keys: 'name' (required), 'size' (default 32), 'color' (optional).
67
+ **kwargs: Additional keyword arguments. Supports 'localize' to enable translation.
68
+ """
69
+ self._message = message
70
+ self._command = command
71
+ self._width = width
72
+ self._padding = padding
73
+ self._icon = icon
74
+ self._localize = kwargs.get("localize")
75
+ self._img = None # Store icon image to prevent garbage collection
76
+
77
+ if buttons is None:
78
+ # Use semantic keys - widgets now have built-in localization
79
+ button_labels = [
80
+ "button.cancel",
81
+ "button.ok",
82
+ ]
83
+ else:
84
+ button_labels = buttons
85
+
86
+ # Parse button labels and create DialogButton specs
87
+ button_specs = self._parse_buttons(button_labels, default)
88
+
89
+ # Create the underlying dialog
90
+ self._dialog = Dialog(
91
+ master=master,
92
+ title=title,
93
+ content_builder=self._create_content,
94
+ buttons=button_specs,
95
+ alert=alert,
96
+ minsize=(300, 100),
97
+ )
98
+ self._master = master
99
+
100
+ def _create_content(self, parent: tkinter.Widget) -> None:
101
+ """Create the message body with optional icon."""
102
+ container = ttk.Frame(parent, padding=self._padding)
103
+
104
+ if self._icon:
105
+ try:
106
+ # Parse icon specification - initialize variables
107
+ icon_name: Optional[str] = None
108
+ icon_size: int = 32
109
+ icon_color: Optional[str] = None
110
+
111
+ if isinstance(self._icon, str):
112
+ icon_name = self._icon
113
+ elif isinstance(self._icon, dict):
114
+ icon_name = self._icon.get("name")
115
+ icon_size = self._icon.get("size", 32)
116
+ icon_color = self._icon.get("color")
117
+ else:
118
+ logger.warning("Invalid icon specification: %s", self._icon)
119
+
120
+ # Generate icon image
121
+ if icon_name:
122
+ if icon_color:
123
+ icon_image = BootstrapIcon(icon_name, icon_size, icon_color).image
124
+ else:
125
+ icon_image = BootstrapIcon(icon_name, icon_size).image
126
+
127
+ self._img = icon_image
128
+ icon_lbl = ttk.Label(container, image=self._img)
129
+ icon_lbl.pack(side=LEFT, anchor=N, padx=(0, 10))
130
+
131
+ except Exception as e:
132
+ logger.warning("Failed to create icon: %s", e)
133
+
134
+ if self._message:
135
+ for msg in self._message.split("\n"):
136
+ message = "\n".join(textwrap.wrap(msg, width=self._width))
137
+ message_label = ttk.Label(container, text=message)
138
+ message_label.pack(pady=(0, 3), fill=X, anchor=N)
139
+ container.pack(fill=X, expand=True)
140
+
141
+ def _parse_buttons(self, button_labels: List[str], default: Optional[str]) -> List[DialogButton]:
142
+ """Parse button label strings into DialogButton specifications."""
143
+ button_specs: List[DialogButton] = []
144
+
145
+ for i, button in enumerate(button_labels):
146
+ # Parse "text:bootstyle" format
147
+ cnf = button.split(":")
148
+ text = cnf[0]
149
+
150
+ # Apply localization if enabled
151
+ if self._localize:
152
+ text = MessageCatalog.translate(text)
153
+
154
+ # Determine if this is the default button
155
+ is_default = (text == default) if default else (i == len(button_labels) - 1)
156
+
157
+ # Determine accent
158
+ if len(cnf) == 2:
159
+ accent = cnf[1]
160
+ elif is_default:
161
+ accent = "primary"
162
+ else:
163
+ accent = "secondary"
164
+
165
+ # Determine button role
166
+ role: ButtonRole
167
+ if accent == "primary":
168
+ role = "primary"
169
+ elif i == 0 and "cancel" in text.lower():
170
+ role = "cancel"
171
+ else:
172
+ role = "secondary"
173
+
174
+ # Create button specification
175
+ button_specs.append(
176
+ DialogButton(
177
+ text=text,
178
+ role=role,
179
+ result=text,
180
+ accent=accent if accent != role else None,
181
+ default=is_default,
182
+ command=self._make_command_callback() if self._command else None,
183
+ )
184
+ )
185
+
186
+ return button_specs
187
+
188
+ def _make_command_callback(self) -> Callable[[Dialog], None]:
189
+ """Create a callback wrapper for the custom command."""
190
+
191
+ def callback(dialog: Dialog) -> None:
192
+ if self._command:
193
+ self._command()
194
+
195
+ return callback
196
+
197
+ def show(self, position: Optional[tuple[int, int]] = None) -> None:
198
+ """Show the dialog.
199
+
200
+ Args:
201
+ position: x and y coordinates to position the dialog. If None, centers on parent.
202
+ """
203
+ self._dialog.show(position=position, modal=True)
204
+ target = self._dialog.toplevel or self._master
205
+ if target:
206
+ payload = {"result": self._dialog.result, "confirmed": self._dialog.result is not None}
207
+ try:
208
+ target.event_generate("<<DialogResult>>", data=payload)
209
+ except Exception:
210
+ try:
211
+ target.event_generate("<<DialogResult>>")
212
+ except Exception:
213
+ pass
214
+
215
+ @property
216
+ def result(self) -> Any:
217
+ """The dialog result value (the text of the button pressed)."""
218
+ return self._dialog.result
219
+
220
+ def on_dialog_result(self, callback: Callable[[Any], None]) -> Optional[str]:
221
+ """Bind a callback fired when the dialog produces a result.
222
+
223
+ The callback receives `event.data["result"]` when available.
224
+
225
+ Args:
226
+ callback: Callable that receives the result payload.
227
+
228
+ Returns:
229
+ Binding identifier for use with `off_dialog_result`.
230
+ """
231
+ target = self._dialog.toplevel or self._master
232
+ if target is None:
233
+ return None
234
+
235
+ def handler(event):
236
+ callback(getattr(event, "data", None))
237
+
238
+ return target.bind("<<DialogResult>>", handler, add="+")
239
+
240
+ def off_dialog_result(self, funcid: str) -> None:
241
+ """Unbind a previously bound dialog result callback."""
242
+ target = self._dialog.toplevel or self._master
243
+ if target is None:
244
+ return
245
+ target.unbind("<<DialogResult>>", funcid)
246
+
247
+
248
+ class MessageBox:
249
+ """Static methods for displaying standard message dialogs."""
250
+
251
+ @staticmethod
252
+ def _show(
253
+ message: str,
254
+ title: str = " ",
255
+ master: Optional[tkinter.Misc] = None,
256
+ alert: bool = False,
257
+ buttons: Optional[List[str]] = None,
258
+ icon: Optional[str] = None,
259
+ on_result: Optional[Callable[[Any], None]] = None,
260
+ **kwargs: Any,
261
+ ) -> Optional[str]:
262
+ """Internal helper to show a message dialog.
263
+
264
+ Args:
265
+ message: The message text to display.
266
+ title: The dialog window title.
267
+ master: Parent widget for the dialog.
268
+ alert: If True, rings the system bell.
269
+ buttons: List of button labels.
270
+ icon: Optional icon to display.
271
+ on_result: Optional callback receiving the dialog result payload.
272
+ **kwargs: Additional arguments including 'position'.
273
+
274
+ Returns:
275
+ The text of the button pressed, or None.
276
+ """
277
+ position = kwargs.pop("position", None)
278
+ dialog = MessageDialog(
279
+ message=message,
280
+ title=title,
281
+ master=master,
282
+ alert=alert,
283
+ buttons=buttons,
284
+ icon=icon,
285
+ localize=True,
286
+ **kwargs,
287
+ )
288
+ if on_result:
289
+ dialog.on_dialog_result(on_result)
290
+ dialog.show(position)
291
+ return dialog.result
292
+
293
+ @staticmethod
294
+ def show_info(
295
+ message: str,
296
+ title: str = " ",
297
+ master: Optional[tkinter.Misc] = None,
298
+ alert: bool = False,
299
+ **kwargs: Any,
300
+ ) -> Optional[str]:
301
+ """Display an info dialog with OK button and info icon.
302
+
303
+ Args:
304
+ message: The message text to display.
305
+ title: The dialog window title.
306
+ master: Parent widget for the dialog.
307
+ alert: If True, rings the system bell.
308
+ **kwargs: Additional arguments including 'position'.
309
+
310
+ Returns:
311
+ The text of the button pressed.
312
+ """
313
+ return MessageBox._show(message, title, master, alert, ["OK:primary"], "info-circle-fill", **kwargs)
314
+
315
+ @staticmethod
316
+ def show_warning(
317
+ message: str,
318
+ title: str = " ",
319
+ master: Optional[tkinter.Misc] = None,
320
+ alert: bool = True,
321
+ **kwargs: Any,
322
+ ) -> Optional[str]:
323
+ """Display a warning dialog with OK button and warning icon.
324
+
325
+ Args:
326
+ message: The message text to display.
327
+ title: The dialog window title.
328
+ master: Parent widget for the dialog.
329
+ alert: If True, rings the system bell.
330
+ **kwargs: Additional arguments including 'position'.
331
+
332
+ Returns:
333
+ The text of the button pressed.
334
+ """
335
+ return MessageBox._show(message, title, master, alert, ["OK:primary"], "exclamation-triangle-fill", **kwargs)
336
+
337
+ @staticmethod
338
+ def show_error(
339
+ message: str,
340
+ title: str = " ",
341
+ master: Optional[tkinter.Misc] = None,
342
+ alert: bool = True,
343
+ **kwargs: Any,
344
+ ) -> Optional[str]:
345
+ """Display an error dialog with OK button and error icon.
346
+
347
+ Args:
348
+ message: The message text to display.
349
+ title: The dialog window title.
350
+ master: Parent widget for the dialog.
351
+ alert: If True, rings the system bell.
352
+ **kwargs: Additional arguments including 'position'.
353
+
354
+ Returns:
355
+ The text of the button pressed.
356
+ """
357
+ return MessageBox._show(message, title, master, alert, ["OK:primary"], "x-circle-fill", **kwargs)
358
+
359
+ @staticmethod
360
+ def show_question(
361
+ message: str,
362
+ title: str = " ",
363
+ master: Optional[tkinter.Misc] = None,
364
+ alert: bool = False,
365
+ **kwargs: Any,
366
+ ) -> Optional[str]:
367
+ """Display a question dialog with OK button and question icon.
368
+
369
+ Args:
370
+ message: The message text to display.
371
+ title: The dialog window title.
372
+ master: Parent widget for the dialog.
373
+ alert: If True, rings the system bell.
374
+ **kwargs: Additional arguments including 'position'.
375
+
376
+ Returns:
377
+ The text of the button pressed.
378
+ """
379
+ return MessageBox._show(message, title, master, alert, ["OK:primary"], "question-circle-fill", **kwargs)
380
+
381
+ @staticmethod
382
+ def ok(
383
+ message: str,
384
+ title: str = " ",
385
+ master: Optional[tkinter.Misc] = None,
386
+ alert: bool = False,
387
+ **kwargs: Any,
388
+ ) -> Optional[str]:
389
+ """Display a dialog with an OK button.
390
+
391
+ Args:
392
+ message: The message text to display.
393
+ title: The dialog window title.
394
+ master: Parent widget for the dialog.
395
+ alert: If True, rings the system bell.
396
+ **kwargs: Additional arguments including 'position'.
397
+
398
+ Returns:
399
+ The text of the button pressed.
400
+ """
401
+ return MessageBox._show(message, title, master, alert, ["OK:primary"], None, **kwargs)
402
+
403
+ @staticmethod
404
+ def okcancel(
405
+ message: str,
406
+ title: str = " ",
407
+ master: Optional[tkinter.Misc] = None,
408
+ alert: bool = False,
409
+ **kwargs: Any,
410
+ ) -> Optional[str]:
411
+ """Display a dialog with OK and Cancel buttons.
412
+
413
+ Args:
414
+ message: The message text to display.
415
+ title: The dialog window title.
416
+ master: Parent widget for the dialog.
417
+ alert: If True, rings the system bell.
418
+ **kwargs: Additional arguments including 'position'.
419
+
420
+ Returns:
421
+ The text of the button pressed.
422
+ """
423
+ return MessageBox._show(message, title, master, alert, ["Cancel", "OK"], None, **kwargs)
424
+
425
+ @staticmethod
426
+ def yesno(
427
+ message: str,
428
+ title: str = " ",
429
+ master: Optional[tkinter.Misc] = None,
430
+ alert: bool = False,
431
+ **kwargs: Any,
432
+ ) -> Optional[str]:
433
+ """Display a dialog with Yes and No buttons.
434
+
435
+ Args:
436
+ message: The message text to display.
437
+ title: The dialog window title.
438
+ master: Parent widget for the dialog.
439
+ alert: If True, rings the system bell.
440
+ **kwargs: Additional arguments including 'position'.
441
+
442
+ Returns:
443
+ The text of the button pressed.
444
+ """
445
+ return MessageBox._show(message, title, master, alert, ["No", "Yes"], None, **kwargs)
446
+
447
+ @staticmethod
448
+ def yesnocancel(
449
+ message: str,
450
+ title: str = " ",
451
+ master: Optional[tkinter.Misc] = None,
452
+ alert: bool = False,
453
+ **kwargs: Any,
454
+ ) -> Optional[str]:
455
+ """Display a dialog with Yes, No, and Cancel buttons.
456
+
457
+ Args:
458
+ message: The message text to display.
459
+ title: The dialog window title.
460
+ master: Parent widget for the dialog.
461
+ alert: If True, rings the system bell.
462
+ **kwargs: Additional arguments including 'position'.
463
+
464
+ Returns:
465
+ The text of the button pressed.
466
+ """
467
+ return MessageBox._show(message, title, master, alert, ["Cancel", "No", "Yes"], None, **kwargs)
468
+
469
+ @staticmethod
470
+ def retrycancel(
471
+ message: str,
472
+ title: str = " ",
473
+ master: Optional[tkinter.Misc] = None,
474
+ alert: bool = False,
475
+ **kwargs: Any,
476
+ ) -> Optional[str]:
477
+ """Display a dialog with Retry and Cancel buttons.
478
+
479
+ Args:
480
+ message: The message text to display.
481
+ title: The dialog window title.
482
+ master: Parent widget for the dialog.
483
+ alert: If True, rings the system bell.
484
+ **kwargs: Additional arguments including 'position'.
485
+
486
+ Returns:
487
+ The text of the button pressed.
488
+ """
489
+ return MessageBox._show(message, title, master, alert, ["Cancel", "Retry"], None, **kwargs)