meltygui 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 (372) hide show
  1. meltygui/__init__.py +107 -0
  2. meltygui/accounts/__init__.py +0 -0
  3. meltygui/accounts/internet_accounts.py +1355 -0
  4. meltygui/chat/__init__.py +91 -0
  5. meltygui/chat/activity.py +75 -0
  6. meltygui/chat/backends.py +36 -0
  7. meltygui/chat/chat_interface.py +732 -0
  8. meltygui/chat/chat_proxy.py +352 -0
  9. meltygui/chat/codex_proxy.py +592 -0
  10. meltygui/chat/codex_settings.py +100 -0
  11. meltygui/chat/codex_transport.py +60 -0
  12. meltygui/chat/command_parser.py +204 -0
  13. meltygui/chat/images.py +227 -0
  14. meltygui/chat/messages.py +417 -0
  15. meltygui/chat/metadata.py +139 -0
  16. meltygui/chat/writer_locks.py +64 -0
  17. meltygui/code/__init__.py +0 -0
  18. meltygui/code/basic_converters.py +533 -0
  19. meltygui/code/chain_converters.py +2111 -0
  20. meltygui/code/code_checks.py +2209 -0
  21. meltygui/code/core_syntax.py +1430 -0
  22. meltygui/code/file_converters.py +1933 -0
  23. meltygui/code/fileref.py +702 -0
  24. meltygui/code/hotswap_guard.py +144 -0
  25. meltygui/code/libcst_conversion.py +9724 -0
  26. meltygui/code/live_instrument.py +392 -0
  27. meltygui/code/live_view.py +2490 -0
  28. meltygui/code/melty_scan.py +2684 -0
  29. meltygui/code/new_codecs.py +1255 -0
  30. meltygui/code/new_converters.py +3017 -0
  31. meltygui/code/project_code.py +278 -0
  32. meltygui/code/source_context.py +63 -0
  33. meltygui/code/symbol_roster.py +1588 -0
  34. meltygui/code/syntax_check.py +34 -0
  35. meltygui/code/syntax_check_worker.py +114 -0
  36. meltygui/completion/__init__.py +0 -0
  37. meltygui/completion/fim.py +1232 -0
  38. meltygui/completion/fim_context.py +481 -0
  39. meltygui/completion/providers/__init__.py +0 -0
  40. meltygui/completion/providers/anthropic_oauth.py +446 -0
  41. meltygui/completion/providers/anthropic_requests.py +69 -0
  42. meltygui/completion/providers/claude.py +203 -0
  43. meltygui/completion/providers/claude_usage.py +499 -0
  44. meltygui/completion/providers/codex_accounts.py +180 -0
  45. meltygui/completion/providers/copilot.py +617 -0
  46. meltygui/completion/providers/oauth_popup.py +220 -0
  47. meltygui/completion/providers/ollama.py +320 -0
  48. meltygui/completion/providers/profiles.py +23 -0
  49. meltygui/core/README.md +88 -0
  50. meltygui/core/__init__.py +1 -0
  51. meltygui/core/automation/__init__.py +1 -0
  52. meltygui/core/automation/action_core.py +153 -0
  53. meltygui/core/automation/collection_action.py +45 -0
  54. meltygui/core/automation/mcp_eval.py +167 -0
  55. meltygui/core/automation/mcp_hotswap.py +107 -0
  56. meltygui/core/automation/mcp_query.py +552 -0
  57. meltygui/core/automation/mcp_server.py +657 -0
  58. meltygui/core/automation/orchestration_core.py +2636 -0
  59. meltygui/core/automation/query_core.py +124 -0
  60. meltygui/core/automation/search_core.py +26 -0
  61. meltygui/core/automation/selector_core.py +340 -0
  62. meltygui/core/automation/value_core.py +1752 -0
  63. meltygui/core/cache/__init__.py +1 -0
  64. meltygui/core/cache/cache_diagnostics.py +0 -0
  65. meltygui/core/cache/invalidation_decoration.py +153 -0
  66. meltygui/core/cache/invalidation_tracker.py +43 -0
  67. meltygui/core/cache/tile_cache.py +5968 -0
  68. meltygui/core/conversion/__init__.py +1 -0
  69. meltygui/core/conversion/bubbling.py +599 -0
  70. meltygui/core/conversion/cache_tree.py +188 -0
  71. meltygui/core/conversion/chain.py +113 -0
  72. meltygui/core/conversion/converter_register.py +145 -0
  73. meltygui/core/conversion/data_decoration.py +67 -0
  74. meltygui/core/conversion/dict_conversion.py +1815 -0
  75. meltygui/core/conversion/dict_conversion_util.py +177 -0
  76. meltygui/core/conversion/dynamic_obj.py +89 -0
  77. meltygui/core/conversion/graph_compare.py +183 -0
  78. meltygui/core/conversion/load_save_v2.py +1032 -0
  79. meltygui/core/conversion/missing_saved_class.py +39 -0
  80. meltygui/core/conversion/path_finder.py +606 -0
  81. meltygui/core/conversion/render_host.py +1083 -0
  82. meltygui/core/core_render.py +6537 -0
  83. meltygui/core/definition_hotswap.py +231 -0
  84. meltygui/core/diagnostics/__init__.py +1 -0
  85. meltygui/core/diagnostics/attribute_churn.py +38 -0
  86. meltygui/core/diagnostics/fps_counter.py +39 -0
  87. meltygui/core/diagnostics/gpu_frame_timer.py +103 -0
  88. meltygui/core/diagnostics/inspection_core.py +169 -0
  89. meltygui/core/diagnostics/monitor_core.py +105 -0
  90. meltygui/core/diagnostics/notifications.py +706 -0
  91. meltygui/core/diagnostics/perf_trace.py +281 -0
  92. meltygui/core/diagnostics/profile_decoration.py +88 -0
  93. meltygui/core/diagnostics/resize_trace.py +62 -0
  94. meltygui/core/diagnostics/screenshot_core.py +247 -0
  95. meltygui/core/diagnostics/session_status.py +98 -0
  96. meltygui/core/diagnostics/trace_core.py +445 -0
  97. meltygui/core/files/__init__.py +1 -0
  98. meltygui/core/files/file_core.py +208 -0
  99. meltygui/core/files/file_explorer_core.py +104 -0
  100. meltygui/core/files/file_tree_core.py +198 -0
  101. meltygui/core/files/file_watch_core.py +43 -0
  102. meltygui/core/files/import_graph_core.py +43 -0
  103. meltygui/core/files/metadata_core.py +51 -0
  104. meltygui/core/graphics/__init__.py +1 -0
  105. meltygui/core/graphics/cuda_context_core.py +166 -0
  106. meltygui/core/graphics/cuda_interop_core.py +136 -0
  107. meltygui/core/graphics/cuda_kernel_core.py +91 -0
  108. meltygui/core/graphics/framebuffer_recorder.py +337 -0
  109. meltygui/core/graphics/gl_state.py +658 -0
  110. meltygui/core/graphics/lut_core.py +52 -0
  111. meltygui/core/graphics/overlay_renderer.py +984 -0
  112. meltygui/core/graphics/scene_target.py +180 -0
  113. meltygui/core/graphics/screenshot.py +439 -0
  114. meltygui/core/graphics/shader_func.py +478 -0
  115. meltygui/core/graphics/tensor_core.py +45 -0
  116. meltygui/core/graphics/text_texture.py +329 -0
  117. meltygui/core/graphics/wayland_color.py +635 -0
  118. meltygui/core/input/__init__.py +1 -0
  119. meltygui/core/input/collision.py +165 -0
  120. meltygui/core/input/drag_drop_core.py +1525 -0
  121. meltygui/core/input/hypr_left_drag.py +323 -0
  122. meltygui/core/input/input_core.py +245 -0
  123. meltygui/core/input/input_handler.py +1101 -0
  124. meltygui/core/input/mouse_cursor.py +355 -0
  125. meltygui/core/input/pynput_backend.py +1054 -0
  126. meltygui/core/input/space_mouse.py +338 -0
  127. meltygui/core/input/touchpad_backend.py +393 -0
  128. meltygui/core/input/view_selection.py +177 -0
  129. meltygui/core/layout/__init__.py +1 -0
  130. meltygui/core/layout/column_core.py +2153 -0
  131. meltygui/core/layout/cursor_core.py +161 -0
  132. meltygui/core/layout/dropdown_core.py +278 -0
  133. meltygui/core/layout/edge_constraints.py +155 -0
  134. meltygui/core/layout/grid_core.py +117 -0
  135. meltygui/core/layout/header_core.py +23 -0
  136. meltygui/core/layout/header_runtime.py +67 -0
  137. meltygui/core/layout/layout_core.py +87 -0
  138. meltygui/core/layout/tile_manager_core.py +591 -0
  139. meltygui/core/melty.py +6726 -0
  140. meltygui/core/module_map.json +896 -0
  141. meltygui/core/module_names.py +19 -0
  142. meltygui/core/rendering/__init__.py +1 -0
  143. meltygui/core/rendering/core_decoration.py +431 -0
  144. meltygui/core/rendering/core_render_helpers.py +328 -0
  145. meltygui/core/rendering/func_metadata.py +398 -0
  146. meltygui/core/rendering/mode.py +818 -0
  147. meltygui/core/rendering/mode_defaults.py +41 -0
  148. meltygui/core/rendering/modes.py +136 -0
  149. meltygui/core/rendering/parameter_core.py +1665 -0
  150. meltygui/core/rendering/render_dispatch.py +1891 -0
  151. meltygui/core/rendering/render_funcs.py +273 -0
  152. meltygui/core/rendering/shaped.py +312 -0
  153. meltygui/core/rendering/window_decoration.py +25 -0
  154. meltygui/core/runtime/__init__.py +1 -0
  155. meltygui/core/runtime/app.py +735 -0
  156. meltygui/core/runtime/app_session.py +140 -0
  157. meltygui/core/runtime/background.py +564 -0
  158. meltygui/core/runtime/extensions.py +53 -0
  159. meltygui/core/runtime/gc_manager.py +1163 -0
  160. meltygui/core/runtime/lifecycle.py +21 -0
  161. meltygui/core/runtime/paths.py +27 -0
  162. meltygui/core/runtime/settings.py +14 -0
  163. meltygui/core/runtime/singleton.py +16 -0
  164. meltygui/core/runtime/thread_safe_bool.py +24 -0
  165. meltygui/core/runtime/thread_signal.py +30 -0
  166. meltygui/core/runtime/toggles.py +3115 -0
  167. meltygui/core/services/__init__.py +1 -0
  168. meltygui/core/services/account_core.py +10 -0
  169. meltygui/core/services/chat_core.py +19 -0
  170. meltygui/core/services/claude_terminal_core.py +346 -0
  171. meltygui/core/services/terminal_core.py +458 -0
  172. meltygui/core/services/terminal_runtime.py +78 -0
  173. meltygui/core/styling/__init__.py +1 -0
  174. meltygui/core/styling/color_core.py +46 -0
  175. meltygui/core/styling/fonts.py +639 -0
  176. meltygui/core/styling/global_style.py +338 -0
  177. meltygui/core/styling/style.py +198 -0
  178. meltygui/core/styling/style_core.py +522 -0
  179. meltygui/core/styling/warm_start.py +149 -0
  180. meltygui/core/windowing/__init__.py +1 -0
  181. meltygui/core/windowing/backends/PYIMGUI_LICENSE +28 -0
  182. meltygui/core/windowing/backends/__init__.py +1 -0
  183. meltygui/core/windowing/backends/imgui_renderer.py +138 -0
  184. meltygui/core/windowing/backends/native_wayland.py +850 -0
  185. meltygui/core/windowing/backends/protocols/xdg-decoration-unstable-v1.xml +156 -0
  186. meltygui/core/windowing/backends/protocols/xdg-shell.xml +1420 -0
  187. meltygui/core/windowing/backends/wayland_protocol.py +101 -0
  188. meltygui/core/windowing/dock_core.py +182 -0
  189. meltygui/core/windowing/frame_geometry.py +42 -0
  190. meltygui/core/windowing/geometry_feed.py +864 -0
  191. meltygui/core/windowing/glfw_utils.py +1343 -0
  192. meltygui/core/windowing/os_frame.py +1552 -0
  193. meltygui/core/windowing/surface.py +643 -0
  194. meltygui/core/windowing/titlebar.py +1560 -0
  195. meltygui/core/windowing/titlebar_buttons.py +281 -0
  196. meltygui/core/windowing/wayland_move.py +932 -0
  197. meltygui/core/windowing/window_api.py +62 -0
  198. meltygui/core/windowing/window_constants.py +339 -0
  199. meltygui/core/windowing/window_visibility.py +162 -0
  200. meltygui/debug/__init__.py +0 -0
  201. meltygui/debug/app_view_utils.py +9 -0
  202. meltygui/editor/__init__.py +0 -0
  203. meltygui/editor/bash_syntax.py +30 -0
  204. meltygui/editor/code_line_fast.py +152 -0
  205. meltygui/editor/diff.py +139 -0
  206. meltygui/editor/external_changes.py +159 -0
  207. meltygui/editor/file_header.py +41 -0
  208. meltygui/editor/live_usage.py +169 -0
  209. meltygui/editor/live_view_views.py +1803 -0
  210. meltygui/editor/pending_save.py +1351 -0
  211. meltygui/editor/roster_tints.py +547 -0
  212. meltygui/editor/source_preview.py +16 -0
  213. meltygui/editor/source_tools.py +10 -0
  214. meltygui/editor/source_ui.py +70 -0
  215. meltygui/editor/spell_check.py +77 -0
  216. meltygui/editor/text_editor.py +9076 -0
  217. meltygui/editor/usage_picker.py +538 -0
  218. meltygui/events/__init__.py +0 -0
  219. meltygui/events/example.py +118 -0
  220. meltygui/examples/__init__.py +0 -0
  221. meltygui/examples/columns_demo.py +33 -0
  222. meltygui/examples/columns_window_demo.py +60 -0
  223. meltygui/examples/context_menu_demo.py +24 -0
  224. meltygui/examples/context_menu_window_demo.py +49 -0
  225. meltygui/examples/gui_playground.py +127 -0
  226. meltygui/examples/live_view_playground.py +256 -0
  227. meltygui/examples/lora.py +43 -0
  228. meltygui/examples/lora_data.py +59 -0
  229. meltygui/examples/lora_policies.py +67 -0
  230. meltygui/examples/mode_demo.py +49 -0
  231. meltygui/examples/modifies_demo.py +119 -0
  232. meltygui/examples/scalar_policies.py +60 -0
  233. meltygui/examples/style_layouts.py +149 -0
  234. meltygui/examples/tile_manager_demo.py +74 -0
  235. meltygui/examples/tint_demo.py +160 -0
  236. meltygui/examples/tint_functions.py +56 -0
  237. meltygui/examples/trace_demo.py +88 -0
  238. meltygui/examples/two_windows.py +36 -0
  239. meltygui/files/__init__.py +0 -0
  240. meltygui/files/fast_file_explorer.py +439 -0
  241. meltygui/gnome_extension/lsd-window-geometry@latent-descent/extension.js +237 -0
  242. meltygui/gnome_extension/lsd-window-geometry@latent-descent/lsd-window-geometry@latent-descent.iml +9 -0
  243. meltygui/gnome_extension/lsd-window-geometry@latent-descent/metadata.json +7 -0
  244. meltygui/graphics/__init__.py +6 -0
  245. meltygui/graphics/base.py +85 -0
  246. meltygui/graphics/examples.py +507 -0
  247. meltygui/graphics/executor.py +520 -0
  248. meltygui/graphics/filter.py +667 -0
  249. meltygui/graphics/filter.pyi +856 -0
  250. meltygui/graphics/generate_stubs.py +22 -0
  251. meltygui/graphics/registry.py +203 -0
  252. meltygui/graphics/shader_compiler.py +155 -0
  253. meltygui/graphics/shaders.py +1302 -0
  254. meltygui/graphics/stub_generator.py +250 -0
  255. meltygui/graphics/texture_manager.py +170 -0
  256. meltygui/graphics/texture_min_max.py +295 -0
  257. meltygui/hdr_color.py +757 -0
  258. meltygui/image_load.py +308 -0
  259. meltygui/model/__init__.py +1 -0
  260. meltygui/model/account_model.py +142 -0
  261. meltygui/model/camera_model.py +159 -0
  262. meltygui/model/chat_model.py +86 -0
  263. meltygui/model/code_model.py +62 -0
  264. meltygui/model/code_proxy_model.py +876 -0
  265. meltygui/model/collection_model.py +41 -0
  266. meltygui/model/color_model.py +127 -0
  267. meltygui/model/cuda_tensor_model.py +36 -0
  268. meltygui/model/cuda_texture_model.py +149 -0
  269. meltygui/model/dropdown_model.py +137 -0
  270. meltygui/model/file_metadata_model.py +73 -0
  271. meltygui/model/file_model.py +289 -0
  272. meltygui/model/format_model.py +390 -0
  273. meltygui/model/graph_model.py +98 -0
  274. meltygui/model/icon_model.py +1024 -0
  275. meltygui/model/import_graph_model.py +468 -0
  276. meltygui/model/layout_model.py +15 -0
  277. meltygui/model/lut_model.py +266 -0
  278. meltygui/model/search_model.py +173 -0
  279. meltygui/model/tensor_model.py +402 -0
  280. meltygui/model/terminal_model.py +329 -0
  281. meltygui/model/texture_model.py +146 -0
  282. meltygui/model/tile_model.py +24 -0
  283. meltygui/model/trace_model.py +198 -0
  284. meltygui/model/trace_report_model.py +146 -0
  285. meltygui/models/__init__.py +0 -0
  286. meltygui/models/file_meta.py +613 -0
  287. meltygui/models/function_console.py +184 -0
  288. meltygui/models/orchestration.py +48 -0
  289. meltygui/pbr.py +1576 -0
  290. meltygui/png_unfilter.c +49 -0
  291. meltygui/resources/JetBrainsMono-Regular.ttf +0 -0
  292. meltygui/resources/THIRD_PARTY_NOTICES.md +21 -0
  293. meltygui/resources/dejavu/DejaVuSans-Bold.ttf +0 -0
  294. meltygui/resources/dejavu/DejaVuSans-ExtraLight.ttf +0 -0
  295. meltygui/resources/dejavu/DejaVuSans.ttf +0 -0
  296. meltygui/resources/dejavu/LICENSE.txt +78 -0
  297. meltygui/resources/fontawesome-LICENSE.txt +121 -0
  298. meltygui/resources/fontawesome-webfont.ttf +0 -0
  299. meltygui/resources/hdri/studio_small_09_1k.hdr +0 -0
  300. meltygui/resources/jetbrains-weights/JetBrainsMono-Bold.ttf +0 -0
  301. meltygui/resources/jetbrains-weights/JetBrainsMono-ExtraBold.ttf +0 -0
  302. meltygui/resources/jetbrains-weights/JetBrainsMono-ExtraLight.ttf +0 -0
  303. meltygui/resources/jetbrains-weights/JetBrainsMono-Light.ttf +0 -0
  304. meltygui/resources/jetbrains-weights/JetBrainsMono-Medium.ttf +0 -0
  305. meltygui/resources/jetbrains-weights/JetBrainsMono-SemiBold.ttf +0 -0
  306. meltygui/resources/jetbrains-weights/JetBrainsMono-Thin.ttf +0 -0
  307. meltygui/resources/jetbrains-weights/OFL.txt +93 -0
  308. meltygui/resources/jetbrains-weights/README.md +2 -0
  309. meltygui/state/__init__.py +0 -0
  310. meltygui/state/account_state.py +22 -0
  311. meltygui/state/animation_state.py +97 -0
  312. meltygui/state/annotation_state.py +22 -0
  313. meltygui/state/chat_state.py +36 -0
  314. meltygui/state/code_state.py +10 -0
  315. meltygui/state/core_enums.py +59 -0
  316. meltygui/state/core_markers.py +115 -0
  317. meltygui/state/core_undo.py +1075 -0
  318. meltygui/state/file_state.py +75 -0
  319. meltygui/state/graph_state.py +26 -0
  320. meltygui/state/inspection_state.py +47 -0
  321. meltygui/state/menu_state.py +10 -0
  322. meltygui/state/model_enums.py +11 -0
  323. meltygui/state/new_core_model.py +2394 -0
  324. meltygui/state/orchestration_state.py +14 -0
  325. meltygui/state/query_state.py +24 -0
  326. meltygui/state/tensor_state.py +10 -0
  327. meltygui/state/terminal_state.py +23 -0
  328. meltygui/state/trace_state.py +32 -0
  329. meltygui/state/voxel_state.py +12 -0
  330. meltygui/text_index.py +816 -0
  331. meltygui/utils/__init__.py +0 -0
  332. meltygui/utils/jump_to_code.py +344 -0
  333. meltygui/utils/pkl_inspect.py +90 -0
  334. meltygui/utils/render_utils.py +1419 -0
  335. meltygui/view/__init__.py +1 -0
  336. meltygui/view/account_view.py +524 -0
  337. meltygui/view/action_view.py +73 -0
  338. meltygui/view/chat_decoration_view.py +112 -0
  339. meltygui/view/chat_view.py +1703 -0
  340. meltygui/view/code_view.py +2677 -0
  341. meltygui/view/collection_view.py +1185 -0
  342. meltygui/view/color_view.py +824 -0
  343. meltygui/view/control_view.py +559 -0
  344. meltygui/view/decoration_view.py +439 -0
  345. meltygui/view/diagnostic_view.py +177 -0
  346. meltygui/view/dropdown_view.py +1082 -0
  347. meltygui/view/file_view.py +1599 -0
  348. meltygui/view/graph_cuda_view.py +105 -0
  349. meltygui/view/graph_view.py +882 -0
  350. meltygui/view/header_view.py +848 -0
  351. meltygui/view/input_view.py +238 -0
  352. meltygui/view/inspection_view.py +1783 -0
  353. meltygui/view/layout_view.py +596 -0
  354. meltygui/view/lut_view.py +45 -0
  355. meltygui/view/menu_view.py +212 -0
  356. meltygui/view/orchestration_view.py +658 -0
  357. meltygui/view/query_view.py +118 -0
  358. meltygui/view/search_view.py +342 -0
  359. meltygui/view/tab_view.py +258 -0
  360. meltygui/view/tensor_view.py +430 -0
  361. meltygui/view/terminal_view.py +355 -0
  362. meltygui/view/text_view.py +8031 -0
  363. meltygui/view/texture_view.py +480 -0
  364. meltygui/view/tile_view.py +38 -0
  365. meltygui/view/trace_view.py +923 -0
  366. meltygui/view/voxel_cuda_view.py +824 -0
  367. meltygui/view/voxel_view.py +1860 -0
  368. meltygui/view/window_view.py +111 -0
  369. meltygui-0.1.0.dist-info/METADATA +143 -0
  370. meltygui-0.1.0.dist-info/RECORD +372 -0
  371. meltygui-0.1.0.dist-info/WHEEL +4 -0
  372. meltygui-0.1.0.dist-info/licenses/LICENSE +202 -0
@@ -0,0 +1,208 @@
1
+ """
2
+ Folder files — a directory tree rendered through a RenderHost.
3
+
4
+ `folder_io` is the plain stateful wrapper — it knows nothing about RenderHost.
5
+ It follows the same shape as `code_file_io` / `claude_terminals_io`:
6
+
7
+ discover() → view_func(dict) → apply() (folder_io)
8
+
9
+ except discover/apply are RECURSIVE: it reconciles a persistent nested dict
10
+ against the directory tree on disk — subfolders become nested dicts, files
11
+ become Path leaves. RenderHost wraps it so the program just sees "a dict
12
+ shaped like the folder". File CONTENT never flows through here: each Path
13
+ leaf renders via Mode.FILE_TREE → code_file_io, whose TextFileCodec owns that
14
+ file's whole-file load/edit/save round-trip — the recursion is pure structure.
15
+
16
+ The dict is mutable the way the terminals dict is: a key the user deletes
17
+ deletes its file (claude_terminals kills the tmux session, we unlink); a key
18
+ the user adds creates one (a held dict → mkdir, a held str → its contents).
19
+ A background poller re-runs discovery when the tree changes on disk (the
20
+ wrapper's body is blit-cached, so it wouldn't otherwise notice a file that
21
+ appeared/vanished with no edit to invalidate it).
22
+ """
23
+
24
+ import threading
25
+
26
+ from meltygui.core.runtime.lifecycle import module_is_live
27
+ import time
28
+ from pathlib import Path
29
+
30
+ import meltygui_imgui as imgui
31
+ from meltygui.core.melty import Melty
32
+ from meltygui.core.rendering.modes import Modes
33
+ from meltygui.view.file_view import draw_file_tree
34
+ from meltygui.view.file_view import draw_file_metadata
35
+ from meltygui.core.windowing.glfw_utils import request_render
36
+ from meltygui.core.conversion.render_host import RenderHost
37
+ from meltygui.core.core_render import render_func
38
+ from meltygui.core.rendering.window_decoration import window
39
+ from meltygui.core.rendering.core_decoration import Core
40
+
41
+ from meltygui.model.file_model import _scan
42
+ from meltygui.model.file_model import _reconcile
43
+ from meltygui.model.file_model import _file_meta
44
+ from meltygui.model.file_model import _apply_meta
45
+ from meltygui.model.file_model import _collect_meta
46
+
47
+ # Keep the original default folder when the implementation moves packages.
48
+ ROOT = Path(__file__).resolve().parents[2] / "files"
49
+ from meltygui.core.runtime.paths import application_root
50
+ TEST_FOLDER = application_root()
51
+
52
+
53
+ # ── persisted per-file metadata (tint / expanded / order ...) ─────────────────────
54
+ # The tree holds display params the framework ignores: each file dict holds
55
+ # __overrides__['__<name>__'] = {param: value}, which core_render feeds into the
56
+ # child row's view (same mechanism as '# [tint=...]' comment overrides). The
57
+ # durable copy lives in AppModel.file_meta_collection.file_meta, keyed by
58
+ # absolute path string, so it persists with the next save. folder_io syncs both
59
+ # ways every run: APPLY meta → tree __overrides__ + key order before render,
60
+ # COLLECT tree → meta after render (UI edits land in __overrides__ via
61
+ # _LazyOverrideEntry / bubbling, drag reorders land as tree key order).
62
+
63
+
64
+ # ── debug window: the persisted per-file metadata tree ──────────────────────────
65
+ @window(disable_scroll=False, use_cache=True, tint=(0.18, 0.11, 0.11))
66
+ def file_meta_debug(_, draw_state=None):
67
+ """Raw view of AppModel.file_meta_collection.file_meta — the path-keyed
68
+ params store the folder tree and the codec layer read/write (tint, order,
69
+ …). Rendered as a plain editable dict: edits land directly in the store
70
+ (bubble-free plain dicts, so a manual touch persists on the next root
71
+ save; deleting an entry clears that file's attributes)."""
72
+ meta = _file_meta()
73
+ if meta is None:
74
+ imgui.text("No app model loaded")
75
+ return
76
+ if not meta:
77
+ imgui.text("No file metadata yet")
78
+ return
79
+ return draw_file_metadata(meta)
80
+
81
+
82
+ # ── the stateful wrapper: discover -> view_func(dict) -> apply ──────────────────
83
+ # Shaped like claude_terminals_io. It does not know about RenderHost - the host
84
+ # gives it `view_func` and holds whatever dict it passes through.
85
+ @render_func(use_cache=True, selectable=False, show_bg=False)
86
+ def folder_io(input_value, draw_state, view_func=None, root=None, external_change=False, **kwargs):
87
+ # ── IN: reconcile the HELD tree IN PLACE against the disk snapshot - same
88
+ # reason as claude_terminals_io: `input_value` IS the dict the host holds
89
+ # and the @window reads; a separate store would leave it a stale copy.
90
+ # The snapshot is PER ROOT: the single shared global handed the second
91
+ # window the first root's tree - the the store saw every ROOT entry as
92
+ # "new on disk", complete with Path leaves pointing into the wrong folder.
93
+ disk = _disk_trees.get(root)
94
+ if disk is None:
95
+ disk = _disk_trees[root] = _scan(root)
96
+ store = input_value if isinstance(input_value, dict) else {}
97
+ seen = getattr(draw_state, "_seen_paths", None)
98
+ if seen is None:
99
+ seen = draw_state._seen_paths = set()
100
+ _reconcile(store, disk, root, seen)
101
+
102
+ # ── META IN: persisted per-file params → the tree's __overrides__ + key
103
+ # order. On a change (first load, or the store edited elsewhere) the cached
104
+ # rows below still hold the old capture - invalidate this subtree so they
105
+ # repaint with the fresh kwargs.
106
+ meta = _file_meta()
107
+ if meta is not None and _apply_meta(store, root, meta):
108
+ tid = getattr(draw_state, "_tile_id", None)
109
+ if tid is not None and Melty.cache is not None:
110
+ Melty.cache.invalidate_up(tid, force=True, max_depth=8)
111
+ request_render()
112
+
113
+ # ── VIEW: hand the tree to the host's view func (which materializes + renders)
114
+ edited, value = view_func(input_value=store, external_change=False, **kwargs)
115
+
116
+ # ── META OUT: UI edits landed in __overrides__ (bubbling re-ran this body);
117
+ # drag reorders changed key order. Mirror both into the persisted store.
118
+ if meta is not None:
119
+ _collect_meta(store, root, meta)
120
+
121
+ imgui.text(str(root))
122
+ return edited, value
123
+
124
+
125
+ # ── the proxy: to the program it's just a dict shaped like the folder ───────────
126
+ if "files_proxy" not in globals():
127
+ files_proxy = RenderHost(io_function=folder_io, input_value=None,
128
+ name="Folder Files", root=ROOT)
129
+ if "test_folder_proxy" not in globals():
130
+ test_folder_proxy = RenderHost(io_function=folder_io, input_value=None,
131
+ name="TestFolderProxy", root=TEST_FOLDER)
132
+
133
+ # ── per-root state: every root gets its own snapshot, window draw_state, and
134
+ # poller entry. (These were single globals once: the second window reconciled
135
+ # against the first root's snapshot and rendered ROOT's files.)
136
+ _disk_trees = globals().get("_disk_trees", {}) # root -> the poller's nested snapshot ({name: Path | dict})
137
+ _window_dss = globals().get("_window_dss", {}) # root -> that root's @window draw_state, stashed each render
138
+ _proxies = globals().get("_proxies", {ROOT: files_proxy, TEST_FOLDER: test_folder_proxy}) # poller targets
139
+ _poller_running = globals().get("_poller_running", False)
140
+
141
+
142
+ @window(input_value=files_proxy, tint=(0.36, 0.46, 0.59), disable_scroll=False, mode=Modes.WINDOW)
143
+ @render_func(show_bg=True, use_cache=True, shadow=True, selectable=False)
144
+ def draw_folder_files(input_value, draw_state, **kwargs):
145
+ _draw_tree(input_value, draw_state, ROOT)
146
+ return False, None
147
+
148
+
149
+ @window(input_value=test_folder_proxy, tint=(0.84, 0.933, 0.98), bg_offset=4, disable_scroll=False, mode=Modes.WINDOW)
150
+ @render_func(show_bg=False, use_cache=True, selectable=False)
151
+ def draw_test_folders(input_value, draw_state, **kwargs):
152
+ _draw_tree(input_value, draw_state, TEST_FOLDER)
153
+ return False, None
154
+
155
+
156
+ def folder_proxy(root, name):
157
+ """A RenderHost over folder_io for `root`, registered with the poller —
158
+ the reusable entry point for other views (e.g. playground.file_tree)."""
159
+ proxy = _proxies.get(root)
160
+ if proxy is None:
161
+ proxy = _proxies[root] = RenderHost(io_function=folder_io, input_value=None,
162
+ name=name, root=root)
163
+ return proxy
164
+
165
+
166
+ def watch_folder(root, draw_state):
167
+ """Per-frame from a folder window's body: start the (single, all-roots)
168
+ poller and stash this root's draw_state so a disk change re-renders it."""
169
+ global _poller_running
170
+ if not _poller_running:
171
+ threading.Thread(target=_poll_loop, daemon=True, name="folder-files-poller").start()
172
+ _poller_running = True
173
+ _window_dss[root] = draw_state
174
+
175
+
176
+ def _draw_tree(input_value, draw_state, root):
177
+ """Shared @window body: watch the root and draw the held tree."""
178
+ watch_folder(root, draw_state)
179
+
180
+ # The tree is held one LEVEL UP under value name ("value") - same as
181
+ # claude_terminals: draw_collection on the proxy itself would render the
182
+ # single {"value": tree} key, not the files.
183
+ tree = input_value.get("value") if isinstance(input_value, dict) else {}
184
+ return draw_file_tree(tree if tree is not None else {}, root=root)
185
+
186
+
187
+ # ── discovery poller: the wrappers' bodies are blit-cached, so they wouldn't
188
+ # show a file that appeared/vanished with no way to render them. One
189
+ # thread sweeps EVERY registered root; on a change to a tree, swap in the new
190
+ # snapshot AND re-render that root's @window.
191
+ def _poll_loop():
192
+ while module_is_live(globals()): # exits once script restart purges this module
193
+ if Core.melty.frame_count < 4:
194
+ time.sleep(2)
195
+ for root, proxy in list(_proxies.items()):
196
+ try:
197
+ cur = _scan(root)
198
+ if cur != _disk_trees.get(root):
199
+ _disk_trees[root] = cur
200
+ for ds in (getattr(proxy, "_wrapper_draw_state", None),
201
+ getattr(proxy, "_draw_state", None),
202
+ _window_dss.get(root)):
203
+ if ds is not None:
204
+ ds.invalidate()
205
+ request_render()
206
+ except Exception:
207
+ pass
208
+ time.sleep(1.0)
@@ -0,0 +1,104 @@
1
+ """Directory subscriptions and browser runtime diagnostics."""
2
+ import os
3
+ import sys
4
+ from meltygui.core.melty import Melty, FileWatch
5
+
6
+ # ── the directory watch ─────────────────────────────────────────────────────
7
+ # directory (str) -> the listing draw_states showing it. One FileWatch emitter per
8
+ # dir in this map; a listing moves its emitter on navigation (watch_directory)
9
+ # and the observer-thread listener posts an invalidate to the render thread.
10
+ def _existing_directory_watchers():
11
+ # One-time resource transfer when this module is first loaded by hotswap.
12
+ # Existing FileWatch callbacks and per-view state retain this same mapping.
13
+ previous_module = sys.modules.get("meltygui.files.fast_file_explorer")
14
+ if previous_module is not None:
15
+ return vars(previous_module).get("_WATCHERS", {})
16
+ return {}
17
+
18
+
19
+ _WATCHERS = globals().get("_WATCHERS")
20
+ if _WATCHERS is None:
21
+ _WATCHERS = _existing_directory_watchers()
22
+
23
+
24
+ def _on_file_event(src_path):
25
+ """FileWatch global listener (observer thread): an entry of a watched
26
+ directory changed — created, modified, moved, deleted — repaint the
27
+ listings showing that directory. Bumps nothing else; the listing's
28
+ mtime memo notices what changed."""
29
+ directory = os.path.dirname(src_path)
30
+ watchers = _WATCHERS.get(directory) or _WATCHERS.get(src_path)
31
+ if not watchers:
32
+ return
33
+
34
+ def repaint(draw_states=tuple(watchers)):
35
+ for draw_state in draw_states:
36
+ draw_state.invalidate()
37
+ Melty.post_to_render(repaint)
38
+
39
+
40
+ def watch_directory(draw_state, state, dir_key):
41
+ """Point this listing's emitter at `dir_key`: the previous directory's
42
+ emitter is retired when no other listing shows it (the inotify instance
43
+ cap is per user), the new one scheduled through FileWatch.watch_dir."""
44
+ if state._watched == dir_key:
45
+ return
46
+ if _on_file_event not in FileWatch.global_listeners:
47
+ # Hotswap-safe: an older copy of this function is replaced by itself.
48
+ FileWatch.global_listeners[:] = [f for f in FileWatch.global_listeners
49
+ if getattr(f, "__name__", "") != "_on_file_event"]
50
+ FileWatch.global_listeners.append(_on_file_event)
51
+ FileWatch.start()
52
+ previous = state._watched
53
+ if previous is not None:
54
+ holders = _WATCHERS.get(previous)
55
+ if holders is not None:
56
+ holders.discard(draw_state)
57
+ if not holders:
58
+ del _WATCHERS[previous]
59
+ FileWatch.unwatch_dir(previous)
60
+ _WATCHERS.setdefault(dir_key, set()).add(draw_state)
61
+ FileWatch.watch_dir(dir_key)
62
+ state._watched = dir_key
63
+
64
+
65
+
66
+ from weakref import WeakKeyDictionary
67
+ _browser_size_traces = globals().get("_browser_size_traces", WeakKeyDictionary())
68
+
69
+ def _trace_browser_size(stage, draw_state, **details):
70
+ """File browser size diagnostics (the nested-OS-window resize glitch):
71
+ one line per CHANGE of the view's box / content rect / the surface's
72
+ GLFW window and framebuffer size, to the bounded resize trace
73
+ (.melty cache root, resize-<pid>.log) and stderr. Never raises."""
74
+ try:
75
+ import sys
76
+ import meltygui.core.diagnostics.resize_trace as resize_trace
77
+ from meltygui import window_api as glfw
78
+ window = getattr(Melty, "glfw_window", None)
79
+ window_size = fb_size = None
80
+ if window is not None:
81
+ window_size = tuple(glfw.get_window_size(window))
82
+ fb_size = tuple(glfw.get_framebuffer_size(window))
83
+ try:
84
+ import meltygui.core.windowing.geometry_feed as geometry_feed
85
+ frame = geometry_feed._current_frame()
86
+ details["feed"] = (geometry_feed.backend(), geometry_feed._hypr_selector(),
87
+ geometry_feed.hypr_honors_geometry(),
88
+ None if frame is None else (frame.get("at"), frame.get("size")))
89
+ except Exception as error:
90
+ details["feed"] = f"error {error!r}"
91
+ stamp = (draw_state.width, draw_state.height, draw_state.abs_left, draw_state.abs_top,
92
+ window_size, fb_size, tuple(sorted(details.items())))
93
+ if _browser_size_traces.get(draw_state) == stamp:
94
+ return
95
+ _browser_size_traces[draw_state] = stamp
96
+ resize_trace.record(stage, draw_state, window_size=window_size, fb_size=fb_size,
97
+ gesture=bool(Melty.resize_gesture_live()), **details)
98
+ print(f"[{stage}] f{Melty.frame_count} view {draw_state.width}x{draw_state.height} "
99
+ f"at ({draw_state.abs_left}, {draw_state.abs_top}) window {window_size} "
100
+ f"fb {fb_size} {details}", file=sys.stderr, flush=True)
101
+ except Exception:
102
+ pass
103
+
104
+
@@ -0,0 +1,198 @@
1
+ """File tree — a general-purpose directory browser with collapsable folders.
2
+
3
+ Unlike folder_files (which materializes file CONTENT through a RenderHost),
4
+ this view is display-only: it walks the directory and draws just the names,
5
+ straight to the window draw_list — no per-row widgets, no draw_states per
6
+ file (the fast_dock.py interaction model: event params for clicks, blit
7
+ cache while idle, wrapper re-renders every frame while hovered). Click a
8
+ folder to expand/collapse it; double-click a file to open it
9
+ (FileTreeState.open_file, a stub for now).
10
+
11
+ Frame-to-frame state (which folders are expanded, selection) lives in
12
+ FileTreeState, injected by annotation the same way GLState/CodeState are.
13
+ """
14
+
15
+ import colorsys
16
+ from pathlib import Path
17
+
18
+ import meltygui_imgui as imgui
19
+ from meltygui.hdr_color import pack_color
20
+ from meltygui.hdr_color import with_alpha
21
+ from meltygui.core.melty import Melty
22
+ from meltygui.core.conversion.dict_conversion import DictConversion
23
+ from meltygui.core.rendering.modes import Modes
24
+ from meltygui.core.windowing.glfw_utils import request_render
25
+ from meltygui.core.core_render import render_func
26
+ from meltygui.core.layout.header_runtime import _brightness_clamp_fn
27
+ import meltygui.model.import_graph_model as file_graph
28
+ from meltygui.core.runtime.toggles import Toggles
29
+ from meltygui.core.files.file_core import folder_proxy
30
+ from meltygui.core.files.file_core import watch_folder
31
+ from meltygui.model.file_model import _file_meta
32
+ from meltygui.core.input.drag_drop_core import DragDrop
33
+ from meltygui.core.cache.tile_cache import add_shadow
34
+ from meltygui.core.rendering.window_decoration import window
35
+
36
+ from meltygui.core.runtime.paths import application_root
37
+
38
+
39
+ def open_file(path):
40
+ """Route `path` into the code editor (summons the editor window)."""
41
+ from meltygui.core.runtime.extensions import open_source as open_in_editor
42
+ open_in_editor(str(path))
43
+
44
+
45
+ def _children(folder):
46
+ """Visible entries, folders first, case-insensitive by name."""
47
+ try:
48
+ entries = [p for p in folder.iterdir()
49
+ if not p.name.startswith(".") and p.name != "__pycache__"]
50
+ except OSError:
51
+ return []
52
+ return sorted(entries, key=lambda p: (p.is_file(), p.name.lower()))
53
+
54
+
55
+ def _flatten(folder, expanded, depth=0, rows=None):
56
+ """The tree as drawn: one (path, depth) per visible row."""
57
+ if rows is None:
58
+ rows = []
59
+ for p in _children(folder):
60
+ rows.append((p, depth))
61
+ if p.is_dir() and str(p) in expanded:
62
+ _flatten(p, expanded, depth + 1, rows)
63
+ return rows
64
+
65
+
66
+ def _meta():
67
+ """AppModel's path → FileMeta store (None before the model exists)."""
68
+ return _file_meta()
69
+
70
+
71
+ def _tint_of(meta, path):
72
+ """The row's background tint (rgb), or None for an unpainted file — no
73
+ stored tint, or FileMeta's black-transparent default."""
74
+ from meltygui.models.file_meta import FileMeta
75
+ entry = meta.get(str(path)) if meta is not None else None
76
+ tint = FileMeta.painted_tint(entry)
77
+ return tuple(tint[:3]) if tint else None
78
+
79
+
80
+ def _ordered_children(folder, meta, position):
81
+ """`folder`'s visible entries in FILE-META ORDER: an entry's position in
82
+ the file_meta dict is its rank; entries the dict doesn't know yet trail
83
+ in the natural order (folders first, case-insensitive by name)."""
84
+ natural = _children(folder)
85
+ unknown = float("inf")
86
+ ranked = [(position.get(str(p), unknown), i, p) for i, p in enumerate(natural)]
87
+ ranked.sort(key=lambda t: (t[0], t[1]))
88
+ return [p for _r, _i, p in ranked]
89
+
90
+
91
+ def _flatten_ordered(folder, expanded, meta, position, depth=0, rows=None):
92
+ """The tree as drawn — one (path, depth) per visible row — in meta order."""
93
+ if rows is None:
94
+ rows = []
95
+ for p in _ordered_children(folder, meta, position):
96
+ rows.append((p, depth))
97
+ if p.is_dir() and str(p) in expanded:
98
+ _flatten_ordered(p, expanded, meta, position, depth + 1, rows)
99
+ return rows
100
+
101
+
102
+ def reorder_siblings(meta, siblings, dragged, insert_index):
103
+ """Move `dragged` to `insert_index` (pre-removal coordinates, the Reorder
104
+ convention) within `siblings` and write the new order into the file_meta
105
+ dict: every sibling gets an entry, and the siblings' existing SLOTS in the
106
+ dict (their key positions) are refilled in the new order, so nothing else
107
+ in the dict moves. Returns True when the order changed."""
108
+ from meltygui.models.file_meta import FileMeta
109
+ keys = [str(p) for p in siblings]
110
+ dragged_key = str(dragged)
111
+ if dragged_key not in keys:
112
+ return False
113
+ current = keys.index(dragged_key)
114
+ new_keys = list(keys)
115
+ new_keys.pop(current)
116
+ target = insert_index - 1 if current < insert_index else insert_index
117
+ target = max(0, min(target, len(new_keys)))
118
+ if target == current:
119
+ return False
120
+ new_keys.insert(target, dragged_key)
121
+ for k in keys:
122
+ if not isinstance(meta.get(k), dict):
123
+ meta[k] = FileMeta()
124
+ slots = [i for i, k in enumerate(meta) if k in set(keys)]
125
+ items = list(meta.items())
126
+ for slot, k in zip(slots, new_keys):
127
+ items[slot] = (k, meta[k])
128
+ meta.clear()
129
+ meta.update(items)
130
+ return True
131
+
132
+
133
+ from meltygui.view.file_view import render_file_tree
134
+ render_file_tree = window(initial={'width': 320, 'height': 540}, tint=(0.72, 0.79, 0.85))(render_file_tree)
135
+
136
+
137
+ def _apply_row_drop(meta, dragged, visible, insert_index, position):
138
+ """Translate a flattened-row drop into a sibling reorder. Returns True
139
+ when the file_meta order changed."""
140
+ if meta is None:
141
+ return False
142
+ parent = dragged.parent
143
+ siblings = _ordered_children(parent, meta, position)
144
+ below = visible[insert_index][0] if 0 <= insert_index < len(visible) else None
145
+ above = visible[insert_index - 1][0] if 0 < insert_index <= len(visible) else None
146
+ if below is not None and below.parent == parent:
147
+ sibling_index = siblings.index(below)
148
+ elif above is not None and above.parent == parent:
149
+ sibling_index = siblings.index(above) + 1
150
+ elif above is not None and above.is_dir() and above == parent:
151
+ sibling_index = 0 # dropped right above its own folder row
152
+ else:
153
+ return False
154
+ return reorder_siblings(meta, siblings, dragged, sibling_index)
155
+
156
+
157
+ # # ── Framework file tree ──────────────────────────────────────────────────────
158
+ # # The same directory rendered through the framework: folder_files' RenderHost
159
+ # # (folder_io) holds the {name: Path | dict} tree - background loading, diff
160
+ # # reconcile, and the change poller for free - and draw_collection renders it
161
+ # # under Mode.FILE_TREE_NAMES (view/modes.py): folders are drawn with
162
+ # # expandollapsing headers, add/delete, drag reorder - all framework - files route
163
+ # # by name to draw_file_name below, which shows just the name. Contrast with
164
+ # # the flat draw-list tree above: ~no code here, one draw_state per file item.
165
+ #
166
+ # # Disabled while diagnosing frame-time: registering the repo ROOT causes the
167
+ # # folder poller to _poll_loop rescan 143k entries (venv included) every
168
+ # # second, starving the render thread.
169
+ # # files_host = folder_proxy(ROOT, "FileTreeRoot")
170
+ #
171
+ #
172
+ # @render_func(is_render_for="PosixPath", show_bg=False, selectable=True,
173
+ # use_cache=True, is_tree=True, with_header=draw_header)
174
+ # def draw_file_name(input_value=None, draw_state=None,
175
+ # left_mouse_double_clicked=False, **kwargs):
176
+ # # The header draws the name (the dict key) and carries selection/drag -
177
+ # # the body is only the double-click → open handler.
178
+ # if left_mouse_double_clicked:
179
+ # open_file(input_value)
180
+ # return False, input_value
181
+ #
182
+ #
183
+ # # @window(input_value=files_host, tint=(0.42, 0.36, 0.54), disable_scroll=False, mode=Modes.WINDOW)
184
+ # @render_func(show_bg=True, use_cache=False, shadow=True, selectable=False)
185
+ # def render_file_tree_melty(input_value=None, draw_state=None, **kwargs):
186
+ # from meltygui.core.rendering.render_funcs import RenderFuncs
187
+ # watch_folder(ROOT, draw_state)
188
+ # # Same shape as draw_folder_files: the host holds the tree one level down
189
+ # # under "value"; a simple top-level draw_collection, and the names-only
190
+ # # mode passed to the host.
191
+ # tree = input_value.get("value") if isinstance(input_value, dict) else {}
192
+ # RenderFuncs.draw_collection(tree if tree is not None else {}, name=ROOT.name,
193
+ # show_add_delete=True, new_item_type=str, temp=True,
194
+ # width=draw_state.content_width,
195
+ # show_scroll=True, show_bg=True,
196
+ # child_kwargs={"show_bg": True, "bg_offset": -4,
197
+ # "mode": Modes.FILE_TREE_NAMES})
198
+ # return True, None
@@ -0,0 +1,43 @@
1
+ """File Watch Debug window — what the watcher and symbol index can see, now.
2
+
3
+ One row per known file, grouped by watched directory: whether its text is
4
+ baselined in Melty.code_cache (an external edit to an UNCACHED file is
5
+ invisible — nothing to diff), how many views watch it, whether it's
6
+ project-tracked (watch_project_files), whether external drift is currently
7
+ recorded for it, and the usage-symbol index status — the warmer's per-file
8
+ refs cache (fresh/stale vs disk mtime) plus how many cached span-usage
9
+ results are fresh under the current (mtime, pending-gen, index-gen)
10
+ signature. The rescan button re-runs the project walk to pick up files/dirs
11
+ created since startup.
12
+ """
13
+
14
+ import os
15
+ import sys
16
+ from collections import defaultdict
17
+ from pathlib import Path
18
+
19
+ from meltygui.core.rendering.render_funcs import RenderFuncs
20
+ from meltygui.core.core_render import render_func
21
+ from meltygui.core.rendering.window_decoration import window
22
+
23
+
24
+ def _symbol_index_view():
25
+ """Merged read-only view of the symbol index's per-file state across BOTH
26
+ module identities (src.lsd.… / lsd.… — the span/mtime stores are
27
+ sys-anchored and shared, but _index_refs_cache is module-level, so the
28
+ warmer may be filling either twin's dict)."""
29
+ refs, spans, snap, gen = {}, {}, {}, 0
30
+ for name in ("meltygui.code.libcst_conversion",
31
+ "lsd.gl_gui.view.core_conversion.libcst_conversion"):
32
+ m = sys.modules.get(name)
33
+ if m is None:
34
+ continue
35
+ refs.update(getattr(m, "_index_refs_cache", {}))
36
+ spans.update(getattr(m, "_symbol_usage_cache", {}))
37
+ snap.update(getattr(m, "_mtime_snapshot", {}))
38
+ gen = max(gen, getattr(m, "_index_generation", 0))
39
+ return refs, spans, snap, gen
40
+
41
+
42
+ from meltygui.view.file_view import file_watch_debug
43
+ file_watch_debug = window(disable_scroll=False, tint=(0.16296297311782837, 0.2611111, 0.24118687212467194))(file_watch_debug)
@@ -0,0 +1,43 @@
1
+ """Import graph — every project file as a labelled box, every import a line.
2
+
3
+ The whole `file_graph.ImportGraph` drawn straight to the window draw_list
4
+ (the file_tree / fast_dock model: no per-node widgets, event params for
5
+ gestures, blit cache while idle). The graph's layered layout
6
+ (file_graph.layout_graph: column = dependency depth, left → right, rows
7
+ ordered to keep lines short) gives the ORDER; this view sizes it in
8
+ pixels — each node is a rounded box around its file name, a column is as
9
+ wide as its widest box, rows share one pitch — so nothing overlaps, then
10
+ projects it: screen = origin + (box − centre) · fit · zoom + pan, where
11
+ zoom 1 fits the whole graph in the window.
12
+
13
+ Gestures: middle-drag pans, wheel zooms about the cursor, click a box to
14
+ select it (its importers light in the file's tint, its imports in the
15
+ washed variant, everything else fades), Esc clears, `/` resets the camera.
16
+ Box size follows USAGE (importer count, log scale) through the font scale,
17
+ so the hubs read at a glance. Shares the graph with render_file_tree
18
+ through file_graph.current(): either window's Build button serves both.
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ import colorsys
24
+ import math
25
+ from pathlib import Path
26
+
27
+ import meltygui_imgui as imgui
28
+ from meltygui.hdr_color import pack_color
29
+ from meltygui.core.melty import Melty
30
+ from meltygui.core.conversion.dict_conversion import DictConversion
31
+ from meltygui.core.runtime.toggles import Toggles
32
+ from meltygui.core.windowing.glfw_utils import request_render
33
+ from meltygui.core.core_render import render_func
34
+ from meltygui.core.rendering.window_decoration import window
35
+ from meltygui.core.layout.header_runtime import _brightness_clamp_fn
36
+ import meltygui.model.import_graph_model as file_graph
37
+ from meltygui.core.files.file_tree_core import _meta
38
+ from meltygui.core.files.file_tree_core import _tint_of
39
+ from meltygui.core.files.file_tree_core import open_file
40
+
41
+
42
+ from meltygui.view.graph_view import render_import_graph
43
+ render_import_graph = window(initial={'width': 720, 'height': 620}, tint=(0.42, 0.36, 0.54), disable_scroll=True)(render_import_graph)
@@ -0,0 +1,51 @@
1
+ import inspect
2
+ from functools import wraps
3
+ from typing import Any
4
+
5
+
6
+ def meta_preset(func, *o_args, **o_kwargs):
7
+ sig = inspect.signature(func)
8
+ params = sig.parameters
9
+ wanted_params = list(params.keys())
10
+
11
+ @wraps(func)
12
+ def wrapper(*args, **kwargs):
13
+ first_arg = args[0] if args else None
14
+
15
+ if 'for_type' in kwargs and not isinstance(first_arg, type):
16
+ def class_wrapper(cls):
17
+ inner_args = args[1:]
18
+ return wrapper(cls, *inner_args, **kwargs)
19
+ return class_wrapper
20
+
21
+ if isinstance(first_arg, type):
22
+ if 'default_value' in kwargs:
23
+ default_value = kwargs['default_value']
24
+ else:
25
+ default_value = None
26
+ for_type = kwargs.get('for_type', None)
27
+ kwargs.pop('for_type', None)
28
+ kwargs.pop('default_value', None)
29
+ args = args[1:] if len(args) > 1 else ()
30
+
31
+ retrieved_meta = func(default_value=default_value, *args, **kwargs)
32
+ if for_type is not None:
33
+ first_arg.default_meta_for = getattr(first_arg, 'default_meta_for', {})
34
+ first_arg.default_meta_for[for_type] = retrieved_meta
35
+ else:
36
+ first_arg.meta = retrieved_meta
37
+
38
+ return first_arg
39
+ else:
40
+ arg_idx = 0
41
+ # Clean up kwargs to only what the function wants
42
+ for wanted_param in wanted_params:
43
+ if wanted_param not in kwargs:
44
+ kwargs[wanted_param] = args[arg_idx] if arg_idx < len(args) else None
45
+ arg_idx += 1
46
+
47
+ retrieved_meta = func(**kwargs)
48
+ return retrieved_meta
49
+
50
+ wrapper.__meta_preset__ = True
51
+ return wrapper
@@ -0,0 +1 @@
1
+ """Shared framework graphics machinery."""