vispy 0.15.0__cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.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.

Potentially problematic release.


This version of vispy might be problematic. Click here for more details.

Files changed (521) hide show
  1. vispy/__init__.py +33 -0
  2. vispy/app/__init__.py +15 -0
  3. vispy/app/_default_app.py +76 -0
  4. vispy/app/_detect_eventloop.py +148 -0
  5. vispy/app/application.py +263 -0
  6. vispy/app/backends/__init__.py +52 -0
  7. vispy/app/backends/_egl.py +264 -0
  8. vispy/app/backends/_glfw.py +513 -0
  9. vispy/app/backends/_jupyter_rfb.py +278 -0
  10. vispy/app/backends/_offscreen_util.py +121 -0
  11. vispy/app/backends/_osmesa.py +235 -0
  12. vispy/app/backends/_pyglet.py +451 -0
  13. vispy/app/backends/_pyqt4.py +36 -0
  14. vispy/app/backends/_pyqt5.py +36 -0
  15. vispy/app/backends/_pyqt6.py +40 -0
  16. vispy/app/backends/_pyside.py +37 -0
  17. vispy/app/backends/_pyside2.py +52 -0
  18. vispy/app/backends/_pyside6.py +53 -0
  19. vispy/app/backends/_qt.py +1003 -0
  20. vispy/app/backends/_sdl2.py +444 -0
  21. vispy/app/backends/_template.py +244 -0
  22. vispy/app/backends/_test.py +8 -0
  23. vispy/app/backends/_tk.py +800 -0
  24. vispy/app/backends/_wx.py +476 -0
  25. vispy/app/backends/tests/__init__.py +0 -0
  26. vispy/app/backends/tests/test_offscreen_util.py +52 -0
  27. vispy/app/backends/tests/test_rfb.py +77 -0
  28. vispy/app/base.py +294 -0
  29. vispy/app/canvas.py +828 -0
  30. vispy/app/qt.py +92 -0
  31. vispy/app/tests/__init__.py +0 -0
  32. vispy/app/tests/qt-designer.ui +58 -0
  33. vispy/app/tests/test_app.py +442 -0
  34. vispy/app/tests/test_backends.py +164 -0
  35. vispy/app/tests/test_canvas.py +122 -0
  36. vispy/app/tests/test_context.py +92 -0
  37. vispy/app/tests/test_qt.py +47 -0
  38. vispy/app/tests/test_simultaneous.py +134 -0
  39. vispy/app/timer.py +174 -0
  40. vispy/color/__init__.py +17 -0
  41. vispy/color/_color_dict.py +193 -0
  42. vispy/color/color_array.py +447 -0
  43. vispy/color/color_space.py +181 -0
  44. vispy/color/colormap.py +1213 -0
  45. vispy/color/tests/__init__.py +0 -0
  46. vispy/color/tests/test_color.py +378 -0
  47. vispy/conftest.py +12 -0
  48. vispy/ext/__init__.py +0 -0
  49. vispy/ext/cocoapy.py +1522 -0
  50. vispy/ext/cubehelix.py +138 -0
  51. vispy/ext/egl.py +375 -0
  52. vispy/ext/fontconfig.py +118 -0
  53. vispy/ext/gdi32plus.py +206 -0
  54. vispy/ext/osmesa.py +105 -0
  55. vispy/geometry/__init__.py +23 -0
  56. vispy/geometry/_triangulation_debugger.py +171 -0
  57. vispy/geometry/calculations.py +162 -0
  58. vispy/geometry/curves.py +399 -0
  59. vispy/geometry/generation.py +643 -0
  60. vispy/geometry/isocurve.py +175 -0
  61. vispy/geometry/isosurface.py +465 -0
  62. vispy/geometry/meshdata.py +700 -0
  63. vispy/geometry/normals.py +78 -0
  64. vispy/geometry/parametric.py +56 -0
  65. vispy/geometry/polygon.py +137 -0
  66. vispy/geometry/rect.py +210 -0
  67. vispy/geometry/tests/__init__.py +0 -0
  68. vispy/geometry/tests/test_calculations.py +23 -0
  69. vispy/geometry/tests/test_generation.py +56 -0
  70. vispy/geometry/tests/test_meshdata.py +106 -0
  71. vispy/geometry/tests/test_triangulation.py +594 -0
  72. vispy/geometry/torusknot.py +142 -0
  73. vispy/geometry/triangulation.py +876 -0
  74. vispy/gloo/__init__.py +56 -0
  75. vispy/gloo/buffer.py +505 -0
  76. vispy/gloo/context.py +272 -0
  77. vispy/gloo/framebuffer.py +257 -0
  78. vispy/gloo/gl/__init__.py +234 -0
  79. vispy/gloo/gl/_constants.py +332 -0
  80. vispy/gloo/gl/_es2.py +986 -0
  81. vispy/gloo/gl/_gl2.py +1365 -0
  82. vispy/gloo/gl/_proxy.py +499 -0
  83. vispy/gloo/gl/_pyopengl2.py +362 -0
  84. vispy/gloo/gl/dummy.py +24 -0
  85. vispy/gloo/gl/es2.py +62 -0
  86. vispy/gloo/gl/gl2.py +98 -0
  87. vispy/gloo/gl/glplus.py +168 -0
  88. vispy/gloo/gl/pyopengl2.py +97 -0
  89. vispy/gloo/gl/tests/__init__.py +0 -0
  90. vispy/gloo/gl/tests/test_basics.py +282 -0
  91. vispy/gloo/gl/tests/test_functionality.py +568 -0
  92. vispy/gloo/gl/tests/test_names.py +246 -0
  93. vispy/gloo/gl/tests/test_use.py +71 -0
  94. vispy/gloo/glir.py +1824 -0
  95. vispy/gloo/globject.py +101 -0
  96. vispy/gloo/preprocessor.py +67 -0
  97. vispy/gloo/program.py +543 -0
  98. vispy/gloo/tests/__init__.py +0 -0
  99. vispy/gloo/tests/test_buffer.py +558 -0
  100. vispy/gloo/tests/test_context.py +119 -0
  101. vispy/gloo/tests/test_framebuffer.py +195 -0
  102. vispy/gloo/tests/test_glir.py +307 -0
  103. vispy/gloo/tests/test_globject.py +35 -0
  104. vispy/gloo/tests/test_program.py +302 -0
  105. vispy/gloo/tests/test_texture.py +732 -0
  106. vispy/gloo/tests/test_use_gloo.py +187 -0
  107. vispy/gloo/tests/test_util.py +60 -0
  108. vispy/gloo/tests/test_wrappers.py +261 -0
  109. vispy/gloo/texture.py +1046 -0
  110. vispy/gloo/util.py +129 -0
  111. vispy/gloo/wrappers.py +762 -0
  112. vispy/glsl/__init__.py +42 -0
  113. vispy/glsl/antialias/antialias.glsl +7 -0
  114. vispy/glsl/antialias/cap-butt.glsl +31 -0
  115. vispy/glsl/antialias/cap-round.glsl +29 -0
  116. vispy/glsl/antialias/cap-square.glsl +30 -0
  117. vispy/glsl/antialias/cap-triangle-in.glsl +30 -0
  118. vispy/glsl/antialias/cap-triangle-out.glsl +30 -0
  119. vispy/glsl/antialias/cap.glsl +67 -0
  120. vispy/glsl/antialias/caps.glsl +67 -0
  121. vispy/glsl/antialias/filled.glsl +50 -0
  122. vispy/glsl/antialias/outline.glsl +40 -0
  123. vispy/glsl/antialias/stroke.glsl +43 -0
  124. vispy/glsl/arrowheads/angle.glsl +99 -0
  125. vispy/glsl/arrowheads/arrowheads.frag +60 -0
  126. vispy/glsl/arrowheads/arrowheads.glsl +12 -0
  127. vispy/glsl/arrowheads/arrowheads.vert +83 -0
  128. vispy/glsl/arrowheads/curved.glsl +48 -0
  129. vispy/glsl/arrowheads/inhibitor.glsl +26 -0
  130. vispy/glsl/arrowheads/stealth.glsl +46 -0
  131. vispy/glsl/arrowheads/triangle.glsl +97 -0
  132. vispy/glsl/arrowheads/util.glsl +13 -0
  133. vispy/glsl/arrows/angle-30.glsl +12 -0
  134. vispy/glsl/arrows/angle-60.glsl +12 -0
  135. vispy/glsl/arrows/angle-90.glsl +12 -0
  136. vispy/glsl/arrows/arrow.frag +39 -0
  137. vispy/glsl/arrows/arrow.vert +49 -0
  138. vispy/glsl/arrows/arrows.glsl +17 -0
  139. vispy/glsl/arrows/common.glsl +187 -0
  140. vispy/glsl/arrows/curved.glsl +63 -0
  141. vispy/glsl/arrows/stealth.glsl +50 -0
  142. vispy/glsl/arrows/triangle-30.glsl +12 -0
  143. vispy/glsl/arrows/triangle-60.glsl +12 -0
  144. vispy/glsl/arrows/triangle-90.glsl +12 -0
  145. vispy/glsl/arrows/util.glsl +98 -0
  146. vispy/glsl/build_spatial_filters.py +660 -0
  147. vispy/glsl/collections/agg-fast-path.frag +20 -0
  148. vispy/glsl/collections/agg-fast-path.vert +78 -0
  149. vispy/glsl/collections/agg-glyph.frag +60 -0
  150. vispy/glsl/collections/agg-glyph.vert +33 -0
  151. vispy/glsl/collections/agg-marker.frag +35 -0
  152. vispy/glsl/collections/agg-marker.vert +48 -0
  153. vispy/glsl/collections/agg-path.frag +55 -0
  154. vispy/glsl/collections/agg-path.vert +166 -0
  155. vispy/glsl/collections/agg-point.frag +21 -0
  156. vispy/glsl/collections/agg-point.vert +35 -0
  157. vispy/glsl/collections/agg-segment.frag +32 -0
  158. vispy/glsl/collections/agg-segment.vert +75 -0
  159. vispy/glsl/collections/marker.frag +38 -0
  160. vispy/glsl/collections/marker.vert +48 -0
  161. vispy/glsl/collections/raw-path.frag +15 -0
  162. vispy/glsl/collections/raw-path.vert +24 -0
  163. vispy/glsl/collections/raw-point.frag +14 -0
  164. vispy/glsl/collections/raw-point.vert +31 -0
  165. vispy/glsl/collections/raw-segment.frag +18 -0
  166. vispy/glsl/collections/raw-segment.vert +26 -0
  167. vispy/glsl/collections/raw-triangle.frag +13 -0
  168. vispy/glsl/collections/raw-triangle.vert +26 -0
  169. vispy/glsl/collections/sdf-glyph-ticks.vert +69 -0
  170. vispy/glsl/collections/sdf-glyph.frag +80 -0
  171. vispy/glsl/collections/sdf-glyph.vert +59 -0
  172. vispy/glsl/collections/tick-labels.vert +71 -0
  173. vispy/glsl/colormaps/autumn.glsl +20 -0
  174. vispy/glsl/colormaps/blues.glsl +20 -0
  175. vispy/glsl/colormaps/color-space.glsl +17 -0
  176. vispy/glsl/colormaps/colormaps.glsl +24 -0
  177. vispy/glsl/colormaps/cool.glsl +20 -0
  178. vispy/glsl/colormaps/fire.glsl +21 -0
  179. vispy/glsl/colormaps/gray.glsl +20 -0
  180. vispy/glsl/colormaps/greens.glsl +20 -0
  181. vispy/glsl/colormaps/hot.glsl +22 -0
  182. vispy/glsl/colormaps/ice.glsl +20 -0
  183. vispy/glsl/colormaps/icefire.glsl +23 -0
  184. vispy/glsl/colormaps/parse.py +40 -0
  185. vispy/glsl/colormaps/reds.glsl +20 -0
  186. vispy/glsl/colormaps/spring.glsl +20 -0
  187. vispy/glsl/colormaps/summer.glsl +20 -0
  188. vispy/glsl/colormaps/user.glsl +22 -0
  189. vispy/glsl/colormaps/util.glsl +41 -0
  190. vispy/glsl/colormaps/wheel.glsl +21 -0
  191. vispy/glsl/colormaps/winter.glsl +20 -0
  192. vispy/glsl/lines/agg.frag +320 -0
  193. vispy/glsl/lines/agg.vert +241 -0
  194. vispy/glsl/markers/arrow.glsl +12 -0
  195. vispy/glsl/markers/asterisk.glsl +16 -0
  196. vispy/glsl/markers/chevron.glsl +14 -0
  197. vispy/glsl/markers/clover.glsl +20 -0
  198. vispy/glsl/markers/club.glsl +31 -0
  199. vispy/glsl/markers/cross.glsl +17 -0
  200. vispy/glsl/markers/diamond.glsl +12 -0
  201. vispy/glsl/markers/disc.glsl +9 -0
  202. vispy/glsl/markers/ellipse.glsl +67 -0
  203. vispy/glsl/markers/hbar.glsl +9 -0
  204. vispy/glsl/markers/heart.glsl +15 -0
  205. vispy/glsl/markers/infinity.glsl +15 -0
  206. vispy/glsl/markers/marker-sdf.frag +74 -0
  207. vispy/glsl/markers/marker-sdf.vert +41 -0
  208. vispy/glsl/markers/marker.frag +36 -0
  209. vispy/glsl/markers/marker.vert +46 -0
  210. vispy/glsl/markers/markers.glsl +24 -0
  211. vispy/glsl/markers/pin.glsl +18 -0
  212. vispy/glsl/markers/ring.glsl +11 -0
  213. vispy/glsl/markers/spade.glsl +28 -0
  214. vispy/glsl/markers/square.glsl +10 -0
  215. vispy/glsl/markers/tag.glsl +11 -0
  216. vispy/glsl/markers/triangle.glsl +14 -0
  217. vispy/glsl/markers/vbar.glsl +9 -0
  218. vispy/glsl/math/circle-through-2-points.glsl +30 -0
  219. vispy/glsl/math/constants.glsl +48 -0
  220. vispy/glsl/math/double.glsl +114 -0
  221. vispy/glsl/math/functions.glsl +20 -0
  222. vispy/glsl/math/point-to-line-distance.glsl +31 -0
  223. vispy/glsl/math/point-to-line-projection.glsl +29 -0
  224. vispy/glsl/math/signed-line-distance.glsl +27 -0
  225. vispy/glsl/math/signed-segment-distance.glsl +30 -0
  226. vispy/glsl/misc/regular-grid.frag +244 -0
  227. vispy/glsl/misc/spatial-filters.frag +1407 -0
  228. vispy/glsl/misc/viewport-NDC.glsl +20 -0
  229. vispy/glsl/transforms/azimuthal-equal-area.glsl +32 -0
  230. vispy/glsl/transforms/azimuthal-equidistant.glsl +38 -0
  231. vispy/glsl/transforms/hammer.glsl +44 -0
  232. vispy/glsl/transforms/identity.glsl +6 -0
  233. vispy/glsl/transforms/identity_forward.glsl +23 -0
  234. vispy/glsl/transforms/identity_inverse.glsl +23 -0
  235. vispy/glsl/transforms/linear-scale.glsl +127 -0
  236. vispy/glsl/transforms/log-scale.glsl +126 -0
  237. vispy/glsl/transforms/mercator-transverse-forward.glsl +40 -0
  238. vispy/glsl/transforms/mercator-transverse-inverse.glsl +40 -0
  239. vispy/glsl/transforms/panzoom.glsl +10 -0
  240. vispy/glsl/transforms/polar.glsl +41 -0
  241. vispy/glsl/transforms/position.glsl +44 -0
  242. vispy/glsl/transforms/power-scale.glsl +139 -0
  243. vispy/glsl/transforms/projection.glsl +7 -0
  244. vispy/glsl/transforms/pvm.glsl +13 -0
  245. vispy/glsl/transforms/rotate.glsl +45 -0
  246. vispy/glsl/transforms/trackball.glsl +15 -0
  247. vispy/glsl/transforms/translate.glsl +35 -0
  248. vispy/glsl/transforms/transverse_mercator.glsl +38 -0
  249. vispy/glsl/transforms/viewport-clipping.glsl +14 -0
  250. vispy/glsl/transforms/viewport-transform.glsl +16 -0
  251. vispy/glsl/transforms/viewport.glsl +50 -0
  252. vispy/glsl/transforms/x.glsl +24 -0
  253. vispy/glsl/transforms/y.glsl +19 -0
  254. vispy/glsl/transforms/z.glsl +14 -0
  255. vispy/io/__init__.py +20 -0
  256. vispy/io/_data/spatial-filters.npy +0 -0
  257. vispy/io/datasets.py +94 -0
  258. vispy/io/image.py +231 -0
  259. vispy/io/mesh.py +122 -0
  260. vispy/io/stl.py +167 -0
  261. vispy/io/tests/__init__.py +0 -0
  262. vispy/io/tests/test_image.py +47 -0
  263. vispy/io/tests/test_io.py +121 -0
  264. vispy/io/wavefront.py +350 -0
  265. vispy/plot/__init__.py +36 -0
  266. vispy/plot/fig.py +58 -0
  267. vispy/plot/plotwidget.py +522 -0
  268. vispy/plot/tests/__init__.py +0 -0
  269. vispy/plot/tests/test_plot.py +46 -0
  270. vispy/scene/__init__.py +43 -0
  271. vispy/scene/cameras/__init__.py +27 -0
  272. vispy/scene/cameras/_base.py +38 -0
  273. vispy/scene/cameras/arcball.py +105 -0
  274. vispy/scene/cameras/base_camera.py +551 -0
  275. vispy/scene/cameras/fly.py +474 -0
  276. vispy/scene/cameras/magnify.py +163 -0
  277. vispy/scene/cameras/panzoom.py +311 -0
  278. vispy/scene/cameras/perspective.py +338 -0
  279. vispy/scene/cameras/tests/__init__.py +0 -0
  280. vispy/scene/cameras/tests/test_cameras.py +27 -0
  281. vispy/scene/cameras/tests/test_link.py +53 -0
  282. vispy/scene/cameras/tests/test_perspective.py +122 -0
  283. vispy/scene/cameras/turntable.py +183 -0
  284. vispy/scene/canvas.py +639 -0
  285. vispy/scene/events.py +85 -0
  286. vispy/scene/node.py +644 -0
  287. vispy/scene/subscene.py +20 -0
  288. vispy/scene/tests/__init__.py +0 -0
  289. vispy/scene/tests/test_canvas.py +119 -0
  290. vispy/scene/tests/test_node.py +142 -0
  291. vispy/scene/tests/test_visuals.py +141 -0
  292. vispy/scene/visuals.py +276 -0
  293. vispy/scene/widgets/__init__.py +18 -0
  294. vispy/scene/widgets/anchor.py +25 -0
  295. vispy/scene/widgets/axis.py +88 -0
  296. vispy/scene/widgets/colorbar.py +176 -0
  297. vispy/scene/widgets/console.py +351 -0
  298. vispy/scene/widgets/grid.py +509 -0
  299. vispy/scene/widgets/label.py +50 -0
  300. vispy/scene/widgets/tests/__init__.py +0 -0
  301. vispy/scene/widgets/tests/test_colorbar.py +47 -0
  302. vispy/scene/widgets/viewbox.py +199 -0
  303. vispy/scene/widgets/widget.py +478 -0
  304. vispy/testing/__init__.py +51 -0
  305. vispy/testing/_runners.py +448 -0
  306. vispy/testing/_testing.py +416 -0
  307. vispy/testing/image_tester.py +494 -0
  308. vispy/testing/rendered_array_tester.py +85 -0
  309. vispy/testing/tests/__init__.py +0 -0
  310. vispy/testing/tests/test_testing.py +20 -0
  311. vispy/util/__init__.py +32 -0
  312. vispy/util/bunch.py +15 -0
  313. vispy/util/check_environment.py +57 -0
  314. vispy/util/config.py +490 -0
  315. vispy/util/dpi/__init__.py +19 -0
  316. vispy/util/dpi/_linux.py +69 -0
  317. vispy/util/dpi/_quartz.py +26 -0
  318. vispy/util/dpi/_win32.py +34 -0
  319. vispy/util/dpi/tests/__init__.py +0 -0
  320. vispy/util/dpi/tests/test_dpi.py +16 -0
  321. vispy/util/eq.py +41 -0
  322. vispy/util/event.py +774 -0
  323. vispy/util/fetching.py +276 -0
  324. vispy/util/filter.py +44 -0
  325. vispy/util/fonts/__init__.py +14 -0
  326. vispy/util/fonts/_freetype.py +73 -0
  327. vispy/util/fonts/_quartz.py +192 -0
  328. vispy/util/fonts/_triage.py +36 -0
  329. vispy/util/fonts/_vispy_fonts.py +20 -0
  330. vispy/util/fonts/_win32.py +105 -0
  331. vispy/util/fonts/data/OpenSans-Bold.ttf +0 -0
  332. vispy/util/fonts/data/OpenSans-BoldItalic.ttf +0 -0
  333. vispy/util/fonts/data/OpenSans-Italic.ttf +0 -0
  334. vispy/util/fonts/data/OpenSans-Regular.ttf +0 -0
  335. vispy/util/fonts/tests/__init__.py +0 -0
  336. vispy/util/fonts/tests/test_font.py +45 -0
  337. vispy/util/fourier.py +69 -0
  338. vispy/util/frozen.py +25 -0
  339. vispy/util/gallery_scraper.py +268 -0
  340. vispy/util/keys.py +91 -0
  341. vispy/util/logs.py +358 -0
  342. vispy/util/osmesa_gl.py +17 -0
  343. vispy/util/profiler.py +135 -0
  344. vispy/util/ptime.py +16 -0
  345. vispy/util/quaternion.py +229 -0
  346. vispy/util/svg/__init__.py +18 -0
  347. vispy/util/svg/base.py +20 -0
  348. vispy/util/svg/color.py +219 -0
  349. vispy/util/svg/element.py +51 -0
  350. vispy/util/svg/geometry.py +478 -0
  351. vispy/util/svg/group.py +66 -0
  352. vispy/util/svg/length.py +81 -0
  353. vispy/util/svg/number.py +25 -0
  354. vispy/util/svg/path.py +332 -0
  355. vispy/util/svg/shapes.py +57 -0
  356. vispy/util/svg/style.py +59 -0
  357. vispy/util/svg/svg.py +40 -0
  358. vispy/util/svg/transform.py +223 -0
  359. vispy/util/svg/transformable.py +28 -0
  360. vispy/util/svg/viewport.py +73 -0
  361. vispy/util/tests/__init__.py +0 -0
  362. vispy/util/tests/test_config.py +58 -0
  363. vispy/util/tests/test_docstring_parameters.py +123 -0
  364. vispy/util/tests/test_emitter_group.py +262 -0
  365. vispy/util/tests/test_event_emitter.py +743 -0
  366. vispy/util/tests/test_fourier.py +35 -0
  367. vispy/util/tests/test_gallery_scraper.py +112 -0
  368. vispy/util/tests/test_import.py +127 -0
  369. vispy/util/tests/test_key.py +22 -0
  370. vispy/util/tests/test_logging.py +45 -0
  371. vispy/util/tests/test_run.py +14 -0
  372. vispy/util/tests/test_transforms.py +42 -0
  373. vispy/util/tests/test_vispy.py +48 -0
  374. vispy/util/transforms.py +201 -0
  375. vispy/util/wrappers.py +155 -0
  376. vispy/version.py +21 -0
  377. vispy/visuals/__init__.py +50 -0
  378. vispy/visuals/_scalable_textures.py +487 -0
  379. vispy/visuals/axis.py +678 -0
  380. vispy/visuals/border.py +208 -0
  381. vispy/visuals/box.py +79 -0
  382. vispy/visuals/collections/__init__.py +30 -0
  383. vispy/visuals/collections/agg_fast_path_collection.py +219 -0
  384. vispy/visuals/collections/agg_path_collection.py +197 -0
  385. vispy/visuals/collections/agg_point_collection.py +52 -0
  386. vispy/visuals/collections/agg_segment_collection.py +142 -0
  387. vispy/visuals/collections/array_list.py +401 -0
  388. vispy/visuals/collections/base_collection.py +482 -0
  389. vispy/visuals/collections/collection.py +253 -0
  390. vispy/visuals/collections/path_collection.py +23 -0
  391. vispy/visuals/collections/point_collection.py +19 -0
  392. vispy/visuals/collections/polygon_collection.py +25 -0
  393. vispy/visuals/collections/raw_path_collection.py +119 -0
  394. vispy/visuals/collections/raw_point_collection.py +113 -0
  395. vispy/visuals/collections/raw_polygon_collection.py +77 -0
  396. vispy/visuals/collections/raw_segment_collection.py +112 -0
  397. vispy/visuals/collections/raw_triangle_collection.py +78 -0
  398. vispy/visuals/collections/segment_collection.py +19 -0
  399. vispy/visuals/collections/triangle_collection.py +16 -0
  400. vispy/visuals/collections/util.py +168 -0
  401. vispy/visuals/colorbar.py +699 -0
  402. vispy/visuals/cube.py +41 -0
  403. vispy/visuals/ellipse.py +162 -0
  404. vispy/visuals/filters/__init__.py +10 -0
  405. vispy/visuals/filters/base_filter.py +242 -0
  406. vispy/visuals/filters/clipper.py +60 -0
  407. vispy/visuals/filters/clipping_planes.py +122 -0
  408. vispy/visuals/filters/color.py +181 -0
  409. vispy/visuals/filters/markers.py +28 -0
  410. vispy/visuals/filters/mesh.py +801 -0
  411. vispy/visuals/filters/picking.py +60 -0
  412. vispy/visuals/filters/tests/__init__.py +3 -0
  413. vispy/visuals/filters/tests/test_primitive_picking_filters.py +70 -0
  414. vispy/visuals/filters/tests/test_wireframe_filter.py +16 -0
  415. vispy/visuals/glsl/__init__.py +1 -0
  416. vispy/visuals/glsl/antialiasing.py +133 -0
  417. vispy/visuals/glsl/color.py +63 -0
  418. vispy/visuals/graphs/__init__.py +1 -0
  419. vispy/visuals/graphs/graph.py +240 -0
  420. vispy/visuals/graphs/layouts/__init__.py +55 -0
  421. vispy/visuals/graphs/layouts/circular.py +49 -0
  422. vispy/visuals/graphs/layouts/force_directed.py +211 -0
  423. vispy/visuals/graphs/layouts/networkx_layout.py +87 -0
  424. vispy/visuals/graphs/layouts/random.py +52 -0
  425. vispy/visuals/graphs/tests/__init__.py +1 -0
  426. vispy/visuals/graphs/tests/test_layouts.py +139 -0
  427. vispy/visuals/graphs/tests/test_networkx_layout.py +47 -0
  428. vispy/visuals/graphs/util.py +120 -0
  429. vispy/visuals/gridlines.py +161 -0
  430. vispy/visuals/gridmesh.py +98 -0
  431. vispy/visuals/histogram.py +58 -0
  432. vispy/visuals/image.py +701 -0
  433. vispy/visuals/image_complex.py +130 -0
  434. vispy/visuals/infinite_line.py +199 -0
  435. vispy/visuals/instanced_mesh.py +152 -0
  436. vispy/visuals/isocurve.py +213 -0
  437. vispy/visuals/isoline.py +241 -0
  438. vispy/visuals/isosurface.py +113 -0
  439. vispy/visuals/line/__init__.py +6 -0
  440. vispy/visuals/line/arrow.py +289 -0
  441. vispy/visuals/line/dash_atlas.py +90 -0
  442. vispy/visuals/line/line.py +545 -0
  443. vispy/visuals/line_plot.py +135 -0
  444. vispy/visuals/linear_region.py +199 -0
  445. vispy/visuals/markers.py +819 -0
  446. vispy/visuals/mesh.py +373 -0
  447. vispy/visuals/mesh_normals.py +159 -0
  448. vispy/visuals/plane.py +54 -0
  449. vispy/visuals/polygon.py +145 -0
  450. vispy/visuals/rectangle.py +196 -0
  451. vispy/visuals/regular_polygon.py +56 -0
  452. vispy/visuals/scrolling_lines.py +197 -0
  453. vispy/visuals/shaders/__init__.py +17 -0
  454. vispy/visuals/shaders/compiler.py +206 -0
  455. vispy/visuals/shaders/expression.py +99 -0
  456. vispy/visuals/shaders/function.py +788 -0
  457. vispy/visuals/shaders/multiprogram.py +145 -0
  458. vispy/visuals/shaders/parsing.py +140 -0
  459. vispy/visuals/shaders/program.py +161 -0
  460. vispy/visuals/shaders/shader_object.py +162 -0
  461. vispy/visuals/shaders/tests/__init__.py +0 -0
  462. vispy/visuals/shaders/tests/test_function.py +486 -0
  463. vispy/visuals/shaders/tests/test_multiprogram.py +78 -0
  464. vispy/visuals/shaders/tests/test_parsing.py +57 -0
  465. vispy/visuals/shaders/variable.py +272 -0
  466. vispy/visuals/spectrogram.py +169 -0
  467. vispy/visuals/sphere.py +80 -0
  468. vispy/visuals/surface_plot.py +192 -0
  469. vispy/visuals/tests/__init__.py +0 -0
  470. vispy/visuals/tests/test_arrows.py +109 -0
  471. vispy/visuals/tests/test_axis.py +120 -0
  472. vispy/visuals/tests/test_collections.py +15 -0
  473. vispy/visuals/tests/test_colorbar.py +179 -0
  474. vispy/visuals/tests/test_colormap.py +97 -0
  475. vispy/visuals/tests/test_ellipse.py +122 -0
  476. vispy/visuals/tests/test_gridlines.py +30 -0
  477. vispy/visuals/tests/test_histogram.py +24 -0
  478. vispy/visuals/tests/test_image.py +392 -0
  479. vispy/visuals/tests/test_image_complex.py +36 -0
  480. vispy/visuals/tests/test_infinite_line.py +53 -0
  481. vispy/visuals/tests/test_instanced_mesh.py +50 -0
  482. vispy/visuals/tests/test_isosurface.py +22 -0
  483. vispy/visuals/tests/test_linear_region.py +152 -0
  484. vispy/visuals/tests/test_markers.py +54 -0
  485. vispy/visuals/tests/test_mesh.py +261 -0
  486. vispy/visuals/tests/test_mesh_normals.py +218 -0
  487. vispy/visuals/tests/test_polygon.py +112 -0
  488. vispy/visuals/tests/test_rectangle.py +163 -0
  489. vispy/visuals/tests/test_regular_polygon.py +111 -0
  490. vispy/visuals/tests/test_scalable_textures.py +196 -0
  491. vispy/visuals/tests/test_sdf.py +73 -0
  492. vispy/visuals/tests/test_spectrogram.py +42 -0
  493. vispy/visuals/tests/test_surface_plot.py +57 -0
  494. vispy/visuals/tests/test_text.py +95 -0
  495. vispy/visuals/tests/test_volume.py +542 -0
  496. vispy/visuals/tests/test_windbarb.py +33 -0
  497. vispy/visuals/text/__init__.py +7 -0
  498. vispy/visuals/text/_sdf_cpu.cpython-313-x86_64-linux-gnu.so +0 -0
  499. vispy/visuals/text/_sdf_cpu.pyx +112 -0
  500. vispy/visuals/text/_sdf_gpu.py +316 -0
  501. vispy/visuals/text/text.py +675 -0
  502. vispy/visuals/transforms/__init__.py +34 -0
  503. vispy/visuals/transforms/_util.py +191 -0
  504. vispy/visuals/transforms/base_transform.py +233 -0
  505. vispy/visuals/transforms/chain.py +300 -0
  506. vispy/visuals/transforms/interactive.py +98 -0
  507. vispy/visuals/transforms/linear.py +564 -0
  508. vispy/visuals/transforms/nonlinear.py +398 -0
  509. vispy/visuals/transforms/tests/__init__.py +0 -0
  510. vispy/visuals/transforms/tests/test_transforms.py +243 -0
  511. vispy/visuals/transforms/transform_system.py +339 -0
  512. vispy/visuals/tube.py +173 -0
  513. vispy/visuals/visual.py +923 -0
  514. vispy/visuals/volume.py +1366 -0
  515. vispy/visuals/windbarb.py +291 -0
  516. vispy/visuals/xyz_axis.py +34 -0
  517. vispy-0.15.0.dist-info/METADATA +243 -0
  518. vispy-0.15.0.dist-info/RECORD +521 -0
  519. vispy-0.15.0.dist-info/WHEEL +6 -0
  520. vispy-0.15.0.dist-info/licenses/LICENSE.txt +36 -0
  521. vispy-0.15.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,800 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (c) Vispy Development Team. All Rights Reserved.
3
+ # Distributed under the (new) BSD License. See LICENSE.txt for more info.
4
+
5
+ """vispy backend for Tkinter."""
6
+
7
+ from __future__ import division
8
+
9
+ from time import sleep
10
+ import warnings
11
+
12
+ from ..base import (BaseApplicationBackend, BaseCanvasBackend,
13
+ BaseTimerBackend)
14
+ from ...util import keys
15
+ from ...util.ptime import time
16
+ from ...gloo import gl
17
+
18
+ # -------------------------------------------------------------------- init ---
19
+
20
+ # Import
21
+ try:
22
+ import sys
23
+
24
+ _tk_on_linux, _tk_on_darwin, _tk_on_windows = \
25
+ map(sys.platform.startswith, ("linux", "darwin", "win"))
26
+ _tk_pyopengltk_imported = False
27
+
28
+ import tkinter as tk
29
+ import pyopengltk
30
+ except (ModuleNotFoundError, ImportError):
31
+ available, testable, why_not, which = \
32
+ False, False, "Could not import Tkinter or pyopengltk, module(s) not found.", None
33
+ else:
34
+ which_pyopengltk = getattr(pyopengltk, "__version__", "???")
35
+ which = f"Tkinter {tk.TkVersion} (with pyopengltk {which_pyopengltk})"
36
+
37
+ if hasattr(pyopengltk, "OpenGLFrame"):
38
+ _tk_pyopengltk_imported = True
39
+ available, testable, why_not = True, True, None
40
+ else:
41
+ # pyopengltk does not provide an implementation for this platform
42
+ available, testable, why_not = \
43
+ False, False, f"pyopengltk {which_pyopengltk} is not supported on this platform ({sys.platform})!"
44
+
45
+ if _tk_pyopengltk_imported:
46
+ # Put OpenGLFrame class in global namespace
47
+ OpenGLFrame = pyopengltk.OpenGLFrame
48
+ else:
49
+ # Create empty placeholder class
50
+ class OpenGLFrame(object):
51
+ pass
52
+
53
+ # Map native keys to vispy keys
54
+ # e.keysym_num -> vispy
55
+ KEYMAP = {
56
+ 65505: keys.SHIFT,
57
+ 65506: keys.SHIFT,
58
+ 65507: keys.CONTROL,
59
+ 65508: keys.CONTROL,
60
+ 65513: keys.ALT,
61
+ 65514: keys.ALT,
62
+ 65371: keys.META,
63
+ 65372: keys.META,
64
+
65
+ 65361: keys.LEFT,
66
+ 65362: keys.UP,
67
+ 65363: keys.RIGHT,
68
+ 65364: keys.DOWN,
69
+ 65365: keys.PAGEUP,
70
+ 65366: keys.PAGEDOWN,
71
+
72
+ 65379: keys.INSERT,
73
+ 65535: keys.DELETE,
74
+ 65360: keys.HOME,
75
+ 65367: keys.END,
76
+
77
+ 65307: keys.ESCAPE,
78
+ 65288: keys.BACKSPACE,
79
+
80
+ 32: keys.SPACE,
81
+ 65293: keys.ENTER,
82
+ 65289: keys.TAB,
83
+
84
+ 65470: keys.F1,
85
+ 65471: keys.F2,
86
+ 65472: keys.F3,
87
+ 65473: keys.F4,
88
+ 65474: keys.F5,
89
+ 65475: keys.F6,
90
+ 65476: keys.F7,
91
+ 65477: keys.F8,
92
+ 65478: keys.F9,
93
+ 65479: keys.F10,
94
+ 65480: keys.F11,
95
+ 65481: keys.F12,
96
+ }
97
+
98
+ # e.state -> vispy
99
+ KEY_STATE_MAP = {
100
+ 0x0001: keys.SHIFT,
101
+ # 0x0002: CAPSLOCK,
102
+ 0x0004: keys.CONTROL,
103
+ # 0x0008: keys.ALT, # LEFT_ALT: Seems always pressed?
104
+ # 0x0010: NUMLOCK,
105
+ # 0x0020: SCROLLLOCK,
106
+ 0x0080: keys.ALT,
107
+ # 0x0100: ?, # Mouse button 1.
108
+ # 0x0200: ?, # Mouse button 2.
109
+ # 0x0400: ?, # Mouse button 3.
110
+ 0x20000: keys.ALT # LEFT_ALT ?
111
+ }
112
+
113
+ # e.num -> vispy
114
+ MOUSE_BUTTON_MAP = {
115
+ 1: 1, # Mouse Left == 1 -> Mouse Left
116
+ 2: 3, # Mouse Middle == 2 -> Mouse Middle
117
+ 3: 2, # Mouse Right == 3 -> Mouse Right
118
+
119
+ # TODO: If other mouse buttons are needed
120
+ # and they differ from the Tkinter numbering, add them here.
121
+ # e.g. BACK/FORWARD buttons or other custom mouse buttons
122
+ }
123
+
124
+ # -------------------------------------------------------------- capability ---
125
+
126
+ # These are all booleans. Note that they mirror many of the kwargs to
127
+ # the initialization of the Canvas class.
128
+ capability = dict(
129
+ # if True they mean:
130
+ title=True, # can set title on the fly
131
+ size=True, # can set size on the fly
132
+ position=True, # can set position on the fly
133
+ show=True, # can show/hide window
134
+ vsync=False, # can set window to sync to blank
135
+ resizable=True, # can toggle resizability (e.g., no user resizing)
136
+ decorate=True, # can toggle decorations
137
+ fullscreen=True, # fullscreen window support
138
+ context=False, # can share contexts between windows
139
+ multi_window=True, # can use multiple windows at once
140
+ scroll=True, # scroll-wheel events are supported
141
+ parent=True, # can pass native widget backend parent
142
+ always_on_top=True, # can be made always-on-top
143
+ )
144
+
145
+
146
+ # ------------------------------------------------------- set_configuration ---
147
+ def _set_config(c):
148
+ """Set gl configuration for template.
149
+ Currently not used for Tkinter backend.
150
+ """
151
+ return []
152
+
153
+
154
+ # ------------------------------------------------------------- application ---
155
+
156
+ class _TkInstanceManager:
157
+ _tk_inst = None # Reference to tk.Tk instance
158
+ _tk_inst_owned = False # Whether we created the Tk instance or not
159
+ _canvasses = [] # References to created CanvasBackends
160
+
161
+ @classmethod
162
+ def get_tk_instance(cls):
163
+ """Return the Tk instance.
164
+
165
+ Returns
166
+ -------
167
+ tk.Tk
168
+ The tk.Tk instance.
169
+ """
170
+ if cls._tk_inst is None:
171
+ if tk._default_root:
172
+ # There already is a tk.Tk() instance available
173
+ cls._tk_inst = tk._default_root
174
+ cls._tk_inst_owned = False
175
+ else:
176
+ # Create our own top level Tk instance
177
+ cls._tk_inst = tk.Tk()
178
+ cls._tk_inst.withdraw()
179
+ cls._tk_inst_owned = True
180
+ return cls._tk_inst
181
+
182
+ @classmethod
183
+ def get_canvasses(cls):
184
+ """Return a list of CanvasBackends.
185
+
186
+ Returns
187
+ -------
188
+ list
189
+ A list with CanvasBackends.
190
+ """
191
+ return cls._canvasses
192
+
193
+ @classmethod
194
+ def new_toplevel(cls, canvas, *args, **kwargs):
195
+ """Create and return a new withdrawn Toplevel.
196
+ Create a tk.Toplevel with the given args and kwargs,
197
+ minimize it and add it to the list before returning
198
+
199
+ Parameters
200
+ ----------
201
+ canvas : CanvasBackend
202
+ The CanvasBackend instance that wants a new Toplevel.
203
+ *args
204
+ Variable length argument list.
205
+ **kwargs
206
+ Arbitrary keyword arguments.
207
+
208
+ Returns
209
+ -------
210
+ tk.Toplevel
211
+ Return the created tk.Toplevel
212
+ """
213
+ tl = tk.Toplevel(cls._tk_inst, *args, **kwargs)
214
+ tl.withdraw()
215
+ cls._canvasses.append(canvas)
216
+ return tl
217
+
218
+ @classmethod
219
+ def del_toplevel(cls, canvas=None):
220
+ """
221
+ Destroy the given Toplevel, and if it was the last one,
222
+ also destroy the Tk instance if we created it.
223
+
224
+ Parameters
225
+ ----------
226
+ canvas : CanvasBackend
227
+ The CanvasBackend to destroy, defaults to None.
228
+ """
229
+ if canvas:
230
+ try:
231
+ canvas.destroy()
232
+ if canvas.top:
233
+ canvas.top.destroy()
234
+ cls._canvasses.remove(canvas)
235
+ except Exception:
236
+ pass
237
+
238
+ # If there are no Toplevels left, quit the mainloop.
239
+ if cls._tk_inst and not cls._canvasses and cls._tk_inst_owned:
240
+ cls._tk_inst.quit()
241
+ cls._tk_inst.destroy()
242
+ cls._tk_inst = None
243
+
244
+
245
+ class ApplicationBackend(BaseApplicationBackend):
246
+ def _vispy_get_backend_name(self):
247
+ """
248
+ Returns
249
+ -------
250
+ str
251
+ The name of the backend.
252
+ """
253
+ return tk.__name__
254
+
255
+ def _vispy_process_events(self):
256
+ """Process events related to the spawned Tk application window.
257
+ First, update the Tk instance, then call `_delayed_update`
258
+ on every created Toplevel (to force a redraw), and process some Tkinter
259
+ GUI events by calling the Tk.mainloop and immediately exiting.
260
+ """
261
+ # Update idle tasks first (probably not required)
262
+ app = self._vispy_get_native_app()
263
+ app.update_idletasks()
264
+
265
+ # Update every active Canvas window
266
+ for c in _TkInstanceManager.get_canvasses():
267
+ c._delayed_update()
268
+
269
+ # Process some events in the main Tkinter event loop
270
+ # And quit so we can continue elsewhere (call blocks normally)
271
+ app.after(0, lambda: app.quit())
272
+ app.mainloop()
273
+
274
+ def _vispy_run(self):
275
+ """Start the Tk.mainloop. This will block until all Tk windows are destroyed."""
276
+ self._vispy_get_native_app().mainloop()
277
+
278
+ def _vispy_quit(self):
279
+ """Destroy each created Toplevel by calling _vispy_close on it.
280
+ If there are no Toplevels left, also destroy the Tk instance.
281
+ """
282
+ for c in _TkInstanceManager.get_canvasses():
283
+ c._vispy_close()
284
+ _TkInstanceManager.del_toplevel()
285
+
286
+ def _vispy_get_native_app(self):
287
+ """Get or create the Tk instance.
288
+
289
+ Returns
290
+ -------
291
+ tk.Tk
292
+ The tk.Tk instance.
293
+ """
294
+ return _TkInstanceManager.get_tk_instance()
295
+
296
+
297
+ # ------------------------------------------------------------------ canvas ---
298
+
299
+
300
+ class CanvasBackend(BaseCanvasBackend, OpenGLFrame):
301
+ """Tkinter backend for Canvas abstract class.
302
+ Uses pyopengltk.OpenGLFrame as the internal tk.Frame instance that
303
+ is able to receive OpenGL draw commands and display the results,
304
+ while also being placeable in another Toplevel window.
305
+ """
306
+
307
+ def __init__(self, vispy_canvas, **kwargs):
308
+ BaseCanvasBackend.__init__(self, vispy_canvas)
309
+ p = self._process_backend_kwargs(kwargs)
310
+
311
+ self._double_click_supported = True
312
+
313
+ # Deal with config
314
+ # ... use context.config
315
+ # Deal with context
316
+ p.context.shared.add_ref('tk', self)
317
+ if p.context.shared.ref is self:
318
+ self._native_context = None
319
+ else:
320
+ self._native_context = p.context.shared.ref._native_context
321
+
322
+ # Pop args unrecognised by OpenGLFrame
323
+ kwargs.pop("parent")
324
+ kwargs.pop("title")
325
+ kwargs.pop("size")
326
+ kwargs.pop("position")
327
+ kwargs.pop("show")
328
+ kwargs.pop("vsync")
329
+ kwargs.pop("resizable")
330
+ kwargs.pop("decorate")
331
+ kwargs.pop("always_on_top")
332
+ kwargs.pop("fullscreen")
333
+ kwargs.pop("context")
334
+
335
+ if p.parent is None:
336
+ # Create native window and top level
337
+ self.top = _TkInstanceManager.new_toplevel(self)
338
+
339
+ # Check input args and call appropriate set-up functions.
340
+ if p.title:
341
+ self._vispy_set_title(p.title)
342
+ if p.size:
343
+ self._vispy_set_size(p.size[0], p.size[1])
344
+ if p.position:
345
+ self._vispy_set_position(p.position[0], p.position[1])
346
+
347
+ self.top.update_idletasks()
348
+
349
+ if not p.resizable:
350
+ self.top.resizable(False, False)
351
+ if not p.decorate:
352
+ self.top.overrideredirect(True)
353
+ if p.always_on_top:
354
+ self.top.wm_attributes("-topmost", "True")
355
+ self._fullscreen = bool(p.fullscreen)
356
+
357
+ self.top.protocol("WM_DELETE_WINDOW", self._vispy_close)
358
+ parent = self.top
359
+ else:
360
+ # Use given parent as top level
361
+ self.top = None
362
+ parent = p.parent
363
+ self._fullscreen = False
364
+
365
+ self._init = False
366
+ self.is_destroyed = False
367
+ self._dynamic_keymap = {}
368
+
369
+ OpenGLFrame.__init__(self, parent, **kwargs)
370
+
371
+ if self.top:
372
+ # Embed canvas in top (new window) if this was created
373
+ self.top.configure(bg="black")
374
+ self.pack(fill=tk.BOTH, expand=True)
375
+
376
+ # Also bind the key events to the top window instead.
377
+ self.top.bind("<Any-KeyPress>", self._on_key_down)
378
+ self.top.bind("<Any-KeyRelease>", self._on_key_up)
379
+ else:
380
+ # If no top, bind key events to the canvas itself.
381
+ self.bind("<Any-KeyPress>", self._on_key_down)
382
+ self.bind("<Any-KeyRelease>", self._on_key_up)
383
+
384
+ # Bind the other events to our internal methods.
385
+ self.bind("<Enter>", self._on_mouse_enter) # This also binds MouseWheel
386
+ self.bind("<Leave>", self._on_mouse_leave) # This also unbinds MouseWheel
387
+ self.bind("<Motion>", self._on_mouse_move)
388
+ self.bind("<Any-Button>", self._on_mouse_button_press)
389
+ self.bind("<Double-Any-Button>", self._on_mouse_double_button_press)
390
+ self.bind("<Any-ButtonRelease>", self._on_mouse_button_release)
391
+ self.bind("<Configure>", self._on_configure, add='+')
392
+
393
+ self._vispy_set_visible(p.show)
394
+ self.focus_force()
395
+
396
+ def initgl(self):
397
+ """Overridden from OpenGLFrame
398
+ Gets called on init or when the frame is remapped into its container.
399
+ """
400
+ if not hasattr(self, "_native_context") or self._native_context is None:
401
+ # Workaround to get OpenGLFrame.__context for reference here
402
+ # if access would ever be needed from self._native_context.
403
+ # FIXME: Context sharing this way seems unsupported
404
+ self._native_context = vars(self).get("_CanvasBackend__context", None)
405
+
406
+ self.update_idletasks()
407
+ gl.glClear(gl.GL_COLOR_BUFFER_BIT)
408
+ gl.glClearColor(0.0, 0.0, 0.0, 0.0)
409
+
410
+ def redraw(self, *args):
411
+ """Overridden from OpenGLFrame
412
+ Gets called when the OpenGLFrame redraws itself.
413
+ It will set the current buffer, call self.redraw() and
414
+ swap buffers afterwards.
415
+ """
416
+ if self._vispy_canvas is None:
417
+ return
418
+ if not self._init:
419
+ self._initialize()
420
+ self._vispy_canvas.set_current()
421
+ self._vispy_canvas.events.draw(region=None)
422
+
423
+ def _delayed_update(self):
424
+ """
425
+ Expose a new frame to the canvas. This will call self.redraw() internally.
426
+
427
+ The self.animate sets the refresh rate in milliseconds. Using this is not
428
+ necessary because VisPy will use the TimerBackend to periodically call
429
+ self._vispy_update, resulting in the exact same behaviour.
430
+ So we set it to `0` to tell OpenGLFrame not to redraw itself on its own.
431
+ """
432
+ if self.is_destroyed:
433
+ return
434
+ self.animate = 0
435
+ self.tkExpose(None)
436
+
437
+ def _on_configure(self, e):
438
+ """Called when the frame get configured or resized."""
439
+ if self._vispy_canvas is None or not self._init:
440
+ return
441
+ size_tup = e if isinstance(e, tuple) else (e.width, e.height)
442
+ self._vispy_canvas.events.resize(size=size_tup)
443
+
444
+ def _initialize(self):
445
+ """Initialise the Canvas for drawing."""
446
+ self.initgl()
447
+ if self._vispy_canvas is None:
448
+ return
449
+ self._init = True
450
+ self._vispy_canvas.set_current()
451
+ self._vispy_canvas.events.initialize()
452
+ self.update_idletasks()
453
+ self._on_configure(self._vispy_get_size())
454
+
455
+ def _vispy_warmup(self):
456
+ """Provided for VisPy tests, so they can 'warm the canvas up'.
457
+ Mostly taken from the wxWidgets backend.
458
+ """
459
+ tk_inst = _TkInstanceManager.get_tk_instance()
460
+
461
+ etime = time() + 0.3
462
+ while time() < etime:
463
+ sleep(0.01)
464
+ self._vispy_canvas.set_current()
465
+ self._vispy_canvas.app.process_events()
466
+
467
+ tk_inst.after(0, lambda: tk_inst.quit())
468
+ tk_inst.mainloop()
469
+
470
+ def _parse_state(self, e):
471
+ """Helper to parse event.state into modifier keys.
472
+
473
+ Parameters
474
+ ----------
475
+ e : tk.Event
476
+ The passed in Event.
477
+
478
+ Returns
479
+ -------
480
+ list
481
+ A list of modifier keys that are active (from vispy's keys)
482
+ """
483
+ return [key for mask, key in KEY_STATE_MAP.items() if e.state & mask]
484
+
485
+ def _parse_keys(self, e):
486
+ """Helper to parse key states into Vispy keys.
487
+
488
+ Parameters
489
+ ----------
490
+ e : tk.Event
491
+ The passed in Event.
492
+
493
+ Returns
494
+ -------
495
+ tuple
496
+ A tuple (key.Key(), chr(key)), which has the vispy key object and
497
+ the character representation if available.
498
+ """
499
+ if e.keysym_num in KEYMAP:
500
+ return KEYMAP[e.keysym_num], ""
501
+ # e.char, e.keycode, e.keysym, e.keysym_num
502
+ if e.char:
503
+ self._dynamic_keymap[e.keycode] = e.char
504
+ return keys.Key(e.char), e.char
505
+
506
+ if e.keycode in self._dynamic_keymap:
507
+ char = self._dynamic_keymap[e.keycode]
508
+ return keys.Key(char), char
509
+
510
+ warnings.warn("The key you typed is not supported by the tkinter backend."
511
+ "Please map your functionality to a different key")
512
+ return None, None
513
+
514
+ def _on_mouse_enter(self, e):
515
+ """Event callback when the mouse enters the canvas.
516
+
517
+ Parameters
518
+ ----------
519
+ e : tk.Event
520
+ The passed in Event.
521
+ """
522
+ if self._vispy_canvas is None:
523
+ return
524
+ if _tk_on_linux:
525
+ # On Linux, bind wheel as buttons instead
526
+ self.bind_all("<Button-4>", self._on_mouse_wheel)
527
+ self.bind_all("<Button-5>", self._on_mouse_wheel)
528
+ else:
529
+ # Other platforms, bind wheel event
530
+ # FIXME: What to do on Darwin?
531
+ self.bind_all("<MouseWheel>", self._on_mouse_wheel)
532
+
533
+ self._vispy_mouse_move(
534
+ pos=(e.x, e.y), modifiers=self._parse_state(e))
535
+
536
+ def _on_mouse_leave(self, e):
537
+ """Event callback when the mouse leaves the canvas.
538
+
539
+ Parameters
540
+ ----------
541
+ e : tk.Event
542
+ The passed in Event.
543
+ """
544
+ if self._vispy_canvas is None:
545
+ return
546
+ # Unbind mouse wheel events when not over the canvas any more.
547
+ if _tk_on_linux:
548
+ self.unbind_all("<Button-4>")
549
+ self.unbind_all("<Button-5>")
550
+ else:
551
+ self.unbind_all("<MouseWheel>")
552
+
553
+ def _on_mouse_move(self, e):
554
+ """Event callback when the mouse is moved within the canvas.
555
+
556
+ Parameters
557
+ ----------
558
+ e : tk.Event
559
+ The passed in Event.
560
+ """
561
+ if self._vispy_canvas is None:
562
+ return
563
+ self._vispy_mouse_move(
564
+ pos=(e.x, e.y), modifiers=self._parse_state(e))
565
+
566
+ def _on_mouse_wheel(self, e):
567
+ """Event callback when the mouse wheel changes within the canvas.
568
+
569
+ Parameters
570
+ ----------
571
+ e : tk.Event
572
+ The passed in Event.
573
+ """
574
+ if self._vispy_canvas is None:
575
+ return
576
+ if _tk_on_linux:
577
+ # Fix mouse wheel delta
578
+ e.delta = {4: 120, 5: -120}.get(e.num, 0)
579
+ self._vispy_canvas.events.mouse_wheel(
580
+ delta=(0.0, float(e.delta / 120)),
581
+ pos=(e.x, e.y), modifiers=self._parse_state(e))
582
+
583
+ def _on_mouse_button_press(self, e):
584
+ """Event callback when a mouse button is pressed within the canvas.
585
+
586
+ Parameters
587
+ ----------
588
+ e : tk.Event
589
+ The passed in Event.
590
+ """
591
+ if self._vispy_canvas is None:
592
+ return
593
+ # Ignore MouseWheel on linux
594
+ if _tk_on_linux and e.num in (4, 5):
595
+ return
596
+ self._vispy_mouse_press(
597
+ pos=(e.x, e.y), button=MOUSE_BUTTON_MAP.get(e.num, e.num), modifiers=self._parse_state(e))
598
+
599
+ def _vispy_detect_double_click(self, e):
600
+ """Override base class function
601
+ since double click handling is native in Tk.
602
+ """
603
+ pass
604
+
605
+ def _on_mouse_double_button_press(self, e):
606
+ """Event callback when a mouse button is double clicked within the canvas.
607
+
608
+ Parameters
609
+ ----------
610
+ e : tk.Event
611
+ The passed in Event.
612
+ """
613
+ if self._vispy_canvas is None:
614
+ return
615
+ # Ignore MouseWheel on linux
616
+ if _tk_on_linux and e.num in (4, 5):
617
+ return
618
+ self._vispy_mouse_double_click(
619
+ pos=(e.x, e.y), button=MOUSE_BUTTON_MAP.get(e.num, e.num), modifiers=self._parse_state(e))
620
+
621
+ def _on_mouse_button_release(self, e):
622
+ """Event callback when a mouse button is released within the canvas.
623
+
624
+ Parameters
625
+ ----------
626
+ e : tk.Event
627
+ The passed in Event.
628
+ """
629
+ if self._vispy_canvas is None:
630
+ return
631
+ # Ignore MouseWheel on linux
632
+ if _tk_on_linux and e.num in (4, 5):
633
+ return
634
+ self._vispy_mouse_release(
635
+ pos=(e.x, e.y), button=MOUSE_BUTTON_MAP.get(e.num, e.num), modifiers=self._parse_state(e))
636
+
637
+ def _on_key_down(self, e):
638
+ """Event callback when a key is pressed within the canvas or window.
639
+
640
+ Ignore keys.ESCAPE if this is an embedded canvas,
641
+ as this would make it unresponsive (because it won't close the entire window),
642
+ while still being updateable.
643
+
644
+ Parameters
645
+ ----------
646
+ e : tk.Event
647
+ The passed in Event.
648
+ """
649
+ if self._vispy_canvas is None:
650
+ return
651
+ key, text = self._parse_keys(e)
652
+ if not self.top and key == keys.ESCAPE:
653
+ return
654
+ self._vispy_canvas.events.key_press(
655
+ key=key, text=text, modifiers=self._parse_state(e))
656
+
657
+ def _on_key_up(self, e):
658
+ """Event callback when a key is released within the canvas or window.
659
+
660
+ Ignore keys.ESCAPE if this is an embedded canvas,
661
+ as this would make it unresponsive (because it won't close the entire window),
662
+ while still being updateable.
663
+
664
+ Parameters
665
+ ----------
666
+ e : tk.Event
667
+ The passed in Event.
668
+ """
669
+ if self._vispy_canvas is None:
670
+ return
671
+ key, text = self._parse_keys(e)
672
+ if not self.top and key == keys.ESCAPE:
673
+ return
674
+ self._vispy_canvas.events.key_release(
675
+ key=key, text=text, modifiers=self._parse_state(e))
676
+
677
+ def _vispy_set_current(self):
678
+ """Make this the current context."""
679
+ if not self.is_destroyed:
680
+ self.tkMakeCurrent()
681
+
682
+ def _vispy_swap_buffers(self):
683
+ """Swap front and back buffer. This is done internally inside OpenGLFrame."""
684
+ self._vispy_canvas.set_current()
685
+
686
+ def _vispy_set_title(self, title):
687
+ """Set the window title. Has no effect for widgets."""
688
+ if self.top:
689
+ self.top.title(title)
690
+
691
+ def _vispy_set_size(self, w, h):
692
+ """Set size of the window. Has no effect for widgets."""
693
+ if self.top:
694
+ self.top.geometry(f"{w}x{h}")
695
+
696
+ def _vispy_set_position(self, x, y):
697
+ """Set location of the window. Has no effect for widgets."""
698
+ if self.top:
699
+ self.top.geometry(f"+{x}+{y}")
700
+
701
+ def _vispy_set_visible(self, visible):
702
+ """Show or hide the window. Has no effect for widgets."""
703
+ if self.top:
704
+ if visible:
705
+ self.top.wm_deiconify()
706
+ self.top.lift()
707
+ self.top.attributes('-fullscreen', self._fullscreen)
708
+ else:
709
+ self.top.withdraw()
710
+
711
+ def _vispy_set_fullscreen(self, fullscreen):
712
+ """Set the current fullscreen state.
713
+
714
+ Has no effect for widgets. If you want it to become fullscreen,
715
+ while embedded in another Toplevel window, you should make that
716
+ window fullscreen instead.
717
+ """
718
+ self._fullscreen = bool(fullscreen)
719
+ if self.top:
720
+ self._vispy_set_visible(True)
721
+
722
+ def _vispy_update(self):
723
+ """Invoke a redraw
724
+
725
+ Delay this by letting Tk call it later, even a delay of 0 will do.
726
+ Doing this, prevents EventEmitter loops that are caused
727
+ by wanting to draw too fast.
728
+ """
729
+ self.after(0, self._delayed_update)
730
+
731
+ def _vispy_close(self):
732
+ """Force the window to close, destroying the canvas in the process.
733
+
734
+ When this was the last VisPy window, also quit the Tk instance.
735
+ This will not interfere if there is already another user window,
736
+ unrelated top VisPy open.
737
+ """
738
+ if self.top and not self.is_destroyed:
739
+ self.is_destroyed = True
740
+ self._vispy_canvas.close()
741
+ _TkInstanceManager.del_toplevel(self)
742
+
743
+ def destroy(self):
744
+ """Callback when the window gets closed.
745
+ Destroy the VisPy canvas by calling close on it.
746
+ """
747
+ self._vispy_canvas.close()
748
+
749
+ def _vispy_get_size(self):
750
+ """Return the actual size of the frame."""
751
+ if self.top:
752
+ self.top.update_idletasks()
753
+ return self.winfo_width(), self.winfo_height()
754
+
755
+ def _vispy_get_position(self):
756
+ """Return the widget or window position."""
757
+ return self.winfo_x(), self.winfo_y()
758
+
759
+ def _vispy_get_fullscreen(self):
760
+ """Return the last set full screen state, regardless if it's actually in that state.
761
+
762
+ When using the canvas as a widget, it will not go into fullscreen.
763
+ See _vispy_set_fullscreen
764
+ """
765
+ return self._fullscreen
766
+
767
+
768
+ # ------------------------------------------------------------------- timer ---
769
+
770
+ class TimerBackend(BaseTimerBackend):
771
+ def __init__(self, vispy_timer):
772
+ BaseTimerBackend.__init__(self, vispy_timer)
773
+ self._tk = _TkInstanceManager.get_tk_instance()
774
+ if self._tk is None:
775
+ raise Exception("TimerBackend: No toplevel?")
776
+ self._id = None
777
+ self.last_interval = 1
778
+
779
+ def _vispy_start(self, interval):
780
+ """Start the timer.
781
+ Use Tk.after to schedule timer events.
782
+ """
783
+ self._vispy_stop()
784
+ self.last_interval = max(0, int(round(interval * 1000)))
785
+ self._id = self._tk.after(self.last_interval, self._vispy_timeout)
786
+
787
+ def _vispy_stop(self):
788
+ """Stop the timer.
789
+ Unschedule the previous callback if it exists.
790
+ """
791
+ if self._id is not None:
792
+ self._tk.after_cancel(self._id)
793
+ self._id = None
794
+
795
+ def _vispy_timeout(self):
796
+ """Callback when the timer finishes.
797
+ Also reschedules the next callback.
798
+ """
799
+ self._vispy_timer._timeout()
800
+ self._id = self._tk.after(self.last_interval, self._vispy_timeout)