Package: textual-canvas
textual-canvasAn example oftextual-canvasbeing used in a Textual applicationIntroductionThis library aims to provide a very simple terminal-based drawing canvas
widget for use withTextual. Initially
developed for a (also-being-worked-on-right-now) less general project, I'm
making it available on the off-chance anyone else might want to play with it
now.You might not want to rely on this just yet though; I'm still messing and
experimenting.InstallingThe package can be installed withpipor related tools, for example:$pipinstalltextual-canvasIt's early daysThis is a very early release of this code, it's still very much a work in
progress. This means things may change and break; it's also sitting atop
Textual which is, of course, still undergoing rapid development. As much as
possible I'll try and ensure that it's always working with the latest stable
release of Textual.Also, because it's early days... while I love the collaborative aspect of
FOSS, I'm highly unlikely to be accepting any non-trivial PRs at the moment.
Developing this is a learning exercise for me, it's a hobby project, and
it's also something to help me further test Textual (disclaimer for those
who may not have gathered, I am employed byTextualize).On the other hand: I'mveryopen to feedback and suggestions so don't
hesitate to engage with me in Discussions, or if it's a bug, in Issues. I
can't and won't promise that I'll take everything on board (see above about
hobby project, etc), but helpful input should help make this as useful as
possible in the longer term.The libraryThe library provides one very simple widget for use in Textual:Canvas.
This is a scrollable and focusable widget that can be used to colour
"pixels", acting as a basic building block for drawing other things. The
"pixels" themselves are half a character cell in height, hopefully coming
out roughly square in most environments.TheCanvascan be imported like this:fromtextual_canvasimportCanvasAnd is created by providing a width and height (in its own idea of "pixels")
plus an optional initial background colour (which should be a TextualColor).In a Textualcomposemethod you might use it something like this:yieldCanvas(120,120,Color(30,40,50))Currently there are the following methods available for drawing:clear( self, color: Color | None = None ) -> Selfset_pixel( self, x: int, y: int, color: Color ) -> Selfset_pixels( self, locations: Iterable[ tuple[ int, int ] ], color: Color ) -> Selfdraw_line( self, x0: int, y0: int, x1: int, y1: int, color: Color ) -> Selfdraw_rectangle( self, x: int, y: int, width: int, height: int, color: Color ) -> Selfdraw_circle( self, center_x: int, center_y: int, radius: int, color: Color ) -> SelfI'll document all of this better, when I spend more time on it than the 1/2
hour somewhere between dinner and bedtime.A quick and dirty example of this being used would be:fromtextual.appimportApp,ComposeResultfromtextual.colorimportColorfromtextual_canvasimportCanvas##############################################################################classCanvasTestApp(App[None]):"""The Canvas testing application."""CSS="""Canvas {border: round green;width: 1fr;height: 1fr;}"""defcompose(self)->ComposeResult:yieldCanvas(120,120,Color(30,40,50))defon_mount(self)->None:"""Set up the display once the DOM is available."""canvas=self.query_one(Canvas)canvas.draw_line(60,40,90,80,Color(128,128,128))canvas.draw_line(60,40,30,80,Color(128,128,128))canvas.draw_line(30,80,90,80,Color(128,128,128))canvas.draw_line(0,70,48,55,Color(255,255,255))forninrange(52,59):canvas.draw_line(48,55,58,n,Color(128,128,128))canvas.draw_line(70,52,119,57,Color(255,0,0))canvas.draw_line(71,53,119,58,Color(255,165,0))canvas.draw_line(72,54,119,59,Color(255,255,0))canvas.draw_line(72,55,119,60,Color(0,255,0))canvas.draw_line(73,56,119,61,Color(0,0,255))canvas.draw_line(74,57,119,62,Color(75,0,130))canvas.draw_line(75,58,119,63,Color(143,0,255))if__name__=="__main__":CanvasTestApp().run()To see this code in action you, in an environment where the library is
installed, run:$python-mtextual_canvasYou should see something like this:TODOLots. Lots and lots. As mentioned above, there's little tinker project that
I'm building on top of this, so I'll be using that to see how this gets
fleshed out.