[gnome-mud] New input box code
- From: Mart Raudsepp <leio dustbite net>
- To: gnome-mud-list gnome org
- Subject: [gnome-mud] New input box code
- Date: Tue, 25 Apr 2006 23:23:43 +0300
Hello,
The attached patch re-implements input box as always a GtkTextView that
is adjusting its height as necessary. Return/Enter sends text,
Return/Enter with any modifier keys goes to next line in the input box,
adjusting height as necessary.
A largest height of 5 is used, after which a scrollbar is used - that
value can easily be changed by adjusting the value passed to
mud_window_textview_ensure_height().
The height is always kept only as high as necessary.
The code used to check line_yrange in ensure_height too, in addition to
on creation, but I opted for saving the line height and re-use it,
because there seem to be bugs in GtkTextView that cause get_line_yrange
to report a bogus value (usually an old visible_line_count * real height
of a line) on line reduction to 1; e.g if you have two visible lines,
and hitting backspace deletes the linebreak, get_yrange will report 34,
not 17 as it should on my system. I think the same can be seen with
after sending the thing off the mud (and keep_text is off?).
This means that if the input boxes font height changes after initial
creation, it will get bad heights from that on. Need to either
workaround the get_yrange problem somehow, or respond to height changing
signals and cache it again, or do something more clean.
In wxMUD I always query the font height, for example. But that's mainly
just because I don't have clean access to gtk_text_view_get_line_yrange
at all there.
The horizontal scrollbar policy is made AUTOMATIC instead of NONE
because of gnome bugzilla bug #308126 - it will appear only if we hit
that bug. This ensures that the input box won't make the toplevel grow
it's width without a limit, which would be just plain wrong to do.
The discoverability of modifier+enter is a little problem, imho, too.
But all the cool kids are doing it (gaim, gossip?)
You might want to set the wrap mode in glade file instead of code. I did
it in code because:
a) I don't trust my glade GUI to not screw up the glade file to no
recognition (the removal of text_entry and co was done by hand in text
editor)
b) I'm not sure if it should be in the glade file, instead of code - it
is a programmatical thing to ensure such word-wrap, not an UI choice.
The size_request is set on the vscrollbar of text_view_scroll because
otherwise it's higher than a line height, and we don't like that.
Worth noting is, that with it always being a GtkTextView, implementing
password hiding will be quite a feat, if possible at all without loosing
sanity.
Hopefully the patch is useful and commitable as is, or after slight
changes/improvements.
I need to work on other things for a couple of days myself, so posting
the current (not-too-bad) state of the patch here for consideration.
--
With regards,
Mart Raudsepp
Project manager of wxMUD - http://wxmud.sourceforge.net/
Developer of wxWidgets - http://www.wxwidgets.org/
GTK+ port maintainer of OMGUI - http://www.omgui.org/
Index: src/mud-window.c
===================================================================
RCS file: /cvs/gnome/gnome-mud/src/mud-window.c,v
retrieving revision 1.19
diff -u -B -r1.19 mud-window.c
--- src/mud-window.c 25 Apr 2006 09:12:44 -0000 1.19
+++ src/mud-window.c 25 Apr 2006 19:59:27 -0000
@@ -42,7 +42,6 @@
GtkWidget *window;
GtkWidget *notebook;
- GtkWidget *textentry;
GtkWidget *textview;
GtkWidget *textviewscroll;
GtkWidget *mainvpane;
@@ -64,7 +63,7 @@
gchar *port;
gint nr_of_tabs;
- gint toggleState;
+ gint textview_line_height;
MudTray *tray;
};
@@ -190,34 +189,72 @@
}
-static gboolean
-mud_window_textentry_keypress(GtkWidget *widget, GdkEventKey *event, MudWindow *window)
+static gint
+mud_window_textview_get_display_line_count(GtkTextView *textview)
{
+ gint result = 1;
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer(textview);
+ GtkTextIter iter;
- return FALSE;
+ gtk_text_buffer_get_start_iter(buffer, &iter);
+ while (gtk_text_view_forward_display_line(textview, &iter))
+ ++result;
+
+ if (gtk_text_buffer_get_line_count(buffer) != 1)
+ {
+ GtkTextIter iter2;
+ gtk_text_buffer_get_end_iter(buffer, &iter2);
+ if (gtk_text_iter_get_chars_in_line(&iter) == 0)
+ ++result;
+ }
+
+ return result;
+}
+
+static void
+mud_window_textview_ensure_height(MudWindow *window, guint max_lines)
+{
+ gint lines = mud_window_textview_get_display_line_count(GTK_TEXT_VIEW(window->priv->textview));
+ gtk_widget_set_size_request(window->priv->textview, -1,
+ window->priv->textview_line_height * MIN(lines, max_lines));
+ gtk_widget_queue_resize(gtk_widget_get_parent(window->priv->textview));
+}
+
+static void
+mud_window_textview_buffer_changed(GtkTextBuffer *buffer, MudWindow *window)
+{
+ mud_window_textview_ensure_height(window, 5);
}
static gboolean
mud_window_textview_keypress(GtkWidget *widget, GdkEventKey *event, MudWindow *window)
{
gchar *text;
- GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(window->priv->textview));
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(window->priv->textview));
GtkTextIter start, end;
- if(event->keyval == GDK_KP_Enter)
+ if ((event->keyval == GDK_Return || event->keyval == GDK_KP_Enter) &&
+ (event->state & gtk_accelerator_get_default_mod_mask()) == 0)
{
- if(window->priv->current_view)
- {
- gtk_text_buffer_get_bounds(buffer, &start, &end);
-
- text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
+ gtk_text_buffer_get_bounds(buffer, &start, &end);
+
+ text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
+
+ if (g_str_equal(text, ""))
+ text = g_strdup(" ");
+
+ if (window->priv->current_view)
mud_connection_view_send(MUD_CONNECTION_VIEW(window->priv->current_view), text);
-
+
+ if (gconf_client_get_bool(window->priv->gconf_client,
+ "/apps/gnome-mud/functionality/keeptext", NULL) == FALSE)
+ gtk_text_buffer_delete(buffer, &start, &end);
+ else
gtk_text_buffer_select_range(buffer, &start, &end);
- return TRUE;
-
- }
+ free(text);
+
+ return TRUE;
}
return FALSE;
@@ -257,22 +294,6 @@
}
static void
-mud_window_textentry_activate(GtkWidget *widget, MudWindow *window)
-{
- gchar *tmp;
-
- tmp = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
- if (g_str_equal(tmp, ""))
- tmp = g_strdup(" ");
- if (window->priv->current_view)
- mud_connection_view_send(MUD_CONNECTION_VIEW(window->priv->current_view), tmp);
- if (gconf_client_get_bool(window->priv->gconf_client,
- "/apps/gnome-mud/functionality/keeptext", NULL) == FALSE)
- gtk_entry_set_text(GTK_ENTRY(widget), g_strdup(""));
- free (tmp);
-}
-
-static void
mud_window_preferences_cb(GtkWidget *widget, MudWindow *window)
{
mud_preferences_window_new("Default");
@@ -316,25 +337,6 @@
mud_window_mconnect_new(window, mywig, window->priv->tray);
}
-static void
-mud_window_inputtoggle_cb(GtkWidget *widget, MudWindow *window)
-{
-
- if(window->priv->toggleState)
- {
- gtk_widget_hide(window->priv->textview);
- gtk_widget_hide(window->priv->textviewscroll);
- gtk_widget_show(window->priv->textentry);
- }
- else
- {
- gtk_widget_hide(window->priv->textentry);
- gtk_widget_show(window->priv->textview);
- gtk_widget_show(window->priv->textviewscroll);
- }
- window->priv->toggleState = !window->priv->toggleState;
-}
-
gboolean
mud_window_size_request(GtkWidget *widget, GdkEventConfigure *event, gpointer user_data)
{
@@ -650,10 +652,9 @@
g_signal_connect(window->priv->bufferdump, "activate", G_CALLBACK(mud_window_buffer_cb), window);
/* preferences window button */
-
window->priv->mi_profiles = glade_xml_get_widget(glade, "mi_profiles_menu");
g_signal_connect(glade_xml_get_widget(glade, "menu_preferences"), "activate", G_CALLBACK(mud_window_preferences_cb), window);
-
+
g_signal_connect(glade_xml_get_widget(glade, "menu_about"), "activate", G_CALLBACK(mud_window_about_cb), window);
/* other objects */
@@ -663,22 +664,27 @@
window->priv->textviewscroll = glade_xml_get_widget(glade, "text_view_scroll");
window->priv->textview = glade_xml_get_widget(glade, "text_view");
+ gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(window->priv->textview), GTK_WRAP_WORD_CHAR);
+
g_signal_connect(window->priv->textview, "key_press_event", G_CALLBACK(mud_window_textview_keypress), window);
-
- gtk_widget_hide(window->priv->textviewscroll);
- gtk_widget_hide(window->priv->textview);
-
- window->priv->toggleState = 0;
+ g_signal_connect(gtk_text_view_get_buffer(GTK_TEXT_VIEW(window->priv->textview)), "changed",
+ G_CALLBACK(mud_window_textview_buffer_changed), window);
- window->priv->textentry = glade_xml_get_widget(glade, "text_entry");
- g_signal_connect(window->priv->textentry, "key_press_event", G_CALLBACK(mud_window_textentry_keypress), window);
- g_signal_connect(window->priv->textentry, "activate", G_CALLBACK(mud_window_textentry_activate), window);
+ {
+ /* Set the initial height of the input box equal to the height of one line */
+ GtkTextIter iter;
+ gint y;
+ gtk_text_buffer_get_start_iter(gtk_text_view_get_buffer(GTK_TEXT_VIEW(window->priv->textview)), &iter);
+ gtk_text_view_get_line_yrange(GTK_TEXT_VIEW(window->priv->textview), &iter, &y, &window->priv->textview_line_height);
- window->priv->mainvpane = glade_xml_get_widget(glade, "main_vpane");
-
- window->priv->image = glade_xml_get_widget(glade, "image");
+ gtk_widget_set_size_request(window->priv->textview, -1, window->priv->textview_line_height*1);
+ gtk_widget_set_size_request(GTK_SCROLLED_WINDOW(window->priv->textviewscroll)->vscrollbar, -1, 1);
- g_signal_connect(glade_xml_get_widget(glade, "toggle_input"), "clicked", G_CALLBACK(mud_window_inputtoggle_cb), window);
+ if (GTK_WIDGET_VISIBLE(window->priv->textviewscroll))
+ gtk_widget_queue_resize(window->priv->textviewscroll);
+ }
+
+ window->priv->image = glade_xml_get_widget(glade, "image");
g_signal_connect(glade_xml_get_widget(glade, "plugin_list"), "activate", G_CALLBACK(do_plugin_information), NULL);
Index: ui/main.glade
===================================================================
RCS file: /cvs/gnome/gnome-mud/ui/main.glade,v
retrieving revision 1.17
diff -u -B -r1.17 main.glade
--- ui/main.glade 25 Apr 2006 09:12:44 -0000 1.17
+++ ui/main.glade 25 Apr 2006 19:59:27 -0000
@@ -537,30 +537,10 @@
<property name="spacing">0</property>
<child>
- <widget class="GtkEntry" id="text_entry">
- <property name="height_request">25</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="editable">True</property>
- <property name="visibility">True</property>
- <property name="max_length">0</property>
- <property name="text" translatable="yes"></property>
- <property name="has_frame">True</property>
- <property name="invisible_char">*</property>
- <property name="activates_default">False</property>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
-
- <child>
<widget class="GtkScrolledWindow" id="text_view_scroll">
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="shadow_type">GTK_SHADOW_IN</property>
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
@@ -598,31 +578,6 @@
</packing>
</child>
- <child>
- <widget class="GtkButton" id="toggle_input">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="relief">GTK_RELIEF_NORMAL</property>
- <property name="focus_on_click">True</property>
-
- <child>
- <widget class="GtkImage" id="image65">
- <property name="visible">True</property>
- <property name="stock">gtk-justify-fill</property>
- <property name="icon_size">1</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
</widget>
<packing>
<property name="padding">0</property>
[
Date Prev][Date Next] [
Thread Prev][Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]