[geany/geany] 8ea549: Merge branch 'kugel/document-messages2'
Matthew Brush
git-noreply at xxxxx
Mon May 26 01:55:07 UTC 2014
Branch: refs/heads/master
Author: Matthew Brush <matt at geany.org>
Committer: Matthew Brush <matt at geany.org>
Date: Mon, 26 May 2014 01:55:07 UTC
Commit: 8ea54993c5d599f82b6060550f304e06302b46d6
https://github.com/geany/geany/commit/8ea54993c5d599f82b6060550f304e06302b46d6
Log Message:
-----------
Merge branch 'kugel/document-messages2'
This is an extension of the long-lived `document-messages` branch.
It is mostly adjusted according to the feedback on the mailing list.
There might existing some usability issues to be resolved, but this
is the first step towards non-modal document notifications.
Modified Paths:
--------------
src/document.c
src/documentprivate.h
src/notebook.c
Modified: src/document.c
355 lines changed, 310 insertions(+), 45 deletions(-)
===================================================================
@@ -74,6 +74,7 @@
/*#define USE_GIO_FILEMON 1*/
#include <gio/gio.h>
+#include <gdk/gdkkeysyms.h>
GeanyFilePrefs file_prefs;
@@ -220,10 +221,47 @@ GeanyDocument *document_find_by_sci(ScintillaObject *sci)
* @since 0.19 */
gint document_get_notebook_page(GeanyDocument *doc)
{
+ GtkWidget *parent;
+
g_return_val_if_fail(doc != NULL, -1);
- return gtk_notebook_page_num(GTK_NOTEBOOK(main_widgets.notebook),
- GTK_WIDGET(doc->editor->sci));
+ parent = gtk_widget_get_parent(GTK_WIDGET(doc->editor->sci));
+ g_return_val_if_fail(GTK_IS_BOX(parent), -1);
+
+ return gtk_notebook_page_num(GTK_NOTEBOOK(main_widgets.notebook), parent);
+}
+
+
+/*
+ * Recursively searches a containers children until it finds a
+ * Scintilla widget, or NULL if one was not found.
+ */
+static ScintillaObject *locate_sci_in_container(GtkWidget *container)
+{
+ ScintillaObject *sci = NULL;
+ GList *children, *iter;
+
+ g_return_val_if_fail(GTK_IS_CONTAINER(container), NULL);
+
+ children = gtk_container_get_children(GTK_CONTAINER(container));
+ for (iter = children; iter != NULL; iter = g_list_next(iter))
+ {
+ if (IS_SCINTILLA(iter->data))
+ {
+ sci = SCINTILLA(iter->data);
+ break;
+ }
+ else if (GTK_IS_CONTAINER(iter->data))
+ {
+ sci = locate_sci_in_container(iter->data);
+ if (IS_SCINTILLA(sci))
+ break;
+ sci = NULL;
+ }
+ }
+ g_list_free(children);
+
+ return sci;
}
@@ -236,13 +274,17 @@ gint document_get_notebook_page(GeanyDocument *doc)
**/
GeanyDocument *document_get_from_page(guint page_num)
{
+ GtkWidget *parent;
ScintillaObject *sci;
if (page_num >= documents_array->len)
return NULL;
- sci = (ScintillaObject*)gtk_notebook_get_nth_page(
- GTK_NOTEBOOK(main_widgets.notebook), page_num);
+ parent = gtk_notebook_get_nth_page(GTK_NOTEBOOK(main_widgets.notebook), page_num);
+ g_return_val_if_fail(GTK_IS_BOX(parent), NULL);
+
+ sci = locate_sci_in_container(parent);
+ g_return_val_if_fail(IS_SCINTILLA(sci), NULL);
return document_find_by_sci(sci);
}
@@ -255,14 +297,21 @@ GeanyDocument *document_get_from_page(guint page_num)
**/
GeanyDocument *document_get_current(void)
{
- gint cur_page = gtk_notebook_get_current_page(GTK_NOTEBOOK(main_widgets.notebook));
+ gint cur_page;
+ GtkWidget *parent;
+ ScintillaObject *sci;
+
+ cur_page = gtk_notebook_get_current_page(GTK_NOTEBOOK(main_widgets.notebook));
if (cur_page == -1)
return NULL;
else
{
- ScintillaObject *sci = (ScintillaObject*)
- gtk_notebook_get_nth_page(GTK_NOTEBOOK(main_widgets.notebook), cur_page);
+ parent = gtk_notebook_get_nth_page(GTK_NOTEBOOK(main_widgets.notebook), cur_page);
+ g_return_val_if_fail(GTK_IS_BOX(parent), NULL);
+
+ sci = locate_sci_in_container(parent);
+ g_return_val_if_fail(IS_SCINTILLA(sci), NULL);
return document_find_by_sci(sci);
}
@@ -1190,6 +1239,7 @@ GeanyDocument *document_open_file_full(GeanyDocument *doc, const gchar *filename
doc->readonly = readonly || filedata.readonly;
sci_set_readonly(doc->editor->sci, doc->readonly);
+ doc->priv->protected = 0;
/* update line number margin width */
doc->priv->line_count = sci_get_line_count(doc->editor->sci);
@@ -1322,6 +1372,10 @@ gboolean document_reload_file(GeanyDocument *doc, const gchar *forced_enc)
g_return_val_if_fail(doc != NULL, FALSE);
+ /* Use cancel because the response handler would call this recursively */
+ if (doc->priv->info_bars[MSG_TYPE_RELOAD] != NULL)
+ gtk_info_bar_response(GTK_INFO_BAR(doc->priv->info_bars[MSG_TYPE_RELOAD]), GTK_RESPONSE_CANCEL);
+
/* try to set the cursor to the position before reloading */
pos = sci_get_current_position(doc->editor->sci);
new_doc = document_open_file_full(doc, NULL, pos, doc->readonly, doc->file_type, forced_enc);
@@ -1443,6 +1497,22 @@ void document_rename_file(GeanyDocument *doc, const gchar *new_filename)
}
+static void protect_document(GeanyDocument *doc)
+{
+ /* do not call queue_colourise because to we want to keep the text-changed indication! */
+ if (!doc->priv->protected++)
+ sci_set_readonly(doc->editor->sci, TRUE);
+}
+
+static void unprotect_document(GeanyDocument *doc)
+{
+ g_return_if_fail(doc->priv->protected > 0);
+
+ if (!--doc->priv->protected && doc->readonly == FALSE)
+ sci_set_readonly(doc->editor->sci, FALSE);
+}
+
+
/* Return TRUE if the document doesn't have a full filename set.
* This makes filenames without a path show the save as dialog, e.g. for file templates.
* Otherwise just use the set filename instead of asking the user - e.g. for command-line
@@ -1469,9 +1539,11 @@ gboolean document_need_save_as(GeanyDocument *doc)
gboolean document_save_file_as(GeanyDocument *doc, const gchar *utf8_fname)
{
gboolean ret;
+ gboolean new_file;
g_return_val_if_fail(doc != NULL, FALSE);
+ new_file = document_need_save_as(doc) || (utf8_fname != NULL && !strcmp(doc->file_name, utf8_fname));
if (utf8_fname != NULL)
SETPTR(doc->file_name, g_strdup(utf8_fname));
@@ -1491,6 +1563,15 @@ gboolean document_save_file_as(GeanyDocument *doc, const gchar *utf8_fname)
ignore_callback = FALSE;
}
}
+
+ if (new_file)
+ {
+ sci_set_readonly(doc->editor->sci, FALSE);
+ doc->readonly = FALSE;
+ if (doc->priv->protected > 0)
+ unprotect_document(doc);
+ }
+
replace_header_filename(doc);
ret = document_save_file(doc, TRUE);
@@ -1681,7 +1762,6 @@ static gchar *save_doc(GeanyDocument *doc, const gchar *locale_filename,
return NULL;
}
-
/**
* Saves the document.
* Also shows the Save As dialog if necessary.
@@ -1725,7 +1805,9 @@ gboolean document_save_file(GeanyDocument *doc, gboolean force)
}
/* the "changed" flag should exclude the "readonly" flag, but check it anyway for safety */
- if (! force && (! doc->changed || doc->readonly))
+ if (doc->readonly || doc->priv->protected)
+ return FALSE;
+ if (!force && !doc->changed)
return FALSE;
fp = project_get_file_prefs();
@@ -2880,6 +2962,7 @@ GeanyDocument *document_clone(GeanyDocument *old_doc)
old_doc->editor->indent_width);
doc->readonly = old_doc->readonly;
doc->has_bom = old_doc->has_bom;
+ doc->priv->protected = 0;
document_set_encoding(doc, old_doc->encoding);
sci_set_lines_wrapped(doc->editor->sci, doc->editor->line_wrapping);
sci_set_readonly(doc->editor->sci, doc->readonly);
@@ -2952,59 +3035,240 @@ gboolean document_close_all(void)
}
-static void monitor_reload_file(GeanyDocument *doc)
+/* *
+ * Shows a message related to a document.
+ *
+ * Use this whenever the user needs to see a document-related message,
+ * for example when the file was externally modified or deleted.
+ *
+ * Any of the buttons can be @c NULL. If not @c NULL, @a btn_1's
+ * @a response_1 response will be the default for the @c GtkInfoBar or
+ * @c GtkDialog.
+ *
+ * @param doc @c GeanyDocument.
+ * @param msgtype The type of message.
+ * @param response_cb A callback function called when there's a response.
+ * @param btn_1 The first action area button.
+ * @param response_1 The response for @a btn_1.
+ * @param btn_2 The second action area button.
+ * @param response_2 The response for @a btn_2.
+ * @param btn_3 The third action area button.
+ * @param response_3 The response for @a btn_3.
+ * @param extra_text Text to show below the main message.
+ * @param format The text format for the main message.
+ * @param ... Used with @a format as in @c printf.
+ *
+ * @since 1.25
+ * */
+static GtkWidget* document_show_message(GeanyDocument *doc, GtkMessageType msgtype,
+ void (*response_cb)(GtkWidget *info_bar, gint response_id, GeanyDocument *doc),
+ const gchar *btn_1, GtkResponseType response_1,
+ const gchar *btn_2, GtkResponseType response_2,
+ const gchar *btn_3, GtkResponseType response_3,
+ const gchar *extra_text, const gchar *format, ...)
+{
+ va_list args;
+ gchar *text, *markup;
+ GtkWidget *hbox, *vbox, *icon, *label, *extra_label, *content_area;
+ GtkWidget *info_widget, *ok_button, *cancel_button, *parent;
+ parent = gtk_notebook_get_nth_page(GTK_NOTEBOOK(main_widgets.notebook),
+ document_get_notebook_page(doc));
+
+ va_start(args, format);
+ text = g_strdup_vprintf(format, args);
+ va_end(args);
+
+ markup = g_strdup_printf("<span size=\"larger\">%s</span>", text);
+ g_free(text);
+
+ info_widget = gtk_info_bar_new();
+ /* must be done now else Gtk-WARNING: widget not within a GtkWindow */
+ gtk_box_pack_start(GTK_BOX(parent), info_widget, FALSE, TRUE, 0);
+
+ gtk_info_bar_set_message_type(GTK_INFO_BAR(info_widget), msgtype);
+
+ if (btn_1)
+ gtk_info_bar_add_button(GTK_INFO_BAR(info_widget), btn_1, response_1);
+ if (btn_2)
+ gtk_info_bar_add_button(GTK_INFO_BAR(info_widget), btn_2, response_2);
+ if (btn_3)
+ gtk_info_bar_add_button(GTK_INFO_BAR(info_widget), btn_3, response_3);
+
+ content_area = gtk_info_bar_get_content_area(GTK_INFO_BAR(info_widget));
+
+ label = gtk_label_new(NULL);
+ gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
+
+ gtk_label_set_markup(GTK_LABEL(label), markup);
+ g_free(markup);
+
+ g_signal_connect(info_widget, "response", G_CALLBACK(response_cb), doc);
+ g_signal_connect_after(info_widget, "response", G_CALLBACK(gtk_widget_destroy), NULL);
+
+ hbox = gtk_hbox_new(FALSE, 12);
+ gtk_container_add(GTK_CONTAINER(content_area), hbox);
+
+ switch (msgtype)
+ {
+ case GTK_MESSAGE_INFO:
+ icon = gtk_image_new_from_stock(GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_DIALOG);
+ break;
+ case GTK_MESSAGE_WARNING:
+ icon = gtk_image_new_from_stock(GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_DIALOG);
+ break;
+ case GTK_MESSAGE_QUESTION:
+ icon = gtk_image_new_from_stock(GTK_STOCK_DIALOG_QUESTION, GTK_ICON_SIZE_DIALOG);
+ break;
+ case GTK_MESSAGE_ERROR:
+ icon = gtk_image_new_from_stock(GTK_STOCK_DIALOG_ERROR, GTK_ICON_SIZE_DIALOG);
+ break;
+ default:
+ icon = NULL;
+ break;
+ }
+
+ if (icon)
+ gtk_box_pack_start(GTK_BOX(hbox), icon, FALSE, TRUE, 0);
+
+ if (extra_text)
+ {
+ vbox = gtk_vbox_new(FALSE, 6);
+ extra_label = gtk_label_new(extra_text);
+ gtk_misc_set_alignment(GTK_MISC(extra_label), 0.0, 0.5);
+ gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), extra_label, TRUE, TRUE, 0);
+ gtk_container_add(GTK_CONTAINER(hbox), vbox);
+ }
+ else
+ gtk_container_add(GTK_CONTAINER(hbox), label);
+
+ gtk_box_reorder_child(GTK_BOX(parent), info_widget, 0);
+
+ gtk_widget_show_all(info_widget);
+
+ return info_widget;
+}
+
+static void on_monitor_reload_file_response(GtkWidget *bar, gint response_id, GeanyDocument *doc)
{
- gchar *base_name = g_path_get_basename(doc->file_name);
- gint ret;
-
- /* we use No instead of Cancel to avoid mnemonic clash */
- ret = dialogs_show_prompt(NULL,
- GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
- GTK_STOCK_NO, GTK_RESPONSE_CANCEL,
- _("_Reload"), GTK_RESPONSE_ACCEPT,
- _("Do you want to reload it?"),
- _("The file '%s' on the disk is more recent than\nthe current buffer."),
- base_name);
- g_free(base_name);
+ unprotect_document(doc);
+ doc->priv->info_bars[MSG_TYPE_RELOAD] = NULL;
- if (ret == GTK_RESPONSE_ACCEPT)
+ if (response_id == GTK_RESPONSE_ACCEPT)
document_reload_file(doc, doc->encoding);
- else if (ret == GTK_RESPONSE_CLOSE)
- document_close(doc);
}
-
-static gboolean monitor_resave_missing_file(GeanyDocument *doc)
+static gboolean on_sci_key(GtkWidget *w, GdkEventKey *event, gpointer data)
{
- gboolean want_reload = FALSE;
- gboolean file_saved = FALSE;
- gint ret;
+ GtkInfoBar *bar = GTK_INFO_BAR(data);
+
+ g_return_val_if_fail(event->type == GDK_KEY_PRESS, FALSE);
- ret = dialogs_show_prompt(NULL,
- _("Close _without saving"), GTK_RESPONSE_CLOSE,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
- _("Try to resave the file?"),
- _("File \"%s\" was not found on disk!"),
- doc->file_name);
- if (ret == GTK_RESPONSE_ACCEPT)
+ switch (event->keyval)
{
- file_saved = dialogs_show_save_as();
- want_reload = TRUE;
+ case GDK_KEY_Tab:
+ case GDK_KEY_ISO_Left_Tab:
+ {
+ GtkWidget *w = gtk_info_bar_get_action_area(bar);
+ GtkDirectionType dir = event->keyval == GDK_KEY_Tab ? GTK_DIR_TAB_FORWARD : GTK_DIR_TAB_BACKWARD;
+ gtk_widget_child_focus(w, dir);
+ return TRUE;
+ }
+ case GDK_KEY_Escape:
+ {
+ gtk_info_bar_response(bar, GTK_RESPONSE_CANCEL);
+ return TRUE;
+ }
+ default:
+ return FALSE;
}
- else if (ret == GTK_RESPONSE_CLOSE)
+}
+
+/* g_signal_handlers_disconnect_by_data is a macro that cannot be used as GCallback */
+static gint nonmacro_g_signal_handlers_disconnect_by_data(gpointer instance, gpointer data)
+{
+ return g_signal_handlers_disconnect_by_data(instance, data);
+}
+
+static void enable_key_intercept(GeanyDocument *doc, GtkWidget *bar)
+{
+ g_signal_connect(doc->editor->sci, "key-press-event", G_CALLBACK(on_sci_key), bar);
+ /* make the signal disconnect automatically */
+ g_signal_connect_swapped(bar, "unrealize",
+ G_CALLBACK(nonmacro_g_signal_handlers_disconnect_by_data), doc->editor->sci);
+}
+
+static void monitor_reload_file(GeanyDocument *doc)
+{
+ gchar *base_name = g_path_get_basename(doc->file_name);
+
+ /* show this message only once */
+ if (doc->priv->info_bars[MSG_TYPE_RELOAD] == NULL)
{
- document_close(doc);
+ GtkWidget *bar;
+
+ bar = document_show_message(doc, GTK_MESSAGE_QUESTION, on_monitor_reload_file_response,
+ _("_Reload"), GTK_RESPONSE_ACCEPT,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ NULL, GTK_RESPONSE_NONE,
+ _("Do you want to reload it?"),
+ _("The file '%s' on the disk is more recent than the current buffer."),
+ base_name);
+
+ protect_document(doc);
+ doc->priv->info_bars[MSG_TYPE_RELOAD] = bar;
+ enable_key_intercept(doc, bar);
}
- if (ret != GTK_RESPONSE_CLOSE && ! file_saved)
+ g_free(base_name);
+}
+
+
+static void on_monitor_resave_missing_file_response(GtkWidget *bar,
+ gint response_id,
+ GeanyDocument *doc)
+{
+ gboolean file_saved = FALSE;
+
+ unprotect_document(doc);
+
+ if (response_id == GTK_RESPONSE_ACCEPT)
+ file_saved = dialogs_show_save_as();
+
+ if (!file_saved)
{
- /* file is missing - set unsaved state */
document_set_text_changed(doc, TRUE);
/* don't prompt more than once */
SETPTR(doc->real_path, NULL);
}
- return want_reload;
+ doc->priv->info_bars[MSG_TYPE_RESAVE] = NULL;
+}
+
+
+static void monitor_resave_missing_file(GeanyDocument *doc)
+{
+ GtkWidget *bar;
+
+ if (doc->priv->info_bars[MSG_TYPE_RESAVE] == NULL)
+ {
+ GtkWidget *bar;
+ bar = doc->priv->info_bars[MSG_TYPE_RELOAD];
+ if (bar != NULL) /* the "file on disk is newer" warning is now moot */
+ gtk_info_bar_response(GTK_INFO_BAR(bar), GTK_RESPONSE_CANCEL);
+
+ bar = document_show_message(doc, GTK_MESSAGE_WARNING,
+ on_monitor_resave_missing_file_response,
+ GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ NULL, GTK_RESPONSE_NONE,
+ _("Try to resave the file?"),
+ _("File \"%s\" was not found on disk!"),
+ doc->file_name);
+
+ protect_document(doc);
+ doc->priv->info_bars[MSG_TYPE_RESAVE] = bar;
+ enable_key_intercept(doc, bar);
+ }
}
@@ -3058,6 +3322,7 @@ gboolean document_check_disk_status(GeanyDocument *doc, gboolean force)
}
else if (doc->priv->mtime < st.st_mtime)
{
+ /* make sure the user is not prompted again after he cancelled the "reload file?" message */
doc->priv->mtime = st.st_mtime;
monitor_reload_file(doc);
/* doc may be closed now */
Modified: src/documentprivate.h
12 lines changed, 12 insertions(+), 0 deletions(-)
===================================================================
@@ -53,6 +53,13 @@ typedef struct FileEncoding
}
FileEncoding;
+enum
+{
+ MSG_TYPE_RELOAD,
+ MSG_TYPE_RESAVE,
+
+ NUM_MSG_TYPES
+};
/* Private GeanyDocument fields */
typedef struct GeanyDocumentPrivate
@@ -86,6 +93,11 @@ typedef struct GeanyDocumentPrivate
time_t mtime;
/* ID of the idle callback updating the tag list */
guint tag_list_update_source;
+ /* Whether it's temoporarily protected (read-only and saving is prevented). Does
+ * not imply doc->readonly as writable files can be protected */
+ gint protected;
+ /* Save pointer to info bars allowing to cancel them programatically (to avoid multiple ones) */
+ GtkWidget *info_bars[NUM_MSG_TYPES];
}
GeanyDocumentPrivate;
Modified: src/notebook.c
27 lines changed, 15 insertions(+), 12 deletions(-)
===================================================================
@@ -608,6 +608,7 @@ static void tab_count_changed(void)
static gboolean notebook_tab_click(GtkWidget *widget, GdkEventButton *event, gpointer data)
{
guint state;
+ GeanyDocument *doc = (GeanyDocument *) data;
/* toggle additional widgets on double click */
if (event->type == GDK_2BUTTON_PRESS)
@@ -620,8 +621,7 @@ static gboolean notebook_tab_click(GtkWidget *widget, GdkEventButton *event, gpo
/* close tab on middle click */
if (event->button == 2)
{
- document_remove_page(gtk_notebook_page_num(GTK_NOTEBOOK(main_widgets.notebook),
- GTK_WIDGET(data)));
+ document_close(doc);
return TRUE; /* stop other handlers like notebook_tab_bar_click_cb() */
}
/* switch last used tab on ctrl-click */
@@ -656,14 +656,18 @@ static void notebook_tab_close_button_style_set(GtkWidget *btn, GtkRcStyle *prev
/* Returns page number of notebook page, or -1 on error */
gint notebook_new_tab(GeanyDocument *this)
{
- GtkWidget *hbox, *ebox;
+ GtkWidget *hbox, *ebox, *vbox;
gint tabnum;
GtkWidget *page;
gint cur_page;
g_return_val_if_fail(this != NULL, -1);
+ /* page is packed into a vbox so we can stack infobars above it */
+ vbox = gtk_vbox_new(FALSE, 0);
page = GTK_WIDGET(this->editor->sci);
+ gtk_box_pack_start(GTK_BOX(vbox), page, TRUE, TRUE, 0);
+ gtk_widget_show(vbox);
this->priv->tab_label = gtk_label_new(NULL);
@@ -671,7 +675,7 @@ gint notebook_new_tab(GeanyDocument *this)
* the close button, if any */
ebox = gtk_event_box_new();
gtk_widget_set_has_window(ebox, FALSE);
- g_signal_connect(ebox, "button-press-event", G_CALLBACK(notebook_tab_click), page);
+ g_signal_connect(ebox, "button-press-event", G_CALLBACK(notebook_tab_click), this);
/* focus the current document after clicking on a tab */
g_signal_connect_after(ebox, "button-release-event",
G_CALLBACK(focus_sci), NULL);
@@ -698,7 +702,7 @@ gint notebook_new_tab(GeanyDocument *this)
g_signal_connect(btn, "clicked", G_CALLBACK(notebook_tab_close_clicked_cb), page);
/* button overrides event box, so make middle click on button also close tab */
- g_signal_connect(btn, "button-press-event", G_CALLBACK(notebook_tab_click), page);
+ g_signal_connect(btn, "button-press-event", G_CALLBACK(notebook_tab_click), this);
/* handle style modification to keep button small as possible even when theme change */
g_signal_connect(btn, "style-set", G_CALLBACK(notebook_tab_close_button_style_set), NULL);
}
@@ -712,28 +716,27 @@ gint notebook_new_tab(GeanyDocument *this)
else
cur_page = file_prefs.tab_order_ltr ? -2 /* hack: -2 + 1 = -1, last page */ : 0;
if (file_prefs.tab_order_ltr)
- tabnum = gtk_notebook_insert_page_menu(GTK_NOTEBOOK(main_widgets.notebook), page,
+ tabnum = gtk_notebook_insert_page_menu(GTK_NOTEBOOK(main_widgets.notebook), vbox,
ebox, NULL, cur_page + 1);
else
- tabnum = gtk_notebook_insert_page_menu(GTK_NOTEBOOK(main_widgets.notebook), page,
+ tabnum = gtk_notebook_insert_page_menu(GTK_NOTEBOOK(main_widgets.notebook), vbox,
ebox, NULL, cur_page);
tab_count_changed();
/* enable tab DnD */
- gtk_notebook_set_tab_reorderable(GTK_NOTEBOOK(main_widgets.notebook), page, TRUE);
+ gtk_notebook_set_tab_reorderable(GTK_NOTEBOOK(main_widgets.notebook), vbox, TRUE);
return tabnum;
}
static void
-notebook_tab_close_clicked_cb(GtkButton *button, gpointer user_data)
+notebook_tab_close_clicked_cb(GtkButton *button, gpointer data)
{
- gint cur_page = gtk_notebook_page_num(GTK_NOTEBOOK(main_widgets.notebook),
- GTK_WIDGET(user_data));
+ GeanyDocument *doc = (GeanyDocument *) data;
- document_remove_page(cur_page);
+ document_close(doc);
}
--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).
More information about the Commits
mailing list