How to use GTK+ with ada - gtk

Anyone can show me some examples, simple, how to use GTK with Ada?
examples, like: How to use Glade with Ada, create an simple window....
an simple window, like this:
#include <gtk/gtk.h>
int main(int argc, char *argv[] )
{
GtkWidget *window;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_show (window);
gtk_main ();
return 0;
}
And, It's possible to use GtkMM, with ada ?
Thanks...

A few of my favorite GtkAda programs:
Animation demo
Linxtris
Mine Detector
Also, don't overlook the examples and testgtk folders of GtkAda itself.
Additional resources:
GTK+ API Documentation
Rosetta Code Category: Ada
Glade

Related

Why does gtk3 call the ClosureNotify function in the example code, but gkt4 doesn't?

When this example program
#include <gtk/gtk.h>
static void draw_func(
GtkDrawingArea* drawing_area,
cairo_t *cr,
#ifdef GTK3
#else
int width,
int height,
#endif
gpointer user_data
) {
printf("draw!\n");
}
struct Ctx {
char *text;
GtkWidget *drawing_area;
};
static void ctx_destroy_notify(
gpointer data
#ifdef GTK3
, GClosure* closure
#endif
) {
struct Ctx *ctx = data;
printf("drop!\n");
free(ctx->text);
g_object_unref(ctx->drawing_area);
free(ctx);
}
static void
activate (GtkApplication* app,
gpointer user_data)
{
GtkWidget *drawing_area = gtk_drawing_area_new();
GtkWidget *window = gtk_application_window_new (app);
struct Ctx *ctx = malloc(sizeof(struct Ctx));
ctx->text = strdup("Hallo");
ctx->drawing_area = g_object_ref(drawing_area);
#ifdef GTK3
g_signal_connect_data(G_OBJECT(drawing_area), "draw", G_CALLBACK(draw_func), ctx, ctx_destroy_notify, G_CONNECT_AFTER);
#else
gtk_drawing_area_set_draw_func( GTK_DRAWING_AREA(drawing_area), draw_func, ctx, ctx_destroy_notify);
#endif
#ifdef GTK3
gtk_container_add (GTK_CONTAINER (window), drawing_area);
#else
gtk_window_set_child (GTK_WINDOW(window), drawing_area);
#endif
#ifdef GTK3
gtk_widget_show_all(window);
#else
gtk_widget_show(window);
#endif
gtk_window_close(GTK_WINDOW(window));
}
int
main (int argc,
char **argv)
{
GtkApplication * app = gtk_application_new ("org.example.test", G_APPLICATION_FLAGS_NONE);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
g_application_run (G_APPLICATION (app), argc, argv);
printf("end of main loop\n");
g_object_unref (app);
}
is run with this Makefile:
.PHONY: test
test: test3 test4
./test3
./test4
test3: test.c
gcc -g -O0 -DGTK3 `pkg-config --cflags gtk+-3.0` -o test3 test.c `pkg-config --libs gtk+-3.0`
test4: test.c
gcc -g -O0 -DGTK4 `pkg-config --cflags gtk4` -o test4 test.c `pkg-config --libs gtk4`
The output is:
./test3
drop!
end of main loop
./test4
end of main loop
So ctx_destroy_notify is called with gtk3 but not with gtk4. Note, that gtk_widget_show (window); gtk_window_close(GTK_WINDOW(window)); can be replaced with g_object_run_dispose(G_OBJECT(window)); with the same result.
Why do gtk3 and gtk4 behave differently here?
[ to be ignored: stackoverflow wants a little bit more text, so that the text to code ratio is acceptable to its heuristic... ]
Edit 31.12.2022: Add first few lines of source, which were missing because of copy-and-paste mistake.
Okay, as nobody jumped on this, I try to answer that myself.
The code, obviously, contains a circular reference: drawing_area -> draw callback -> ctx -> drawing_area
The reference ctx -> drawing_area is correctly created with 
g_object_ref(), the other references are implied by gtk.
The function ctx_destroy_notify() in the code would break the reference
cycle with g_object_unref() if it gets called.
It is true, that gtk3 calls ctx_destroy_notify() when the application window is closed. This is a result of the fact that gtk3 immediately disposes the child widgets when a window is destroyed. But this is just an implementation detail.
There were substantial changes in this area between gtk3 and gtk4. See "Life-cycle handling" at https://docs.gtk.org/gtk4/migrating-3to4.html.
Here is a related discussion: https://gitlab.gnome.org/GNOME/gtk/-/issues/3243
In short: While the destroy_data notify of signal_connect_data() can be used to clean up the user data of the callback when the object is destroyed, it can not reliably be used to break a reference cycle which prevents the object from being destroyed in the first place.
Possible approaches to clean up the reference cycle would be:
subclass one of the widgets and make the ctx data part of it
For gtk4: Use a "win.close" action
Use weak references in ctx

Why doesn't my GtkBox update until I resize the whole window?

When I attach a menu to a window I detach the existing root control, add a vertical GtkBox to hold the menu and the root control and then attach that box to the GtkWindow, like so:
Gtk::GtkWidget *menubar = GTK_WIDGET(Info.obj);
Wnd->_VBox = Gtk::gtk_box_new(Gtk::GTK_ORIENTATION_VERTICAL, 0);
Gtk::GtkBox *vbox = GTK_BOX(Wnd->_VBox);
Gtk::GtkContainer *wndcontainer = GTK_CONTAINER(Wnd->Wnd);
g_object_ref(Wnd->_Root);
gtk_container_remove(wndcontainer, Wnd->_Root);
gtk_box_pack_start(vbox, menubar, false, false, 0);
gtk_box_pack_end(vbox, Wnd->_Root, true, true, 0);
gtk_container_add(wndcontainer, Wnd->_VBox);
gtk_widget_show_all(GTK_WIDGET(Wnd->Wnd));
g_object_unref(Wnd->_Root);
gtk_window_add_accel_group(Wnd->Wnd, AccelGrp);
In practice it looks like this:
What I'd like is the menu to appear in the correct place automatically without having to resize the window to force a layout update.
I've tried calling gtk_widget_queue_draw on the window but that made no difference. Am I doing something wrong here? Can a call an extra function to invalidate the layout and get it to refresh?
It's difficult to answer without having a minimal reproducible example. Your code in not even plain GTK or gtkmm... it seems to be some exotic variant between the two.
Here is my attempt: I tried to be as close as possible to your code. The issue you are describing is not present though.
/* gcc -o test test.c $(pkg-config --cflags --libs gtk+-3.0) */
#include <gtk/gtk.h>
static GMenu *
menu_model(void)
{
GMenu *menu = g_menu_new();
g_menu_append(menu, "File", NULL);
g_menu_append(menu, "Edit", NULL);
g_menu_append(menu, "Project", NULL);
/* ... */
return menu;
}
int main(int argc, char **argv)
{
GtkWidget *window;
GMenuModel *model;
GtkWidget *menubar;
GtkWidget *content;
GtkWidget *vbox;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
model = G_MENU_MODEL(menu_model());
menubar = gtk_menu_bar_new_from_model(model);
g_object_unref(model);
content = gtk_label_new("Some content here");
vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0);
gtk_box_pack_end(GTK_BOX(vbox), content, TRUE, TRUE, 0);
gtk_container_add(GTK_CONTAINER(window), vbox);
gtk_widget_show_all(GTK_WIDGET(window));
gtk_main();
return 0;
}
So while it should "just work" out of the box. And indeed on my Raspberry Pi the code does just do what it's supposed to do, this is still an issue on my Ubuntu 18 VM. I have found somewhat of a work around to kick the GtkBox into reconfiguring the child widget's layout:
GdkRectangle allocation = Wnd->GetClient();
g_signal_emit_by_name(G_OBJECT(vbox), "size-allocate", GTK_WIDGET(vbox), &allocation, NULL, NULL);
The menu now appears in the right location automatically. It seems like a "hack" that may stop working in the future or crash on some systems? IDK. But in terms of right now and Ubuntu 18, I don't have anything better.

Learning GUI programming with GTK+3

I am new to GUI programming. I recently installed Gtk+3 version on Linux. But, when I typed following code:
#include <gtk/gtk.h>
#include <stdio.h>
static int count = 0;
void button_clicked(GtkWidget *button, gpointer data)
{
printf(“%s pressed %d time(s) \n”, (char *) data, ++count);
}
int main (int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *button;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
button = gtk_button_new_with_label(“Hello World!”);
gtk_container_add(GTK_CONTAINER(window), button);
g_signal_connect(GTK_OBJECT (button), “clicked”,
GTK_SIGNAL_FUNC (button_clicked),
“Button 1”);
gtk_widget_show(button);
gtk_widget_show(window);
gtk_main ();
return 0;
}
To run this code I used this command: $ gcc gtk1.c –o gtk1 pkg-config --cflags --libs gtk+-3.0
but I had error like this
undefined reference to GTK_OBJECT;
undefined reference to GTK_SIGNAL_FUNC;
This is because your code sample is for an old version of GTK+ 2. GTK_OBJECT was deprecated in the late GTK+ 2.x versions, and finally removed in GTK+ 3. Same for GTK_SIGNAL_FUNC. Both have been moved to the GObject library, where they now stand as G_OBJECT and G_CALLBACK.
To avoid using outdated code, just get started with the code samples from the GTK+ 3 documentation.

Segfault when calling gtk_drawing_area_new

I have just a simple program
#include <gtk/gtk.h>
int main() {
GtkWidget * drawingarea = gtk_drawing_area_new(); // <-- Segfault
return 0;
}
which just creates a drawing area. But it segfaults. Why? I'm using ubuntu 18.04.
Using gtk_init before the call to gtk_drawing_area_new solves this problem.

How to create a GtkImage from a Cairo context?

I got a paint function that works using a Cairo context and the end result should be a GtkImage (without intermediate image creation). I tried to use the gdk_cairo_create function but this code:
...
GdkPixbuf *pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, 22, 22);
GtkWidget *image = gtk_image_new_from_pixbuf (pixbuf);
GdkDrawable *drawable = image->window;
cairo_t *ctx = gdk_cairo_create (drawable);
my_cairo_paint_function (ctx);
...
fails with:
Gdk-CRITICAL **: IA__gdk_cairo_create: assertion `GDK_IS_DRAWABLE (drawable)' failed
Same with a simple:
#include <gtk/gtk.h>
#include <cairo.h>
int
main (int argc, char *argv[])
{
gtk_init(&argc, &argv);
cairo_t *ctx = gdk_cairo_create (gtk_widget_get_window (gtk_image_new_from_file ("foobar.png")));
gtk_main();
return 0;
}
I don't understand why this fails. Any help is appreciated!
GtkImage doesn't have a GdkWindow, so the call to gtk_widget_get_window() or the access of widget->window returns NULL. You can put the GtkImage in a GtkEventBox and draw on the event box's GdkWindow.
Although, it looks like you're trying (with gdk_pixbuf_new) to create an empty space to draw on. In that case, GtkImage is not the widget you want -- use GtkDrawingArea. And don't forget to call your paint function in the handler for the event-expose signal!