Source code for pdpy_lib.patching.canvas

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# **************************************************************************** #
# This file is part of the pdpy project: https://github.com/pdpy-org
# Copyright (C) 2021 Fede Camara Halac
# **************************************************************************** #
"""
Canvas
======
"""
from ..core.base import Base
from ..core.canvasbase import CanvasBase
from ..primitives.point import Point
from ..primitives.size import Size

__all__ = [ 'Canvas' ]

[docs]class Canvas(CanvasBase, Base): """ Represents a Pure Data canvas, aka subpatch Besides basic properties, the Canvas class takes `#X connect`, `#X coords`, and `#X restore` into its own namespace, as well as the pure data nodes that are created within the context of a subpatch/canvas window. Parameters ---------- - `__pdpy__` (`str`) PdPy className (`self.__class__.__name__`) - `name` (`str`) The canvas name on parent ('(subpatch)') - `vis` (`bool`) Flag to tell if canvas should be visible or not (False) - `gop` (`bool`) Flag to tell if canvas should Graph on Parent (False) - `coords` (`Coords`) Obj holding coordinates necessary for GOP (None) - `position` (`Point`) X-Y pair defining where the pd box is graphed (None) - `title` (`str`) Name to display on the canvas window title bar (None) - `border` (`int`) Position of the object's box right border (None) - `id` (`int`) Identifier number for connections (None) - `__obj_idx__` (`int`) Number of objects currently on this canvas (-1) The basic properties come from the pure data file representation: `#N canvas 0 22 450 300 12;` Attributes: ----------- `screen` (`Point`) x-y pair of the top-left window corner on the screen (0,22) `dimension` (`Size`) window width and height dimensions (450, 300) `font` (`int`) window font size (12) `__pdpy__` (`str`) PdPy className (`self.__class__.__name__`) """ def __init__(self, json=None, name=None, **kwargs): CanvasBase.__init__(self, obj_idx=-1) Base.__init__(self, pdtype='N', cls='canvas') self.__pdpy__ = self.__class__.__name__ if json is not None: super().__populate__(self, json) else: default = self.__d__ self.name = default.name if name is None else self.__sane_name__(name) self.root = False super().__set_default__(kwargs, [ ('screen', default, lambda d: Point(x=d['x'], y=d['y'])), ('dimension', default, lambda d: Size(w=d['width'], h=d['height'])), ('font', default, lambda d: d['size']), ('vis', default) ]) self.isgraph = kwargs.pop('isgraph') if 'isgraph' in kwargs else False if hasattr(self, 'isroot'): self.isroot = self.__pdbool__(self.isroot) if hasattr(self, 'font'): self.font = self.__num__(self.font) self.__pad__ = Size(w=self.font, h=self.font) self.__cursor_init__ = Point(x=self.font, y=self.font) self.__cursor__ = Point(x=self.font, y=self.font) self.__box__ = Size(w=int(self.font * 1.25), h=int(self.font * 2)) self.__margin__ = Size(w=self.font, h=self.font)
[docs] def update_cursor(self, w_step=0, h_step=0): """ Fill objects from top to bottom until we reach bottom (used to be get_position) """ print("Update Cursor:", w_step, h_step) mod_x = self.__cursor__.x // self.dimension.width mod_y = self.__cursor__.y // self.dimension.height # def _print(): # print(self.__cursor__.x, self.__cursor__.y, mod_x, mod_y) # if mod_x > 1 and mod_y > 1: # print("out of bounds --------------------") # # if cursor is out of bounds, grow downwards... # # reset x, # # resize the canvas to be twice as tall as before # # and make y be the bottom most position # self.__cursor__.x = self.__cursor_init__.x # self.__cursor__.y += self.dimension.height # self.__cursor__.y += self.__pad__.height # return # if mod_x < 1 and mod_y > 1: # print("surpassed y", mod_y) # # reset y and increment x position # self.dimension.set_height(self.dimension.height * 2) # self.__cursor__.y = self.__cursor_init__.y + h_step # self.__cursor__.x += w_step # return # if mod_x > 1 and mod_y < 1: # print("surpassed x") # # reset x and increment y position # self.dimension.set_width(self.dimension.width * 2) # self.__cursor__.y += self.dimension.height * (1+mod_y) # self.__cursor__.x = self.__cursor_init__.x # return # grow downwards self.__cursor__.y += h_step self.__cursor__.x += w_step
[docs] def get_char_dim(self): return int(self.dimension.width / self.font * 1.55)
[docs] def get(self, id): if hasattr(self, 'nodes'): for node in self.nodes: if node.id == id: return node else: return None
def __pd__(self): """ Pure Data representation of the canvas """ # the canvas line s = super().__pd__() # print("Screen:",self.screen.__pd__()) # print("Dimension:",self.dimension.__pd__()) # print("Name:",self.name) # print("Font:",self.font) # print("Vis:",self.vis) # print("End:",repr(self.__end__)) s += " " + self.screen.__pd__() + " " + self.dimension.__pd__() isroot = getattr(self, 'isroot', False) isgraph = getattr(self, 'isgraph', False) if isroot: # root canvas only reports font s += " " + str(self.font) else: # non-root canvases, report their name and their vis status s += " " + self.name + " " + str(1 if self.vis else 0) # end the line so we can continue appending to `s` s += self.__end__ s = super().__render__(s, isroot=isroot, isgraph=isgraph) # the border, only if not root if hasattr(self, 'border') and (not isroot): s += "#X f " + str(self.border) s += self.__end__ return s def __xml__(self, tag=None): """ Return the XML Element for this object """ x = super().__element__(scope=self, tag=tag) for e in ('id', 'font', 'name', 'vis', 'isroot', 'border', 'title'): if hasattr(self, e): super().__subelement__(x, e, text=getattr(self, e)) for e in ('screen', 'dimension', 'position', 'coords'): if hasattr(self, e): super().__subelement__(x, getattr(self,e).__xml__(e)) super().__xml_nodes__(x) super().__xml_comments__(x) super().__xml_edges__(x) return x