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,285 @@
1
+ """App icon command — a visual designer for application icons.
2
+
3
+ Launches a small bootstack app that previews an `AppIcon` live as you adjust the
4
+ glyph, colors, and corner radius, then exports it (`.ico`/`.icns`/`.png`) or
5
+ copies a ready-to-paste `[build.icon]` snippet for `bootstack.toml`.
6
+ """
7
+ from __future__ import annotations
8
+
9
+ import argparse
10
+
11
+ from bootstack.widgets.types import IconSpec
12
+ from bootstack.clipboard import set_clipboard
13
+
14
+
15
+ def add_parser(subparsers: argparse._SubParsersAction) -> None:
16
+ parser = subparsers.add_parser(
17
+ "appicon",
18
+ help="Design an application icon and export it",
19
+ description=(
20
+ "Launch the app icon designer.\n\n"
21
+ "Pick a Bootstrap glyph, choose background and foreground colors and "
22
+ "a corner radius, and preview the result live at several sizes. Export "
23
+ "an .ico / .icns / .png for a packaged build, or copy a [build.icon] "
24
+ "snippet for bootstack.toml. (Find glyph names with `bootstack icons`.)"
25
+ ),
26
+ )
27
+ parser.set_defaults(func=lambda args: run_appicon())
28
+
29
+
30
+ # Windows/Linux preview sizes (glyph-only), largest first.
31
+ _PREVIEW_SIZES = [96, 64, 48, 32, 16]
32
+ # macOS preview size (the rounded tile).
33
+ _MACOS_SIZE = 196
34
+
35
+ _HEX_DIGITS = set("0123456789abcdefABCDEF")
36
+
37
+
38
+ def _is_hex(color: str) -> bool:
39
+ return (
40
+ color.startswith("#")
41
+ and len(color) in (4, 7, 9)
42
+ and all(ch in _HEX_DIGITS for ch in color[1:])
43
+ )
44
+
45
+
46
+ def run_appicon() -> None:
47
+ import bootstack as bs
48
+ from bootstack.images import AppIcon, list_icons
49
+
50
+ state: dict = {"jobs": {}, "win_imgs": [], "mac_img": None}
51
+
52
+ with bs.App(title="App Icon Designer", size=(800, 600)) as app:
53
+ # Signals require the application root, so create them inside the context.
54
+ glyph_sig = bs.Signal("rocket")
55
+ bg_sig = bs.Signal("#0d6efd")
56
+ fg_sig = bs.Signal("#ffffff")
57
+ radius_sig = bs.Signal(0.22)
58
+ dark_sig = bs.Signal(False)
59
+ status_sig = bs.Signal("Adjust settings to see live preview")
60
+
61
+ with bs.Row(grow=True, horizontal="stretch"):
62
+
63
+ # ── Controls ──────────────────────────────────────────────────────
64
+ with bs.Column(padding=16, gap=24, vertical="stretch", horizontal_items="stretch"):
65
+ bs.Label("App Icon Designer", font="heading-md")
66
+ bs.Label(textsignal=status_sig, font="caption", accent="muted", wrap_width=225)
67
+
68
+ gl = bs.TextField(textsignal=glyph_sig, label="Glyph")
69
+ gl.insert_addon("button", "after", icon="grid-fill", on_click=lambda: _open_picker(gl))
70
+
71
+ bg = bs.TextField(textsignal=bg_sig, label="Background color")
72
+ bg.insert_addon("button", "after", icon="palette-fill", on_click=lambda: _pick(bg_sig))
73
+
74
+ fg = bs.TextField(textsignal=fg_sig, label="Foreground")
75
+ fg.insert_addon("button", "after", icon="palette-fill", on_click=lambda: _pick(fg_sig))
76
+
77
+ bs.NumberField(signal=radius_sig, min_value=0.00, max_value=0.50, step=0.01, label="Corner radius (macOS tile)")
78
+
79
+ with bs.Row():
80
+ bs.Label("Preview Dark Theme", grow=True)
81
+ bs.Switch(None, signal=dark_sig)
82
+
83
+ with bs.Row(gap=6, grow=True, grow_items=True, vertical_items="bottom"):
84
+ bs.Button("Export…", accent="primary", on_click=lambda: _export())
85
+ bs.Button("Copy TOML", variant="outline", on_click=lambda: _copy_toml())
86
+
87
+
88
+ bs.Divider(orient="vertical", vertical="stretch")
89
+
90
+ # ── Preview ───────────────────────────────────────────────────────
91
+ with bs.Column(padding=16, grow=True, vertical="stretch"):
92
+ preview = bs.Grid(rows=2, columns=1, gap=10, grow=True, horizontal="stretch")
93
+
94
+
95
+ def _current_icon() -> "AppIcon":
96
+ # shape="auto" — exports glyph-only for .ico/.png, a tile for .icns.
97
+ return AppIcon(
98
+ glyph_sig() or "rocket",
99
+ background=bg_sig(),
100
+ foreground=fg_sig(),
101
+ radius=radius_sig(),
102
+ )
103
+
104
+ def _colors_ok() -> bool:
105
+ return _is_hex(bg_sig()) and _is_hex(fg_sig())
106
+
107
+ def _win_tiled(icon: "AppIcon", size: int) -> bool:
108
+ # Mirror the real shape='auto' .ico: glyph-only at small title-bar frames,
109
+ # a tile at taskbar sizes and up — so the preview matches the export.
110
+ return icon._tiled_for_size(size, suffix=".ico")
111
+
112
+ def _build_preview() -> None:
113
+ # Build the preview skeleton ONCE; updates swap images in place so the
114
+ # screen never flashes from tearing down and rebuilding the widgets.
115
+ icon = _current_icon()
116
+ win_imgs: list = []
117
+
118
+ with bs.Column(parent=preview, row=0, column=0, gap=4, horizontal_items="center"):
119
+ bs.Label("Windows / Linux", font="caption", accent="muted")
120
+ with bs.Row(gap=12, vertical_items="bottom"):
121
+ for size in _PREVIEW_SIZES:
122
+ tiled = _win_tiled(icon, size)
123
+ with bs.Column(gap=2):
124
+ img = bs.Label(image=icon.to_image(size, tiled=tiled))
125
+ bs.Label(f"{size}px", font="caption", accent="muted", vertical="bottom")
126
+ win_imgs.append((size, tiled, img))
127
+
128
+ with bs.Column(parent=preview, row=1, column=0, gap=4, horizontal_items="center"):
129
+ bs.Label("macOS", font="caption", accent="muted")
130
+ mac_img = bs.Label(image=icon.to_image(_MACOS_SIZE, tiled=True))
131
+
132
+ state["win_imgs"] = win_imgs
133
+ state["mac_img"] = mac_img
134
+
135
+ def _colors_ready() -> bool:
136
+ if not _colors_ok():
137
+ status_sig.set("Colors must be hex values (e.g. #0d6efd).")
138
+ return False
139
+ status_sig.set("Adjust the settings — the preview updates live.")
140
+ return True
141
+
142
+ def _update_tiles() -> None:
143
+ # Foreground and corner radius only affect TILED frames — the macOS tile
144
+ # and the larger Windows/Linux frames. The small glyph-only frames are
145
+ # unchanged, so they are left in place.
146
+ if state.get("rendering") or not _colors_ready():
147
+ return
148
+ state["rendering"] = True
149
+ try:
150
+ icon = _current_icon()
151
+ for size, tiled, img in state["win_imgs"]:
152
+ if tiled:
153
+ img.image = icon.to_image(size, tiled=True)
154
+ state["mac_img"].image = icon.to_image(_MACOS_SIZE, tiled=True)
155
+ finally:
156
+ state["rendering"] = False
157
+
158
+ def _update_all() -> None:
159
+ # Guard against re-entrancy: a scheduled update can fire inside a modal
160
+ # dialog's nested event loop (e.g. while the color picker is open), which
161
+ # could otherwise overlap an in-progress swap.
162
+ if state.get("rendering") or not _colors_ready():
163
+ return
164
+ state["rendering"] = True
165
+ try:
166
+ icon = _current_icon()
167
+ # Swap each image in place — no widget rebuild, no flicker. Each frame
168
+ # keeps the shape it was built with (small = glyph-only, large = tile).
169
+ for size, tiled, img in state["win_imgs"]:
170
+ img.image = icon.to_image(size, tiled=tiled)
171
+ state["mac_img"].image = icon.to_image(_MACOS_SIZE, tiled=True)
172
+ finally:
173
+ state["rendering"] = False
174
+
175
+ def _schedule(key: str, fn) -> None:
176
+ # Coalesce rapid signal changes (e.g. dragging the radius slider) into
177
+ # one update via the framework scheduler (cancelable Job, lifetime-tied).
178
+ job = state["jobs"].get(key)
179
+ if job is not None:
180
+ job.cancel()
181
+ state["jobs"][key] = app.schedule.delay(80, fn)
182
+
183
+ def _pick(target: "bs.Signal") -> None:
184
+ choice = bs.ask_color()
185
+ if choice is not None:
186
+ target.set(choice.hex)
187
+
188
+ def _apply_theme(*_) -> None:
189
+ app.theme = "bootstrap-dark" if dark_sig() else "bootstrap-light"
190
+
191
+ def _open_picker(parent) -> None:
192
+ all_names = list_icons()
193
+ pick: dict = {"job": None, "grid": None}
194
+
195
+ with bs.Window(title="Choose an icon", size=(500, 500), parent=parent) as win:
196
+ query = bs.Signal("")
197
+ count = bs.Signal("")
198
+ with bs.Column(padding=12, gap=8, grow=True, horizontal="stretch"):
199
+ bs.TextField(textsignal=query, placeholder="Search icons…", horizontal="stretch")
200
+ bs.Label(textsignal=count, font="caption", accent="muted")
201
+ scroller = bs.ScrollView(grow=True, horizontal="stretch", height=430)
202
+
203
+ def _choose(name: str) -> None:
204
+ glyph_sig.set(name)
205
+ win.close()
206
+
207
+ def _rebuild_grid(*_) -> None:
208
+ if pick["grid"] is not None:
209
+ pick["grid"].destroy()
210
+ q = (query() or "").strip().lower()
211
+ matches = [n for n in all_names if q in n] if q else all_names
212
+ shown = matches[:120]
213
+ count.set(
214
+ f"{len(matches):,} icons"
215
+ + (" — showing first 120, refine to narrow" if len(matches) > 120 else "")
216
+ )
217
+ with bs.Grid(parent=scroller, columns=8, gap=2) as grid:
218
+ for name in shown:
219
+ spec: IconSpec = {"name": name, "size": 36}
220
+ bs.Button(
221
+ icon=spec,
222
+ icon_only=True,
223
+ variant="ghost",
224
+ on_click=lambda n=name: _choose(n),
225
+ )
226
+ pick["grid"] = grid
227
+
228
+ def _on_query(*_) -> None:
229
+ # Debounce search via the window's own scheduler (auto-cancels when
230
+ # the picker closes).
231
+ if pick["job"] is not None:
232
+ pick["job"].cancel()
233
+ pick["job"] = win.schedule.delay(150, _rebuild_grid)
234
+
235
+ query.subscribe(_on_query)
236
+ _rebuild_grid()
237
+ # Open beside the trigger — the window's top-left at the field's top-right.
238
+ win.show(anchor_to=parent, anchor_point="ne", window_point="nw", offset=(8, 0))
239
+
240
+ def _export() -> None:
241
+ if not _colors_ok():
242
+ status_sig.set("Fix the colors before exporting.")
243
+ return
244
+ path = bs.ask_save_file(
245
+ title="Export app icon",
246
+ default_extension=".ico",
247
+ initial_file=f"{glyph_sig() or 'app'}.ico",
248
+ file_types=[
249
+ ("Windows icon", "*.ico"),
250
+ ("macOS icon", "*.icns"),
251
+ ("PNG image", "*.png"),
252
+ ],
253
+ )
254
+ if not path:
255
+ return
256
+ try:
257
+ _current_icon().save(path)
258
+ status_sig.set(f"Exported to {path}")
259
+ except Exception as exc: # pragma: no cover - surfaced to the user
260
+ status_sig.set(f"Could not export: {exc}")
261
+
262
+ def _copy_toml() -> None:
263
+ snippet = (
264
+ "[build.icon]\n"
265
+ f'glyph = "{glyph_sig() or "rocket"}"\n'
266
+ f'background = "{bg_sig()}"\n'
267
+ f'foreground = "{fg_sig()}"\n'
268
+ f"radius = {round(radius_sig(), 3)}\n"
269
+ )
270
+ set_clipboard(snippet)
271
+ status_sig.set("Copied [build.icon] snippet to the clipboard.")
272
+
273
+ _build_preview()
274
+ # Glyph and background affect every frame; foreground and corner radius affect
275
+ # only the tiled frames (the macOS tile and the larger Windows/Linux frames),
276
+ # so those re-render just the tiles.
277
+ glyph_sig.subscribe(lambda *_: _schedule("all", _update_all))
278
+ bg_sig.subscribe(lambda *_: _schedule("all", _update_all))
279
+ fg_sig.subscribe(lambda *_: _schedule("tiles", _update_tiles))
280
+ radius_sig.subscribe(lambda *_: _schedule("tiles", _update_tiles))
281
+ dark_sig.subscribe(_apply_theme)
282
+ app.run()
283
+
284
+ if __name__ == '__main__':
285
+ run_appicon()
bootstack/cli/build.py ADDED
@@ -0,0 +1,115 @@
1
+ """bootstack build command - Build the application for distribution."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import shutil
7
+ import subprocess
8
+ import sys
9
+ from pathlib import Path
10
+
11
+ from bootstack.cli.config import TtkbConfig, find_config
12
+
13
+
14
+ def add_parser(subparsers: argparse._SubParsersAction) -> None:
15
+ """Add the 'build' subcommand parser."""
16
+ parser = subparsers.add_parser(
17
+ "build",
18
+ help="Build the application for distribution",
19
+ description="Build the application using the configured build backend.",
20
+ )
21
+ parser.add_argument(
22
+ "--clean",
23
+ action="store_true",
24
+ help="Clean build artifacts before building",
25
+ )
26
+ parser.set_defaults(func=run_build)
27
+
28
+
29
+ def run_build(args: argparse.Namespace) -> None:
30
+ """Execute the build command."""
31
+ # Find project root
32
+ config_path = find_config()
33
+ if config_path is None:
34
+ print("Error: No bootstack.toml found in current directory or parents.")
35
+ print("Run 'bootstack start <appname>' to create a new project first.")
36
+ return
37
+
38
+ project_root = config_path.parent
39
+ config = TtkbConfig.load(config_path)
40
+
41
+ # Check if project has been promoted
42
+ if config.build is None:
43
+ print("Error: Project has not been promoted for building.")
44
+ print("Run 'bootstack promote --pyinstaller' first.")
45
+ return
46
+
47
+ backend = config.build.backend
48
+
49
+ if backend == "pyinstaller":
50
+ _build_pyinstaller(config, project_root, clean=args.clean)
51
+ else:
52
+ print(f"Error: Unknown build backend '{backend}'")
53
+ return
54
+
55
+
56
+ def _build_pyinstaller(
57
+ config: TtkbConfig,
58
+ project_root: Path,
59
+ clean: bool = False,
60
+ ) -> None:
61
+ """Build using PyInstaller."""
62
+ # Check if PyInstaller is installed
63
+ try:
64
+ import PyInstaller # noqa: F401
65
+ except ImportError:
66
+ print("Error: PyInstaller is not installed.")
67
+ print("Install it with: pip install pyinstaller")
68
+ return
69
+
70
+ spec_path = project_root / "build" / "pyinstaller" / "app.spec"
71
+ if not spec_path.exists():
72
+ print("Error: PyInstaller spec file not found.")
73
+ print("Run 'bootstack promote --pyinstaller' to generate it.")
74
+ return
75
+
76
+ # Clean if requested
77
+ if clean:
78
+ print("Cleaning build artifacts...")
79
+ dist_dir = project_root / "dist"
80
+ build_dir = project_root / "build" / "pyinstaller" / "build"
81
+ if dist_dir.exists():
82
+ shutil.rmtree(dist_dir)
83
+ if build_dir.exists():
84
+ shutil.rmtree(build_dir)
85
+
86
+ print(f"Building '{config.app.name}' with PyInstaller...")
87
+ print()
88
+
89
+ # Run PyInstaller
90
+ cmd = [
91
+ sys.executable,
92
+ "-m",
93
+ "PyInstaller",
94
+ str(spec_path),
95
+ "--distpath",
96
+ str(project_root / "dist"),
97
+ "--workpath",
98
+ str(project_root / "build" / "pyinstaller" / "build"),
99
+ "--noconfirm",
100
+ ]
101
+
102
+ try:
103
+ result = subprocess.run(cmd, cwd=str(project_root))
104
+ if result.returncode == 0:
105
+ print()
106
+ print("Build completed successfully!")
107
+ print()
108
+ print(f"Output: {project_root / 'dist' / config.app.name}")
109
+ else:
110
+ print()
111
+ print("Build failed.")
112
+ sys.exit(result.returncode)
113
+ except KeyboardInterrupt:
114
+ print("\nBuild interrupted.")
115
+ sys.exit(1)