Subclassing racket/gui editor%

I want to create a version of the text% editor that can reflow text around images. This is for a simple HTML renderer. I'm looking for advice on how to approach this because it seems like the implementation of racket/gui is going to make it difficult.

Ideally, I'd like to just create a new subclass of editor% alongside text% and pasteboard%, but I don't think this will work for a number of reasons. For one, editor-canvas% assumes that editor%s are either text% or pasteboard%. It is also hard to determine what exactly I'd need to do in a new editor% to satisfy editor-canvas%.

Subclassing text% and changing how it handles text flow is another option but the way that the editor classes have a super class in the wx layer makes it difficult to subclass them. For example, the main text% inherits from another class in the wx layer also called text%. The behavior I want to change is mostly implemented in the wx layer, so if I subclassed the text% in that layer I would also have to re-implement all the text% code in the main layer.

I'm not that experienced with Racket's class system, so perhaps there is a viable approach that I'm just not aware of. Any advice is appreciated!

1 Like

Is it possible to require the wx layer from application code? I'm looking at the definition of editor-canvas% in mrcanvas.rkt and it requires wx.rkt, wxcanvas.rkt, mrwindow.rkt, etc. using filenames. Is any of this stuff available in a module I can require from my application code?

EDIT: perhaps I'm over complicating and it is possible to do what I need by just subclassing canvas% and creating something similar to editor-canvas% that also includes some editor%-like functionality. I'm just reluctant to start writing a bunch of code only to realize later that what I want to achieve isn't possible. If I can insert snips and render them the way I want to in the dc% provided by get-dc, I should be ok though, right?

From my little experience with the editor classes, I don't think they are designed to be able to extend the text re-flowing behavior and, as far as I know they don't already support that. To do what you want you will need to modify these classes inside the racket/gui library, or write your own HTML renderer from scratch using canvas%. Both of these alternatives would require a lot of work.

On the other hand, if you relax the "simple HTML renderer" requirement to not flow text around images, you can look at this blog post on how to implement one on top of text%. The code can be used almost directly, singe Greg's markown parser already produces HTML like expressions:

Hope this helps,
Alex.

1 Like

Thank you for the response. It is good to at least confirm my current understanding.

For my use case I'm only interested in rendering HTML 3.2 and earlier and I don't care about things like css or perfect accuracy. So this at least limits my scope a bit. I already have a basic implementation using html-parsing and text%, but I knew at some point I'd have to handle text flow around images plus implement tables, etc. I also considered a really ugly hack where I have a custom snip with an image and some text and manually flow the text around it with the snip's draw function. The was an interesting experiment but I don't think it is a practical solution. I might be able to implement tables with a custom snip though.

Working within racket/gui is something I've also considered, but I think it may be easier to create a new class rather than try to modify text%. text% has a lot of complexity that I don't need for my use case. If I can muster the energy I may attempt working off of canvas%.

I didn't originally intend to take this as far as I already have, but now I'm finding it hard to let it go!

FWIW you can require mrcanvas.rkt like this:

(require mred/private/mrcanvas)

I am not sure that's the way to go though.

Out of curiosity - have you looked at the how the old browser library did it?
It was used to display help pages directly in DrRacket (Well, DrScheme at the time).
[Disclaimer: I have never looked at the code of browser]

https://docs.racket-lang.org/browser/index.html

Thanks for this. I'm not sure this is the way to go either, but I like having the option.

I did look at browser when I began investigating this and I borrowed some ideas from there. But I don't believe it handles text flow or any of the more complicated things like tables. I haven't tried using the browser code directly, but I think what I have written so far is probably more capable. I'd be happy to be proven wrong about this though!

1 Like

Keep in mind the private/* convention means you'd be using private implementation stuff. The author could change it and break your use, someday.

(OTOH that might not matter much; depends on what you want to do with your own project, eventually.)

3 Likes

It has been over a year, but i wanted to follow up and post the solution I finally arrived at. I subclassed canvas% and created a new canvas that handles text flow. In a sense, my new class layout-canvas% is a combination of editor% and editor-canvas%.

layout-canvas% has modes for non-wrapped text, word wrapping, and a layout mode that implements the alignment and text flow. It supports snips and strings with an attached style. I'm currently working on a table snip. There are still lots of bugs and missing features, but it is coming along nicely.

The project I'm using this in is:

Here's a screen shot of some html:

1 Like