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.
- pyalgoviz-0.1.0/LICENSE +21 -0
- pyalgoviz-0.1.0/PKG-INFO +267 -0
- pyalgoviz-0.1.0/README.md +240 -0
- pyalgoviz-0.1.0/pyproject.toml +49 -0
- pyalgoviz-0.1.0/setup.cfg +4 -0
- pyalgoviz-0.1.0/src/pyalgoviz/__init__.py +1 -0
- pyalgoviz-0.1.0/src/pyalgoviz/app.py +8 -0
- pyalgoviz-0.1.0/src/pyalgoviz/canvas/__init__.py +0 -0
- pyalgoviz-0.1.0/src/pyalgoviz/canvas/array_canvas.py +65 -0
- pyalgoviz-0.1.0/src/pyalgoviz/canvas/array_type.py +28 -0
- pyalgoviz-0.1.0/src/pyalgoviz/canvas/base.py +17 -0
- pyalgoviz-0.1.0/src/pyalgoviz/canvas/graph_canvas.py +116 -0
- pyalgoviz-0.1.0/src/pyalgoviz/canvas/graph_type.py +126 -0
- pyalgoviz-0.1.0/src/pyalgoviz/canvas/grid_canvas.py +53 -0
- pyalgoviz-0.1.0/src/pyalgoviz/canvas/grid_type.py +35 -0
- pyalgoviz-0.1.0/src/pyalgoviz/canvas/registry.py +56 -0
- pyalgoviz-0.1.0/src/pyalgoviz/canvas/tk_array_renderer.py +75 -0
- pyalgoviz-0.1.0/src/pyalgoviz/canvas/tk_graph_renderer.py +96 -0
- pyalgoviz-0.1.0/src/pyalgoviz/canvas/tk_grid_renderer.py +64 -0
- pyalgoviz-0.1.0/src/pyalgoviz/canvas_types.py +8 -0
- pyalgoviz-0.1.0/src/pyalgoviz/engine/__init__.py +0 -0
- pyalgoviz-0.1.0/src/pyalgoviz/engine/playback.py +7 -0
- pyalgoviz-0.1.0/src/pyalgoviz/engine/runner.py +87 -0
- pyalgoviz-0.1.0/src/pyalgoviz/plugins.py +62 -0
- pyalgoviz-0.1.0/src/pyalgoviz/preset_loader.py +192 -0
- pyalgoviz-0.1.0/src/pyalgoviz/presets/bfs-pathfinding.toml +50 -0
- pyalgoviz-0.1.0/src/pyalgoviz/presets/bresenham-line.toml +63 -0
- pyalgoviz-0.1.0/src/pyalgoviz/presets/bubble-sort.toml +19 -0
- pyalgoviz-0.1.0/src/pyalgoviz/presets/dijkstra-shortest-path.toml +68 -0
- pyalgoviz-0.1.0/src/pyalgoviz/pseudocode/__init__.py +0 -0
- pyalgoviz-0.1.0/src/pyalgoviz/pseudocode/builtins_registry.py +105 -0
- pyalgoviz-0.1.0/src/pyalgoviz/pseudocode/errors.py +8 -0
- pyalgoviz-0.1.0/src/pyalgoviz/pseudocode/interpreter.py +312 -0
- pyalgoviz-0.1.0/src/pyalgoviz/pseudocode/step_event.py +13 -0
- pyalgoviz-0.1.0/src/pyalgoviz/theme.py +137 -0
- pyalgoviz-0.1.0/src/pyalgoviz/ui/__init__.py +0 -0
- pyalgoviz-0.1.0/src/pyalgoviz/ui/graph_editor_model.py +232 -0
- pyalgoviz-0.1.0/src/pyalgoviz/ui/graph_editor_view.py +279 -0
- pyalgoviz-0.1.0/src/pyalgoviz/ui/main_window.py +495 -0
- pyalgoviz-0.1.0/src/pyalgoviz.egg-info/PKG-INFO +267 -0
- pyalgoviz-0.1.0/src/pyalgoviz.egg-info/SOURCES.txt +60 -0
- pyalgoviz-0.1.0/src/pyalgoviz.egg-info/dependency_links.txt +1 -0
- pyalgoviz-0.1.0/src/pyalgoviz.egg-info/entry_points.txt +2 -0
- pyalgoviz-0.1.0/src/pyalgoviz.egg-info/requires.txt +4 -0
- pyalgoviz-0.1.0/src/pyalgoviz.egg-info/top_level.txt +1 -0
- pyalgoviz-0.1.0/tests/test_algorithms_bfs.py +61 -0
- pyalgoviz-0.1.0/tests/test_algorithms_bresenham.py +65 -0
- pyalgoviz-0.1.0/tests/test_algorithms_bubble_sort.py +38 -0
- pyalgoviz-0.1.0/tests/test_algorithms_dijkstra.py +82 -0
- pyalgoviz-0.1.0/tests/test_array_canvas.py +58 -0
- pyalgoviz-0.1.0/tests/test_canvas_registry.py +38 -0
- pyalgoviz-0.1.0/tests/test_customization_e2e.py +52 -0
- pyalgoviz-0.1.0/tests/test_graph_canvas.py +92 -0
- pyalgoviz-0.1.0/tests/test_graph_editor_model.py +248 -0
- pyalgoviz-0.1.0/tests/test_graph_type.py +61 -0
- pyalgoviz-0.1.0/tests/test_grid_canvas.py +56 -0
- pyalgoviz-0.1.0/tests/test_interpreter.py +196 -0
- pyalgoviz-0.1.0/tests/test_package_smoke.py +5 -0
- pyalgoviz-0.1.0/tests/test_plugins.py +96 -0
- pyalgoviz-0.1.0/tests/test_preset_loader.py +148 -0
- pyalgoviz-0.1.0/tests/test_runner.py +96 -0
- pyalgoviz-0.1.0/tests/test_theme.py +59 -0
pyalgoviz-0.1.0/LICENSE
ADDED
|
@@ -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.
|
pyalgoviz-0.1.0/PKG-INFO
ADDED
|
@@ -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 @@
|
|
|
1
|
+
__version__ = "0.1.0"
|
|
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)
|