I’ve restarted my cross-platform GTK4 C application from scratch. It’s an application that unfolds a volume from its 3d file and draws it flattened as a net of 2d triangles, that’s the easy part that I already made.
Next I want to add interactivity. For the previous version I did that using only a drawingArea that I redraw as needed, adding visible elements to show the user what the current selection is and so on. What do I need to do if I want the user to be able to hover a piece and have it change its border or color to reflect this hover event ? And what do I need to do for the user to be able to drag a piece a move it around the drawingArea ? (make a custom widget ? another drawingArea with only the pieces that shows on top of the big one ?) Or do I need to keep using only one big drawingArea and it’s events ? Depending on the 3d model, the big DrawingArea can contain more than 100 pages (the example shown has 15 pages). Is there somewhere an example of GTK4 C application implementing drawingArea hover and/or drag ? I think I read here that it’s just a matter of event to be able to hover on a drawArea, but I didn’t find anything about dragging, if needed it would be enough for me to be able to drag the bounding box frame of the piece, does this mean that I need to put a box over the drawingArea ?
GTK doesn’t care what you draw on the GtkDrawingArea, that’s the application business. As such, it cannot do picking for you — the application has to do some math and determine which piece is under the cursor.
Thank you, for the previous version of my application I handled piece picking, movement and rotation using events on the drawingArea, one on left click, another on right click and lots of keyboards pressed events. As I saw the gtkDemo drag example I was hoping that it was possible to implement it using a drawingArea or a custom widget, but I can simply reuse my code and improve it using an event to capture mouse moves even without a button press.
Apparently, it could be helpful for me to use gtk.snapshot for each piece I draw as I can use translate on them to move the whole piece instead of redrawing everything. Browsing the gtk demos, I found that “Simple paintable” is using snapshot, so I’m going to learn from it.
For the moment I was able to implement hover on graphical elements and it works fine. Sadly even if my app works, the way I use Cairo makes it hangs from time to time, certainly because of memory management. I tried to use GtkSnapshot but didn’t understand how to use it. It reminds me that before I started using GTK4, I made a console version of my application that only uses cairo to create a pdf file and it was able to create pdfs with hundreds pages without problem, and the first GTK4 GUI version of the app that used a GtkNotebook also was able to create and edit big pdfs, but having only one page shown at a time was not handy for edition. I hope that I will be able to implement a pagination that would allow Cairo memory management to stop hanging the application. But if pagination is mentioned several times on posts about draw area and cairo, there’s no concrete example. I first planned to use one gtkDrawArea per page, that was what I did on first version on the app with a notebook, but here pages are shown altogether. I don’t get how I could handle mouse events in such context. What is frustrating is that what I implemented, hover handling works perfectly.
Well, I figured out what was causing Cairo to hang and now my code works fine, but I still haven’t find anything about dragging graphical elements. There is the drag and drop project from Gtk Demos, but I didn’t find it helpful to learn about dragging, it looks more than a technical demo there to show what can be achieved when you know how it works, but without enough comments for those who don’t know how it works, and it uses things like ‘G_GNUC_BEGIN_IGNORE_DEPRECATIONS’ instead of dealing with deprecation. I’m afraid it is a very good example of how GTK works, more a technical demo than something usable by average coders.
If this is all within one drawing area, then you do not even need to use drop targets and drag sources. All that is needed is a GtkGestureDrag and then you implement the picking and dropping behavior yourself. The drop targets are only if you intend to have dragging from one window to another, or if you want users to be able to drop things from other apps into your app, or the other way around.
My previous version already used GtkGestureDrag but it had pages splitted into a notebook, each having a drawing area and the edition worked by redrawing the current drawing area after each event. Now I’m doing a new version where all the pages are shown into the same window (with scrolling), some of my files have > 100 pages, so that’s why I’m looking for a way to have my pieces drawn into their own snapshot so that the memory usage don’t become too important, but I didn’t find a way to use snapshots with Cairo or even create a custom widget (it’s something I already did but not with GTK that I’m using for the first time for this unfolder project). I doubt that the performance will be acceptable if I keep refreshing all the design after each event, but maybe I’m not understanding the way GTK drawing model works (even if I read the GTK doc chapter about it). What is sad is that Cairo can generate svg elements but doesn’t handle events involving them.
You can use gsk_cairo_node_new and then draw cairo content into the node. Then add it to a new snapshot and use gtk_snapshot_to_paintable to add it to a DragIcon. You can keep a reference to the node and also append it to another snapshot when drawing to the drawing area.
Cairo can only output to SVG as text, it does not include an implementation of SVG DOM or even an SVG renderer. That would be a lot more complicated.
The “model” for handling events is GTK. It is also not particularly hard to make a widget that wraps a cairo path and then calls cairo_in_fill to do hit testing, if that is what you want. IIRC Qt does a similar thing. Cairo is closer to using QPainter or HTML <canvas>, if you use those directly you will also have to handle hit testing within whatever content you draw.
Here, I mean targeting graphical elements created by Cairo, there is simply no model for handling events on them. I already have all the logic needed to handle hit testing and I’m happy to know that making a widget doing what I want is not particularly hard, so I will try to do that. What is hard about GTK is not its mechanisms that are the same as others libraries, but that there are not lots of examples project (or even real world projects) to learn from, that the documentation is not very detailed and that the developers seems to forget that there are first time users like me that don’t know all the backstage history of the library and its whole technical ecosystem.
On graphical elements there is no event handling, I mean for graphical elements like HTML <line> or <polygon> or for QT, QGraphicsSvgItem that handles events, I still need to learn more about QT but on its examples I found several projects involving graphical elements dragging. I would be happy to give some hand on GTK, my project is already partly on github, but I’m not sure it will be interesting for others.
Sorry I cannot understand how that is related, your example GTK app appears to drawing its own shapes, not SVGs. Drawing SVGs is only useful when you have loaded an external file, i.e. with QT SVG you cannot edit the lines or polygons at all.
Edit: on the web I would also not recommend using SVG DOM for anything besides simple generation or CSS transforms. If you need complex interactivity you must use HTML <canvas> and draw everything again, or at the very least you must rewrite the event handling anyway to handle transforms correctly.
Indeed I’m using vector graphics because the purpose of my application is to generate a 2d pattern that will be used with a cutter, and svg is a vector graphics format, does it make sense now ? You previously said that dragging is only useful between applications but here it is useful to move pieces around and join/disjoin pieces, and the code using dragging techniques is very simple. What you say about SVG DOM is wrong, my html.js application uses it to do exactly what I need it to do, dragging pieces, rotate them, tie and untie, add/remove flaps, I’m using this technique for years and it helps me build lots of cardboard furniture and objects that rely on correctness of the pattern. And what you said about QT SVG is just wrong also, I just read a QT example project which purpose is to dynamically edit svg elements.
Not quite. SVG is a document format for vector graphics. It is meant for writing and reading from files, not necessarily for being the in-memory representation. It works well for SVG embedded in HTML documents because the DOM is already available there, but GTK does not have a DOM so there is not really much reason to use SVG internally at all. Cairo primitives are almost identical to it anyway.