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,169 @@
1
+ """Type definitions and configuration normalizers for TableView widget."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+ from typing_extensions import Literal, TypedDict
7
+
8
+
9
+ class EditingOptions(TypedDict, total=False):
10
+ """Configure add/update/delete support and form dialog options."""
11
+ adding: bool
12
+ updating: bool
13
+ deleting: bool
14
+ form: dict[str, Any]
15
+
16
+
17
+ class SelectionOptions(TypedDict, total=False):
18
+ """Control selection mode (single/multi/none) and select-all allowance."""
19
+ mode: Literal['single', 'multi', 'none']
20
+ allow_select_all: bool
21
+
22
+
23
+ class ExportingOptions(TypedDict, total=False):
24
+ """Configure export availability and formats."""
25
+ enabled: bool
26
+ allow_export_selection: bool
27
+ export_scope: Literal['page', 'all']
28
+ formats: tuple[str, ...]
29
+
30
+
31
+ class PagingOptions(TypedDict, total=False):
32
+ """Paging mode and sizing; toggles x/y scrollbars."""
33
+ mode: Literal['standard', 'virtual']
34
+ page_size: int
35
+ page_index: int
36
+ cache_size: int
37
+ xscroll: bool
38
+ yscroll: bool
39
+
40
+
41
+ class RowAlternationOptions(TypedDict, total=False):
42
+ """Alternating row striping (enabled flag and accent token)."""
43
+ enabled: bool
44
+ accent: str
45
+
46
+
47
+ class FilteringOptions(TypedDict, total=False):
48
+ """Toggle filtering and which menus expose filter actions."""
49
+ enabled: bool
50
+ header_menu_filtering: bool
51
+ row_menu_filtering: bool
52
+
53
+
54
+ class SearchOptions(TypedDict, total=False):
55
+ """Configure searchbar visibility, advanced mode, and trigger timing."""
56
+ enabled: bool
57
+ mode: Literal['standard', 'advanced']
58
+ event: Literal['input', 'enter']
59
+
60
+
61
+ # ------ Helper methods --------
62
+
63
+ def parse_selection_mode(mode: str):
64
+ """Convert TableView selection mode to Treeview selectmode."""
65
+ if mode == 'single':
66
+ return 'browse'
67
+ elif mode == 'multi':
68
+ return 'extended'
69
+ else:
70
+ return 'none'
71
+
72
+
73
+ # ------ Build internal dicts from flattened kwargs --------
74
+
75
+ def build_editing_options(
76
+ enable_adding: bool = False,
77
+ enable_editing: bool = False,
78
+ enable_deleting: bool = False,
79
+ form_options: dict | None = None,
80
+ ) -> EditingOptions:
81
+ """Build editing options dict from flattened kwargs."""
82
+ return dict(
83
+ adding=enable_adding,
84
+ updating=enable_editing,
85
+ deleting=enable_deleting,
86
+ form=form_options or {}
87
+ )
88
+
89
+
90
+ def build_selection_options(
91
+ selection_mode: Literal['none', 'single', 'multi'] = 'single',
92
+ allow_select_all: bool = True,
93
+ ) -> SelectionOptions:
94
+ """Build selection options dict from flattened kwargs."""
95
+ return dict(
96
+ mode=selection_mode,
97
+ allow_select_all=allow_select_all,
98
+ )
99
+
100
+
101
+ def build_filtering_options(
102
+ enable_filtering: bool = True,
103
+ enable_header_filtering: bool = True,
104
+ enable_row_filtering: bool = True,
105
+ ) -> FilteringOptions:
106
+ """Build filtering options dict from flattened kwargs."""
107
+ return dict(
108
+ enabled=enable_filtering,
109
+ header_menu_filtering=enable_header_filtering,
110
+ row_menu_filtering=enable_row_filtering,
111
+ )
112
+
113
+
114
+ def build_exporting_options(
115
+ enable_exporting: bool = False,
116
+ allow_export_selection: bool = True,
117
+ export_scope: Literal['page', 'all'] = 'page',
118
+ export_formats: tuple[str, ...] | None = None,
119
+ ) -> ExportingOptions:
120
+ """Build exporting options dict from flattened kwargs."""
121
+ return dict(
122
+ enabled=enable_exporting,
123
+ allow_export_selection=allow_export_selection,
124
+ export_scope=export_scope,
125
+ formats=export_formats or ('csv',)
126
+ )
127
+
128
+
129
+ def build_paging_options(
130
+ paging_mode: Literal['standard', 'virtual'] = 'standard',
131
+ page_size: int = 25,
132
+ page_index: int = 0,
133
+ page_cache_size: int = 3,
134
+ show_vscrollbar: bool = True,
135
+ show_hscrollbar: bool = False,
136
+ ) -> PagingOptions:
137
+ """Build paging options dict from flattened kwargs."""
138
+ return dict(
139
+ mode=paging_mode,
140
+ page_size=page_size,
141
+ page_index=page_index,
142
+ cache_size=page_cache_size,
143
+ xscroll=show_hscrollbar,
144
+ yscroll=show_vscrollbar,
145
+ )
146
+
147
+
148
+ def build_search_options(
149
+ enable_search: bool = True,
150
+ search_mode: Literal['standard', 'advanced'] = 'standard',
151
+ search_trigger: Literal['enter', 'input'] = 'enter',
152
+ ) -> SearchOptions:
153
+ """Build search options dict from flattened kwargs."""
154
+ return dict(
155
+ enabled=enable_search,
156
+ mode=search_mode,
157
+ event=search_trigger,
158
+ )
159
+
160
+
161
+ def build_row_alternation_options(
162
+ striped: bool = False,
163
+ striped_background: str = 'background[+1]',
164
+ ) -> RowAlternationOptions:
165
+ """Build row alternation options dict from flattened kwargs."""
166
+ return dict(
167
+ enabled=striped,
168
+ accent=striped_background,
169
+ )
@@ -0,0 +1,6 @@
1
+ """Tabs composite widget module."""
2
+
3
+ from .tabs import Tabs
4
+ from .tabview import TabView
5
+
6
+ __all__ = ["Tabs", "TabView"]
@@ -0,0 +1,372 @@
1
+ """TabItem widget - a tab with optional close button."""
2
+ from __future__ import annotations
3
+
4
+ __all__ = ['TabItem']
5
+
6
+ from tkinter import TclError, Variable
7
+ from typing import Any, Callable, Literal, TYPE_CHECKING, Union
8
+
9
+ from bootstack.widgets.composites.compositeframe import CompositeFrame
10
+ from bootstack.widgets.primitives.button import Button
11
+ from bootstack.widgets.primitives.label import Label
12
+ from bootstack.widgets.mixins import configure_delegate
13
+ from bootstack.widgets.types import Master
14
+ from bootstack.core.capabilities.signals import normalize_signal
15
+
16
+ if TYPE_CHECKING:
17
+ from bootstack.core.signals import Signal
18
+
19
+
20
+ class TabItem(CompositeFrame):
21
+ """A tab item widget with optional close button.
22
+
23
+ TabItem extends CompositeFrame to provide a clickable tab with coordinated
24
+ hover/pressed/focus states across all child widgets. It supports selection
25
+ via signal/variable and optional close functionality.
26
+
27
+ !!! note "Events"
28
+ - `<<TabSelect>>`: Fired when the tab is clicked (for selection).
29
+ - `<<TabClose>>`: Fired when the close button is clicked.
30
+
31
+ Attributes:
32
+ selected (bool): Current selection state (read-only).
33
+ value: The value associated with this tab.
34
+ """
35
+
36
+ def __init__(
37
+ self,
38
+ master: Master = None,
39
+ text: str = "",
40
+ icon: str | dict = None,
41
+ compound: Literal['left', 'right', 'top', 'bottom', 'center', 'none'] = 'left',
42
+ value: Any = None,
43
+ variable: Variable = None,
44
+ orient: Literal['horizontal', 'vertical'] = 'horizontal',
45
+ signal: 'Signal[Any]' = None,
46
+ command: Callable = None,
47
+ closable: Union[bool, Literal['hover']] = False,
48
+ close_command: Callable = None,
49
+ variant: Literal['pill', 'bar'] = 'bar',
50
+ **kwargs
51
+ ):
52
+ """Create a TabItem widget.
53
+
54
+ Args:
55
+ master: Parent widget. If None, uses the default root window.
56
+ text: Text to display on the tab.
57
+ icon: Icon to display on the tab (left of text).
58
+ compound: How to position icon relative to text. One of 'left',
59
+ 'right', 'top', 'bottom', 'center', or 'none'. Default is 'left'.
60
+ value: Value to set on signal/variable when this tab is selected.
61
+ variable: Tk variable for selection state (synced with signal).
62
+ orient: Orientation hint for styling ('horizontal' or 'vertical').
63
+ Default is 'horizontal'.
64
+ signal: Reactive Signal for selection state (preferred over variable).
65
+ command: Callback invoked when the tab is selected.
66
+ closable: Close button visibility. True=always visible, False=hidden,
67
+ 'hover'=visible only on hover (space reserved).
68
+ close_command: Callback invoked when close button is clicked.
69
+ variant: Tab style variant ('pill' or 'bar').
70
+ **kwargs: Additional arguments passed to CompositeFrame.
71
+ """
72
+ self._text = text
73
+ self._icon = icon
74
+ self._compound = compound
75
+ self._value = value
76
+ self._command = command
77
+ self._closable = closable
78
+ self._close_command = close_command
79
+ self._variant = variant
80
+ self._orient = orient
81
+ self._accent = None # Will be set from kwargs
82
+
83
+ # Selection state - signal/variable syncing
84
+ self._signal: Signal[Any] | None = None
85
+ self._variable: Variable | None = None
86
+ self._trace_id: str | None = None
87
+
88
+ # Determine ttk_class based on variant
89
+ ttk_class = self._get_ttk_class(variant)
90
+
91
+ # Extract accent for styling
92
+ accent = kwargs.pop('accent', None)
93
+ surface = kwargs.pop('surface', None)
94
+ self._accent = accent # Store for later use
95
+
96
+ # Extract width for label (frame width doesn't work well with propagation)
97
+ self._width = kwargs.pop('width', None)
98
+
99
+ # Extract anchor for label
100
+ self._anchor = kwargs.pop('anchor', 'center')
101
+
102
+ super().__init__(
103
+ master=master,
104
+ ttk_class=ttk_class,
105
+ accent=accent,
106
+ variant=variant,
107
+ takefocus=False,
108
+ style_options={"orient": orient},
109
+ **kwargs
110
+ )
111
+
112
+ # Build internal widgets
113
+ self._label: Label | None = None
114
+ self._close_button: Button | None = None
115
+
116
+ self._build_widget(accent, surface)
117
+
118
+ # Set up signal/variable after widget is built
119
+ if signal is not None:
120
+ self._set_signal_or_variable(signal)
121
+ elif variable is not None:
122
+ self._set_signal_or_variable(variable)
123
+
124
+ # Bind click handler
125
+ self.on_invoked(self._on_tab_click)
126
+
127
+ # Bind destroy handler to clean up variable trace
128
+ self.bind('<Destroy>', self._on_destroy, add='+')
129
+
130
+ def _on_destroy(self, event=None):
131
+ """Clean up variable trace when widget is destroyed."""
132
+ if event.widget is not self:
133
+ return
134
+ if self._variable is not None and self._trace_id is not None:
135
+ try:
136
+ self._variable.trace_remove('write', self._trace_id)
137
+ except Exception:
138
+ pass
139
+ self._trace_id = None
140
+
141
+ def _get_ttk_class(self, variant: str) -> str:
142
+ """Get the ttk class name for the given variant."""
143
+ return 'TabItem.TFrame'
144
+
145
+ def _build_widget(self, accent: str = None, surface: str = None):
146
+ """Build the internal widget structure."""
147
+ style_opts = {}
148
+ if surface:
149
+ style_opts['surface'] = surface
150
+
151
+ # Pass width to label if specified
152
+ label_opts = {}
153
+ if self._width is not None:
154
+ label_opts['width'] = self._width
155
+
156
+ # Main label for text/icon
157
+ self._label = Label(
158
+ self,
159
+ text=self._text,
160
+ icon=self._icon,
161
+ compound=self._compound,
162
+ ttk_class='TabItem.TLabel',
163
+ accent=accent,
164
+ variant=self._variant,
165
+ takefocus=False,
166
+ anchor=self._anchor,
167
+ **style_opts,
168
+ **label_opts
169
+ )
170
+ self.register_composite(self._label)
171
+ self._label.pack(side='left', fill='both', expand=True)
172
+
173
+ # Close button (optional - show when closable is True or 'hover')
174
+ if self._closable:
175
+ self._create_close_button(accent, style_opts)
176
+
177
+ def _create_close_button(self, accent: str = None, style_opts: dict = None):
178
+ """Create the close button widget."""
179
+ style_opts = style_opts or {}
180
+ # Pass closable mode to style builder via style_options
181
+ extra_style_options = {}
182
+ if self._closable == 'hover':
183
+ extra_style_options['closable'] = 'hover'
184
+ self._close_button = Button(
185
+ self,
186
+ icon={'name': 'x-lg', 'size': 14},
187
+ icon_only=True,
188
+ ttk_class='TabItem.TButton',
189
+ accent=accent,
190
+ variant=self._variant, # Use same variant as the tab for matching background
191
+ takefocus=False,
192
+ command=self._on_close_click,
193
+ padding=0,
194
+ anchor='center',
195
+ style_options=extra_style_options,
196
+ **style_opts
197
+ )
198
+ self.register_composite(self._close_button)
199
+ self._close_button.place(relx=1.0, rely=0.5, anchor='e', x=4)
200
+
201
+ def _set_signal_or_variable(self, value: Any):
202
+ """Set up signal/variable binding with trace for selection updates."""
203
+ # Remove old trace if exists
204
+ if self._variable is not None and self._trace_id is not None:
205
+ try:
206
+ self._variable.trace_remove('write', self._trace_id)
207
+ except Exception:
208
+ pass
209
+
210
+ # Normalize to get both signal and variable
211
+ binding = normalize_signal(value)
212
+ if binding is not None:
213
+ self._signal = binding.signal
214
+ self._variable = binding.variable
215
+ else:
216
+ self._variable = value
217
+ self._signal = None
218
+
219
+ # Add trace to update selection state
220
+ if self._variable is not None:
221
+ self._trace_id = self._variable.trace_add('write', self._on_variable_changed)
222
+ # Initial update
223
+ self._update_selection_state()
224
+
225
+ def _on_variable_changed(self, *args):
226
+ """Handle variable changes to update selection state."""
227
+ self._update_selection_state()
228
+
229
+ def _update_selection_state(self):
230
+ """Update visual state based on selection."""
231
+ # Guard against updates after widget destruction
232
+ try:
233
+ if not self.winfo_exists():
234
+ return
235
+ except TclError:
236
+ return
237
+
238
+ if self._variable is not None and self._value is not None:
239
+ is_selected = self._variable.get() == self._value
240
+ self.set_selected(is_selected)
241
+
242
+ def _on_tab_click(self, event=None):
243
+ """Handle tab click - select and invoke command."""
244
+ # Set selection if variable is configured
245
+ if self._variable is not None and self._value is not None:
246
+ self._variable.set(self._value)
247
+
248
+ # Invoke command if provided
249
+ if self._command is not None:
250
+ self._command()
251
+
252
+ # Generate virtual event
253
+ self.event_generate('<<TabSelect>>', data={'value': self._value})
254
+
255
+ def _on_close_click(self):
256
+ """Handle close button click."""
257
+ # Store value before potential destruction
258
+ value = self._value
259
+
260
+ # Generate virtual event BEFORE close_command (which may destroy the widget)
261
+ self.event_generate('<<TabClose>>', data={'value': value})
262
+
263
+ # Invoke close command if provided (this may destroy the widget)
264
+ if self._close_command is not None:
265
+ self._close_command()
266
+
267
+ # --- Public API ---
268
+
269
+ def select(self):
270
+ """Select this tab (set variable to this tab's value)."""
271
+ if self._variable is not None and self._value is not None:
272
+ self._variable.set(self._value)
273
+
274
+ @property
275
+ def value(self) -> Any:
276
+ """Get the value associated with this tab."""
277
+ return self._value
278
+
279
+ @property
280
+ def is_selected(self) -> bool:
281
+ """Check if this tab is currently selected."""
282
+ if self._variable is not None and self._value is not None:
283
+ return self._variable.get() == self._value
284
+ return self.selected
285
+
286
+ # --- Configuration delegates ---
287
+
288
+ @configure_delegate('text')
289
+ def _delegate_text(self, value=None):
290
+ """Get or set the tab text."""
291
+ if value is None:
292
+ return self._text
293
+ self._text = value
294
+ if self._label is not None:
295
+ self._label.configure(text=value)
296
+ return None
297
+
298
+ @configure_delegate('icon')
299
+ def _delegate_icon(self, value=None):
300
+ """Get or set the tab icon."""
301
+ if value is None:
302
+ return self._icon
303
+ self._icon = value
304
+ if self._label is not None:
305
+ self._label.configure(icon=value)
306
+ return None
307
+
308
+ @configure_delegate('compound')
309
+ def _delegate_compound(self, value=None):
310
+ """Get or set the compound (icon position relative to text)."""
311
+ if value is None:
312
+ return self._compound
313
+ self._compound = value
314
+ if self._label is not None:
315
+ self._label.configure(compound=value)
316
+ return None
317
+
318
+ @configure_delegate('value')
319
+ def _delegate_value(self, value=None):
320
+ """Get or set the tab value."""
321
+ if value is None:
322
+ return self._value
323
+ self._value = value
324
+ self._update_selection_state()
325
+ return None
326
+
327
+ @configure_delegate('command')
328
+ def _delegate_command(self, value=None):
329
+ """Get or set the selection command."""
330
+ if value is None:
331
+ return self._command
332
+ self._command = value
333
+ return None
334
+
335
+ @configure_delegate('close_command')
336
+ def _delegate_close_command(self, value=None):
337
+ """Get or set the close command."""
338
+ if value is None:
339
+ return self._close_command
340
+ self._close_command = value
341
+ return None
342
+
343
+ @configure_delegate('closable')
344
+ def _delegate_closable(self, value=None):
345
+ """Get or set close button visibility (True, False, or 'hover')."""
346
+ if value is None:
347
+ return self._closable
348
+ if value != self._closable:
349
+ self._closable = value
350
+ if value and self._close_button is None:
351
+ self._create_close_button(self._accent)
352
+ elif not value and self._close_button is not None:
353
+ self._close_button.place_forget()
354
+ self._close_button.destroy()
355
+ self._close_button = None
356
+ return None
357
+
358
+ @configure_delegate('signal')
359
+ def _delegate_signal(self, value=None):
360
+ """Get or set the signal for selection state."""
361
+ if value is None:
362
+ return self._signal
363
+ self._set_signal_or_variable(value)
364
+ return None
365
+
366
+ @configure_delegate('variable')
367
+ def _delegate_variable(self, value=None):
368
+ """Get or set the variable for selection state."""
369
+ if value is None:
370
+ return self._variable
371
+ self._set_signal_or_variable(value)
372
+ return None