From 5ea9e6bc18d3177fec3dafde1810ba374c9be4e5 Mon Sep 17 00:00:00 2001
From: Naomi Pentrel <5212232+npentrel@users.noreply.github.com>
Date: Sun, 16 Jun 2024 18:32:40 +0100
Subject: [PATCH] Updates
---
docs/hexpansions/.flake8 | 4 -
docs/hexpansions/eeprom.md | 12 +-
docs/hexpansions/writing-hexpansion-apps.md | 27 +--
docs/tildagon-apps/development.md | 40 ++--
docs/tildagon-apps/examples/api.md | 12 +-
.../examples/detect-hexpansion.md | 30 ++-
docs/tildagon-apps/examples/snake.md | 77 ++++---
.../tildagon-apps/reference/badge-hardware.md | 135 +++++++-----
docs/tildagon-apps/reference/ctx.md | 144 +++++++------
docs/tildagon-apps/reference/eventbus.md | 15 +-
docs/tildagon-apps/reference/ui-elements.md | 203 ++++++++++--------
docs/tildagon-apps/simple_tildagon.md | 7 +-
docs/tildagon-apps/simulate.md | 4 +-
13 files changed, 407 insertions(+), 303 deletions(-)
delete mode 100644 docs/hexpansions/.flake8
diff --git a/docs/hexpansions/.flake8 b/docs/hexpansions/.flake8
deleted file mode 100644
index 94e74f5..0000000
--- a/docs/hexpansions/.flake8
+++ /dev/null
@@ -1,4 +0,0 @@
-[flake8]
-extend-ignore = F704, F821, F401, F841
-exclude = .git,build,dist
-max-complexity = 20
\ No newline at end of file
diff --git a/docs/hexpansions/eeprom.md b/docs/hexpansions/eeprom.md
index 58890a0..f8c8bd5 100644
--- a/docs/hexpansions/eeprom.md
+++ b/docs/hexpansions/eeprom.md
@@ -110,17 +110,17 @@ The header is 32 bytes long and contains the following values:
An example implementation of the checksum algorithm in Python:
```python
-
-def calc_checksum(header): #header assumed to be of type bytes
- value=0x55
+def calc_checksum(header): # header assumed to be of type bytes
+ value = 0x55
for b in header[1:]:
- value= value ^ b
+ value = value ^ b
return value
-header_w_checksum = header+bytes([calc_checksum(header)]) #to generate a checksum
-calc_checksum(header_w_checksum) # should return 0 if checksum is correct
+# to generate a checksum
+header_w_checksum = header+bytes([calc_checksum(header)])
+calc_checksum(header_w_checksum) # should return 0 if checksum is correct
```
The header format uses little-endian byte ordering for the individual values, e.g. 0x0123 = 0x01 as least significant byte and 0x23 as most significant byte, resulting in a value of 8961.
diff --git a/docs/hexpansions/writing-hexpansion-apps.md b/docs/hexpansions/writing-hexpansion-apps.md
index ba5b2c7..5857f68 100644
--- a/docs/hexpansions/writing-hexpansion-apps.md
+++ b/docs/hexpansions/writing-hexpansion-apps.md
@@ -55,7 +55,7 @@ Below is an example of how you find which port your hexpansion is plugged in to
def draw(self, ctx):
ctx.save()
clear_background(ctx)
- ctx.rgb(0,1,0).move_to(-90,-40).text("Hello from your\nhexpansion!")
+ ctx.rgb(0, 1, 0).move_to(-90, -40).text("Hello from your\nhexpansion!")
ctx.restore()
return None
@@ -109,7 +109,7 @@ Below is an example of how you find which port your hexpansion is plugged in to
def draw(self, ctx):
ctx.save()
clear_background(ctx)
- ctx.rgb(0,1,0).move_to(-90,-40).text(self.text)
+ ctx.rgb(0, 1, 0).move_to(-90, -40).text(self.text)
ctx.restore()
def scan_for_hexpansion(self):
@@ -132,7 +132,7 @@ Below is an example of how you find which port your hexpansion is plugged in to
# You can add some logic here to check the PID and VID match your hexpansion
return HexpansionConfig(port)
- self.color = (1,0,0)
+ self.color = (1, 0, 0)
self.text = "No hexpansion found."
return None
@@ -181,12 +181,12 @@ Below is an example of how you find which port your hexpansion is plugged in to
# This might look weird, but we're just drawing a shape as a port indicator.
ctx.save()
ctx.font_size = 22
- ctx.rgb(*colors["dark_green"]).rectangle(-120,-120, 240, 100).fill()
+ ctx.rgb(*colors["dark_green"]).rectangle(-120, -120, 240, 100).fill()
ctx.rgb(*colors["dark_green"]).rectangle(-120, 20, 240, 100).fill()
rotation_angle = self.menu.position*pi/3
- ctx.rgb(*colors["mid_green"]).rotate(rotation_angle).rectangle(80,-120,40,240).fill()
+ ctx.rgb(*colors["mid_green"]).rotate(rotation_angle).rectangle(80, -120, 40, 240).fill()
prompt_message = "Select hexpansion port:"
- ctx.rgb(1,1,1).rotate(-rotation_angle).move_to(0,-45).text(prompt_message)
+ ctx.rgb(1, 1, 1).rotate(-rotation_angle).move_to(0, -45).text(prompt_message)
ctx.restore()
else:
@@ -194,7 +194,7 @@ Below is an example of how you find which port your hexpansion is plugged in to
ctx.font_size = 24
msg = "Hexpansion in port " + str(self.hexpansion_config.port)
msg_width = ctx.text_width(msg)
- ctx.rgb(1,1,1).move_to(-msg_width/2,0).text(msg)
+ ctx.rgb(1, 1, 1).move_to(-msg_width/2, 0).text(msg)
ctx.restore()
__app_export__ = ExampleApp
@@ -206,12 +206,13 @@ In all of these examples, the `HexpansionConfig` object is used to provide infor
The `HexpansionConfig` object that you get after following the examples is where the magic all happens. It allows you to access the following:
-| Object | Description | Example Usage |
-| --------------------------- | -------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
-| `HexpansionConfig.port` | The port number your hexpansion is connected to. | |
-| `HexpansionConfig.pin[]` | A list of 4 `Pin` objects. These are the high-speed, direct GPIO pins for this hexpansion port. | [See MicroPython Docs](https://docs.micropython.org/en/latest/library/machine.Pin.html) |
-| `HexpansionConfig.ls_pin[]` | A list of 5 `ePin` objects for this hexpansion port. These are the emulated, low-speed GPIO pins for this hexpansion port. | [See eGPIO](../tildagon-apps/reference/badge-hardware.md#egpio) |
-| `HexpansionConfig.i2c` | The dedicated `I2C` object for this hexpansion port. | [See I2C](../tildagon-apps/reference/badge-hardware.md#i2c) |
+
+| Object | Description | Example Usage |
+| ------ | ----------- | ------------- |
+| `HexpansionConfig.port` | The port number your hexpansion is connected to. | |
+| `HexpansionConfig.pin[]` | A list of 4 `Pin` objects. These are the high-speed, direct GPIO pins for this hexpansion port. | [See MicroPython Docs](https://docs.micropython.org/en/latest/library/machine.Pin.html) |
+| `HexpansionConfig.ls_pin[]` | A list of 5 `ePin` objects for this hexpansion port. These are the emulated, low-speed GPIO pins for this hexpansion port. | [See eGPIO](../tildagon-apps/reference/badge-hardware.md#egpio) |
+| `HexpansionConfig.i2c` | The dedicated `I2C` object for this hexpansion port. | [See I2C](../tildagon-apps/reference/badge-hardware.md#i2c) |
### Pin vs ePin
diff --git a/docs/tildagon-apps/development.md b/docs/tildagon-apps/development.md
index 4d6faee..d874273 100644
--- a/docs/tildagon-apps/development.md
+++ b/docs/tildagon-apps/development.md
@@ -22,17 +22,18 @@ class ExampleApp(app.App):
def update(self, delta):
if self.button_states.get(BUTTON_TYPES["CANCEL"]):
# The button_states do not update while you are in the background.
- # Calling clear() ensures the next time you open the app, it stays open.
- # Without it the app would close again immediately.
+ # Calling clear() ensures the next time you open the app, it stays
+ # open. Without it the app would close again immediately.
self.button_states.clear()
self.minimise()
def draw(self, ctx):
ctx.save()
- ctx.rgb(0.2,0,0).rectangle(-120,-120,240,240).fill()
- ctx.rgb(1,0,0).move_to(-80,0).text("Hello world")
+ ctx.rgb(0.2, 0, 0).rectangle(-120, -120, 240, 240).fill()
+ ctx.rgb(1, 0, 0).move_to(-80, 0).text("Hello world")
ctx.restore()
+
__app_export__ = ExampleApp
```
@@ -171,8 +172,8 @@ Afterwards, you'll learn how to [update state while an app is minimized](#update
self.counter = self.counter + 1
def draw(self, ctx):
- ctx.rgb(0,0.2,0).rectangle(-120,-120,240,240).fill()
- ctx.rgb(0,1,0).move_to(-80,0).text(str(self.counter))
+ ctx.rgb(0, 0.2, 0).rectangle(-120, -120, 240, 240).fill()
+ ctx.rgb(0, 1, 0).move_to(-80, 0).text(str(self.counter))
__app_export__ = RightButtonCounterApp
```
@@ -195,8 +196,8 @@ Afterwards, you'll learn how to [update state while an app is minimized](#update
self.counter = self.counter + 1
def draw(self, ctx):
- ctx.rgb(0,0.2,0).rectangle(-120,-120,240,240).fill()
- ctx.rgb(0,1,0).move_to(-80,0).text(str(self.counter))
+ ctx.rgb(0, 0.2, 0).rectangle(-120, -120, 240, 240).fill()
+ ctx.rgb(0, 1, 0).move_to(-80, 0).text(str(self.counter))
__app_export__ = RightButtonCounterApp
```
@@ -225,8 +226,8 @@ Afterwards, you'll learn how to [update state while an app is minimized](#update
self.counter = self.counter + 1
def draw(self, ctx):
- ctx.rgb(0,0.2,0).rectangle(-120,-120,240,240).fill()
- ctx.rgb(0,1,0).move_to(-80,0).text(str(self.counter))
+ ctx.rgb(0, 0.2, 0).rectangle(-120, -120, 240, 240).fill()
+ ctx.rgb(0, 1, 0).move_to(-80, 0).text(str(self.counter))
__app_export__ = RightButtonCounterApp
```
@@ -244,6 +245,7 @@ import app
from events.input import Buttons, BUTTON_TYPES
+
class TimeCounterApp(app.App):
def __init__(self):
self.button_states = Buttons(self)
@@ -254,13 +256,14 @@ class TimeCounterApp(app.App):
self.button_states.clear()
self.minimise()
- def background_update():
+ def background_update(self):
# if self.button_states.get(BUTTON_TYPES["RIGHT"]):
self.counter = self.counter + 1
def draw(self, ctx):
- ctx.rgb(0,0.2,0).rectangle(-120,-120,240,240).fill()
- ctx.rgb(0,1,0).move_to(-80,0).text(str(self.counter))
+ ctx.rgb(0, 0.2, 0).rectangle(-120, -120, 240, 240).fill()
+ ctx.rgb(0, 1, 0).move_to(-80, 0).text(str(self.counter))
+
__app_export__ = TimeCounterApp
```
@@ -280,6 +283,7 @@ import random
from app_components import clear_background
from events.input import Buttons, BUTTON_TYPES
+
class Rectangle(object):
def __init__(self):
self.r = random.random()
@@ -287,7 +291,7 @@ class Rectangle(object):
self.b = random.random()
def draw(self, ctx):
- ctx.rgb(self.r, self.g, self.b).rectangle(-60,-60,120,120).fill()
+ ctx.rgb(self.r, self.g, self.b).rectangle(-60, -60, 120, 120).fill()
class OverlaysApp(app.App):
@@ -315,6 +319,7 @@ class OverlaysApp(app.App):
clear_background(ctx)
self.draw_overlays(ctx)
+
__app_export__ = OverlaysApp
```
@@ -354,9 +359,11 @@ class BasicApp(app.App):
# Create a yes/no dialogue, add it to the overlays
dialog = YesNoDialog("Change the colour?", self)
self.overlays = [dialog]
- # Wait for an answer from the dialogue, and if it was yes, randomise colour
+ # Wait for an answer from the dialogue, and if it was yes,
+ # randomise colour
if await dialog.run(render_update):
- self.color = (random.random(), random.random(), random.random())
+ self.color = (
+ random.random(), random.random(), random.random())
# Remove the dialogue and re-render
self.overlays = []
@@ -371,6 +378,7 @@ class BasicApp(app.App):
self.draw_overlays(ctx)
+
__app_export__ = BasicApp
```
diff --git a/docs/tildagon-apps/examples/api.md b/docs/tildagon-apps/examples/api.md
index cb9d7a8..d9a149a 100644
--- a/docs/tildagon-apps/examples/api.md
+++ b/docs/tildagon-apps/examples/api.md
@@ -35,7 +35,8 @@ class FilmScheduleApp(app.App):
# When we load, grab all the API data in JSON format
# Requests will automatically convert this to a python dict
# for us, it really is that good!
- self.schedule = requests.get("https://emffilms.org/schedule.json").json()
+ self.schedule = requests.get(
+ "https://emffilms.org/schedule.json").json()
self.button_states = Buttons(self)
# Setup lists to hold our film titles and timings
main_menu_items = []
@@ -56,7 +57,8 @@ class FilmScheduleApp(app.App):
self.notification = None
def select_handler(self, item, position):
- self.notification = Notification('Showing at ' + self.timings[position] + '!')
+ self.notification = Notification(
+ 'Showing at ' + self.timings[position] + '!')
def back_handler(self):
self.button_states.clear()
@@ -67,7 +69,6 @@ class FilmScheduleApp(app.App):
if self.notification:
self.notification.update(delta)
-
def draw(self, ctx):
clear_background(ctx)
# Display the menu on the device
@@ -76,6 +77,7 @@ class FilmScheduleApp(app.App):
if self.notification:
self.notification.draw(ctx)
+
__app_export__ = FilmScheduleApp
```
@@ -136,6 +138,7 @@ def FetchWeather():
print("Error fetching weather data")
raise Exception("Error fetching weather data")
+
class WeatherType:
id: int
main: str
@@ -172,6 +175,7 @@ class WeatherInfo:
def human_readable(self):
return f"{self.weather.main}, {round(self.temp, 1)}°C"
+
class WeatherApp(app.App):
text: str
connected: bool
@@ -217,7 +221,7 @@ class WeatherApp(app.App):
try:
weather = FetchWeather()
self.text = weather.human_readable()
- except:
+ except Exception:
self.text = "API failure.\nTry again."
diff --git a/docs/tildagon-apps/examples/detect-hexpansion.md b/docs/tildagon-apps/examples/detect-hexpansion.md
index 35b3afb..9ea269a 100644
--- a/docs/tildagon-apps/examples/detect-hexpansion.md
+++ b/docs/tildagon-apps/examples/detect-hexpansion.md
@@ -13,18 +13,26 @@ from machine import I2C
from app_components import clear_background
from events.input import Buttons, BUTTON_TYPES
from system.eventbus import eventbus
-from system.hexpansion.events import HexpansionRemovalEvent, HexpansionInsertionEvent
+from system.hexpansion.events import \
+ HexpansionRemovalEvent, HexpansionInsertionEvent
from system.hexpansion.util import read_hexpansion_header, detect_eeprom_addr
+
class ExampleApp(app.App):
def __init__(self):
self.button_states = Buttons(self)
self.text = "No hexpansion found."
- self.color = (1,0,0)
+ self.color = (1, 0, 0)
self.scan_for_hexpansion()
- eventbus.on(HexpansionInsertionEvent, self.handle_hexpansion_insertion, self)
- eventbus.on(HexpansionRemovalEvent, self.handle_hexpansion_removal, self)
+ eventbus.on(
+ HexpansionInsertionEvent,
+ self.handle_hexpansion_insertion,
+ self)
+ eventbus.on(
+ HexpansionRemovalEvent,
+ self.handle_hexpansion_removal,
+ self)
def handle_hexpansion_insertion(self, event):
self.scan_for_hexpansion()
@@ -39,8 +47,8 @@ class ExampleApp(app.App):
def draw(self, ctx):
ctx.save()
clear_background(ctx)
- x,y,z = self.color
- ctx.rgb(x,y,z).move_to(-90,-40).text(self.text)
+ x, y, z = self.color
+ ctx.rgb(x, y, z).move_to(-90, -40).text(self.text)
ctx.restore()
def scan_for_hexpansion(self):
@@ -60,21 +68,21 @@ class ExampleApp(app.App):
continue
else:
print("Read header: " + str(header))
- self.text = "Hexp. found.\nvid: {}\npid: {}\nat port: {}".format(hex(header.vid), hex(header.pid), port)
+ self.text = "Hexp. found.\nvid: {}\npid: {}\nat port: {}".format(
+ hex(header.vid), hex(header.pid), port)
found = True
# Swap 0xCAFE with your EEPROM header vid
# Swap 0xCAFF with your EEPROM header pid
- if (header.vid is 0xCAFE) and (header.pid is 0xCAFF):
+ if (header.vid == 0xCAFE) and (header.pid == 0xCAFF):
print("Found the desired hexpansion in port " + str(port))
- self.color = (0,1,0)
+ self.color = (0, 1, 0)
else:
print()
if not found:
- self.color = (1,0,0)
+ self.color = (1, 0, 0)
self.text = "No hexpansion found."
-
return None
```
diff --git a/docs/tildagon-apps/examples/snake.md b/docs/tildagon-apps/examples/snake.md
index c5d78b3..d2f0107 100644
--- a/docs/tildagon-apps/examples/snake.md
+++ b/docs/tildagon-apps/examples/snake.md
@@ -37,9 +37,9 @@ The badge simulator simulates all apps in the [`sim/apps/`](https://github.com/e
def draw(self, ctx):
ctx.save()
- ctx.rgb(0.2,0,0).rectangle(-120,-120,240,240).fill()
+ ctx.rgb(0.2, 0, 0).rectangle(-120, -120, 240, 240).fill()
ctx.font_size = 14
- ctx.rgb(1,0,0).move_to(-90,0).text("This will be my snake game soon!")
+ ctx.rgb(1, 0, 0).move_to(-90, 0).text("This will be my snake game soon!")
ctx.restore()
__app_export__ = SnakeApp
@@ -118,7 +118,7 @@ def draw(self, ctx):
clear_background(ctx)
ctx.save()
- ctx.translate(-80,-80)
+ ctx.translate(-80, -80)
# draw game board
ctx.rgb(0, 0, 0).rectangle(0, 0, 160, 160).fill()
@@ -147,7 +147,7 @@ class SnakeApp(app.App):
clear_background(ctx)
ctx.save()
- ctx.translate(-80,-80)
+ ctx.translate(-80, -80)
# draw game board
ctx.rgb(0, 0, 0).rectangle(0, 0, 160, 160).fill()
@@ -218,7 +218,7 @@ class SnakeApp(app.App):
clear_background(ctx)
ctx.save()
- ctx.translate(-80,-80)
+ ctx.translate(-80, -80)
# draw game board
ctx.rgb(0, 0, 0).rectangle(0, 0, 160, 160).fill()
@@ -228,6 +228,7 @@ class SnakeApp(app.App):
ctx.restore()
+
__app_export__ = SnakeApp
```
@@ -242,12 +243,16 @@ Next, you'll make your snake move up, down, left, and right using the respective
```python
def update(self, delta):
if self.button_states.get(BUTTON_TYPES["RIGHT"]):
+ print("right")
# do something
elif self.button_states.get(BUTTON_TYPES["LEFT"]):
+ print("left")
# do something
elif self.button_states.get(BUTTON_TYPES["UP"]):
+ print("up")
# do something
elif self.button_states.get(BUTTON_TYPES["DOWN"]):
+ print("down")
# do something
elif self.button_states.get(BUTTON_TYPES["CANCEL"]):
self.button_states.clear()
@@ -349,7 +354,7 @@ class SnakeApp(app.App):
clear_background(ctx)
ctx.save()
- ctx.translate(-80,-80)
+ ctx.translate(-80, -80)
# draw game board
ctx.rgb(0, 0, 0).rectangle(0, 0, 160, 160).fill()
@@ -359,6 +364,7 @@ class SnakeApp(app.App):
ctx.restore()
+
__app_export__ = SnakeApp
```
@@ -404,7 +410,6 @@ class SnakeApp(app.App):
self.direction = ""
self.step = 0
-
def update(self, delta):
if self.button_states.get(BUTTON_TYPES["RIGHT"]):
self.direction = "RIGHT"
@@ -443,7 +448,7 @@ class SnakeApp(app.App):
clear_background(ctx)
ctx.save()
- ctx.translate(-80,-80)
+ ctx.translate(-80, -80)
# draw game board
ctx.rgb(0, 0, 0).rectangle(0, 0, 160, 160).fill()
@@ -453,6 +458,7 @@ class SnakeApp(app.App):
ctx.restore()
+
__app_export__ = SnakeApp
```
@@ -486,17 +492,17 @@ Then, define a `_generate_food()` method that creates random coordinates for a n
```python
def _generate_food(self):
coordinates = (random.randrange(32), random.randrange(32))
- if not coordinates in self.food:
+ if coordinates not in self.food:
self.food = self.food + [coordinates]
```
You could call this method in multiple ways. I suggest you use the `background_task()` method which allows you to add food asynchronously every few seconds:
```python
- async def background_task(self):
- while True:
- await asyncio.sleep(5)
- self._generate_food()
+async def background_task(self):
+ while True:
+ await asyncio.sleep(5)
+ self._generate_food()
```
Add the `asyncio` package at the top of your file:
@@ -583,7 +589,7 @@ class SnakeApp(app.App):
def _generate_food(self):
coordinates = (random.randrange(32), random.randrange(32))
- if not coordinates in self.food:
+ if coordinates not in self.food:
self.food = self.food + [coordinates]
async def background_task(self):
@@ -595,7 +601,7 @@ class SnakeApp(app.App):
clear_background(ctx)
ctx.save()
- ctx.translate(-80,-80)
+ ctx.translate(-80, -80)
# draw game board
ctx.rgb(0, 0, 0).rectangle(0, 0, 160, 160).fill()
@@ -609,6 +615,7 @@ class SnakeApp(app.App):
ctx.restore()
+
__app_export__ = SnakeApp
```
@@ -704,10 +711,9 @@ class SnakeApp(app.App):
self.food.remove(self.snake[0])
self.snake = self.snake + [self.snake[0]]
-
def _generate_food(self):
coordinates = (random.randrange(32), random.randrange(32))
- if not coordinates in self.food:
+ if coordinates not in self.food:
self.food = self.food + [coordinates]
async def background_task(self):
@@ -719,7 +725,7 @@ class SnakeApp(app.App):
clear_background(ctx)
ctx.save()
- ctx.translate(-80,-80)
+ ctx.translate(-80, -80)
# draw game board
ctx.rgb(0, 0, 0).rectangle(0, 0, 160, 160).fill()
@@ -733,6 +739,7 @@ class SnakeApp(app.App):
ctx.restore()
+
__app_export__ = SnakeApp
```
@@ -777,7 +784,7 @@ Draw the score before you call the `translate()` method:
# draw score
ctx.font_size = 12
width = ctx.text_width("Score: {}".format(self.score))
-ctx.rgb(1,0,0).move_to(0 - width/2,100).text("Score: {}".format(self.score))
+ctx.rgb(1, 0, 0).move_to(0 - width/2, 100).text("Score: {}".format(self.score))
```
Your app should now resemble this:
@@ -802,7 +809,6 @@ class SnakeApp(app.App):
self.step = 0
self.score = 0
-
def update(self, delta):
if self.button_states.get(BUTTON_TYPES["RIGHT"]):
self.direction = "RIGHT"
@@ -843,10 +849,9 @@ class SnakeApp(app.App):
self.snake = self.snake + [self.snake[0]]
self.score = self.score + 1
-
def _generate_food(self):
coordinates = (random.randrange(32), random.randrange(32))
- if not coordinates in self.food:
+ if coordinates not in self.food:
self.food = self.food + [coordinates]
async def background_task(self):
@@ -861,9 +866,10 @@ class SnakeApp(app.App):
# draw score
ctx.font_size = 12
width = ctx.text_width("Score: {}".format(self.score))
- ctx.rgb(1,0,0).move_to(0 - width/2,100).text("Score: {}".format(self.score))
+ ctx.rgb(1, 0, 0).move_to(0 - width/2, 100).text(
+ "Score: {}".format(self.score))
- ctx.translate(-80,-80)
+ ctx.translate(-80, -80)
# draw game board
ctx.rgb(0, 0, 0).rectangle(0, 0, 160, 160).fill()
@@ -877,6 +883,7 @@ class SnakeApp(app.App):
ctx.restore()
+
__app_export__ = SnakeApp
```
@@ -998,7 +1005,7 @@ Define the `_reset()` method and make it reset the game state:
```python
def _reset(self):
- self.snake = [(16,16)]
+ self.snake = [(16, 16)]
self.food = []
self.direction = ""
self.score = 0
@@ -1048,7 +1055,7 @@ class SnakeApp(app.App):
self.dialog = None
def _reset(self):
- self.snake = [(16,16)]
+ self.snake = [(16, 16)]
self.food = []
self.direction = ""
self.score = 0
@@ -1059,7 +1066,6 @@ class SnakeApp(app.App):
self.button_states.clear()
self.minimise()
-
def update(self, delta):
if self.button_states.get(BUTTON_TYPES["RIGHT"]):
self.direction = "RIGHT"
@@ -1091,7 +1097,8 @@ class SnakeApp(app.App):
on_no=self._exit,
app=self,
)
- # Reset the game variable to ensure this dialog is only created once
+ # Reset the game variable to ensure this dialog is only created
+ # once
self.game = ""
def _move_snake(self):
@@ -1124,7 +1131,7 @@ class SnakeApp(app.App):
def _generate_food(self):
coordinates = (random.randrange(32), random.randrange(32))
- if not coordinates in self.food:
+ if coordinates not in self.food:
self.food = self.food + [coordinates]
async def background_task(self):
@@ -1140,9 +1147,10 @@ class SnakeApp(app.App):
# draw score
ctx.font_size = 12
width = ctx.text_width("Score: {}".format(self.score))
- ctx.rgb(1,0,0).move_to(0 - width/2,100).text("Score: {}".format(self.score))
+ ctx.rgb(1, 0, 0).move_to(0 - width/2, 100).text(
+ "Score: {}".format(self.score))
- ctx.translate(-80,-80)
+ ctx.translate(-80, -80)
# draw game board
ctx.rgb(0, 0, 0).rectangle(0, 0, 160, 160).fill()
@@ -1159,6 +1167,7 @@ class SnakeApp(app.App):
if self.dialog:
self.dialog.draw(ctx)
+
__app_export__ = SnakeApp
```
@@ -1223,11 +1232,13 @@ def update(self, delta):
else:
# Use Y coordinate to go left or right
if self.acc_read[1] > 0:
- # A positive Y coordinate indicates the badge is tilted to the right
+ # A positive Y coordinate indicates the badge is tilted to the
+ # right
self.direction = "RIGHT"
self.game = "ON"
else:
- # A positive Y coordinate indicates the badge is tilted to the left
+ # A positive Y coordinate indicates the badge is tilted to the
+ # left
self.direction = "LEFT"
self.game = "ON"
diff --git a/docs/tildagon-apps/reference/badge-hardware.md b/docs/tildagon-apps/reference/badge-hardware.md
index b4622c0..40a180e 100644
--- a/docs/tildagon-apps/reference/badge-hardware.md
+++ b/docs/tildagon-apps/reference/badge-hardware.md
@@ -15,13 +15,15 @@ from app_components import clear_background
from events.input import Buttons, BUTTON_TYPES
from tildagonos import tildagonos
from system.eventbus import eventbus
-from system.patterndisplay.events import *
+from system.patterndisplay.events import PatternDisable
+
class LEDExampleApp(app.App):
def __init__(self):
self.button_states = Buttons(self)
- # This disables the patterndisplay system module, which does the default colour spinny thing
+ # This disables the patterndisplay system module, which does the
+ # default colour spinny thing
eventbus.emit(PatternDisable())
def update(self, delta):
@@ -44,12 +46,13 @@ class LEDExampleApp(app.App):
tildagonos.leds[4] = (255, 0, 255)
tildagonos.leds[5] = (255, 0, 255)
else:
- for i in range(0,12):
+ for i in range(0, 12):
tildagonos.leds[i+1] = (0, 0, 0)
def draw(self, ctx):
clear_background(ctx)
+
__app_export__ = LEDExampleApp
```
@@ -98,6 +101,7 @@ from app_components import clear_background
from events.input import Buttons, BUTTON_TYPES
from tildagonos import tildagonos
+
class LEDExampleApp(app.App):
def __init__(self):
self.button_states = Buttons(self)
@@ -122,12 +126,13 @@ class LEDExampleApp(app.App):
tildagonos.leds[4] = (255, 0, 255)
tildagonos.leds[5] = (255, 0, 255)
else:
- for i in range(0,12):
+ for i in range(0, 12):
tildagonos.leds[i+1] = (0, 0, 0)
def draw(self, ctx):
clear_background(ctx)
+
__app_export__ = LEDExampleApp
```
@@ -170,7 +175,8 @@ You can also use the `ButtonDownEvent` and the `ButtonUpEvent` directly with an
1. Import the `events.input` package:
```python
- from events.input import Button, BUTTON_TYPES, ButtonDownEvent, ButtonUpEvent
+ from events.input import \
+ Button, BUTTON_TYPES, ButtonDownEvent, ButtonUpEvent
from system.eventbus import eventbus
```
@@ -231,7 +237,7 @@ Select a hexpansion port, then press the **UP** button to toggle the eGPIO value
```python
import app
-from system.hexpansion.config import *
+from system.hexpansion.config import HexpansionConfig
from app_components import clear_background, Menu
from app_components.tokens import colors
from events.input import Buttons, BUTTON_TYPES
@@ -239,9 +245,11 @@ from math import pi
menu_items = ["1", "2", "3", "4", "5", "6"]
+
class ExampleApp(app.App):
def __init__(self):
- self.menu = Menu(self, menu_items, select_handler=self.select_handler, back_handler=self.back_handler)
+ self.menu = Menu(self, menu_items, select_handler=self.select_handler,
+ back_handler=self.back_handler)
self.hexpansion_config = None
self.button_states = Buttons(self)
self.pins = {}
@@ -291,12 +299,16 @@ class ExampleApp(app.App):
# Drawing a shape as a port indicator.
ctx.save()
ctx.font_size = 22
- ctx.rgb(*colors["dark_green"]).rectangle(-120,-120, 240, 100).fill()
- ctx.rgb(*colors["dark_green"]).rectangle(-120, 20, 240, 100).fill()
+ ctx.rgb(*colors["dark_green"]).rectangle(
+ -120, -120, 240, 100).fill()
+ ctx.rgb(*colors["dark_green"]).rectangle(
+ -120, 20, 240, 100).fill()
rotation_angle = self.menu.position*pi/3
- ctx.rgb(*colors["mid_green"]).rotate(rotation_angle).rectangle(80,-120,40,240).fill()
+ ctx.rgb(*colors["mid_green"]).rotate(rotation_angle).rectangle(
+ 80, -120, 40, 240).fill()
prompt_message = "Select hexpansion port:"
- ctx.rgb(1,1,1).rotate(-rotation_angle).move_to(0,-45).text(prompt_message)
+ ctx.rgb(1, 1, 1).rotate(-rotation_angle).move_to(
+ 0, -45).text(prompt_message)
ctx.restore()
else:
@@ -304,19 +316,20 @@ class ExampleApp(app.App):
ctx.font_size = 24
msg = "Hexpansion in port " + str(self.hexpansion_config.port)
msg_width = ctx.text_width(msg)
- ctx.rgb(1,1,1).move_to(-msg_width/2,0).text(msg)
+ ctx.rgb(1, 1, 1).move_to(-msg_width/2, 0).text(msg)
# draw pin values
pin_ls_1 = "LS_1: " + str(self.pins["ls_1"].value())
msg_width = ctx.text_width(pin_ls_1)
- ctx.rgb(1,1,1).move_to(-msg_width/2,-90).text(pin_ls_1)
+ ctx.rgb(1, 1, 1).move_to(-msg_width/2, -90).text(pin_ls_1)
pin_hs_1 = "HS_1: " + str(self.pins["hs_1"].value())
msg_width = ctx.text_width(pin_hs_1)
- ctx.rgb(1,1,1).move_to(-msg_width/2,90).text(pin_hs_1)
+ ctx.rgb(1, 1, 1).move_to(-msg_width/2, 90).text(pin_hs_1)
ctx.restore()
+
__app_export__ = ExampleApp
```
@@ -328,11 +341,12 @@ GPIO pins support the standard [`machine.Pin` methods](https://docs.micropython.
[eGPIO pins](https://github.com/emfcamp/badge-2024-software/blob/main/modules/tildagon/pins.py) support the following methods:
-| Method | Description | Arguments | Returns |
-| --------- | ---------------------------------------------------------------------------------------------- | --------- | ---------------------------------------------------- |
-| `on()` | Drive the pin high. | None | None |
-| `off()` | Drive the pin low. | None | None |
-| `value()` | If provided with a value, sets the `Pin` value. If called without value, gets the `Pin` value. | None | `value`: The pin value. If called without a `value`. |
+
+| Method | Description | Arguments | Returns |
+| ------ | ----------- | --------- | ------- |
+| `on()` | Drive the pin high. | None | None |
+| `off()` | Drive the pin low. | None | None |
+| `value()` | If provided with a value, sets the `Pin` value. If called without value, gets the `Pin` value. | None | `value`: The pin value. If called without a `value`. |
### Usage
@@ -385,13 +399,16 @@ class ExampleApp(app.App):
def draw(self, ctx):
ctx.save()
- ctx.rgb(0.2,0,0).rectangle(-120,-120,240,240).fill()
+ ctx.rgb(0.2, 0, 0).rectangle(-120, -120, 240, 240).fill()
if self.acc_read:
- ctx.rgb(1,0,0).move_to(-80,-40).text("accel x,y,z:\n{},\n{},\n{}".format(self.acc_read[0], self.acc_read[1], self.acc_read[2]))
+ ctx.rgb(1, 0, 0).move_to(-80, -40).text(
+ "accel x,y,z:\n{},\n{},\n{}".format(
+ self.acc_read[0], self.acc_read[1], self.acc_read[2]))
else:
- ctx.rgb(1,0,0).move_to(-80,0).text("no readings yet")
+ ctx.rgb(1, 0, 0).move_to(-80, 0).text("no readings yet")
ctx.restore()
+
__app_export__ = ExampleApp
```
@@ -399,10 +416,11 @@ __app_export__ = ExampleApp
The api currently only allows access to the raw data.
-| Method | Description | Arguments | Returns |
-| ------------- | --------------------------- | --------- | --------------------------------------------------------------- |
-| `acc_read()` | Get the accelerometer data. | None | `(x,y,z)`: The accelerometer data as a tuple of floats (m/s^2). |
-| `gyro_read()` | Get the gyro data. | None | `(x,y,z)`: The gyro data as a tuple of floats (d/s). |
+
+| Method | Description | Arguments | Returns |
+| ------ | ----------- | --------- | ------- |
+| `acc_read()` | Get the accelerometer data. | None | `(x,y,z)`: The accelerometer data as a tuple of floats (m/s^2). |
+| `gyro_read()` | Get the gyro data. | None | `(x,y,z)`: The gyro data as a tuple of floats (d/s). |
### Usage
@@ -447,10 +465,11 @@ class ExampleApp(app.App):
def draw(self, ctx):
ctx.save()
- ctx.rgb(0.2,0,0).rectangle(-120,-120,240,240).fill()
- ctx.rgb(1,0,0).move_to(-80,0).text("Press up to\npower off")
+ ctx.rgb(0.2, 0, 0).rectangle(-120, -120, 240, 240).fill()
+ ctx.rgb(1, 0, 0).move_to(-80, 0).text("Press up to\npower off")
ctx.restore()
+
__app_export__ = ExampleApp
```
@@ -472,18 +491,19 @@ To use the `power` package:
### Methods
-| Method | Description | Arguments | Returns |
-| ---------------------- | --------------------------------------------------------------------------- | ----------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `Off()` | Turn off the battery. When the usb is disconnected the badge will turn off. | None | None |
-| `BatteryChargeState()` | Status of the Battery charing cycle. | None | `status` (`string`): `"Not Charging"`, `"Pre-Charging"`, `"Fast Charging"`, `"Terminated"`. |
-| `BatteryLevel()` | Return the battery charge level. | None. | `level` (`float`): Battery charge level as a float representing the charge percentage. |
-| `Enable5V()` | Enable the usb out 5V supply. | `enable` (`Boolean`): whether to enable or disable the 5V supply. | None. |
-| `Fault()` | Get the PMIC fault status. | None. | - `fault`: The battery fault. Battery: Normal, Over Voltage; Boost: Normal, Overloaded or low battery; Charge: Normal, Input Fault, Safety Timer expired |
-| `SupplyCapabilities()` | Read the capabilities of the power supply. | None. | `capabilities` (`List`): List of tuples containing supply type, voltage (V) and current (mA). |
-| `Icharge()` | Get the battery charge current | None. | `current` (`float`): The charge current in mA. |
-| `Vbat()` | Get the battery voltage. | None. | `voltage` (`float`): The battery voltage in V. |
-| `Vin()` | Get the input voltage. | None. | `voltage` (`float`): The input voltage in V. |
-| `Vsys()` (`float`) | Get the system voltage. | None. | `voltage` (`float`): Get the system voltage in V. |
+
+| Method | Description | Arguments | Returns |
+| ------ | ----------- | --------- | ------- |
+| `Off()`| Turn off the battery. When the usb is disconnected the badge will turn off. | None | None |
+| `BatteryChargeState()` | Status of the Battery charing cycle. | None | `status` (`string`): `"Not Charging"`, `"Pre-Charging"`, `"Fast Charging"`, `"Terminated"`. |
+| `BatteryLevel()` | Return the battery charge level. | None. | `level` (`float`): Battery charge level as a float representing the charge percentage. |
+| `Enable5V()` | Enable the usb out 5V supply. | `enable` (`Boolean`): whether to enable or disable the 5V supply. | None. |
+| `Fault()` | Get the PMIC fault status. | None. | - `fault`: The battery fault. Battery: Normal, Over Voltage; Boost: Normal, Overloaded or low battery; Charge: Normal, Input Fault, Safety Timer expired |
+| `SupplyCapabilities()` | Read the capabilities of the power supply. | None. | `capabilities` (`List`): List of tuples containing supply type, voltage (V) and current (mA). |
+| `Icharge()` | Get the battery charge current | None. | `current` (`float`): The charge current in mA. |
+| `Vbat()` | Get the battery voltage. | None. | `voltage` (`float`): The battery voltage in V. |
+| `Vin()` | Get the input voltage. | None. | `voltage` (`float`): The input voltage in V. |
+| `Vsys()` (`float`) | Get the system voltage. | None. | `voltage` (`float`): Get the system voltage in V. |
### Events
@@ -517,7 +537,8 @@ You can also use the following hexpansion-related events
To use these events with the `EventBus`, import the following package:
```python
-from system.hexpansion.events import HexpansionRemovalEvent, HexpansionInsertionEvent
+from system.hexpansion.events import \
+ HexpansionRemovalEvent, HexpansionInsertionEvent
```
Then `emit()` the event as following:
@@ -536,7 +557,7 @@ The badge supports the [I2C communication protocol](https://www.circuitbasics.co
```python
from machine import I2C
-bus = I2C(slot)
+bus = I2C(1)
```
=== "App loaded from EEPROM"
@@ -570,7 +591,7 @@ bus = I2C(slot)
def draw(self, ctx):
ctx.save()
clear_background(ctx)
- ctx.rgb(0,1,0).move_to(-90,-40).text("Hello from your\nhexpansion!")
+ ctx.rgb(0, 1, 0).move_to(-90, -40).text("Hello from your\nhexpansion!")
ctx.restore()
return None
@@ -621,7 +642,7 @@ bus = I2C(slot)
def draw(self, ctx):
ctx.save()
clear_background(ctx)
- ctx.rgb(0,1,0).move_to(-90,-40).text(self.text)
+ ctx.rgb(0, 1, 0).move_to(-90, -40).text(self.text)
ctx.restore()
def scan_for_hexpansion(self):
@@ -643,7 +664,7 @@ bus = I2C(slot)
self.text = "Hexp. found.\nvid: {}\npid: {}\nat port: {}".format(hex(header.vid), hex(header.pid), port)
return HexpansionConfig(port)
- self.color = (1,0,0)
+ self.color = (1, 0, 0)
self.text = "No hexpansion found."
return None
@@ -658,15 +679,21 @@ Example usage from the [MicroPython I2C docs](https://docs.micropython.org/en/la
```python
from machine import I2C
-i2c.scan() # scan for peripherals, returning a list of 7-bit addresses
-
-i2c.writeto(42, b'123') # write 3 bytes to peripheral with 7-bit address 42
-i2c.readfrom(42, 4) # read 4 bytes from peripheral with 7-bit address 42
-
-i2c.readfrom_mem(42, 8, 3) # read 3 bytes from memory of peripheral 42,
- # starting at memory-address 8 in the peripheral
-i2c.writeto_mem(42, 2, b'\x10') # write 1 byte to memory of peripheral 42
- # starting at address 2 in the peripheral
+i2c = I2C(freq=400000)
+
+# scan for peripherals, returning a list of 7-bit addresses
+i2c.scan()
+
+# write 3 bytes to peripheral with 7-bit address 42
+i2c.writeto(42, b'123')
+# read 4 bytes from peripheral with 7-bit address 42
+i2c.readfrom(42, 4)
+# read 3 bytes from memory of peripheral 42, starting at memory-address 8 in
+# the peripheral
+i2c.readfrom_mem(42, 8, 3)
+# write 1 byte to memory of peripheral 42 starting at address 2 in the
+# peripheral
+i2c.writeto_mem(42, 2, b'\x10')
```
For more information, see [MicroPython I2C docs](https://docs.micropython.org/en/latest/library/machine.I2C.html).
diff --git a/docs/tildagon-apps/reference/ctx.md b/docs/tildagon-apps/reference/ctx.md
index 8e82a69..6861ad0 100644
--- a/docs/tildagon-apps/reference/ctx.md
+++ b/docs/tildagon-apps/reference/ctx.md
@@ -30,6 +30,7 @@ class ExampleApp(app.App):
def draw(self, ctx):
clear_background(ctx)
+
__app_export__ = ExampleApp
```
@@ -37,7 +38,7 @@ __app_export__ = ExampleApp
### Coordinates of the display area
-With `ctx`, you need to provide a place for where to draw objects using coordinates in the form of `(x,y)`. The x-coordinate represents the horizontal coordinate and the y-coordinate the vertical. The middle is at `(0,0)`.
+With `ctx`, you need to provide a place for where to draw objects using coordinates in the form of `(x, y)`. The x-coordinate represents the horizontal coordinate and the y-coordinate the vertical. The middle is at `(0, 0)`.
{: style="width:400px;height: auto;margin:auto;display:block;" }
@@ -49,7 +50,6 @@ The following is the code for the axes drawing:
```python
import app
-import math
from app_components import clear_background
from events.input import Buttons, BUTTON_TYPES
@@ -67,12 +67,12 @@ class ExampleApp(app.App):
def draw(self, ctx):
clear_background(ctx)
ctx.rgb(0, 1, 0).begin_path()
- ctx.move_to(-120,0)
+ ctx.move_to(-120, 0)
ctx.line_to(120, 0)
ctx.move_to(0, 120)
ctx.line_to(0, -120)
- for i in range(-5,6):
+ for i in range(-5, 6):
# draw indicator lines for x
ctx.move_to(i*20, 5)
ctx.line_to(i*20, -5)
@@ -83,13 +83,14 @@ class ExampleApp(app.App):
# text for x and y
ctx.stroke()
- for i in range(-5,6):
+ for i in range(-5, 6):
ctx.font_size = 12
width = ctx.text_width(str(i*20))
# x axes
ctx.rgb(0, 1, 0).move_to(i*20 - width/2, 15).text(i*20)
# y axes
- ctx.rgb(0, 1, 0).move_to(-15 - width, i*20 + 2*line_height).text(i*20)
+ ctx.rgb(0, 1, 0).move_to(
+ -15 - width, i*20 + 2*line_height).text(i*20)
width = ctx.text_width("y")
ctx.rgb(0, 1, 0).move_to(+15, -100+2*line_height).text("y")
@@ -97,6 +98,7 @@ class ExampleApp(app.App):
width = ctx.text_width("x")
ctx.rgb(0, 1, 0).move_to(100 - width/2, -15).text("x")
+
__app_export__ = ExampleApp
```
@@ -179,6 +181,7 @@ class ExampleApp(app.App):
ctx.rectangle(0, 30, 5, 5).fill()
ctx.rectangle(0, 40, 5, 5).fill()
+
__app_export__ = ExampleApp
```
@@ -216,6 +219,7 @@ class ExampleApp(app.App):
ctx.restore()
+
__app_export__ = ExampleApp
```
@@ -251,6 +255,7 @@ class ExampleApp(app.App):
ctx.restore()
+
__app_export__ = ExampleApp
```
@@ -280,12 +285,13 @@ class ExampleApp(app.App):
ctx.save()
ctx.radial_gradient(30, 30, 80, -30, -50, 70)
- ctx.add_stop(0, (100,0,100), 0.5)
- ctx.add_stop(1, (100,0,0), 0.8)
+ ctx.add_stop(0, (100, 0, 100), 0.5)
+ ctx.add_stop(1, (100, 0, 0), 0.8)
ctx.rectangle(-100, -100, 200, 200).fill()
ctx.restore()
+
__app_export__ = ExampleApp
```
@@ -294,7 +300,6 @@ __app_export__ = ExampleApp
This example shows an example of a linear gradient on a rectangle.
```python
-import asyncio
import app
from events.input import Buttons, BUTTON_TYPES
@@ -310,7 +315,7 @@ class ExampleApp(app.App):
def draw(self, ctx):
ctx.save()
- ctx.linear_gradient(0.18*120,0.5*120,0.95*120,0.5*120)
+ ctx.linear_gradient(0.18*120, 0.5*120, 0.95*120, 0.5*120)
ctx.add_stop(0.0, (255, 0, 0), 1.0)
ctx.add_stop(0.2, (255, 255, 0), 1.0)
ctx.add_stop(0.4, (0, 255, 0), 1.0)
@@ -323,6 +328,7 @@ class ExampleApp(app.App):
ctx.restore()
+
__app_export__ = ExampleApp
```
@@ -356,6 +362,7 @@ class ExampleApp(app.App):
ctx.gray(1.0).arc(30, 0, 40, 0, 2 * math.pi, True).fill()
ctx.restore()
+
__app_export__ = ExampleApp
```
@@ -382,10 +389,11 @@ class ExampleApp(app.App):
def draw(self, ctx):
ctx.save()
ctx.font = ctx.get_font_name(5)
- ctx.rgb(100, 0, 0).rectangle(-120,-120,240,240).fill()
- ctx.rgb(255, 0, 0).move_to(-80,0).text("Hello world")
+ ctx.rgb(100, 0, 0).rectangle(-120, -120, 240, 240).fill()
+ ctx.rgb(255, 0, 0).move_to(-80, 0).text("Hello world")
ctx.restore()
+
__app_export__ = ExampleApp
```
@@ -432,9 +440,10 @@ class ExampleApp(app.App):
ctx.rgb(255, 0, 0).move_to(-55, -10).text(line_1)
ctx.rgb(255, 0, 0).move_to(-55, 10).text(line_2)
else:
- ctx.rgb(255, 0, 0).move_to(-55, 0).text(text)
+ ctx.rgb(255, 0, 0).move_to(-55, 0).text(text)
ctx.restore()
+
__app_export__ = ExampleApp
```
@@ -471,6 +480,7 @@ class ExampleApp(app.App):
ctx.rgb(0, 0, 200).arc(0, 0, 10, 0, 2 * math.pi, True).stroke()
ctx.restore()
+
__app_export__ = ExampleApp
```
@@ -511,6 +521,7 @@ class ExampleApp(app.App):
ctx.rgb(255, 0, 0).fill()
ctx.restore()
+
__app_export__ = ExampleApp
```
@@ -538,11 +549,12 @@ class ExampleApp(app.App):
def draw(self, ctx):
clear_background(ctx)
ctx.save()
- ctx.rgb(100,0,0).rectangle(-40, 0, 40, 20).fill()
+ ctx.rgb(100, 0, 0).rectangle(-40, 0, 40, 20).fill()
ctx.scale(1, 3)
- ctx.rgb(0,100,0).rectangle(0, 0, 40, 20).fill()
+ ctx.rgb(0, 100, 0).rectangle(0, 0, 40, 20).fill()
ctx.restore()
+
__app_export__ = ExampleApp
```
@@ -570,11 +582,12 @@ class ExampleApp(app.App):
clear_background(ctx)
ctx.save()
ctx.rotate(math.pi)
- ctx.rgb(100,0,0).rectangle(-40, 0, 40, 20).fill()
+ ctx.rgb(100, 0, 0).rectangle(-40, 0, 40, 20).fill()
ctx.scale(1, 3)
- ctx.rgb(0,100,0).rectangle(0, 0, 40, 20).fill()
+ ctx.rgb(0, 100, 0).rectangle(0, 0, 40, 20).fill()
ctx.restore()
+
__app_export__ = ExampleApp
```
@@ -601,13 +614,14 @@ class ExampleApp(app.App):
def draw(self, ctx):
clear_background(ctx)
ctx.save()
- ctx.translate(-50,0)
+ ctx.translate(-50, 0)
ctx.rotate(math.pi)
- ctx.rgb(100,0,0).rectangle(-40, 0, 40, 20).fill()
+ ctx.rgb(100, 0, 0).rectangle(-40, 0, 40, 20).fill()
ctx.scale(1, 3)
- ctx.rgb(0,100,0).rectangle(0, 0, 40, 20).fill()
+ ctx.rgb(0, 100, 0).rectangle(0, 0, 40, 20).fill()
ctx.restore()
+
__app_export__ = ExampleApp
```
@@ -623,6 +637,7 @@ import app
from app_components import clear_background
from events.input import Buttons, BUTTON_TYPES
+
class ExampleApp(app.App):
def __init__(self):
self.button_states = Buttons(self)
@@ -635,13 +650,14 @@ class ExampleApp(app.App):
clear_background(ctx)
ctx.save()
ctx.rgb(1, 0, 0).begin_path()
- ctx.move_to(0,0)
+ ctx.move_to(0, 0)
ctx.line_to(50, 50)
ctx.move_to(-30, 50)
ctx.line_to(50, 80)
ctx.stroke()
ctx.restore()
+
__app_export__ = ExampleApp
```
@@ -657,6 +673,7 @@ import app
from app_components import clear_background
from events.input import Buttons, BUTTON_TYPES
+
class ExampleApp(app.App):
def __init__(self):
self.button_states = Buttons(self)
@@ -669,7 +686,7 @@ class ExampleApp(app.App):
clear_background(ctx)
ctx.save()
ctx.rgb(1, 0, 0).begin_path()
- ctx.move_to(0,0)
+ ctx.move_to(0, 0)
ctx.line_to(50, 50)
ctx.stroke()
ctx.rgb(0, 1, 0)
@@ -678,6 +695,7 @@ class ExampleApp(app.App):
ctx.stroke()
ctx.restore()
+
__app_export__ = ExampleApp
```
@@ -689,11 +707,11 @@ This example draws a triangle.
```python
import app
-import math
from app_components import clear_background
from events.input import Buttons, BUTTON_TYPES
+
class ExampleApp(app.App):
def __init__(self):
self.button_states = Buttons(self)
@@ -713,6 +731,7 @@ class ExampleApp(app.App):
ctx.stroke()
ctx.restore()
+
__app_export__ = ExampleApp
```
@@ -729,6 +748,7 @@ import math
from app_components import clear_background
from events.input import Buttons, BUTTON_TYPES
+
class ExampleApp(app.App):
def __init__(self):
self.button_states = Buttons(self)
@@ -747,24 +767,25 @@ class ExampleApp(app.App):
# end point (e, f): (60, 80)
# Add cubic bézier curve
- ctx.move_to(-80,-80)
+ ctx.move_to(-80, -80)
ctx.curve_to(-70, 0, 60, 20, 60, 80)
ctx.stroke()
# Show start and end points in blue
ctx.rgb(0, 0, 1).begin_path()
- ctx.arc(-80,-80, 5, 0, 2 * math.pi, True) # start point
- ctx.arc(60, 80, 5, 0, 2 * math.pi, True) # end point
+ ctx.arc(-80, -80, 5, 0, 2 * math.pi, True) # start point
+ ctx.arc(60, 80, 5, 0, 2 * math.pi, True) # end point
ctx.fill()
# Show control points in green
ctx.rgb(0, 1, 0).begin_path()
- ctx.arc(-70, 0, 5, 0, 2 * math.pi, True) # first control point
- ctx.arc(60, 20, 5, 0, 2 * math.pi, True) # second control point
+ ctx.arc(-70, 0, 5, 0, 2 * math.pi, True) # first control point
+ ctx.arc(60, 20, 5, 0, 2 * math.pi, True) # second control point
ctx.fill()
ctx.restore()
+
__app_export__ = ExampleApp
```
@@ -780,36 +801,37 @@ __app_export__ = ExampleApp
You can use the following methods on a `ctx` canvas object:
-| Method | Description | Arguments | Returns |
-| ------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- |
-| `move_to(x, y)` | Begin a new sub-path at the point specified by the given `(x, y)` coordinates. |
- `x`: The x-axis (horizontal) coordinate of the point.
- `y`: The y-axis (vertical) coordinate of the point.
| `self`: The `ctx` object. |
-| `curve_to(a, b, c, d, e, f)` | Add a cubic [Bézier curve](https://developer.mozilla.org/en-US/docs/Glossary/Bezier_curve) to the current sub-path. It requires three points: the first two are control points and the third one is the end point. The starting point is the latest point in the current path, which can be changed using `moveTo()` before creating the Bézier curve. | - `a`: The x-axis coordinate of the first control point.
- `b`: The y-axis coordinate of the first control point.
- `c`: The x-axis coordinate of the second control point.
- `d`: The y-axis coordinate of the second control point.
- `e`: The x-axis coordinate of the end point.
- `f`: The y-axis coordinate of the end point.
| `self`: The `ctx` object. |
-| `quad_to(a, b, c, d)` | Add a quadratic [Bézier curve](https://developer.mozilla.org/en-US/docs/Glossary/Bezier_curve) to the current sub-path. It requires two points: the first one is a control point and the second one is the end point. The starting point is the latest point in the current path, which can be changed using `moveTo()` before creating the quadratic Bézier curve. | - `a`: The x-axis coordinate of the control point.
- `b`: The y-axis coordinate of the control point.
- `c`: The x-axis coordinate of the end point.
- `d`: The y-axis coordinate of the end point.
| `self`: The `ctx` object. |
-| `rel_move_to(x, y)` | Begin a new sub-path at the point specified reached by adding `(x, y)` to the current coordinates. | - `x`: The new sub-path will begin at the coordinates reached by moving `x` units horizontally and `y` units vertically on the grid.
- `y`: The new sub-path will begin at the coordinates reached by moving `x` units horizontally and `y` units vertically on the grid.
| `self`: The `ctx` object. |
-| `rel_curve_to(a, b, c, d, e, f)` | Add a cubic Bézier curve to the current sub-path relative to the current position instead of relative to `(0, 0, 0)`. It requires three points: the first two are control points and the third one is the end point. The starting point is the latest point in the current path, which can be changed using `moveTo()` before creating the Bézier curve. | - `a`: The x-axis coordinate of the first control point specified relative to the current point. That means, you must specify the units to move on the x axis from the current point.
- `b`: The y-axis coordinate of the first control point specified relative to the current point. That means, you must specify the units to move on the y axis from the current point.
- `c`: The x-axis coordinate of the second control point specified relative to the current point.
- `d`: The y-axis coordinate of the second control point specified relative to the current point.
- `e`: The x-axis coordinate of the end point specified relative to the current point.
- `f`: The y-axis coordinate of the end point specified relative to the current point.
| `self`: The `ctx` object. |
-| `rel_quad_to(a, b, c, d)` | Add a quadratic Bézier curve to the current sub-path relative to the current position. It requires two points: the first one is a control point and the second one is the end point. The starting point is the latest point in the current path, which can be changed using `moveTo()` before creating the quadratic Bézier curve. | - `a`: The x-axis coordinate of the control point specified relative to the current point. That means, you must specify the units to move on the x axis from the current point.
- `b`: The y-axis coordinate of the control point specified relative to the current point. That means, you must specify the units to move on the y axis from the current point.
- `c`: The x-axis coordinate of the end point.
- `d`: The y-axis coordinate of the end point.
| `self`: The `ctx` object. |
-| `close_path()` | Attempt to add a straight line from the current point to the start of the current sub-path. If the shape has already been closed or has only one point, this function does nothing. This method doesn't draw anything to the canvas directly. You can render the path using the stroke() or fill() methods. | None. | `self`: The `ctx` object. |
-| `translate(x, y)` | Add a translation transformation to the current matrix by moving the canvas and its origin `x` units horizontally and `y` units vertically on the grid. | - `x`: Distance to move in the horizontal direction. Positive values are to the right, and negative to the left.
- `y`: Distance to move in the vertical direction. Positive values are down, and negative are up.
| `self`: The `ctx` object. |
-| `scale(x, y)` | Add a scaling transformation to the canvas units horizontally and/or vertically. By default, one unit on the canvas is exactly one pixel. A scaling transformation modifies this behavior. For instance, a scaling factor of 0.5 results in a unit size of 0.5 pixels; shapes are thus drawn at half the normal size. Similarly, a scaling factor of 2.0 increases the unit size so that one unit becomes two pixels; shapes are thus drawn at twice the normal size. | - `x`: Scaling factor in the horizontal direction. A negative value flips pixels across the vertical axis. A value of `1` results in no horizontal scaling.
- `y`: Scaling factor in the vertical direction. A negative value flips pixels across the horizontal axis. A value of `1` results in no vertical scaling.
| `self`: The `ctx` object. |
-| `line_to(x, y)` | Add a straight line to the current sub-path by connecting the sub-path's last point to the specified `(x, y)` coordinates. Like other methods that modify the current path, this method does not directly render anything. To draw the path onto a canvas, you can use the `fill()` or `stroke()` methods. | - `x`: The x-axis coordinate of the line's end point.
- `y`: The y-axis coordinate of the line's end point.
| `self`: The `ctx` object. |
-| `rel_line_to(x, y)` | Add a straight line to the current sub-path by connecting the sub-path's last point to a point moved `x` units horizontally and `y` units vertically on the grid. Like other methods that modify the current path, this method does not directly render anything. To draw the path onto a canvas, you can use the `fill()` or `stroke()` methods. | - `x`: The path will be drawn towards a point moved horizontally by `x` units and vertically by `y` units.
- `y`: The path will be drawn towards a point moved horizontally by `x` units and vertically by `y` units.
| `self`: The `ctx` object. |
-| `rotate(v)` | Add a rotation to the transformation matrix. The rotation center point is always the canvas origin. To change the center point, you will need to move the canvas by using the `translate()` method. | `v`: The rotation angle, clockwise in radians. You can use degree \* pi / 180 to calculate a radian from a degree. | `self`: The `ctx` object. |
-| `gray(v)` | Sets the color of the canvas to a color between `0.0` (black) and `1.0`. | `v`: Intensity of the gray color. `0.0` results in black and `1.0` in white. | `self`: The `ctx` object. |
-| `rgba(r, g, b, a)` | Color the canvas in the color `(r, g, b)` with an alpha channel. | - `r`: The intensity of the color with a value between `0` and `255` or between `0.0` and `1.0`.
- `g`: The intensity of the color with a value between `0` and `255` or between `0.0` and `1.0`.
- `b`: The intensity of the color with a value between `0` and `255` or between `0.0` and `1.0`.
- `a`: The alpha channel which specifies the opacity for a color between `0.0` (fully transparent) and `1.0` (not transparent at all).
| `self`: The `ctx` object. |
-| `rgb(r, g, b)` | Color the canvas in the color `(r, g, b)`. | - `r`: The intensity of the color with a value between `0` and `255` or between `0.0` and `1.0`.
- `g`: The intensity of the color with a value between `0` and `255` or between `0.0` and `1.0`.
- `b`: The intensity of the color with a value between `0` and `255` or between `0.0` and `1.0`.
| `self`: The `ctx` object. |
-| `text(s)` | Draw the provided text on the canvas. | `s`: The text to draw provided as a string. | `self`: The `ctx` object. |
-| `round_rectangle(x, y, width, height, radius)` | Add a rounded rectangle on the canvas at position `(x, y)` with the provided width, height, and corner radius. | - `x`: The horizontal position to draw the rectangle at.
- `y`: The vertical position to draw the rectangle at.
- `width`: The width of the rectangle to draw.
- `height`: The height of the rectangle to draw.
- `radius`: The radius of the rectangle's corners.
| `self`: The `ctx` object. |
-| `image(path, x, y, w, h)` | **Currently not functional.** Draw an image to be read from the provided path onto the canvas. | - `path`: The path to an image file.
- `x`: The x-axis coordinate of the top left corner of the image to draw.
- `y`: The y-axis coordinate of the top left corner of the image to draw.
- `w`: The width of the image to draw.
- `h`: The height of the image to draw.
| `self`: The `ctx` object. |
-| `rectangle(x, y, width, height)` | Add a rectangle to the current path. Like other methods that modify the current path, this method does not directly render anything. To draw the rectangle onto a canvas, you can use the `fill()` or `stroke()` methods. The `rect()` method creates a rectangular path whose starting point is at `(x, y)` and whose size is specified by width and height. | - `x`: The x-axis coordinate (horizontal) of the rectangle's starting point.
- `y`: The y-axis coordinate (vertical) of the rectangle's starting point.
- `width`: The rectangle's width. Positive values are to the right, and negative to the left.
- `height`: The rectangle's height. Positive values are down, and negative are up.
| `self`: The `ctx` object. |
-| `stroke()` | Stroke (outline) the current or given path with the current stroke style. | None. | `self`: The `ctx` object. |
-| `save()` | Save the entire state of the canvas by pushing the current state onto a stack. | None. | `self`: The `ctx` object. |
-| `restore()` | Restore the most recently saved canvas state by popping the top entry in the drawing state stack. If there is no saved state, this method does nothing. | None. | `self`: The `ctx` object. |
-| `fill()` | Fill the current or given path. | None. | `self`: The `ctx` object. |
-| `radial_gradient(x0, y0, r0, x1, y1, r1)` | Create a radial gradient using the size and coordinates of two circles. | - `x0`: The x-axis coordinate of the start circle.
- `y0`: The y-axis coordinate of the start circle.
- `r0`: The radius of the start circle. Must be non-negative and finite.
- `x1`: The x-axis coordinate of the end circle.
- `y1`: The y-axis coordinate of the end circle.
- `r1`: The radius of the end circle. Must be non-negative and finite.
| `self`: The `ctx` object. |
-| `linear_gradient(x0, y0, x1, y1)` | Create a gradient along the line connecting two given coordinates. | - `x0`: The x-axis coordinate of the start point.
- `y0`: The y-axis coordinate of the start point.
- `x1`: The x-axis coordinate of the end point.
- `y1`: The y-axis coordinate of the end point.
| `self`: The `ctx` object. |
-| `add_stop(pos, color, alpha)` | Adds a color stop in a gradient with the provided position, color, and alpha values. | `pos`: The position of the stop determining the order of the stops. - `color`: The colour at the stop.
- `alpha`: The opacity value of the colour at the stop.
| `self`: The `ctx` object. |
-| `begin_path()` | Start a new path by emptying the list of sub-paths. Call this method when you want to create a new path. | None. | `self`: The `ctx` object. |
-| `arc(x, y, radius, arc_from, arc_to, direction)` | Add a circular arc to the current sub-path. | - `x`: The horizontal coordinate of the arc's center.
- `y`: The vertical coordinate of the arc's center.
- `radius`: The arc's radius. Must be positive.
- `arg_from`: The angle at which the arc starts in radians, measured from the positive x-axis.
- `arg_to`: The angle at which the arc ends in radians, measured from the positive x-axis.
- `direction`: A boolean value. If true, draws the arc counter-clockwise between the start and end angles.
| `self`: The `ctx` object. |
-| `text_width(text)` | Calculate the width of the provided text. | `text`: The text to calculate the width of. | `width`: The width of the provided text. |
-| `clip()` | Turn the current or given path into the current clipping region. The previous clipping region, if any, is intersected with the current or given path to create the new clipping region. For a visual example, see the [mdn web docs](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/clip). | None. | `self`: The `ctx` object. |
-| `get_font_name(i)` | Get the name of one of the 9 fonts: `"Arimo Regular"`, `"Arimo Bold"`, `"Arimo Italic"`, `"Arimo Bold Italic"`, `"Camp Font 1"`, `"Camp Font 2"`, `"Camp Font 3"`, `"Material Icons"`, and `"Comic Mono"`. | `i`: The number of the font to get the name of. A number between `0` and `8`. | `font_name`: The font. |
+
+| Method | Description | Arguments | Returns |
+| ------ | ----------- | --------- | ------- |
+| `move_to(x, y)` | Begin a new sub-path at the point specified by the given `(x, y)` coordinates. | - `x`: The x-axis (horizontal) coordinate of the point.
- `y`: The y-axis (vertical) coordinate of the point.
| `self`: The `ctx` object. |
+| `curve_to(a, b, c, d, e, f)` | Add a cubic [Bézier curve](https://developer.mozilla.org/en-US/docs/Glossary/Bezier_curve) to the current sub-path. It requires three points: the first two are control points and the third one is the end point. The starting point is the latest point in the current path, which can be changed using `moveTo()` before creating the Bézier curve. | - `a`: The x-axis coordinate of the first control point.
- `b`: The y-axis coordinate of the first control point.
- `c`: The x-axis coordinate of the second control point.
- `d`: The y-axis coordinate of the second control point.
- `e`: The x-axis coordinate of the end point.
- `f`: The y-axis coordinate of the end point.
| `self`: The `ctx` object. |
+| `quad_to(a, b, c, d)` | Add a quadratic [Bézier curve](https://developer.mozilla.org/en-US/docs/Glossary/Bezier_curve) to the current sub-path. It requires two points: the first one is a control point and the second one is the end point. The starting point is the latest point in the current path, which can be changed using `moveTo()` before creating the quadratic Bézier curve. | - `a`: The x-axis coordinate of the control point.
- `b`: The y-axis coordinate of the control point.
- `c`: The x-axis coordinate of the end point.
- `d`: The y-axis coordinate of the end point.
| `self`: The `ctx` object. |
+| `rel_move_to(x, y)` | Begin a new sub-path at the point specified reached by adding `(x, y)` to the current coordinates. | - `x`: The new sub-path will begin at the coordinates reached by moving `x` units horizontally and `y` units vertically on the grid.
- `y`: The new sub-path will begin at the coordinates reached by moving `x` units horizontally and `y` units vertically on the grid.
| `self`: The `ctx` object. |
+| `rel_curve_to(a, b, c, d, e, f)` | Add a cubic Bézier curve to the current sub-path relative to the current position instead of relative to `(0, 0, 0)`. It requires three points: the first two are control points and the third one is the end point. The starting point is the latest point in the current path, which can be changed using `moveTo()` before creating the Bézier curve. | - `a`: The x-axis coordinate of the first control point specified relative to the current point. That means, you must specify the units to move on the x axis from the current point.
- `b`: The y-axis coordinate of the first control point specified relative to the current point. That means, you must specify the units to move on the y axis from the current point.
- `c`: The x-axis coordinate of the second control point specified relative to the current point.
- `d`: The y-axis coordinate of the second control point specified relative to the current point.
- `e`: The x-axis coordinate of the end point specified relative to the current point.
- `f`: The y-axis coordinate of the end point specified relative to the current point.
| `self`: The `ctx` object. |
+| `rel_quad_to(a, b, c, d)` | Add a quadratic Bézier curve to the current sub-path relative to the current position. It requires two points: the first one is a control point and the second one is the end point. The starting point is the latest point in the current path, which can be changed using `moveTo()` before creating the quadratic Bézier curve. | - `a`: The x-axis coordinate of the control point specified relative to the current point. That means, you must specify the units to move on the x axis from the current point.
- `b`: The y-axis coordinate of the control point specified relative to the current point. That means, you must specify the units to move on the y axis from the current point.
- `c`: The x-axis coordinate of the end point.
- `d`: The y-axis coordinate of the end point.
| `self`: The `ctx` object. |
+| `close_path()` | Attempt to add a straight line from the current point to the start of the current sub-path. If the shape has already been closed or has only one point, this function does nothing. This method doesn't draw anything to the canvas directly. You can render the path using the stroke() or fill() methods. | None. | `self`: The `ctx` object. |
+| `translate(x, y)` | Add a translation transformation to the current matrix by moving the canvas and its origin `x` units horizontally and `y` units vertically on the grid. | - `x`: Distance to move in the horizontal direction. Positive values are to the right, and negative to the left.
- `y`: Distance to move in the vertical direction. Positive values are down, and negative are up.
| `self`: The `ctx` object. |
+| `scale(x, y)` | Add a scaling transformation to the canvas units horizontally and/or vertically. By default, one unit on the canvas is exactly one pixel. A scaling transformation modifies this behavior. For instance, a scaling factor of 0.5 results in a unit size of 0.5 pixels; shapes are thus drawn at half the normal size. Similarly, a scaling factor of 2.0 increases the unit size so that one unit becomes two pixels; shapes are thus drawn at twice the normal size. | - `x`: Scaling factor in the horizontal direction. A negative value flips pixels across the vertical axis. A value of `1` results in no horizontal scaling.
- `y`: Scaling factor in the vertical direction. A negative value flips pixels across the horizontal axis. A value of `1` results in no vertical scaling.
| `self`: The `ctx` object. |
+| `line_to(x, y)` | Add a straight line to the current sub-path by connecting the sub-path's last point to the specified `(x, y)` coordinates. Like other methods that modify the current path, this method does not directly render anything. To draw the path onto a canvas, you can use the `fill()` or `stroke()` methods. | - `x`: The x-axis coordinate of the line's end point.
- `y`: The y-axis coordinate of the line's end point.
| `self`: The `ctx` object. |
+| `rel_line_to(x, y)` | Add a straight line to the current sub-path by connecting the sub-path's last point to a point moved `x` units horizontally and `y` units vertically on the grid. Like other methods that modify the current path, this method does not directly render anything. To draw the path onto a canvas, you can use the `fill()` or `stroke()` methods. | - `x`: The path will be drawn towards a point moved horizontally by `x` units and vertically by `y` units.
- `y`: The path will be drawn towards a point moved horizontally by `x` units and vertically by `y` units.
| `self`: The `ctx` object. |
+| `rotate(v)` | Add a rotation to the transformation matrix. The rotation center point is always the canvas origin. To change the center point, you will need to move the canvas by using the `translate()` method. | `v`: The rotation angle, clockwise in radians. You can use degree \* pi / 180 to calculate a radian from a degree. | `self`: The `ctx` object. |
+| `gray(v)` | Sets the color of the canvas to a color between `0.0` (black) and `1.0`. | `v`: Intensity of the gray color. `0.0` results in black and `1.0` in white. | `self`: The `ctx` object. |
+| `rgba(r, g, b, a)` | Color the canvas in the color `(r, g, b)` with an alpha channel. | - `r`: The intensity of the color with a value between `0` and `255` or between `0.0` and `1.0`.
- `g`: The intensity of the color with a value between `0` and `255` or between `0.0` and `1.0`.
- `b`: The intensity of the color with a value between `0` and `255` or between `0.0` and `1.0`.
- `a`: The alpha channel which specifies the opacity for a color between `0.0` (fully transparent) and `1.0` (not transparent at all).
| `self`: The `ctx` object. |
+| `rgb(r, g, b)` | Color the canvas in the color `(r, g, b)`. | - `r`: The intensity of the color with a value between `0` and `255` or between `0.0` and `1.0`.
- `g`: The intensity of the color with a value between `0` and `255` or between `0.0` and `1.0`.
- `b`: The intensity of the color with a value between `0` and `255` or between `0.0` and `1.0`.
| `self`: The `ctx` object. |
+| `text(s)` | Draw the provided text on the canvas. | `s`: The text to draw provided as a string. | `self`: The `ctx` object. |
+| `round_rectangle(x, y, width, height, radius)` | Add a rounded rectangle on the canvas at position `(x, y)` with the provided width, height, and corner radius. | - `x`: The horizontal position to draw the rectangle at.
- `y`: The vertical position to draw the rectangle at.
- `width`: The width of the rectangle to draw.
- `height`: The height of the rectangle to draw.
- `radius`: The radius of the rectangle's corners.
| `self`: The `ctx` object. |
+| `image(path, x, y, w, h)` | **Currently not functional.** Draw an image to be read from the provided path onto the canvas. | - `path`: The path to an image file.
- `x`: The x-axis coordinate of the top left corner of the image to draw.
- `y`: The y-axis coordinate of the top left corner of the image to draw.
- `w`: The width of the image to draw.
- `h`: The height of the image to draw.
| `self`: The `ctx` object. |
+| `rectangle(x, y, width, height)` | Add a rectangle to the current path. Like other methods that modify the current path, this method does not directly render anything. To draw the rectangle onto a canvas, you can use the `fill()` or `stroke()` methods. The `rect()` method creates a rectangular path whose starting point is at `(x, y)` and whose size is specified by width and height. | - `x`: The x-axis coordinate (horizontal) of the rectangle's starting point.
- `y`: The y-axis coordinate (vertical) of the rectangle's starting point.
- `width`: The rectangle's width. Positive values are to the right, and negative to the left.
- `height`: The rectangle's height. Positive values are down, and negative are up.
| `self`: The `ctx` object. |
+| `stroke()` | Stroke (outline) the current or given path with the current stroke style. | None. | `self`: The `ctx` object. |
+| `save()` | Save the entire state of the canvas by pushing the current state onto a stack. | None. | `self`: The `ctx` object. |
+| `restore()` | Restore the most recently saved canvas state by popping the top entry in the drawing state stack. If there is no saved state, this method does nothing. | None. | `self`: The `ctx` object. |
+| `fill()` | Fill the current or given path. | None. | `self`: The `ctx` object. |
+| `radial_gradient(x0, y0, r0, x1, y1, r1)` | Create a radial gradient using the size and coordinates of two circles. | - `x0`: The x-axis coordinate of the start circle.
- `y0`: The y-axis coordinate of the start circle.
- `r0`: The radius of the start circle. Must be non-negative and finite.
- `x1`: The x-axis coordinate of the end circle.
- `y1`: The y-axis coordinate of the end circle.
- `r1`: The radius of the end circle. Must be non-negative and finite.
| `self`: The `ctx` object. |
+| `linear_gradient(x0, y0, x1, y1)` | Create a gradient along the line connecting two given coordinates. | - `x0`: The x-axis coordinate of the start point.
- `y0`: The y-axis coordinate of the start point.
- `x1`: The x-axis coordinate of the end point.
- `y1`: The y-axis coordinate of the end point.
| `self`: The `ctx` object. |
+| `add_stop(pos, color, alpha)` | Adds a color stop in a gradient with the provided position, color, and alpha values. | `pos`: The position of the stop determining the order of the stops. - `color`: The colour at the stop.
- `alpha`: The opacity value of the colour at the stop.
| `self`: The `ctx` object. |
+| `begin_path()` | Start a new path by emptying the list of sub-paths. Call this method when you want to create a new path. | None. | `self`: The `ctx` object. |
+| `arc(x, y, radius, arc_from, arc_to, direction)` | Add a circular arc to the current sub-path. | - `x`: The horizontal coordinate of the arc's center.
- `y`: The vertical coordinate of the arc's center.
- `radius`: The arc's radius. Must be positive.
- `arg_from`: The angle at which the arc starts in radians, measured from the positive x-axis.
- `arg_to`: The angle at which the arc ends in radians, measured from the positive x-axis.
- `direction`: A boolean value. If true, draws the arc counter-clockwise between the start and end angles.
| `self`: The `ctx` object. |
+| `text_width(text)` | Calculate the width of the provided text. | `text`: The text to calculate the width of. | `width`: The width of the provided text. |
+| `clip()` | Turn the current or given path into the current clipping region. The previous clipping region, if any, is intersected with the current or given path to create the new clipping region. For a visual example, see the [mdn web docs](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/clip). | None. | `self`: The `ctx` object. |
+| `get_font_name(i)` | Get the name of one of the 9 fonts: `"Arimo Regular"`, `"Arimo Bold"`, `"Arimo Italic"`, `"Arimo Bold Italic"`, `"Camp Font 1"`, `"Camp Font 2"`, `"Camp Font 3"`, `"Material Icons"`, and `"Comic Mono"`. | `i`: The number of the font to get the name of. A number between `0` and `8`. | `font_name`: The font. |
diff --git a/docs/tildagon-apps/reference/eventbus.md b/docs/tildagon-apps/reference/eventbus.md
index c8fd383..4508096 100644
--- a/docs/tildagon-apps/reference/eventbus.md
+++ b/docs/tildagon-apps/reference/eventbus.md
@@ -77,10 +77,11 @@ You can see a more comprehensive example in [`dialog.py`](https://github.com/emf
You can use the following methods on the `eventbus`:
-| Method | Description | Arguments | Returns |
-| ------------------------------------------ | -------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
-| `on(event_type, event_handler, app)` | Register an event for an app alongside the synchronous handler to be called when the event fires. | event_type
: The event, for example `ButtonDownEvent`. An `event` object must have the methods `__init__()` and `__str__()`.event_handler
: The synchronous function to be called when the event fires to handle the event.app
: The app this event is being registered for.
| None |
-| `on_async(event_type, event_handler, app)` | Register an event for an app alongside the asynchronous handler to be called when the event fires. | event_type
: The event, for example `ButtonDownEvent`. An `event` object must have the methods `__init__()` and `__str__()`.event_handler
: The asynchronous function to be called when the event fires to handle the event.app
: The app this event is being registered for.
| None |
-| `emit(event)` | Emit an event to the eventbus. The handler for the event must be synchronous. | `event` : The event, for example `ButtonDownEvent`. An `event` object must have the methods `__init__()` and `__str__()`. | None |
-| `emit_async(event)` | Emit an event to the eventbus. The handler for the event must be asynchronous. | `event` : The event, for example `ButtonDownEvent`. An `event` object must have the methods `__init__()` and `__str__()`. | None |
-| `remove(event_type, event_handler, app)` | Remove the event for an app from the eventbus. | event_type
: The event to be removed.event_handler
: The asynchronous function to be called when the event fires to handle the event.app
: The app this event is being removed for.
| None |
+
+| Method | Description | Arguments | Returns |
+| ------ | ----------- | --------- | ------- |
+| `on(event_type, event_handler, app)` | Register an event for an app alongside the synchronous handler to be called when the event fires. | event_type
: The event, for example `ButtonDownEvent`. An `event` object must have the methods `__init__()` and `__str__()`.event_handler
: The synchronous function to be called when the event fires to handle the event.app
: The app this event is being registered for.
| None |
+| `on_async(event_type, event_handler, app)` | Register an event for an app alongside the asynchronous handler to be called when the event fires. | event_type
: The event, for example `ButtonDownEvent`. An `event` object must have the methods `__init__()` and `__str__()`.event_handler
: The asynchronous function to be called when the event fires to handle the event.app
: The app this event is being registered for.
| None |
+| `emit(event)` | Emit an event to the eventbus. The handler for the event must be synchronous. | `event` : The event, for example `ButtonDownEvent`. An `event` object must have the methods `__init__()` and `__str__()`. | None |
+| `emit_async(event)` | Emit an event to the eventbus. The handler for the event must be asynchronous. | `event` : The event, for example `ButtonDownEvent`. An `event` object must have the methods `__init__()` and `__str__()`. | None |
+| `remove(event_type, event_handler, app)` | Remove the event for an app from the eventbus. | event_type
: The event to be removed.event_handler
: The asynchronous function to be called when the event fires to handle the event.app
: The app this event is being removed for.
| None |
diff --git a/docs/tildagon-apps/reference/ui-elements.md b/docs/tildagon-apps/reference/ui-elements.md
index 391ab5b..f5380ef 100644
--- a/docs/tildagon-apps/reference/ui-elements.md
+++ b/docs/tildagon-apps/reference/ui-elements.md
@@ -14,6 +14,7 @@ from app_components import Menu, Notification, clear_background
main_menu_items = ["menu_item1", "menu_item2", "menu_item3"]
+
class MenuDemo(App):
def __init__(self):
self.menu = Menu(
@@ -41,6 +42,7 @@ class MenuDemo(App):
if self.notification:
self.notification.update(delta)
+
__app_export__ = MenuDemo
```
@@ -75,18 +77,18 @@ To use a menu:
To initialize the Menu use the following parameters:
- | Parameter | Type | Description |
- | ------------------------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
- | `app` | `App` | The app to add the menu to. |
- | `menu_items` | `[str]` | A list of strings containing the menu items. |
- | `select_handler` | `method` | The method to be called when an item is selected and the confirm button is pressed. |
- | `back_handler` | `method` | The method to be called when the cancel button is pressed. |
- | `position` | `int` | _Optional_. The menu position to start at. Default: `0`. |
- | `speed_ms` | `int` | _Optional_. The speed to redraw the UI at. Default: `300`. |
- | `item_font_size` | `float` | _Optional_. The item line height. Default: [`tokens.ten_pt`](https://github.com/emfcamp/badge-2024-software/blob/main/modules/app_components/tokens.py). |
- | `item_line_height` | `float` | _Optional_. The item line height. Default: [`tokens.label_font_size * tokens.line_height`](https://github.com/emfcamp/badge-2024-software/blob/main/modules/app_components/tokens.py). |
- | `focused_item_font_size` | `float` | _Optional_. The font size of the focused item. Default: [`tokens.heading_font_size`](https://github.com/emfcamp/badge-2024-software/blob/main/modules/app_components/tokens.py). |
- | `focused_item_margin` | `float` | _Optional_. The margin on the focused item. Default: `20`. |
+ | Parameter | Type | Description |
+ | --------- | ---- | ----------- |
+ | `app` | `App` | The app to add the menu to. |
+ | `menu_items` | `[str]` | A list of strings containing the menu items. |
+ | `select_handler` | `method` | The method to be called when an item is selected and the confirm button is pressed. |
+ | `back_handler` | `method` | The method to be called when the cancel button is pressed. |
+ | `position` | `int` | _Optional_. The menu position to start at. Default: `0`. |
+ | `speed_ms` | `int` | _Optional_. The speed to redraw the UI at. Default: `300`. |
+ | `item_font_size` | `float` | _Optional_. The item line height. Default: [`tokens.ten_pt`](https://github.com/emfcamp/badge-2024-software/blob/main/modules/app_components/tokens.py). |
+ | `item_line_height` | `float` | _Optional_. The item line height. Default: [`tokens.label_font_size * tokens.line_height`](https://github.com/emfcamp/badge-2024-software/blob/main/modules/app_components/tokens.py). |
+ | `focused_item_font_size` | `float` | _Optional_. The font size of the focused item. Default: [`tokens.heading_font_size`](https://github.com/emfcamp/badge-2024-software/blob/main/modules/app_components/tokens.py). |
+ | `focused_item_margin` | `float` | _Optional_. The margin on the focused item. Default: `20`. |
4. If you are creating a multi-layered menu, also create a variable like `current_menu` in the `__init__` method of your app to store the users menu state:
@@ -126,12 +128,13 @@ To use a menu:
You can use the following methods on a `Menu` object:
-| Method | Description | Parameter | Returns |
-| ---------------- | ---------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | ------- |
-| `up_handler()` | Manually moves you up one position in the menu. | None | None |
-| `down_handler()` | Manually moves you down one position in the menu. | None | None |
-| `update(delta)` | Update the menu as animations are happening. You need to call this method in your app's `update()` method. | `delta`: Time difference between the last update call and the current update call. | None |
-| `draw(ctx)` | Add the menu to the screen. You need to call this method in your app's `draw()` method. | `ctx`: The canvas that let's you add graphics or texts. See [`ctx` library](../reference/ctx.md). | None |
+
+| Method | Description | Arguments | Returns |
+| ------ | ----------- | --------- | ------- |
+| `up_handler()` | Manually moves you up one position in the menu. | None | None |
+| `down_handler()` | Manually moves you down one position in the menu. | None | None |
+| `update(delta)` | Update the menu as animations are happening. You need to call this method in your app's `update()` method. | `delta`: Time difference between the last update call and the current update call. | None |
+| `draw(ctx)` | Add the menu to the screen. You need to call this method in your app's `draw()` method. | `ctx`: The canvas that let's you add graphics or texts. See [`ctx` library](../reference/ctx.md). | None |
## Notification
@@ -173,6 +176,7 @@ class NotificationDemo(App):
if self.notification:
self.notification.draw(ctx)
+
__app_export__ = NotificationDemo
```
@@ -200,11 +204,11 @@ To use a notification:
`Notification()` supports the following parameters:
- | Parameter | Type | Description |
- | --------- | --------- | -------------------------------------------------------------------------- |
- | `message` | `str` | The notification message. |
- | `port` | `int` | _Optional_. The port from which the notification was issued. Default: `0`. |
- | `open` | `boolean` | _Optional_. Whether to open the notification. Default: `True`. |
+ | Parameter | Type | Description |
+ | --------- | ---- | ----------- |
+ | `message` | `str` | The notification message. |
+ | `port` | `int` | _Optional_. The port from which the notification was issued. Default: `0`. |
+ | `open` | `boolean` | _Optional_. Whether to open the notification. Default: `True`. |
4. Add the following lines in your `draw()` method to draw the notification when `self.notification` contains a notification:
@@ -226,12 +230,13 @@ To use a notification:
You can use the following methods on a `Notification` object:
-| Method | Description | Arguments | Returns |
-| --------------- | ------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | ------- |
-| `open()` | Manually open the notification. | None | None |
-| `close()` | Manually close the notification. | None | None |
-| `update(delta)` | Automatically display the notification for a period of 5 seconds. You need to call this method in your app's `update()` method. | `delta`: Time difference between the last update call and the current update call. | None |
-| `draw(ctx)` | Add the notification to the screen. You need to call this method in your app's `draw()` method. | `ctx`: The canvas that let's you add graphics or texts. See [`ctx` library](../reference/ctx.md). | None |
+
+| Method | Description | Arguments | Returns |
+| ------ | ----------- | --------- | ------- |
+| `open()` | Manually open the notification. | None | None |
+| `close()` | Manually close the notification. | None | None |
+| `update(delta)` | Automatically display the notification for a period of 5 seconds. You need to call this method in your app's `update()` method. | `delta`: Time difference between the last update call and the current update call. | None |
+| `draw(ctx)` | Add the notification to the screen. You need to call this method in your app's `draw()` method. | `ctx`: The canvas that let's you add graphics or texts. See [`ctx` library](../reference/ctx.md). | None |
## Yes/No Dialog
@@ -282,8 +287,8 @@ The [`YesNoDialog`](https://github.com/emfcamp/badge-2024-software/blob/main/mod
ctx.save()
if self.answer:
- ctx.rgb(0,0,0.2).rectangle(-120,-120,240,240).fill()
- ctx.rgb(0,0,1).move_to(-80,0).text(self.answer)
+ ctx.rgb(0, 0, 0.2).rectangle(-120, -120, 240, 240).fill()
+ ctx.rgb(0, 0, 1).move_to(-80, 0).text(self.answer)
ctx.restore()
if self.dialog:
@@ -331,8 +336,8 @@ The [`YesNoDialog`](https://github.com/emfcamp/badge-2024-software/blob/main/mod
clear_background(ctx)
if self.answer:
ctx.save()
- ctx.rgb(0,0,0.2).rectangle(-120,-120,240,240).fill()
- ctx.rgb(0,0,1).move_to(-80,0).text(self.answer)
+ ctx.rgb(0, 0, 0.2).rectangle(-120, -120, 240, 240).fill()
+ ctx.rgb(0, 0, 1).move_to(-80, 0).text(self.answer)
ctx.restore()
self.draw_overlays(ctx)
@@ -380,7 +385,8 @@ To use the Yes/No dialog:
# Create a yes/no dialogue, add it to the overlays
dialog = YesNoDialog("Is it a happy day?", self)
self.overlays = [dialog]
- # Wait for an answer from the dialogue, and if it was yes, do something
+ # Wait for an answer from the dialogue, and if it was yes, do
+ # something
if await dialog.run(render_update):
# this sets a variable that can be used in the draw method
self.answer = "I'm sorry"
@@ -394,12 +400,12 @@ To use the Yes/No dialog:
`YesNoDialog()` supports the following parameters:
-| Parameter | Type | Description |
-| --------- | -------- | ---------------------------------------------------------------------------------------------------------------------------- |
-| `message` | `str` | The dialog message. |
-| `app` | `App` | The app opening the dialog. |
-| `on_yes` | `method` | _Optional_. Call the provided handler method or return `True` if answer is yes and no handler is provided. Default: `None`. |
-| `on_no` | `method` | _Optional_. Call the provided handler method or return `False` if answer is yes and no handler is provided. Default: `None`. |
+| Parameter | Type | Description |
+| --------- | ---- | ----------- |
+| `message` | `str` | The dialog message. |
+| `app` | `App` | The app opening the dialog. |
+| `on_yes` | `method` | _Optional_. Call the provided handler method or return `True` if answer is yes and no handler is provided. Default: `None`. |
+| `on_no` | `method` | _Optional_. Call the provided handler method or return `False` if answer is yes and no handler is provided. Default: `None`. |
=== "Synchronous"
@@ -427,11 +433,12 @@ To make the dialog's answers have an effect you need to do something based on th
You can use the following methods on a `YesNoDialog` object:
-| Method | Description | Arguments | Returns |
-| -------------------- | ---------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | ----------------- |
-| `run(render_update)` | Asynchronous. Open the dialog. You need to call this method to display the dialog. | `render_update`: The method that triggers a `draw()` call when updates are complete. | `True` or `False` |
-| `draw_message(ctx)` | Helper method to add your message to the screen. This method is called by the `draw()` method. | `ctx`: The canvas that let's you add graphics or texts. See [`ctx` library](../reference/ctx.md). | None |
-| `draw(ctx)` | Add the dialog to the screen. You need to call this method in your app's `draw()` method. | `ctx`: The canvas that let's you add graphics or texts. See [`ctx` library](../reference/ctx.md). | None |
+
+| Method | Description | Arguments | Returns |
+| ------ | ----------- | --------- | ------- |
+| `run(render_update)` | Asynchronous. Open the dialog. You need to call this method to display the dialog. | `render_update`: The method that triggers a `draw()` call when updates are complete. | `True` or `False` |
+| `draw_message(ctx)` | Helper method to add your message to the screen. This method is called by the `draw()` method. | `ctx`: The canvas that let's you add graphics or texts. See [`ctx` library](../reference/ctx.md). | None |
+| `draw(ctx)` | Add the dialog to the screen. You need to call this method in your app's `draw()` method. | `ctx`: The canvas that let's you add graphics or texts. See [`ctx` library](../reference/ctx.md). | None |
## Text Dialog
@@ -585,13 +592,13 @@ To use the text dialog:
`TextDialog()` supports the following parameters:
-| Parameter | Type | Description |
-| ------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `message` | `str` | The dialog message. |
-| `app` | `App` | The app opening the dialog. |
-| `masked` | `bool` | _Optional_. Whether to obscure the text buffer with asterisks (for example, for passwords). Default: `False`. |
+| Parameter | Type | Description |
+| --------- | ---- | ----------- |
+| `message` | `str` | The dialog message. |
+| `app` | `App` | The app opening the dialog. |
+| `masked` | `bool` | _Optional_. Whether to obscure the text buffer with asterisks (for example, for passwords). Default: `False`. |
| `on_complete` | `method` | _Optional_. Call the provided handler method or return the text entry if the text entry is confirmed and no handler is provided. Default: `None`. |
-| `on_cancel` | `method` | _Optional_. Call the provided handler method or return `False` if answer is cancelled and no handler is provided. Default: `None`. |
+| `on_cancel` | `method` | _Optional_. Call the provided handler method or return `False` if answer is cancelled and no handler is provided. Default: `None`. |
=== "Synchronous"
@@ -619,11 +626,12 @@ To make the dialog's answer have an effect you need to do something with the ans
You can use the following methods on a `TextDialog` object:
-| Method | Description | Arguments | Returns |
-| -------------------- | ---------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | ----------------- |
-| `run(render_update)` | Asynchronous. Open the dialog. You need to call this method to display the dialog. | `render_update`: The method that triggers a `draw()` call when updates are complete. | `True` or `False` |
-| `draw_message(ctx)` | Helper method to add your message to the screen. This method is called by the `draw()` method. | `ctx`: The canvas that let's you add graphics or texts. See [`ctx` library](../reference/ctx.md). | None |
-| `draw(ctx)` | Add the dialog to the screen. You need to call this method in your app's `draw()` method. | `ctx`: The canvas that let's you add graphics or texts. See [`ctx` library](../reference/ctx.md). | None |
+
+| Method | Description | Arguments | Returns |
+| ------ | ----------- | --------- | ------- |
+| `run(render_update)` | Asynchronous. Open the dialog. You need to call this method to display the dialog. | `render_update`: The method that triggers a `draw()` call when updates are complete. | `True` or `False` |
+| `draw_message(ctx)` | Helper method to add your message to the screen. This method is called by the `draw()` method. | `ctx`: The canvas that let's you add graphics or texts. See [`ctx` library](../reference/ctx.md). | None |
+| `draw(ctx)` | Add the dialog to the screen. You need to call this method in your app's `draw()` method. | `ctx`: The canvas that let's you add graphics or texts. See [`ctx` library](../reference/ctx.md). | None |
## Layouts
@@ -645,11 +653,20 @@ This example creates what could be a small game menu with three parts:
import app
from app_components import clear_background, TextDialog
-from app_components.layout import TextDisplay, ButtonDisplay, DefinitionDisplay, LinearLayout
+from app_components.layout import \
+ TextDisplay, ButtonDisplay, DefinitionDisplay, LinearLayout
from events.input import BUTTON_TYPES, ButtonDownEvent
from system.eventbus import eventbus
DIFFICULTY_VALUES = ["easy", "normal", "hard"]
+LOREM = """Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do\
+ eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim\
+ veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea\
+ commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit\
+ esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat \
+ cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est\
+ laborum."""
+
def string_formatter(value):
if value is None:
@@ -657,19 +674,25 @@ def string_formatter(value):
else:
return str(value)
+
class LayoutMenuDemo(app.App):
def __init__(self):
self.layout = LinearLayout(items=[DefinitionDisplay("", "")])
self.dialog = None
self.options = {
- ("text_setting", "Player Name", string_formatter, self.string_editor),
+ (
+ "text_setting",
+ "Player Name",
+ string_formatter,
+ self.string_editor
+ ),
("button_selector", "Difficulty selector", string_formatter, None),
("text", "Game Instructions", string_formatter, None),
}
self.app_settings = {
"text_setting": "Naomi",
"button_selector": "easy",
- "instructions": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
+ "instructions": LOREM
}
eventbus.on_async(ButtonDownEvent, self._button_handler, self)
@@ -699,12 +722,13 @@ class LayoutMenuDemo(app.App):
self.layout.items = []
for id, label, formatter, editor in self.options:
if id in self.app_settings.keys():
- value = self.app_settings[id
- ]
+ value = self.app_settings[id]
else:
- value = ""
+ value = ""
+
if editor:
- async def _button_event(event, label=label, id=id, editor=editor):
+ async def _button_event(
+ event, label=label, id=id, editor=editor):
if BUTTON_TYPES["CONFIRM"] in event.button:
await editor(label, id, render_update)
return True
@@ -751,13 +775,12 @@ class LayoutMenuDemo(app.App):
result = await self.dialog.run(render_update)
if (
result is not False
- ): #!= because we want to allow entering empty strings
+ ): # != because we want to allow entering empty strings
self.app_settings[self.dialog._settings_id] = result
self.dialog = None
if result:
break
-
def update(self, delta):
return True
@@ -765,6 +788,7 @@ class LayoutMenuDemo(app.App):
clear_background(ctx)
self.layout.draw(ctx)
+
__app_export__ = LayoutMenuDemo
```
@@ -801,12 +825,12 @@ To use layouts:
To initialize the definition display use the following parameters:
- | Parameter | Type | Description |
- | --------- | ---- | ----------- |
- | `label` | `str` | The text to display for the label. |
- | `value` | `str` | The text to display for the definition. |
- | `height` | `int` | The height at which to display the definition display. |
- | `button_handler` | `method` | The handler for button events. |
+ | Parameter | Type | Description |
+ | --------- | ---- | ----------- |
+ | `label` | `str` | The text to display for the label. |
+ | `value` | `str` | The text to display for the definition. |
+ | `height` | `int` | The height at which to display the definition display. |
+ | `button_handler` | `method` | The handler for button events. |
=== "TextDisplay"
@@ -815,17 +839,17 @@ To use layouts:
Initialize the text_display in your `__init__` or in your `update` method and add it to the `self.layout.items` variable:
```python
- text_display = TextDisplay("My long text", font_size=8, rgb=(0,0,50))
+ text_display = TextDisplay("My long text", font_size=8, rgb=(0, 0, 50))
self.layout.items.append(text_display)
```
To initialize the `TextDisplay` use the ?following parameters:
- | Parameter | Type | Description |
- | --------- | ---- | ----------- |
- | `text` | `str` | The long text to display. |
- | `font_size` | `int` | The font size to display the text in. |
- | `rgb` | `tuple` | The color to display the text in. |
+ | Parameter | Type | Description |
+ | --------- | ---- | ----------- |
+ | `text` | `str` | The long text to display. |
+ | `font_size` | `int` | The font size to display the text in. |
+ | `rgb` | `tuple` | The color to display the text in. |
=== "ButtonDisplay"
@@ -838,20 +862,20 @@ To use layouts:
text="Select me",
app=self,
font_size=8,
- rgb=(50,0,0),
+ rgb=(50, 0, 0),
button_handler=self.select_handler)
self.layout.items.append(button_display)
```
To initialize the button display use the following parameters:
- | Parameter | Type | Description |
- | --------- | ---- | ----------- |
- | `text` | `str` | The long text to display. |
- | `app` | `App` | The app to add the button display to. |
- | `font_size` | `int` | The font size to display the text in. |
- | `rgb` | `tuple` | The color to display the text in. |
- | `button_handler` | `method` | The handler for button events. |
+ | Parameter | Type | Description |
+ | --------- | ---- | ----------- |
+ | `text` | `str` | The long text to display. |
+ | `app` | `App` | The app to add the button display to. |
+ | `font_size` | `int` | The font size to display the text in. |
+ | `rgb` | `tuple` | The color to display the text in. |
+ | `button_handler` | `method` | The handler for button events. |
Create an asynchronous `select_handler` that does something when a button is pressed:
@@ -875,10 +899,11 @@ The [`Tokens`](https://github.com/emfcamp/badge-2024-software/blob/main/modules/
### Functions
-| Method | Description | Arguments | Returns |
-| ----------------------- | ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
-| `clear_background(ctx)` | Clear the badge background. | `ctx`: The canvas that let's you add graphics or texts. See [`ctx` library](../reference/ctx.md). | None |
-| `set_color(ctx, color)` | Set the color for the canvas. | ctx
: The canvas that let's you add graphics or texts. See [`ctx` library](../reference/ctx.md).color
: The provided color as a string from the following options: `pale_green`, `mid_green`, `dark_green`, `colors.yellow`, `colors.orange`, `colors.pink`, `colors.blue`, `ui_colors.background`, `ui_colors.label`.
| None |
+
+| Method | Description | Arguments | Returns |
+| ------ | ----------- | --------- | ------- |
+| `clear_background(ctx)` | Clear the badge background. | `ctx`: The canvas that let's you add graphics or texts. See [`ctx` library](../reference/ctx.md). | None |
+| `set_color(ctx, color)` | Set the color for the canvas. | ctx
: The canvas that let's you add graphics or texts. See [`ctx` library](../reference/ctx.md).color
: The provided color as a string from the following options: `pale_green`, `mid_green`, `dark_green`, `colors.yellow`, `colors.orange`, `colors.pink`, `colors.blue`, `ui_colors.background`, `ui_colors.label`.
| None |
#### Usage
diff --git a/docs/tildagon-apps/simple_tildagon.md b/docs/tildagon-apps/simple_tildagon.md
index d700f24..93dc6fc 100644
--- a/docs/tildagon-apps/simple_tildagon.md
+++ b/docs/tildagon-apps/simple_tildagon.md
@@ -104,7 +104,7 @@ while True:
# is_tilted_foward, is_tilted_back
if st.imu.is_tilted_left():
print("Left!")
- time.sleep(1) # Only checking every second
+ time.sleep(1) # Only checking every second
```
There is also a check for shaking using `st.imu.is_shaken()`.
@@ -131,10 +131,11 @@ import time
while True:
- # Options include is_tilted_left, is_tilted_right, is_tilted_foward, is_tilted_back
+ # Options include is_tilted_left, is_tilted_right, is_tilted_foward,
+ # is_tilted_back
if st.button.get("A"):
print("Button A is being pressed!")
- time.sleep(1) # Only checking every second
+ time.sleep(1) # Only checking every second
```
!!! warning "Multiple loops"
diff --git a/docs/tildagon-apps/simulate.md b/docs/tildagon-apps/simulate.md
index 6ba24d6..eb34164 100644
--- a/docs/tildagon-apps/simulate.md
+++ b/docs/tildagon-apps/simulate.md
@@ -41,8 +41,8 @@ The badge simulator simulates all apps in the [`sim/apps/`](https://github.com/e
def draw(self, ctx):
ctx.save()
- ctx.rgb(0.2,0,0).rectangle(-120,-120,240,240).fill()
- ctx.rgb(1,0,0).move_to(-80,0).text("Hello world")
+ ctx.rgb(0.2, 0, 0).rectangle(-120, -120, 240, 240).fill()
+ ctx.rgb(1, 0, 0).move_to(-80, 0).text("Hello world")
ctx.restore()
__app_export__ = ExampleApp