How can I add GtkEventBox in scrolled windows layout? - c

I have a GTK+2 program which combining GtkScrolledWindow and GtkLayout. It works fine. But, I found if I put a GtkEvent object to GtkLayout, it will not display properly. Anybody knows why ? Thanks.
#include <gtk/gtk.h>
int main( int argc, char *argv[] )
{
GtkWidget *window, *button, *layout, *eventbox, *scrollwindow;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_set_size_request (window, 150, 150);
button = gtk_button_new_with_label ("button");
layout = gtk_layout_new(NULL, NULL);
gtk_layout_set_size( GTK_LAYOUT(layout), 300, 300);
scrollwindow = gtk_scrolled_window_new(GTK_LAYOUT(layout)->hadjustment, GTK_LAYOUT(layout)->vadjustment);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollwindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_layout_put( GTK_LAYOUT(layout), button, 50, 250 );
/* uncomment to use eventbox
eventbox = gtk_event_box_new();
gtk_container_add( GTK_CONTAINER(eventbox), layout);
gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(scrollwindow), eventbox);
*/
// comment this line when use eventbox
gtk_container_add( GTK_CONTAINER(scrollwindow), layout);
gtk_container_add((GtkContainer*)window, scrollwindow);
gtk_widget_show_all(window);
gtk_main ();
return 0;
}
The picture if the eventbox is used.

I found it does not have to use GtkEventBox here. The GtkLayout can capture events directly.
The following widgets do not have an associated window. So, It should be used with the GtkEventBox if you want to capture events.
GtkAlignment
GtkArrow
GtkBin
GtkBox
GtkImage
GtkItem
GtkLabel
GtkPaned
GtkPixmap
GtkScrolledWindow
GtkSeparator
GtkTable
GtkViewport
GtkAspectFrame
GtkFrame
GtkVPaned
GtkHPaned
GtkVBox
GtkHBox
GtkVSeparator
GtkHSeparator
The fixed program :
#include <gtk/gtk.h>
static gboolean button_press_event( GtkWidget *widget, GdkEventButton *event ) {
if (event->button == 1 ) printf("but down %i , %i\n", (int)event->x, (int)event->y);
return TRUE;
}
int main( int argc, char *argv[] )
{
GtkWidget *window, *button, *layout, *eventbox, *scrollwindow;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_set_size_request (window, 150, 150);
button = gtk_button_new_with_label ("button");
layout = gtk_layout_new(NULL, NULL);
gtk_layout_set_size( GTK_LAYOUT(layout), 300, 300);
scrollwindow = gtk_scrolled_window_new(gtk_layout_get_hadjustment(layout), gtk_layout_get_vadjustment(layout));
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollwindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_layout_put( GTK_LAYOUT(layout), button, 50, 250 );
gtk_container_add( GTK_CONTAINER(scrollwindow), layout);
gtk_container_add(GTK_CONTAINER(window), scrollwindow);
g_signal_connect (layout, "button_press_event", G_CALLBACK (button_press_event), NULL);
gtk_widget_set_events(layout, GDK_EXPOSURE_MASK
| GDK_LEAVE_NOTIFY_MASK | GDK_BUTTON_PRESS_MASK
| GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK);
gtk_widget_show_all(window);
gtk_main ();
return 0;
}
The result of clicking on GtkLayout :

Related

How to change the background color of the line numbers mode in GTK3+?

I'm designing a text editor in C/GTK3+, using the GtkSourceView class to be able to show the line numbers via the method gtk_source_view_set_show_line_numbers. I'm able to modify the background color of textview and text but not that of panel containing line numbers. By default it seems to be white. Can you show me how to modify it?
This is the code:
#include <gtk/gtk.h>
#include <gtksourceview/gtksource.h>
void find (GtkTextView *text_view, const gchar *text, GtkTextIter *iter)
{
GtkTextIter mstart, mend;
GtkTextBuffer *buffer;
gboolean found;
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
found = gtk_text_iter_forward_search (iter, text, 0, &mstart, &mend, NULL);
if (found)
{
gtk_text_buffer_select_range (buffer, &mstart, &mend);
gtk_text_buffer_create_mark (buffer, "last_pos", &mend, FALSE);
}
}
typedef struct App
{
GtkWidget *text_view;
GtkWidget *search_entry;
} App;
/* Called when main window is destroyed. */
void
win_destroy (void)
{
gtk_main_quit();
}
void
next_button_clicked (GtkWidget *next_button, App *app)
{
const gchar *text;
GtkTextBuffer *buffer;
GtkTextMark *last_pos;
GtkTextIter iter;
text = gtk_entry_get_text (GTK_ENTRY (app->search_entry));
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (app->text_view));
last_pos = gtk_text_buffer_get_mark (buffer, "last_pos");
if (last_pos == NULL)
return;
gtk_text_buffer_get_iter_at_mark (buffer, &iter, last_pos);
find (GTK_TEXT_VIEW (app->text_view), text, &iter);
}
/* Called when search button is clicked. */
void
search_button_clicked (GtkWidget *search_button, App *app)
{
const gchar *text;
GtkTextBuffer *buffer;
GtkTextIter iter;
text = gtk_entry_get_text (GTK_ENTRY (app->search_entry));
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (app->text_view));
gtk_text_buffer_get_start_iter (buffer, &iter);
find (GTK_TEXT_VIEW (app->text_view), text, &iter);
}
int
main (int argc, char *argv[])
{
GtkWidget *win;
GtkWidget *vbox;
GtkWidget *hbox;
GtkWidget *search_button;
GtkWidget *next_button;
GtkWidget *swindow;
GtkCssProvider *provider;
GtkStyleContext *context;
App app;
gtk_init (&argc, &argv);
/* Create a window with a search entry, search button and a text
area. */
win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
g_signal_connect (G_OBJECT (win), "destroy", win_destroy, NULL);
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL,0);
gtk_container_add (GTK_CONTAINER (win), vbox);
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL,0);
gtk_container_add(GTK_CONTAINER (vbox), hbox);
app.search_entry = gtk_entry_new ();
search_button = gtk_button_new_with_label ("Search");
next_button = gtk_button_new_with_label ("Next");
gtk_container_add(GTK_CONTAINER (hbox), app.search_entry);
gtk_container_add(GTK_CONTAINER (hbox), search_button);
gtk_container_add(GTK_CONTAINER (hbox), next_button);
g_signal_connect (G_OBJECT (search_button), "clicked",
G_CALLBACK (search_button_clicked), &app);
g_signal_connect (G_OBJECT (next_button), "clicked",
G_CALLBACK (next_button_clicked), &app);
/* A scrolled window which automatically displays horizontal and
vertical scrollbars when the text exceeds the text view's size. */
swindow = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_widget_set_vexpand (swindow, TRUE);
gtk_container_add(GTK_CONTAINER (vbox), swindow);
app.text_view = gtk_source_view_new ();
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_data (provider,
"textview{"
"font-size: 30px;"
"font-family: serif;"
"} text{"
"color: green;"
"background: black;"
"}",
-1,
NULL);
context = gtk_widget_get_style_context (app.text_view);
gtk_style_context_add_provider (context,
GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
gtk_container_add (GTK_CONTAINER (swindow), app.text_view);
gtk_source_view_set_show_line_numbers (GTK_SOURCE_VIEW((app.text_view)), TRUE);
gtk_widget_show_all (win);
gtk_main();
}
There are generally two possibilities.
The typical way this is done is not by changing colors on the GtkSourceView, but to instead use a style scheme with gtk_source_buffer_set_style_scheme(). The style scheme has a "line-number" and "current-line-number" style which can have a color associated with it.
Another way, that is typically only used to show information about marks, is to have a GtkSourceMark with GtkSourceMarkAttributes:background set. Then you can show marks in the gutter.
Generally speaking, when you get to certain levels of complexity, it's just easier to write your own gutter renderer to optimize for the problem space.

How to add css style context providers for all labels in a grid?

I am trying to set the background color of all labels in GtkGrid. Here is a simplified example:
#include <gtk/gtk.h>
static void activate (GtkApplication* app, gpointer user_data)
{
GtkWidget *window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Window1");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
GtkWidget *grid = gtk_grid_new ();
gtk_container_add (GTK_CONTAINER (window), grid);
GtkWidget *label1 = gtk_label_new("Hello world!");
gtk_widget_set_hexpand( label1, TRUE);
gtk_grid_attach(GTK_GRID (grid), label1, 0,0,1,1);
GtkWidget *label2 = gtk_label_new("Simple Gtk example");
gtk_widget_set_hexpand( label2, TRUE);
gtk_grid_attach(GTK_GRID (grid), label2, 0,1,1,1);
GtkCssProvider *provider = gtk_css_provider_new ();
gtk_css_provider_load_from_data (
provider, "label {background-color: #AAAAAA;}", -1, NULL);
GtkStyleContext *context = gtk_widget_get_style_context (grid);
gtk_style_context_add_provider(
context, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_USER);
gtk_widget_show_all (window);
}
int main (int argc, char **argv) {
GtkApplication *app = gtk_application_new(
"org.gtk.example", G_APPLICATION_FLAGS_NONE );
g_signal_connect( app, "activate", G_CALLBACK(activate), NULL);
int status = g_application_run(G_APPLICATION(app), argc, argv);
g_object_unref (app);
return status;
}
However, adding the style context provider to the grid's context (as shown above) does not work.
I've modified your code, this will change the background of the labels:
#include <gtk/gtk.h>
static void activate (GtkApplication* app, gpointer user_data)
{
GtkWidget *window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Window1");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
GtkWidget *grid = gtk_grid_new ();
gtk_container_add (GTK_CONTAINER (window), grid);
GtkWidget *label1 = gtk_label_new("Hello world!");
gtk_widget_set_hexpand( label1, TRUE);
gtk_grid_attach(GTK_GRID (grid), label1, 0,0,1,1);
GtkWidget *label2 = gtk_label_new("Simple Gtk example");
gtk_widget_set_hexpand( label2, TRUE);
gtk_grid_attach(GTK_GRID (grid), label2, 0,1,1,1);
GtkCssProvider *provider = gtk_css_provider_new ();
GdkDisplay *display = gdk_display_get_default();
GdkScreen *screen = gdk_display_get_default_screen (display);
gtk_style_context_add_provider_for_screen (screen, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_USER);
gtk_css_provider_load_from_data (
provider, "GtkLabel { background-color: #AAAAAA;}", -1, NULL);
gtk_widget_show_all (window);
}
int main (int argc, char **argv) {
GtkApplication *app = gtk_application_new(
"org.gtk.example", G_APPLICATION_FLAGS_NONE );
g_signal_connect( app, "activate", G_CALLBACK(activate), NULL);
int status = g_application_run(G_APPLICATION(app), argc, argv);
g_object_unref (app);
return status;
}
Result:

Is it possible to put GtkLayouts inside GtkLayout?

I want to put 2 GtkLayouts into GtkLayout. But, it seems to not be working. Anyone knows why ? or, there are some restrictions using gtk components.
#include <gtk/gtk.h>
int main( int argc, char *argv[] )
{
GtkWidget *window, *main_container, *t, *p;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "layout test");
gtk_window_maximize(GTK_WINDOW(window));
g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
main_container = gtk_layout_new(NULL, NULL);
GdkColor color;
gdk_color_parse ("green", &color);
gtk_widget_modify_bg( GTK_WIDGET(main_container), GTK_STATE_NORMAL, &color);
gdk_color_parse ("red", &color);
t = gtk_layout_new(NULL, NULL);
gtk_layout_set_size( GTK_LAYOUT(t), 300, 300);
gtk_widget_modify_bg( GTK_WIDGET(t), GTK_STATE_NORMAL, &color);
gdk_color_parse ("yellow", &color);
p = gtk_layout_new(NULL, NULL);
gtk_layout_set_size( GTK_LAYOUT(p), 300, 300);
gtk_widget_modify_bg( GTK_WIDGET(p), GTK_STATE_NORMAL, &color);
gtk_layout_put( GTK_LAYOUT(main_container), t, 0, 0 );
gtk_layout_put( GTK_LAYOUT(main_container), p, 0, 300 );
gtk_container_add(GTK_CONTAINER(window), main_container);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}
I found the answer. If the container is appended into another container, it should be treated as a widget. Therefore, uses gtk_widget_set_size_request instead of gtk_layout_set_size will solve this problem.

How to set fontsize of label with Pango attributes?

I am trying to add a label to a GTK3 window and then set the font size of the label. Here is my attempt:
#include <gtk/gtk.h>
static void
add_label (GtkWidget* window, gchar *text)
{
GtkWidget *label = gtk_label_new(text);
PangoAttrList *attrlist = pango_attr_list_new();
PangoAttribute *attr = pango_attr_size_new_absolute(20);
pango_attr_list_insert(attrlist, attr);
gtk_label_set_attributes(GTK_LABEL(label), attrlist);
pango_attr_list_unref(attrlist);
gtk_container_add (GTK_CONTAINER (window), label);
}
static void
activate (GtkApplication* app,
gpointer user_data)
{
GtkWidget *window;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Window1");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
add_label( window, "Hello world" );
gtk_widget_show_all (window);
}
int
main (int argc, char **argv)
{
GtkApplication *app;
int status;
app = gtk_application_new ( "org.gtk.example", G_APPLICATION_FLAGS_NONE );
g_signal_connect( app, "activate", G_CALLBACK(activate), NULL);
status = g_application_run(G_APPLICATION(app), argc, argv);
g_object_unref (app);
return status;
}
This does not produce any label at all. If I comment out the line:
gtk_label_set_attributes(GTK_LABEL(label), attrlist);
the label shows up, but the font size is not set.
I think PANGO_SCALE is missing here.
PangoAttribute *attr = pango_attr_size_new_absolute(20 * PANGO_SCALE);
This should give you the desired result:

c GTK3 Text should scoll upward and not hide

here is my problem: I just put a gtk_text_view_new() in a gtk_scrolled_window_new(). Now when I write in the textField, at the end of the gtk_widget_set_size_request->high the text is hidden and the whole text does not scroll upwards as I want.
-> The textfield should automatically scroll upwards and show its last line.
#include <gtk/gtk.h>
int main(int argc, char **argv) {
gtk_init(&argc, &argv);
GtkWidget *window;
GtkWidget *myGrid;
GtkWidget *scollwindow;
GtkWidget *textField;
GtkTextBuffer *buffer;
GtkWidget *quitbutton;
//---------------------widgets-------------------------------
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
quitbutton = gtk_button_new_with_label("QUIT");
myGrid = gtk_grid_new ();
//---------------------textField-------------------------------
textField = gtk_text_view_new ();
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textField));
gtk_text_buffer_set_text (buffer, "Hello, this is some text, ", -1);
//---------------------insert textField in scrollwindow-------------------------------
scollwindow = gtk_scrolled_window_new (NULL,NULL);
gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scollwindow), textField);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scollwindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
//---------------------widgets size-------------------------------
gtk_widget_set_size_request (scollwindow, 200, 200);
gtk_widget_set_size_request (window, 200, 200);
//---------------------grid attache-------------------------------
gtk_grid_attach(GTK_GRID(myGrid), scollwindow, 0, 0, 1, 1);
gtk_grid_attach(GTK_GRID(myGrid), quitbutton, 0, 1, 1, 1);
//---------------------add to grid-------------------------------
gtk_container_add(GTK_CONTAINER(window), myGrid);
//---------------------signals-------------------------------
g_signal_connect(quitbutton, "clicked", G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(window, "destroy", gtk_main_quit, NULL);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
Got it, just change line " gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scollwindow), textField);" to "gtk_container_add (GTK_CONTAINER(scollwindow), textField);"

Resources