1

I've been working on my summer research project, and I've been using the Diagrams library to draw graphs with edges, nodes. I'm simulating the spread of information throughout the graph, so my diagram is constantly updating discretely. I have all of the infrastructure for updating the graph's state data structures, drawing the diagrams etc.

For testing purposes, I've just been using the SVG backend with a feedback loop of getLine, updating the diagram, then rendering it to the same '.svg' file. This is obviously quite shoddy and relies on the fact that my .svg viewer updates when the file does.

I've looked into using the GTK backend for this, so I can just render the diagram to a drawingArea in a GTK window. I've got all of this installed and have been messing around with a few small programs.

However I cannot wrap my head around how I can implement my program. I've seen quite a few examples of how to draw a diagram in a GTK window, but none of them seem to include updating of that image based on a button press, or even something from the command line.

I've heard a bit about multithreading with GTK. I'm considering writing a function like:

renderDiagram :: DrawingArea -> Diagram B -> IO ()
renderDiagram c d = do
 c `on` exposeEvent $ do
   liftIO (defaultRender c d)
   return True
 widgetQueueDraw c

To change what diagram is rendered when the canvas is exposed, then forcing an expose event. If I then run my main program execution of updating the graph, and running renderDiagram on a separate thread to mainGUI, will I get my desired results? Is there a cleaner way to do this?

If anyone could point me in the right direction, or offer some external reading, that would be great. Thanks.

  • Multithreading is almost certainly neither needed nor will it be helpful here without great effort. Presumably the thing you might want to do in a separate thread is render the image while still accepting GTK events in another thread; but this will require rendering to an off-screen buffer first, then copying that buffer into your `DrawingArea`. Unless rendering takes a long time, that probably isn't worth the effort. That said, [I have some writing on how to do GTK multithreading correctly](http://dmwit.com/gtk2hs/) should you ultimately decide to go down that path. – Daniel Wagner Jul 07 '18 at 15:41

1 Answers1

0

Have you checked this article? I think the article explains just what you are trying to do.

You can use buttonPressEvent instead of motionNotifyEvent, if you want to do something upon mouse clicking.

wkoiking
  • 68
  • 5
  • I have just uploaded some [sample code](https://github.com/wkoiking/diagrams-gtk-template/blob/master/app/Main.hs) for diagrams + gtk application for your reference. – wkoiking Jul 07 '18 at 16:56
  • Also, you can set up the environment by following the [README](https://github.com/wkoiking/diagrams-gtk-template) – wkoiking Jul 07 '18 at 17:59
  • Yes! That sample code is exactly what I need! I thought about using IORefs as I'm pretty experienced with pointers in C, but they seemed very un-Haskell, but it clearly makes sense here. – user2930356 Jul 08 '18 at 15:11
  • Update: This is working now, and my diagram updates using my function and an IORef with a press of a key. Now I have another problem related to this and the links you provided. I'm trying to use queries for mouse clicks. All of my diagrams are constructed from parts that are "named". I thought I'd be able to somehow link of the querying system to give me the name of each part when clicked. I see in your example you use "value", but that requires QDiagram Cairo V2 Double [String] as the type signature, whilst all of mine are Diagram B. Is there anyway to get around this? – user2930356 Jul 09 '18 at 14:56
  • I usually just define `type SelectableDiagram = QDiagram Cairo V2 Double [String]` and `type NormalDiagram = Diagram B` then conversion can be done by `value [] :: NormalDiagram -> SelectableDiagram` and `clearValue :: SelectableDiagram -> NormalDiagram` – wkoiking Jul 12 '18 at 03:49
  • By the way, the type `Diagram B` just synonym of `QDiagram Cairo V2 Double Any`. You can get detail of how query is done [here](https://archives.haskell.org/projects.haskell.org/diagrams/doc/manual.html#using-queries) – wkoiking Jul 12 '18 at 03:57