Re: GtkScrolledWindow containing GtkTextView containing a TextBuffer can't keep at bottom of Buffer

2013-06-10 Thread Thomas A. Moulton

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

2013-06-10 Thread Colomban Wendling
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

2013-06-10 Thread Thomas A. Moulton



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

2013-06-09 Thread Thomas A. Moulton

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

2013-06-09 Thread Thomas A. Moulton
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