Forum > GTK

Creating own widget in GTK

(1/1)

yyttyy:
The question will be very big! I'm a newbie and I'm currently writing a mini-project. I needed a button widget for it, but the standard widget didn't suit me, because I needed a button with my own style. I was looking for tutorials on creating my own widget and creating my own button. I found something, but widgets are implemented differently everywhere. I also found something about creating a button, but it wasn't a separate widget, just a single button implementation that didn't allow me to make multiple buttons(and I needed several). But thanks to this tutorial, I realized that it's best to use the cairo library to draw the context (image) inside the button. In short, here's what I managed to write:
Something like a header for types, and so on:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---unit ButtonWidgetHeader; interface uses glib2, gdk2pixbuf, gdk2, gtk2, Cairo; type    button_widget_state =        (state_button_normal, state_button_hovered, state_button_pressed); type    PGtkButtonWidget = ^TGtkButtonWidget;    TGtkButtonWidget = record        button_widget : TGtkFixed;        state : button_widget_state;        drawing_box : PGtkWidget;    end; type    PGtkButtonWidgetClass = ^TGtkButtonWidgetClass;    TGtkButtonWidgetClass = record        parent_class : TGtkFixedClass;        press_button : procedure (button_widget : PGtkButtonWidget);cdecl;        release_button : procedure (button_widget : PGtkButtonWidget);cdecl;    end; function GTK_TYPE_BUTTON_WIDGET() : GType;function GTK_BUTTON_WIDGET(obj : gpointer) : PGtkButtonWidget;function GTK_IS_BUTTON_WIDGET(obj : gpointer) : gboolean; implementation function GTK_TYPE_BUTTON_WIDGET() : GType;begin    GTK_TYPE_BUTTON_WIDGET := gtk_button_get_type();end; function GTK_BUTTON_WIDGET(obj : gpointer) : PGtkButtonWidget;begin    GTK_BUTTON_WIDGET := PGtkButtonWidget(G_TYPE_CHECK_INSTANCE_CAST ((obj),                                          GTK_TYPE_BUTTON_WIDGET))end; function GTK_IS_BUTTON_WIDGET(obj : gpointer) : gboolean;begin    GTK_IS_BUTTON_WIDGET := G_TYPE_CHECK_INSTANCE_TYPE(obj,                            gtk_button_get_type());end;    end. 
And the widget itself:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---unit ButtonWidget; interface uses glib2, gdk2pixbuf, gdk2, gtk2, Cairo, ButtonWidgetHeader in        '/home/yarik/Desktop/ButtonWidgetUnit(Incorrectly)/' +        'ButtonWidgetHeader.pp',        Header in        '/home/yarik/Desktop/Zhuzhculator/Prog/Units/Header/Header.pp'; function gtk_button_widget_new(pathnorm, pathhover,                               pathpress, pathmask : PathArr;                               width, height : integer) : PGtkWidget; implementation procedure gtk_button_widget_class_init(class : PGtkButtonWidgetClass);                                                 cdecl; forward;procedure gtk_button_widget_init(button_widget : PGtkButtonWidget);                                                 cdecl; forward;procedure move_cursor(widget : PGtkWidget; event : PGdkEventCrossing;                      user_data : gpointer);cdecl; forward;procedure press_cursor(widget : PGtkWidget; event : PGdkEventButton;                       user_data : gpointer);cdecl; forward; procedure gtk_button_widget_unrealize(widget : PGtkWidget); cdecl; forward; procedure gtk_button_widget_update(button_widget : PGtkButtonWidget);                                                        forward;procedure button_context_create(button_widget : PGtkButtonWidget;                                width, height : integer); forward;procedure button_images_init(); forward; type    button_signals = (PRESS_BUTTON_SIGNAL, RELEASE_BUTTON_SIGNAL);    button_images = (image_button_normal, image_button_hovered,                     image_button_pressed, image_button_mask);    button_pathes = (path_button_normal, path_button_hovered,                     path_button_pressed, path_button_mask);var    date_type : GType = 0;    button_widget_signals : array [button_signals] of guint = (0, 0);    button_widget_images : array [button_images] of Pcairo_surface_t;    button_widget_pathes : array [button_pathes] of PathArr;    parent_class : PGtkWidgetClass = nil; function gtk_button_get_type() : GType;const    date_info : TGTypeInfo =        (class_size : SizeOf(TGtkButtonWidgetClass);         base_init : nil;         base_finalize : nil;         class_init : TGClassInitFunc (@gtk_button_widget_class_init);         class_finalize : nil;         class_data : nil;         instance_size : SizeOf(TGtkButtonWidget);         n_preallocs : 0;         instance_init : TGInstanceInitFunc (@gtk_button_widget_init););begin    if (date_type = 0) then        date_type := g_type_register_static(            GTK_TYPE_EVENT_BOX, 'GtkButtonWidget', @date_info, 0            );    gtk_button_get_type := date_type;end;   procedure gtk_button_widget_class_init(class : PGtkButtonWidgetClass);cdecl;var    widget_class : PGtkWidgetClass;begin    widget_class := GTK_WIDGET_CLASS(class);    widget_class^.unrealize := @gtk_button_widget_unrealize;    button_widget_signals[PRESS_BUTTON_SIGNAL] :=        g_signal_new(        'press_button',        G_OBJECT_CLASS_TYPE(G_OBJECT_CLASS(class)),        G_SIGNAL_RUN_FIRST,        @class^.press_button - pointer(class),        nil,        nil,        @g_cclosure_marshal_VOID__VOID,        G_TYPE_NONE,        0);    button_widget_signals[RELEASE_BUTTON_SIGNAL] :=        g_signal_new(        'release_button',        G_OBJECT_CLASS_TYPE(G_OBJECT_CLASS(class)),        G_SIGNAL_RUN_FIRST,        @class^.release_button - pointer(class),        nil,        nil,        @g_cclosure_marshal_VOID__VOID,        G_TYPE_NONE,        0);end; procedure gtk_button_widget_init(button_widget : PGtkButtonWidget);cdecl;begin    button_widget^.state := state_button_normal;    button_widget^.drawing_box := gtk_drawing_area_new();    gtk_widget_realize(GTK_WIDGET(button_widget));    button_widget^.drawing_box^.window :=        gdk_window_new(GTK_WIDGET(button_widget)^.window, nil, 0);    gtk_widget_realize(button_widget^.drawing_box);    gtk_widget_show(button_widget^.drawing_box);    gtk_container_add(GTK_CONTAINER(button_widget),                      button_widget^.drawing_box);    gtk_widget_set_events (GTK_WIDGET(button_widget), GDK_ENTER_NOTIFY_MASK                           or GDK_LEAVE_NOTIFY_MASK);    g_signal_connect (G_OBJECT(button_widget),                      'button-press-event',                      G_CALLBACK(@press_cursor), nil);    g_signal_connect (G_OBJECT(button_widget),                      'button-release-event',                      G_CALLBACK(@press_cursor), nil);    g_signal_connect (G_OBJECT(button_widget),                      'enter-notify-event',                      G_CALLBACK(@move_cursor), nil);    g_signal_connect (G_OBJECT(button_widget),                      'leave-notify-event',                      G_CALLBACK(@move_cursor), nil);end; procedure move_cursor(widget : PGtkWidget; event : PGdkEventCrossing;                      user_data : gpointer);cdecl;//const   //  hand_cursor : PGdkCursor = nil;begin    if (event^._type = GDK_ENTER_NOTIFY) then    begin    //    if (hand_cursor = nil) then     //   begin       //     hand_cursor := gdk_cursor_new(GDK_HAND2);         //   gdk_window_set_cursor(widget^.window, hand_cursor)      //  end;        GTK_BUTTON_WIDGET(widget)^.state := state_button_hovered;        gtk_widget_queue_draw(GTK_BUTTON_WIDGET(widget)^.drawing_box);    end;    if (event^._type = GDK_LEAVE_NOTIFY) then    begin        GTK_BUTTON_WIDGET(widget)^.state := state_button_normal;        gtk_widget_queue_draw(GTK_BUTTON_WIDGET(widget)^.drawing_box);    end;    gtk_button_widget_update(GTK_BUTTON_WIDGET(widget));end; procedure press_cursor(widget : PGtkWidget; event : PGdkEventButton;                       user_data : gpointer);cdecl;begin    if (event^._type = GDK_BUTTON_PRESS) then    begin        g_signal_emit(GTK_BUTTON_WIDGET(widget),                      button_widget_signals[PRESS_BUTTON_SIGNAL], 0);         GTK_BUTTON_WIDGET(widget)^.state := state_button_pressed;        gtk_widget_queue_draw(GTK_BUTTON_WIDGET(widget)^.drawing_box);    end;    if (event^._type = GDK_BUTTON_RELEASE) then    begin        g_signal_emit(GTK_BUTTON_WIDGET(widget),                      button_widget_signals[RELEASE_BUTTON_SIGNAL], 0);         GTK_BUTTON_WIDGET(widget)^.state := state_button_hovered;     end;    gtk_button_widget_update(GTK_BUTTON_WIDGET(widget));end; procedure gtk_button_widget_unrealize(widget : PGtkWidget);cdecl;var    button_widget : PGtkButtonWidget;begin    if(widget = nil) then;        exit;    if(GTK_IS_BUTTON_WIDGET(widget) = false) then        exit;    button_widget := GTK_BUTTON_WIDGET(widget);    if(button_widget^.drawing_box <> nil) then        g_free(button_widget^.drawing_box);    if(GTK_OBJECT_CLASS(parent_class)^.destroy <> nil) then        GTK_OBJECT_CLASS(parent_class)^.destroy(GTK_OBJECT(widget))end; function gtk_button_widget_new(pathnorm, pathhover,                               pathpress, pathmask : PathArr;                               width, height : integer) : PGtkWidget;var    button_widget : PGtkButtonWidget;begin    button_widget :=         g_object_new(GTK_TYPE_BUTTON_WIDGET, nil);    button_widget_pathes[path_button_normal] := pathnorm;    button_widget_pathes[path_button_hovered] := pathhover;    button_widget_pathes[path_button_pressed] := pathpress;    button_widget_pathes[path_button_mask] := pathmask;    button_images_init();    button_context_create(button_widget, width, height);    gtk_button_widget_update(button_widget);    gtk_button_widget_new := GTK_WIDGET(button_widget);end; procedure button_images_init();begin    button_widget_images[image_button_normal] :=        cairo_image_surface_create_from_png(            @button_widget_pathes[path_button_normal]);    button_widget_images[image_button_hovered] :=        cairo_image_surface_create_from_png(            @button_widget_pathes[path_button_hovered]);    button_widget_images[image_button_pressed] :=         cairo_image_surface_create_from_png(            @button_widget_pathes[path_button_pressed]);    button_widget_images[image_button_mask] :=         cairo_image_surface_create_from_png(            @button_widget_pathes[path_button_mask]);end; procedure button_context_create(button_widget : PGtkButtonWidget;                                width, height : integer);var    mask_pixmap : PGdkPixmap;    context : Pcairo_t;begin    mask_pixmap := gdk_pixmap_new(nil, width, height, 1);    context := gdk_cairo_create(mask_pixmap);    cairo_set_source_surface(context, button_widget_images[image_button_mask],                             0, 0);    cairo_paint(context);    cairo_destroy(context);    gtk_widget_shape_combine_mask(button_widget^.drawing_box,                                  mask_pixmap, 0, 0);    gtk_widget_set_size_request(button_widget^.drawing_box,                                width, height);end; procedure gtk_button_widget_update(button_widget : PGtkButtonWidget);var    cr : Pcairo_t;begin    cr := gdk_cairo_create(button_widget^.drawing_box^.window);    case button_widget^.state of        state_button_normal:            cairo_set_source_surface(cr,                 button_widget_images[image_button_normal], 0, 0);        state_button_hovered:            cairo_set_source_surface(cr,                 button_widget_images[image_button_hovered], 0, 0);        state_button_pressed:            cairo_set_source_surface(cr,                 button_widget_images[image_button_pressed], 0, 0);    end;    cairo_paint(cr);    cairo_destroy(cr);end;  end. 
When creating a button with the button_widget_new (...) there are such errors:

(ZhuzhMain:11860): Gtk-CRITICAL **: 12:52:58.972: IA__gtk_widget_shape_combine_mask: assertion 'GTK_IS_WIDGET (widget)' failed

(ZhuzhMain:11860): Gtk-CRITICAL **: 12:52:58.972: IA__gtk_widget_set_size_request: assertion 'GTK_IS_WIDGET (widget)' failed
An unhandled exception occurred at $000000000043C7D8:
EAccessViolation: Access violation
  $000000000043C7D8
  $000000000043C67D
  $0000000000409A0B

I tried everything, but I don't understand what the problem is. Maybe I'm writing absolutely the wrong thing. Knowledgeable people please help!

Navigation

[0] Message Index

Go to full version