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,404 @@
1
+ import tkinter as tk
2
+ from tkinter import Misc
3
+ from types import SimpleNamespace
4
+ from typing import Any, Literal, Optional, Union
5
+
6
+ from bootstack.constants import *
7
+ from bootstack.runtime.toplevel import Toplevel
8
+ from bootstack.runtime.utility import scale_size
9
+ from bootstack.runtime.window_utilities import WindowPositioning, AnchorPoint
10
+ from bootstack.widgets.primitives import Button, Frame, Label
11
+
12
+ ttk = SimpleNamespace(
13
+ Button=Button,
14
+ Frame=Frame,
15
+ Label=Label,
16
+ window=SimpleNamespace(Toplevel=Toplevel),
17
+ )
18
+
19
+
20
+ class ToolTip:
21
+ # Position offset from mouse pointer
22
+ _MOUSE_OFFSET_X = 25
23
+ _MOUSE_OFFSET_Y = 10
24
+
25
+ # Spacing between tooltip and widget when anchored
26
+ _WIDGET_SPACING = 1
27
+
28
+ # Fallback dimensions for tooltip sizing
29
+ _FALLBACK_WIDTH = 200
30
+ _FALLBACK_HEIGHT = 50
31
+
32
+ def __init__(
33
+ self,
34
+ widget: Misc,
35
+ text: str = "widget info",
36
+ padding: int = 10,
37
+ justify: Literal["left", "center", "right"] = "left",
38
+ accent: Optional[str] = None,
39
+ wraplength: Optional[int] = None,
40
+ delay: int = 250, # milliseconds
41
+ image: Any = None,
42
+ anchor_point: Optional[AnchorPoint] = None,
43
+ window_point: Optional[AnchorPoint] = None,
44
+ auto_flip: Union[bool, Literal['vertical', 'horizontal']] = True,
45
+ **kwargs: Any,
46
+ ) -> None:
47
+ """Initialize a ToolTip instance for the specified widget.
48
+
49
+ Creates a tooltip that appears after a configurable delay when the mouse
50
+ enters the widget and disappears when the mouse leaves or on button press.
51
+ The tooltip can either follow the mouse pointer or be anchored to a specific
52
+ position relative to the widget.
53
+
54
+ The tooltip window is created with semi-transparency (alpha=0.95 by default)
55
+ and uses the Bootstrap styling system for consistent theming. Text automatically
56
+ wraps based on the specified wraplength, and optional images can be displayed
57
+ alongside the text.
58
+
59
+ Args:
60
+ widget: The tkinter widget to attach this tooltip to. The tooltip will
61
+ appear when hovering over this widget.
62
+ text: The text content to display in the tooltip. Supports multi-line
63
+ text that will wrap according to wraplength. Defaults to "widget info".
64
+ padding: The internal padding in pixels between the tooltip text and the
65
+ tooltip border. Defaults to 10.
66
+ justify: Text alignment within the tooltip. Valid options are "left",
67
+ "center", or "right". Defaults to "left".
68
+ accent: Accent token for the tooltip frame (e.g., "danger", "info").
69
+ If None, uses default elevated background styling.
70
+ bootstyle: DEPRECATED - Use `accent` instead. Bootstrap style(s) to apply
71
+ to the tooltip frame.
72
+ wraplength: Maximum width in screen units before text wraps to a new line.
73
+ If None, defaults to a scaled value of 300 based on the widget's display.
74
+ delay: Time in milliseconds to wait before showing the tooltip after mouse
75
+ enters the widget. Defaults to 250ms.
76
+ image: Optional image to display in the tooltip below the text. Should be
77
+ a PhotoImage or compatible tkinter image object.
78
+ anchor_point: Point on the widget to anchor to (n, s, e, w, ne, nw, se, sw, center).
79
+ If None, tooltip follows the mouse pointer.
80
+ window_point: Point on the tooltip window to align with anchor_point
81
+ (n, s, e, w, ne, nw, se, sw, center). If None, auto-defaults to the
82
+ opposite of anchor_point for natural positioning.
83
+ auto_flip: Smart positioning to keep tooltip on screen. Defaults to True.
84
+ - False: No flipping
85
+ - True: Flip both vertically and horizontally as needed
86
+ - 'vertical': Only flip up/down
87
+ - 'horizontal': Only flip left/right
88
+ **kwargs: Additional keyword arguments passed to the Toplevel window
89
+ constructor. Common options include alpha, topmost, etc. The arguments
90
+ overrideredirect, master, and windowtype are set automatically.
91
+ """
92
+ # Configuration
93
+ self._widget = widget
94
+ self._text = text
95
+ self._padding = padding
96
+ self._justify = justify
97
+ self._accent = accent
98
+ self._wraplength = wraplength if wraplength is not None else scale_size(self._widget, 300)
99
+ self._delay = delay
100
+ self._image = image
101
+ self._anchor_point = anchor_point
102
+ self._window_point = window_point
103
+ self._auto_flip = auto_flip
104
+
105
+ self._toplevel = None
106
+ self._id = None
107
+
108
+ # Set keyword arguments (create copy to avoid mutating caller's dict)
109
+ self.toplevel_kwargs = kwargs.copy()
110
+ self.toplevel_kwargs["overrideredirect"] = True
111
+ self.toplevel_kwargs["master"] = self._widget
112
+ self.toplevel_kwargs["windowtype"] = "tooltip"
113
+ if "alpha" not in self.toplevel_kwargs:
114
+ self.toplevel_kwargs["alpha"] = 0.95
115
+
116
+ # event binding
117
+ self._widget.bind("<Enter>", self._on_enter)
118
+ self._widget.bind("<Leave>", self._on_leave)
119
+ self._widget.bind("<Motion>", self._move_tip)
120
+ self._widget.bind("<ButtonPress>", self._on_leave)
121
+
122
+ def destroy(self) -> None:
123
+ """Cleanup tooltip resources and unbind all event handlers.
124
+
125
+ This method should be called when the tooltip is no longer needed to prevent
126
+ memory leaks. It cancels any pending tooltip display, hides any visible tooltip,
127
+ and removes all event bindings from the widget.
128
+ """
129
+ self._unschedule()
130
+ self._hide_tip()
131
+ self._widget.unbind("<Enter>")
132
+ self._widget.unbind("<Leave>")
133
+ self._widget.unbind("<Motion>")
134
+ self._widget.unbind("<ButtonPress>")
135
+
136
+ def _on_enter(self, _) -> None:
137
+ """Handle mouse enter event by scheduling tooltip display."""
138
+ self._schedule()
139
+
140
+ def _on_leave(self, _) -> None:
141
+ """Handle mouse leave event by canceling and hiding tooltip."""
142
+ self._unschedule()
143
+ self._hide_tip()
144
+
145
+ def _schedule(self) -> None:
146
+ """Schedule the tooltip to appear after the configured delay."""
147
+ self._unschedule()
148
+ self._id = self._widget.after(self._delay, self._show_tip)
149
+
150
+ def _unschedule(self) -> None:
151
+ """Cancel any pending scheduled tooltip display."""
152
+ _id = self._id
153
+ self._id = None
154
+ if _id:
155
+ self._widget.after_cancel(_id)
156
+
157
+ def _show_tip(self, *_: Any) -> None:
158
+ """Create and display the tooltip window at the appropriate position."""
159
+ if self._toplevel:
160
+ return
161
+
162
+ # Check if widget still exists before showing tooltip
163
+ try:
164
+ if not self._widget.winfo_exists():
165
+ return
166
+ except tk.TclError:
167
+ return
168
+
169
+ # Create the tooltip window (position will be set after content is built)
170
+ self._toplevel = Toplevel(**self.toplevel_kwargs)
171
+ # Use accent with tooltip variant
172
+ accent = 'background[+1]' if self._accent is None else self._accent
173
+ frame = ttk.Frame(
174
+ self._toplevel,
175
+ accent=accent,
176
+ variant='tooltip',
177
+ padding=self._padding
178
+ )
179
+ frame.pack(fill=BOTH, expand=YES)
180
+
181
+ lbl = ttk.Label(
182
+ master=frame,
183
+ text=self._text,
184
+ image=self._image,
185
+ compound='bottom',
186
+ justify=self._justify,
187
+ font="caption",
188
+ wraplength=self._wraplength,
189
+ )
190
+ lbl.pack(fill=BOTH, expand=YES)
191
+
192
+ # Wait until size is known, then position
193
+ self._toplevel.update_idletasks()
194
+
195
+ if self._anchor_point:
196
+ # Use WindowPositioning for anchored tooltips (sets geometry directly)
197
+ self._position_anchored()
198
+ else:
199
+ # Mouse-following tooltip
200
+ x, y = self._get_mouse_position()
201
+ self._toplevel.geometry(f"+{x}+{y}")
202
+
203
+ # Ensure the tooltip is visible
204
+ self._toplevel.deiconify()
205
+
206
+ def _move_tip(self, *_: Any) -> None:
207
+ """Update the tooltip position based on mouse or anchor position."""
208
+ if self._toplevel:
209
+ if self._anchor_point:
210
+ # Anchored tooltips don't move
211
+ pass
212
+ else:
213
+ # Update mouse-following tooltip
214
+ x, y = self._get_mouse_position()
215
+ self._toplevel.geometry(f"+{x}+{y}")
216
+
217
+ def _hide_tip(self, *_: Any) -> None:
218
+ """Hide and destroy the tooltip window."""
219
+ if self._toplevel:
220
+ self._toplevel.destroy()
221
+ self._toplevel = None
222
+
223
+ def _get_mouse_position(self) -> tuple[int, int]:
224
+ """Get tooltip position offset from the current mouse pointer.
225
+
226
+ Uses WindowPositioning to ensure the tooltip stays on screen.
227
+
228
+ Returns:
229
+ Tuple of (x, y) screen coordinates for the tooltip.
230
+ """
231
+ x = self._widget.winfo_pointerx() + self._MOUSE_OFFSET_X
232
+ y = self._widget.winfo_pointery() + self._MOUSE_OFFSET_Y
233
+
234
+ # Ensure tooltip stays on screen (no titlebar since overrideredirect=True)
235
+ if self._toplevel:
236
+ x, y = WindowPositioning.ensure_on_screen(
237
+ self._toplevel, x, y, padding=5, titlebar_height=0
238
+ )
239
+
240
+ return x, y
241
+
242
+ def _position_anchored(self) -> None:
243
+ """Position tooltip using WindowPositioning for intelligent anchor-based positioning.
244
+
245
+ Uses anchor_point and window_point attributes and applies auto-flip
246
+ to keep tooltip on screen.
247
+ """
248
+ if not self._toplevel or not self._anchor_point:
249
+ return
250
+
251
+ # Ensure the widget is fully laid out before calculating position
252
+ self._widget.update_idletasks()
253
+
254
+ # Default window_point based on anchor_point if not specified
255
+ window_point = self._window_point
256
+ if window_point is None:
257
+ # Auto-determine opposite anchor point for natural positioning
258
+ opposite = {
259
+ 'n': 's', 's': 'n', 'e': 'w', 'w': 'e',
260
+ 'ne': 'sw', 'nw': 'se', 'se': 'nw', 'sw': 'ne',
261
+ 'center': 'center'
262
+ }
263
+ window_point = opposite.get(self._anchor_point, 's')
264
+
265
+ # Get widget dimensions using max of requested and actual size
266
+ widget_x = self._widget.winfo_rootx()
267
+ widget_y = self._widget.winfo_rooty()
268
+ widget_w = max(self._widget.winfo_reqwidth(), self._widget.winfo_width())
269
+ widget_h = max(self._widget.winfo_reqheight(), self._widget.winfo_height())
270
+
271
+ # Calculate anchor coordinates based on anchor_point
272
+ if self._anchor_point == 'nw':
273
+ anchor_x, anchor_y = widget_x, widget_y
274
+ elif self._anchor_point == 'n':
275
+ anchor_x, anchor_y = widget_x + widget_w // 2, widget_y
276
+ elif self._anchor_point == 'ne':
277
+ anchor_x, anchor_y = widget_x + widget_w, widget_y
278
+ elif self._anchor_point == 'w':
279
+ anchor_x, anchor_y = widget_x, widget_y + widget_h // 2
280
+ elif self._anchor_point == 'center':
281
+ anchor_x, anchor_y = widget_x + widget_w // 2, widget_y + widget_h // 2
282
+ elif self._anchor_point == 'e':
283
+ anchor_x, anchor_y = widget_x + widget_w, widget_y + widget_h // 2
284
+ elif self._anchor_point == 'sw':
285
+ anchor_x, anchor_y = widget_x, widget_y + widget_h
286
+ elif self._anchor_point == 's':
287
+ anchor_x, anchor_y = widget_x + widget_w // 2, widget_y + widget_h
288
+ elif self._anchor_point == 'se':
289
+ anchor_x, anchor_y = widget_x + widget_w, widget_y + widget_h
290
+ else:
291
+ anchor_x, anchor_y = widget_x, widget_y
292
+
293
+ # Calculate window offset based on window_point
294
+ w_width = max(self._toplevel.winfo_reqwidth(), self._toplevel.winfo_width())
295
+ w_height = max(self._toplevel.winfo_reqheight(), self._toplevel.winfo_height())
296
+
297
+ x_offset, y_offset = 0, 0
298
+ if window_point == 'nw':
299
+ x_offset, y_offset = 0, 0
300
+ elif window_point == 'n':
301
+ x_offset, y_offset = -w_width // 2, 0
302
+ elif window_point == 'ne':
303
+ x_offset, y_offset = -w_width, 0
304
+ elif window_point == 'w':
305
+ x_offset, y_offset = 0, -w_height // 2
306
+ elif window_point == 'center':
307
+ x_offset, y_offset = -w_width // 2, -w_height // 2
308
+ elif window_point == 'e':
309
+ x_offset, y_offset = -w_width, -w_height // 2
310
+ elif window_point == 'sw':
311
+ x_offset, y_offset = 0, -w_height
312
+ elif window_point == 's':
313
+ x_offset, y_offset = -w_width // 2, -w_height
314
+ elif window_point == 'se':
315
+ x_offset, y_offset = -w_width, -w_height
316
+
317
+ # Calculate position with offset
318
+ x = int(anchor_x + x_offset + self._WIDGET_SPACING)
319
+ y = int(anchor_y + y_offset + self._WIDGET_SPACING)
320
+
321
+ # Auto-flip logic
322
+ if self._auto_flip:
323
+ vertical_offscreen, horizontal_offscreen = WindowPositioning._check_offscreen(
324
+ self._toplevel, x, y, padding=5
325
+ )
326
+
327
+ should_flip_vertical = False
328
+ should_flip_horizontal = False
329
+
330
+ if self._auto_flip is True or self._auto_flip == 'vertical':
331
+ should_flip_vertical = vertical_offscreen
332
+
333
+ if self._auto_flip is True or self._auto_flip == 'horizontal':
334
+ should_flip_horizontal = horizontal_offscreen
335
+
336
+ # Flip if needed
337
+ if should_flip_vertical or should_flip_horizontal:
338
+ flipped_anchor_point = self._anchor_point
339
+ flipped_window_point = window_point
340
+
341
+ if should_flip_vertical:
342
+ flipped_anchor_point = WindowPositioning._flip_anchor_vertical(flipped_anchor_point)
343
+ flipped_window_point = WindowPositioning._flip_anchor_vertical(flipped_window_point)
344
+
345
+ if should_flip_horizontal:
346
+ flipped_anchor_point = WindowPositioning._flip_anchor_horizontal(flipped_anchor_point)
347
+ flipped_window_point = WindowPositioning._flip_anchor_horizontal(flipped_window_point)
348
+
349
+ # Recalculate anchor coordinates with flipped anchor point
350
+ if flipped_anchor_point == 'nw':
351
+ anchor_x, anchor_y = widget_x, widget_y
352
+ elif flipped_anchor_point == 'n':
353
+ anchor_x, anchor_y = widget_x + widget_w // 2, widget_y
354
+ elif flipped_anchor_point == 'ne':
355
+ anchor_x, anchor_y = widget_x + widget_w, widget_y
356
+ elif flipped_anchor_point == 'w':
357
+ anchor_x, anchor_y = widget_x, widget_y + widget_h // 2
358
+ elif flipped_anchor_point == 'center':
359
+ anchor_x, anchor_y = widget_x + widget_w // 2, widget_y + widget_h // 2
360
+ elif flipped_anchor_point == 'e':
361
+ anchor_x, anchor_y = widget_x + widget_w, widget_y + widget_h // 2
362
+ elif flipped_anchor_point == 'sw':
363
+ anchor_x, anchor_y = widget_x, widget_y + widget_h
364
+ elif flipped_anchor_point == 's':
365
+ anchor_x, anchor_y = widget_x + widget_w // 2, widget_y + widget_h
366
+ elif flipped_anchor_point == 'se':
367
+ anchor_x, anchor_y = widget_x + widget_w, widget_y + widget_h
368
+ else:
369
+ anchor_x, anchor_y = widget_x, widget_y
370
+
371
+ # Recalculate window offset with flipped window point
372
+ if flipped_window_point == 'nw':
373
+ x_offset, y_offset = 0, 0
374
+ elif flipped_window_point == 'n':
375
+ x_offset, y_offset = -w_width // 2, 0
376
+ elif flipped_window_point == 'ne':
377
+ x_offset, y_offset = -w_width, 0
378
+ elif flipped_window_point == 'w':
379
+ x_offset, y_offset = 0, -w_height // 2
380
+ elif flipped_window_point == 'center':
381
+ x_offset, y_offset = -w_width // 2, -w_height // 2
382
+ elif flipped_window_point == 'e':
383
+ x_offset, y_offset = -w_width, -w_height // 2
384
+ elif flipped_window_point == 'sw':
385
+ x_offset, y_offset = 0, -w_height
386
+ elif flipped_window_point == 's':
387
+ x_offset, y_offset = -w_width // 2, -w_height
388
+ elif flipped_window_point == 'se':
389
+ x_offset, y_offset = -w_width, -w_height
390
+
391
+ # Recalculate position with flipped anchors
392
+ x = int(anchor_x + x_offset + self._WIDGET_SPACING)
393
+ y = int(anchor_y + y_offset + self._WIDGET_SPACING)
394
+
395
+ # Ensure on screen (final safety check)
396
+ try:
397
+ x, y = WindowPositioning.ensure_on_screen(
398
+ self._toplevel, x, y, padding=5, titlebar_height=0
399
+ )
400
+ except Exception:
401
+ pass
402
+
403
+ # Set geometry
404
+ self._toplevel.geometry(f"+{x}+{y}")
File without changes