bootstack 0.1.0__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 (471) hide show
  1. bootstack/__init__.py +157 -0
  2. bootstack/__main__.py +5 -0
  3. bootstack/_core/__init__.py +21 -0
  4. bootstack/_core/capabilities/__init__.py +45 -0
  5. bootstack/_core/capabilities/after.py +103 -0
  6. bootstack/_core/capabilities/bind.py +192 -0
  7. bootstack/_core/capabilities/bindtags.py +112 -0
  8. bootstack/_core/capabilities/busy.py +72 -0
  9. bootstack/_core/capabilities/clipboard.py +89 -0
  10. bootstack/_core/capabilities/focus.py +118 -0
  11. bootstack/_core/capabilities/grab.py +65 -0
  12. bootstack/_core/capabilities/grid.py +211 -0
  13. bootstack/_core/capabilities/localization.py +231 -0
  14. bootstack/_core/capabilities/pack.py +140 -0
  15. bootstack/_core/capabilities/place.py +113 -0
  16. bootstack/_core/capabilities/selection.py +136 -0
  17. bootstack/_core/capabilities/signals.py +244 -0
  18. bootstack/_core/capabilities/winfo.py +315 -0
  19. bootstack/_core/colorutils.py +234 -0
  20. bootstack/_core/exceptions.py +25 -0
  21. bootstack/_core/images.py +463 -0
  22. bootstack/_core/mixins/__init__.py +1 -0
  23. bootstack/_core/mixins/ttk_state.py +35 -0
  24. bootstack/_core/mixins/widget.py +132 -0
  25. bootstack/_core/paths.py +49 -0
  26. bootstack/_core/publisher.py +149 -0
  27. bootstack/_core/variables.py +62 -0
  28. bootstack/_runtime/__init__.py +3 -0
  29. bootstack/_runtime/app.py +930 -0
  30. bootstack/_runtime/base_window.py +945 -0
  31. bootstack/_runtime/events.py +399 -0
  32. bootstack/_runtime/shortcuts.py +496 -0
  33. bootstack/_runtime/tk_patch.py +43 -0
  34. bootstack/_runtime/toplevel.py +276 -0
  35. bootstack/_runtime/utility.py +457 -0
  36. bootstack/_runtime/visual_focus.py +240 -0
  37. bootstack/_runtime/window_utilities.py +1123 -0
  38. bootstack/assets/__init__.py +21 -0
  39. bootstack/assets/bootstack.ico +0 -0
  40. bootstack/assets/bootstack.png +0 -0
  41. bootstack/assets/elements/__init__.py +0 -0
  42. bootstack/assets/elements/badge-pill.png +0 -0
  43. bootstack/assets/elements/badge-square.png +0 -0
  44. bootstack/assets/elements/button-compact.png +0 -0
  45. bootstack/assets/elements/button-default.png +0 -0
  46. bootstack/assets/elements/buttongroup-after-h-compact.png +0 -0
  47. bootstack/assets/elements/buttongroup-after-h-default.png +0 -0
  48. bootstack/assets/elements/buttongroup-after-v-compact.png +0 -0
  49. bootstack/assets/elements/buttongroup-after-v-default.png +0 -0
  50. bootstack/assets/elements/buttongroup-before-h-compact.png +0 -0
  51. bootstack/assets/elements/buttongroup-before-h-default.png +0 -0
  52. bootstack/assets/elements/buttongroup-before-v-compact.png +0 -0
  53. bootstack/assets/elements/buttongroup-before-v-default.png +0 -0
  54. bootstack/assets/elements/buttongroup-center-h-compact.png +0 -0
  55. bootstack/assets/elements/buttongroup-center-h-default.png +0 -0
  56. bootstack/assets/elements/buttongroup-center-v-compact.png +0 -0
  57. bootstack/assets/elements/buttongroup-center-v-default.png +0 -0
  58. bootstack/assets/elements/card.png +0 -0
  59. bootstack/assets/elements/checkbox-checked.png +0 -0
  60. bootstack/assets/elements/checkbox-indeterminate.png +0 -0
  61. bootstack/assets/elements/checkbox-unchecked.png +0 -0
  62. bootstack/assets/elements/field.png +0 -0
  63. bootstack/assets/elements/input-addon-compact.png +0 -0
  64. bootstack/assets/elements/input-addon-default.png +0 -0
  65. bootstack/assets/elements/input-compact.png +0 -0
  66. bootstack/assets/elements/input-default.png +0 -0
  67. bootstack/assets/elements/list-item-separated.png +0 -0
  68. bootstack/assets/elements/list-item.png +0 -0
  69. bootstack/assets/elements/listrow-compact.png +0 -0
  70. bootstack/assets/elements/listrow-default.png +0 -0
  71. bootstack/assets/elements/manifest.toml +361 -0
  72. bootstack/assets/elements/menu-item.png +0 -0
  73. bootstack/assets/elements/navitem-compact.png +0 -0
  74. bootstack/assets/elements/navitem-default.png +0 -0
  75. bootstack/assets/elements/progressbar-h-compact.png +0 -0
  76. bootstack/assets/elements/progressbar-h-default.png +0 -0
  77. bootstack/assets/elements/progressbar-v-compact.png +0 -0
  78. bootstack/assets/elements/progressbar-v-default.png +0 -0
  79. bootstack/assets/elements/radiobutton.png +0 -0
  80. bootstack/assets/elements/scrollbar-horizontal.png +0 -0
  81. bootstack/assets/elements/scrollbar-vertical.png +0 -0
  82. bootstack/assets/elements/slider-handle.png +0 -0
  83. bootstack/assets/elements/slider-track-h.png +0 -0
  84. bootstack/assets/elements/slider-track-v.png +0 -0
  85. bootstack/assets/elements/switch-off.png +0 -0
  86. bootstack/assets/elements/switch-on.png +0 -0
  87. bootstack/assets/elements/tab-h.png +0 -0
  88. bootstack/assets/elements/tab-v.png +0 -0
  89. bootstack/assets/icons/bootstrap.ttf +0 -0
  90. bootstack/assets/icons/glyphmap.json +2080 -0
  91. bootstack/assets/icons/icon_metrics.json +12470 -0
  92. bootstack/assets/locales/ar/LC_MESSAGES/bootstack.mo +0 -0
  93. bootstack/assets/locales/ar/LC_MESSAGES/bootstack.po +856 -0
  94. bootstack/assets/locales/bg/LC_MESSAGES/bootstack.mo +0 -0
  95. bootstack/assets/locales/bg/LC_MESSAGES/bootstack.po +878 -0
  96. bootstack/assets/locales/cs/LC_MESSAGES/bootstack.mo +0 -0
  97. bootstack/assets/locales/cs/LC_MESSAGES/bootstack.po +856 -0
  98. bootstack/assets/locales/da/LC_MESSAGES/bootstack.mo +0 -0
  99. bootstack/assets/locales/da/LC_MESSAGES/bootstack.po +856 -0
  100. bootstack/assets/locales/de/LC_MESSAGES/bootstack.mo +0 -0
  101. bootstack/assets/locales/de/LC_MESSAGES/bootstack.po +856 -0
  102. bootstack/assets/locales/en/LC_MESSAGES/bootstack.mo +0 -0
  103. bootstack/assets/locales/en/LC_MESSAGES/bootstack.po +878 -0
  104. bootstack/assets/locales/es/LC_MESSAGES/bootstack.mo +0 -0
  105. bootstack/assets/locales/es/LC_MESSAGES/bootstack.po +856 -0
  106. bootstack/assets/locales/fr/LC_MESSAGES/bootstack.mo +0 -0
  107. bootstack/assets/locales/fr/LC_MESSAGES/bootstack.po +856 -0
  108. bootstack/assets/locales/he/LC_MESSAGES/bootstack.mo +0 -0
  109. bootstack/assets/locales/he/LC_MESSAGES/bootstack.po +854 -0
  110. bootstack/assets/locales/hi/LC_MESSAGES/bootstack.mo +0 -0
  111. bootstack/assets/locales/hi/LC_MESSAGES/bootstack.po +845 -0
  112. bootstack/assets/locales/it/LC_MESSAGES/bootstack.mo +0 -0
  113. bootstack/assets/locales/it/LC_MESSAGES/bootstack.po +844 -0
  114. bootstack/assets/locales/ja/LC_MESSAGES/bootstack.mo +0 -0
  115. bootstack/assets/locales/ja/LC_MESSAGES/bootstack.po +917 -0
  116. bootstack/assets/locales/ko/LC_MESSAGES/bootstack.mo +0 -0
  117. bootstack/assets/locales/ko/LC_MESSAGES/bootstack.po +845 -0
  118. bootstack/assets/locales/nb/LC_MESSAGES/bootstack.mo +0 -0
  119. bootstack/assets/locales/nb/LC_MESSAGES/bootstack.po +844 -0
  120. bootstack/assets/locales/nl/LC_MESSAGES/bootstack.mo +0 -0
  121. bootstack/assets/locales/nl/LC_MESSAGES/bootstack.po +844 -0
  122. bootstack/assets/locales/pl/LC_MESSAGES/bootstack.mo +0 -0
  123. bootstack/assets/locales/pl/LC_MESSAGES/bootstack.po +845 -0
  124. bootstack/assets/locales/pt/LC_MESSAGES/bootstack.mo +0 -0
  125. bootstack/assets/locales/pt/LC_MESSAGES/bootstack.po +845 -0
  126. bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.mo +0 -0
  127. bootstack/assets/locales/pt_BR/LC_MESSAGES/bootstack.po +845 -0
  128. bootstack/assets/locales/sl/LC_MESSAGES/bootstack.mo +0 -0
  129. bootstack/assets/locales/sl/LC_MESSAGES/bootstack.po +845 -0
  130. bootstack/assets/locales/sv/LC_MESSAGES/bootstack.mo +0 -0
  131. bootstack/assets/locales/sv/LC_MESSAGES/bootstack.po +845 -0
  132. bootstack/assets/locales/tr/LC_MESSAGES/bootstack.mo +0 -0
  133. bootstack/assets/locales/tr/LC_MESSAGES/bootstack.po +845 -0
  134. bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.mo +0 -0
  135. bootstack/assets/locales/zh_CN/LC_MESSAGES/bootstack.po +845 -0
  136. bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.mo +0 -0
  137. bootstack/assets/locales/zh_TW/LC_MESSAGES/bootstack.po +845 -0
  138. bootstack/cli/__init__.py +133 -0
  139. bootstack/cli/__main__.py +6 -0
  140. bootstack/cli/add.py +395 -0
  141. bootstack/cli/appicon.py +285 -0
  142. bootstack/cli/build.py +115 -0
  143. bootstack/cli/config.py +313 -0
  144. bootstack/cli/demo.py +564 -0
  145. bootstack/cli/dev.py +153 -0
  146. bootstack/cli/doctor.py +195 -0
  147. bootstack/cli/icons.py +98 -0
  148. bootstack/cli/promote.py +120 -0
  149. bootstack/cli/pyinstaller.py +268 -0
  150. bootstack/cli/run.py +95 -0
  151. bootstack/cli/start.py +117 -0
  152. bootstack/cli/templates/__init__.py +931 -0
  153. bootstack/clipboard.py +48 -0
  154. bootstack/constants.py +318 -0
  155. bootstack/data/README.md +615 -0
  156. bootstack/data/__init__.py +78 -0
  157. bootstack/data/_observable.py +276 -0
  158. bootstack/data/base.py +780 -0
  159. bootstack/data/file_source.py +367 -0
  160. bootstack/data/memory_source.py +450 -0
  161. bootstack/data/query.py +367 -0
  162. bootstack/data/readers.py +289 -0
  163. bootstack/data/sqlite_source.py +869 -0
  164. bootstack/data/types.py +354 -0
  165. bootstack/data/writers.py +232 -0
  166. bootstack/dev/__init__.py +36 -0
  167. bootstack/dev/_capture.py +141 -0
  168. bootstack/dev/_env.py +43 -0
  169. bootstack/dev/_registry.py +140 -0
  170. bootstack/dev/_reloader.py +351 -0
  171. bootstack/dev/_reset.py +50 -0
  172. bootstack/dev/_watcher.py +91 -0
  173. bootstack/dialogs/__init__.py +948 -0
  174. bootstack/dialogs/_impl/__init__.py +47 -0
  175. bootstack/dialogs/_impl/colorchooser.py +588 -0
  176. bootstack/dialogs/_impl/datedialog.py +450 -0
  177. bootstack/dialogs/_impl/dialog.py +594 -0
  178. bootstack/dialogs/_impl/filterdialog.py +358 -0
  179. bootstack/dialogs/_impl/fontdialog.py +364 -0
  180. bootstack/dialogs/_impl/formdialog.py +564 -0
  181. bootstack/dialogs/_impl/message.py +486 -0
  182. bootstack/dialogs/_impl/query.py +570 -0
  183. bootstack/errors.py +67 -0
  184. bootstack/events/__init__.py +111 -0
  185. bootstack/events/_event.py +135 -0
  186. bootstack/events/_payloads.py +539 -0
  187. bootstack/events/_subscription.py +38 -0
  188. bootstack/i18n/README.md +77 -0
  189. bootstack/i18n/__init__.py +23 -0
  190. bootstack/i18n/catalog.py +121 -0
  191. bootstack/i18n/intl_format.py +584 -0
  192. bootstack/i18n/msgcat.py +425 -0
  193. bootstack/i18n/specs.py +156 -0
  194. bootstack/images.py +563 -0
  195. bootstack/py.typed +1 -0
  196. bootstack/scheduling/__init__.py +11 -0
  197. bootstack/scheduling/_schedule.py +218 -0
  198. bootstack/shortcuts.py +21 -0
  199. bootstack/signals/README.md +98 -0
  200. bootstack/signals/__init__.py +10 -0
  201. bootstack/signals/integration.py +100 -0
  202. bootstack/signals/signal.py +353 -0
  203. bootstack/signals/types.py +6 -0
  204. bootstack/store.py +286 -0
  205. bootstack/streams/__init__.py +12 -0
  206. bootstack/streams/_stream.py +321 -0
  207. bootstack/style/__init__.py +38 -0
  208. bootstack/style/builders/__init__.py +51 -0
  209. bootstack/style/builders/badge.py +46 -0
  210. bootstack/style/builders/button.py +339 -0
  211. bootstack/style/builders/buttongroup.py +311 -0
  212. bootstack/style/builders/calendar.py +271 -0
  213. bootstack/style/builders/checkbutton.py +110 -0
  214. bootstack/style/builders/combobox.py +113 -0
  215. bootstack/style/builders/contextmenu.py +268 -0
  216. bootstack/style/builders/entry.py +82 -0
  217. bootstack/style/builders/expander.py +148 -0
  218. bootstack/style/builders/field.py +335 -0
  219. bootstack/style/builders/frame.py +50 -0
  220. bootstack/style/builders/label.py +28 -0
  221. bootstack/style/builders/labelframe.py +34 -0
  222. bootstack/style/builders/listview.py +369 -0
  223. bootstack/style/builders/menubar.py +91 -0
  224. bootstack/style/builders/menubutton.py +359 -0
  225. bootstack/style/builders/panedwindow.py +25 -0
  226. bootstack/style/builders/progressbar.py +67 -0
  227. bootstack/style/builders/radiobutton.py +99 -0
  228. bootstack/style/builders/scale.py +64 -0
  229. bootstack/style/builders/scrollbar.py +225 -0
  230. bootstack/style/builders/separator.py +49 -0
  231. bootstack/style/builders/sidenav.py +643 -0
  232. bootstack/style/builders/sizegrip.py +15 -0
  233. bootstack/style/builders/spinbox.py +119 -0
  234. bootstack/style/builders/switch.py +70 -0
  235. bootstack/style/builders/tabitem.py +204 -0
  236. bootstack/style/builders/togglegroup.py +294 -0
  237. bootstack/style/builders/toolbutton.py +275 -0
  238. bootstack/style/builders/tooltip.py +26 -0
  239. bootstack/style/builders/treeview.py +193 -0
  240. bootstack/style/builders/utils.py +455 -0
  241. bootstack/style/builders_tk/__init__.py +16 -0
  242. bootstack/style/builders_tk/defaults.py +229 -0
  243. bootstack/style/element.py +173 -0
  244. bootstack/style/fonts.py +123 -0
  245. bootstack/style/style.py +609 -0
  246. bootstack/style/style_builder_base.py +716 -0
  247. bootstack/style/style_builder_mixed.py +93 -0
  248. bootstack/style/style_builder_tk.py +109 -0
  249. bootstack/style/style_builder_ttk.py +353 -0
  250. bootstack/style/style_resolver.py +447 -0
  251. bootstack/style/theme.py +245 -0
  252. bootstack/style/theme_provider.py +471 -0
  253. bootstack/style/themes/__init__.py +128 -0
  254. bootstack/style/tk_patch.py +5 -0
  255. bootstack/style/token_maps.py +41 -0
  256. bootstack/style/types.py +32 -0
  257. bootstack/style/typography.py +523 -0
  258. bootstack/style/utility.py +746 -0
  259. bootstack/types.py +39 -0
  260. bootstack/validation/__init__.py +6 -0
  261. bootstack/validation/types.py +15 -0
  262. bootstack/validation/validation_result.py +17 -0
  263. bootstack/validation/validation_rules.py +205 -0
  264. bootstack/widgets/__init__.py +74 -0
  265. bootstack/widgets/_core/__init__.py +31 -0
  266. bootstack/widgets/_core/app_config.py +266 -0
  267. bootstack/widgets/_core/base.py +461 -0
  268. bootstack/widgets/_core/container.py +334 -0
  269. bootstack/widgets/_core/context.py +35 -0
  270. bootstack/widgets/_core/events.py +130 -0
  271. bootstack/widgets/_core/field_mixin.py +353 -0
  272. bootstack/widgets/_core/icon_image_props.py +72 -0
  273. bootstack/widgets/_core/image_binding.py +93 -0
  274. bootstack/widgets/_core/navmodel.py +345 -0
  275. bootstack/widgets/_core/options.py +210 -0
  276. bootstack/widgets/_core/selection_group.py +130 -0
  277. bootstack/widgets/_core/window_controls.py +96 -0
  278. bootstack/widgets/_core/window_menu.py +246 -0
  279. bootstack/widgets/_impl/__init__.py +1 -0
  280. bootstack/widgets/_impl/_internal/__init__.py +0 -0
  281. bootstack/widgets/_impl/_internal/wrapper_base.py +307 -0
  282. bootstack/widgets/_impl/_parts/__init__.py +11 -0
  283. bootstack/widgets/_impl/_parts/numberentry_part.py +385 -0
  284. bootstack/widgets/_impl/_parts/spinnerentry_part.py +434 -0
  285. bootstack/widgets/_impl/_parts/textentry_part.py +406 -0
  286. bootstack/widgets/_impl/composites/__init__.py +33 -0
  287. bootstack/widgets/_impl/composites/_dateutils.py +33 -0
  288. bootstack/widgets/_impl/composites/_image_fit.py +105 -0
  289. bootstack/widgets/_impl/composites/accordion.py +381 -0
  290. bootstack/widgets/_impl/composites/avatar.py +191 -0
  291. bootstack/widgets/_impl/composites/buttongroup.py +371 -0
  292. bootstack/widgets/_impl/composites/calendar.py +972 -0
  293. bootstack/widgets/_impl/composites/carousel.py +567 -0
  294. bootstack/widgets/_impl/composites/chart.py +882 -0
  295. bootstack/widgets/_impl/composites/compositeframe.py +298 -0
  296. bootstack/widgets/_impl/composites/contextmenu.py +1951 -0
  297. bootstack/widgets/_impl/composites/dateentry.py +404 -0
  298. bootstack/widgets/_impl/composites/dropdownbutton.py +325 -0
  299. bootstack/widgets/_impl/composites/expander.py +515 -0
  300. bootstack/widgets/_impl/composites/field.py +670 -0
  301. bootstack/widgets/_impl/composites/form.py +1066 -0
  302. bootstack/widgets/_impl/composites/gallery.py +551 -0
  303. bootstack/widgets/_impl/composites/list/__init__.py +15 -0
  304. bootstack/widgets/_impl/composites/list/listitem.py +802 -0
  305. bootstack/widgets/_impl/composites/list/listview.py +1433 -0
  306. bootstack/widgets/_impl/composites/menu/__init__.py +18 -0
  307. bootstack/widgets/_impl/composites/menu/model.py +358 -0
  308. bootstack/widgets/_impl/composites/menu/render_native.py +134 -0
  309. bootstack/widgets/_impl/composites/menu/render_themed.py +134 -0
  310. bootstack/widgets/_impl/composites/meter.py +860 -0
  311. bootstack/widgets/_impl/composites/numericentry.py +201 -0
  312. bootstack/widgets/_impl/composites/pagestack.py +395 -0
  313. bootstack/widgets/_impl/composites/passwordentry.py +142 -0
  314. bootstack/widgets/_impl/composites/pathentry.py +168 -0
  315. bootstack/widgets/_impl/composites/picture.py +289 -0
  316. bootstack/widgets/_impl/composites/radiogroup.py +511 -0
  317. bootstack/widgets/_impl/composites/scrolledtext.py +375 -0
  318. bootstack/widgets/_impl/composites/scrolledtext.pyi +186 -0
  319. bootstack/widgets/_impl/composites/scrollview.py +764 -0
  320. bootstack/widgets/_impl/composites/selectbox.py +1026 -0
  321. bootstack/widgets/_impl/composites/shell/__init__.py +40 -0
  322. bootstack/widgets/_impl/composites/shell/content_host.py +52 -0
  323. bootstack/widgets/_impl/composites/shell/layout.py +335 -0
  324. bootstack/widgets/_impl/composites/shell/nav_panel.py +345 -0
  325. bootstack/widgets/_impl/composites/shell/providers.py +558 -0
  326. bootstack/widgets/_impl/composites/shell/rail.py +117 -0
  327. bootstack/widgets/_impl/composites/shell/shell.py +581 -0
  328. bootstack/widgets/_impl/composites/shell/workspace.py +273 -0
  329. bootstack/widgets/_impl/composites/sidenav/__init__.py +16 -0
  330. bootstack/widgets/_impl/composites/sidenav/header.py +81 -0
  331. bootstack/widgets/_impl/composites/sidenav/separator.py +44 -0
  332. bootstack/widgets/_impl/composites/slider/__init__.py +7 -0
  333. bootstack/widgets/_impl/composites/slider/_shared.py +195 -0
  334. bootstack/widgets/_impl/composites/slider/rangeslider.py +982 -0
  335. bootstack/widgets/_impl/composites/slider/slider.py +851 -0
  336. bootstack/widgets/_impl/composites/spinnerentry.py +185 -0
  337. bootstack/widgets/_impl/composites/tableview/__init__.py +5 -0
  338. bootstack/widgets/_impl/composites/tableview/tableview.py +3388 -0
  339. bootstack/widgets/_impl/composites/tableview/types.py +169 -0
  340. bootstack/widgets/_impl/composites/tabs/__init__.py +23 -0
  341. bootstack/widgets/_impl/composites/tabs/tabitem.py +389 -0
  342. bootstack/widgets/_impl/composites/tabs/tabs.py +974 -0
  343. bootstack/widgets/_impl/composites/tabs/tabview.py +650 -0
  344. bootstack/widgets/_impl/composites/textarea/__init__.py +26 -0
  345. bootstack/widgets/_impl/composites/textarea/change.py +46 -0
  346. bootstack/widgets/_impl/composites/textarea/codeeditor.py +526 -0
  347. bootstack/widgets/_impl/composites/textarea/core.py +495 -0
  348. bootstack/widgets/_impl/composites/textarea/decoration.py +42 -0
  349. bootstack/widgets/_impl/composites/textarea/diff.py +127 -0
  350. bootstack/widgets/_impl/composites/textarea/extensions/__init__.py +1 -0
  351. bootstack/widgets/_impl/composites/textarea/extensions/bracket_matcher.py +138 -0
  352. bootstack/widgets/_impl/composites/textarea/extensions/indent_guides.py +158 -0
  353. bootstack/widgets/_impl/composites/textarea/extensions/line_numbers.py +138 -0
  354. bootstack/widgets/_impl/composites/textarea/extensions/pygments_highlighter.py +312 -0
  355. bootstack/widgets/_impl/composites/textarea/extensions/smart_indent.py +177 -0
  356. bootstack/widgets/_impl/composites/textarea/filter.py +171 -0
  357. bootstack/widgets/_impl/composites/textarea/search_overlay.py +459 -0
  358. bootstack/widgets/_impl/composites/textarea/sidebar.py +88 -0
  359. bootstack/widgets/_impl/composites/textarea/style_registry.py +178 -0
  360. bootstack/widgets/_impl/composites/textarea/textarea.py +606 -0
  361. bootstack/widgets/_impl/composites/textarea/undo.py +217 -0
  362. bootstack/widgets/_impl/composites/textentry.py +57 -0
  363. bootstack/widgets/_impl/composites/timeentry.py +176 -0
  364. bootstack/widgets/_impl/composites/toast.py +390 -0
  365. bootstack/widgets/_impl/composites/toast_stack.py +156 -0
  366. bootstack/widgets/_impl/composites/togglegroup.py +418 -0
  367. bootstack/widgets/_impl/composites/toolbar.py +608 -0
  368. bootstack/widgets/_impl/composites/tooltip.py +491 -0
  369. bootstack/widgets/_impl/composites/tree/__init__.py +7 -0
  370. bootstack/widgets/_impl/composites/tree/source_binding.py +136 -0
  371. bootstack/widgets/_impl/composites/tree/treeitem.py +393 -0
  372. bootstack/widgets/_impl/composites/tree/treenode.py +174 -0
  373. bootstack/widgets/_impl/composites/tree/treeview.py +841 -0
  374. bootstack/widgets/_impl/mixins/__init__.py +24 -0
  375. bootstack/widgets/_impl/mixins/configure_mixin.py +216 -0
  376. bootstack/widgets/_impl/mixins/entry_mixin.py +134 -0
  377. bootstack/widgets/_impl/mixins/font_mixin.py +368 -0
  378. bootstack/widgets/_impl/mixins/icon_mixin.py +61 -0
  379. bootstack/widgets/_impl/mixins/localization_mixin.py +253 -0
  380. bootstack/widgets/_impl/mixins/signal_mixin.py +268 -0
  381. bootstack/widgets/_impl/mixins/validation_mixin.py +226 -0
  382. bootstack/widgets/_impl/primitives/__init__.py +49 -0
  383. bootstack/widgets/_impl/primitives/_menubutton.py +107 -0
  384. bootstack/widgets/_impl/primitives/badge.py +45 -0
  385. bootstack/widgets/_impl/primitives/button.py +76 -0
  386. bootstack/widgets/_impl/primitives/card.py +45 -0
  387. bootstack/widgets/_impl/primitives/checkbutton.py +124 -0
  388. bootstack/widgets/_impl/primitives/checktoggle.py +62 -0
  389. bootstack/widgets/_impl/primitives/combobox.py +156 -0
  390. bootstack/widgets/_impl/primitives/entry.py +87 -0
  391. bootstack/widgets/_impl/primitives/flexframe.py +448 -0
  392. bootstack/widgets/_impl/primitives/frame.py +185 -0
  393. bootstack/widgets/_impl/primitives/gridframe.py +546 -0
  394. bootstack/widgets/_impl/primitives/label.py +84 -0
  395. bootstack/widgets/_impl/primitives/labelframe.py +54 -0
  396. bootstack/widgets/_impl/primitives/optionmenu.py +387 -0
  397. bootstack/widgets/_impl/primitives/packframe.py +227 -0
  398. bootstack/widgets/_impl/primitives/panedwindow.py +45 -0
  399. bootstack/widgets/_impl/primitives/progressbar.py +83 -0
  400. bootstack/widgets/_impl/primitives/radiobutton.py +115 -0
  401. bootstack/widgets/_impl/primitives/radiotoggle.py +54 -0
  402. bootstack/widgets/_impl/primitives/scrollbar.py +42 -0
  403. bootstack/widgets/_impl/primitives/separator.py +43 -0
  404. bootstack/widgets/_impl/primitives/sizegrip.py +33 -0
  405. bootstack/widgets/_impl/primitives/spinbox.py +95 -0
  406. bootstack/widgets/_impl/primitives/switch.py +44 -0
  407. bootstack/widgets/_impl/primitives/treeview.py +69 -0
  408. bootstack/widgets/app.py +371 -0
  409. bootstack/widgets/appshell.py +1179 -0
  410. bootstack/widgets/avatar.py +140 -0
  411. bootstack/widgets/boolean_controls.py +455 -0
  412. bootstack/widgets/button.py +224 -0
  413. bootstack/widgets/buttongroup.py +239 -0
  414. bootstack/widgets/calendar.py +195 -0
  415. bootstack/widgets/card.py +159 -0
  416. bootstack/widgets/carousel.py +241 -0
  417. bootstack/widgets/chart.py +302 -0
  418. bootstack/widgets/codeeditor.py +675 -0
  419. bootstack/widgets/contextmenu.py +371 -0
  420. bootstack/widgets/datatable.py +688 -0
  421. bootstack/widgets/datefield.py +395 -0
  422. bootstack/widgets/divider.py +60 -0
  423. bootstack/widgets/expander.py +579 -0
  424. bootstack/widgets/form.py +200 -0
  425. bootstack/widgets/gallery.py +250 -0
  426. bootstack/widgets/gauge.py +168 -0
  427. bootstack/widgets/grid.py +121 -0
  428. bootstack/widgets/groupbox.py +162 -0
  429. bootstack/widgets/label.py +229 -0
  430. bootstack/widgets/listview.py +354 -0
  431. bootstack/widgets/menubutton.py +419 -0
  432. bootstack/widgets/numberfield.py +431 -0
  433. bootstack/widgets/pagestack.py +345 -0
  434. bootstack/widgets/passwordfield.py +383 -0
  435. bootstack/widgets/pathfield.py +454 -0
  436. bootstack/widgets/picture.py +251 -0
  437. bootstack/widgets/progressbar.py +106 -0
  438. bootstack/widgets/radio_variants.py +271 -0
  439. bootstack/widgets/radiogroup.py +228 -0
  440. bootstack/widgets/scrollbar.py +64 -0
  441. bootstack/widgets/scrollview.py +186 -0
  442. bootstack/widgets/select.py +302 -0
  443. bootstack/widgets/selectbutton.py +182 -0
  444. bootstack/widgets/sidebar_toggle.py +130 -0
  445. bootstack/widgets/sizegrip.py +42 -0
  446. bootstack/widgets/slider.py +408 -0
  447. bootstack/widgets/spinbox.py +147 -0
  448. bootstack/widgets/spinnerfield.py +413 -0
  449. bootstack/widgets/splash.py +367 -0
  450. bootstack/widgets/splitview.py +482 -0
  451. bootstack/widgets/stacks.py +249 -0
  452. bootstack/widgets/statusbar.py +189 -0
  453. bootstack/widgets/tabs.py +425 -0
  454. bootstack/widgets/textarea.py +459 -0
  455. bootstack/widgets/textfield.py +410 -0
  456. bootstack/widgets/theme_toggle.py +92 -0
  457. bootstack/widgets/timefield.py +340 -0
  458. bootstack/widgets/toast.py +314 -0
  459. bootstack/widgets/togglegroup.py +231 -0
  460. bootstack/widgets/toolbar.py +347 -0
  461. bootstack/widgets/tooltip.py +94 -0
  462. bootstack/widgets/tree.py +648 -0
  463. bootstack/widgets/types.py +305 -0
  464. bootstack/widgets/window.py +307 -0
  465. bootstack-0.1.0.dist-info/METADATA +301 -0
  466. bootstack-0.1.0.dist-info/RECORD +471 -0
  467. bootstack-0.1.0.dist-info/WHEEL +5 -0
  468. bootstack-0.1.0.dist-info/entry_points.txt +2 -0
  469. bootstack-0.1.0.dist-info/licenses/LICENSE +21 -0
  470. bootstack-0.1.0.dist-info/licenses/NOTICE +10 -0
  471. bootstack-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,45 @@
1
+ from typing_extensions import Unpack
2
+ from bootstack.widgets._impl.primitives.label import Label, LabelKwargs
3
+ from bootstack.widgets.types import Master
4
+
5
+
6
+ class Badge(Label):
7
+ """bootstack wrapper for `ttk.Label` that renders with a badge style."""
8
+
9
+ def __init__(self, master: Master = None, **kwargs: Unpack[LabelKwargs]):
10
+ """Create a themed bootstack Badge.
11
+
12
+ Args:
13
+ master: Parent widget. If None, uses the default root window.
14
+
15
+ Note:
16
+ Badge is text-only by design. The TBadge ttk style layout omits the
17
+ image element, so `image=`, `icon=`, `icon_only=`, and `compound=`
18
+ are silently dropped at render time even though Label accepts them.
19
+
20
+ Other Parameters:
21
+ text: Text to display on the badge.
22
+ anchor: Alignment of the badge content within its area.
23
+ justify: How to justify multiple lines of text.
24
+ localize: Determines the widget's localization mode.
25
+ value_format: Format specification for the badge value.
26
+ padding: Extra space around the badge content.
27
+ width: Width of the badge in characters.
28
+ wraplength: Maximum width before wrapping text.
29
+ font: Font for the badge text.
30
+ foreground: Text color.
31
+ background: Background color.
32
+ relief: Border style.
33
+ state: Widget state.
34
+ takefocus: Whether the widget participates in focus traversal.
35
+ style: Explicit ttk style name (overrides accent/variant).
36
+ accent: Accent token for styling, e.g. 'primary', 'success', 'danger'.
37
+ variant: Shape of badge. 'pill' or 'square' (default).
38
+ surface: Optional surface token; otherwise inherited.
39
+ style_options: Optional dict forwarded to the style builder.
40
+ """
41
+ kwargs.setdefault('ttk_class', 'TBadge')
42
+ kwargs.setdefault('anchor', 'center')
43
+ kwargs.setdefault('font', '-size 8')
44
+ kwargs.setdefault('variant', 'square')
45
+ super().__init__(master=master, **kwargs)
@@ -0,0 +1,76 @@
1
+ from __future__ import annotations
2
+
3
+ from tkinter import ttk
4
+ from typing import Any, Callable, Literal, TYPE_CHECKING
5
+ from typing_extensions import Unpack
6
+
7
+ from bootstack._core.mixins.ttk_state import TtkStateMixin
8
+ from bootstack._core.mixins.widget import WidgetCapabilitiesMixin
9
+ from bootstack.widgets._impl._internal.wrapper_base import TTKWrapperBase
10
+ from bootstack.widgets._impl.mixins import IconMixin, TextSignalMixin, LocalizationMixin
11
+ from bootstack.widgets.types import Master, StyledKwargs, Anchor, CompoundMode, WidgetState, WidgetDensity
12
+
13
+ if TYPE_CHECKING:
14
+ from bootstack.signals import Signal
15
+
16
+
17
+ class ButtonKwargs(StyledKwargs, total=False):
18
+ # Standard ttk.Button options
19
+ text: Any
20
+ command: Callable[[], Any] | None
21
+ image: Any
22
+ icon: Any
23
+ icon_only: bool
24
+ anchor: Anchor
25
+ compound: CompoundMode
26
+ padding: Any
27
+ width: int
28
+ underline: int
29
+ state: WidgetState
30
+ localize: bool | Literal['auto']
31
+ default: Any
32
+ textvariable: Any
33
+ textsignal: Signal[str]
34
+
35
+ # bootstack-specific extensions
36
+ density: WidgetDensity
37
+
38
+
39
+ class Button(LocalizationMixin, TextSignalMixin, IconMixin, TTKWrapperBase, WidgetCapabilitiesMixin, TtkStateMixin, ttk.Button):
40
+ """bootstack wrapper for `ttk.Button` with themed styling and icon support.
41
+ """
42
+ _ttk_base = ttk.Button
43
+
44
+ def __init__(self, master: Master = None, **kwargs: Unpack[ButtonKwargs]) -> None:
45
+ """Create a themed bootstack Button.
46
+
47
+ Args:
48
+ master: Parent widget. If None, uses the default root window.
49
+
50
+ Other Parameters:
51
+ text: Text to display on the button.
52
+ textvariable: Tk variable linked to the button text.
53
+ See [tkinter Variables](https://docs.python.org/3/library/tkinter.html#tkinter-variables).
54
+ textsignal: Reactive Signal linked to the button text (auto-synced with textvariable).
55
+ command: Callable invoked when the button is pressed.
56
+ image: Image to display on the button.
57
+ icon: Optional icon spec integrated via the style system.
58
+ icon_only: If true, removes the extra padding reserved for the text labels.
59
+ compound: Placement of the image relative to text (e.g., 'left').
60
+ padding: Extra space around the button content.
61
+ anchor: Determines how the content is aligned in the container. Combination of 'n', 's', 'e', 'w', or 'center' (default).
62
+ localize: Determines the widgets localization mode.
63
+ width: Width of the button in characters.
64
+ underline: Index of the character to underline in `text`.
65
+ state: Widget state — 'normal', 'active', 'disabled', or 'readonly'.
66
+ takefocus: Whether the widget accepts focus during traversal.
67
+ style: Explicit ttk style name to apply (overrides accent/variant).
68
+ accent: Accent token for styling, e.g. 'primary', 'danger', 'success'.
69
+ variant: Style variant, e.g. 'solid', 'outline', 'link', 'text'. Defaults to 'solid'.
70
+ density: Widget density — 'default' or 'compact'.
71
+ surface: Optional surface token to use for this button; if not provided, surface color is inherited from the parent.
72
+ style_options: Optional dict forwarded to the style builder.
73
+ """
74
+ kwargs.setdefault('variant', 'solid')
75
+ kwargs.update(style_options=self._capture_style_options(['icon_only', 'icon', 'anchor', 'density'], kwargs))
76
+ super().__init__(master, **kwargs)
@@ -0,0 +1,45 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ from typing_extensions import Unpack
6
+
7
+ from bootstack.widgets._impl.primitives.frame import Frame
8
+ from bootstack.widgets.types import Master, StyledKwargs
9
+
10
+
11
+ class CardKwargs(StyledKwargs, total=False):
12
+ # Standard ttk.Frame options
13
+ padding: Any
14
+ width: int
15
+ height: int
16
+
17
+ # bootstack-specific extensions
18
+ show_border: bool
19
+
20
+
21
+ class Card(Frame):
22
+ """A frame with card styling"""
23
+
24
+ def __init__(self, master: Master = None, **kwargs: Unpack[CardKwargs]) -> None:
25
+ """Create a themed Card container.
26
+
27
+ Args:
28
+ master: Parent widget. If None, uses the default root window.
29
+
30
+ Other Parameters:
31
+ padding: Extra padding inside the card. Default 16.
32
+ width: Requested width in pixels.
33
+ height: Requested height in pixels.
34
+ takefocus: Widget accepts focus during keyboard traversal.
35
+ style: Explicit ttk style name (overrides accent/variant).
36
+ accent: Accent/color token for the card. Default 'card'.
37
+ surface: Surface token for the parent background.
38
+ show_border: Draw a border around the card. Default True.
39
+ style_options: Optional dict forwarded to the style builder.
40
+ """
41
+ kwargs.setdefault('accent', 'card')
42
+ kwargs.setdefault('show_border', True)
43
+ kwargs.setdefault('padding', 16)
44
+ kwargs.setdefault('variant', 'card')
45
+ super().__init__(master, **kwargs)
@@ -0,0 +1,124 @@
1
+ from __future__ import annotations
2
+
3
+ from tkinter import ttk
4
+ from typing import Any, Callable, Literal, TYPE_CHECKING
5
+
6
+ from typing_extensions import Unpack
7
+
8
+ from bootstack._core.mixins.ttk_state import TtkStateMixin
9
+ from bootstack._core.mixins.widget import WidgetCapabilitiesMixin
10
+ from bootstack.widgets._impl._internal.wrapper_base import TTKWrapperBase
11
+ from bootstack.widgets._impl.mixins import IconMixin, LocalizationMixin, SignalMixin, TextSignalMixin
12
+ from bootstack.widgets._impl.mixins.configure_mixin import configure_delegate
13
+ from bootstack.widgets.types import Master, StyledKwargs, Anchor, CompoundMode, WidgetState
14
+
15
+ if TYPE_CHECKING:
16
+ from bootstack.signals import Signal
17
+
18
+
19
+ class CheckButtonKwargs(StyledKwargs, total=False):
20
+ # Standard ttk.Checkbutton options
21
+ text: Any
22
+ command: Callable[[], Any] | None
23
+ image: Any
24
+ icon: Any
25
+ on_icon: Any
26
+ off_icon: Any
27
+ icon_only: bool
28
+ show_indicator: bool
29
+ compound: CompoundMode
30
+ variable: Any
31
+ signal: Signal[Any]
32
+ value: Any
33
+ onvalue: Any
34
+ offvalue: Any
35
+ padding: Any
36
+ anchor: Anchor
37
+ width: int
38
+ underline: int
39
+ state: WidgetState
40
+ textvariable: Any
41
+ textsignal: Signal[str]
42
+
43
+ # bootstack-specific extensions
44
+ localize: bool | Literal['auto']
45
+
46
+
47
+ class CheckButton(LocalizationMixin, SignalMixin, TextSignalMixin, IconMixin, TTKWrapperBase, WidgetCapabilitiesMixin, TtkStateMixin, ttk.Checkbutton):
48
+ """bootstack wrapper for `ttk.Checkbutton` with themed styling and icon support."""
49
+
50
+ _ttk_base = ttk.Checkbutton
51
+
52
+ def __init__(self, master: Master = None, **kwargs: Unpack[CheckButtonKwargs]) -> None:
53
+ """Create a themed bootstack Checkbutton.
54
+
55
+ Args:
56
+ master: Parent widget. If None, uses the default root window.
57
+
58
+ Other Parameters:
59
+ text: Text to display.
60
+ textvariable: Tk variable linked to the text.
61
+ See [tkinter Variables](https://docs.python.org/3/library/tkinter.html#tkinter-variables).
62
+ textsignal: Reactive Signal linked to the text (auto-synced with textvariable).
63
+ command: Callable invoked when the value toggles.
64
+ image: Image to display.
65
+ icon: Icon shown in the label area for all states. Color shifts
66
+ from foreground (unselected) to accent (selected) automatically.
67
+ on_icon: Icon shown in the label area when the button is selected.
68
+ Shortcut for `state=[("selected", name)]` inside a full icon spec.
69
+ off_icon: Icon shown in the label area when the button is unselected.
70
+ Used as the base icon when `on_icon` is also provided.
71
+ icon_only: If True, removes the additional padding reserved for text.
72
+ show_indicator: Whether to show the standard checkbox indicator. Defaults
73
+ to True. Set to False to hide the indicator (e.g. when using icons alone).
74
+ compound: Placement of the image relative to text.
75
+ variable: Linked variable controlling the on/off state.
76
+ See [tkinter Variables](https://docs.python.org/3/library/tkinter.html#tkinter-variables).
77
+ localize: Determines the widget's localization mode.
78
+ signal: Reactive Signal controlling the on/off state (auto-synced with variable).
79
+ value: Initial state for the widget's associated variable (defaults to None when unset).
80
+ onvalue: Value set in `variable` when selected.
81
+ offvalue: Value set in `variable` when deselected.
82
+ padding: Extra space around the content.
83
+ anchor: Determines how the content is aligned in the container. Combination of 'n', 's', 'e', 'w', or 'center' (default).
84
+ width: Width of the control in characters.
85
+ underline: Index of character to underline in `text`.
86
+ state: Widget state.
87
+ takefocus: Whether the widget participates in focus traversal.
88
+ style: Explicit ttk style name (overrides accent/variant).
89
+ accent: Accent token for styling, e.g. 'primary', 'success', 'danger'.
90
+ variant: Style variant, e.g. 'default', 'round', 'square'.
91
+ surface: Optional surface token; otherwise inherited.
92
+ style_options: Optional dict forwarded to the style builder.
93
+ """
94
+ signal_provided = 'signal' in kwargs
95
+ variable_provided = 'variable' in kwargs
96
+ initial_value = kwargs.pop('value', None)
97
+ kwargs.update(style_options=self._capture_style_options(['icon_only', 'icon', 'on_icon', 'off_icon', 'show_indicator', 'anchor'], kwargs))
98
+ super().__init__(master, **kwargs)
99
+ if initial_value is not None and not signal_provided and not variable_provided:
100
+ self.variable.set(initial_value)
101
+
102
+ def get(self) -> Any:
103
+ """Return the current value of the checkbutton."""
104
+ return self.variable.get()
105
+
106
+ def set(self, value: Any) -> None:
107
+ """Set the value of the checkbutton."""
108
+ self.variable.set(value)
109
+
110
+ @property
111
+ def value(self) -> Any:
112
+ """Get or set the checkbutton's value."""
113
+ return self.get()
114
+
115
+ @value.setter
116
+ def value(self, value: Any) -> None:
117
+ self.set(value)
118
+
119
+ @configure_delegate('value')
120
+ def _delegate_value(self, value=None):
121
+ """Get or set the value via configure."""
122
+ if value is None:
123
+ return self.get()
124
+ self.set(value)
@@ -0,0 +1,62 @@
1
+ from typing import Literal
2
+
3
+ from typing_extensions import Unpack
4
+
5
+ from bootstack.widgets._impl.primitives.checkbutton import CheckButton, CheckButtonKwargs
6
+ from bootstack.widgets.types import Master
7
+
8
+
9
+ class CheckToggle(CheckButton):
10
+ """bootstack wrapper for `ttk.Checkbutton` that renders with a ToolButton style"""
11
+
12
+ def __init__(self, master: Master = None, **kwargs: Unpack[CheckButtonKwargs]) -> None:
13
+ """Create a themed bootstack CheckToggle.
14
+
15
+ Args:
16
+ master: Parent widget. If None, uses the default root window.
17
+
18
+ Other Parameters:
19
+ text: Text to display on the toggle.
20
+ textvariable: Tk variable linked to the text.
21
+ See [tkinter Variables](https://docs.python.org/3/library/tkinter.html#tkinter-variables).
22
+ textsignal: Reactive Signal linked to the text (auto-synced with textvariable).
23
+ command: Callable invoked when the toggle changes state.
24
+ image: Image to display.
25
+ icon: Icon shown in the label area for all states. Color shifts
26
+ with the button's pressed/selected state automatically.
27
+ on_icon: Icon shown when the toggle is selected (on). Shortcut
28
+ for `state=[("selected", name)]` inside a full icon spec.
29
+ off_icon: Icon shown when the toggle is unselected (off). Used
30
+ as the base icon when `on_icon` is also provided.
31
+ icon_only: If True, removes the additional padding reserved for text.
32
+ compound: Placement of the image relative to text.
33
+ variable: Linked variable controlling the on/off state.
34
+ See [tkinter Variables](https://docs.python.org/3/library/tkinter.html#tkinter-variables).
35
+ signal: Reactive Signal controlling the on/off state (auto-synced with variable).
36
+ value: Initial state for the widget's associated variable (defaults to None when unset).
37
+ onvalue: Value set in `variable` when selected.
38
+ offvalue: Value set in `variable` when deselected.
39
+ padding: Extra space around the content.
40
+ anchor: Determines how the content is aligned in the container. Combination of 'n', 's', 'e', 'w', or 'center' (default).
41
+ density: The vertical and horizontal compactness of widget content, e.g. 'default', 'compact'.
42
+ width: Width of the control in characters.
43
+ underline: Index of character to underline in `text`.
44
+ state: Widget state ('normal', 'active', 'disabled', 'readonly').
45
+ takefocus: Whether the widget participates in focus traversal.
46
+ accent: Accent token for styling, e.g. 'primary', 'success', 'danger'.
47
+ variant: Style variant (coerced to 'toolbutton').
48
+ surface: Optional surface token; otherwise inherited.
49
+ style_options: Optional dict forwarded to the style builder.
50
+ localize: Determines the widget's localization mode.
51
+ """
52
+ self._capture_density_option(kwargs)
53
+ kwargs.setdefault('class_', 'Toolbutton')
54
+ super().__init__(master, **kwargs)
55
+
56
+ @staticmethod
57
+ def _capture_density_option(kwargs: dict) -> None:
58
+ """Capture density from kwargs into style_options."""
59
+ density: Literal['default', 'compact'] | None = kwargs.pop('density', None)
60
+ if density is not None:
61
+ style_options = kwargs.setdefault('style_options', {})
62
+ style_options['density'] = density
@@ -0,0 +1,156 @@
1
+ from __future__ import annotations
2
+
3
+ from tkinter import ttk
4
+ from typing import Any, TYPE_CHECKING
5
+
6
+ from typing_extensions import Unpack
7
+
8
+ from bootstack._core.mixins.ttk_state import TtkStateMixin
9
+ from bootstack._core.mixins.widget import WidgetCapabilitiesMixin
10
+ from bootstack.widgets._impl._internal.wrapper_base import TTKWrapperBase
11
+ from bootstack.widgets.types import Master, StyledKwargs, Justify, WidgetState, WidgetDensity
12
+ from ..mixins import TextSignalMixin, configure_delegate
13
+
14
+ if TYPE_CHECKING:
15
+ from bootstack.signals import Signal
16
+
17
+
18
+ class ComboboxKwargs(StyledKwargs, total=False):
19
+ # Standard ttk.Combobox options
20
+ values: Any
21
+ textvariable: Any
22
+ textsignal: Signal[Any]
23
+ state: WidgetState
24
+ width: int
25
+ height: int
26
+ postcommand: Any
27
+ justify: Justify
28
+ exportselection: bool
29
+ xscrollcommand: Any
30
+ font: Any
31
+ foreground: str
32
+ background: str
33
+
34
+ # bootstack-specific extensions
35
+ density: WidgetDensity
36
+
37
+
38
+ class Combobox(TextSignalMixin, TTKWrapperBase, WidgetCapabilitiesMixin, TtkStateMixin, ttk.Combobox):
39
+ """bootstack wrapper for `ttk.Combobox` with themed styling support."""
40
+
41
+ _ttk_base = ttk.Combobox
42
+
43
+ def __init__(self, master: Master = None, **kwargs: Unpack[ComboboxKwargs]) -> None:
44
+ """Create a themed bootstack Combobox.
45
+
46
+ Args:
47
+ master: Parent widget. If None, uses the default root window.
48
+
49
+ Other Parameters:
50
+ values: Sequence of values to display.
51
+ textvariable: Tk variable linked to the selected value.
52
+ See [tkinter Variables](https://docs.python.org/3/library/tkinter.html#tkinter-variables).
53
+ textsignal: Reactive Signal linked to the text (auto-synced with textvariable).
54
+ state: Widget state; 'readonly' restricts to list items.
55
+ width: Width in characters.
56
+ height: Maximum rows shown in the drop-down list.
57
+ postcommand: Callback executed before showing the drop-down.
58
+ justify: Text justification within the entry field.
59
+ exportselection: Whether selection is exported to X clipboard.
60
+ xscrollcommand: Scroll callback for horizontal scrolling.
61
+ font: Font for the entry field.
62
+ foreground: Text color.
63
+ background: Background color for the entry field.
64
+ style: Explicit ttk style name (overrides accent/variant).
65
+ accent: Accent token for styling, e.g. 'primary', 'danger', 'success'.
66
+ density: Vertical and horizontal compactness, e.g. 'default', 'compact'.
67
+ surface: Optional surface token; otherwise inherited.
68
+ style_options: Optional dict forwarded to the style builder.
69
+ """
70
+ # Store density for popdown positioning
71
+ if kwargs.get('density') == 'compact':
72
+ kwargs['font'] = 'caption'
73
+ kwargs.update(style_options=self._capture_style_options(['density'], kwargs))
74
+ super().__init__(master, **kwargs)
75
+
76
+ # Store original postcommand if provided
77
+ self._original_postcommand = kwargs.get('postcommand')
78
+
79
+ # Set up popdown styling. A theme change re-styles an already-open
80
+ # popdown through the unified theme walk (`_bs_apply_theme`).
81
+ self._setup_postcommand()
82
+
83
+ @configure_delegate('density')
84
+ def _delegate_density(self, value=None):
85
+ if value is None:
86
+ return self.configure_style_options(value)
87
+ else:
88
+ if value == 'compact':
89
+ self.configure(font='caption')
90
+ else:
91
+ self.configure(font='body')
92
+ return self.configure_style_options(density=value)
93
+
94
+ def _setup_postcommand(self) -> None:
95
+ """Re-style the popdown each time it opens.
96
+
97
+ The popdown is created lazily on first open and reused. Re-styling on
98
+ every open ensures it picks up the current theme's colors, since the
99
+ embedded Tk listbox/scrollbar aren't rebuilt by the ttk style engine.
100
+ """
101
+
102
+ def on_popdown():
103
+ self._apply_popdown_style(create_if_missing=True)
104
+
105
+ if self._original_postcommand:
106
+ if callable(self._original_postcommand):
107
+ self._original_postcommand()
108
+ else:
109
+ self.tk.eval(str(self._original_postcommand))
110
+
111
+ self.configure(postcommand=on_popdown)
112
+
113
+ def _apply_popdown_style(self, create_if_missing: bool = False, **kwargs) -> None:
114
+ """Apply theme colors and density font to the embedded popdown.
115
+
116
+ Args:
117
+ create_if_missing: If True, force-create the popdown so we can
118
+ style it before it's mapped (used from the postcommand). If
119
+ False, no-op when the popdown doesn't exist yet (used from
120
+ the theme-change subscriber).
121
+ """
122
+ popdown_path = f"{self}.popdown"
123
+ try:
124
+ popdown_exists = bool(int(self.tk.eval(f"winfo exists {popdown_path}")))
125
+ except Exception:
126
+ return
127
+
128
+ if not popdown_exists:
129
+ if not create_if_missing:
130
+ return
131
+ try:
132
+ self.tk.eval(f"ttk::combobox::PopdownWindow {self}")
133
+ except Exception:
134
+ return
135
+
136
+ try:
137
+ from bootstack.style.style_builder_mixed import StyleBuilderMixed
138
+ StyleBuilderMixed().update_combobox_popdown_style(self)
139
+ except Exception:
140
+ pass
141
+
142
+ try:
143
+ density = self.configure_style_options('density') or 'default'
144
+ from bootstack.style.typography import get_font
145
+ font_token = 'caption' if density == 'compact' else 'body'
146
+ self.tk.call(f"{popdown_path}.f.l", "configure", "-font", str(get_font(font_token)))
147
+ except Exception:
148
+ pass
149
+
150
+ def _bs_apply_theme(self) -> None:
151
+ """Unified theme-walk hook — re-style an already-open popdown.
152
+
153
+ The ttk style engine handles the entry itself; this re-colors the
154
+ embedded Tk listbox/scrollbar of the popdown if one has been created.
155
+ """
156
+ self._apply_popdown_style()
@@ -0,0 +1,87 @@
1
+ from __future__ import annotations
2
+
3
+ from tkinter import ttk
4
+ from typing import Any, TYPE_CHECKING
5
+ from typing_extensions import Unpack
6
+
7
+ from bootstack._core.mixins.ttk_state import TtkStateMixin
8
+ from bootstack._core.mixins.widget import WidgetCapabilitiesMixin
9
+ from bootstack.widgets._impl._internal.wrapper_base import TTKWrapperBase
10
+ from bootstack.widgets.types import Master, StyledKwargs, Justify, WidgetState, WidgetDensity
11
+ from ..mixins import TextSignalMixin, configure_delegate
12
+
13
+ if TYPE_CHECKING:
14
+ from bootstack.signals import Signal
15
+
16
+
17
+ class EntryKwargs(StyledKwargs, total=False):
18
+ # Standard ttk.Entry options
19
+ textvariable: Any
20
+ textsignal: Signal[str]
21
+ show: Any
22
+ width: int
23
+ exportselection: bool
24
+ justify: Justify
25
+ validate: Any
26
+ validatecommand: Any
27
+ invalidcommand: Any
28
+ xscrollcommand: Any
29
+ font: Any
30
+ foreground: str
31
+ background: str
32
+ state: WidgetState
33
+
34
+ # bootstack-specific extensions
35
+ density: WidgetDensity
36
+
37
+
38
+ class Entry(TextSignalMixin, TTKWrapperBase, WidgetCapabilitiesMixin, TtkStateMixin, ttk.Entry):
39
+ """bootstack wrapper for `ttk.Entry` with themed styling support."""
40
+
41
+ _ttk_base = ttk.Entry
42
+
43
+ def __init__(self, master: Master = None, **kwargs: Unpack[EntryKwargs]) -> None:
44
+ """Create a themed bootstack Entry.
45
+
46
+ Args:
47
+ master: Parent widget. If None, uses the default root window.
48
+
49
+ Other Parameters:
50
+ textvariable: Tk variable linked to the entry text.
51
+ See [tkinter Variables](https://docs.python.org/3/library/tkinter.html#tkinter-variables).
52
+ textsignal: Reactive Signal linked to the entry text (auto-synced with textvariable).
53
+ show: Substitute character for masked input.
54
+ width: Width in characters.
55
+ exportselection: Whether selection is exported to X clipboard.
56
+ justify: Text alignment inside the entry.
57
+ validate: Validation mode.
58
+ validatecommand: Validation callback.
59
+ invalidcommand: Callback executed on validation failure.
60
+ xscrollcommand: Horizontal scroll callback.
61
+ font: Font for the entry text.
62
+ foreground: Text color.
63
+ background: Background color.
64
+ state: Widget state.
65
+ takefocus: Whether the widget participates in focus traversal.
66
+ style: Explicit ttk style name (overrides accent/variant).
67
+ accent: Accent token for styling, e.g. 'primary', 'danger', 'success'.
68
+ variant: Style variant, e.g. 'default'.
69
+ density: Vertical and horizontal compactness, e.g. 'default', 'compact'.
70
+ surface: Optional surface token; otherwise inherited.
71
+ style_options: Optional dict forwarded to the style builder.
72
+ """
73
+ if kwargs.get('density') == 'compact':
74
+ kwargs['font'] = 'caption'
75
+ kwargs.update(style_options=self._capture_style_options(['density'], kwargs))
76
+ super().__init__(master, **kwargs)
77
+
78
+ @configure_delegate('density')
79
+ def _delegate_density(self, value=None):
80
+ if value is None:
81
+ return self.configure_style_options(value)
82
+ else:
83
+ if value == 'compact':
84
+ self.configure(font='caption')
85
+ else:
86
+ self.configure(font='body')
87
+ return self.configure_style_options(density=value)