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,345 @@
1
+ """Numeric entry widget with manual stepping and validation.
2
+
3
+ This module provides a number entry widget that extends TextEntryPart with
4
+ numeric-specific features like min/max bounds, stepping, and keyboard/mouse
5
+ wheel support.
6
+ """
7
+
8
+ from typing import Union
9
+
10
+ from bootstack.widgets.mixins.configure_mixin import configure_delegate
11
+ from bootstack.widgets.parts.textentry_part import TextEntryPart
12
+
13
+
14
+ class NumberEntryPart(TextEntryPart):
15
+ """Numeric entry widget with stepping and bounds validation.
16
+
17
+ Extends TextEntryPart to provide numeric input with constraints and
18
+ stepping functionality. Supports min/max bounds, increment/decrement
19
+ via keyboard and mouse wheel, and optional wrapping.
20
+
21
+ !!! note "Events"
22
+ - `<<Increment>>`: Fired when an increment is requested (before step occurs). `event.data = {'value': current_value}`
23
+ - `<<Decrement>>`: Fired when a decrement is requested (before step occurs). `event.data = {'value': current_value}`
24
+ - Plus all events from TextEntryPart: `<<Input>>`, `<<Change>>`, `<Return>`
25
+ """
26
+
27
+ def __init__(
28
+ self,
29
+ master=None,
30
+ *,
31
+ value: Union[int, float, str] = 0,
32
+ value_format: str = None,
33
+ minvalue: Union[int, float, None] = None,
34
+ maxvalue: Union[int, float, None] = None,
35
+ increment: Union[int, float] = 1,
36
+ wrap: bool = False,
37
+ initial_focus: bool = False,
38
+ allow_blank: bool = True,
39
+ **kwargs
40
+ ):
41
+ """Initialize a NumberEntryPart widget.
42
+
43
+ Args:
44
+ master: Parent widget
45
+ value: Initial numeric value (int, float, string, or None)
46
+ value_format: Number format specification for IntlFormatter.
47
+ Examples: 'decimal', 'percent', 'currency', '#,##0.00', etc.
48
+ minvalue: Minimum allowed value (inclusive), or None for no lower bound
49
+ maxvalue: Maximum allowed value (inclusive), or None for no upper bound
50
+ increment: Step size for increment/decrement operations
51
+ wrap: If True, values wrap around at min/max boundaries.
52
+ If False, values are clamped at boundaries.
53
+ initial_focus: If True, widget receives focus on creation
54
+ allow_blank: If True, empty input is allowed (sets value to None)
55
+ locale: Locale identifier for number formatting (e.g., 'en_US')
56
+ **kwargs: Additional keyword arguments passed to TextEntryPart
57
+ """
58
+ # Store numeric configuration
59
+ self._minvalue = minvalue
60
+ self._maxvalue = maxvalue
61
+ self._increment = increment
62
+ self._wrap = wrap
63
+
64
+ # Determine numeric type (float if any parameter is float)
65
+ def _has_fractional(x: Union[int, float, None]) -> bool:
66
+ if x is None:
67
+ return False
68
+ if isinstance(x, float):
69
+ return True
70
+ if isinstance(x, (int, float)) and float(x) != int(x):
71
+ return True
72
+ return False
73
+
74
+ self._num_type = float if any(
75
+ _has_fractional(x) for x in (
76
+ minvalue, maxvalue, increment,
77
+ value if not isinstance(value, str) else 0
78
+ )
79
+ ) else int
80
+
81
+ # Initialize base TextEntryPart
82
+ # Convert initial value to appropriate type
83
+ if isinstance(value, str):
84
+ initial_value = value
85
+ else:
86
+ initial_value = None if value is None else self._num_type(value)
87
+
88
+ super().__init__(
89
+ master=master,
90
+ value=initial_value,
91
+ value_format=value_format,
92
+ initial_focus=initial_focus,
93
+ allow_blank=allow_blank,
94
+ **kwargs
95
+ )
96
+
97
+ # Apply bounds to initial value
98
+ if self._value is not None:
99
+ self._value = self._apply_bounds(float(self._value))
100
+ if self._num_type is int:
101
+ self._value = int(round(self._value))
102
+ # Update display with bounded value
103
+ formatted_text = self._format_value(self._value)
104
+ self.textsignal.set(formatted_text)
105
+ self._prev_changed_value = self._value
106
+
107
+ # Bind keyboard stepping (Up/Down arrows)
108
+ self.bind('<Up>', self._handle_up_key, add=True)
109
+ self.bind('<Down>', self._handle_down_key, add=True)
110
+
111
+ # Bind mouse wheel (Windows/macOS)
112
+ self.bind('<MouseWheel>', self._handle_mouse_wheel, add=True)
113
+
114
+ # Bind mouse wheel (Linux/X11)
115
+ self.bind('<Button-4>', self._handle_wheel_up, add=True)
116
+ self.bind('<Button-5>', self._handle_wheel_down, add=True)
117
+
118
+ # Listen for increment/decrement events to invoke step
119
+ self.bind('<<Increment>>', self._handle_increment_event, add=True)
120
+ self.bind('<<Decrement>>', self._handle_decrement_event, add=True)
121
+
122
+ def _handle_up_key(self, event):
123
+ """Handle Up arrow key press - emit increment event."""
124
+ if not self._is_interactive():
125
+ return 'break'
126
+ self.event_generate('<<Increment>>', data={'value': self._value})
127
+ return 'break' # Prevent default behavior
128
+
129
+ def _handle_down_key(self, event):
130
+ """Handle Down arrow key press - emit decrement event."""
131
+ if not self._is_interactive():
132
+ return 'break'
133
+ self.event_generate('<<Decrement>>', data={'value': self._value})
134
+ return 'break' # Prevent default behavior
135
+
136
+ def _handle_mouse_wheel(self, event):
137
+ """Handle mouse wheel on Windows/macOS."""
138
+ if not self._is_interactive():
139
+ return 'break'
140
+ try:
141
+ delta = int(event.delta)
142
+ except (AttributeError, ValueError):
143
+ delta = 0
144
+
145
+ if delta != 0:
146
+ if delta > 0:
147
+ self.event_generate('<<Increment>>', data={'value': self._value})
148
+ else:
149
+ self.event_generate('<<Decrement>>', data={'value': self._value})
150
+ return 'break'
151
+
152
+ def _handle_wheel_up(self, event):
153
+ """Handle mouse wheel up on Linux/X11."""
154
+ if not self._is_interactive():
155
+ return 'break'
156
+ self.event_generate('<<Increment>>', data={'value': self._value})
157
+ return 'break'
158
+
159
+ def _handle_wheel_down(self, event):
160
+ """Handle mouse wheel down on Linux/X11."""
161
+ if not self._is_interactive():
162
+ return 'break'
163
+ self.event_generate('<<Decrement>>', data={'value': self._value})
164
+ return 'break'
165
+
166
+ def _handle_increment_event(self, event):
167
+ """Handle <<Increment>> event by stepping up."""
168
+ if not self._is_interactive():
169
+ return 'break'
170
+ self.step(+1)
171
+
172
+ def _handle_decrement_event(self, event):
173
+ """Handle <<Decrement>> event by stepping down."""
174
+ if not self._is_interactive():
175
+ return 'break'
176
+ self.step(-1)
177
+
178
+ def _apply_bounds(self, x: float) -> float:
179
+ """Apply min/max bounds with optional wrapping."""
180
+ lo = float(self._minvalue) if self._minvalue is not None else None
181
+ hi = float(self._maxvalue) if self._maxvalue is not None else None
182
+
183
+ if self._wrap and lo is not None and hi is not None:
184
+ if hi <= lo:
185
+ return lo
186
+
187
+ span = hi - lo
188
+ while x < lo:
189
+ x += span
190
+ while x > hi:
191
+ x -= span
192
+ return x
193
+
194
+ if lo is not None and x < lo:
195
+ x = lo
196
+ if hi is not None and x > hi:
197
+ x = hi
198
+
199
+ return x
200
+
201
+ def _is_interactive(self) -> bool:
202
+ """Return True if the widget is not readonly or disabled."""
203
+ current_states = self.state()
204
+ return 'disabled' not in current_states and 'readonly' not in current_states
205
+
206
+ def step(self, n: int = 1):
207
+ """Increment or decrement value by n steps."""
208
+ if not self._is_interactive():
209
+ return self
210
+ # Get current value (default to min if None)
211
+ current = self._value
212
+ if current is None:
213
+ base = float(self._minvalue) if self._minvalue is not None else 0.0
214
+ else:
215
+ base = float(current)
216
+
217
+ # Calculate new value
218
+ new_value = base + float(self._increment) * float(n)
219
+
220
+ # Apply bounds/wrapping
221
+ new_value = self._apply_bounds(new_value)
222
+
223
+ # Coerce to desired type
224
+ if self._num_type is float:
225
+ coerced = float(new_value)
226
+ else:
227
+ coerced = int(round(new_value))
228
+
229
+ # Store previous value for change detection
230
+ prev_value = self._value
231
+
232
+ # Update internal value
233
+ self._value = coerced
234
+
235
+ # Update display
236
+ self._normalize_display_from_value()
237
+
238
+ # Emit changed event if value actually changed
239
+ if self._value != prev_value:
240
+ self._prev_changed_value = self._value
241
+ self.event_generate(
242
+ '<<Change>>', data={
243
+ "value": self._value,
244
+ "prev_value": prev_value,
245
+ "text": self.textsignal.get()
246
+ })
247
+
248
+ return self
249
+
250
+ def _normalize_display_from_value(self):
251
+ """Update display text from internal value without triggering input events."""
252
+ # Format the value
253
+ new_text = self._format_value(self._value)
254
+
255
+ # Only update if text changed
256
+ if new_text != self.textsignal.get():
257
+ # Temporarily unsubscribe from input signal to avoid spurious events
258
+ fid = getattr(self, '_on_input_fid', None)
259
+ if fid:
260
+ try:
261
+ self.textsignal.unsubscribe(fid)
262
+ except Exception:
263
+ pass
264
+
265
+ # Update display
266
+ self.textsignal.set(new_text)
267
+
268
+ # Re-subscribe to input signal
269
+ if fid:
270
+ self._on_input_fid = self.textsignal.subscribe(self._handle_change)
271
+
272
+ def commit(self):
273
+ """Override commit to apply bounds validation after parsing.
274
+
275
+ This ensures user-entered values are constrained to valid range.
276
+ """
277
+ # Call parent commit to parse and format
278
+ super().commit()
279
+
280
+ # Apply bounds to the parsed value
281
+ if self._value is not None:
282
+ bounded_value = self._apply_bounds(float(self._value))
283
+
284
+ # Coerce to appropriate type
285
+ if self._num_type is float:
286
+ self._value = float(bounded_value)
287
+ else:
288
+ self._value = int(round(bounded_value))
289
+
290
+ # Update display if value changed due to bounds
291
+ self._normalize_display_from_value()
292
+
293
+ def on_increment(self, callback) -> str:
294
+ """Bind to `<<Increment>>`. Callback receives `event.data = {'value': current_value}`."""
295
+ return self.bind('<<Increment>>', callback, add=True)
296
+
297
+ def off_increment(self, bind_id: str | None = None) -> None:
298
+ """Unbind from `<<Increment>>`."""
299
+ self.unbind('<<Increment>>', bind_id)
300
+
301
+ def on_decrement(self, callback) -> str:
302
+ """Bind to `<<Decrement>>`. Callback receives `event.data = {'value': current_value}`."""
303
+ return self.bind('<<Decrement>>', callback, add=True)
304
+
305
+ def off_decrement(self, bind_id: str | None = None) -> None:
306
+ """Unbind from `<<Decrement>>`."""
307
+ self.unbind('<<Decrement>>', bind_id)
308
+
309
+ @configure_delegate('minvalue')
310
+ def _delegate_minvalue(self, value: Union[int, float]):
311
+ """Get or set the minimum allowed value and re-validate current value."""
312
+ if value is None:
313
+ return self._minvalue
314
+
315
+ self._minvalue = value
316
+ if self._value is not None:
317
+ self._value = self._apply_bounds(float(self._value))
318
+ self._normalize_display_from_value()
319
+
320
+ @configure_delegate('maxvalue')
321
+ def _delegate_maxvalue(self, value: Union[int, float]):
322
+ """Get or set the maximum allowed value and re-validate current value."""
323
+ if value is None:
324
+ return self._maxvalue
325
+
326
+ self._maxvalue = value
327
+ if self._value is not None:
328
+ self._value = self._apply_bounds(float(self._value))
329
+ self._normalize_display_from_value()
330
+
331
+ @configure_delegate('increment')
332
+ def _delegate_increment(self, value: Union[int, float]):
333
+ """Get or set the step increment value."""
334
+ if value is None:
335
+ return self._increment
336
+
337
+ self._increment = value
338
+
339
+ @configure_delegate('wrap')
340
+ def _delegate_wrap(self, value: bool):
341
+ """Get or set the wrap setting."""
342
+ if value is None:
343
+ return self._wrap
344
+
345
+ self._wrap = bool(value)