Revision: 4148 http://geany.svn.sourceforge.net/geany/?rev=4148&view=rev Author: ntrel Date: 2009-09-03 12:04:27 +0000 (Thu, 03 Sep 2009)
Log Message: ----------- Enable type-ahead find for sidebar symbols and documents tabs (patch by Thomas Martitz, thanks).
Modified Paths: -------------- trunk/ChangeLog trunk/THANKS trunk/src/document.c trunk/src/document.h trunk/src/treeviews.c
Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2009-09-03 04:32:05 UTC (rev 4147) +++ trunk/ChangeLog 2009-09-03 12:04:27 UTC (rev 4148) @@ -1,3 +1,10 @@ +2009-09-03 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com> + + * src/treeviews.c, src/document.c, src/document.h, THANKS: + Enable type-ahead find for sidebar symbols and documents tabs + (patch by Thomas Martitz, thanks). + + 2009-09-03 Lex Trotman <elextr(at)gmail(dot)com>
* src/build.c, src/filetypes.h, src/filetypes.c
Modified: trunk/THANKS =================================================================== --- trunk/THANKS 2009-09-03 04:32:05 UTC (rev 4147) +++ trunk/THANKS 2009-09-03 12:04:27 UTC (rev 4148) @@ -59,7 +59,7 @@ Guillaume de Rorthais <ioguix(at)free(dot)fr> - Auto-close brackets/braces/quotes patch Tyler Mulligan <tyler(at)doknowevil(dot)net> - Close All toolbar icon Philipp Gildein <philipp(at)gildein(dot)com> - Ada filetype patch -Thomas Martitz <thomas47(at)arcor(dot)de> - Multiple %cursor% wildcards in Snippets patch +Thomas Martitz <thomas47(at)arcor(dot)de> - Multiple %cursor% in Snippets, typeahead sidebar patch David Gleich <dgleich(at)stanford(dot)edu> - Send Selection to Terminal patch Chris Macksey <cmacksey(at)users(dot)sourceforge(dot)net> - ActionScript filetype patch Simon Treny <simon(dot)treny(at)free(dot)fr> - Documents sidebar stock icons patch
Modified: trunk/src/document.c =================================================================== --- trunk/src/document.c 2009-09-03 04:32:05 UTC (rev 4147) +++ trunk/src/document.c 2009-09-03 12:04:27 UTC (rev 4148) @@ -513,19 +513,40 @@ }
+void document_try_focus(GeanyDocument *doc) +{ + /* doc might not be valid e.g. if user closed a tab whilst Geany is opening files */ + if (DOC_VALID(doc)) + { + GtkWidget *sci = GTK_WIDGET(doc->editor->sci); + GtkWidget *focusw = gtk_window_get_focus(GTK_WINDOW(main_widgets.window)); + + if (focusw == doc->priv->tag_tree) + gtk_widget_grab_focus(sci); + } +} + + +static gboolean on_idle_focus(gpointer doc) +{ + document_try_focus(doc); + return FALSE; +} + + /* Creates a new document and editor, adding a tab in the notebook. * @return The created document */ static GeanyDocument *document_create(const gchar *utf8_filename) { - GeanyDocument *this; + GeanyDocument *doc; gint new_idx; gint cur_pages = gtk_notebook_get_n_pages(GTK_NOTEBOOK(main_widgets.notebook));
if (cur_pages == 1) { - GeanyDocument *doc = document_get_current(); + GeanyDocument *cur = document_get_current(); /* remove the empty document and open a new one */ - if (doc != NULL && doc->file_name == NULL && ! doc->changed) + if (cur != NULL && cur->file_name == NULL && ! cur->changed) document_remove_page(0); }
@@ -537,36 +558,35 @@ new_idx = documents_array->len; g_ptr_array_add(documents_array, new_doc); } - this = documents[new_idx]; - init_doc_struct(this); /* initialize default document settings */ - this->index = new_idx; + doc = documents[new_idx]; + init_doc_struct(doc); /* initialize default document settings */ + doc->index = new_idx;
- this->file_name = g_strdup(utf8_filename); + doc->file_name = g_strdup(utf8_filename);
- this->editor = editor_create(this); + doc->editor = editor_create(doc);
- editor_apply_update_prefs(this->editor); + editor_apply_update_prefs(doc->editor);
- treeviews_openfiles_add(this); /* sets this->iter */ + treeviews_openfiles_add(doc); /* sets doc->iter */
- notebook_new_tab(this); + notebook_new_tab(doc);
/* select document in sidebar */ { GtkTreeSelection *sel;
sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv.tree_openfiles)); - gtk_tree_selection_select_iter(sel, &this->priv->iter); + gtk_tree_selection_select_iter(sel, &doc->priv->iter); }
ui_document_buttons_update();
- gtk_widget_grab_focus(GTK_WIDGET(this->editor->sci)); - - this->is_valid = TRUE; /* do this last to prevent UI updating with NULL items. */ - return this; + doc->is_valid = TRUE; /* do this last to prevent UI updating with NULL items. */ + return doc; }
+ /** * Close the given document. * @@ -729,7 +749,9 @@ ui_document_show_hide(doc); /* update the document menu */
sci_set_line_numbers(doc->editor->sci, editor_prefs.show_linenumber_margin, 0); - sci_goto_pos(doc->editor->sci, 0, TRUE); + /* bring it in front, jump to the start and grab the focus */ + editor_goto_pos(doc->editor, 0, FALSE); + document_try_focus(doc);
#if USE_GIO_FILEMON monitor_file_setup(doc); @@ -996,8 +1018,10 @@
/* Sets the cursor position on opening a file. First it sets the line when cl_options.goto_line * is set, otherwise it sets the line when pos is greater than zero and finally it sets the column - * if cl_options.goto_column is set. */ -static void set_cursor_position(GeanyEditor *editor, gint pos) + * if cl_options.goto_column is set. + * + * returns the new position which may have changed */ +static int set_cursor_position(GeanyEditor *editor, gint pos) { if (cl_options.goto_line >= 0) { /* goto line which was specified on command line and then undefine the line */ @@ -1013,11 +1037,14 @@
if (cl_options.goto_column >= 0) { /* goto column which was specified on command line and then undefine the column */ - gint cur_pos = sci_get_current_position(editor->sci); - sci_set_current_position(editor->sci, cur_pos + cl_options.goto_column, FALSE); + + gint new_pos = sci_get_current_position(editor->sci) + cl_options.goto_column; + sci_set_current_position(editor->sci, new_pos, FALSE); editor->scroll_percent = 0.5F; cl_options.goto_column = -1; + return new_pos; } + return sci_get_current_position(editor->sci); }
@@ -1204,14 +1231,10 @@ if (doc != NULL) { ui_add_recent_file(utf8_filename); /* either add or reorder recent item */ - gtk_notebook_set_current_page(GTK_NOTEBOOK(main_widgets.notebook), - gtk_notebook_page_num(GTK_NOTEBOOK(main_widgets.notebook), - (GtkWidget*) doc->editor->sci)); g_free(utf8_filename); g_free(locale_filename); document_check_disk_status(doc, TRUE); /* force a file changed check */ - set_cursor_position(doc->editor, pos); - return doc; + goto end; } } display_filename = utils_str_middle_truncate(utf8_filename, 100); @@ -1269,7 +1292,7 @@ sci_set_line_numbers(doc->editor->sci, editor_prefs.show_linenumber_margin, 0);
/* set the cursor position according to pos, cl_options.goto_line and cl_options.goto_column */ - set_cursor_position(doc->editor, pos); + pos = set_cursor_position(doc->editor, pos);
if (! reload) { @@ -1323,6 +1346,13 @@ * based on a configurable interval */ /*g_timeout_add(10000, auto_update_tag_list, doc);*/
+end: + /* now bring the file in front */ + editor_goto_pos(doc->editor, pos, FALSE); + + /* finally, let the editor widget grab the focus so you can start coding + * right away */ + g_idle_add(on_idle_focus, doc); return doc; }
Modified: trunk/src/document.h =================================================================== --- trunk/src/document.h 2009-09-03 04:32:05 UTC (rev 4147) +++ trunk/src/document.h 2009-09-03 12:04:27 UTC (rev 4148) @@ -184,6 +184,8 @@
gboolean document_remove_page(guint page_num);
+void document_try_focus(GeanyDocument *doc); + gboolean document_close(GeanyDocument *doc);
gboolean document_account_for_unsaved(void);
Modified: trunk/src/treeviews.c =================================================================== --- trunk/src/treeviews.c 2009-09-03 04:32:05 UTC (rev 4147) +++ trunk/src/treeviews.c 2009-09-03 12:04:27 UTC (rev 4148) @@ -42,10 +42,13 @@ #include "project.h" #include "stash.h" #include "keyfile.h" +#include "sciwrappers.h"
#include <gdk/gdkkeysyms.h>
SidebarTreeviews tv = {NULL, NULL, NULL}; +/* while typeahead searching, editor should not get focus */ +static gboolean may_steal_focus = FALSE;
static struct { @@ -85,17 +88,16 @@ static GtkWidget *tag_window; /* scrolled window that holds the symbol list GtkTreeView */
/* callback prototypes */ -static void on_openfiles_tree_selection_changed(GtkTreeSelection *selection, gpointer data); +static gboolean on_openfiles_tree_selection_changed(GtkTreeSelection *selection); static void on_openfiles_document_action(GtkMenuItem *menuitem, gpointer user_data); static gboolean on_taglist_tree_selection_changed(GtkTreeSelection *selection); -static gboolean on_symbols_button_press_event(GtkWidget *widget, GdkEventButton *event, +static gboolean treeviews_button_press_cb(GtkWidget *widget, GdkEventButton *event, gpointer user_data); -static gboolean on_documents_button_release_event(GtkWidget *widget, GdkEventButton *event, +static gboolean treeviews_key_press_cb(GtkWidget *widget, GdkEventKey *event, gpointer user_data); -static gboolean on_treeviews_key_press_event(GtkWidget *widget, GdkEventKey *event, - gpointer user_data); static void on_list_document_activate(GtkCheckMenuItem *item, gpointer user_data); static void on_list_symbol_activate(GtkCheckMenuItem *item, gpointer user_data); +static void documents_menu_update(GtkTreeSelection *selection);
/* the prepare_* functions are document-related, but I think they fit better here than in document.c */ @@ -107,9 +109,9 @@
text_renderer = gtk_cell_renderer_text_new(); icon_renderer = gtk_cell_renderer_pixbuf_new(); - column = gtk_tree_view_column_new(); + column = gtk_tree_view_column_new();
- gtk_tree_view_column_pack_start(column, icon_renderer, FALSE); + gtk_tree_view_column_pack_start(column, icon_renderer, FALSE); gtk_tree_view_column_set_attributes(column, icon_renderer, "pixbuf", SYMBOLS_COLUMN_ICON, NULL); g_object_set(icon_renderer, "xalign", 0.0, NULL);
@@ -127,12 +129,10 @@ g_object_unref(store);
g_signal_connect(tree, "button-press-event", - G_CALLBACK(on_symbols_button_press_event), NULL); + G_CALLBACK(treeviews_button_press_cb), NULL); g_signal_connect(tree, "key-press-event", - G_CALLBACK(on_treeviews_key_press_event), GINT_TO_POINTER(TREEVIEW_SYMBOL)); + G_CALLBACK(treeviews_key_press_cb), NULL);
- gtk_tree_view_set_enable_search(GTK_TREE_VIEW(tree), FALSE); - if (gtk_check_version(2, 12, 0) == NULL) { g_object_set(tree, "show-expanders", interface_prefs.show_symbol_list_expanders, NULL); @@ -242,13 +242,12 @@ store_openfiles = gtk_tree_store_new(5, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER, GDK_TYPE_COLOR, G_TYPE_STRING); gtk_tree_view_set_model(GTK_TREE_VIEW(tv.tree_openfiles), GTK_TREE_MODEL(store_openfiles)); - g_object_unref(store_openfiles);
/* set policy settings for the scolledwindow around the treeview again, because glade * doesn't keep the settings */ gtk_scrolled_window_set_policy( - GTK_SCROLLED_WINDOW(ui_lookup_widget(main_widgets.window, "scrolledwindow7")), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + GTK_SCROLLED_WINDOW(ui_lookup_widget(main_widgets.window, "scrolledwindow7")), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
icon_renderer = gtk_cell_renderer_pixbuf_new(); text_renderer = gtk_cell_renderer_text_new(); @@ -262,7 +261,8 @@ gtk_tree_view_append_column(GTK_TREE_VIEW(tv.tree_openfiles), column); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tv.tree_openfiles), FALSE);
- gtk_tree_view_set_enable_search(GTK_TREE_VIEW(tv.tree_openfiles), FALSE); + gtk_tree_view_set_search_column(GTK_TREE_VIEW(tv.tree_openfiles), + DOCUMENTS_SHORTNAME);
/* sort opened filenames in the store_openfiles treeview */ sortable = GTK_TREE_SORTABLE(GTK_TREE_MODEL(store_openfiles)); @@ -274,13 +274,15 @@ if (gtk_check_version(2, 12, 0) == NULL) g_object_set(tv.tree_openfiles, "has-tooltip", TRUE, "tooltip-column", DOCUMENTS_FILENAME, NULL);
- g_signal_connect(tv.tree_openfiles, "button-release-event", - G_CALLBACK(on_documents_button_release_event), NULL); - /* selection handling */ select = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv.tree_openfiles)); gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE); - g_signal_connect(select, "changed", G_CALLBACK(on_openfiles_tree_selection_changed), NULL); + g_object_unref(store_openfiles); + + g_signal_connect(GTK_TREE_VIEW(tv.tree_openfiles), "button-press-event", + G_CALLBACK(treeviews_button_press_cb), NULL); + g_signal_connect(GTK_TREE_VIEW(tv.tree_openfiles), "key-press-event", + G_CALLBACK(treeviews_key_press_cb), NULL); }
@@ -702,31 +704,16 @@ }
-static gboolean change_focus_to_editor(GeanyDocument *doc, GtkWidget *focus_widget) +static void change_focus_to_editor(GeanyDocument *doc) { - /* idx might not be valid e.g. if user closed a tab whilst Geany is opening files */ - if (DOC_VALID(doc)) - { - GtkWidget *focusw = gtk_window_get_focus(GTK_WINDOW(main_widgets.window)); - GtkWidget *sci = GTK_WIDGET(doc->editor->sci); - - if (focusw == focus_widget) - gtk_widget_grab_focus(sci); - } - return FALSE; + if (may_steal_focus) + document_try_focus(doc); + may_steal_focus = FALSE; }
-static gboolean change_focus_cb(gpointer data) +static gboolean on_openfiles_tree_selection_changed(GtkTreeSelection *selection) { - change_focus_to_editor(data, tv.tree_openfiles); - - return FALSE; -} - - -static void on_openfiles_tree_selection_changed(GtkTreeSelection *selection, gpointer data) -{ GtkTreeIter iter; GtkTreeModel *model; GeanyDocument *doc = NULL; @@ -734,14 +721,18 @@ /* use switch_notebook_page to ignore changing the notebook page because it is already done */ if (gtk_tree_selection_get_selected(selection, &model, &iter) && ! ignore_callback) { + gint pos; gtk_tree_model_get(model, &iter, DOCUMENTS_DOCUMENT, &doc, -1); if (! doc) - return; /* parent */ - gtk_notebook_set_current_page(GTK_NOTEBOOK(main_widgets.notebook), - gtk_notebook_page_num(GTK_NOTEBOOK(main_widgets.notebook), - (GtkWidget*) doc->editor->sci)); - g_idle_add((GSourceFunc) change_focus_cb, doc); + return FALSE; /* parent */ + pos = sci_get_current_position(doc->editor->sci); + + /* we could just reload, but that would destroy the notification about + * the file being modified if it was externally, so fill in all required fields */ + document_open_file_full(NULL, doc->file_name, pos, + doc->readonly, doc->file_type, doc->encoding); } + return FALSE; }
@@ -767,7 +758,7 @@ if (doc != NULL) { navqueue_goto_line(doc, doc, line); - change_focus_to_editor(doc, doc->priv->tag_tree); + change_focus_to_editor(doc); } } } @@ -775,29 +766,35 @@ }
-static gboolean on_treeviews_key_press_event(GtkWidget *widget, GdkEventKey *event, +static gboolean treeviews_key_press_cb(GtkWidget *widget, GdkEventKey *event, gpointer user_data) { + may_steal_focus = FALSE; if (event->keyval == GDK_Return || event->keyval == GDK_ISO_Enter || event->keyval == GDK_KP_Enter || event->keyval == GDK_space) { + may_steal_focus = TRUE; GtkTreeSelection *select = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); /* delay the query of selection state because this callback is executed before GTK * changes the selection (g_signal_connect_after would be better but it doesn't work) */ - g_idle_add((GSourceFunc) on_taglist_tree_selection_changed, select); + if (widget == tv.tree_openfiles) /* tag and doc list have separate handlers */ + g_idle_add((GSourceFunc) on_openfiles_tree_selection_changed, select); + else + g_idle_add((GSourceFunc) on_taglist_tree_selection_changed, select); } return FALSE; }
-static gboolean on_symbols_button_press_event(GtkWidget *widget, GdkEventButton *event, +static gboolean treeviews_button_press_cb(GtkWidget *widget, GdkEventButton *event, G_GNUC_UNUSED gpointer user_data) { GtkTreeSelection *selection;
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); + may_steal_focus = TRUE;
if (event->type == GDK_2BUTTON_PRESS) { /* double click on parent node(section) expands/collapses it */ @@ -824,18 +821,31 @@ { /* allow reclicking of taglist treeview item */ /* delay the query of selection state because this callback is executed before GTK * changes the selection (g_signal_connect_after would be better but it doesn't work) */ - g_idle_add((GSourceFunc) on_taglist_tree_selection_changed, selection); + if (widget == tv.tree_openfiles) + g_idle_add((GSourceFunc) on_openfiles_tree_selection_changed, selection); + else + g_idle_add((GSourceFunc) on_taglist_tree_selection_changed, selection); } else if (event->button == 3) { - gtk_menu_popup(GTK_MENU(tv.popup_taglist), NULL, NULL, NULL, NULL, - event->button, event->time); - return TRUE; /* prevent selection changed signal for symbol tags */ + documents_menu_update(selection); + if (widget == tv.tree_openfiles) + { + if (!openfiles_popup_menu) + create_openfiles_popup_menu(); + + gtk_menu_popup(GTK_MENU(openfiles_popup_menu), NULL, NULL, NULL, NULL, + event->button, event->time); + } + else + { + gtk_menu_popup(GTK_MENU(tv.popup_taglist), NULL, NULL, NULL, NULL, + event->button, event->time); + } } return FALSE; }
- static void documents_menu_update(GtkTreeSelection *selection) { GtkTreeModel *model; @@ -866,26 +876,6 @@ }
-static gboolean on_documents_button_release_event(GtkWidget *widget, GdkEventButton *event, - gpointer user_data) -{ - GtkTreeSelection *selection; - - selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); - - if (event->button == 3) - { - if (!openfiles_popup_menu) - create_openfiles_popup_menu(); - - documents_menu_update(selection); - gtk_menu_popup(GTK_MENU(openfiles_popup_menu), NULL, NULL, NULL, NULL, - event->button, event->time); - } - return FALSE; -} - - GeanyPrefGroup *stash_group = NULL;
static void on_load_settings(void)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.