Skip to content

Commit

Permalink
Remove decorators and use async/await instead
Browse files Browse the repository at this point in the history
  • Loading branch information
amolenaar committed Aug 18, 2024
1 parent 060760f commit 98201cf
Show file tree
Hide file tree
Showing 18 changed files with 288 additions and 455 deletions.
4 changes: 0 additions & 4 deletions docs/decorators.rst

This file was deleted.

1 change: 0 additions & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ Gaphas is released under the terms of the Apache Software License, version 2.0.
quadtree
table
tree
decorators

.. _Cairo: https://cairographics.org
.. _Model-View-Controller: https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller
4 changes: 4 additions & 0 deletions examples/demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,16 @@
- Delete focused item
- Exports to SVG and PNG
"""
import asyncio
import math
import sys

import cairo
import gi
from gi.events import GLibEventLoopPolicy

# fmt: off

gi.require_version("Gtk", "4.0")
from gi.repository import Gtk
# fmt: on
Expand Down Expand Up @@ -417,6 +420,7 @@ def activate(app):

app.connect("activate", activate)

asyncio.set_event_loop_policy(GLibEventLoopPolicy())
app.run()


Expand Down
103 changes: 0 additions & 103 deletions gaphas/decorators.py

This file was deleted.

64 changes: 44 additions & 20 deletions gaphas/view/gtkview.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
"""This module contains everything to display a model on a screen."""
from __future__ import annotations

import asyncio
from typing import Collection, Iterable

import cairo
from gi.repository import Graphene, GLib, GObject, Gtk
from gi.repository import Graphene, GObject, Gtk

from gaphas.decorators import g_async
from gaphas.geometry import Rect, Rectangle
from gaphas.item import Item
from gaphas.matrix import Matrix
Expand Down Expand Up @@ -87,6 +87,9 @@ def __init__(self, model: Model | None = None, selection: Selection | None = Non
self._back_buffer: cairo.Surface | None = None
self._back_buffer_needs_resizing = True

self._update_scrolling_task: asyncio.Task | None = None
self._update_task: asyncio.Task | None = None

self._controllers: set[Gtk.EventController] = set()

self.set_can_focus(True)
Expand Down Expand Up @@ -148,6 +151,10 @@ def model(self, model: Model | None) -> None:
self._selection.clear()
self._dirty_items.clear()
self._qtree.clear()
if self._update_task:
self._update_task.cancel()
if self._update_scrolling_task:
self._update_scrolling_task.cancel()

self._model = model

Expand Down Expand Up @@ -273,22 +280,31 @@ def request_update(
if items or removed_items:
self.update()

@g_async(single=True, priority=GLib.PRIORITY_DEFAULT)
def update(self) -> None:
def update(self) -> asyncio.Task:
"""Update view status according to the items updated in the model."""
model = self._model
if not model:
return

dirty_items = self.all_dirty_items()
model.update_now(dirty_items)
dirty_items |= self.all_dirty_items()
async def _update():
model = self._model
if not model:
return

old_bb = self._qtree.soft_bounds
self.update_bounding_box(dirty_items)
if self._qtree.soft_bounds != old_bb:
self.update_scrolling()
self.update_back_buffer()
dirty_items = self.all_dirty_items()
model.update_now(dirty_items)
dirty_items |= self.all_dirty_items()

old_bb = self._qtree.soft_bounds
self.update_bounding_box(dirty_items)
if self._qtree.soft_bounds != old_bb:
self.update_scrolling()
self.update_back_buffer()

def clear_task(task):
self._update_task = None

if not self._update_task:
self._update_task = asyncio.create_task(_update())
self._update_task.add_done_callback(clear_task)
return self._update_task

def all_dirty_items(self) -> set[Item]:
"""Return all dirty items, clearing the marked items."""
Expand Down Expand Up @@ -327,11 +343,19 @@ def update_bounding_box(self, items: Collection[Item]) -> None:

qtree.add(item=item, bounds=(x, y, w, h))

@g_async(single=True)
def update_scrolling(self) -> None:
self._scrolling.update_adjustments(
self.get_width(), self.get_height(), self.bounding_box
)
def update_scrolling(self) -> asyncio.Task:
async def _update_scrolling():
self._scrolling.update_adjustments(
self.get_width(), self.get_height(), self.bounding_box
)

def clear_task(task):
self._update_scrolling_task = None

if not self._update_scrolling_task:
self._update_scrolling_task = asyncio.create_task(_update_scrolling())
self._update_scrolling_task.add_done_callback(clear_task)
return self._update_scrolling_task

def _debug_draw_bounding_box(self, cr, width, height):
for item in self.get_items_in_rectangle((0, 0, width, height)):
Expand Down
Loading

0 comments on commit 98201cf

Please sign in to comment.