Re: GtkScrolledWindow containing GtkTextView containing a TextBuffer can't keep at bottom of Buffer
That did it! Thanks! On 06/10/2013 08:44 AM, Colomban Wendling wrote: Hi, Le 10/06/2013 12:26, Thomas A. Moulton a écrit : On 06/09/2013 05:21 PM, Thomas A. Moulton wrote: Ok here is a single file example of my code... it works the same way it does in my larger project Any suggestions would be GREATLY appreciated! tom What happens is when you enter enough lines of text to fill the window the scrolled window does not scroll up when the "eob" mark is not visible (eob=last line of text buffer) The problem you have is that you insert the TextView in the ScrolledWindow through a Viewport. This results in a widget hierarchy like this: ... + GtkScrolledWindow + GtkViewport + GtkTextView This means that the TextView doesn't get to control the ScrolledWinodw, its the Viewport that does. So when you ask scroll_to_mark() the ScrolledWindow won't get the request, and so won't scroll. What you need it NOT to add a Viewport, so you get a hierarchy like this: ... + GtkScrolledWindow + GtkTextView Like this, the thing that gets scrolled is the TextView, not a kind of proxy. GtkViewport is only useful if you want to add a non-scrollable widget (e.g. boxes, grids, etc) to a scrolled window: it acts as a proxy that implements the scrolling. On the other hand, if the widget you want to add IS scrollable (implement the GtkScrollable interface), it must NOT be in a Viewport: if it does, it will expect scrolling requests and alike, but never get them since its the Viewport that gets them. In practice, just replace gtk_scrolled_window_add_with_viewport(scroll, GTK_WIDGET(text)); with gtk_container_add(GTK_CONTAINER(scroll), GTK_WIDGET(text)); and it will work as you expect. Not that gtk_scrolled_window_add_with_viewport() is even deprecated nowadays, simply adding a child to a ScrolledWindow is enough (it will automatically add a Viewport for you if required -- which is NOT the case for GtkTextViews). Regards, Colomban PS: you do: char line[512]; const gchar *cmd; cmd = gtk_entry_get_text(entry); strcpy(line, cmd); gtk_entry_set_text(entry, ""); ... gtk_text_buffer_insert_with_tags(buf, ..., line, -1, ...); Why do you copy the line in a static buffer (that might be too small, and cause a crash since strcpy() doesn't have a max size parameter)? You could just put the line into the buffer: const gchar *line; line = gtk_entry_get_text(entry); ... gtk_text_buffer_insert_with_tags(buf, ..., line, -1, ...); gtk_entry_set_text(entry, ""); ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: GtkScrolledWindow containing GtkTextView containing a TextBuffer can't keep at bottom of Buffer
Hi, Le 10/06/2013 12:26, Thomas A. Moulton a écrit : > On 06/09/2013 05:21 PM, Thomas A. Moulton wrote: >> Ok here is a single file example of my code... it works the same way >> it does in my larger project >> >> Any suggestions would be GREATLY appreciated! >> >> tom >> > What happens is when you enter enough lines of text to fill the window > the scrolled window does not scroll up > when the "eob" mark is not visible (eob=last line of text buffer) The problem you have is that you insert the TextView in the ScrolledWindow through a Viewport. This results in a widget hierarchy like this: ... + GtkScrolledWindow + GtkViewport + GtkTextView This means that the TextView doesn't get to control the ScrolledWinodw, its the Viewport that does. So when you ask scroll_to_mark() the ScrolledWindow won't get the request, and so won't scroll. What you need it NOT to add a Viewport, so you get a hierarchy like this: ... + GtkScrolledWindow + GtkTextView Like this, the thing that gets scrolled is the TextView, not a kind of proxy. GtkViewport is only useful if you want to add a non-scrollable widget (e.g. boxes, grids, etc) to a scrolled window: it acts as a proxy that implements the scrolling. On the other hand, if the widget you want to add IS scrollable (implement the GtkScrollable interface), it must NOT be in a Viewport: if it does, it will expect scrolling requests and alike, but never get them since its the Viewport that gets them. In practice, just replace gtk_scrolled_window_add_with_viewport(scroll, GTK_WIDGET(text)); with gtk_container_add(GTK_CONTAINER(scroll), GTK_WIDGET(text)); and it will work as you expect. Not that gtk_scrolled_window_add_with_viewport() is even deprecated nowadays, simply adding a child to a ScrolledWindow is enough (it will automatically add a Viewport for you if required -- which is NOT the case for GtkTextViews). Regards, Colomban PS: you do: char line[512]; const gchar *cmd; cmd = gtk_entry_get_text(entry); strcpy(line, cmd); gtk_entry_set_text(entry, ""); ... gtk_text_buffer_insert_with_tags(buf, ..., line, -1, ...); Why do you copy the line in a static buffer (that might be too small, and cause a crash since strcpy() doesn't have a max size parameter)? You could just put the line into the buffer: const gchar *line; line = gtk_entry_get_text(entry); ... gtk_text_buffer_insert_with_tags(buf, ..., line, -1, ...); gtk_entry_set_text(entry, ""); ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: GtkScrolledWindow containing GtkTextView containing a TextBuffer can't keep at bottom of Buffer
On 06/09/2013 05:21 PM, Thomas A. Moulton wrote: Ok here is a single file example of my code... it works the same way it does in my larger project Any suggestions would be GREATLY appreciated! tom What happens is when you enter enough lines of text to fill the window the scrolled window does not scroll up when the "eob" mark is not visible (eob=last line of text buffer) tom ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: GtkScrolledWindow containing GtkTextView containing a TextBuffer can't keep at bottom of Buffer
On 06/09/2013 09:21 AM, Thomas A. Moulton wrote: I see a lot of questions about this and I have not found an answer that works for me. I create the chat window like this: The printf above at times tells me the objects are not valid, but the addresses have not changed. Also the TextBuffer has a parent of 0! I even allocated and set the buffer manually. If there it no anything obvious wrong here I will strip it down to a simpler test case Tom Ok here is a single file example of my code... it works the same way it does in my larger project Any suggestions would be GREATLY appreciated! tom /* Name: Scrolled.c Author : Tom Moulton Version : Copyright : (c) 2013 Thoomas A. Moulton, Public Domain Description : Hello World in GTK+ */ #include GtkNotebook *nb; void Enter_Chat(GtkEntry *entry, GtkTextBuffer *buf) { char line[512]; const gchar *cmd; GtkTextIter endit; cmd = gtk_entry_get_text(entry); strcpy(line, cmd); gtk_entry_set_text(entry, ""); gtk_text_buffer_get_end_iter(buf, &endit); gtk_text_buffer_insert_with_tags(buf, &endit, line, -1, NULL, NULL); } void Chat_scroll_to_end(GtkTextBuffer *buf, GtkTextView *text) { GtkTextMark *mark; mark = gtk_text_buffer_get_mark(buf, "eob"); gtk_text_view_scroll_mark_onscreen(text, mark); } void ChatNew(void) { GtkBox *chat; GtkTextBuffer *buf; GtkTextView *text; GtkEntry *entry; GtkScrolledWindow *scroll; GtkTextIter endit; GtkLabel *label; text = (GtkTextView *)gtk_text_view_new(); gtk_text_view_set_editable(text, FALSE); gtk_text_view_set_wrap_mode(text, GTK_WRAP_WORD_CHAR); gtk_text_view_set_cursor_visible(text, FALSE); buf = gtk_text_buffer_new(NULL); gtk_text_view_set_buffer(text, buf); scroll = (GtkScrolledWindow *)gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(scroll, GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); gtk_scrolled_window_add_with_viewport(scroll, GTK_WIDGET(text)); entry = (GtkEntry *)gtk_entry_new(); gtk_widget_set_size_request(GTK_WIDGET(entry), -1, 30); chat = GTK_BOX(gtk_box_new(GTK_ORIENTATION_VERTICAL, 0)); gtk_box_pack_start(chat, GTK_WIDGET(scroll), TRUE, TRUE, 0); gtk_box_pack_end(chat, (GtkWidget *)entry, FALSE, TRUE, 0); g_signal_connect(G_OBJECT(entry), "activate", G_CALLBACK(Enter_Chat), (gpointer)buf); gtk_text_buffer_get_end_iter(buf, &endit); gtk_text_buffer_create_mark(buf, "eob", &endit, FALSE); g_signal_connect(G_OBJECT(buf), "changed", G_CALLBACK(Chat_scroll_to_end), (gpointer)text); label = (GtkLabel *)gtk_label_new("Test Scroll"); gtk_notebook_append_page(nb, GTK_WIDGET(chat), GTK_WIDGET(label)); } int main (int argc, char *argv[]) { GtkWidget *window; gtk_init (&argc, &argv); /* create the main, top level, window */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); /* give it the title */ gtk_window_set_title (GTK_WINDOW (window), "Hello World"); /* Connect the destroy signal of the window to gtk_main_quit * When the window is about to be destroyed we get a notification and * stop the main GTK+ loop */ g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL); nb = (GtkNotebook *)gtk_notebook_new(); ChatNew(); /* and insert it into the main window */ gtk_container_add (GTK_CONTAINER (window), GTK_WIDGET(nb)); /* make sure that everything, window and label, are visible */ gtk_widget_show_all (window); /* start the main loop, and let it rest there until the application is closed */ gtk_main (); return 0; } ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
GtkScrolledWindow containing GtkTextView containing a TextBuffer can't keep at bottom of Buffer
I see a lot of questions about this and I have not found an answer that works for me. I create the chat window like this: CHAT *ChatNew(char *player) { CHAT *chatlog; GtkBox *chat; GtkTextBuffer *buf; GtkTextView *text; GtkEntry *entry; GtkScrolledWindow *scroll; GtkTextIter endit; text = (GtkTextView *)gtk_text_view_new(); gtk_text_view_set_editable(text, FALSE); gtk_text_view_set_wrap_mode(text, GTK_WRAP_WORD_CHAR); gtk_text_view_set_cursor_visible(text, FALSE); buf = gtk_text_buffer_new(NULL); printf("New TextBuffer %x\r\n", (int)buf); gtk_text_view_set_buffer(text, buf); scroll = (GtkScrolledWindow *)gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(scroll, GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); gtk_scrolled_window_add_with_viewport(scroll, GTK_WIDGET(text)); entry = (GtkEntry *)gtk_entry_new(); gtk_widget_set_size_request(GTK_WIDGET(entry), -1, 30); chat = GTK_BOX(gtk_box_new(GTK_ORIENTATION_VERTICAL, 0)); gtk_box_pack_start(chat, GTK_WIDGET(scroll), TRUE, TRUE, 0); gtk_box_pack_end(chat, (GtkWidget *)entry, FALSE, TRUE, 0); chatlog = g_malloc0(sizeof(CHAT)); if (chatlog == NULL) return NULL; strcpy(chatlog->player, player); chatlog->scroll = scroll; chatlog->box = chat; chatlog->text = text; chatlog->entry = entry; g_signal_connect(G_OBJECT(entry), "activate", G_CALLBACK(Enter_Chat), (gpointer)chatlog); //buf = gtk_text_view_get_buffer(chatlog->text); gtk_text_buffer_get_end_iter(buf, &endit); gtk_text_buffer_create_mark(buf, "eob", &endit, FALSE); g_signal_connect(G_OBJECT(buf), "changed", G_CALLBACK(Chat_scroll_to_end), (gpointer)text); //g_signal_connect(G_OBJECT(buf), "key_press_event", G_CALLBACK(Chat_keys), (gpointer)chatlog); return chatlog; } The caller adds it to a GtkNotebook if (item == NULL) { chatlog = ChatNew(name); label = (GtkLabel *)gtk_label_new(name); g_queue_insert_sorted(gfibs.chats, chatlog, chatNB_sort_chat, 0); n = gtk_notebook_insert_page(nb, (GtkWidget *)chatlog->box, (GtkWidget *)label, 2); buf = gtk_text_view_get_buffer(chatlog->text); textv = chatlog->text; gtk_widget_show((GtkWidget *)chatlog->scroll); gtk_widget_show((GtkWidget *)chatlog->box); gtk_widget_show((GtkWidget *)chatlog->text); gtk_widget_show((GtkWidget *)chatlog->entry); gtk_widget_show((GtkWidget *)label); printf("chat inserted at %d\r\n", n); } else { chatlog = (CHAT *)item->data; buf = NULL; if (chatlog != NULL && chatlog->text != NULL) { buf = gtk_text_view_get_buffer(chatlog->text); textv = chatlog->text; n = gtk_notebook_page_num(nb, GTK_WIDGET(chatlog->box)); } } if (buf != NULL) { GtkTextIter endit; gtk_text_buffer_get_end_iter(buf, &endit); gtk_text_buffer_insert_with_tags(buf, &endit, line, -1, NULL, NULL); return TRUE; } and then to make sure it is visible void Chat_scroll_to_end(GtkTextBuffer *buf, GtkTextView *text) { GtkTextMark *mark; printf("Chat_scroll_to_end arg %x text %x parent %x\r\n", (int)buf, (int)text, (int)gtk_widget_get_parent(GTK_WIDGET(buf)));fflush(stdout); mark = gtk_text_buffer_get_mark(buf, "eob"); gtk_text_view_scroll_mark_onscreen(text, mark); } The printf above at times tells me the objects are not valid, but the addresses have not changed. Also the TextBuffer has a parent of 0! I even allocated and set the buffer manually. If there it no anything obvious wrong here I will strip it down to a simpler test case Tom ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list