# YaDraw

YaDraw is a super-simple graphical interface built on top of pygame.
The key use case is when you have a program which performs some calculations, 
and you want to add super-simple visualization to it. YaDraw runs
the graphical interface in a separate thread, so that:
1. GUI is fully responsive during main thread computations.
2. Adding GUI to an existing program is easy and doesn't require program design changes. 

### Minimal example
```python
import yadraw.yadraw as yd
import time

# Create a window
window = yd.Window()

# Fill it with grey color and draw a blue circle
window.fill(color=(100, 100, 100))
window.circle(center=(100, 100), radius=10, color=(0, 0, 255))
window.update()

# Close after 5 seconds
time.sleep(5)
window.close()
```
This example shows the straightforward application approach: the user tells the program what to do.

### Async draw example
Suppose you have a calculation which you want to visualize in real time:
- You have an ongoing calculation (a for loop in this case). 
- The result of this calculation (in this case list_of_points_to_draw) is dynamically updated and needs visualization during calculation.
- The pace of producing results and the pace of visualization (e.i. fps) should be independent.
```python
import yadraw.yadraw as yd
import time


# Create a custom on_redraw handler
def custom_on_redraw(self: yd.Window):
    self.fill((200, 200, 200))  # Fill entire screen with grey color 
    for point in list_of_points_to_draw:  # For each already calculated point
        self.circle(center=point, radius=4, color=(0, 0, 255))  # Draw a blue circle at this point

        
# Monkey-patch the on_redraw handler for yd.Window class
yd.Window.on_redraw = custom_on_redraw

# Create a window, set automatic update to 1 second interval = 1 fps.
window = yd.Window(auto_update_s=1)

# Start the "calculation" of the points to draw
list_of_points_to_draw = []
for i in range(100):  # this loop simulates a calculation of the points to draw 
    time.sleep(0.1)  # calculation takes time
    list_of_points_to_draw.append((i * 8, i * 8))  # adding calculated points

# Await GUI exit (i.e. wait for the user to close the window) 
window.wait_until_exit()
```
This example also shows a different approach compared to the minimal example: 
the user reacts to the events generated by system or pydraw. 
In order to specify the desired behavior, custom event handler is created.

Both approaches can be easily implemented and require nearly no boilerplate code. 

### Using original pygame functions
YaDraw can be used with original pygame functions in case they haven't been implemented yet: 
```python
import yadraw.yadraw as yd
import pygame
import time

# Create a window
window = yd.Window()

# Fill it with grey color and draw a blue circle using original pygame functions
window.surface.fill(color=(100, 100, 100))
pygame.draw.circle(surface=window.surface, center=(100, 100), radius=50, color=(0, 0, 255))
window.update()

# Close after 5 seconds
time.sleep(5)
window.close() 
```

### Areas
The window can be split into multiple areas. Each area can have its own position and scale.
The positions of points are scaled, while the properties such as widths and radii are not.
```python
import yadraw.yadraw as yd
import time

# Create a window
window = yd.Window()

# Adding an area called "main" with shifted origin of coordinates
window.areas["main"] = yd.Area(x0=10, y0=10,  # coordinated of top-left corner of area
                               w=400, h=800,  # area width and height
                               xc=100, yc=100,  # origin of coordinated relative to the top-left corner of area
                               xs=50, ys=50)  # scale
# Fill screen with blue color
window.fill(color=(0, 0, 100))

# Fill the "main" area with grey color and draw a couple of circles
window.areas["main"].fill(color=(100, 100, 100))
window.areas["main"].circle(center=(0, 0), radius=50, color=(0, 0, 255))  # Center at (110, 110), radius is 50
window.areas["main"].circle(center=(1, 1), radius=50, color=(0, 255, 0))  # Center at (160, 160), radius is 50
window.update()

# Close after 5 seconds
time.sleep(5)
window.close()
```

---
Copyright &copy; 2022 [Ivan I. Yakovkin](https://yakovkinii.com)

- [Github](https://github.com/EmixD/yadraw)
- [PyPi](https://pypi.org/project/yadraw/)

