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,382 @@
1
+ from __future__ import annotations
2
+
3
+ from tkinter import StringVar
4
+ from typing import Any, Callable, Literal, TYPE_CHECKING
5
+
6
+ from typing_extensions import TypedDict, Unpack
7
+
8
+ from bootstack.widgets.primitives.radiotoggle import RadioToggle
9
+ from bootstack.widgets.primitives.checktoggle import CheckToggle
10
+ from bootstack.core.variables import SetVar
11
+ from bootstack.widgets.mixins.configure_mixin import configure_delegate
12
+ from bootstack.widgets.primitives import Frame
13
+
14
+ if TYPE_CHECKING:
15
+ from bootstack.core.signals import Signal
16
+ import tkinter as tk
17
+
18
+
19
+ class ToggleGroupKwargs(TypedDict, total=False):
20
+ mode: Literal['single', 'multi']
21
+ variable: Any
22
+ signal: Signal[Any]
23
+ value: str | set[str]
24
+ orient: Literal['horizontal', 'vertical']
25
+ accent: str
26
+ variant: Literal['outline', 'ghost'] | None
27
+ show_border: bool
28
+ surface: str
29
+ style_options: dict[str, Any]
30
+ # Frame options
31
+ padding: Any
32
+ width: int
33
+ height: int
34
+
35
+
36
+ class ToggleGroup(Frame):
37
+ """A group of toggle buttons with single or multi-selection support.
38
+
39
+ The ToggleGroup widget provides a convenient way to create groups of toggle
40
+ buttons with automatic position tracking and styling. It supports both single
41
+ selection (radio button behavior) and multi-selection (checkbox behavior).
42
+ """
43
+
44
+ def __init__(self, master: Any = None, **kwargs: Unpack[ToggleGroupKwargs]):
45
+ """Initialize the ToggleGroup.
46
+
47
+ Args:
48
+ master: Parent widget. If None, uses the default root window.
49
+
50
+ Other Parameters:
51
+ mode (str): Selection mode - 'single' for radio button behavior (default),
52
+ or 'multi' for checkbox behavior allowing multiple selections.
53
+ orient (str): Layout orientation - 'horizontal' (default) or 'vertical'.
54
+ accent (str): Accent token for styling (e.g., 'primary', 'danger').
55
+ Defaults to 'primary'.
56
+ variant (str): Style variant (e.g., 'outline', 'ghost').
57
+ bootstyle (str): DEPRECATED - Use `accent` and `variant` instead.
58
+ variable (Variable): Optional tk.Variable for controlling the value. For single mode,
59
+ use StringVar; for multi mode, use SetVar.
60
+ signal (Signal): Optional Signal instance for reactive programming.
61
+ value (str | set): Initial value - string for single mode, set for multi mode.
62
+ show_border (bool): If True, draws a border around the group.
63
+ surface (str): Optional surface token; otherwise inherited.
64
+ style_options (dict): Additional style options passed to child buttons.
65
+ padding (int | tuple): Frame padding. Defaults to 1.
66
+ width (int): Requested width in pixels.
67
+ height (int): Requested height in pixels.
68
+ """
69
+ # Extract ToggleGroup-specific options before super().__init__
70
+ self._mode = kwargs.pop('mode', 'single')
71
+ self._orientation = kwargs.pop('orient', 'horizontal')
72
+ accent = kwargs.pop('accent', None) or 'primary'
73
+ variant = kwargs.pop('variant', None) # None (default), 'outline', or 'ghost'
74
+
75
+ # Handle signal/variable/value similar to CheckToggle pattern
76
+ initial_value = kwargs.pop('value', None)
77
+
78
+ style_options = kwargs.pop('style_options', {})
79
+
80
+ # Initialize internal state
81
+ self._buttons: dict[str, RadioToggle | CheckToggle] = {}
82
+
83
+ # Extract signal/variable before Frame init
84
+ signal_value = kwargs.pop('signal', None)
85
+ variable_value = kwargs.pop('variable', None)
86
+
87
+ # Call super().__init__() - just Frame now
88
+ super().__init__(master, style_options=style_options, padding=1, **kwargs)
89
+
90
+ # Restore accent/variant (super().__init__ overwrites them with None)
91
+ self._accent = accent
92
+ self._variant = variant
93
+
94
+ # Handle variable/signal setup manually
95
+ if signal_value is not None:
96
+ # Signal provided - extract its variable
97
+ self._signal = signal_value
98
+ self._variable = signal_value.var
99
+ elif variable_value is not None:
100
+ # Variable provided - wrap in Signal
101
+ from bootstack.core.signals import Signal
102
+ self._variable = variable_value
103
+ self._signal = Signal.from_variable(variable_value)
104
+ # Set initial value if provided
105
+ if initial_value is not None:
106
+ self._variable.set(initial_value)
107
+ else:
108
+ # Neither provided - create internal variable
109
+ from bootstack.core.signals import Signal
110
+ if self._mode == 'single':
111
+ internal_var = StringVar(value=initial_value or '')
112
+ else:
113
+ internal_var = SetVar(value=initial_value or set())
114
+ self._variable = internal_var
115
+ self._signal = Signal.from_variable(internal_var)
116
+
117
+ @property
118
+ def variable(self) -> 'tk.Variable':
119
+ """Get the underlying tk.Variable."""
120
+ return self._variable
121
+
122
+ @variable.setter
123
+ def variable(self, value: 'tk.Variable') -> None:
124
+ """Set the variable."""
125
+ from bootstack.core.signals import Signal
126
+ self._variable = value
127
+ self._signal = Signal.from_variable(value)
128
+
129
+ @property
130
+ def signal(self) -> 'Signal[Any]':
131
+ """Get the signal."""
132
+ return self._signal
133
+
134
+ @signal.setter
135
+ def signal(self, value: 'Signal[Any]') -> None:
136
+ """Set the signal."""
137
+ self._signal = value
138
+ self._variable = value.var
139
+
140
+ def add(self, text: str = None, value: Any = None, key: str | None = None, **kwargs: Any) -> RadioToggle | CheckToggle:
141
+ """Add a toggle button to the group.
142
+
143
+ Args:
144
+ text: Text to display on the button.
145
+ value: Value this button represents (required).
146
+ key: Unique identifier. Defaults to value.
147
+ **kwargs: Additional arguments passed to RadioToggle or CheckToggle.
148
+
149
+ Returns:
150
+ The created button widget.
151
+ """
152
+ if value is None:
153
+ raise ValueError("The 'value' argument is required.")
154
+
155
+ key = key or value
156
+ if key in self._buttons:
157
+ raise ValueError(f"A button with the key '{key}' already exists.")
158
+
159
+ btn_kwargs = kwargs.copy()
160
+ # Set the ButtonGroup ttk_class - position will be updated by _update_button_positions
161
+ custom_accent = btn_kwargs.pop('accent', None) or self._accent
162
+ btn_kwargs['accent'] = custom_accent
163
+ btn_kwargs['ttk_class'] = 'ButtonGroup'
164
+ # variant can be None (default), 'outline', or 'ghost' - use group's variant if not specified
165
+ if 'variant' not in btn_kwargs:
166
+ btn_kwargs['variant'] = self._variant
167
+ # Merge orient and initial position into style_options
168
+ existing_style_opts = btn_kwargs.get('style_options', {}).copy()
169
+ existing_style_opts['orient'] = self._orientation
170
+ existing_style_opts.setdefault('position', 'before') # Default position, will be corrected later
171
+ btn_kwargs['style_options'] = existing_style_opts
172
+
173
+ if self._mode == 'single':
174
+ button = RadioToggle(self, text=text, value=value, variable=self.variable, **btn_kwargs)
175
+ else: # multi
176
+ button = CheckToggle(self, text=text, **btn_kwargs)
177
+
178
+ # Set initial state based on current SetVar value
179
+ current_set = self.variable.get()
180
+ if not isinstance(current_set, set):
181
+ current_set = set()
182
+ button.variable.set(value in current_set)
183
+
184
+ # Bind command to update SetVar
185
+ # Pop command to avoid double-calling
186
+ original_command = btn_kwargs.pop('command', None)
187
+
188
+ def toggle_command():
189
+ self._on_multi_toggle(value)
190
+ if original_command:
191
+ original_command()
192
+
193
+ button.configure(command=toggle_command)
194
+
195
+ if self._orientation == 'horizontal':
196
+ button.pack(side='left')
197
+ else: # vertical
198
+ button.pack(side='top', fill='x')
199
+
200
+ self._buttons[key] = button
201
+ self._update_button_positions()
202
+ return button
203
+
204
+ def _update_button_positions(self):
205
+ """Update button styles based on their position in the group.
206
+
207
+ Note: Relies on dictionary insertion order (Python 3.7+) to maintain
208
+ button order based on when they were added.
209
+ """
210
+ # List conversion maintains insertion order (Python 3.7+)
211
+ button_list = list(self._buttons.values())
212
+ num_buttons = len(button_list)
213
+
214
+ if num_buttons == 0:
215
+ return
216
+
217
+ for idx, button in enumerate(button_list):
218
+ if num_buttons == 1:
219
+ # Single button - use 'before' position (fully rounded on left/top)
220
+ position = 'before'
221
+ elif idx == 0:
222
+ # First button
223
+ position = 'before'
224
+ elif idx == num_buttons - 1:
225
+ # Last button
226
+ position = 'after'
227
+ else:
228
+ # Middle button
229
+ position = 'center'
230
+
231
+ # Update position and rebuild style
232
+ button.configure_style_options(position=position)
233
+ button.rebuild_style()
234
+
235
+ def _on_multi_toggle(self, val: str):
236
+ """Callback to update the SetVar when a CheckToggle is clicked."""
237
+ current_set = self.get()
238
+ if val in current_set:
239
+ current_set.remove(val)
240
+ else:
241
+ current_set.add(val)
242
+ self.set(current_set)
243
+
244
+ def get(self) -> str | set[str]:
245
+ """Return the current value (string for single mode, set for multi mode)."""
246
+ return self.variable.get()
247
+
248
+ def set(self, value: str | set[str]) -> None:
249
+ """Set the value (string for single mode, set for multi mode).
250
+
251
+ Args:
252
+ value: The value to set.
253
+
254
+ Raises:
255
+ TypeError: If value type doesn't match the mode.
256
+ """
257
+ # Validate value type matches mode
258
+ if self._mode == 'single':
259
+ if not isinstance(value, str):
260
+ raise TypeError(f"Single mode requires a string value, got {type(value).__name__}")
261
+ else: # multi mode
262
+ if not isinstance(value, set):
263
+ raise TypeError(f"Multi mode requires a set value, got {type(value).__name__}")
264
+
265
+ self.variable.set(value)
266
+
267
+ # For multi mode, update CheckToggle states to match new value
268
+ if self._mode == 'multi':
269
+ for key, button in self._buttons.items():
270
+ button.variable.set(key in value)
271
+
272
+ @property
273
+ def value(self) -> str | set[str]:
274
+ """Get or set the value (string for single mode, set for multi mode)."""
275
+ return self.get()
276
+
277
+ @value.setter
278
+ def value(self, value: str | set[str]) -> None:
279
+ self.set(value)
280
+
281
+ def remove(self, key: str):
282
+ """Remove a button by its key."""
283
+ if key in self._buttons:
284
+ button = self._buttons.pop(key)
285
+ button.destroy()
286
+ self._update_button_positions()
287
+
288
+ def items(self) -> tuple[RadioToggle | CheckToggle, ...]:
289
+ """Get all button widgets in the group.
290
+
291
+ Returns:
292
+ A tuple of all button instances in the group.
293
+ """
294
+ return tuple(self._buttons.values())
295
+
296
+ def item(self, key: str) -> RadioToggle | CheckToggle:
297
+ """Get a button by its key.
298
+
299
+ Args:
300
+ key: The key of the button to retrieve.
301
+
302
+ Returns:
303
+ The button instance.
304
+
305
+ Raises:
306
+ KeyError: If no button with the given key exists.
307
+ """
308
+ if key not in self._buttons:
309
+ raise KeyError(f"No button with key '{key}'")
310
+ return self._buttons[key]
311
+
312
+ def configure_item(self, key: str, option: str = None, **kwargs: Any):
313
+ """Configure a specific button by its key.
314
+
315
+ Args:
316
+ key: The key of the button to configure.
317
+ option: If provided, return the value of this option.
318
+ **kwargs: Configuration options to apply to the button.
319
+
320
+ Returns:
321
+ If option is provided, returns the value of that option.
322
+ """
323
+ button = self.item(key)
324
+ if option is not None:
325
+ return button.cget(option)
326
+ button.configure(**kwargs)
327
+
328
+ def keys(self) -> tuple[str, ...]:
329
+ """Get all button keys.
330
+
331
+ Returns:
332
+ A tuple of all button keys in the group.
333
+ """
334
+ return tuple(self._buttons.keys())
335
+
336
+ def on_changed(self, callback: Callable) -> Any:
337
+ """Subscribe to value changes. Callback receives `new_value: str | set[str]` directly (str in 'single' mode, set in 'multi' mode)."""
338
+ return self._signal.subscribe(callback)
339
+
340
+ def off_changed(self, bind_id: Any) -> None:
341
+ """Unsubscribe from value changes."""
342
+ self._signal.unsubscribe(bind_id)
343
+
344
+ @configure_delegate('accent')
345
+ def _delegate_accent(self, value=None):
346
+ """Get or set the accent. Updates all buttons when changed."""
347
+ if value is None:
348
+ return self._accent
349
+
350
+ self._accent = value
351
+ # Update all buttons with new accent
352
+ self._update_button_positions()
353
+
354
+ @configure_delegate('orient')
355
+ def _delegate_orient(self, value=None):
356
+ """Get or set orientation ('horizontal' or 'vertical'). Repacks buttons when changed."""
357
+ if value is None:
358
+ return self._orientation
359
+
360
+ if value not in ('horizontal', 'vertical'):
361
+ raise ValueError("orient must be 'horizontal' or 'vertical'")
362
+
363
+ self._orientation = value
364
+
365
+ # Repack all buttons in new orientation
366
+ for button in self._buttons.values():
367
+ button.pack_forget()
368
+ button.configure_style_options(orient=value)
369
+ if self._orientation == 'horizontal':
370
+ button.pack(side='left')
371
+ else:
372
+ button.pack(side='top', fill='x')
373
+
374
+ # Update button styles with new orientation
375
+ self._update_button_positions()
376
+
377
+ @configure_delegate('value')
378
+ def _delegate_value(self, value=None):
379
+ """Get or set the value via configure."""
380
+ if value is None:
381
+ return self.get()
382
+ self.set(value)