Attached file canvas-pane.lisp is a work-in-progress. clim-patch.lisp provides MEDIUM-DRAW-PIXELS* it depends on, based on Andy Hefner's code that he posted a while back.
I use it in my raytracer's CLIM frontend to put up the pretty pictures as they are drawn, and to provide a selection area on already rendered images.
There are (currently) three major behaviours that it provides for me:
(SETF (CANVAS-RGBA CANVAS) <RGBA-AS-UB32>)
allows me to quickly assign color to a pixel.
(REPAINT-SHEET CANVAS (CANVAS-DIRTY-REGION CANVAS))
allows me to refresh the screen during rendering, updating only those portions where pixel colors have changed.
(CANVAS-SELECTION CANVAS)
gives me the bounding rectangle of the selected area. (A region is selected at any time by clicking and dragging on the canvas.)
There may be any number of dubious things in there, but the things that most confuse me are:
* What to subclass? I currently subclass APPLICATION-PANE. I don't know if I should subclass something else instead.
* Unintended overriding. I seem to accidentally override the border-building stuff from APPLICATION-PANE. It is not obvious to me why this happens, nor do I know how to avoid this should I want to.
* Event handling: to get pointer events I define a method on DISPATCH-EVENT that calls HANDLE-EVENT. Is this the way it is supposed to be done?
* Event handling & coordinates: to get coordinates relative to canvas when the pointer is outside the canvas area during the click-and-drag selection I transform coordinates through a common ancestor. This seems a bit awkward -- is there a better way?
Any comments would be most welcome.
Cheers,
-- Nikodemus
On Wed, Jul 29, 2009 at 2:23 PM, Nikodemus Siivolanikodemus@random-state.net wrote:
There may be any number of dubious things in there, but the things that most confuse me are:
- What to subclass? I currently subclass APPLICATION-PANE. I don't
know if I should subclass something else instead.
Subclassing APPLICATION-PANE is fine. For your purposes, subclassing BASIC-GADGET (or both) might be better (see below).
- Unintended overriding. I seem to accidentally override the
border-building stuff from APPLICATION-PANE. It is not obvious to me why this happens, nor do I know how to avoid this should I want to.
Not sure what you're referring to.
- Event handling: to get pointer events I define a method on
DISPATCH-EVENT that calls HANDLE-EVENT. Is this the way it is supposed to be done?
This works, but may inhibit built-in behaviors of the stream (like text selection, or wheel scrolling). CLIM's input model is brain-damaged, and event handlers on stream panes (including application-pane) usually don't work like you want, because magic input machinery steals the events and turns drives the input editor, mouse sensitivity to presentations, etc. Gadgets are excluded from this idiocy, so I've taken to mixing BASIC-GADGET into my classes when I want a stream pane with custom event handling. For your purposes, I'm not sure if you need a full CLIM stream at all, so you might consider subclassing only BASIC-GADGET.
Also, calling tracking-pointer from an event-handler is.. interesting. I'm sure it says something good about the CLIM design that this works. I'd have tried this using separate press/release event handlers, relying on X's implicit pointer grab, but I fear that doesn't give the behavior you want when the pointer is out of the window.
- Event handling & coordinates: to get coordinates relative to canvas
when the pointer is outside the canvas area during the click-and-drag selection I transform coordinates through a common ancestor. This seems a bit awkward -- is there a better way?
I can't think of a better way. You could simply the code slightly by using (graft sheet) as the common ancestor.