pyalgoviz 0.1.0__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.
Files changed (62) hide show
  1. pyalgoviz-0.1.0/LICENSE +21 -0
  2. pyalgoviz-0.1.0/PKG-INFO +267 -0
  3. pyalgoviz-0.1.0/README.md +240 -0
  4. pyalgoviz-0.1.0/pyproject.toml +49 -0
  5. pyalgoviz-0.1.0/setup.cfg +4 -0
  6. pyalgoviz-0.1.0/src/pyalgoviz/__init__.py +1 -0
  7. pyalgoviz-0.1.0/src/pyalgoviz/app.py +8 -0
  8. pyalgoviz-0.1.0/src/pyalgoviz/canvas/__init__.py +0 -0
  9. pyalgoviz-0.1.0/src/pyalgoviz/canvas/array_canvas.py +65 -0
  10. pyalgoviz-0.1.0/src/pyalgoviz/canvas/array_type.py +28 -0
  11. pyalgoviz-0.1.0/src/pyalgoviz/canvas/base.py +17 -0
  12. pyalgoviz-0.1.0/src/pyalgoviz/canvas/graph_canvas.py +116 -0
  13. pyalgoviz-0.1.0/src/pyalgoviz/canvas/graph_type.py +126 -0
  14. pyalgoviz-0.1.0/src/pyalgoviz/canvas/grid_canvas.py +53 -0
  15. pyalgoviz-0.1.0/src/pyalgoviz/canvas/grid_type.py +35 -0
  16. pyalgoviz-0.1.0/src/pyalgoviz/canvas/registry.py +56 -0
  17. pyalgoviz-0.1.0/src/pyalgoviz/canvas/tk_array_renderer.py +75 -0
  18. pyalgoviz-0.1.0/src/pyalgoviz/canvas/tk_graph_renderer.py +96 -0
  19. pyalgoviz-0.1.0/src/pyalgoviz/canvas/tk_grid_renderer.py +64 -0
  20. pyalgoviz-0.1.0/src/pyalgoviz/canvas_types.py +8 -0
  21. pyalgoviz-0.1.0/src/pyalgoviz/engine/__init__.py +0 -0
  22. pyalgoviz-0.1.0/src/pyalgoviz/engine/playback.py +7 -0
  23. pyalgoviz-0.1.0/src/pyalgoviz/engine/runner.py +87 -0
  24. pyalgoviz-0.1.0/src/pyalgoviz/plugins.py +62 -0
  25. pyalgoviz-0.1.0/src/pyalgoviz/preset_loader.py +192 -0
  26. pyalgoviz-0.1.0/src/pyalgoviz/presets/bfs-pathfinding.toml +50 -0
  27. pyalgoviz-0.1.0/src/pyalgoviz/presets/bresenham-line.toml +63 -0
  28. pyalgoviz-0.1.0/src/pyalgoviz/presets/bubble-sort.toml +19 -0
  29. pyalgoviz-0.1.0/src/pyalgoviz/presets/dijkstra-shortest-path.toml +68 -0
  30. pyalgoviz-0.1.0/src/pyalgoviz/pseudocode/__init__.py +0 -0
  31. pyalgoviz-0.1.0/src/pyalgoviz/pseudocode/builtins_registry.py +105 -0
  32. pyalgoviz-0.1.0/src/pyalgoviz/pseudocode/errors.py +8 -0
  33. pyalgoviz-0.1.0/src/pyalgoviz/pseudocode/interpreter.py +312 -0
  34. pyalgoviz-0.1.0/src/pyalgoviz/pseudocode/step_event.py +13 -0
  35. pyalgoviz-0.1.0/src/pyalgoviz/theme.py +137 -0
  36. pyalgoviz-0.1.0/src/pyalgoviz/ui/__init__.py +0 -0
  37. pyalgoviz-0.1.0/src/pyalgoviz/ui/graph_editor_model.py +232 -0
  38. pyalgoviz-0.1.0/src/pyalgoviz/ui/graph_editor_view.py +279 -0
  39. pyalgoviz-0.1.0/src/pyalgoviz/ui/main_window.py +495 -0
  40. pyalgoviz-0.1.0/src/pyalgoviz.egg-info/PKG-INFO +267 -0
  41. pyalgoviz-0.1.0/src/pyalgoviz.egg-info/SOURCES.txt +60 -0
  42. pyalgoviz-0.1.0/src/pyalgoviz.egg-info/dependency_links.txt +1 -0
  43. pyalgoviz-0.1.0/src/pyalgoviz.egg-info/entry_points.txt +2 -0
  44. pyalgoviz-0.1.0/src/pyalgoviz.egg-info/requires.txt +4 -0
  45. pyalgoviz-0.1.0/src/pyalgoviz.egg-info/top_level.txt +1 -0
  46. pyalgoviz-0.1.0/tests/test_algorithms_bfs.py +61 -0
  47. pyalgoviz-0.1.0/tests/test_algorithms_bresenham.py +65 -0
  48. pyalgoviz-0.1.0/tests/test_algorithms_bubble_sort.py +38 -0
  49. pyalgoviz-0.1.0/tests/test_algorithms_dijkstra.py +82 -0
  50. pyalgoviz-0.1.0/tests/test_array_canvas.py +58 -0
  51. pyalgoviz-0.1.0/tests/test_canvas_registry.py +38 -0
  52. pyalgoviz-0.1.0/tests/test_customization_e2e.py +52 -0
  53. pyalgoviz-0.1.0/tests/test_graph_canvas.py +92 -0
  54. pyalgoviz-0.1.0/tests/test_graph_editor_model.py +248 -0
  55. pyalgoviz-0.1.0/tests/test_graph_type.py +61 -0
  56. pyalgoviz-0.1.0/tests/test_grid_canvas.py +56 -0
  57. pyalgoviz-0.1.0/tests/test_interpreter.py +196 -0
  58. pyalgoviz-0.1.0/tests/test_package_smoke.py +5 -0
  59. pyalgoviz-0.1.0/tests/test_plugins.py +96 -0
  60. pyalgoviz-0.1.0/tests/test_preset_loader.py +148 -0
  61. pyalgoviz-0.1.0/tests/test_runner.py +96 -0
  62. pyalgoviz-0.1.0/tests/test_theme.py +59 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Kavindu Fernando
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,267 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyalgoviz
3
+ Version: 0.1.0
4
+ Summary: Pseudocode-driven 2D algorithm visualizer
5
+ Author-email: Kavindu Fernando <kavindufernando329@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/F3rNaNDEZ57/GraphicsAlgoVisualizer
8
+ Project-URL: Repository, https://github.com/F3rNaNDEZ57/GraphicsAlgoVisualizer
9
+ Project-URL: Issues, https://github.com/F3rNaNDEZ57/GraphicsAlgoVisualizer/issues
10
+ Keywords: algorithm-visualization,tkinter,education,pseudocode,dsl
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Environment :: X11 Applications
13
+ Classifier: Intended Audience :: Education
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Topic :: Education
19
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
+ Requires-Python: >=3.11
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: customtkinter>=5.2
24
+ Provides-Extra: dev
25
+ Requires-Dist: pytest; extra == "dev"
26
+ Dynamic: license-file
27
+
28
+ # GraphicsAlgoVisualizer
29
+
30
+ A pseudocode-driven 2D algorithm visualizer built with Python and CustomTkinter. Write algorithms in a simple DSL, pick a canvas type, and watch them execute step-by-step with animated visuals, speed control, and presentation mode.
31
+
32
+ ---
33
+
34
+ ## ✨ Features
35
+
36
+ - **Pseudocode DSL** — Write algorithms in a clean, Python-like subset with `for`, `while`, `if/elif/else`, variables, expressions, and built-in functions. No Python knowledge required.
37
+ - **Multiple Canvas Types** — Grid, Array, and Graph canvases with dedicated renderers and built-in operations.
38
+ - **Bundled Algorithm Presets** — Bresenham line drawing, Bubble sort, BFS pathfinding, and Dijkstra's shortest path ship out of the box as TOML presets.
39
+ - **In-App Graph Editor** — Click to add nodes, drag between nodes to create edges, set weights — build custom networks visually.
40
+ - **Step-by-Step Playback** — Play, pause, step forward, adjust speed, and see line-by-line highlighting of the executing pseudocode.
41
+ - **Presentation Mode** — A distraction-free, canvas-only view for demos and classroom walkthroughs.
42
+ - **Theme System** — Centralized theme tokens drive all canvas and UI colors for a consistent look.
43
+ - **Plugin Architecture** — Drop-in and entry-point based plugin loading. Extend the visualizer with custom canvas types (see the bundled `pyalgoviz-heap-canvas` example).
44
+ - **User Presets** — Save your own algorithms as `.toml` preset files and load them from a user presets directory.
45
+
46
+ ---
47
+
48
+ ## 📋 Prerequisites
49
+
50
+ - **Python 3.11+**
51
+ - **Tkinter** (usually ships with Python; see platform notes below)
52
+ - **Git** (to clone the repo)
53
+
54
+ ---
55
+
56
+ ## 🚀 Getting Started
57
+
58
+ ### 1. Clone the Repository
59
+
60
+ ```bash
61
+ git clone https://github.com/F3rNaNDEZ57/GraphicsAlgoVisualizer.git
62
+ cd GraphicsAlgoVisualizer
63
+ ```
64
+
65
+ ### 2. Create a Virtual Environment
66
+
67
+ #### macOS / Linux
68
+
69
+ ```bash
70
+ python3 -m venv .venv
71
+ source .venv/bin/activate
72
+ ```
73
+
74
+ #### Windows (PowerShell)
75
+
76
+ ```powershell
77
+ python -m venv .venv
78
+ .\.venv\Scripts\Activate.ps1
79
+ ```
80
+
81
+ #### Windows (Command Prompt)
82
+
83
+ ```cmd
84
+ python -m venv .venv
85
+ .venv\Scripts\activate.bat
86
+ ```
87
+
88
+ ### 3. Install the Package
89
+
90
+ Install in editable (development) mode so changes take effect immediately:
91
+
92
+ ```bash
93
+ pip install -e ".[dev]"
94
+ ```
95
+
96
+ > **Note:** The `[dev]` extra includes `pytest` for running tests.
97
+
98
+ ### 4. Run the Visualizer
99
+
100
+ ```bash
101
+ pyalgoviz
102
+ ```
103
+
104
+ Or run directly as a module:
105
+
106
+ ```bash
107
+ python -m pyalgoviz.app
108
+ ```
109
+
110
+ ---
111
+
112
+ ## 🖥️ Platform-Specific Notes
113
+
114
+ ### macOS
115
+
116
+ Tkinter is included with the official Python installer from [python.org](https://www.python.org). If you installed Python via Homebrew, you may need to install it separately:
117
+
118
+ ```bash
119
+ brew install python-tk@3.11
120
+ ```
121
+
122
+ ### Linux (Debian / Ubuntu)
123
+
124
+ ```bash
125
+ sudo apt update
126
+ sudo apt install python3-tk
127
+ ```
128
+
129
+ ### Linux (Fedora)
130
+
131
+ ```bash
132
+ sudo dnf install python3-tkinter
133
+ ```
134
+
135
+ ### Linux (Arch)
136
+
137
+ ```bash
138
+ sudo pacman -S tk
139
+ ```
140
+
141
+ ### Windows
142
+
143
+ Tkinter is bundled with the standard Python installer from [python.org](https://www.python.org). No extra steps needed — just make sure to check **"tcl/tk and IDLE"** during installation if using the custom installer.
144
+
145
+ ---
146
+
147
+ ## 🏗️ Project Structure
148
+
149
+ ```
150
+ GraphicsAlgoVisualizer/
151
+ ├── src/pyalgoviz/
152
+ │ ├── app.py # Entry point
153
+ │ ├── theme.py # Centralized theme tokens
154
+ │ ├── canvas_types.py # Side-effect import to register canvas types
155
+ │ ├── plugins.py # Plugin discovery and loading
156
+ │ ├── preset_loader.py # TOML preset loader
157
+ │ ├── canvas/ # Canvas types, renderers, and registry
158
+ │ │ ├── base.py # Abstract base canvas
159
+ │ │ ├── registry.py # Canvas type registry
160
+ │ │ ├── grid_canvas.py # Grid canvas (e.g., Bresenham)
161
+ │ │ ├── array_canvas.py # Array canvas (e.g., Bubble sort)
162
+ │ │ ├── graph_canvas.py # Graph canvas (e.g., BFS, Dijkstra)
163
+ │ │ └── tk_*_renderer.py # Tkinter renderers for each canvas
164
+ │ ├── engine/ # Step engine and playback state
165
+ │ │ ├── runner.py # Runs pseudocode on a canvas
166
+ │ │ └── playback.py # Play/pause/step state machine
167
+ │ ├── pseudocode/ # DSL interpreter
168
+ │ │ ├── interpreter.py # Pseudocode interpreter
169
+ │ │ ├── builtins_registry.py# Built-in functions (SetCell, Enqueue, etc.)
170
+ │ │ ├── step_event.py # Step event payloads
171
+ │ │ └── errors.py # Error types
172
+ │ ├── presets/ # Bundled TOML algorithm presets
173
+ │ │ ├── bresenham-line.toml
174
+ │ │ ├── bubble-sort.toml
175
+ │ │ ├── bfs-pathfinding.toml
176
+ │ │ └── dijkstra-shortest-path.toml
177
+ │ └── ui/ # CustomTkinter UI layer
178
+ │ ├── main_window.py # Main application window
179
+ │ ├── graph_editor_model.py # Headless graph editor model
180
+ │ └── graph_editor_view.py # Visual graph editor widget
181
+ ├── plugins/ # Drop-in plugin directory
182
+ │ └── pyalgoviz-heap-canvas/ # Example plugin
183
+ ├── tests/ # Test suite (pytest)
184
+ ├── pyproject.toml # Project metadata and build config
185
+ └── .gitignore
186
+ ```
187
+
188
+ ---
189
+
190
+ ## 🧪 Running Tests
191
+
192
+ ```bash
193
+ pytest
194
+ ```
195
+
196
+ Run with verbose output:
197
+
198
+ ```bash
199
+ pytest -v
200
+ ```
201
+
202
+ Run a specific test file:
203
+
204
+ ```bash
205
+ pytest tests/test_interpreter.py
206
+ ```
207
+
208
+ ---
209
+
210
+ ## 📝 Writing a Custom Preset
211
+
212
+ Presets are `.toml` files that define an algorithm's pseudocode, canvas type, and parameters. Place them in the bundled `src/pyalgoviz/presets/` directory or the user presets directory.
213
+
214
+ **Example — a simple grid algorithm:**
215
+
216
+ ```toml
217
+ [meta]
218
+ name = "My Algorithm"
219
+ canvas = "grid"
220
+
221
+ [params]
222
+ width = 20
223
+ height = 20
224
+
225
+ [source]
226
+ code = """
227
+ for x in Range(0, 10):
228
+ SetCell(x, x, "visited")
229
+ """
230
+ ```
231
+
232
+ ### Supported Canvas Types
233
+
234
+ | Canvas | Use Case | Key Builtins |
235
+ |---------|---------------------------------|---------------------------------------|
236
+ | `grid` | 2D grid algorithms | `SetCell`, `GetCell`, `Mark` |
237
+ | `array` | Sorting / linear data | `Swap`, `Compare`, `SetIndex` |
238
+ | `graph` | Graph traversal / shortest path | `Enqueue`, `Dequeue`, `MarkEdge` |
239
+
240
+ ---
241
+
242
+ ## 🔌 Plugins
243
+
244
+ The visualizer supports two plugin mechanisms:
245
+
246
+ 1. **Drop-in plugins** — Place a Python package in the `plugins/` directory. It will be auto-discovered on startup.
247
+ 2. **Entry-point plugins** — Register a `pyalgoviz.canvases` entry point in your package's `pyproject.toml`. Installed packages with this entry point are loaded automatically.
248
+
249
+ See [`plugins/pyalgoviz-heap-canvas/`](plugins/pyalgoviz-heap-canvas/) for a working example.
250
+
251
+ ---
252
+
253
+ ## 🤝 Contributing
254
+
255
+ 1. Fork the repository
256
+ 2. Create a feature branch (`git checkout -b feature/my-feature`)
257
+ 3. Make your changes
258
+ 4. Run the tests (`pytest`)
259
+ 5. Commit with a descriptive message (`git commit -m "Add my feature"`)
260
+ 6. Push to your fork (`git push origin feature/my-feature`)
261
+ 7. Open a Pull Request
262
+
263
+ ---
264
+
265
+ ## 📄 License
266
+
267
+ MIT — see [LICENSE](LICENSE) for details.
@@ -0,0 +1,240 @@
1
+ # GraphicsAlgoVisualizer
2
+
3
+ A pseudocode-driven 2D algorithm visualizer built with Python and CustomTkinter. Write algorithms in a simple DSL, pick a canvas type, and watch them execute step-by-step with animated visuals, speed control, and presentation mode.
4
+
5
+ ---
6
+
7
+ ## ✨ Features
8
+
9
+ - **Pseudocode DSL** — Write algorithms in a clean, Python-like subset with `for`, `while`, `if/elif/else`, variables, expressions, and built-in functions. No Python knowledge required.
10
+ - **Multiple Canvas Types** — Grid, Array, and Graph canvases with dedicated renderers and built-in operations.
11
+ - **Bundled Algorithm Presets** — Bresenham line drawing, Bubble sort, BFS pathfinding, and Dijkstra's shortest path ship out of the box as TOML presets.
12
+ - **In-App Graph Editor** — Click to add nodes, drag between nodes to create edges, set weights — build custom networks visually.
13
+ - **Step-by-Step Playback** — Play, pause, step forward, adjust speed, and see line-by-line highlighting of the executing pseudocode.
14
+ - **Presentation Mode** — A distraction-free, canvas-only view for demos and classroom walkthroughs.
15
+ - **Theme System** — Centralized theme tokens drive all canvas and UI colors for a consistent look.
16
+ - **Plugin Architecture** — Drop-in and entry-point based plugin loading. Extend the visualizer with custom canvas types (see the bundled `pyalgoviz-heap-canvas` example).
17
+ - **User Presets** — Save your own algorithms as `.toml` preset files and load them from a user presets directory.
18
+
19
+ ---
20
+
21
+ ## 📋 Prerequisites
22
+
23
+ - **Python 3.11+**
24
+ - **Tkinter** (usually ships with Python; see platform notes below)
25
+ - **Git** (to clone the repo)
26
+
27
+ ---
28
+
29
+ ## 🚀 Getting Started
30
+
31
+ ### 1. Clone the Repository
32
+
33
+ ```bash
34
+ git clone https://github.com/F3rNaNDEZ57/GraphicsAlgoVisualizer.git
35
+ cd GraphicsAlgoVisualizer
36
+ ```
37
+
38
+ ### 2. Create a Virtual Environment
39
+
40
+ #### macOS / Linux
41
+
42
+ ```bash
43
+ python3 -m venv .venv
44
+ source .venv/bin/activate
45
+ ```
46
+
47
+ #### Windows (PowerShell)
48
+
49
+ ```powershell
50
+ python -m venv .venv
51
+ .\.venv\Scripts\Activate.ps1
52
+ ```
53
+
54
+ #### Windows (Command Prompt)
55
+
56
+ ```cmd
57
+ python -m venv .venv
58
+ .venv\Scripts\activate.bat
59
+ ```
60
+
61
+ ### 3. Install the Package
62
+
63
+ Install in editable (development) mode so changes take effect immediately:
64
+
65
+ ```bash
66
+ pip install -e ".[dev]"
67
+ ```
68
+
69
+ > **Note:** The `[dev]` extra includes `pytest` for running tests.
70
+
71
+ ### 4. Run the Visualizer
72
+
73
+ ```bash
74
+ pyalgoviz
75
+ ```
76
+
77
+ Or run directly as a module:
78
+
79
+ ```bash
80
+ python -m pyalgoviz.app
81
+ ```
82
+
83
+ ---
84
+
85
+ ## 🖥️ Platform-Specific Notes
86
+
87
+ ### macOS
88
+
89
+ Tkinter is included with the official Python installer from [python.org](https://www.python.org). If you installed Python via Homebrew, you may need to install it separately:
90
+
91
+ ```bash
92
+ brew install python-tk@3.11
93
+ ```
94
+
95
+ ### Linux (Debian / Ubuntu)
96
+
97
+ ```bash
98
+ sudo apt update
99
+ sudo apt install python3-tk
100
+ ```
101
+
102
+ ### Linux (Fedora)
103
+
104
+ ```bash
105
+ sudo dnf install python3-tkinter
106
+ ```
107
+
108
+ ### Linux (Arch)
109
+
110
+ ```bash
111
+ sudo pacman -S tk
112
+ ```
113
+
114
+ ### Windows
115
+
116
+ Tkinter is bundled with the standard Python installer from [python.org](https://www.python.org). No extra steps needed — just make sure to check **"tcl/tk and IDLE"** during installation if using the custom installer.
117
+
118
+ ---
119
+
120
+ ## 🏗️ Project Structure
121
+
122
+ ```
123
+ GraphicsAlgoVisualizer/
124
+ ├── src/pyalgoviz/
125
+ │ ├── app.py # Entry point
126
+ │ ├── theme.py # Centralized theme tokens
127
+ │ ├── canvas_types.py # Side-effect import to register canvas types
128
+ │ ├── plugins.py # Plugin discovery and loading
129
+ │ ├── preset_loader.py # TOML preset loader
130
+ │ ├── canvas/ # Canvas types, renderers, and registry
131
+ │ │ ├── base.py # Abstract base canvas
132
+ │ │ ├── registry.py # Canvas type registry
133
+ │ │ ├── grid_canvas.py # Grid canvas (e.g., Bresenham)
134
+ │ │ ├── array_canvas.py # Array canvas (e.g., Bubble sort)
135
+ │ │ ├── graph_canvas.py # Graph canvas (e.g., BFS, Dijkstra)
136
+ │ │ └── tk_*_renderer.py # Tkinter renderers for each canvas
137
+ │ ├── engine/ # Step engine and playback state
138
+ │ │ ├── runner.py # Runs pseudocode on a canvas
139
+ │ │ └── playback.py # Play/pause/step state machine
140
+ │ ├── pseudocode/ # DSL interpreter
141
+ │ │ ├── interpreter.py # Pseudocode interpreter
142
+ │ │ ├── builtins_registry.py# Built-in functions (SetCell, Enqueue, etc.)
143
+ │ │ ├── step_event.py # Step event payloads
144
+ │ │ └── errors.py # Error types
145
+ │ ├── presets/ # Bundled TOML algorithm presets
146
+ │ │ ├── bresenham-line.toml
147
+ │ │ ├── bubble-sort.toml
148
+ │ │ ├── bfs-pathfinding.toml
149
+ │ │ └── dijkstra-shortest-path.toml
150
+ │ └── ui/ # CustomTkinter UI layer
151
+ │ ├── main_window.py # Main application window
152
+ │ ├── graph_editor_model.py # Headless graph editor model
153
+ │ └── graph_editor_view.py # Visual graph editor widget
154
+ ├── plugins/ # Drop-in plugin directory
155
+ │ └── pyalgoviz-heap-canvas/ # Example plugin
156
+ ├── tests/ # Test suite (pytest)
157
+ ├── pyproject.toml # Project metadata and build config
158
+ └── .gitignore
159
+ ```
160
+
161
+ ---
162
+
163
+ ## 🧪 Running Tests
164
+
165
+ ```bash
166
+ pytest
167
+ ```
168
+
169
+ Run with verbose output:
170
+
171
+ ```bash
172
+ pytest -v
173
+ ```
174
+
175
+ Run a specific test file:
176
+
177
+ ```bash
178
+ pytest tests/test_interpreter.py
179
+ ```
180
+
181
+ ---
182
+
183
+ ## 📝 Writing a Custom Preset
184
+
185
+ Presets are `.toml` files that define an algorithm's pseudocode, canvas type, and parameters. Place them in the bundled `src/pyalgoviz/presets/` directory or the user presets directory.
186
+
187
+ **Example — a simple grid algorithm:**
188
+
189
+ ```toml
190
+ [meta]
191
+ name = "My Algorithm"
192
+ canvas = "grid"
193
+
194
+ [params]
195
+ width = 20
196
+ height = 20
197
+
198
+ [source]
199
+ code = """
200
+ for x in Range(0, 10):
201
+ SetCell(x, x, "visited")
202
+ """
203
+ ```
204
+
205
+ ### Supported Canvas Types
206
+
207
+ | Canvas | Use Case | Key Builtins |
208
+ |---------|---------------------------------|---------------------------------------|
209
+ | `grid` | 2D grid algorithms | `SetCell`, `GetCell`, `Mark` |
210
+ | `array` | Sorting / linear data | `Swap`, `Compare`, `SetIndex` |
211
+ | `graph` | Graph traversal / shortest path | `Enqueue`, `Dequeue`, `MarkEdge` |
212
+
213
+ ---
214
+
215
+ ## 🔌 Plugins
216
+
217
+ The visualizer supports two plugin mechanisms:
218
+
219
+ 1. **Drop-in plugins** — Place a Python package in the `plugins/` directory. It will be auto-discovered on startup.
220
+ 2. **Entry-point plugins** — Register a `pyalgoviz.canvases` entry point in your package's `pyproject.toml`. Installed packages with this entry point are loaded automatically.
221
+
222
+ See [`plugins/pyalgoviz-heap-canvas/`](plugins/pyalgoviz-heap-canvas/) for a working example.
223
+
224
+ ---
225
+
226
+ ## 🤝 Contributing
227
+
228
+ 1. Fork the repository
229
+ 2. Create a feature branch (`git checkout -b feature/my-feature`)
230
+ 3. Make your changes
231
+ 4. Run the tests (`pytest`)
232
+ 5. Commit with a descriptive message (`git commit -m "Add my feature"`)
233
+ 6. Push to your fork (`git push origin feature/my-feature`)
234
+ 7. Open a Pull Request
235
+
236
+ ---
237
+
238
+ ## 📄 License
239
+
240
+ MIT — see [LICENSE](LICENSE) for details.
@@ -0,0 +1,49 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "pyalgoviz"
7
+ dynamic = ["version"]
8
+ description = "Pseudocode-driven 2D algorithm visualizer"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ license-files = ["LICENSE"]
12
+ authors = [{ name = "Kavindu Fernando", email = "kavindufernando329@gmail.com" }]
13
+ requires-python = ">=3.11"
14
+ keywords = ["algorithm-visualization", "tkinter", "education", "pseudocode", "dsl"]
15
+ classifiers = [
16
+ "Development Status :: 3 - Alpha",
17
+ "Environment :: X11 Applications",
18
+ "Intended Audience :: Education",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.11",
21
+ "Programming Language :: Python :: 3.12",
22
+ "Programming Language :: Python :: 3.13",
23
+ "Topic :: Education",
24
+ "Topic :: Software Development :: Libraries :: Python Modules",
25
+ ]
26
+ dependencies = ["customtkinter>=5.2"]
27
+
28
+ [project.urls]
29
+ Homepage = "https://github.com/F3rNaNDEZ57/GraphicsAlgoVisualizer"
30
+ Repository = "https://github.com/F3rNaNDEZ57/GraphicsAlgoVisualizer"
31
+ Issues = "https://github.com/F3rNaNDEZ57/GraphicsAlgoVisualizer/issues"
32
+
33
+ [project.optional-dependencies]
34
+ dev = ["pytest"]
35
+
36
+ [project.scripts]
37
+ pyalgoviz = "pyalgoviz.app:main"
38
+
39
+ [tool.setuptools.packages.find]
40
+ where = ["src"]
41
+
42
+ [tool.setuptools.package-data]
43
+ pyalgoviz = ["presets/*.toml"]
44
+
45
+ [tool.setuptools.dynamic]
46
+ version = { attr = "pyalgoviz.__version__" }
47
+
48
+ [tool.pytest.ini_options]
49
+ testpaths = ["tests"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1 @@
1
+ __version__ = "0.1.0"
@@ -0,0 +1,8 @@
1
+ def main() -> None:
2
+ from pyalgoviz.ui.main_window import launch
3
+
4
+ launch()
5
+
6
+
7
+ if __name__ == "__main__":
8
+ main()
File without changes
@@ -0,0 +1,65 @@
1
+ """Array/bars visualization model for sorting-family algorithms. No
2
+ rendering/GUI dependency. The canvas owns the values being visualized —
3
+ pseudocode reads/mutates them only through builtins (Value, SetValue, Swap,
4
+ Compare), never through a raw Python list variable.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from typing import Callable
10
+
11
+
12
+ class ArrayCanvas:
13
+ def __init__(self, values: list[int]):
14
+ self._initial_values = list(values)
15
+ self.values: list[int] = list(values)
16
+ self._change_listeners: list[Callable[[], None]] = []
17
+ self._highlight_listeners: list[Callable[[list[int], str], None]] = []
18
+
19
+ def on_change(self, listener: Callable[[], None]) -> None:
20
+ self._change_listeners.append(listener)
21
+
22
+ def on_highlight(self, listener: Callable[[list[int], str], None]) -> None:
23
+ self._highlight_listeners.append(listener)
24
+
25
+ def detach_listeners(self) -> None:
26
+ """Drops every registered listener -- used when a renderer bound to
27
+ this canvas is being replaced (e.g. presentation-mode zoom), so the
28
+ old renderer's now-destroyed Tk widget doesn't keep getting notified
29
+ alongside the new one."""
30
+ self._change_listeners.clear()
31
+ self._highlight_listeners.clear()
32
+
33
+ def get(self, i: int) -> int:
34
+ return self.values[int(i)]
35
+
36
+ def length(self) -> int:
37
+ return len(self.values)
38
+
39
+ def set_value(self, i: int, value: int) -> None:
40
+ i = int(i)
41
+ self.values[i] = value
42
+ self._notify_change()
43
+ self._notify_highlight([i], "write")
44
+
45
+ def swap(self, i: int, j: int) -> None:
46
+ i, j = int(i), int(j)
47
+ self.values[i], self.values[j] = self.values[j], self.values[i]
48
+ self._notify_change()
49
+ self._notify_highlight([i, j], "swap")
50
+
51
+ def compare(self, i: int, j: int) -> None:
52
+ self._notify_highlight([int(i), int(j)], "compare")
53
+
54
+ def clear(self) -> None:
55
+ self.values = list(self._initial_values)
56
+ self._notify_change()
57
+ self._notify_highlight([], "clear")
58
+
59
+ def _notify_change(self) -> None:
60
+ for listener in self._change_listeners:
61
+ listener()
62
+
63
+ def _notify_highlight(self, indices: list[int], kind: str) -> None:
64
+ for listener in self._highlight_listeners:
65
+ listener(indices, kind)
@@ -0,0 +1,28 @@
1
+ """Registers the "array" canvas type."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+ from .array_canvas import ArrayCanvas
8
+ from .registry import CanvasType, ParamSpec, register
9
+ from .tk_array_renderer import TkArrayRenderer
10
+
11
+ DEFAULT_VALUES = [8, 3, 9, 1, 6, 4, 7, 2, 5]
12
+
13
+
14
+ def _make_canvas(params: dict[str, Any]) -> ArrayCanvas:
15
+ values = params.get("values", DEFAULT_VALUES)
16
+ return ArrayCanvas([int(v) for v in values])
17
+
18
+
19
+ ARRAY_CANVAS_TYPE = CanvasType(
20
+ id="array",
21
+ canvas_params=[ParamSpec("values", "int_list", default=DEFAULT_VALUES, label="Values")],
22
+ make_canvas=_make_canvas,
23
+ viz_builtins={"Swap": "swap", "SetValue": "set_value", "Compare": "compare"},
24
+ plain_builtins={"Value": "get", "Length": "length"},
25
+ renderers={"tk": TkArrayRenderer},
26
+ )
27
+
28
+ register(ARRAY_CANVAS_TYPE)