Hello
I want after inserting a new Entry into a GtkListBox, that it scrolls without any further
action by the User to this new entry; no matter, which Entry was selected before and
what the ListScrollposition was.
Problem: It works “not every time”.
Here is an example:
/*
I want after inserting a new Entry into a GtkListBox, that it scrolls without any further action by
the User to this new entry; no matter, which Entry was selected before and what the ListScrollposition was.
Problem: It works "not every time".
And if you click on the "Add new Entry"-Button several times in quick succession, it fails most if the time!
I tried "gtk_widget_show_all" for the viewport and even for the scrolledwindow as well. It doesn* solve the problem.
*/
#include <stdbool.h>
#include <gtk/gtk.h>
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
GtkWidget *gListBox;
GtkWidget *gWindow;
bool callback_buttonTest1(void);
bool callback_buttonTest2(void);
bool callback_buttonTest3(void);
GtkWidget *add_listentry(GtkListBox *ListP,char *TextP,gint idx);
bool get_line_in_visible_area(GtkListBox *lbP,gint idx);
bool get_selected_line_in_visible_area(GtkListBox *lbP);;
gint get_number_of_ListBoxEntrys(GtkListBox *ListP);
gboolean jump2Entry_idle_(gpointer data);
gboolean jump2Entry_idle__Step2(gpointer data);
// Get the selected Entry into the visible Area
bool callback_buttonTest1(void)
{
get_selected_line_in_visible_area((GtkListBox *)gListBox);
return true;
}
// Insert a new Entry to the ListBox
bool callback_buttonTest2(void)
{
add_listentry((GtkListBox *)gListBox,"new entry",-1);
return true;
}
// Get the last Entry into the visible Area
bool callback_buttonTest3(void)
{
get_line_in_visible_area((GtkListBox *)gListBox,get_number_of_ListBoxEntrys((GtkListBox *)gListBox) - 1);
return true;
}
int main ( void )
{
GtkWidget *scroll_window;
GtkWidget *grid_window;
GtkWidget *buttonTest1,*buttonTest2,*buttonTest3;
GtkWidget *viewport;
int i;
char stringTP[100];
gtk_init ( NULL, NULL );
gWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size(GTK_WINDOW(gWindow),600,200);
g_signal_connect(gWindow,"delete-event",gtk_main_quit,NULL);
g_signal_connect(gWindow,"destroy",gtk_main_quit,NULL);
grid_window = gtk_grid_new();
gtk_container_add( GTK_CONTAINER ( gWindow ), (GtkWidget*)grid_window );
buttonTest1 = gtk_button_new_with_label("Jump to selected line");
gtk_grid_attach((GtkGrid*)grid_window,buttonTest1,1,1,10,10);
g_signal_connect(buttonTest1,"clicked",(GCallback)callback_buttonTest1,NULL);
buttonTest2 = gtk_button_new_with_label("Add new Entry");
gtk_grid_attach((GtkGrid*)grid_window,buttonTest2,1,15,10,10);
g_signal_connect(buttonTest2,"clicked",(GCallback)callback_buttonTest2,NULL);
buttonTest3 = gtk_button_new_with_label("scroll to end");
gtk_grid_attach((GtkGrid*)grid_window,buttonTest3,1,29,10,10);
g_signal_connect(buttonTest3,"clicked",(GCallback)callback_buttonTest3,NULL);
scroll_window = gtk_scrolled_window_new(NULL,NULL);
gtk_widget_set_size_request(scroll_window, 500, 100);
gtk_grid_attach((GtkGrid*)grid_window,scroll_window,11,1,150,150);
viewport = gtk_viewport_new (NULL,NULL);
gtk_container_add(GTK_CONTAINER(scroll_window),viewport);
gListBox = gtk_list_box_new();
gtk_container_add(GTK_CONTAINER(viewport),gListBox);
for(i=0;i!=30;i++)
{
sprintf(stringTP,"Entry-%02d",i);
add_listentry((GtkListBox *)gListBox,stringTP,-1);
}
// add_listentry : Doesn't work here;
gtk_widget_show_all(gWindow);
gtk_main();
}
GtkWidget *add_listentry(GtkListBox *ListP,char *TextP,gint idx)
{
GtkWidget *labelTP;
labelTP = gtk_label_new(TextP);
gtk_label_set_xalign((GtkLabel*)labelTP,0); // Align left
gtk_list_box_insert(ListP,labelTP,idx);
g_idle_add_full(G_PRIORITY_LOW,jump2Entry_idle_,(GtkListBox*)ListP,NULL);
gtk_widget_show_all(gWindow); // It has to be here, since I did some experiments
return labelTP;
}
bool get_selected_line_in_visible_area(GtkListBox *lbP)
{
GtkListBoxRow *LBrow;
LBrow = gtk_list_box_get_selected_row(lbP);
if(LBrow != NULL)
{
gtk_widget_grab_focus((GtkWidget *)LBrow);
}
else
{
return false;
}
gtk_widget_activate((GtkWidget*)lbP);
return true;
}
bool get_line_in_visible_area(GtkListBox *lbP,gint idx)
{
GtkListBoxRow *LBrow;
LBrow = gtk_list_box_get_row_at_index(lbP,idx);
if(LBrow != NULL)
{
gtk_widget_grab_focus((GtkWidget *)LBrow);
}
else
{
return false;
}
gtk_widget_activate((GtkWidget*)lbP);
return true;
}
gint get_number_of_ListBoxEntrys(GtkListBox *ListP)
{
gint i;
for(i=0; true; i++)
{
if(gtk_list_box_get_row_at_index (ListP,i) == 0) break;
}
return i;
}
gboolean jump2Entry_idle_(gpointer data)
{
gint last_index;
GtkListBoxRow *LBrow;
last_index = get_number_of_ListBoxEntrys((GtkListBox *)gListBox) - 1;
LBrow = gtk_list_box_get_row_at_index ((GtkListBox *)gListBox,last_index);
gtk_list_box_select_row((GtkListBox *)gListBox,LBrow);
g_idle_add_full(G_PRIORITY_LOW,jump2Entry_idle__Step2,(GtkListBox*)gListBox,NULL);
return G_SOURCE_REMOVE;
}
gboolean jump2Entry_idle__Step2(gpointer data)
{
get_selected_line_in_visible_area((GtkListBox *)gListBox); // geht nicht ! Ich muss es per Knopf-1 tun !
return G_SOURCE_REMOVE;
}