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,499 @@
1
+ """Enhanced TTK Style class with builder registry and theme management."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import weakref
6
+ from tkinter.ttk import Style as ttkStyle
7
+ from typing import Dict, Optional, Set
8
+
9
+ from bootstack.runtime.app import get_app_settings
10
+ from bootstack.style.bootstyle_builder_ttk import BootstyleBuilderTTk
11
+ from bootstack.style.theme_provider import ThemeProvider, use_theme
12
+ from bootstack.widgets.types import Master
13
+
14
+ _style_instance: Style | None = None
15
+
16
+
17
+ class Style(ttkStyle):
18
+ """Enhanced TTK Style with builder registry and theme management.
19
+
20
+ This class extends ttk.Style to provide:
21
+
22
+ - Singleton pattern (one instance per Tkinter master)
23
+ - Integration with BootstyleBuilder registry
24
+ - Theme management via ThemeProvider
25
+ - Automatic style rebuilding on theme changes
26
+ - Custom style options support
27
+
28
+ The Style class maintains registries to track:
29
+
30
+ - All created styles (for theme change rebuilds)
31
+ - Which styles exist in each theme (for caching)
32
+ - Custom options per style (for recreating with same options)
33
+ """
34
+
35
+ def __new__(cls, *args, **kwargs):
36
+ """Ensure Style() always returns the global singleton instance.
37
+
38
+ If an instance already exists, return it. Otherwise, create it.
39
+ """
40
+ global _style_instance
41
+ if _style_instance is None:
42
+ _style_instance = super().__new__(cls)
43
+ return _style_instance
44
+
45
+ def __init__(self, master: Master = None, theme: str = "light"):
46
+ """Initialize the Style instance.
47
+
48
+ Args:
49
+ master: Tkinter master widget (None for default)
50
+ theme: Initial theme name (default: "light")
51
+ """
52
+ # Prevent reinitialization on subsequent Style() calls
53
+ if getattr(self, "_initialized", False):
54
+ # Optionally honor a theme argument after initialization
55
+ try:
56
+ if theme and theme != self._current_theme:
57
+ self.theme_use(theme)
58
+ except Exception:
59
+ pass
60
+ return
61
+
62
+ super().__init__(master)
63
+
64
+ self._theme_provider = use_theme(theme)
65
+ self._style_builder = BootstyleBuilderTTk(theme_provider=self._theme_provider, style_instance=None)
66
+ self._style_builder.set_style_instance(self)
67
+
68
+ # Style registries
69
+ self._style_registry: Set[str] = set()
70
+ self._style_accents: Dict[str, Optional[str]] = {}
71
+ self._style_variants: Dict[str, str] = {}
72
+ self._style_options: Dict[str, dict] = {}
73
+ self._style_widget_classes: Dict[str, str] = {}
74
+
75
+ # Current theme tracking
76
+ self._current_theme: Optional[str] = theme
77
+
78
+ # Track legacy Tk widgets for theme-change restyling
79
+ self._tk_widgets = weakref.WeakSet()
80
+
81
+ self.theme_use(theme)
82
+ self._initialized = True
83
+
84
+ @property
85
+ def style_builder(self) -> BootstyleBuilderTTk:
86
+ """Get the builder manager instance.
87
+
88
+ Returns:
89
+ BootstyleBuilder instance
90
+ """
91
+ return self._style_builder
92
+
93
+ @property
94
+ def theme_provider(self) -> ThemeProvider:
95
+ """Get the theme provider instance.
96
+
97
+ Returns:
98
+ ThemeProvider instance
99
+ """
100
+ return self._theme_provider
101
+
102
+ # ----- Theme metadata helpers -------------------------------------------------
103
+
104
+ def list_themes(self) -> list[dict[str, str]]:
105
+ """Return available themes as [{'name', 'display_name'}, ...].
106
+
107
+ This delegates to the underlying ThemeProvider. Themes are always
108
+ loaded from both the v2 and legacy theme packages.
109
+
110
+ Returns:
111
+ List of theme dictionaries with 'name' and 'display_name' keys.
112
+ """
113
+ return self._theme_provider.list_themes()
114
+
115
+ @property
116
+ def current_theme(self) -> Optional[str]:
117
+ """Get the current theme name.
118
+
119
+ Returns:
120
+ Current theme name or None
121
+ """
122
+ return self._current_theme
123
+
124
+ @property
125
+ def colors(self) -> dict[str, str]:
126
+ """Get colors for the current theme.
127
+
128
+ Returns:
129
+ Colors dictionary from ThemeProvider
130
+ """
131
+ return self._theme_provider.colors
132
+
133
+ def style_exists(self, style: str) -> bool:
134
+ """Check if a style exists (basic check).
135
+
136
+ Args:
137
+ style: TTK style name
138
+
139
+ Returns:
140
+ True if style has any configuration
141
+ """
142
+ return bool(self.configure(style))
143
+
144
+ def register_style(self, ttk_style: str, options: Optional[dict] = None):
145
+ """Register a style in the current theme.
146
+
147
+ This adds the style to registries so it can be:
148
+
149
+ - Cached (not recreated if already exists)
150
+ - Rebuilt when theme changes
151
+ - Recreated with same options
152
+
153
+ Args:
154
+ ttk_style: Full TTK style name
155
+ options: Optional custom style options
156
+ """
157
+ # Add to global registry
158
+ self._style_registry.add(ttk_style)
159
+
160
+ # Store a copy of custom options if provided (to prevent mutation issues)
161
+ if options:
162
+ self._style_options[ttk_style] = options.copy()
163
+
164
+ def create_style(
165
+ self,
166
+ widget_class: str,
167
+ variant: str,
168
+ ttk_style: str,
169
+ accent: Optional[str] = None,
170
+ options: Optional[dict] = None) -> None:
171
+ """Create a new style if it doesn't exist in current theme.
172
+
173
+ Args:
174
+ widget_class: TTK widget class (e.g., "TButton")
175
+ variant: Variant name (e.g., "outline")
176
+ ttk_style: Full TTK style name (e.g., "success.Outline.TButton")
177
+ accent: Optional accent token (e.g., "success", "blue[100]")
178
+ options: Optional custom style options
179
+ """
180
+ # Check if already exists in this theme
181
+ if self.style_exists(ttk_style):
182
+ return # Already created for this theme
183
+
184
+ # Call builder with widget class, variant, and parsed accent
185
+ self._style_builder.call_builder(
186
+ widget_class=widget_class,
187
+ variant=variant,
188
+ ttk_style=ttk_style,
189
+ accent=accent,
190
+ **(options or {})
191
+ )
192
+
193
+ # Store the accent, variant, and widget_class so we can rebuild with the same values
194
+ self._style_accents[ttk_style] = accent
195
+ self._style_variants[ttk_style] = variant
196
+ self._style_widget_classes[ttk_style] = widget_class
197
+
198
+ # Register it
199
+ self.register_style(ttk_style, options)
200
+
201
+ def theme_use(self, name: str = None) -> str | None:
202
+ """Switch to a different theme and rebuild all styles.
203
+
204
+ Applies theme change to the global Style instance, rebuilds all
205
+ TTK styles and registered Tk widgets, and publishes a legacy
206
+ theme-change event for subscribers.
207
+
208
+ Args:
209
+ name: Theme name to switch to. If None, returns the current theme.
210
+
211
+ Returns:
212
+ The current theme name, or None if no theme is set.
213
+ """
214
+ if name is None:
215
+ return super().theme_use()
216
+
217
+ # Only call use() if theme is changing to avoid redundant build_theme_colors()
218
+ if name != self._theme_provider.name:
219
+ self._theme_provider.use(name)
220
+ self._current_theme = name
221
+
222
+ if name not in self.theme_names():
223
+ self.theme_create(name, 'clam', {})
224
+
225
+ super().theme_use(name)
226
+
227
+ # Initialize all default widget styles before rebuilding custom styles
228
+ # self._style_builder.initialize_all_default_styles()
229
+
230
+ self._rebuild_all_styles()
231
+
232
+ # Re-apply Tk widget styling (legacy widgets)
233
+ self._rebuild_all_tk_widgets()
234
+
235
+ # Publish theme-change event for legacy subscribers
236
+ from bootstack.core.publisher import Channel, Publisher # lazy import
237
+ Publisher.publish_message(Channel.STD)
238
+
239
+ return self._current_theme
240
+
241
+ def _rebuild_all_styles(self):
242
+ """Recreate all registered styles when theme changes.
243
+
244
+ This iterates through all styles that have been created and
245
+ rebuilds them using the new theme's colors, preserving any
246
+ custom options.
247
+ """
248
+ for style in self._style_registry:
249
+ # Get stored options, accent, and variant
250
+ options = self._style_options.get(style, {})
251
+ accent = self._style_accents.get(style)
252
+ variant = self._style_variants.get(style)
253
+
254
+ # Use stored widget_class if available (preserves composite classes like 'Menubar.TField')
255
+ # Fall back to parsing from style name for backwards compatibility
256
+ widget_class = self._style_widget_classes.get(style)
257
+ if not widget_class:
258
+ parsed = self._parse_style_name(style)
259
+ if not parsed:
260
+ continue
261
+ widget_class = parsed['widget_class']
262
+ # Only use parsed variant if we don't have a stored one
263
+ if variant is None:
264
+ variant = parsed['variant']
265
+
266
+ if variant is None:
267
+ from bootstack.style.bootstyle_builder_ttk import BootstyleBuilderTTk
268
+ variant = BootstyleBuilderTTk.get_default_variant(widget_class)
269
+
270
+ self._style_builder.call_builder(
271
+ widget_class=widget_class,
272
+ variant=variant,
273
+ ttk_style=style,
274
+ accent=accent,
275
+ **options
276
+ )
277
+
278
+ def register_tk_widget(self, widget) -> None:
279
+ """Register a Tk widget to be restyled on theme changes."""
280
+ self._tk_widgets.add(widget)
281
+
282
+ def _rebuild_all_tk_widgets(self) -> None:
283
+ """Restyle all registered Tk widgets on theme change."""
284
+ from bootstack.style.bootstyle_builder_tk import BootstyleBuilderBuilderTk
285
+ builder_tk = BootstyleBuilderBuilderTk(theme_provider=self._theme_provider, style_instance=self)
286
+
287
+ for widget in list(self._tk_widgets):
288
+ try:
289
+ surface = getattr(widget, '_surface', 'background')
290
+ builder_tk.call_builder(widget, surface=surface)
291
+ except Exception:
292
+ # ignore incompatible or unmapped widgets
293
+ pass
294
+
295
+ @staticmethod
296
+ def _parse_style_name(ttk_style: str) -> Optional[dict]:
297
+ """Parse TTK style name to extract widget class and variant.
298
+
299
+ Args:
300
+ ttk_style: Full TTK style name
301
+
302
+ Returns:
303
+ Dict with 'widget_class' and 'variant', or None
304
+
305
+ Examples:
306
+ >>> Style._parse_style_name("success.TButton")
307
+ {'widget_class': 'TButton', 'variant': 'solid'}
308
+ >>> Style._parse_style_name("info.Striped.TProgressbar")
309
+ {'widget_class': 'TProgressbar', 'variant': 'striped'}
310
+ """
311
+ # Split into parts
312
+ parts = ttk_style.split('.')
313
+
314
+ if not parts:
315
+ return None
316
+
317
+ # Extract widget class (e.g., "TButton")
318
+ # Widget class is always the LAST part starting with 'T'
319
+ widget_class = None
320
+ for part in parts:
321
+ if part.startswith('T'):
322
+ widget_class = part
323
+
324
+ if not widget_class:
325
+ return None
326
+
327
+ # Determine variant using registered builders for this widget
328
+ from bootstack.style.bootstyle_builder_ttk import BootstyleBuilderTTk
329
+ builder_variants = set(v.lower() for v in BootstyleBuilderTTk.get_registered_builders(widget_class))
330
+
331
+ variant = None
332
+ accent = None
333
+ for part in parts:
334
+ # Skip the widget class itself (e.g., 'TCheckbutton')
335
+ if part == widget_class:
336
+ continue
337
+ token = part.lower()
338
+ # Identify variant by registry match
339
+ if token in builder_variants and variant is None:
340
+ variant = token
341
+ continue
342
+ # First non-variant token becomes accent
343
+ if accent is None:
344
+ accent = part
345
+
346
+ if variant is None:
347
+ variant = BootstyleBuilderTTk.get_default_variant(widget_class)
348
+
349
+ return {
350
+ 'widget_class': widget_class,
351
+ 'variant': variant
352
+ }
353
+
354
+ def get_style_builder(self) -> BootstyleBuilderTTk:
355
+ """Get the style builder instance.
356
+
357
+ Returns:
358
+ BootstyleBuilder instance
359
+ """
360
+ return self._style_builder
361
+
362
+ def __repr__(self) -> str:
363
+ """String representation of Style instance."""
364
+ return f"<Style theme={self._current_theme} styles={len(self._style_registry)}>"
365
+
366
+
367
+ def get_style(master: Master = None) -> Style:
368
+ """Return the global Style singleton instance.
369
+
370
+ Convenience helper function that ensures a single Style instance
371
+ is used across the application.
372
+
373
+ Args:
374
+ master: Optional master for initial construction; ignored thereafter.
375
+
376
+ Returns:
377
+ Global Style instance.
378
+
379
+ Examples:
380
+ >>> style = get_style()
381
+ >>> style.theme_use("ocean-dark")
382
+ """
383
+ if _style_instance:
384
+ return _style_instance
385
+ else:
386
+ return Style(master)
387
+
388
+
389
+ def get_style_builder() -> BootstyleBuilderTTk:
390
+ """Return the style builder for the currently active theme.
391
+
392
+ Returns:
393
+ The BootstyleBuilderTTk instance for the active theme.
394
+
395
+ Examples:
396
+ >>> builder = get_style_builder()
397
+ >>> primary_color = builder.color("primary")
398
+ """
399
+ style = get_style()
400
+ return style.style_builder
401
+
402
+
403
+ # --- Global Utilities ---
404
+
405
+ def set_theme(name: str) -> None:
406
+ """Set the active application theme.
407
+
408
+ Args:
409
+ name: Theme name to activate (e.g., "ocean-dark", "bootstrap-light", "aurora-dark").
410
+
411
+ Examples:
412
+ >>> set_theme("ocean-dark")
413
+ """
414
+ style = get_style()
415
+ style.theme_use(name)
416
+
417
+
418
+ def toggle_theme() -> None:
419
+ """Toggle the active application theme between light and dark mode.
420
+
421
+ Uses the light and dark themes specified in app settings, or defaults
422
+ to bootstrap-light and bootstrap-dark.
423
+
424
+ Examples:
425
+ >>> toggle_theme()
426
+ """
427
+ settings = get_app_settings()
428
+ light = settings.light_theme
429
+ dark = settings.dark_theme
430
+ theme = get_theme()
431
+ if theme == light or theme == "light":
432
+ set_theme(dark)
433
+ else:
434
+ set_theme(light)
435
+
436
+
437
+ def get_theme() -> str:
438
+ """Return the name of the currently active theme.
439
+
440
+ Returns:
441
+ Name of the active theme.
442
+
443
+ Examples:
444
+ >>> theme = get_theme()
445
+ >>> print(theme) # "darkly"
446
+ """
447
+ style = get_style()
448
+ return style.theme_use()
449
+
450
+
451
+ def get_themes() -> list[dict[str, str]]:
452
+ """Return the list of all registered themes.
453
+
454
+ Returns:
455
+ List of dictionaries containing `name` and `display_name` for each theme.
456
+
457
+ Examples:
458
+ >>> themes = get_themes()
459
+ >>> print([theme["name"] for theme in themes])
460
+ """
461
+ style = get_style()
462
+ return style.list_themes()
463
+
464
+
465
+ def get_theme_provider() -> ThemeProvider:
466
+ """Get the theme provider instance for the active theme.
467
+
468
+ Returns:
469
+ ThemeProvider instance.
470
+
471
+ Examples:
472
+ >>> provider = get_theme_provider()
473
+ >>> colors = provider.get_colors()
474
+ """
475
+ style = get_style()
476
+ return style.theme_provider
477
+
478
+
479
+ def get_theme_color(token: str) -> str:
480
+ """Get a hex color value from a color token based on the active theme.
481
+
482
+ Args:
483
+ token: Color token name (e.g., "primary", "background").
484
+
485
+ Returns:
486
+ Hex color string (e.g., "#007bff").
487
+
488
+ Raises:
489
+ ValueError: If the color token is invalid.
490
+
491
+ Examples:
492
+ >>> primary = get_theme_color("primary")
493
+ >>> print(primary) # "#007bff"
494
+ """
495
+ builder = get_style_builder()
496
+ try:
497
+ return builder.color(token)
498
+ except Exception:
499
+ raise ValueError(f"Invalid color token: {token}")