Hello everyone, this is the first time I've worked directly with the graphical GTK, I hope you can help me.
My idea is to create a class that extends GtkTreeView.
This class must have a toolbar (preferably implemented with GtkToolbar, but if it is too difficult even with a simple container) that will provide some additional functionality.
I would also like this toolbar, similar to the way as the labels GtkNotebook, is adjustable by means of a method "_set_toolbar_position ([new Widget] widget, GtkPositionType pos);"
Preferably I would like the result to be like this (see image attachment) or as you can see, the graphics area of the parent class is inscribed in a rounded edge like the cards GtkNotebook.
Attachment:
File comment: Final release how I would like the widget to appear graphically (ps: even the buttons are only a stub)
GtkExtendTreeView.png [ 26.52 KiB | Viewed 638 times ]
For anyone who can help me I will be happy to share the full merits of the implementation of this class. Below place the code in the first draft that I got.
Thank you all in advance! :)
PS: Both the name of the widget that the buttons on the toolbar are currently stubs.gtkextendtreeview.hCode:
/* GTK - The GIMP Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* [...]
*/
#ifndef __GTK_EXTEND_TREE_VIEW_H__
#define __GTK_EXTEND_TREE_VIEW_H__
#include <glib.h>
#include <glib-object.h>
#include <gtk/gtktreeview.h>
#include <gtk/gtktreeselection.h>
#include <gtk/gtkhbox.h>
#include <gtk/gtkvbox.h>
#include <gtk/gtklabel.h>
#include <gtk/gtkstock.h>
#include <gtk/gtkbutton.h>
G_BEGIN_DECLS
#define GTK_TYPE_EXTEND_TREE_VIEW (gtk_extend_tree_view_get_type())
#define GTK_EXTEND_TREE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_EXTEND_TREE_VIEW, GtkExtendTreeView))
#define GTK_EXTEND_TREE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_EXTEND_TREE_VIEW, GtkExtendTreeViewClass))
#define GTK_IS_EXTEND_TREE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_EXTEND_TREE_VIEW))
#define GTK_IS_EXTEND_TREE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_EXTEND_TREE_VIEW))
typedef struct _GtkExtendTreeView GtkExtendTreeView;
typedef struct _GtkExtendTreeViewClass GtkExtendTreeViewClass;
struct _GtkExtendTreeView
{
GtkTreeView parent;
GtkWidget* toolbar;
};
struct _GtkExtendTreeViewClass
{
GtkTreeViewClass parent_class;
};
/* Used to implement object-GTK, provides the type of the created widget */
GType gtk_extend_tree_view_get_type(void) G_GNUC_CONST;
/* Creates a new GtkTableGrid widget */
GtkWidget* gtk_extend_tree_view_new(void);
G_END_DECLS
#endif /* __GTK_EXTEND_TREE_VIEW_H__ */
gtkextendtreeview.cCode:
/* GTK - The GIMP Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* [...]
*/
#include "gtkextendtreeview.h"
/* Static pointer to parent class of GtkExtendTreeView */
static GtkTreeViewClass* parent_class;
static void gtk_extend_tree_view_set_property(GObject* object, guint prop_id, const GValue *value, GParamSpec* pspec){
switch(prop_id){
//TODO: Implements setting properties
break;
default: /* invalid property */
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
}
}
static void gtk_extend_tree_view_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec){
switch(prop_id){
//TODO: Implements getting properties
default: /* invalid property */
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
}
}
static void gtk_extend_tree_view_realize(GtkWidget* const widget){
/* Invokes the method realize the parent class */
GTK_WIDGET_CLASS(parent_class)->realize(widget);
/* Retrieve a reference to the toolbar */
GtkWidget* const toolbar = GTK_EXTEND_TREE_VIEW(widget)->toolbar;
if(gtk_widget_get_parent(toolbar) != widget){
gtk_widget_freeze_child_notify (toolbar);
gtk_widget_set_parent (toolbar, widget);
gtk_widget_thaw_child_notify (toolbar);
}
}
static void gtk_extend_tree_view_show(GtkWidget* const widget){
GTK_WIDGET_CLASS(parent_class)->show(widget);
gtk_widget_show(GTK_EXTEND_TREE_VIEW(widget)->toolbar);
}
static void gtk_extend_tree_view_map(GtkWidget* const widget){
GTK_WIDGET_CLASS(parent_class)->map(widget);
gtk_widget_map(GTK_EXTEND_TREE_VIEW(widget)->toolbar);
}
static void gtk_extend_tree_view_size_request(GtkWidget* const widget, GtkRequisition* const requisition){
/* Invokes the method size request the parent class */
GTK_WIDGET_CLASS(parent_class)->size_request(widget,requisition);
/* Retrieve a reference to the toolbar */
GtkWidget* const toolbar = GTK_EXTEND_TREE_VIEW(widget)->toolbar;
/* Check that the toolbar is visible */
if(gtk_widget_get_visible(toolbar)){
/* Declare a structure to retrieve the required size from the toolbar */
GtkRequisition toolbar_requisition;
/* Recovery required size of the toolbar */
gtk_widget_size_request(toolbar,&toolbar_requisition);
/* Add the required height from the tree view, the request from the toolbar */
requisition->height += toolbar_requisition.height;
/* If the toolbar requires a width greater than that of the tree view, the value of required width is reimposed */
if(toolbar_requisition.width>requisition->width)
requisition->width = toolbar_requisition.width;
}
/* Are added to the size to be requested also those relating to the thickness of the border */
requisition->width += GTK_CONTAINER(widget)->border_width * 2;
requisition->height += GTK_CONTAINER(widget)->border_width * 2;
}
static void gtk_extend_tree_view_size_allocate(GtkWidget* const widget, GtkAllocation* const allocation){
/* Retrieve a reference to the toolbar */
GtkWidget* const toolbar = GTK_EXTEND_TREE_VIEW(widget)->toolbar;
/* Invokes the method size allocation the parent class */
GTK_WIDGET_CLASS(parent_class)->size_allocate(widget,allocation);
/* Check that the toolbar is visible */
if(gtk_widget_get_visible(toolbar)){
/* Declares two structures to represent the size and location of the toolbar */
GtkRequisition toolbar_requisition;
GtkAllocation toolbar_allocation;
/* Retrieve the size of the tree view border */
const guint16 border = GTK_CONTAINER(widget)->border_width;
/* Sets the toolbar width, if it's greater than zero and equal to the difference between the tree view width and twice of the tree view border */
toolbar_allocation.width = (gint) allocation->width - (gint) border * 2;
if(toolbar_allocation.width<1)toolbar_allocation.width=1;
/* Set the horizontal distance of the toolbar */
toolbar_allocation.x = allocation->x + border;
/* Recovery required size of the toolbar */
gtk_widget_get_child_requisition(toolbar, &toolbar_requisition);
/* Imposed on the value of the height of the toolbar, equal to the height required if this is greater than zero */
toolbar_allocation.height = toolbar_requisition.height<1?1:toolbar_requisition.height;
/* Set the vertical distance of the toolbar */
toolbar_allocation.y = allocation->y + allocation->height - border + toolbar_requisition.height;
/* Allocate the new size of the toolbar */
gtk_widget_size_allocate (toolbar, &toolbar_allocation);
}
}
static void gtk_extend_tree_view_forall(GtkContainer* const container, const gboolean include_internals, GtkCallback callback, gpointer const callback_data){
/* Invokes the method forall of the parent class */
GTK_CONTAINER_CLASS(parent_class)->forall(container,include_internals,callback,callback_data);
/* Check if the callback should be applied also to the internal child */
if(include_internals){
/* Invokes the callback for the toolbar of the tree view */
(*callback) (GTK_EXTEND_TREE_VIEW(container)->toolbar, callback_data);
}
}
/* Internal Widget Implementation ::: Initializes the widget class */
static void gtk_extend_tree_view_class_init(GtkExtendTreeViewClass* const klass){
/* GObject signals */
GObjectClass* const o_klass = G_OBJECT_CLASS(klass);
o_klass->set_property = gtk_extend_tree_view_set_property;
o_klass->get_property = gtk_extend_tree_view_get_property;
GtkContainerClass* const c_klass = GTK_CONTAINER_CLASS(klass);
c_klass->forall = gtk_extend_tree_view_forall;
/* GtkWidget signals */
GtkWidgetClass* const w_klass = GTK_WIDGET_CLASS(klass);
w_klass->realize = gtk_extend_tree_view_realize;
w_klass->show = gtk_extend_tree_view_show;
w_klass->map = gtk_extend_tree_view_map;
w_klass->size_request = gtk_extend_tree_view_size_request;
w_klass->size_allocate = gtk_extend_tree_view_size_allocate;
/* Store in global variable the reference to object class of the widget */
parent_class = g_type_class_peek_parent(klass);
/* GtkExtendTreeView Signals */
//TODO: Install signals
/* GtkExtendTreeView Properties */
//TODO: Install properties
}
static void gtk_extend_tree_view_init(GtkExtendTreeView* const widget){
//FIXME: This button is only an example widget that will later be replaced by a
// toolbar with various buttons for various functions of the class.
widget->toolbar = gtk_button_new_from_stock(GTK_STOCK_ABOUT);
}
/* Internal Widget Implementation ::: Return the GtkExtendTreeView type */
GType gtk_extend_tree_view_get_type(void){
static GType gtk_extend_tree_view_type = 0;
if(!gtk_extend_tree_view_type){
const GTypeInfo gtk_extend_tree_view_info = {
sizeof (GtkExtendTreeViewClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) gtk_extend_tree_view_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GtkExtendTreeView),
0,
(GInstanceInitFunc) gtk_extend_tree_view_init,
};
gtk_extend_tree_view_type = g_type_register_static (GTK_TYPE_TREE_VIEW, "GtkExtendTreeView", >k_extend_tree_view_info, 0);
}
return gtk_extend_tree_view_type;
}
/* Creates a new GtkExtendTreeView widget */
GtkWidget* gtk_extend_tree_view_new(){
return g_object_new(GTK_TYPE_EXTEND_TREE_VIEW,NULL);
}
main.cCode:
#include <gtk/gtk.h>
#include "gtkextendtreeview.h"
static GtkWidget* BuildExtendTreeView(){
/* Creates an instance of the new widget */
GtkExtendTreeView* const extend_tree = GTK_EXTEND_TREE_VIEW(gtk_extend_tree_view_new());
/* Create a sample tree model */
GtkListStore* const store = gtk_list_store_new(2,G_TYPE_STRING,G_TYPE_STRING);
/* Set in the template two columns of example */
GtkTreeView* const table = GTK_TREE_VIEW(extend_tree);
gtk_tree_view_set_model(table,GTK_TREE_MODEL(store));
/* Create a new GtkCellRendererText, add it to the tree view column */
GtkCellRenderer* const renderer = gtk_cell_renderer_text_new();
/* Create all the tree view columns needed to build the tree view model, and append them to the tree view */
GtkTreeViewColumn *column = NULL;
column = gtk_tree_view_column_new_with_attributes("First Column",renderer,"text",0,NULL);
gtk_tree_view_append_column(table,column);
column = gtk_tree_view_column_new_with_attributes("Second Column",renderer,"text",1,NULL);
gtk_tree_view_append_column(table,column);
/* Return the new widget */
return GTK_WIDGET(extend_tree);
}
int main (int argc, char *argv[])
{
GtkWidget *win = NULL;
/* Initialize GTK+ */
g_log_set_handler ("Gtk", G_LOG_LEVEL_WARNING, (GLogFunc) gtk_false, NULL);
gtk_init (&argc, &argv);
g_log_set_handler ("Gtk", G_LOG_LEVEL_WARNING, g_log_default_handler, NULL);
/* Create the main window */
win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_container_set_border_width (GTK_CONTAINER (win), 8);
gtk_window_set_title (GTK_WINDOW (win), "Example to Extend Tree View");
gtk_window_set_position (GTK_WINDOW (win), GTK_WIN_POS_CENTER);
g_signal_connect (win, "destroy", gtk_main_quit, NULL);
gtk_widget_set_size_request(GTK_WIDGET(win), 600,300);
gtk_widget_realize (win);
/* Creates an instance of the new widget and attach it to the window */
gtk_container_add (GTK_CONTAINER (win), BuildExtendTreeView());
/* Enter the main loop */
gtk_widget_show_all (win);
gtk_main ();
return 0;
}