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,413 @@
1
+ """SideNavItem widget for selectable navigation items."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from tkinter import Variable
6
+ from typing import Any, Callable, TYPE_CHECKING
7
+
8
+ from typing_extensions import TypedDict, Unpack
9
+
10
+ from bootstack.widgets.primitives.frame import Frame
11
+ from bootstack.widgets.primitives.label import Label
12
+ from bootstack.widgets.composites.compositeframe import CompositeFrame
13
+ from bootstack.widgets.mixins import configure_delegate
14
+ from bootstack.widgets.types import Master
15
+
16
+ if TYPE_CHECKING:
17
+ from bootstack.core.signals import Signal
18
+
19
+
20
+ class SideNavItemKwargs(TypedDict, total=False):
21
+ key: str
22
+ text: str
23
+ icon: Any
24
+ signal: Any
25
+ variable: Variable
26
+ is_enabled: bool
27
+ indent_level: int
28
+ command: Callable
29
+ padding_x: int
30
+ padding_y: int
31
+ icon_gap: int
32
+ accent: str
33
+ variant: str
34
+ # Frame options
35
+ padding: Any
36
+ width: int
37
+ height: int
38
+
39
+
40
+ class SideNavItem(Frame):
41
+ """A selectable navigation item with icon and text.
42
+
43
+ SideNavItem uses a CompositeFrame container with separate icon and
44
+ text label children. This provides synchronized hover/pressed/selected
45
+ states across all elements and precise control over layout.
46
+
47
+ The widget supports expanded and compact modes. In compact mode, only the
48
+ icon is displayed and it remains perfectly centered due to symmetrical
49
+ padding. In expanded mode, both icon and text are visible.
50
+
51
+ Uses NavigationButton.TFrame for the container (with selection indicator)
52
+ and NavigationButton.TLabel for the icon and text labels.
53
+
54
+ !!! note "Events"
55
+ - `<<ItemInvoked>>`: Fired when the item is clicked.
56
+ `event.data = {'key': str}`
57
+
58
+ Example:
59
+ ```python
60
+ # Items are typically created via SideNav.add_item()
61
+ nav.add_item('home', text='Home', icon='house')
62
+ nav.add_item('local', text='Local', icon='hdd', group='files')
63
+ ```
64
+ """
65
+
66
+ # Default indent width in pixels per indent level
67
+ INDENT_WIDTH = 24
68
+
69
+ # Default padding values
70
+ DEFAULT_PADDING_X = 12 # Horizontal padding on left/right edges
71
+ DEFAULT_PADDING_Y = 6 # Vertical padding
72
+ DEFAULT_ICON_GAP = 10 # Gap between icon and text in expanded mode
73
+ COMPACT_PADDING_X = 6 # Reduced horizontal padding in compact mode
74
+ COMPACT_PADDING_Y = 6 # Reduced vertical padding in compact mode
75
+
76
+ def __init__(
77
+ self,
78
+ master: Master = None,
79
+ key: str = '',
80
+ text: str = '',
81
+ icon: str | dict = None,
82
+ signal: 'Signal[Any]' = None,
83
+ variable: Variable = None,
84
+ is_enabled: bool = True,
85
+ indent_level: int = 0,
86
+ command: Callable = None,
87
+ padding_x: int = None,
88
+ padding_y: int = None,
89
+ icon_gap: int = None,
90
+ **kwargs: Unpack[SideNavItemKwargs]
91
+ ):
92
+ """Initialize a SideNavItem.
93
+
94
+ Args:
95
+ master (Master | None): Parent widget.
96
+ key (str): Unique identifier for this item (used as selection value).
97
+ text (str): Display text for the item.
98
+ icon (str | dict | None): Icon name or configuration dict.
99
+ signal (Signal | None): Reactive signal for selection state (preferred).
100
+ variable (Variable | None): Shared variable for radio group selection.
101
+ is_enabled (bool): Whether the item is interactive. Default True.
102
+ indent_level (int): Nesting level for indentation (0 = root, 1 = child). Default 0.
103
+ command (Callable | None): Callback invoked when item is clicked.
104
+ padding_x (int | None): Horizontal padding on edges. Default is 12.
105
+ padding_y (int | None): Vertical padding. Default is 8.
106
+ icon_gap (int | None): Gap between icon and text. Default is 8.
107
+ **kwargs: Additional arguments passed to Frame.
108
+ """
109
+ if not key:
110
+ raise ValueError("SideNavItem requires a non-empty 'key'")
111
+
112
+ # Extract styling kwargs before super().__init__
113
+ # Must set these AFTER super().__init__ because TTKWrapperBase also sets _accent/_variant
114
+ saved_accent = kwargs.pop('accent', 'primary')
115
+ saved_variant = kwargs.pop('variant', None)
116
+
117
+ super().__init__(master, **kwargs)
118
+
119
+ # Set after super() to avoid being overwritten by TTKWrapperBase
120
+ self._accent = saved_accent
121
+ self._variant = saved_variant
122
+
123
+ self._key = key
124
+ self._text = text
125
+ self._icon = icon
126
+ self._signal = signal
127
+ self._variable = variable
128
+ self._is_enabled = is_enabled
129
+ self._indent_level = indent_level
130
+ self._command = command
131
+ self._padding_x = padding_x if padding_x is not None else self.DEFAULT_PADDING_X
132
+ self._padding_y = padding_y if padding_y is not None else self.DEFAULT_PADDING_Y
133
+ self._icon_gap = icon_gap if icon_gap is not None else self.DEFAULT_ICON_GAP
134
+
135
+ # Compact mode state
136
+ self._compact = False
137
+
138
+ # Widget references
139
+ self._container: CompositeFrame | None = None
140
+ self._icon_label: Label | None = None
141
+ self._text_label: Label | None = None
142
+
143
+ # Variable trace
144
+ self._trace_id: str | None = None
145
+
146
+ # Build internal structure
147
+ self._build_widget()
148
+
149
+ # Set up variable trace for selection state
150
+ self._setup_variable_trace()
151
+
152
+ # Apply initial enabled state
153
+ if not is_enabled:
154
+ self._container.set_disabled(True)
155
+
156
+ def _build_widget(self):
157
+ """Build the internal widget structure."""
158
+ # Calculate indentation padding for expanded mode
159
+ indent_padding = self._indent_level * self.INDENT_WIDTH
160
+ left_padding = self._padding_x + indent_padding
161
+
162
+ # CompositeFrame container with selection indicator
163
+ # Uses NavigationButton.TFrame style which has the nav-button assets
164
+ self._container = CompositeFrame(
165
+ self,
166
+ ttk_class='NavigationButton.TFrame',
167
+ accent=self._accent,
168
+ padding=(left_padding, self._padding_y, self._padding_x, self._padding_y),
169
+ takefocus=True,
170
+ )
171
+ self._container.pack(fill='x')
172
+
173
+ # Icon label (optional)
174
+ if self._icon:
175
+ self._icon_label = Label(
176
+ self._container,
177
+ icon=self._icon,
178
+ icon_only=True,
179
+ ttk_class='NavigationButton.TLabel',
180
+ accent=self._accent,
181
+ takefocus=False,
182
+ )
183
+ self._container.register_composite(self._icon_label)
184
+
185
+ # Text label
186
+ self._text_label = Label(
187
+ self._container,
188
+ text=self._text,
189
+ anchor='w',
190
+ ttk_class='NavigationButton.TLabel',
191
+ accent=self._accent,
192
+ takefocus=False,
193
+ )
194
+ self._container.register_composite(self._text_label)
195
+
196
+ # Apply initial layout
197
+ self._apply_layout()
198
+
199
+ # Bind click events - only to container, events bubble up from children
200
+ self._bind_events()
201
+
202
+ def _apply_layout(self):
203
+ """Apply the current layout based on compact mode."""
204
+ # Clear current layout
205
+ if self._icon_label:
206
+ self._icon_label.pack_forget()
207
+ self._text_label.pack_forget()
208
+
209
+ if self._compact:
210
+ # Compact mode: tighter symmetrical padding, icon centered
211
+ px = self.COMPACT_PADDING_X
212
+ py = self.COMPACT_PADDING_Y
213
+ self._container.configure(padding=(px, py, px, py))
214
+ if self._icon_label:
215
+ self._icon_label.pack(expand=True)
216
+ else:
217
+ # Expanded mode: icon + text, with indent
218
+ indent_padding = self._indent_level * self.INDENT_WIDTH
219
+ left_padding = self._padding_x + indent_padding
220
+ self._container.configure(
221
+ padding=(left_padding, self._padding_y, self._padding_x, self._padding_y)
222
+ )
223
+ if self._icon_label:
224
+ self._icon_label.pack(side='left', padx=(0, self._icon_gap))
225
+ self._text_label.pack(side='left', fill='x', expand=True)
226
+
227
+ def _bind_events(self):
228
+ """Bind click and keyboard events.
229
+
230
+ Binds click to container and all child widgets since Tkinter
231
+ doesn't bubble events from children to parents.
232
+ """
233
+ self._container.bind('<Button-1>', self._on_click, add='+')
234
+ if self._icon_label:
235
+ self._icon_label.bind('<Button-1>', self._on_click, add='+')
236
+ self._text_label.bind('<Button-1>', self._on_click, add='+')
237
+
238
+ # Keyboard support on focusable container
239
+ self._container.bind('<Return>', self._on_click, add='+')
240
+ self._container.bind('<space>', self._on_click, add='+')
241
+
242
+ def _setup_variable_trace(self):
243
+ """Set up variable trace for selection state updates.
244
+
245
+ Note: For performance, the SideNav now manages selection updates
246
+ centrally rather than each item tracing the variable. This method is
247
+ kept for backwards compatibility but does nothing when used with
248
+ SideNav.
249
+ """
250
+ # Selection state is now managed by SideNav._on_selection_changed()
251
+ # which only updates the affected items rather than all items.
252
+ # Initial state update
253
+ self._update_selection_state()
254
+
255
+ def _update_selection_state(self):
256
+ """Update visual state based on selection."""
257
+ if self._variable is not None and self._key:
258
+ selected = self._variable.get() == self._key
259
+ self._container.set_selected(selected)
260
+
261
+ def set_selected(self, selected: bool) -> None:
262
+ """Directly set the selection visual state.
263
+
264
+ This is called by SideNav for efficient selection updates,
265
+ avoiding the need to query the variable.
266
+
267
+ Args:
268
+ selected: True to show as selected, False otherwise.
269
+ """
270
+ self._container.set_selected(selected)
271
+
272
+ def _on_click(self, event=None):
273
+ """Handle item click."""
274
+ if not self._is_enabled:
275
+ return
276
+
277
+ # Request focus
278
+ self._container.focus_set()
279
+
280
+ # Set selection if variable is configured
281
+ if self._variable is not None and self._key:
282
+ self._variable.set(self._key)
283
+
284
+ # Fire invoked event
285
+ self.event_generate('<<ItemInvoked>>', data={'key': self._key})
286
+
287
+ # Call command if set
288
+ if self._command:
289
+ self._command()
290
+
291
+ # --- Public API ---
292
+
293
+ def select(self) -> None:
294
+ """Select this item (set the variable to this item's key)."""
295
+ if self._variable is not None:
296
+ self._variable.set(self._key)
297
+
298
+ def set_enabled(self, enabled: bool) -> None:
299
+ """Set the enabled state.
300
+
301
+ Args:
302
+ enabled (bool): True to enable, False to disable.
303
+ """
304
+ self._is_enabled = enabled
305
+ self._container.set_disabled(not enabled)
306
+
307
+ def set_compact(self, compact: bool) -> None:
308
+ """Set compact mode (icon only, no text).
309
+
310
+ Args:
311
+ compact (bool): True for compact mode, False for full display.
312
+ """
313
+ if self._compact == compact:
314
+ return
315
+
316
+ self._compact = compact
317
+ self._apply_layout()
318
+ self._update_selection_state()
319
+
320
+ # --- Properties ---
321
+
322
+ @property
323
+ def key(self) -> str:
324
+ """Get the item's unique key."""
325
+ return self._key
326
+
327
+ @property
328
+ def is_selected(self) -> bool:
329
+ """Check if this item is currently selected."""
330
+ if self._variable is not None:
331
+ return self._variable.get() == self._key
332
+ return False
333
+
334
+ @property
335
+ def is_enabled(self) -> bool:
336
+ """Check if this item is enabled."""
337
+ return self._is_enabled
338
+
339
+ @property
340
+ def signal(self) -> 'Signal[Any] | None':
341
+ """Get the signal for selection state."""
342
+ return self._signal
343
+
344
+ @property
345
+ def variable(self) -> Variable | None:
346
+ """Get the variable for selection state."""
347
+ return self._variable
348
+
349
+ # --- Configuration Delegates ---
350
+
351
+ @configure_delegate('text')
352
+ def _delegate_text(self, value: str = None):
353
+ """Configure the item text."""
354
+ if value is None:
355
+ return self._text
356
+ self._text = value
357
+ if self._text_label:
358
+ self._text_label.configure(text=value)
359
+ return None
360
+
361
+ @configure_delegate('icon')
362
+ def _delegate_icon(self, value: str | dict = None):
363
+ """Configure the item icon."""
364
+ if value is None:
365
+ return self._icon
366
+ self._icon = value
367
+
368
+ if self._icon_label is not None:
369
+ self._icon_label.configure(icon=value)
370
+ elif value is not None:
371
+ # Create icon label if it doesn't exist
372
+ self._icon_label = Label(
373
+ self._container,
374
+ icon=value,
375
+ icon_only=True,
376
+ ttk_class='NavigationButton.TLabel',
377
+ accent=self._accent,
378
+ takefocus=False,
379
+ )
380
+ self._container.register_composite(self._icon_label)
381
+ self._icon_label.bind('<Button-1>', self._on_click, add='+')
382
+ # Re-apply layout
383
+ self._apply_layout()
384
+ return None
385
+
386
+ @configure_delegate('command')
387
+ def _delegate_command(self, value: Callable = None):
388
+ """Configure the command callback."""
389
+ if value is None:
390
+ return self._command
391
+ self._command = value
392
+ return None
393
+
394
+ # --- Event Binding Helpers ---
395
+
396
+ def on_invoked(self, callback) -> str:
397
+ """Bind to `<<ItemInvoked>>`.
398
+
399
+ Args:
400
+ callback: Function to call when item is invoked.
401
+
402
+ Returns:
403
+ str: Binding identifier for use with off_invoked().
404
+ """
405
+ return self.bind('<<ItemInvoked>>', callback, add='+')
406
+
407
+ def off_invoked(self, bind_id: str = None) -> None:
408
+ """Unbind from `<<ItemInvoked>>`.
409
+
410
+ Args:
411
+ bind_id (str | None): Binding identifier from on_invoked().
412
+ """
413
+ self.unbind('<<ItemInvoked>>', bind_id)
@@ -0,0 +1,51 @@
1
+ """SideNavSeparator widget for visual grouping in navigation menus."""
2
+
3
+ from typing import Any
4
+
5
+ from typing_extensions import TypedDict, Unpack
6
+
7
+ from bootstack.widgets.primitives.frame import Frame
8
+ from bootstack.widgets.primitives.separator import Separator
9
+ from bootstack.widgets.types import Master
10
+
11
+
12
+ class SideNavSeparatorKwargs(TypedDict, total=False):
13
+ # Frame options
14
+ padding: Any
15
+ width: int
16
+ height: int
17
+
18
+
19
+ class SideNavSeparator(Frame):
20
+ """A visual separator for grouping items in a SideNav.
21
+
22
+ SideNavSeparator provides a horizontal line to visually separate
23
+ groups of navigation items. It is a thin wrapper around the Separator
24
+ primitive with appropriate padding for navigation contexts.
25
+
26
+ Example:
27
+ ```python
28
+ nav.add_item('home', text='Home', icon='house')
29
+ nav.add_item('documents', text='Documents', icon='folder')
30
+ nav.add_separator() # Creates SideNavSeparator
31
+ nav.add_item('settings', text='Settings', icon='gear')
32
+ ```
33
+ """
34
+
35
+ DEFAULT_PADDING = (0, 4, 0, 4)
36
+
37
+ def __init__(self, master: Master = None, **kwargs: Unpack[SideNavSeparatorKwargs]):
38
+ """Initialize a SideNavSeparator.
39
+
40
+ Args:
41
+ master (Master | None): Parent widget.
42
+ **kwargs: Additional arguments passed to Frame.
43
+ """
44
+ # Default padding for visual separation
45
+ kwargs.setdefault('padding', self.DEFAULT_PADDING)
46
+
47
+ super().__init__(master, **kwargs)
48
+
49
+ # Create horizontal separator
50
+ self._separator = Separator(self, orient='horizontal')
51
+ self._separator.pack(fill='x')