scitex 2.14.0__py3-none-any.whl → 2.15.2__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 (300) hide show
  1. scitex/__init__.py +71 -17
  2. scitex/_env_loader.py +156 -0
  3. scitex/_mcp_resources/__init__.py +37 -0
  4. scitex/_mcp_resources/_cheatsheet.py +135 -0
  5. scitex/_mcp_resources/_figrecipe.py +138 -0
  6. scitex/_mcp_resources/_formats.py +102 -0
  7. scitex/_mcp_resources/_modules.py +337 -0
  8. scitex/_mcp_resources/_session.py +149 -0
  9. scitex/_mcp_tools/__init__.py +4 -0
  10. scitex/_mcp_tools/audio.py +66 -0
  11. scitex/_mcp_tools/diagram.py +11 -95
  12. scitex/_mcp_tools/introspect.py +210 -0
  13. scitex/_mcp_tools/plt.py +260 -305
  14. scitex/_mcp_tools/scholar.py +74 -0
  15. scitex/_mcp_tools/social.py +244 -0
  16. scitex/_mcp_tools/template.py +24 -0
  17. scitex/_mcp_tools/writer.py +21 -204
  18. scitex/ai/_gen_ai/_PARAMS.py +10 -7
  19. scitex/ai/classification/reporters/_SingleClassificationReporter.py +45 -1603
  20. scitex/ai/classification/reporters/_mixins/__init__.py +36 -0
  21. scitex/ai/classification/reporters/_mixins/_constants.py +67 -0
  22. scitex/ai/classification/reporters/_mixins/_cv_summary.py +387 -0
  23. scitex/ai/classification/reporters/_mixins/_feature_importance.py +119 -0
  24. scitex/ai/classification/reporters/_mixins/_metrics.py +275 -0
  25. scitex/ai/classification/reporters/_mixins/_plotting.py +179 -0
  26. scitex/ai/classification/reporters/_mixins/_reports.py +153 -0
  27. scitex/ai/classification/reporters/_mixins/_storage.py +160 -0
  28. scitex/ai/classification/timeseries/_TimeSeriesSlidingWindowSplit.py +30 -1550
  29. scitex/ai/classification/timeseries/_sliding_window_core.py +467 -0
  30. scitex/ai/classification/timeseries/_sliding_window_plotting.py +369 -0
  31. scitex/audio/README.md +40 -36
  32. scitex/audio/__init__.py +129 -61
  33. scitex/audio/_branding.py +185 -0
  34. scitex/audio/_mcp/__init__.py +32 -0
  35. scitex/audio/_mcp/handlers.py +59 -6
  36. scitex/audio/_mcp/speak_handlers.py +238 -0
  37. scitex/audio/_relay.py +225 -0
  38. scitex/audio/_tts.py +18 -10
  39. scitex/audio/engines/base.py +17 -10
  40. scitex/audio/engines/elevenlabs_engine.py +7 -2
  41. scitex/audio/mcp_server.py +228 -75
  42. scitex/canvas/README.md +1 -1
  43. scitex/canvas/editor/_dearpygui/__init__.py +25 -0
  44. scitex/canvas/editor/_dearpygui/_editor.py +147 -0
  45. scitex/canvas/editor/_dearpygui/_handlers.py +476 -0
  46. scitex/canvas/editor/_dearpygui/_panels/__init__.py +17 -0
  47. scitex/canvas/editor/_dearpygui/_panels/_control.py +119 -0
  48. scitex/canvas/editor/_dearpygui/_panels/_element_controls.py +190 -0
  49. scitex/canvas/editor/_dearpygui/_panels/_preview.py +43 -0
  50. scitex/canvas/editor/_dearpygui/_panels/_sections.py +390 -0
  51. scitex/canvas/editor/_dearpygui/_plotting.py +187 -0
  52. scitex/canvas/editor/_dearpygui/_rendering.py +504 -0
  53. scitex/canvas/editor/_dearpygui/_selection.py +295 -0
  54. scitex/canvas/editor/_dearpygui/_state.py +93 -0
  55. scitex/canvas/editor/_dearpygui/_utils.py +61 -0
  56. scitex/canvas/editor/flask_editor/_core/__init__.py +27 -0
  57. scitex/canvas/editor/flask_editor/_core/_bbox_extraction.py +200 -0
  58. scitex/canvas/editor/flask_editor/_core/_editor.py +173 -0
  59. scitex/canvas/editor/flask_editor/_core/_export_helpers.py +353 -0
  60. scitex/canvas/editor/flask_editor/_core/_routes_basic.py +190 -0
  61. scitex/canvas/editor/flask_editor/_core/_routes_export.py +332 -0
  62. scitex/canvas/editor/flask_editor/_core/_routes_panels.py +252 -0
  63. scitex/canvas/editor/flask_editor/_core/_routes_save.py +218 -0
  64. scitex/canvas/editor/flask_editor/_core.py +25 -1684
  65. scitex/canvas/editor/flask_editor/templates/__init__.py +32 -70
  66. scitex/cli/__init__.py +38 -43
  67. scitex/cli/audio.py +76 -27
  68. scitex/cli/capture.py +13 -20
  69. scitex/cli/introspect.py +481 -0
  70. scitex/cli/main.py +200 -109
  71. scitex/cli/mcp.py +60 -34
  72. scitex/cli/plt.py +357 -0
  73. scitex/cli/repro.py +15 -8
  74. scitex/cli/resource.py +15 -8
  75. scitex/cli/scholar/__init__.py +23 -8
  76. scitex/cli/scholar/_crossref_scitex.py +296 -0
  77. scitex/cli/scholar/_fetch.py +25 -3
  78. scitex/cli/social.py +314 -0
  79. scitex/cli/stats.py +15 -8
  80. scitex/cli/template.py +129 -12
  81. scitex/cli/tex.py +15 -8
  82. scitex/cli/writer.py +132 -8
  83. scitex/cloud/__init__.py +41 -2
  84. scitex/config/README.md +1 -1
  85. scitex/config/__init__.py +16 -2
  86. scitex/config/_env_registry.py +256 -0
  87. scitex/context/__init__.py +22 -0
  88. scitex/dev/__init__.py +20 -1
  89. scitex/diagram/__init__.py +42 -19
  90. scitex/diagram/mcp_server.py +13 -125
  91. scitex/gen/__init__.py +50 -14
  92. scitex/gen/_list_packages.py +4 -4
  93. scitex/introspect/__init__.py +82 -0
  94. scitex/introspect/_call_graph.py +303 -0
  95. scitex/introspect/_class_hierarchy.py +163 -0
  96. scitex/introspect/_core.py +41 -0
  97. scitex/introspect/_docstring.py +131 -0
  98. scitex/introspect/_examples.py +113 -0
  99. scitex/introspect/_imports.py +271 -0
  100. scitex/{gen/_inspect_module.py → introspect/_list_api.py} +43 -54
  101. scitex/introspect/_mcp/__init__.py +41 -0
  102. scitex/introspect/_mcp/handlers.py +233 -0
  103. scitex/introspect/_members.py +155 -0
  104. scitex/introspect/_resolve.py +89 -0
  105. scitex/introspect/_signature.py +131 -0
  106. scitex/introspect/_source.py +80 -0
  107. scitex/introspect/_type_hints.py +172 -0
  108. scitex/io/_save.py +1 -2
  109. scitex/io/bundle/README.md +1 -1
  110. scitex/logging/_formatters.py +19 -9
  111. scitex/mcp_server.py +98 -5
  112. scitex/os/__init__.py +4 -0
  113. scitex/{gen → os}/_check_host.py +4 -5
  114. scitex/plt/__init__.py +245 -550
  115. scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin/_wrappers.py +5 -10
  116. scitex/plt/docs/EXTERNAL_PACKAGE_BRANDING.md +149 -0
  117. scitex/plt/gallery/README.md +1 -1
  118. scitex/plt/utils/_hitmap/__init__.py +82 -0
  119. scitex/plt/utils/_hitmap/_artist_extraction.py +343 -0
  120. scitex/plt/utils/_hitmap/_color_application.py +346 -0
  121. scitex/plt/utils/_hitmap/_color_conversion.py +121 -0
  122. scitex/plt/utils/_hitmap/_constants.py +40 -0
  123. scitex/plt/utils/_hitmap/_hitmap_core.py +334 -0
  124. scitex/plt/utils/_hitmap/_path_extraction.py +357 -0
  125. scitex/plt/utils/_hitmap/_query.py +113 -0
  126. scitex/plt/utils/_hitmap.py +46 -1616
  127. scitex/plt/utils/_metadata/__init__.py +80 -0
  128. scitex/plt/utils/_metadata/_artists/__init__.py +25 -0
  129. scitex/plt/utils/_metadata/_artists/_base.py +195 -0
  130. scitex/plt/utils/_metadata/_artists/_collections.py +356 -0
  131. scitex/plt/utils/_metadata/_artists/_extract.py +57 -0
  132. scitex/plt/utils/_metadata/_artists/_images.py +80 -0
  133. scitex/plt/utils/_metadata/_artists/_lines.py +261 -0
  134. scitex/plt/utils/_metadata/_artists/_patches.py +247 -0
  135. scitex/plt/utils/_metadata/_artists/_text.py +106 -0
  136. scitex/plt/utils/_metadata/_csv.py +416 -0
  137. scitex/plt/utils/_metadata/_detect.py +225 -0
  138. scitex/plt/utils/_metadata/_legend.py +127 -0
  139. scitex/plt/utils/_metadata/_rounding.py +117 -0
  140. scitex/plt/utils/_metadata/_verification.py +202 -0
  141. scitex/schema/README.md +1 -1
  142. scitex/scholar/__init__.py +8 -0
  143. scitex/scholar/_mcp/crossref_handlers.py +265 -0
  144. scitex/scholar/core/Scholar.py +63 -1700
  145. scitex/scholar/core/_mixins/__init__.py +36 -0
  146. scitex/scholar/core/_mixins/_enrichers.py +270 -0
  147. scitex/scholar/core/_mixins/_library_handlers.py +100 -0
  148. scitex/scholar/core/_mixins/_loaders.py +103 -0
  149. scitex/scholar/core/_mixins/_pdf_download.py +375 -0
  150. scitex/scholar/core/_mixins/_pipeline.py +312 -0
  151. scitex/scholar/core/_mixins/_project_handlers.py +125 -0
  152. scitex/scholar/core/_mixins/_savers.py +69 -0
  153. scitex/scholar/core/_mixins/_search.py +103 -0
  154. scitex/scholar/core/_mixins/_services.py +88 -0
  155. scitex/scholar/core/_mixins/_url_finding.py +105 -0
  156. scitex/scholar/crossref_scitex.py +367 -0
  157. scitex/scholar/docs/EXTERNAL_PACKAGE_BRANDING.md +149 -0
  158. scitex/scholar/examples/00_run_all.sh +120 -0
  159. scitex/scholar/jobs/_executors.py +27 -3
  160. scitex/scholar/pdf_download/ScholarPDFDownloader.py +38 -416
  161. scitex/scholar/pdf_download/_cli.py +154 -0
  162. scitex/scholar/pdf_download/strategies/__init__.py +11 -8
  163. scitex/scholar/pdf_download/strategies/manual_download_fallback.py +80 -3
  164. scitex/scholar/pipelines/ScholarPipelineBibTeX.py +73 -121
  165. scitex/scholar/pipelines/ScholarPipelineParallel.py +80 -138
  166. scitex/scholar/pipelines/ScholarPipelineSingle.py +43 -63
  167. scitex/scholar/pipelines/_single_steps.py +71 -36
  168. scitex/scholar/storage/_LibraryManager.py +97 -1695
  169. scitex/scholar/storage/_mixins/__init__.py +30 -0
  170. scitex/scholar/storage/_mixins/_bibtex_handlers.py +128 -0
  171. scitex/scholar/storage/_mixins/_library_operations.py +218 -0
  172. scitex/scholar/storage/_mixins/_metadata_conversion.py +226 -0
  173. scitex/scholar/storage/_mixins/_paper_saving.py +456 -0
  174. scitex/scholar/storage/_mixins/_resolution.py +376 -0
  175. scitex/scholar/storage/_mixins/_storage_helpers.py +121 -0
  176. scitex/scholar/storage/_mixins/_symlink_handlers.py +226 -0
  177. scitex/scholar/url_finder/.tmp/open_url/KNOWN_RESOLVERS.py +462 -0
  178. scitex/scholar/url_finder/.tmp/open_url/README.md +223 -0
  179. scitex/scholar/url_finder/.tmp/open_url/_DOIToURLResolver.py +694 -0
  180. scitex/scholar/url_finder/.tmp/open_url/_OpenURLResolver.py +1160 -0
  181. scitex/scholar/url_finder/.tmp/open_url/_ResolverLinkFinder.py +344 -0
  182. scitex/scholar/url_finder/.tmp/open_url/__init__.py +24 -0
  183. scitex/security/README.md +3 -3
  184. scitex/session/README.md +1 -1
  185. scitex/session/__init__.py +26 -7
  186. scitex/session/_decorator.py +1 -1
  187. scitex/sh/README.md +1 -1
  188. scitex/sh/__init__.py +7 -4
  189. scitex/social/__init__.py +155 -0
  190. scitex/social/docs/EXTERNAL_PACKAGE_BRANDING.md +149 -0
  191. scitex/stats/_mcp/_handlers/__init__.py +31 -0
  192. scitex/stats/_mcp/_handlers/_corrections.py +113 -0
  193. scitex/stats/_mcp/_handlers/_descriptive.py +78 -0
  194. scitex/stats/_mcp/_handlers/_effect_size.py +106 -0
  195. scitex/stats/_mcp/_handlers/_format.py +94 -0
  196. scitex/stats/_mcp/_handlers/_normality.py +110 -0
  197. scitex/stats/_mcp/_handlers/_posthoc.py +224 -0
  198. scitex/stats/_mcp/_handlers/_power.py +247 -0
  199. scitex/stats/_mcp/_handlers/_recommend.py +102 -0
  200. scitex/stats/_mcp/_handlers/_run_test.py +279 -0
  201. scitex/stats/_mcp/_handlers/_stars.py +48 -0
  202. scitex/stats/_mcp/handlers.py +19 -1171
  203. scitex/stats/auto/_stat_style.py +175 -0
  204. scitex/stats/auto/_style_definitions.py +411 -0
  205. scitex/stats/auto/_styles.py +22 -620
  206. scitex/stats/descriptive/__init__.py +11 -8
  207. scitex/stats/descriptive/_ci.py +39 -0
  208. scitex/stats/power/_power.py +15 -4
  209. scitex/str/__init__.py +2 -1
  210. scitex/str/_title_case.py +63 -0
  211. scitex/template/README.md +1 -1
  212. scitex/template/__init__.py +25 -10
  213. scitex/template/_code_templates.py +147 -0
  214. scitex/template/_mcp/handlers.py +81 -0
  215. scitex/template/_mcp/tool_schemas.py +55 -0
  216. scitex/template/_templates/__init__.py +51 -0
  217. scitex/template/_templates/audio.py +233 -0
  218. scitex/template/_templates/canvas.py +312 -0
  219. scitex/template/_templates/capture.py +268 -0
  220. scitex/template/_templates/config.py +43 -0
  221. scitex/template/_templates/diagram.py +294 -0
  222. scitex/template/_templates/io.py +107 -0
  223. scitex/template/_templates/module.py +53 -0
  224. scitex/template/_templates/plt.py +202 -0
  225. scitex/template/_templates/scholar.py +267 -0
  226. scitex/template/_templates/session.py +130 -0
  227. scitex/template/_templates/session_minimal.py +43 -0
  228. scitex/template/_templates/session_plot.py +67 -0
  229. scitex/template/_templates/session_stats.py +77 -0
  230. scitex/template/_templates/stats.py +323 -0
  231. scitex/template/_templates/writer.py +296 -0
  232. scitex/template/clone_writer_directory.py +5 -5
  233. scitex/ui/_backends/_email.py +10 -2
  234. scitex/ui/_backends/_webhook.py +5 -1
  235. scitex/web/_search_pubmed.py +10 -6
  236. scitex/writer/README.md +1 -1
  237. scitex/writer/_mcp/handlers.py +11 -744
  238. scitex/writer/_mcp/tool_schemas.py +5 -335
  239. scitex-2.15.2.dist-info/METADATA +648 -0
  240. {scitex-2.14.0.dist-info → scitex-2.15.2.dist-info}/RECORD +246 -150
  241. scitex/canvas/editor/flask_editor/templates/_scripts.py +0 -4933
  242. scitex/canvas/editor/flask_editor/templates/_styles.py +0 -1658
  243. scitex/dev/plt/data/mpl/PLOTTING_FUNCTIONS.yaml +0 -90
  244. scitex/dev/plt/data/mpl/PLOTTING_SIGNATURES.yaml +0 -1571
  245. scitex/dev/plt/data/mpl/PLOTTING_SIGNATURES_DETAILED.yaml +0 -6262
  246. scitex/dev/plt/data/mpl/SIGNATURES_FLATTENED.yaml +0 -1274
  247. scitex/dev/plt/data/mpl/dir_ax.txt +0 -459
  248. scitex/diagram/_compile.py +0 -312
  249. scitex/diagram/_diagram.py +0 -355
  250. scitex/diagram/_mcp/__init__.py +0 -4
  251. scitex/diagram/_mcp/handlers.py +0 -400
  252. scitex/diagram/_mcp/tool_schemas.py +0 -157
  253. scitex/diagram/_presets.py +0 -173
  254. scitex/diagram/_schema.py +0 -182
  255. scitex/diagram/_split.py +0 -278
  256. scitex/gen/_ci.py +0 -12
  257. scitex/gen/_title_case.py +0 -89
  258. scitex/plt/_mcp/__init__.py +0 -4
  259. scitex/plt/_mcp/_handlers_annotation.py +0 -102
  260. scitex/plt/_mcp/_handlers_figure.py +0 -195
  261. scitex/plt/_mcp/_handlers_plot.py +0 -252
  262. scitex/plt/_mcp/_handlers_style.py +0 -219
  263. scitex/plt/_mcp/handlers.py +0 -74
  264. scitex/plt/_mcp/tool_schemas.py +0 -497
  265. scitex/plt/mcp_server.py +0 -231
  266. scitex/scholar/data/.gitkeep +0 -0
  267. scitex/scholar/data/README.md +0 -44
  268. scitex/scholar/data/bib_files/bibliography.bib +0 -1952
  269. scitex/scholar/data/bib_files/neurovista.bib +0 -277
  270. scitex/scholar/data/bib_files/neurovista_enriched.bib +0 -441
  271. scitex/scholar/data/bib_files/neurovista_enriched_enriched.bib +0 -441
  272. scitex/scholar/data/bib_files/neurovista_processed.bib +0 -338
  273. scitex/scholar/data/bib_files/openaccess.bib +0 -89
  274. scitex/scholar/data/bib_files/pac-seizure_prediction_enriched.bib +0 -2178
  275. scitex/scholar/data/bib_files/pac.bib +0 -698
  276. scitex/scholar/data/bib_files/pac_enriched.bib +0 -1061
  277. scitex/scholar/data/bib_files/pac_processed.bib +0 -0
  278. scitex/scholar/data/bib_files/pac_titles.txt +0 -75
  279. scitex/scholar/data/bib_files/paywalled.bib +0 -98
  280. scitex/scholar/data/bib_files/related-papers-by-coauthors.bib +0 -58
  281. scitex/scholar/data/bib_files/related-papers-by-coauthors_enriched.bib +0 -87
  282. scitex/scholar/data/bib_files/seizure_prediction.bib +0 -694
  283. scitex/scholar/data/bib_files/seizure_prediction_processed.bib +0 -0
  284. scitex/scholar/data/bib_files/test_complete_enriched.bib +0 -437
  285. scitex/scholar/data/bib_files/test_final_enriched.bib +0 -437
  286. scitex/scholar/data/bib_files/test_seizure.bib +0 -46
  287. scitex/scholar/data/impact_factor/JCR_IF_2022.xlsx +0 -0
  288. scitex/scholar/data/impact_factor/JCR_IF_2024.db +0 -0
  289. scitex/scholar/data/impact_factor/JCR_IF_2024.xlsx +0 -0
  290. scitex/scholar/data/impact_factor/JCR_IF_2024_v01.db +0 -0
  291. scitex/scholar/data/impact_factor.db +0 -0
  292. scitex/scholar/examples/SUGGESTIONS.md +0 -865
  293. scitex/scholar/examples/dev.py +0 -38
  294. scitex-2.14.0.dist-info/METADATA +0 -1238
  295. /scitex/{gen → context}/_detect_environment.py +0 -0
  296. /scitex/{gen → context}/_get_notebook_path.py +0 -0
  297. /scitex/{gen/_shell.py → sh/_shell_legacy.py} +0 -0
  298. {scitex-2.14.0.dist-info → scitex-2.15.2.dist-info}/WHEEL +0 -0
  299. {scitex-2.14.0.dist-info → scitex-2.15.2.dist-info}/entry_points.txt +0 -0
  300. {scitex-2.14.0.dist-info → scitex-2.15.2.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,190 @@
1
+ #!/usr/bin/env python3
2
+ # Timestamp: "2026-01-24 (ywatanabe)"
3
+ # File: /home/ywatanabe/proj/scitex-python/src/scitex/canvas/editor/_dearpygui/_panels/_element_controls.py
4
+
5
+ """
6
+ Element-specific control groups for DearPyGui editor.
7
+
8
+ Creates control groups for trace, text, axis, and legend elements.
9
+ """
10
+
11
+ from typing import TYPE_CHECKING, Callable
12
+
13
+ if TYPE_CHECKING:
14
+ from .._state import EditorState
15
+
16
+
17
+ def create_trace_controls(
18
+ state: "EditorState", dpg, on_trace_property_change: Callable
19
+ ) -> None:
20
+ """Create trace-specific controls."""
21
+ with dpg.group(tag="trace_controls_group", show=False):
22
+ dpg.add_input_text(
23
+ label="Label",
24
+ tag="trace_label_input",
25
+ callback=lambda s, a: on_trace_property_change(state, dpg),
26
+ on_enter=True,
27
+ width=200,
28
+ )
29
+ dpg.add_color_edit(
30
+ label="Color",
31
+ tag="trace_color_picker",
32
+ callback=lambda s, a: on_trace_property_change(state, dpg),
33
+ no_alpha=True,
34
+ width=200,
35
+ )
36
+ dpg.add_slider_float(
37
+ label="Line Width",
38
+ tag="trace_linewidth_slider",
39
+ default_value=1.0,
40
+ min_value=0.1,
41
+ max_value=5.0,
42
+ callback=lambda s, a: on_trace_property_change(state, dpg),
43
+ width=200,
44
+ )
45
+ dpg.add_combo(
46
+ label="Line Style",
47
+ items=["-", "--", "-.", ":", ""],
48
+ default_value="-",
49
+ tag="trace_linestyle_combo",
50
+ callback=lambda s, a: on_trace_property_change(state, dpg),
51
+ width=100,
52
+ )
53
+ dpg.add_combo(
54
+ label="Marker",
55
+ items=["", "o", "s", "^", "v", "D", "x", "+", "*"],
56
+ default_value="",
57
+ tag="trace_marker_combo",
58
+ callback=lambda s, a: on_trace_property_change(state, dpg),
59
+ width=100,
60
+ )
61
+ dpg.add_slider_float(
62
+ label="Marker Size",
63
+ tag="trace_markersize_slider",
64
+ default_value=6.0,
65
+ min_value=1.0,
66
+ max_value=20.0,
67
+ callback=lambda s, a: on_trace_property_change(state, dpg),
68
+ width=200,
69
+ )
70
+
71
+
72
+ def create_text_controls(
73
+ state: "EditorState", dpg, on_text_element_change: Callable
74
+ ) -> None:
75
+ """Create text element controls."""
76
+ with dpg.group(tag="text_controls_group", show=False):
77
+ dpg.add_input_text(
78
+ label="Text",
79
+ tag="element_text_input",
80
+ callback=lambda s, a: on_text_element_change(state, dpg),
81
+ on_enter=True,
82
+ width=200,
83
+ )
84
+ dpg.add_slider_int(
85
+ label="Font Size",
86
+ tag="element_fontsize_slider",
87
+ default_value=8,
88
+ min_value=4,
89
+ max_value=24,
90
+ callback=lambda s, a: on_text_element_change(state, dpg),
91
+ width=200,
92
+ )
93
+ dpg.add_color_edit(
94
+ label="Color",
95
+ tag="element_text_color",
96
+ callback=lambda s, a: on_text_element_change(state, dpg),
97
+ no_alpha=True,
98
+ default_value=[0, 0, 0],
99
+ width=200,
100
+ )
101
+
102
+
103
+ def create_axis_controls(
104
+ state: "EditorState", dpg, on_axis_element_change: Callable
105
+ ) -> None:
106
+ """Create axis element controls."""
107
+ with dpg.group(tag="axis_controls_group", show=False):
108
+ dpg.add_slider_float(
109
+ label="Line Width (mm)",
110
+ tag="axis_linewidth_slider",
111
+ default_value=0.2,
112
+ min_value=0.05,
113
+ max_value=1.0,
114
+ callback=lambda s, a: on_axis_element_change(state, dpg),
115
+ width=200,
116
+ )
117
+ dpg.add_slider_float(
118
+ label="Tick Length (mm)",
119
+ tag="axis_tick_length_slider",
120
+ default_value=0.8,
121
+ min_value=0.2,
122
+ max_value=3.0,
123
+ callback=lambda s, a: on_axis_element_change(state, dpg),
124
+ width=200,
125
+ )
126
+ dpg.add_slider_int(
127
+ label="Tick Font Size",
128
+ tag="axis_tick_fontsize_slider",
129
+ default_value=7,
130
+ min_value=4,
131
+ max_value=16,
132
+ callback=lambda s, a: on_axis_element_change(state, dpg),
133
+ width=200,
134
+ )
135
+ dpg.add_checkbox(
136
+ label="Show Spine",
137
+ tag="axis_show_spine_checkbox",
138
+ default_value=True,
139
+ callback=lambda s, a: on_axis_element_change(state, dpg),
140
+ )
141
+
142
+
143
+ def create_legend_controls(
144
+ state: "EditorState", dpg, on_legend_element_change: Callable
145
+ ) -> None:
146
+ """Create legend controls."""
147
+ with dpg.group(tag="legend_controls_group", show=False):
148
+ dpg.add_checkbox(
149
+ label="Visible",
150
+ tag="legend_visible_edit",
151
+ default_value=True,
152
+ callback=lambda s, a: on_legend_element_change(state, dpg),
153
+ )
154
+ dpg.add_checkbox(
155
+ label="Show Frame",
156
+ tag="legend_frameon_edit",
157
+ default_value=False,
158
+ callback=lambda s, a: on_legend_element_change(state, dpg),
159
+ )
160
+ dpg.add_combo(
161
+ label="Position",
162
+ items=[
163
+ "best",
164
+ "upper right",
165
+ "upper left",
166
+ "lower right",
167
+ "lower left",
168
+ "center right",
169
+ "center left",
170
+ "upper center",
171
+ "lower center",
172
+ "center",
173
+ ],
174
+ default_value="best",
175
+ tag="legend_loc_edit",
176
+ callback=lambda s, a: on_legend_element_change(state, dpg),
177
+ width=150,
178
+ )
179
+ dpg.add_slider_int(
180
+ label="Font Size",
181
+ tag="legend_fontsize_edit",
182
+ default_value=6,
183
+ min_value=4,
184
+ max_value=14,
185
+ callback=lambda s, a: on_legend_element_change(state, dpg),
186
+ width=200,
187
+ )
188
+
189
+
190
+ # EOF
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env python3
2
+ # Timestamp: "2026-01-24 (ywatanabe)"
3
+ # File: /home/ywatanabe/proj/scitex-python/src/scitex/canvas/editor/_dearpygui/_panels/_preview.py
4
+
5
+ """
6
+ Preview panel creation for DearPyGui editor.
7
+ """
8
+
9
+ from typing import TYPE_CHECKING
10
+
11
+ if TYPE_CHECKING:
12
+ from .._state import EditorState
13
+
14
+
15
+ def create_preview_panel(state: "EditorState", dpg) -> None:
16
+ """Create the preview panel with figure image, click handler, and hover detection."""
17
+ from .._handlers import on_preview_click, on_preview_hover
18
+
19
+ with dpg.child_window(width=900, height=-1, tag="preview_panel"):
20
+ dpg.add_text(
21
+ "Figure Preview (click to select, hover to highlight)",
22
+ color=(100, 200, 100),
23
+ )
24
+ dpg.add_separator()
25
+
26
+ # Image display with click and move handlers
27
+ with dpg.handler_registry(tag="preview_handler"):
28
+ dpg.add_mouse_click_handler(
29
+ callback=lambda s, a: on_preview_click(state, dpg, a)
30
+ )
31
+ dpg.add_mouse_move_handler(
32
+ callback=lambda s, a: on_preview_hover(state, dpg, a)
33
+ )
34
+
35
+ dpg.add_image("preview_texture", tag="preview_image")
36
+
37
+ dpg.add_separator()
38
+ dpg.add_text("", tag="hover_text", color=(150, 200, 150))
39
+ dpg.add_text("", tag="status_text", color=(150, 150, 150))
40
+ dpg.add_text("", tag="selection_text", color=(200, 200, 100))
41
+
42
+
43
+ # EOF
@@ -0,0 +1,390 @@
1
+ #!/usr/bin/env python3
2
+ # Timestamp: "2026-01-24 (ywatanabe)"
3
+ # File: /home/ywatanabe/proj/scitex-python/src/scitex/canvas/editor/_dearpygui/_panels/_sections.py
4
+
5
+ """
6
+ Control panel section creators for DearPyGui editor.
7
+
8
+ Each function creates a collapsible section with related controls.
9
+ """
10
+
11
+ from typing import TYPE_CHECKING, Callable
12
+
13
+ if TYPE_CHECKING:
14
+ from .._state import EditorState
15
+
16
+
17
+ def create_labels_section(state: "EditorState", dpg, o: dict, on_value_change) -> None:
18
+ """Create labels section."""
19
+ with dpg.collapsing_header(label="Labels", default_open=True):
20
+ dpg.add_input_text(
21
+ label="Title",
22
+ default_value=o.get("title", ""),
23
+ tag="title_input",
24
+ callback=lambda s, a: on_value_change(state, dpg),
25
+ on_enter=True,
26
+ width=250,
27
+ )
28
+ dpg.add_input_text(
29
+ label="X Label",
30
+ default_value=o.get("xlabel", ""),
31
+ tag="xlabel_input",
32
+ callback=lambda s, a: on_value_change(state, dpg),
33
+ on_enter=True,
34
+ width=250,
35
+ )
36
+ dpg.add_input_text(
37
+ label="Y Label",
38
+ default_value=o.get("ylabel", ""),
39
+ tag="ylabel_input",
40
+ callback=lambda s, a: on_value_change(state, dpg),
41
+ on_enter=True,
42
+ width=250,
43
+ )
44
+
45
+
46
+ def create_axis_limits_section(
47
+ state: "EditorState", dpg, o: dict, on_apply_limits
48
+ ) -> None:
49
+ """Create axis limits section."""
50
+ with dpg.collapsing_header(label="Axis Limits", default_open=False):
51
+ with dpg.group(horizontal=True):
52
+ xlim = o.get("xlim", [0, 1])
53
+ dpg.add_input_float(
54
+ label="X Min",
55
+ default_value=xlim[0] if xlim else 0,
56
+ tag="xmin_input",
57
+ width=100,
58
+ )
59
+ dpg.add_input_float(
60
+ label="X Max",
61
+ default_value=xlim[1] if xlim else 1,
62
+ tag="xmax_input",
63
+ width=100,
64
+ )
65
+ with dpg.group(horizontal=True):
66
+ ylim = o.get("ylim", [0, 1])
67
+ dpg.add_input_float(
68
+ label="Y Min",
69
+ default_value=ylim[0] if ylim else 0,
70
+ tag="ymin_input",
71
+ width=100,
72
+ )
73
+ dpg.add_input_float(
74
+ label="Y Max",
75
+ default_value=ylim[1] if ylim else 1,
76
+ tag="ymax_input",
77
+ width=100,
78
+ )
79
+ dpg.add_button(
80
+ label="Apply Limits",
81
+ callback=lambda: on_apply_limits(state, dpg),
82
+ width=150,
83
+ )
84
+
85
+
86
+ def create_line_style_section(
87
+ state: "EditorState", dpg, o: dict, on_value_change
88
+ ) -> None:
89
+ """Create line style section."""
90
+ with dpg.collapsing_header(label="Line Style", default_open=True):
91
+ dpg.add_slider_float(
92
+ label="Line Width (pt)",
93
+ default_value=o.get("linewidth", 1.0),
94
+ min_value=0.1,
95
+ max_value=5.0,
96
+ tag="linewidth_slider",
97
+ callback=lambda s, a: on_value_change(state, dpg),
98
+ width=200,
99
+ )
100
+
101
+
102
+ def create_font_settings_section(
103
+ state: "EditorState", dpg, o: dict, on_value_change
104
+ ) -> None:
105
+ """Create font settings section."""
106
+ with dpg.collapsing_header(label="Font Settings", default_open=False):
107
+ dpg.add_slider_int(
108
+ label="Title Font Size",
109
+ default_value=o.get("title_fontsize", 8),
110
+ min_value=6,
111
+ max_value=20,
112
+ tag="title_fontsize_slider",
113
+ callback=lambda s, a: on_value_change(state, dpg),
114
+ width=200,
115
+ )
116
+ dpg.add_slider_int(
117
+ label="Axis Font Size",
118
+ default_value=o.get("axis_fontsize", 7),
119
+ min_value=6,
120
+ max_value=16,
121
+ tag="axis_fontsize_slider",
122
+ callback=lambda s, a: on_value_change(state, dpg),
123
+ width=200,
124
+ )
125
+ dpg.add_slider_int(
126
+ label="Tick Font Size",
127
+ default_value=o.get("tick_fontsize", 7),
128
+ min_value=6,
129
+ max_value=16,
130
+ tag="tick_fontsize_slider",
131
+ callback=lambda s, a: on_value_change(state, dpg),
132
+ width=200,
133
+ )
134
+ dpg.add_slider_int(
135
+ label="Legend Font Size",
136
+ default_value=o.get("legend_fontsize", 6),
137
+ min_value=4,
138
+ max_value=14,
139
+ tag="legend_fontsize_slider",
140
+ callback=lambda s, a: on_value_change(state, dpg),
141
+ width=200,
142
+ )
143
+
144
+
145
+ def create_tick_settings_section(
146
+ state: "EditorState", dpg, o: dict, on_value_change
147
+ ) -> None:
148
+ """Create tick settings section."""
149
+ with dpg.collapsing_header(label="Tick Settings", default_open=False):
150
+ dpg.add_slider_int(
151
+ label="N Ticks",
152
+ default_value=o.get("n_ticks", 4),
153
+ min_value=2,
154
+ max_value=10,
155
+ tag="n_ticks_slider",
156
+ callback=lambda s, a: on_value_change(state, dpg),
157
+ width=200,
158
+ )
159
+ dpg.add_slider_float(
160
+ label="Tick Length (mm)",
161
+ default_value=o.get("tick_length", 0.8),
162
+ min_value=0.2,
163
+ max_value=3.0,
164
+ tag="tick_length_slider",
165
+ callback=lambda s, a: on_value_change(state, dpg),
166
+ width=200,
167
+ )
168
+ dpg.add_slider_float(
169
+ label="Tick Width (mm)",
170
+ default_value=o.get("tick_width", 0.2),
171
+ min_value=0.05,
172
+ max_value=1.0,
173
+ tag="tick_width_slider",
174
+ callback=lambda s, a: on_value_change(state, dpg),
175
+ width=200,
176
+ )
177
+ dpg.add_combo(
178
+ label="Tick Direction",
179
+ items=["out", "in", "inout"],
180
+ default_value=o.get("tick_direction", "out"),
181
+ tag="tick_direction_combo",
182
+ callback=lambda s, a: on_value_change(state, dpg),
183
+ width=150,
184
+ )
185
+
186
+
187
+ def create_style_section(state: "EditorState", dpg, o: dict, on_value_change) -> None:
188
+ """Create style section."""
189
+ with dpg.collapsing_header(label="Style", default_open=True):
190
+ dpg.add_checkbox(
191
+ label="Show Grid",
192
+ default_value=o.get("grid", False),
193
+ tag="grid_checkbox",
194
+ callback=lambda s, a: on_value_change(state, dpg),
195
+ )
196
+ dpg.add_checkbox(
197
+ label="Hide Top Spine",
198
+ default_value=o.get("hide_top_spine", True),
199
+ tag="hide_top_spine_checkbox",
200
+ callback=lambda s, a: on_value_change(state, dpg),
201
+ )
202
+ dpg.add_checkbox(
203
+ label="Hide Right Spine",
204
+ default_value=o.get("hide_right_spine", True),
205
+ tag="hide_right_spine_checkbox",
206
+ callback=lambda s, a: on_value_change(state, dpg),
207
+ )
208
+ dpg.add_checkbox(
209
+ label="Transparent Background",
210
+ default_value=o.get("transparent", True),
211
+ tag="transparent_checkbox",
212
+ callback=lambda s, a: on_value_change(state, dpg),
213
+ )
214
+ dpg.add_slider_float(
215
+ label="Axis Width (mm)",
216
+ default_value=o.get("axis_width", 0.2),
217
+ min_value=0.05,
218
+ max_value=1.0,
219
+ tag="axis_width_slider",
220
+ callback=lambda s, a: on_value_change(state, dpg),
221
+ width=200,
222
+ )
223
+
224
+
225
+ def create_legend_section(state: "EditorState", dpg, o: dict, on_value_change) -> None:
226
+ """Create legend section."""
227
+ with dpg.collapsing_header(label="Legend", default_open=False):
228
+ dpg.add_checkbox(
229
+ label="Show Legend",
230
+ default_value=o.get("legend_visible", True),
231
+ tag="legend_visible_checkbox",
232
+ callback=lambda s, a: on_value_change(state, dpg),
233
+ )
234
+ dpg.add_checkbox(
235
+ label="Show Frame",
236
+ default_value=o.get("legend_frameon", False),
237
+ tag="legend_frameon_checkbox",
238
+ callback=lambda s, a: on_value_change(state, dpg),
239
+ )
240
+ dpg.add_combo(
241
+ label="Position",
242
+ items=[
243
+ "best",
244
+ "upper right",
245
+ "upper left",
246
+ "lower right",
247
+ "lower left",
248
+ "center right",
249
+ "center left",
250
+ "upper center",
251
+ "lower center",
252
+ "center",
253
+ ],
254
+ default_value=o.get("legend_loc", "best"),
255
+ tag="legend_loc_combo",
256
+ callback=lambda s, a: on_value_change(state, dpg),
257
+ width=150,
258
+ )
259
+
260
+
261
+ def create_dimensions_section(
262
+ state: "EditorState", dpg, o: dict, on_value_change
263
+ ) -> None:
264
+ """Create dimensions section."""
265
+ with dpg.collapsing_header(label="Dimensions", default_open=False):
266
+ fig_size = o.get("fig_size", [3.15, 2.68])
267
+ with dpg.group(horizontal=True):
268
+ dpg.add_input_float(
269
+ label="Width (in)",
270
+ default_value=fig_size[0],
271
+ tag="fig_width_input",
272
+ width=100,
273
+ )
274
+ dpg.add_input_float(
275
+ label="Height (in)",
276
+ default_value=fig_size[1],
277
+ tag="fig_height_input",
278
+ width=100,
279
+ )
280
+ dpg.add_slider_int(
281
+ label="DPI",
282
+ default_value=o.get("dpi", 300),
283
+ min_value=72,
284
+ max_value=600,
285
+ tag="dpi_slider",
286
+ callback=lambda s, a: on_value_change(state, dpg),
287
+ width=200,
288
+ )
289
+
290
+
291
+ def create_annotations_section(
292
+ state: "EditorState", dpg, on_add_annotation, on_remove_annotation
293
+ ) -> None:
294
+ """Create annotations section."""
295
+ with dpg.collapsing_header(label="Annotations", default_open=False):
296
+ dpg.add_input_text(
297
+ label="Text",
298
+ tag="annot_text_input",
299
+ width=200,
300
+ )
301
+ with dpg.group(horizontal=True):
302
+ dpg.add_input_float(
303
+ label="X",
304
+ default_value=0.5,
305
+ tag="annot_x_input",
306
+ width=80,
307
+ )
308
+ dpg.add_input_float(
309
+ label="Y",
310
+ default_value=0.5,
311
+ tag="annot_y_input",
312
+ width=80,
313
+ )
314
+ dpg.add_button(
315
+ label="Add Annotation",
316
+ callback=lambda: on_add_annotation(state, dpg),
317
+ width=150,
318
+ )
319
+ dpg.add_listbox(
320
+ label="",
321
+ items=[],
322
+ tag="annotations_listbox",
323
+ num_items=4,
324
+ width=250,
325
+ )
326
+ dpg.add_button(
327
+ label="Remove Selected",
328
+ callback=lambda: on_remove_annotation(state, dpg),
329
+ width=150,
330
+ )
331
+
332
+
333
+ def create_selected_element_section(
334
+ state: "EditorState",
335
+ dpg,
336
+ get_all_element_labels: Callable,
337
+ on_element_selected: Callable,
338
+ on_trace_property_change: Callable,
339
+ on_text_element_change: Callable,
340
+ on_axis_element_change: Callable,
341
+ on_legend_element_change: Callable,
342
+ deselect_element: Callable,
343
+ ) -> None:
344
+ """Create selected element section."""
345
+ from ._element_controls import (
346
+ create_axis_controls,
347
+ create_legend_controls,
348
+ create_text_controls,
349
+ create_trace_controls,
350
+ )
351
+
352
+ with dpg.collapsing_header(
353
+ label="Selected Element",
354
+ default_open=True,
355
+ tag="selected_element_header",
356
+ ):
357
+ dpg.add_text(
358
+ "Click on preview to select elements",
359
+ tag="element_hint_text",
360
+ color=(150, 150, 150),
361
+ )
362
+ dpg.add_combo(
363
+ label="Element",
364
+ items=get_all_element_labels(state),
365
+ tag="element_selector_combo",
366
+ callback=lambda s, a: on_element_selected(state, dpg, a),
367
+ width=200,
368
+ )
369
+ dpg.add_separator()
370
+
371
+ # Trace-specific controls (shown when trace selected)
372
+ create_trace_controls(state, dpg, on_trace_property_change)
373
+
374
+ # Text element controls (title, xlabel, ylabel)
375
+ create_text_controls(state, dpg, on_text_element_change)
376
+
377
+ # Axis element controls (xaxis, yaxis)
378
+ create_axis_controls(state, dpg, on_axis_element_change)
379
+
380
+ # Legend controls
381
+ create_legend_controls(state, dpg, on_legend_element_change)
382
+
383
+ dpg.add_button(
384
+ label="Deselect",
385
+ callback=lambda: deselect_element(state, dpg),
386
+ width=100,
387
+ )
388
+
389
+
390
+ # EOF