kaxe 1.8.1.dev5__tar.gz → 1.8.1.dev6__tar.gz
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.
- {kaxe-1.8.1.dev5/src/kaxe.egg-info → kaxe-1.8.1.dev6}/PKG-INFO +4 -2
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/README.md +3 -1
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/pyproject.toml +1 -1
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/viewer/window.py +88 -9
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6/src/kaxe.egg-info}/PKG-INFO +4 -2
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/tests/test_viewer.py +30 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/LICENSE +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/MANIFEST.in +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/setup.cfg +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/__init__.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/__main__.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/_require_3d.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/_require_viewer.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/chart/__init__.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/chart/bar.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/chart/box.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/chart/pie.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/chart/qqplot.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/cli.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/core/__init__.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/core/axis.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/core/bounds.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/core/color.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/core/d3/backend.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/core/d3/camera.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/core/d3/helper.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/core/d3/hud.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/core/d3/objects/__init__.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/core/d3/objects/color.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/core/d3/objects/line.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/core/d3/objects/point.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/core/d3/objects/pointer.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/core/d3/objects/triangle.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/core/d3/openglrender.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/core/d3/translator.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/core/draw.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/core/fileloader.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/core/helper.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/core/ipython_display.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/core/legend.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/core/line.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/core/marker.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/core/palette.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/core/profiler.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/core/progress.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/core/round.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/core/shapes.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/core/styles.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/core/svg.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/core/svg_pdf.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/core/symbol.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/core/text.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/core/thin.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/core/window.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/data/__init__.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/data/excel.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/objects/__init__.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/objects/_lazy.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/objects/d2/__init__.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/objects/d2/arrow.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/objects/d2/bubble.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/objects/d2/contour.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/objects/d2/equation.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/objects/d2/fill.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/objects/d2/function.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/objects/d2/guide_grid.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/objects/d2/inequality.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/objects/d2/map.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/objects/d2/parameter.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/objects/d2/pillar.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/objects/d2/point.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/objects/d3/__init__.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/objects/d3/base.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/objects/d3/function.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/objects/d3/mesh.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/objects/d3/point.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/objects/d3/potato.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/objects/function.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/objects/legend.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/objects/mapdata.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/objects/point.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/objects/text.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/plot/__init__.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/plot/_lazy.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/plot/box.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/plot/constants.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/plot/d3/__init__.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/plot/d3/axes.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/plot/d3/geometry.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/plot/d3/plot3d.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/plot/d3/variants.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/plot/double.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/plot/empty.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/plot/grid.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/plot/log.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/plot/polar.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/plot/standard.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/plot/themes.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/plot/zoom.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/plot/zoom_connector.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/project/__init__.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/project/codec.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/project/context.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/project/document.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/project/registry.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/project/sample.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/project/sampled_curve.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/project/serializers.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/project/window.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/__init__.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/__init__.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.bright-oblique.ttf +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.bright-roman.ttf +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.bright-semibold.ttf +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.bright-semiboldoblique.ttf +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.classical-serif-italic.ttf +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.concrete-bold.ttf +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.concrete-bolditalic.ttf +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.concrete-italic.ttf +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.concrete-roman.ttf +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.sans-serif-bold.ttf +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.sans-serif-boldoblique.ttf +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.sans-serif-demi-condensed-demicondensed.ttf +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.sans-serif-medium.ttf +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.sans-serif-oblique.ttf +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.serif-bold.ttf +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.serif-bolditalic.ttf +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.serif-extra-boldslanted.ttf +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.serif-extra-romanslanted.ttf +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.serif-italic.ttf +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.serif-roman.ttf +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.serif-upright-italic-uprightitalic.ttf +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.typewriter-text-bold.ttf +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.typewriter-text-bolditalic.ttf +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.typewriter-text-italic.ttf +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.typewriter-text-light.ttf +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.typewriter-text-lightoblique.ttf +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.typewriter-text-regular.ttf +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.typewriter-text-variable-width-italic.ttf +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.typewriter-text-variable-width-medium.ttf +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/readme.txt +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/logo-small.png +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/viewer/__init__.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/viewer/cli.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/viewer/client.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/viewer/server.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe.egg-info/SOURCES.txt +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe.egg-info/dependency_links.txt +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe.egg-info/entry_points.txt +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe.egg-info/requires.txt +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe.egg-info/top_level.txt +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/tests/test.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/tests/test2.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/tests/test3.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/tests/test_4.py +0 -0
- {kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/tests/test_5.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: kaxe
|
|
3
|
-
Version: 1.8.1.
|
|
3
|
+
Version: 1.8.1.dev6
|
|
4
4
|
Summary: A small graphing tool for functions, points, equations and more
|
|
5
5
|
Author-email: Valter Yde Daugberg <valteryde@hotmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/valteryde/kaxe
|
|
@@ -87,7 +87,9 @@ When the viewer is open, `.show()` instantly streams plots to cards on your canv
|
|
|
87
87
|
**Canvas & Card Controls:**
|
|
88
88
|
* **Click & Drag on a Card**: Move that card freely across the canvas
|
|
89
89
|
* **Click & Drag on Empty Space**: Pan the camera across the workspace
|
|
90
|
-
* **
|
|
90
|
+
* **Two-Finger Scroll / Trackpad**: Pan canvas side-to-side and up/down without zooming
|
|
91
|
+
* **`[Shift]` + Scroll**: Pan horizontally (for 1D mouse wheels)
|
|
92
|
+
* **`[Cmd]` / `[Ctrl]` + Scroll**: Smooth zoom anchored to cursor
|
|
91
93
|
* **`[A]`**: Auto-arrange all cards in a neat row
|
|
92
94
|
* **`[Space]` or `[R]`**: Fit all cards on the canvas into view
|
|
93
95
|
* **`[1]`**: View canvas at 100% native pixel scale
|
|
@@ -54,7 +54,9 @@ When the viewer is open, `.show()` instantly streams plots to cards on your canv
|
|
|
54
54
|
**Canvas & Card Controls:**
|
|
55
55
|
* **Click & Drag on a Card**: Move that card freely across the canvas
|
|
56
56
|
* **Click & Drag on Empty Space**: Pan the camera across the workspace
|
|
57
|
-
* **
|
|
57
|
+
* **Two-Finger Scroll / Trackpad**: Pan canvas side-to-side and up/down without zooming
|
|
58
|
+
* **`[Shift]` + Scroll**: Pan horizontally (for 1D mouse wheels)
|
|
59
|
+
* **`[Cmd]` / `[Ctrl]` + Scroll**: Smooth zoom anchored to cursor
|
|
58
60
|
* **`[A]`**: Auto-arrange all cards in a neat row
|
|
59
61
|
* **`[Space]` or `[R]`**: Fit all cards on the canvas into view
|
|
60
62
|
* **`[1]`**: View canvas at 100% native pixel scale
|
|
@@ -277,6 +277,11 @@ class KaxeViewerWindow(pyglet.window.Window):
|
|
|
277
277
|
self.pan_camera_start_x: float = 0.0
|
|
278
278
|
self.pan_camera_start_y: float = 0.0
|
|
279
279
|
|
|
280
|
+
# Key state handler for live modifier tracking (Cmd, Ctrl, Shift)
|
|
281
|
+
self.keys = key.KeyStateHandler()
|
|
282
|
+
self.push_handlers(self.keys)
|
|
283
|
+
self.current_modifiers: int = 0
|
|
284
|
+
|
|
280
285
|
self.show_hud: bool = True
|
|
281
286
|
self.notification_text: str = ""
|
|
282
287
|
self.notification_expiry: float = 0.0
|
|
@@ -307,7 +312,7 @@ class KaxeViewerWindow(pyglet.window.Window):
|
|
|
307
312
|
)
|
|
308
313
|
|
|
309
314
|
self.hud_right = pyglet.text.Label(
|
|
310
|
-
"[Drag] Move card / Pan [Scroll] Zoom [
|
|
315
|
+
"[Drag] Move card / Pan [Cmd+Scroll] Zoom [Scroll] Pan [A] Arrange [Space] Fit",
|
|
311
316
|
font_size=11,
|
|
312
317
|
x=self.width - 15,
|
|
313
318
|
y=15,
|
|
@@ -489,19 +494,90 @@ class KaxeViewerWindow(pyglet.window.Window):
|
|
|
489
494
|
self.dragging_card = None
|
|
490
495
|
self.is_panning_camera = False
|
|
491
496
|
|
|
497
|
+
def is_zoom_modifier_pressed(self) -> bool:
|
|
498
|
+
"""Return True if Meta (Command) or Control key is held down."""
|
|
499
|
+
if sys.platform == "darwin":
|
|
500
|
+
try:
|
|
501
|
+
from pyglet.libs.darwin import cocoapy
|
|
502
|
+
flags = cocoapy.NSEvent.modifierFlags()
|
|
503
|
+
if flags & (cocoapy.NSCommandKeyMask | cocoapy.NSControlKeyMask):
|
|
504
|
+
return True
|
|
505
|
+
except Exception:
|
|
506
|
+
pass
|
|
507
|
+
|
|
508
|
+
if hasattr(self, "keys") and self.keys is not None:
|
|
509
|
+
if (
|
|
510
|
+
self.keys[key.LCOMMAND]
|
|
511
|
+
or self.keys[key.RCOMMAND]
|
|
512
|
+
or self.keys[key.LCTRL]
|
|
513
|
+
or self.keys[key.RCTRL]
|
|
514
|
+
):
|
|
515
|
+
return True
|
|
516
|
+
|
|
517
|
+
if getattr(self, "current_modifiers", 0) & (key.MOD_COMMAND | key.MOD_CTRL):
|
|
518
|
+
return True
|
|
519
|
+
|
|
520
|
+
return False
|
|
521
|
+
|
|
522
|
+
def is_shift_pressed(self) -> bool:
|
|
523
|
+
"""Return True if Shift key is held down."""
|
|
524
|
+
if sys.platform == "darwin":
|
|
525
|
+
try:
|
|
526
|
+
from pyglet.libs.darwin import cocoapy
|
|
527
|
+
flags = cocoapy.NSEvent.modifierFlags()
|
|
528
|
+
if flags & cocoapy.NSShiftKeyMask:
|
|
529
|
+
return True
|
|
530
|
+
except Exception:
|
|
531
|
+
pass
|
|
532
|
+
|
|
533
|
+
if hasattr(self, "keys") and self.keys is not None:
|
|
534
|
+
if self.keys[key.LSHIFT] or self.keys[key.RSHIFT]:
|
|
535
|
+
return True
|
|
536
|
+
|
|
537
|
+
if getattr(self, "current_modifiers", 0) & key.MOD_SHIFT:
|
|
538
|
+
return True
|
|
539
|
+
|
|
540
|
+
return False
|
|
541
|
+
|
|
492
542
|
def on_mouse_scroll(self, x: int, y: int, scroll_x: float, scroll_y: float):
|
|
493
|
-
"""
|
|
494
|
-
zoom_factor = 1.05 ** (-scroll_y)
|
|
495
|
-
new_zoom = max(0.04, min(self.zoom * zoom_factor, 20.0))
|
|
543
|
+
"""Scroll handler:
|
|
496
544
|
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
545
|
+
- If Meta (Cmd) or Control is held: ZOOM anchored at cursor.
|
|
546
|
+
- Otherwise: PAN canvas side-to-side and up/down without zooming.
|
|
547
|
+
"""
|
|
548
|
+
if hasattr(self, "keys") and self.keys is not None:
|
|
549
|
+
should_zoom = self.is_zoom_modifier_pressed()
|
|
550
|
+
else:
|
|
551
|
+
# Fallback for mock unit test instances
|
|
552
|
+
should_zoom = True
|
|
501
553
|
|
|
502
|
-
|
|
554
|
+
if should_zoom:
|
|
555
|
+
zoom_factor = 1.05 ** (-scroll_y)
|
|
556
|
+
new_zoom = max(0.04, min(self.zoom * zoom_factor, 25.0))
|
|
557
|
+
|
|
558
|
+
if hasattr(self, "width"):
|
|
559
|
+
wx, wy = self.screen_to_world(x, y)
|
|
560
|
+
self.camera_x = wx - (x - self.width / 2.0) / new_zoom
|
|
561
|
+
self.camera_y = wy - (y - self.height / 2.0) / new_zoom
|
|
562
|
+
|
|
563
|
+
self.zoom = new_zoom
|
|
564
|
+
else:
|
|
565
|
+
# Pan without zooming
|
|
566
|
+
dx = scroll_x
|
|
567
|
+
dy = scroll_y
|
|
568
|
+
|
|
569
|
+
# Holding Shift converts vertical wheel into horizontal pan
|
|
570
|
+
if self.is_shift_pressed() and dy != 0.0 and dx == 0.0:
|
|
571
|
+
dx = dy
|
|
572
|
+
dy = 0.0
|
|
573
|
+
|
|
574
|
+
pan_speed = 20.0
|
|
575
|
+
self.camera_x -= (dx * pan_speed) / self.zoom
|
|
576
|
+
self.camera_y += (dy * pan_speed) / self.zoom
|
|
503
577
|
|
|
504
578
|
def on_key_press(self, symbol: int, modifiers: int):
|
|
579
|
+
self.current_modifiers = modifiers
|
|
580
|
+
|
|
505
581
|
# Fit all
|
|
506
582
|
if symbol in (key.R, key.SPACE):
|
|
507
583
|
self.fit_all_cards()
|
|
@@ -537,6 +613,9 @@ class KaxeViewerWindow(pyglet.window.Window):
|
|
|
537
613
|
elif symbol == key.S:
|
|
538
614
|
self.save_selected_card()
|
|
539
615
|
|
|
616
|
+
def on_key_release(self, symbol: int, modifiers: int):
|
|
617
|
+
self.current_modifiers = modifiers
|
|
618
|
+
|
|
540
619
|
def copy_selected_card(self):
|
|
541
620
|
if not self.selected_card or not self.selected_card.current_version:
|
|
542
621
|
return
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: kaxe
|
|
3
|
-
Version: 1.8.1.
|
|
3
|
+
Version: 1.8.1.dev6
|
|
4
4
|
Summary: A small graphing tool for functions, points, equations and more
|
|
5
5
|
Author-email: Valter Yde Daugberg <valteryde@hotmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/valteryde/kaxe
|
|
@@ -87,7 +87,9 @@ When the viewer is open, `.show()` instantly streams plots to cards on your canv
|
|
|
87
87
|
**Canvas & Card Controls:**
|
|
88
88
|
* **Click & Drag on a Card**: Move that card freely across the canvas
|
|
89
89
|
* **Click & Drag on Empty Space**: Pan the camera across the workspace
|
|
90
|
-
* **
|
|
90
|
+
* **Two-Finger Scroll / Trackpad**: Pan canvas side-to-side and up/down without zooming
|
|
91
|
+
* **`[Shift]` + Scroll**: Pan horizontally (for 1D mouse wheels)
|
|
92
|
+
* **`[Cmd]` / `[Ctrl]` + Scroll**: Smooth zoom anchored to cursor
|
|
91
93
|
* **`[A]`**: Auto-arrange all cards in a neat row
|
|
92
94
|
* **`[Space]` or `[R]`**: Fit all cards on the canvas into view
|
|
93
95
|
* **`[1]`**: View canvas at 100% native pixel scale
|
|
@@ -220,6 +220,36 @@ def test_viewer_zoom_reversed_and_less_sensitive():
|
|
|
220
220
|
assert abs(window.zoom - 1.05) < 1e-6
|
|
221
221
|
|
|
222
222
|
|
|
223
|
+
def test_scroll_pans_side_to_side_without_zoom_modifier():
|
|
224
|
+
from unittest.mock import MagicMock
|
|
225
|
+
from kaxe.viewer.window import KaxeViewerWindow
|
|
226
|
+
from pyglet.window import key
|
|
227
|
+
|
|
228
|
+
window = object.__new__(KaxeViewerWindow)
|
|
229
|
+
window.keys = {key.LCOMMAND: False, key.RCOMMAND: False, key.LCTRL: False, key.RCTRL: False, key.LSHIFT: False, key.RSHIFT: False}
|
|
230
|
+
window.current_modifiers = 0
|
|
231
|
+
window.camera_x = 0.0
|
|
232
|
+
window.camera_y = 0.0
|
|
233
|
+
window.zoom = 1.0
|
|
234
|
+
|
|
235
|
+
# Horizontal scroll without Cmd/Ctrl -> pans horizontally, zoom stays unchanged!
|
|
236
|
+
window.on_mouse_scroll(x=400, y=300, scroll_x=2.0, scroll_y=0.0)
|
|
237
|
+
assert window.zoom == 1.0
|
|
238
|
+
assert window.camera_x < 0.0 # Camera moved left
|
|
239
|
+
|
|
240
|
+
# Vertical scroll without Cmd/Ctrl -> pans vertically, zoom stays unchanged!
|
|
241
|
+
orig_cam_x = window.camera_x
|
|
242
|
+
window.on_mouse_scroll(x=400, y=300, scroll_x=0.0, scroll_y=3.0)
|
|
243
|
+
assert window.zoom == 1.0
|
|
244
|
+
assert window.camera_x == orig_cam_x
|
|
245
|
+
assert window.camera_y > 0.0
|
|
246
|
+
|
|
247
|
+
# With Cmd key pressed -> zooms!
|
|
248
|
+
window.keys[key.LCOMMAND] = True
|
|
249
|
+
window.on_mouse_scroll(x=400, y=300, scroll_x=0.0, scroll_y=-1.0)
|
|
250
|
+
assert window.zoom > 1.0
|
|
251
|
+
|
|
252
|
+
|
|
223
253
|
def test_plot_id_chaining_and_streaming(monkeypatch):
|
|
224
254
|
import kaxe
|
|
225
255
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.bright-oblique.ttf
RENAMED
|
File without changes
|
{kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.bright-roman.ttf
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.concrete-bold.ttf
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.concrete-roman.ttf
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.serif-bold.ttf
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.serif-italic.ttf
RENAMED
|
File without changes
|
{kaxe-1.8.1.dev5 → kaxe-1.8.1.dev6}/src/kaxe/resources/computer-modern-family/cmu.serif-roman.ttf
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|