Skip to content
Back to top
View this page

# Model

## Protocols

Although `gaphas.Canvas` can be used as a default model, any class that adhere’s to the Model protocol can be used as a model.

class gaphas.model.Model(*args, **kwargs)

  Any class that adhere’s to the Model protocol can be used as a model for GtkView.

  property connections: Connections

    The connections instance used for this model.

  get_all_items() → Iterable[Item]

    Iterate over all items in the order they need to be rendered in.

    Normally that will be depth-first.

  get_parent(item: Item) → Item | None

    Get the parent item of an item.

    Returns `None` if there is no parent item.

  get_children(item: Item | None) → Iterable[Item]

    Iterate all direct child items of an item.

  sort(items: Collection[Item]) → Iterable[Item]

    Sort a collection of items in the order they need to be rendered in.

  request_update(item: Item) → None

    Request update for an item.

    Parameters:

      item (Item) – The item to be updated

  update_now(dirty_items: Collection[Item]) → None

    This method is called during the update process.

    It will allow the model to do some additional updating of it’s own.

  register_view(view: View) → None

    Allow a view to be registered.

    Registered views should receive update requests for modified items.

  unregister_view(view: View) → None

    Unregister a previously registered view.

    If a view is not registered, nothing should happen.

An item should implement these methods, so it can be rendered by the View. Not that painters or tools can require additional methods.

class gaphas.item.Item(*args, **kwargs)

  This protocol should be implemented by model items.

  All items that are rendered on a view.

  property matrix: Matrix

    The “local”, item-to-parent matrix.

  property matrix_i2c: Matrix

    Matrix from item to toplevel.

  handles() → Sequence[Handle]

    Return a list of handles owned by the item.

  ports() → Sequence[Port]

    Return list of ports owned by the item.

  point(x: float, y: float) → float

    Get the distance from a point (`x`, `y`) to the item.

    `x` and `y` are in item coordinates.

    A distance of 0 means the point is on the item.

  draw(context: DrawContext) → None

    Render the item to a canvas view. Context contains the following attributes:

    - cairo: the CairoContext use this one to draw

    - selected, focused, hovered: view state of items (True/False)

## Default implementations

### Canvas

The default implementation for a `Model`, is a class called `Canvas`.

class gaphas.canvas.Canvas

  Container class for items.

  add(item, parent=None, index=None)

    Add an item to the canvas.

        >>> c = Canvas()
        >>> from gaphas import item
        >>> i = item.Item()
        >>> c.add(i)
        >>> len(c._tree.nodes)
        1
        >>> i._canvas is c
        True

  remove(item)

    Remove item from the canvas.

        >>> c = Canvas()
        >>> from gaphas import item
        >>> i = item.Item()
        >>> c.add(i)
        >>> c.remove(i)
        >>> c._tree.nodes
        []
        >>> i._canvas

  reparent(item, parent, index=None)

    Set new parent for an item.

  get_all_items() → Iterable[Item]

    Get a list of all items.

        >>> c = Canvas()
        >>> c.get_all_items()
        []
        >>> from gaphas import item
        >>> i = item.Item()
        >>> c.add(i)
        >>> c.get_all_items()
        [<gaphas.item.Item ...>]

  get_root_items()

    Return the root items of the canvas.

        >>> c = Canvas()
        >>> c.get_all_items()
        []
        >>> from gaphas import item
        >>> i = item.Item()
        >>> c.add(i)
        >>> ii = item.Item()
        >>> c.add(ii, i)
        >>> c.get_root_items()
        [<gaphas.item.Item ...>]

  get_parent(item: Item) → Item | None

    See tree.Tree.get_parent().

        >>> c = Canvas()
        >>> from gaphas import item
        >>> i = item.Item()
        >>> c.add(i)
        >>> ii = item.Item()
        >>> c.add(ii, i)
        >>> c.get_parent(i)
        >>> c.get_parent(ii)
        <gaphas.item.Item ...>

  get_children(item: Item | None) → Iterable[Item]

    See tree.Tree.get_children().

        >>> c = Canvas()
        >>> from gaphas import item
        >>> i = item.Item()
        >>> c.add(i)
        >>> ii = item.Item()
        >>> c.add(ii, i)
        >>> iii = item.Item()
        >>> c.add(iii, ii)
        >>> list(c.get_children(iii))
        []
        >>> list(c.get_children(ii))
        [<gaphas.item.Item ...>]
        >>> list(c.get_children(i))
        [<gaphas.item.Item ...>]

  sort(items: Iterable[Item]) → Iterable[Item]

    Sort a list of items in the order in which they are traversed in the canvas (Depth first).

        >>> c = Canvas()
        >>> from gaphas import item
        >>> i1 = item.Line()
        >>> c.add(i1)
        >>> i2 = item.Line()
        >>> c.add(i2)
        >>> i3 = item.Line()
        >>> c.add (i3)
        >>> c.update_now((i1, i2, i3)) # ensure items are indexed
        >>> s = c.sort([i2, i3, i1])
        >>> s[0] is i1 and s[1] is i2 and s[2] is i3
        True

  get_matrix_i2c(item: Item) → Matrix

    Get the Item to Canvas matrix for `item`.

    item:

      The item who’s item-to-canvas transformation matrix should be found

    calculate:

      True will allow this function to actually calculate it, instead of raising an AttributeError when no matrix is present yet. Note that out-of-date matrices are not recalculated.

  request_update(item: Item) → None

    Set an update request for the item.

        >>> c = Canvas()
        >>> from gaphas import item
        >>> i = item.Item()
        >>> ii = item.Item()
        >>> c.add(i)
        >>> c.add(ii, i)
        >>> len(c._dirty_items)
        0
        >>> c.update_now((i, ii))
        >>> len(c._dirty_items)
        0

  request_matrix_update(item)

    Schedule only the matrix to be updated.

  update_now(dirty_items)

    Perform an update of the items that requested an update.

  register_view(view: View) → None

    Register a view on this canvas.

    This method is called when setting a canvas on a view and should not be called directly from user code.

  unregister_view(view: View) → None

    Unregister a view on this canvas.

    This method is called when setting a canvas on a view and should not be called directly from user code.

### Items

Gaphas provides two default items, an box-like element and a line shape.

class gaphas.item.Element(connections: Connections, width: float = 10, height: float = 10, **kwargs: object)

  An Element has 4 handles (for a start):

      NW +---+ NE
         |   |
      SW +---+ SE

  property width: float

    Width of the box, calculated as the distance from the left and right handle.

  property height: float

    Height.

  handles() → Sequence[Handle]

    Return a list of handles owned by the item.

  ports() → Sequence[Port]

    Return list of ports.

  point(x: float, y: float) → float

    Distance from the point (x, y) to the item.

        >>> e = Element()
        >>> e.point(20, 10)
        10.0

class gaphas.item.Line(connections: Connections, **kwargs: object)

  A Line item.

  Properties:
    - fuzziness (0.0..n): an extra margin that should be taken into

        account when calculating the distance from the line (using point()).

    - orthogonal (bool): whether or not the line should be

        orthogonal (only straight angles)

    - horizontal: first line segment is horizontal

    - line_width: width of the line to be drawn

  This line also supports arrow heads on both the begin and end of the line. These are drawn with the methods draw_head(context) and draw_tail(context). The coordinate system is altered so the methods do not have to know about the angle of the line segment (e.g. drawing a line from (10, 10) via (0, 0) to (10, -10) will draw an arrow point).

  update_orthogonal_constraints() → None

    Update the constraints required to maintain the orthogonal line.

  opposite(handle: Handle) → Handle

    Given the handle of one end of the line, return the other end.

  handles() → Sequence[Handle]

    Return a list of handles owned by the item.

  ports() → Sequence[Port]

    Return list of ports.

  point(x: float, y: float) → float

        >>> a = Line()
        >>> a.handles()[1].pos = 25, 5
        >>> a._handles.append(a._create_handle((30, 30)))
        >>> a.point(-1, 0)
        1.0
        >>> f"{a.point(5, 4):.3f}"
        '2.942'
        >>> f"{a.point(29, 29):.3f}"
        '0.784'

  draw_head(context: DrawContext) → None

    Default head drawer: move cursor to the first handle.

  draw_tail(context: DrawContext) → None

    Default tail drawer: draw line to the last handle.

  draw(context: DrawContext) → None

    Draw the line itself.

    See Item.draw(context).