Diagrams is the best library for drawing diagrams in
Haskell. But can it be used as part of a user interface so you can
interact with parts of a diagram?
The answer is: yes.
In this article we walk through a simple example that combines
Diagrams, its Cairo backend and Gtk, to show a diagram and determine
which parts of the diagram the mouse is over.
The full source code for this example is at the bottom of this
article, but we’ll also look at some excerpts in detail.
Let’s start with the diagram to be shown. It’s a simple picture of a
house that a child might draw. The only special thing we do here is
tag parts of the diagram with the value function. Each part – the
wall, door, handle, roof, chimney and smoke – has a single string
attached to it.
Now we can query the points in the diagram to see what’s there.
With this we’re actually most of the way there. However, the
coordinate system of the diagram is not the same as the mouse
coordinates we’ll get from Gtk. We could take the mouse coordinates
and transform them into diagram coordinates, but let’s do it the other
way around and make the diagram coordinates as close to the mouse
coordinates as possible.
Gtk’s mouse coordinates have the origin (0,0) at the top left of the
canvas. So first we move the diagram’s origin to the top left:
Then we scale the diagram so that it’s the same width as the canvas:
(The freeze makes the line widths scale up too.)
Now we are almost done: our mouse and diagram coordinates are the same
size. The last wrinkle is that in diagrams-land positive
Y-coordinates go up, but in Gtk-land positive Y-coordinates go down.
We could reflect the diagram before we sample from it, but I found it
easier just to negate the Y-coordinate.
And we’re done! The rest of the program is basically just Gtk
plumbing.