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,93 @@
1
+ """Builder utilities for TTK widgets with embedded Tk components.
2
+
3
+ This module handles styling for TTK widgets that contain legacy Tk components
4
+ that aren't styled by the TTK theme engine, such as:
5
+ - ttk.Combobox (contains Tk listbox and scrollbar in popdown)
6
+ - Other hybrid widgets as needed
7
+
8
+ These widgets require manual Tcl/Tk calls to style their embedded components.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ from typing import Any, Optional
14
+
15
+ from bootstack.style.bootstyle_builder_base import BootstyleBuilderBase
16
+ from bootstack.style.theme_provider import ThemeProvider
17
+
18
+
19
+ class BootstyleBuilderMixed(BootstyleBuilderBase):
20
+ """Builder for TTK widgets containing legacy Tk components.
21
+
22
+ This class provides methods to style embedded Tk components within
23
+ TTK widgets that aren't handled by the standard TTK theme engine.
24
+ """
25
+
26
+ def __init__(
27
+ self,
28
+ theme_provider: Optional[ThemeProvider] = None,
29
+ style_instance: Optional[Any] = None
30
+ ):
31
+ """Initialize the mixed builder.
32
+
33
+ Args:
34
+ theme_provider: Optional ThemeProvider instance
35
+ style_instance: Optional Style instance
36
+ """
37
+ super().__init__(theme_provider, style_instance)
38
+
39
+ def update_combobox_popdown_style(self, widget: Any) -> None:
40
+ """Update styling for legacy Tk components in ttk.Combobox.
41
+
42
+ The ttk.Combobox contains embedded Tk components (popdown listbox
43
+ and scrollbar) that aren't styled by the TTK theme engine and must
44
+ be configured manually via Tcl/Tk calls.
45
+
46
+ This method configures:
47
+ - The popdown listbox window (colors, borders, selection)
48
+ - The scrollbar within the popdown
49
+
50
+ Args:
51
+ widget: ttk.Combobox widget to update
52
+ """
53
+ # Match the entry field: surface = 'content', selection = primary
54
+ surface = self.color('content')
55
+ on_surface = self.on_color(surface)
56
+ select = self.color('primary')
57
+ on_select = self.on_color(select)
58
+
59
+ # Listbox has no border of its own — the popdown frame already draws
60
+ # the outer border, and stacking a listbox highlight on top creates a
61
+ # visible double-border effect.
62
+ tk_settings = [
63
+ "-borderwidth", 0,
64
+ "-highlightthickness", 0,
65
+ "-background", surface,
66
+ "-foreground", on_surface,
67
+ "-selectbackground", select,
68
+ "-selectforeground", on_select,
69
+ "-activestyle", "none",
70
+ "-relief", "flat",
71
+ ]
72
+
73
+ try:
74
+ # Skip if the popdown hasn't been created yet (lazy construction).
75
+ # The postcommand handler will style it on first open.
76
+ popdown_path = f"{widget}.popdown"
77
+ if not int(widget.tk.eval(f"winfo exists {popdown_path}")):
78
+ return
79
+ widget.tk.call(f"{popdown_path}.f.l", "configure", *tk_settings)
80
+
81
+ # Build a themed scrollbar style and apply it to the popdown
82
+ # scrollbar. Bootstyle.create_ttk_style returns a hashed style
83
+ # name (e.g. bs[xxx].Default.Vertical.TScrollbar) that is rebuilt
84
+ # automatically on theme change.
85
+ from bootstack.style.bootstyle import Bootstyle
86
+ sb_style = Bootstyle.create_ttk_style(
87
+ 'TScrollbar', variant='default',
88
+ style_options={'orient': 'vertical', 'show_arrows': False},
89
+ )
90
+ widget.tk.call(f"{popdown_path}.f.sb", "configure", "-style", sb_style)
91
+ except Exception:
92
+ # Silently fail if widget isn't fully initialized or mapped yet
93
+ pass
@@ -0,0 +1,109 @@
1
+ from __future__ import annotations
2
+
3
+ import threading
4
+ from typing import Callable, Dict, Optional
5
+ from collections.abc import Sequence
6
+
7
+ from typing_extensions import Any, Protocol
8
+
9
+ from bootstack.style.bootstyle_builder_base import BootstyleBuilderBase, IconSpec
10
+ from bootstack.style.theme_provider import ThemeProvider
11
+
12
+
13
+ class TkBuilderCallable(Protocol):
14
+ def __call__(self, builder: "BootstyleBuilderBuilderTk", widget: Any, **options: Any) -> None: # noqa: ANN401
15
+ ...
16
+
17
+
18
+ class BootstyleBuilderBuilderTk(BootstyleBuilderBase):
19
+ """Builder registry for legacy Tk widgets.
20
+
21
+ Mirrors the TTK BootstyleBuilder API, but targets Tk widgets and passes
22
+ the actual widget instance to builder functions.
23
+
24
+ Usage:
25
+ >>> @BootstyleBuilderBuilderTk.register_builder('Button')
26
+ ... def build_tk_button(builder, widget, **opts):
27
+ ... bg = builder.color(opts.get('surface', 'content'))
28
+ ... widget.configure(background=bg, foreground=builder.colors.get('foreground'))
29
+ """
30
+
31
+ _registry: Dict[str, TkBuilderCallable] = {}
32
+ _lock = threading.Lock()
33
+ _builders_loaded = False
34
+
35
+ def __init__(self, theme_provider: Optional[ThemeProvider] = None, style_instance: Optional[Any] = None):
36
+ super().__init__(theme_provider, style_instance)
37
+
38
+ # Color utilities and provider/colors properties are inherited from BootstyleBase
39
+
40
+ # ----- Registry API -----
41
+ @classmethod
42
+ def register_builder(cls, widget_name: str):
43
+ """Register a Tk widget builder by Tk class name (e.g., 'Button')."""
44
+
45
+ if not isinstance(widget_name, str) or not widget_name:
46
+ raise ValueError("`widget_name` must be a non-empty string")
47
+
48
+ def deco(func: TkBuilderCallable) -> TkBuilderCallable:
49
+ with cls._lock:
50
+ cls._registry[widget_name] = func
51
+ return func
52
+
53
+ return deco
54
+
55
+ @classmethod
56
+ def has_builder(cls, widget_name: str) -> bool:
57
+ cls._ensure_builders_loaded()
58
+ with cls._lock:
59
+ return widget_name in cls._registry
60
+
61
+ @classmethod
62
+ def get_registered_widgets(cls) -> list[str]:
63
+ cls._ensure_builders_loaded()
64
+ with cls._lock:
65
+ return list(cls._registry.keys())
66
+
67
+ @classmethod
68
+ def _ensure_builders_loaded(cls) -> None:
69
+ # Fast path
70
+ if cls._builders_loaded:
71
+ return
72
+ try:
73
+ import bootstack.style.builders_tk # noqa: F401
74
+ except Exception:
75
+ # If not present, that's fine; avoid repeated import attempts
76
+ pass
77
+ finally:
78
+ cls._builders_loaded = True
79
+
80
+ def call_builder(self, widget: Any, **options: Any) -> None: # noqa: ANN401
81
+ """Call a registered builder for this Tk widget instance."""
82
+ # Prefer Tk's class name; fallback to Python class name
83
+ try:
84
+ widget_name = widget.winfo_class()
85
+ except Exception:
86
+ widget_name = widget.__class__.__name__
87
+
88
+ # Ensure builder modules are imported
89
+ self._ensure_builders_loaded()
90
+
91
+ with self._lock:
92
+ builder_func = self._registry.get(widget_name)
93
+
94
+ if builder_func is None:
95
+ # Nothing to do for this Tk widget
96
+ return
97
+
98
+ builder_func(self, widget, **options)
99
+
100
+ # --- Icons ---
101
+ def map_stateful_icons(self, icon: IconSpec, foreground_spec: Sequence[tuple]):
102
+ """Stateful icon mapping is not supported for Tk builders.
103
+
104
+ This API is intended for TTK style building only. Raise a clear
105
+ error if accidentally invoked from the Tk builder.
106
+ """
107
+ raise NotImplementedError(
108
+ "map_stateful_icons is only supported for TTK styles via BootstyleBuilderBuilderTTk."
109
+ )
@@ -0,0 +1,354 @@
1
+ from __future__ import annotations
2
+
3
+ import threading
4
+ from typing import Callable, Dict, Optional
5
+
6
+ from typing_extensions import Any, ParamSpec, Protocol, TypeVar
7
+
8
+ from bootstack.core.exceptions import BootstyleBuilderError
9
+ from bootstack.style.bootstyle_builder_base import BootstyleBuilderBase
10
+ from bootstack.style.element import Element, ElementImage
11
+ from bootstack.style.theme_provider import ThemeProvider
12
+
13
+
14
+ class BuilderCallable(Protocol):
15
+ def __call__(self, builder: BootstyleBuilderTTk, ttk_style: str, **options: Any) -> None:
16
+ ...
17
+
18
+
19
+ F = TypeVar("F", bound=BuilderCallable)
20
+ P = ParamSpec("P")
21
+ R = TypeVar("R")
22
+
23
+ from bootstack.style.token_maps import WIDGET_CLASS_MAP, WIDGET_NAME_MAP
24
+
25
+ # Default variant name used when no variant is specified
26
+ # Builders should register under both their specific name AND 'default'
27
+ # Example:
28
+ # @BootstyleBuilder.register_builder('solid', 'TButton')
29
+ # @BootstyleBuilder.register_builder('default', 'TButton')
30
+ # def build_button_solid(builder, ttk_style, **options):
31
+ # ...
32
+ DEFAULT_VARIANT = 'default'
33
+
34
+
35
+ class BootstyleBuilderTTk(BootstyleBuilderBase):
36
+ """Builder manager with widget-specific style builder registry.
37
+
38
+ This class manages registration and invocation of style builder functions.
39
+ Builders are registered per-widget-class and variant.
40
+
41
+ Registry structure:
42
+ {
43
+ 'TButton': {
44
+ 'solid': builder_func,
45
+ 'outline': builder_func,
46
+ ...
47
+ },
48
+ 'TLabel': {
49
+ 'solid': builder_func,
50
+ 'inverse': builder_func,
51
+ ...
52
+ }
53
+ }
54
+ """
55
+
56
+ # Widget-specific builder registry: {widget_class: {variant: builder_func}}
57
+ _builder_registry: Dict[str, Dict[str, Callable]] = {}
58
+ _builder_lock = threading.Lock()
59
+ _builders_loaded = False # Track if builders have been auto-imported
60
+
61
+ def __init__(
62
+ self, theme_provider: Optional[ThemeProvider] = None,
63
+ style_instance: Optional[Any] = None):
64
+ """Initialize the BootstyleBuilder.
65
+
66
+ Args:
67
+ theme_provider: Optional ThemeProvider instance (creates one if None)
68
+ style_instance: Optional Style instance (set later to avoid circular import)
69
+ """
70
+ super().__init__(theme_provider, style_instance)
71
+
72
+ def set_style_instance(self, style_instance: Any):
73
+ """Set the Style instance (avoids circular import in __init__).
74
+
75
+ Args:
76
+ style_instance: Style instance to use for configuration
77
+ """
78
+ self._style = style_instance
79
+
80
+ # provider, style, colors inherited from BootstyleBase
81
+
82
+ @classmethod
83
+ def register_builder(cls, variant: str, widget_class: str):
84
+ """Register a builder for a specific widget variant.
85
+
86
+ Args:
87
+ variant: Variant name (e.g., 'solid', 'outline', 'link')
88
+ widget_class: TTK widget class (e.g., 'TButton', 'TLabel')
89
+
90
+ Returns:
91
+ Decorator function
92
+
93
+ Raises:
94
+ BootstyleBuilderError: If variant or widget_class invalid
95
+
96
+ Examples:
97
+ >>> @BootstyleBuilderTTk.register_builder('outline', 'TButton')
98
+ ... def build_button_outline(builder, ttk_style, **options):
99
+ ... # Builder implementation
100
+ ... pass
101
+ """
102
+ if not isinstance(variant, str) or not variant:
103
+ raise BootstyleBuilderError("`variant` must be a non-empty string")
104
+
105
+ if not isinstance(widget_class, str) or not widget_class:
106
+ raise BootstyleBuilderError("`widget_class` must be a non-empty string")
107
+
108
+ def deco(func: F) -> F:
109
+ with cls._builder_lock:
110
+ if widget_class not in cls._builder_registry:
111
+ cls._builder_registry[widget_class] = {}
112
+
113
+ if variant not in cls._builder_registry[widget_class]:
114
+ cls._builder_registry[widget_class][variant] = func
115
+ else:
116
+ # Warn about overwriting?
117
+ cls._builder_registry[widget_class][variant] = func
118
+
119
+ return func
120
+
121
+ return deco
122
+
123
+ def call_builder(
124
+ self, widget_class: str, variant: str, ttk_style: str,
125
+ accent: Optional[str] = None, **options):
126
+ """Call a registered builder for a specific widget variant.
127
+
128
+ Args:
129
+ widget_class: TTK widget class (e.g., 'TButton')
130
+ variant: Variant name (e.g., 'outline')
131
+ ttk_style: Full TTK style name
132
+ accent: Optional accent token (passed directly to builder)
133
+ **options: Custom style options
134
+
135
+ Raises:
136
+ BootstyleBuilderError: If builder not found
137
+ """
138
+ # Ensure builders are loaded before accessing registry
139
+ BootstyleBuilderTTk._ensure_builders_loaded()
140
+
141
+ with BootstyleBuilderTTk._builder_lock:
142
+ widget_registry = BootstyleBuilderTTk._builder_registry.get(widget_class)
143
+
144
+ if not widget_registry:
145
+ raise BootstyleBuilderError(
146
+ f"No builders registered for widget class '{widget_class}'"
147
+ )
148
+
149
+ builder_func = widget_registry.get(variant)
150
+
151
+ if not builder_func:
152
+ available = ', '.join(widget_registry.keys())
153
+ raise BootstyleBuilderError(
154
+ f"Builder '{variant}' not found for widget class '{widget_class}'. "
155
+ f"Available variants: {available}"
156
+ )
157
+
158
+ # Pass parsed accent directly to builder
159
+ # No need to pass variant - the builder itself is variant-specific
160
+ builder_func(self, ttk_style, accent=accent, **options)
161
+
162
+ @classmethod
163
+ def get_widget_class(cls, widget_name: str) -> str:
164
+ """Convert widget common name to TTK class name.
165
+
166
+ Args:
167
+ widget_name: Common widget name (e.g., 'button')
168
+
169
+ Returns:
170
+ TTK class name (e.g., 'TButton')
171
+
172
+ Raises:
173
+ ValueError: If widget name not recognized
174
+ """
175
+ if widget_name not in WIDGET_CLASS_MAP:
176
+ raise ValueError(
177
+ f"Unknown widget name: '{widget_name}'. "
178
+ f"Known names: {', '.join(WIDGET_CLASS_MAP.keys())}"
179
+ )
180
+ return WIDGET_CLASS_MAP[widget_name]
181
+
182
+ @classmethod
183
+ def get_widget_name(cls, widget_class: str) -> str:
184
+ """Convert TTK class name to common widget name.
185
+
186
+ Args:
187
+ widget_class: TTK class name (e.g., 'TButton')
188
+
189
+ Returns:
190
+ Common widget name (e.g., 'button')
191
+
192
+ Raises:
193
+ ValueError: If widget class not recognized
194
+ """
195
+ if widget_class not in WIDGET_NAME_MAP:
196
+ raise ValueError(
197
+ f"Unknown widget class: '{widget_class}'. "
198
+ f"Known classes: {', '.join(WIDGET_NAME_MAP.keys())}"
199
+ )
200
+ return WIDGET_NAME_MAP[widget_class]
201
+
202
+ @classmethod
203
+ def get_default_variant(cls, widget_class: str = None) -> str:
204
+ """Get the default variant name.
205
+
206
+ The default variant is 'default'. Builders should register under
207
+ both their specific variant name and 'default' to be used as the
208
+ default for their widget class.
209
+
210
+ Args:
211
+ widget_class: TTK widget class (unused, kept for compatibility)
212
+
213
+ Returns:
214
+ Default variant name ('default')
215
+
216
+ Examples:
217
+ >>> @BootstyleBuilderTTk.register_builder('solid', 'TButton')
218
+ ... @BootstyleBuilderTTk.register_builder('default', 'TButton')
219
+ ... def build_button_solid(builder, ttk_style, **options):
220
+ ... pass
221
+ """
222
+ return DEFAULT_VARIANT
223
+
224
+ @classmethod
225
+ def get_registered_builders(cls, widget_class: str) -> list:
226
+ """Get list of registered builders for a widget class.
227
+
228
+ Args:
229
+ widget_class: TTK widget class
230
+
231
+ Returns:
232
+ List of variant names
233
+ """
234
+ cls._ensure_builders_loaded()
235
+ registry = cls._builder_registry.get(widget_class, {})
236
+ return list(registry.keys())
237
+
238
+ @classmethod
239
+ def get_all_registered_widgets(cls) -> list:
240
+ """Get list of all widget classes with registered builders.
241
+
242
+ Returns:
243
+ List of TTK widget class names
244
+ """
245
+ cls._ensure_builders_loaded()
246
+ return list(cls._builder_registry.keys())
247
+
248
+ @classmethod
249
+ def _ensure_builders_loaded(cls):
250
+ """Ensure builders module is loaded (lazy import).
251
+
252
+ This is called automatically when registry is accessed to ensure
253
+ all builder functions are registered before use.
254
+ """
255
+ # Fast path - no lock needed if already loaded
256
+ if cls._builders_loaded:
257
+ return
258
+
259
+ # Use a simple flag to prevent multiple imports
260
+ # We check WITHOUT holding the lock to avoid deadlock
261
+ if not cls._builders_loaded:
262
+ try:
263
+ # Import builders module WITHOUT holding the lock
264
+ # This allows the builders to register themselves (which needs the lock)
265
+ import bootstack.style.builders # noqa: F401
266
+ cls._builders_loaded = True
267
+ except ImportError:
268
+ # Builders module doesn't exist yet, that's ok
269
+ cls._builders_loaded = True # Set to avoid retrying
270
+ except Exception:
271
+ # Unexpected error, but set flag to avoid infinite retries
272
+ cls._builders_loaded = True
273
+
274
+ @classmethod
275
+ def has_builder(cls, widget_class: str, variant: str) -> bool:
276
+ """Check if a builder exists for widget class and variant.
277
+
278
+ Args:
279
+ widget_class: TTK widget class (e.g., 'TButton')
280
+ variant: Variant name (e.g., 'solid', 'outline')
281
+
282
+ Returns:
283
+ True if builder exists, False otherwise
284
+
285
+ Examples:
286
+ >>> BootstyleBuilderTTk.has_builder('TButton', 'solid')
287
+ True
288
+ >>> BootstyleBuilderTTk.has_builder('TButton', 'nonexistent')
289
+ False
290
+ """
291
+ cls._ensure_builders_loaded()
292
+ return variant in cls._builder_registry.get(widget_class, {})
293
+
294
+ def initialize_all_default_styles(self):
295
+ """Initialize all default widget styles.
296
+
297
+ This method should be called when a theme is loaded to ensure
298
+ all base widget styles are properly configured before any
299
+ bootstyle variants are created.
300
+
301
+ It iterates through all registered widget classes and calls
302
+ their 'default' builder (if registered) with no accent specified,
303
+ which creates the base widget style.
304
+ """
305
+ BootstyleBuilderTTk._ensure_builders_loaded()
306
+
307
+ from bootstack.style.bootstyle import generate_ttk_style_name
308
+
309
+ for widget_class in BootstyleBuilderTTk.get_all_registered_widgets():
310
+ # Check if widget has a default builder
311
+ if BootstyleBuilderTTk.has_builder(widget_class, DEFAULT_VARIANT):
312
+ try:
313
+ # Generate the proper style name (e.g., 'Default.TFrame')
314
+ ttk_style = generate_ttk_style_name(
315
+ accent=None,
316
+ variant=DEFAULT_VARIANT,
317
+ widget_class=widget_class
318
+ )
319
+
320
+ # Call the default builder with the generated style name
321
+ # and no accent (None), which creates the default style
322
+ self.call_builder(
323
+ widget_class=widget_class,
324
+ variant=DEFAULT_VARIANT,
325
+ ttk_style=ttk_style,
326
+ accent=None
327
+ )
328
+ except Exception:
329
+ # Silently ignore errors to avoid breaking theme initialization
330
+ # Individual builder errors shouldn't prevent other builders from running
331
+ pass
332
+
333
+ def map_style(self, ttk_style: str, **options):
334
+ self.style.map(ttk_style, **options)
335
+
336
+ def configure_style(self, ttk_style, **kwargs):
337
+ self.style.configure(ttk_style, **kwargs)
338
+
339
+ def create_style_element_image(self, element: ElementImage):
340
+ name, args, kwargs = element.build()
341
+ try:
342
+ existing = set(self.style.element_names())
343
+ except Exception:
344
+ existing = set()
345
+ if name in existing:
346
+ # Element already exists; avoid duplicate creation error on theme rebuilds
347
+ return
348
+ self.style.element_create(name, "image", *args, **kwargs)
349
+
350
+ def create_style_layout(self, ttk_style: str, element: Element | list[Element]):
351
+ if isinstance(element, list):
352
+ self.style.layout(ttk_style, [e.spec() for e in element])
353
+ else:
354
+ self.style.layout(ttk_style, [element.spec()])
@@ -0,0 +1,51 @@
1
+ """Style builder functions for bootstack widgets.
2
+
3
+ This package contains individual builder functions organized by widget type.
4
+ Each builder is registered with the BootstyleBuilder registry using decorators.
5
+
6
+ Builder modules are automatically imported to trigger registration.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from . import (
12
+ badge, button, checkbutton, combobox, entry, expander, frame, label, labelframe, menubutton, sidenav,
13
+ notebook, panedwindow, progressbar, radiobutton, scale, scrollbar, separator, sizegrip, spinbox, switch,
14
+ treeview, toolbutton, tooltip, field, buttongroup, listview, calendar, contextmenu, tabitem, menubar
15
+ )
16
+
17
+ # Import all builder modules to trigger registration
18
+
19
+ __all__ = [
20
+ 'badge',
21
+ 'button',
22
+ 'expander',
23
+ 'frame',
24
+ 'label',
25
+ 'sidenav',
26
+ 'radiobutton',
27
+ 'checkbutton',
28
+ 'switch',
29
+ 'progressbar',
30
+ 'scale',
31
+ 'scrollbar',
32
+ 'menubutton',
33
+ 'entry',
34
+ 'field',
35
+ 'separator',
36
+ 'combobox',
37
+ 'labelframe',
38
+ 'notebook',
39
+ 'panedwindow',
40
+ 'sizegrip',
41
+ 'spinbox',
42
+ 'treeview',
43
+ 'toolbutton',
44
+ 'tooltip',
45
+ 'buttongroup',
46
+ 'listview',
47
+ 'calendar',
48
+ 'contextmenu',
49
+ 'menubar',
50
+ 'tabitem'
51
+ ]
@@ -0,0 +1,44 @@
1
+ """Badge style builders.
2
+
3
+ This module contains style builders for ttk.Label widget badge variants.
4
+ """
5
+ from bootstack.style.bootstyle_builder_ttk import BootstyleBuilderTTk
6
+ from bootstack.style.element import Element, ElementImage
7
+ from bootstack.style.utility import recolor_element_image
8
+
9
+
10
+ @BootstyleBuilderTTk.register_builder('square', 'TBadge')
11
+ def build_default_badge_style(b: BootstyleBuilderTTk, ttk_style: str, accent: str = None, **options):
12
+ build_badge(b, ttk_style, accent, 'square', **options)
13
+
14
+ @BootstyleBuilderTTk.register_builder('pill', 'TBadge')
15
+ def build_pill_badge_style(b: BootstyleBuilderTTk, ttk_style: str, accent: str = None, **options):
16
+ build_badge(b, ttk_style, accent, 'pill', **options)
17
+
18
+
19
+ def build_badge(b: BootstyleBuilderTTk, ttk_style: str, accent: str = None, variant: str = 'square', **options):
20
+ """Create a badge style for the variant specified"""
21
+
22
+ surface_token = options.get('surface', 'content')
23
+ surface = b.color(surface_token)
24
+ normal = b.color(accent or 'primary')
25
+ foreground = b.on_color(normal)
26
+
27
+ badge_img = recolor_element_image(f'badge_{variant}', normal, surface, surface, surface)
28
+
29
+ b.create_style_element_image(ElementImage(f'{ttk_style}.border', badge_img.image,
30
+ border=badge_img.meta.border,
31
+ padding=badge_img.meta.padding,
32
+ height=badge_img.meta.height,
33
+ sticky='nsew'))
34
+
35
+ b.create_style_layout(
36
+ ttk_style, Element(f"{ttk_style}.border", sticky="nsew").children(
37
+ [
38
+ Element("Label.padding", sticky="nsew").children(
39
+ [
40
+ Element("Label.label", sticky="ew")
41
+ ])
42
+ ]))
43
+
44
+ b.configure_style(ttk_style, background=surface, foreground=foreground, padding=(6, 0))