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,261 @@
1
+ """Date entry field widget with calendar picker button.
2
+
3
+ Provides a specialized entry field for date input with locale-aware formatting
4
+ and an optional calendar picker button.
5
+ """
6
+
7
+ from datetime import date, datetime
8
+ from typing import TYPE_CHECKING
9
+
10
+ from typing_extensions import Unpack
11
+
12
+ from bootstack.widgets.primitives.button import Button
13
+ from bootstack.widgets.composites.field import Field, FieldOptions
14
+ from bootstack.widgets.mixins import configure_delegate
15
+ from bootstack.widgets.types import Master
16
+
17
+ if TYPE_CHECKING:
18
+ from bootstack.dialogs.datedialog import DateDialog
19
+
20
+
21
+ class DateEntry(Field):
22
+ """A date entry field widget with calendar picker button.
23
+
24
+ DateEntry extends the Field widget to provide specialized date input with
25
+ locale-aware formatting and an optional calendar picker button. The widget
26
+ supports various date format presets and custom ICU date format patterns,
27
+ and can accept input as strings, date objects, or datetime objects.
28
+
29
+ The available date format presets are: `longDate` (January 15, 2025),
30
+ `shortDate` (1/15/25), `monthAndDate` (January 15), `monthAndYear`
31
+ (January 2025), `quarterAndYear` (Q1 2025), `day` (15), `dayOfWeek`
32
+ (Wednesday), `month` (January), `quarter` (Q1), `year` (2025),
33
+ `longTime` (3:30:45 PM PST), `shortTime` (3:30 PM), `longDateLongTime`,
34
+ `shortDateShortTime`, or any custom ICU date format pattern (e.g., "yyyy-MM-dd").
35
+
36
+ !!! note "Events"
37
+
38
+ - `<<Change>>`: Fired when date value changes after commit.
39
+ - `<<Input>>`: Fired on each keystroke.
40
+ - `<<Valid>>`: Fired when validation passes.
41
+ - `<<Invalid>>`: Fired when validation fails.
42
+
43
+ The calendar picker button uses a DateDialog. The button can be hidden
44
+ using `show_picker_button=False`.
45
+
46
+ Attributes:
47
+ entry_widget (TextEntryPart): Access to the underlying TextEntryPart widget.
48
+ label_widget (Label): Access to the label widget.
49
+ message_widget (Label): Access to the message label widget.
50
+ addons (dict): Dictionary of inserted addon widgets.
51
+ variable (Variable): Tkinter Variable linked to entry text.
52
+ signal (Signal): Signal object for reactive updates.
53
+ date_picker_button (Button): The calendar picker button widget.
54
+ """
55
+
56
+ def __init__(
57
+ self,
58
+ master: Master = None,
59
+ value: str | date | datetime = None,
60
+ value_format: str = "longDate",
61
+ label: str = None,
62
+ message: str = None,
63
+ show_picker_button=True,
64
+ picker_title: str = "Select new date",
65
+ picker_first_weekday: int = 6,
66
+ **kwargs: Unpack[FieldOptions]
67
+ ):
68
+ """Initialize a DateEntry widget.
69
+
70
+ Creates a date entry field with locale-aware formatting and an optional
71
+ calendar picker button. The widget accepts date input as strings, date
72
+ objects, or datetime objects, and formats them according to the specified
73
+ value_format pattern.
74
+
75
+ Args:
76
+ master: Parent widget. If None, uses the default root window.
77
+ value (str | date | datetime): Initial date value to display. Can be a
78
+ date object, datetime object, or string representation.
79
+ value_format (str): Date format pattern to use for parsing and displaying
80
+ dates. See class docstring for complete list of presets.
81
+ label (str): Optional label text to display above the entry field.
82
+ If required=True, an asterisk (*) is automatically appended.
83
+ message (str): Optional message text to display below the entry field.
84
+ Used for hints or help text. Replaced by validation errors when
85
+ validation fails.
86
+ show_picker_button (bool): If True, displays the calendar picker button
87
+ to the right of the entry. If False, hides the button.
88
+ picker_title (str): Title text for the calendar picker dialog.
89
+ picker_first_weekday (int): First day of the week to display in the
90
+ calendar picker. 0=Monday, 6=Sunday.
91
+
92
+ Other Parameters:
93
+ locale (str): Locale identifier for date formatting (e.g., 'en_US').
94
+ required (bool): If True, field cannot be empty.
95
+ bootstyle (str): The accent color of the focus ring and active border.
96
+ allow_blank (bool): Allow empty input.
97
+ cursor (str): Cursor style when hovering.
98
+ exportselection (bool): Export selection to clipboard.
99
+ font (str): Font for text display.
100
+ foreground (str): Text color.
101
+ initial_focus (bool): If True, widget receives focus on creation.
102
+ justify (str): Text alignment ('left', 'center', 'right').
103
+ show_message (bool): If True, displays message area.
104
+ padding (int | tuple): Padding around entry widget.
105
+ takefocus (bool): If True, widget accepts Tab focus.
106
+ textvariable (Variable): Tkinter Variable to link with text.
107
+ textsignal (Signal): Signal object for reactive updates.
108
+ width (int): Width in characters.
109
+ xscrollcommand (Callable): Callback for horizontal scrolling.
110
+
111
+ Note:
112
+ The widget uses the IntlFormatter for locale-aware date formatting.
113
+ The value is parsed and formatted automatically when the user commits
114
+ input (on FocusOut or Return key). Invalid date strings that cannot
115
+ be parsed will revert to the previous valid value.
116
+ """
117
+ kwargs.setdefault('bootstyle', 'primary')
118
+ super().__init__(master=master, value=value, value_format=value_format, label=label, message=message, **kwargs)
119
+
120
+ # configuration
121
+ self._show_picker_button = show_picker_button
122
+ self._picker_title = picker_title
123
+ self._picker_first_weekday = picker_first_weekday
124
+
125
+ self._button_pack = {}
126
+
127
+ self.insert_addon(
128
+ Button,
129
+ position="after",
130
+ name="date-picker",
131
+ icon="calendar-week",
132
+ icon_only=True,
133
+ command=self._show_date_picker
134
+ )
135
+
136
+ self._delegate_show_picker_button(self._show_picker_button)
137
+
138
+ @property
139
+ def date_picker_button(self):
140
+ """Get the calendar picker button widget."""
141
+ return self.addons.get('date-picker')
142
+
143
+ @configure_delegate('show_picker_button')
144
+ def _delegate_show_picker_button(self, value: bool = None):
145
+ """Get or set the visibility of the calendar picker button."""
146
+ if value is None:
147
+ return self._show_picker_button
148
+ else:
149
+ if value:
150
+ if not self.date_picker_button.winfo_ismapped():
151
+ self.date_picker_button.pack(**self._button_pack)
152
+ else:
153
+ self._button_pack = self.date_picker_button.pack_info()
154
+ self.date_picker_button.pack_forget()
155
+ return None
156
+
157
+ def _show_date_picker(self):
158
+ """Open the calendar picker dialog.
159
+
160
+ Opens a DateDialog seeded with the current value (if valid), updates
161
+ the entry when a date is picked, and leaves the field unchanged on
162
+ cancel.
163
+ """
164
+ from bootstack.dialogs.datedialog import DateDialog
165
+
166
+ # Prevent multiple dialogs: reuse existing if still open
167
+ existing = getattr(self, "_active_date_dialog", None)
168
+ top = getattr(getattr(existing, "_dialog", None), "toplevel", None) if existing else None
169
+ try:
170
+ exists = bool(top and top.winfo_exists())
171
+ except Exception:
172
+ exists = False
173
+
174
+ if exists:
175
+ try:
176
+ top.lift()
177
+ top.focus_force()
178
+ except Exception:
179
+ pass
180
+ return
181
+ self._active_date_dialog = None
182
+
183
+ current_value = self.value
184
+ if isinstance(current_value, datetime):
185
+ current_value = current_value.date()
186
+ if not isinstance(current_value, date):
187
+ current_value = date.today()
188
+
189
+ position = self._picker_position()
190
+
191
+ dialog = DateDialog(
192
+ master=self.winfo_toplevel(),
193
+ title=self._picker_title,
194
+ first_weekday=self._picker_first_weekday,
195
+ initial_date=current_value,
196
+ accent=self._accent,
197
+ hide_window_chrome=True,
198
+ close_on_click_outside=False, # Disabled to avoid interference with button clicks
199
+ )
200
+
201
+ self._active_date_dialog = dialog
202
+
203
+ def _on_result(payload):
204
+ if isinstance(payload, dict):
205
+ result = payload.get('result')
206
+ self.value = result
207
+ else:
208
+ self.value = payload
209
+
210
+ dialog.on_result(lambda x: _on_result(x))
211
+ dialog.show(position=position)
212
+
213
+ top = getattr(getattr(dialog, "_dialog", None), "toplevel", None)
214
+ cleared = False
215
+ try:
216
+ if top and top.winfo_exists():
217
+ def _clear(_=None):
218
+ self._active_date_dialog = None
219
+ top.bind("<Destroy>", _clear, add="+")
220
+ cleared = True
221
+ except Exception:
222
+ cleared = False
223
+ if not cleared:
224
+ self._active_date_dialog = None
225
+
226
+ # Fallback: ensure value is applied after modal dialog closes.
227
+ selected = dialog.result
228
+ if isinstance(selected, datetime):
229
+ selected = selected.date()
230
+ if isinstance(selected, date):
231
+ self.value = selected
232
+
233
+ # Return focus to the entry after dialog closes
234
+ # Note: focus_force() is needed on Windows after override-redirect dialogs
235
+ try:
236
+ self._entry.focus_force()
237
+ except Exception:
238
+ pass
239
+
240
+ def _picker_position(self):
241
+ """Choose a dialog position beneath the entry mirroring SelectBox spacing."""
242
+ try:
243
+ # Position relative to the inner field widget, not the whole container
244
+ # This ensures proper positioning even when message label is visible
245
+ field_widget = self._field
246
+ field_widget.update_idletasks()
247
+ x = field_widget.winfo_rootx() + 4
248
+ y = field_widget.winfo_rooty() + field_widget.winfo_height() + 2
249
+ return x, y
250
+ except Exception:
251
+ pass
252
+
253
+ try:
254
+ top = self.winfo_toplevel()
255
+ top.update_idletasks()
256
+ x = top.winfo_rootx() + top.winfo_width() // 2
257
+ y = top.winfo_rooty() + top.winfo_height() // 2
258
+ return x, y
259
+ except Exception:
260
+ return None
261
+
@@ -0,0 +1,190 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any, Callable, Literal, Optional, TYPE_CHECKING, TypedDict
4
+
5
+ from typing_extensions import Unpack
6
+
7
+ from bootstack.widgets.composites.contextmenu import ContextMenu, ContextMenuItem
8
+ from bootstack.widgets.primitives.menubutton import MenuButton
9
+ from bootstack.widgets.mixins import configure_delegate
10
+ from bootstack.widgets.types import Master
11
+
12
+ if TYPE_CHECKING:
13
+ from bootstack.core.signals import Signal
14
+
15
+
16
+ class DropdownButtonKwargs(TypedDict, total=False):
17
+ command: Optional[Callable[[], Any]]
18
+ image: Any
19
+ icon: Any
20
+ icon_only: bool
21
+ compound: Literal['text', 'image', 'top', 'bottom', 'left', 'right', 'center', 'none'] | str
22
+ padding: Any
23
+ width: int
24
+ underline: int
25
+ state: Literal['normal', 'active', 'disabled', 'readonly'] | str
26
+ takefocus: Any
27
+ style: str
28
+ class_: str
29
+ cursor: str
30
+ default: Any
31
+ name: str
32
+ textvariable: Any
33
+ textsignal: Signal[str]
34
+ bootstyle: str # DEPRECATED: Use accent and variant instead
35
+ accent: str
36
+ density: Literal['default', 'compact']
37
+ variant: str
38
+ surface: str
39
+ style_options: dict[str, Any]
40
+ popdown_options: dict[str, Any]
41
+ show_dropdown_button: bool
42
+ dropdown_button_icon: str | dict
43
+
44
+
45
+ class DropdownButton(MenuButton):
46
+
47
+ def __init__(
48
+ self,
49
+ master: Master = None,
50
+ text: Any = None,
51
+ items: list[ContextMenuItem] = None,
52
+ **kwargs: Unpack[DropdownButtonKwargs],
53
+ ):
54
+ """Create a dropdown button backed by a ContextMenu.
55
+
56
+ Args:
57
+ master: Parent widget. If None, uses the default root window.
58
+ text (str): Label text for the button.
59
+ items (list): Initial list of ContextMenuItem entries.
60
+
61
+ Other Parameters:
62
+ command (Callable): Callback when the button is activated.
63
+ image (PhotoImage): Tk image to display.
64
+ icon (str | dict): Bootstyle icon spec for the button content.
65
+ icon_only (bool): Whether to reserve label padding when showing only an icon.
66
+ compound (str): Placement of image relative to text.
67
+ padding (int | tuple): Extra padding around the button content.
68
+ density (str): The vertical and horizontal compactness of widget content, e.g. 'default', 'compact'.
69
+ width (int): Width of the button.
70
+ underline (int): Index of underlined character in text.
71
+ state (str): Widget state ('normal', 'active', 'disabled', 'readonly').
72
+ takefocus (bool): Participation in focus traversal.
73
+ style (str): Explicit ttk style name.
74
+ textvariable (Variable): Existing Tk variable for the label text.
75
+ textsignal (Signal[str]): Signal bound to the textvariable.
76
+ accent (str): Accent token for styling (e.g., 'primary', 'danger').
77
+ variant (str): Style variant (e.g., 'outline', 'ghost').
78
+ bootstyle (str): DEPRECATED - Use `accent` and `variant` instead.
79
+ surface (str): Surface token for style.
80
+ style_options (dict): Dict forwarded to the menubutton style builder.
81
+ popdown_options (dict): Dict forwarded to ContextMenu (e.g., anchor, attach, offset).
82
+ show_dropdown_button (bool): Show/hide the chevron.
83
+ dropdown_button_icon (str | dict): Icon name for the chevron.
84
+ """
85
+ style_options = kwargs.pop('style_options', {})
86
+ style_options.update(
87
+ self._capture_style_options(
88
+ options=['icon', 'icon_only', 'density', 'show_dropdown_button', 'dropdown_button_icon'],
89
+ source=kwargs
90
+ )
91
+ )
92
+ kwargs['style_options'] = style_options
93
+ self._item_click_callback = None
94
+ self._items = items if items else []
95
+ self._popdown_options = kwargs.pop('popdown_options', {})
96
+
97
+ # Store the textvariable if provided, or create a new one
98
+ super().__init__(master, text=text, **kwargs)
99
+
100
+ # Create menu items that update the shared variable
101
+ self._context_menu = self._build_context_menu()
102
+
103
+ # Bind menu display to button events
104
+ self.bind('<Button-1>', lambda _: self.show_menu(), add="+")
105
+ self.bind('<Return>', lambda _: self.show_menu(), add="+")
106
+ self.bind('<KP_Enter>', lambda _: self.show_menu(), add="+")
107
+
108
+ # passthrough methods
109
+ self.on_item_click = self._context_menu.on_item_click
110
+ self.add_radiobutton = self._context_menu.add_radiobutton
111
+ self.add_command = self._context_menu.add_command
112
+ self.add_checkbutton = self._context_menu.add_checkbutton
113
+ self.add_separator = self._context_menu.add_separator
114
+ self.add_item = self._context_menu.add_item
115
+ self.add_items = self._context_menu.add_items
116
+ self.insert_item = self._context_menu.insert_item
117
+ self.remove_item = self._context_menu.remove_item
118
+ self.move_item = self._context_menu.move_item
119
+ self.configure_item = self._context_menu.configure_item
120
+ self.items = self._context_menu.items
121
+
122
+ def on_item_click(self, callback: Callable) -> None:
123
+ """Set item click callback. Callback receives `item_info = {'type': str, 'text': str, 'value': Any}`."""
124
+ self._item_click_callback = callback
125
+ self._context_menu.on_item_click(callback)
126
+
127
+ def off_item_click(self) -> None:
128
+ """Remove the item click callback."""
129
+ self._item_click_callback = None
130
+ self._context_menu.on_item_click(None)
131
+
132
+ def _build_context_menu(self):
133
+ """Construct the ContextMenu with current items and options."""
134
+ # Offset compensates for the focus-ring affordance baked into the
135
+ # button image so the dropdown's left edge aligns with the visible
136
+ # button border. Same treatment as OptionMenu.
137
+ from bootstack.style.bootstyle_builder_base import BootstyleBuilderBase
138
+ offset_x = BootstyleBuilderBase.scale_from_source(10)
139
+ density = self.configure_style_options('density') or 'default'
140
+ options = {
141
+ "anchor": "nw",
142
+ "attach": "sw",
143
+ "offset": (offset_x, 0),
144
+ "density": density,
145
+ }
146
+ options.update(self._popdown_options)
147
+ # DropdownButton manages its own activation (left-click, Return/
148
+ # KP_Enter via show_menu), so opt out of ContextMenu's auto-trigger.
149
+ cm = ContextMenu(self, target=self, items=self._items, trigger=None, **options)
150
+ if self._item_click_callback:
151
+ self.on_item_click(self._item_click_callback)
152
+ return cm
153
+
154
+ @property
155
+ def context_menu(self):
156
+ """Returns the context menu widget"""
157
+ return self._context_menu
158
+
159
+ def show_menu(self):
160
+ """Show the dropdown menu unless disabled or readonly."""
161
+ if not self.instate(("!disabled", "!readonly")):
162
+ return
163
+ self._context_menu.show()
164
+
165
+ @configure_delegate('popdown_options')
166
+ def _delegate_popdown_options(self, value=None):
167
+ if value is None:
168
+ return self._popdown_options
169
+ else:
170
+ self._popdown_options = value
171
+ return self.context_menu.configure(**value)
172
+
173
+ @configure_delegate('show_dropdown_button')
174
+ def _delegate_show_dropdown_button(self, value=None):
175
+ """Get or set visibility of the dropdown chevron."""
176
+ if value is None:
177
+ return self.configure_style_options('show_dropdown_button')
178
+ else:
179
+ self.configure_style_options(show_dropdown_button=value)
180
+ return self.rebuild_style()
181
+
182
+ @configure_delegate('dropdown_button_icon')
183
+ def _delegate_dropdown_button_icon(self, value=None):
184
+ """Get or set the dropdown chevron icon name."""
185
+ if value is None:
186
+ return self.configure_style_options('dropdown_button_icon')
187
+ else:
188
+ self.configure_style_options(dropdown_button_icon=value)
189
+ return self.rebuild_style()
190
+