Skip to content

Commit

Permalink
Merge pull request #829 from gaphor/asyncio
Browse files Browse the repository at this point in the history
Use asyncio for view updates
  • Loading branch information
danyeaw authored Oct 6, 2024
2 parents 05b7d0b + 46b336e commit cf758e8
Show file tree
Hide file tree
Showing 19 changed files with 261 additions and 472 deletions.
6 changes: 0 additions & 6 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
2 changes: 0 additions & 2 deletions gaphas/canvas.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@

from gaphas import matrix, tree
from gaphas.connections import Connection, Connections
from gaphas.decorators import nonrecursive
from gaphas.item import Item
from gaphas.model import View

Expand Down Expand Up @@ -232,7 +231,6 @@ def request_matrix_update(self, item):
"""Schedule only the matrix to be updated."""
self.request_update(item)

@nonrecursive
def update_now(self, dirty_items):
"""Perform an update of the items that requested an update."""
try:
Expand Down
130 changes: 0 additions & 130 deletions gaphas/decorators.py

This file was deleted.

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

import asyncio
from math import isclose
from collections.abc 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 @@ -88,6 +88,8 @@ 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_task: asyncio.Task | None = None

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

self.set_can_focus(True)
Expand Down Expand Up @@ -152,6 +154,8 @@ 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()

self._model = model

Expand Down Expand Up @@ -277,22 +281,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
Loading

0 comments on commit cf758e8

Please sign in to comment.