I am learning Gtk through C++ by using the gtkmm library.
My goal is to implement a node based gui inspired by Blender’s one.
Basically, I want to create a node editor when I can create and add nodes and arrange them freely.
A node is a rounded rectangle with input and output sockets corresponding to different properties.
I want to be able to connect nodes by dragging cables from each one’s sockets.
These are my questions :
I planned to create a customized widget deriving from Gtk::Container to create the node widget. If I want to have gtk widgets (like sliders, text inputs or images) inside the node itself, I must implement my own container is that right?
The node editor is a frame where I need to be able to pan (with mmb) and zoom by scrolling. Is it possible to do that in Gtk so I can zoom on widgets? Because I can do this with Gtk::DrawingArea and Cairo but then I can’t have native gtk widgets inside the nodes…
I hope it’s clear I can’t really figure out how to implement this…
Thank you for your answer! This is an interesting problem to solve
I managed to style my custom widget with CSS using a grid.
Now I have some other questions :
If I want to be able to drag my nodes on the Gtk::Fixed surface, is there a signal handler for when the mouse is dragged? Then I need to determine on which node I clicked and change its coordinates.
How can I draw on the Gtk::Fixed area? I tried to override the on_draw method with Cairo but then the widgets are not being drawn on the screen… I imagine that I need to draw the node sockets in addition to the links between the nodes with Cairo.
Yes there are signals and stuff for handling drag and drop. But I’m not so proficient in it. Python tutorial on DnD could help you on it. (It’s for Python but…)
From the documentation of GTK Fixed, I think it’s better to use GTK Layout for placing widgets at arbitrary position and also handle drawing.
On the Gtk::Layout documention, it says that it’s convenient for drawing like Gtk::DrawingArea but I can’t find the right method to draw using the Cairo context.
What I managed to do is to override the on_draw method but then the widgets are not drawn on the layout. (I assume that the default on_draw method is drawing all the widgets…)
So I did this :
bool NodeEditor::on_draw(const ::Cairo::RefPtr<::Cairo::Context> &cr)
{
// Draw the background (node editor grid)
// Then draw the widgets on my own
std::vector<Gtk::Widget*> children = get_children();
for(std::size_t i = 0; i<children.size(); i++){
propagate_draw(*children.at(i), cr);
}
return true;
}
Now I am using the propagate_draw method to draw all the child widgets on my own but this seems a bit hacky…
Also it says that Gtk::Layout is an Infinite scrollable area when using Gtk::ScrolledWindow.
I tried putting the layout into a scrolled window with the void Gtk::ScrolledWindow::add ( Gtk::Widget& widget ) method but it doesn’t work, I can’t scroll on the layout…
What is the right way to do this? The documentation isn’t so much informative.