/*
* gedit-documents-panel.c
* This file is part of gedit
*
* Copyright (C) 2014 - Sébastien Lafargue <slafargue@gnome.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "gedit-documents-panel.h"
#include <glib/gi18n.h>
#include "gedit-debug.h"
#include "gedit-document.h"
#include "gedit-multi-notebook.h"
#include "gedit-notebook.h"
#include "gedit-notebook-popup-menu.h"
#include "gedit-tab.h"
#include "gedit-tab-private.h"
#include "gedit-utils.h"
#include "gedit-commands-private.h"
typedef struct _GeditDocumentsGenericRow GeditDocumentsGenericRow;
typedef struct _GeditDocumentsGenericRow GeditDocumentsGroupRow;
typedef struct _GeditDocumentsGenericRow GeditDocumentsDocumentRow;
struct _GeditDocumentsGenericRow
{
GtkListBoxRow parent_instance;
GeditDocumentsPanel *panel;
GtkWidget *ref;
GtkWidget *box;
GtkWidget *label;
GtkWidget *close_button;
/* Not used in GeditDocumentsGroupRow */
GtkWidget *image;
GtkWidget *status_label;
};
#define GEDIT_TYPE_DOCUMENTS_GROUP_ROW (gedit_documents_group_row_get_type ())
#define GEDIT_DOCUMENTS_GROUP_ROW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_DOCUMENTS_GROUP_ROW, GeditDocumentsGroupRow))
#define GEDIT_DOCUMENTS_GROUP_ROW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_DOCUMENTS_GROUP_ROW, GeditDocumentsGroupRowClass))
#define GEDIT_IS_DOCUMENTS_GROUP_ROW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_DOCUMENTS_GROUP_ROW))
#define GEDIT_IS_DOCUMENTS_GROUP_ROW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_DOCUMENTS_GROUP_ROW))
#define GEDIT_DOCUMENTS_GROUP_ROW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GEDIT_TYPE_DOCUMENTS_GROUP_ROW, GeditDocumentsGroupRowClass))
typedef struct _GeditDocumentsGroupRowClass GeditDocumentsGroupRowClass;
struct _GeditDocumentsGroupRowClass
{
GtkListBoxRowClass parent_class;
};
GType gedit_documents_group_row_get_type (void) G_GNUC_CONST;
G_DEFINE_TYPE (GeditDocumentsGroupRow, gedit_documents_group_row, GTK_TYPE_LIST_BOX_ROW)
#define GEDIT_TYPE_DOCUMENTS_DOCUMENT_ROW (gedit_documents_document_row_get_type ())
#define GEDIT_DOCUMENTS_DOCUMENT_ROW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_DOCUMENTS_DOCUMENT_ROW, GeditDocumentsDocumentRow))
#define GEDIT_DOCUMENTS_DOCUMENT_ROW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_DOCUMENTS_DOCUMENT_ROW, GeditDocumentsDocumentRowClass))
#define GEDIT_IS_DOCUMENTS_DOCUMENT_ROW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_DOCUMENTS_DOCUMENT_ROW))
#define GEDIT_IS_DOCUMENTS_DOCUMENT_ROW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_DOCUMENTS_DOCUMENT_ROW))
#define GEDIT_DOCUMENTS_DOCUMENT_ROW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GEDIT_TYPE_DOCUMENTS_DOCUMENT_ROW, GeditDocumentsDocumentRowClass))
typedef struct _GeditDocumentsDocumentRowClass GeditDocumentsDocumentRowClass;
struct _GeditDocumentsDocumentRowClass
{
GtkListBoxRowClass parent_class;
};
GType gedit_documents_document_row_get_type (void) G_GNUC_CONST;
G_DEFINE_TYPE (GeditDocumentsDocumentRow, gedit_documents_document_row, GTK_TYPE_LIST_BOX_ROW)
static GtkWidget *gedit_documents_document_row_new (GeditDocumentsPanel *panel,
GeditTab *tab);
static GtkWidget *gedit_documents_group_row_new (GeditDocumentsPanel *panel,
GeditNotebook *notebook);
struct _GeditDocumentsPanel
{
GtkBox parent_instance;
GeditWindow *window;
GeditMultiNotebook *mnb;
GtkWidget *listbox;
guint selection_changed_handler_id;
guint tab_switched_handler_id;
gboolean is_in_tab_switched;
/* Flag to workaround first GroupRow selection at start ( we don't want to show it ) */
gboolean first_selection;
GtkWidget *current_selection;
GtkAdjustment *adjustment;
guint nb_row_notebook;
guint nb_row_tab;
GtkTargetList *source_targets;
GtkWidget *dnd_window;
GtkWidget *row_placeholder;
guint row_placeholder_index;
guint row_destination_index;
GtkWidget *drag_document_row;
gint row_source_row_offset;
gint document_row_height;
gint drag_document_row_x;
gint drag_document_row_y;
gint drag_root_x;
gint drag_root_y;
gboolean is_on_drag;
};
enum
{
PROP_0,
PROP_WINDOW,
LAST_PROP
};
static GParamSpec *properties[LAST_PROP];
G_DEFINE_TYPE (GeditDocumentsPanel, gedit_documents_panel, GTK_TYPE_BOX)
static const GtkTargetEntry panel_targets [] = {
{"GEDIT_DOCUMENTS_DOCUMENT_ROW", GTK_TARGET_SAME_APP, 0},
};
#define MAX_DOC_NAME_LENGTH 60
#define ROW_OUTSIDE_LISTBOX -1
static guint
get_nb_visible_rows (GeditDocumentsPanel *panel)
{
guint nb = 0;
if (panel->nb_row_notebook > 1)
{
nb += panel->nb_row_notebook;
}
nb += panel->nb_row_tab;
return nb;
}
static guint
get_row_visible_index (GeditDocumentsPanel *panel,
GtkWidget *searched_row)
{
GList *children;
GList *l;
guint nb_notebook_row = 0;
guint nb_tab_row = 0;
children = gtk_container_get_children (GTK_CONTAINER (panel->listbox));
for (l = children; l != NULL; l = g_list_next (l))
{
GtkWidget *row = l->data;
if (GEDIT_IS_DOCUMENTS_GROUP_ROW (row))
{
nb_notebook_row += 1;
}
else
{
nb_tab_row += 1;
}
if (row == searched_row)
{
break;
}
}
g_list_free (children);
if (panel->nb_row_notebook == 1)
{
nb_notebook_row = 0;
}
return nb_tab_row + nb_notebook_row - 1;
}
/* We do not grab focus on the row, so scroll it into view manually */
static void
make_row_visible (GeditDocumentsPanel *panel,
GtkWidget *row)
{
gdouble adjustment_value;
gdouble adjustment_lower;
gdouble adjustment_upper;
gdouble adjustment_page_size;
gdouble nb_visible_rows;
gdouble row_visible_index;
gdouble row_size;
gdouble row_position;
gdouble offset;
gdouble new_adjustment_value;
adjustment_value = gtk_adjustment_get_value (panel->adjustment);
adjustment_lower = gtk_adjustment_get_lower (panel->adjustment);
adjustment_upper = gtk_adjustment_get_upper (panel->adjustment);
adjustment_page_size = gtk_adjustment_get_page_size (panel->adjustment);
nb_visible_rows = get_nb_visible_rows (panel);
row_visible_index = get_row_visible_index (panel, GTK_WIDGET (row));
row_size = (adjustment_upper - adjustment_lower) / nb_visible_rows;
row_position = row_size * row_visible_index;
if (row_position < adjustment_value)
{
new_adjustment_value = row_position;
}
else if ((row_position + row_size) > (adjustment_value + adjustment_page_size))
{
offset = (row_position + row_size) - (adjustment_value + adjustment_page_size);
new_adjustment_value = adjustment_value + offset;
}
else
{
new_adjustment_value = adjustment_value;
}
gtk_adjustment_set_value (panel->adjustment, new_adjustment_value);
}
/* This function is a GCompareFunc to use with g_list_find_custom */
static gint
listbox_search_function (gconstpointer row,
gconstpointer item)
{
GeditDocumentsGenericRow *generic_row = (GeditDocumentsGenericRow *)row;
gpointer *searched_item = (gpointer *)generic_row->ref;
return searched_item == item ? 0 : -1;
}
static GtkListBoxRow *
get_row_from_widget (GeditDocumentsPanel *panel,
GtkWidget *widget)
{
GList *children;
GList *item;
GtkListBoxRow *row;
children = gtk_container_get_children (GTK_CONTAINER (panel->listbox));
item = g_list_find_custom (children, widget, listbox_search_function);
row = item ? item->data : NULL;
g_list_free (children);
return row;
}
static void
row_select (GeditDocumentsPanel *panel,
GtkListBox *listbox,
GtkListBoxRow *row)
{
GtkListBoxRow *selected_row = gtk_list_box_get_selected_row (listbox);
if (row != selected_row)
{
g_signal_handler_block (listbox, panel->selection_changed_handler_id);
gtk_list_box_select_row (listbox, row);
g_signal_handler_unblock (listbox, panel->selection_changed_handler_id);
}
panel->current_selection = GTK_WIDGET (row);
make_row_visible (panel, GTK_WIDGET (row));
}
static void
insert_row (GeditDocumentsPanel *panel,
GtkListBox *listbox,
GtkWidget *row,
gint position)
{
g_signal_handler_block (listbox, panel->selection_changed_handler_id);
gtk_list_box_insert (listbox, row, position);
g_signal_handler_unblock (listbox, panel->selection_changed_handler_id);
}
static void
select_active_tab (GeditDocumentsPanel *panel)
{
GeditNotebook *notebook;
gboolean have_tabs;
GeditTab *tab;
notebook = gedit_multi_notebook_get_active_notebook (panel->mnb);
have_tabs = gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook)) > 0;
tab = gedit_multi_notebook_get_active_tab (panel->mnb);
if (notebook != NULL && tab != NULL && have_tabs)
{
GtkListBoxRow *row = get_row_from_widget (panel, GTK_WIDGET (tab));
if (row)
{
row_select (panel, GTK_LIST_BOX (panel->listbox), row);
}
}
}
static GtkListBoxRow *
get_first_notebook_found (GeditDocumentsPanel *panel)
{
GList *children;
GList *l;
GtkListBoxRow *row = NULL;
children = gtk_container_get_children (GTK_CONTAINER (panel->listbox));
for (l = children; l != NULL; l = g_list_next (l))
{
if (GEDIT_IS_DOCUMENTS_GROUP_ROW (l->data))
{
row = l->data;
break;
}
}
g_list_free (children);
return row;
}
static void
multi_notebook_tab_switched (GeditMultiNotebook *mnb,
GeditNotebook *old_notebook,
GeditTab *old_tab,
GeditNotebook *new_notebook,
GeditTab *new_tab,
GeditDocumentsPanel *panel)
{
gedit_debug (DEBUG_PANEL);
if (!_gedit_window_is_removing_tabs (panel->window) &&
panel->is_in_tab_switched == FALSE)
{
GtkListBoxRow *row;
panel->is_in_tab_switched = TRUE;
row = get_row_from_widget (panel, GTK_WIDGET (new_tab));
if (row)
{
row_select (panel, GTK_LIST_BOX (panel->listbox), row);
}
panel->is_in_tab_switched = FALSE;
}
}
static void
group_row_set_notebook_name (GtkWidget *row)
{
GeditNotebook *notebook;
GeditMultiNotebook *mnb;
guint num;
gchar *name;
GeditDocumentsGroupRow *group_row = GEDIT_DOCUMENTS_GROUP_ROW (row);
notebook = GEDIT_NOTEBOOK (group_row->ref);
mnb = group_row->panel->mnb;
num = gedit_multi_notebook_get_notebook_num (mnb, notebook);
name = g_strdup_printf (_("Tab Group %i"), num + 1);
gtk_label_set_text (GTK_LABEL (group_row->label), name);
g_free (name);
}
static void
group_row_update_names (GeditDocumentsPanel *panel,
GtkWidget *listbox)
{
GList *children;
GList *l;
GtkWidget *row;
children = gtk_container_get_children (GTK_CONTAINER (listbox));
for (l = children; l != NULL; l = g_list_next (l))
{
row = l->data;
if (GEDIT_IS_DOCUMENTS_GROUP_ROW (row))
{
group_row_set_notebook_name (row);
}
}
g_list_free (children);
}
static void
group_row_refresh_visibility (GeditDocumentsPanel *panel)
{
gboolean notebook_is_unique;
GtkWidget *first_group_row;
notebook_is_unique = gedit_multi_notebook_get_n_notebooks (panel->mnb) <= 1;
first_group_row = GTK_WIDGET (get_first_notebook_found (panel));
gtk_widget_set_no_show_all (first_group_row, notebook_is_unique);
gtk_widget_set_visible (first_group_row, !notebook_is_unique);
}
static gchar *
doc_get_name (GeditDocument *doc)
{
gchar *name;
gchar *docname;
name = gedit_document_get_short_name_for_display (doc);
/* Truncate the name so it doesn't get insanely wide. */
docname = gedit_utils_str_middle_truncate (name, MAX_DOC_NAME_LENGTH);
g_free (name);
return docname;
}
static void
document_row_sync_tab_name_and_icon (GeditTab *tab,
GParamSpec *pspec,
GtkWidget *row)
{
GeditDocumentsDocumentRow *document_row = GEDIT_DOCUMENTS_DOCUMENT_ROW (row);
GeditDocument *doc;
GtkSourceFile *file;
gchar *name;
GdkPixbuf *pixbuf;
doc = gedit_tab_get_document (tab);
name = doc_get_name (doc);
if (!gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc)))
{
gtk_label_set_text (GTK_LABEL (document_row->label), name);
}
else
{
gchar *markup;
markup = g_markup_printf_escaped ("<b>%s</b>", name);
gtk_label_set_markup (GTK_LABEL (document_row->label), markup);
g_free (markup);
}
g_free (name);
file = gedit_document_get_file (doc);
/* The status has as separate label to prevent ellipsizing */
if (!gtk_source_file_is_readonly (file))
{
gtk_widget_hide (GTK_WIDGET (document_row->status_label));
}
else
{
gchar *status;
status = g_strdup_printf ("[%s]", _("Read-Only"));
gtk_label_set_text (GTK_LABEL (document_row->status_label), status);
gtk_widget_show (GTK_WIDGET (document_row->status_label));
g_free (status);
}
/* Update header of the row */
pixbuf = _gedit_tab_get_icon (tab);
if (pixbuf)
{
gtk_image_set_from_pixbuf (GTK_IMAGE (document_row->image), pixbuf);
}
else
{
gtk_image_clear (GTK_IMAGE (document_row->image));
}
}
static void
refresh_notebook (GeditDocumentsPanel *panel,
GeditNotebook *notebook)
{
GList *tabs;
GList *l;
tabs = gtk_container_get_children (GTK_CONTAINER (notebook));
for (l = tabs; l != NULL; l = g_list_next (l))
{
GtkWidget *row;
row = gedit_documents_document_row_new (panel, GEDIT_TAB (l->data));
insert_row (panel, GTK_LIST_BOX (panel->listbox), row, -1);
panel->nb_row_tab += 1;
}
g_list_free (tabs);
}
static void
refresh_notebook_foreach (GeditNotebook *notebook,
GeditDocumentsPanel *panel)
{
GtkWidget *row;
row = gedit_documents_group_row_new (panel, notebook);
insert_row (panel, GTK_LIST_BOX (panel->listbox), row, -1);
panel->nb_row_notebook += 1;
group_row_refresh_visibility (panel);
refresh_notebook (panel, notebook);
}
static void
refresh_list (GeditDocumentsPanel *panel)
{
GList *children;
GList *l;
/* Clear the listbox */
children = gtk_container_get_children (GTK_CONTAINER (panel->listbox));
for (l = children; l != NULL; l = g_list_next (l))
{
GeditDocumentsGenericRow *row = l->data;
if (GEDIT_IS_DOCUMENTS_DOCUMENT_ROW (row))
{
GeditTab *tab = GEDIT_TAB (row->ref);
g_signal_handlers_disconnect_matched (tab,
G_SIGNAL_MATCH_FUNC,
0,
0,
NULL,
G_CALLBACK (document_row_sync_tab_name_and_icon),
NULL);
}
gtk_widget_destroy (GTK_WIDGET (row));
}
g_list_free (children);
gedit_multi_notebook_foreach_notebook (panel->mnb,
(GtkCallback)refresh_notebook_foreach,
panel);
select_active_tab (panel);
}
static void
multi_notebook_tab_removed (GeditMultiNotebook *mnb,
GeditNotebook *notebook,
GeditTab *tab,
GeditDocumentsPanel *panel)
{
GtkListBoxRow *row;
gedit_debug (DEBUG_PANEL);
row = get_row_from_widget (panel, GTK_WIDGET (tab));
/* Disconnect before destroy it so document_row_sync_tab_name_and_icon()
* don't get invalid data */
g_signal_handlers_disconnect_by_func (GEDIT_DOCUMENTS_DOCUMENT_ROW (row)->ref,
G_CALLBACK (document_row_sync_tab_name_and_icon),
row);
gtk_widget_destroy (GTK_WIDGET (row));
panel->nb_row_tab -= 1;
}
static gint
get_dest_position_for_tab (GeditDocumentsPanel *panel,
GeditNotebook *notebook,
GeditTab *tab)
{
gint page_num;
GList *children;
GList *item;
gint res = -1;
/* Get tab's position in notebook and notebook's position in GtkListBox
* then return future tab's position in GtkListBox */
page_num = gtk_notebook_page_num (GTK_NOTEBOOK (notebook), GTK_WIDGET (tab));
children = gtk_container_get_children (GTK_CONTAINER (panel->listbox));
item = g_list_find_custom (children, notebook, listbox_search_function);
if (item)
{
res = 1 + page_num + g_list_position (children, item);
}
g_list_free (children);
return res;
}
static void
multi_notebook_tab_added (GeditMultiNotebook *mnb,
GeditNotebook *notebook,
GeditTab *tab,
GeditDocumentsPanel *panel)
{
gint position;
GtkWidget *row;
gedit_debug (DEBUG_PANEL);
position = get_dest_position_for_tab (panel, notebook, tab);
if (position == -1)
{
panel->nb_row_tab = 0;
panel->nb_row_notebook = 0;
refresh_list (panel);
}
else
{
/* Add a new tab's row to the listbox */
row = gedit_documents_document_row_new (panel, tab);
insert_row (panel, GTK_LIST_BOX (panel->listbox), row, position);
panel->nb_row_tab += 1;
if (tab == gedit_multi_notebook_get_active_tab (mnb))
{
row_select (panel, GTK_LIST_BOX (panel->listbox), GTK_LIST_BOX_ROW (row));
}
}
}
static void
multi_notebook_notebook_removed (GeditMultiNotebook *mnb,
GeditNotebook *notebook,
GeditDocumentsPanel *panel)
{
GtkListBoxRow *row;
gedit_debug (DEBUG_PANEL);
row = get_row_from_widget (panel, GTK_WIDGET (notebook));
gtk_container_remove (GTK_CONTAINER (panel->listbox), GTK_WIDGET (row));
panel->nb_row_notebook -= 1;
group_row_refresh_visibility (panel);
group_row_update_names (panel, panel->listbox);
}
static void
row_move (GeditDocumentsPanel *panel,
GeditNotebook *notebook,
GtkWidget *tab,
GtkWidget *row)
{
gint position;
g_object_ref (row);
gtk_container_remove (GTK_CONTAINER (panel->listbox), GTK_WIDGET (row));
position = get_dest_position_for_tab (panel, notebook, GEDIT_TAB (tab));
g_signal_handler_block (panel->listbox, panel->selection_changed_handler_id);
gtk_list_box_insert (GTK_LIST_BOX (panel->listbox), row, position);
g_object_unref (row);
g_signal_handler_unblock (GTK_LIST_BOX (panel->listbox), panel->selection_changed_handler_id);
}
static void
multi_notebook_tabs_reordered (GeditMultiNotebook *mnb,
GeditNotebook *notebook,
GtkWidget *page,
gint page_num,
GeditDocumentsPanel *panel)
{
GtkListBoxRow *row;
gedit_debug (DEBUG_PANEL);
row = get_row_from_widget (panel, GTK_WIDGET (page));
row_move (panel, notebook, page, GTK_WIDGET (row));
row_select (panel, GTK_LIST_BOX (panel->listbox), GTK_LIST_BOX_ROW (row));
}
static void
set_window (GeditDocumentsPanel *panel,
GeditWindow *window)
{
panel->window = g_object_ref (window);
panel->mnb = GEDIT_MULTI_NOTEBOOK (_gedit_window_get_multi_notebook (window));
g_signal_connect (panel->mnb,
"notebook-removed",
G_CALLBACK (multi_notebook_notebook_removed),
panel);
g_signal_connect (panel->mnb,
"tab-added",
G_CALLBACK (multi_notebook_tab_added),
panel);
g_signal_connect (panel->mnb,
"tab-removed",
G_CALLBACK (multi_notebook_tab_removed),
panel);
g_signal_connect (panel->mnb,
"page-reordered",
G_CALLBACK (multi_notebook_tabs_reordered),
panel);
panel->tab_switched_handler_id = g_signal_connect (panel->mnb,
"switch-tab",
G_CALLBACK (multi_notebook_tab_switched),
panel);
panel->first_selection = TRUE;
refresh_list (panel);
group_row_refresh_visibility (panel);
}
static void
listbox_selection_changed (GtkListBox *listbox,
GtkListBoxRow *row,
GeditDocumentsPanel *panel)
{
if (row == NULL)
{
/* No selection on document panel */
return;
}
/* When the window is shown, the first notebook row is selected
* and therefore also shown - we don't want this */
if (panel->first_selection)
{
panel->first_selection = FALSE;
group_row_refresh_visibility (panel);
}
g_signal_handler_block (panel->mnb, panel->tab_switched_handler_id);
if (GEDIT_IS_DOCUMENTS_DOCUMENT_ROW (row))
{
gedit_multi_notebook_set_active_tab (panel->mnb,
GEDIT_TAB (GEDIT_DOCUMENTS_DOCUMENT_ROW (row)->ref));
panel->current_selection = GTK_WIDGET (row);
}
else if (GEDIT_IS_DOCUMENTS_GROUP_ROW (row) && panel->current_selection)
{
row_select (panel,
GTK_LIST_BOX (panel->listbox),
GTK_LIST_BOX_ROW (panel->current_selection));
}
else
{
g_assert_not_reached ();
}
g_signal_handler_unblock (panel->mnb, panel->tab_switched_handler_id);
}
static void
gedit_documents_panel_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GeditDocumentsPanel *panel = GEDIT_DOCUMENTS_PANEL (object);
switch (prop_id)
{
case PROP_WINDOW:
set_window (panel, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gedit_documents_panel_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GeditDocumentsPanel *panel = GEDIT_DOCUMENTS_PANEL (object);
switch (prop_id)
{
case PROP_WINDOW:
g_value_set_object (value, panel->window);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gedit_documents_panel_finalize (GObject *object)
{
GeditDocumentsPanel *panel = GEDIT_DOCUMENTS_PANEL (object);
g_signal_handlers_disconnect_by_func (panel->mnb,
G_CALLBACK (multi_notebook_notebook_removed),
panel);
g_signal_handlers_disconnect_by_func (panel->mnb,
G_CALLBACK (multi_notebook_tab_added),
panel);
g_signal_handlers_disconnect_by_func (panel->mnb,
G_CALLBACK (multi_notebook_tab_removed),
panel);
g_signal_handlers_disconnect_by_func (panel->mnb,
G_CALLBACK (multi_notebook_tabs_reordered),
panel);
g_signal_handlers_disconnect_by_func (panel->mnb,
G_CALLBACK (multi_notebook_tab_switched),
panel);
G_OBJECT_CLASS (gedit_documents_panel_parent_class)->finalize (object);
}
static void
gedit_documents_panel_dispose (GObject *object)
{
GeditDocumentsPanel *panel = GEDIT_DOCUMENTS_PANEL (object);
g_clear_object (&panel->window);
if (panel->source_targets)
{
gtk_target_list_unref (panel->source_targets);
panel->source_targets = NULL;
}
G_OBJECT_CLASS (gedit_documents_panel_parent_class)->dispose (object);
}
static GtkWidget *
create_placeholder_row (gint height)
{
GtkStyleContext *context;
GtkWidget *placeholder_row = gtk_list_box_row_new ();
context = gtk_widget_get_style_context (placeholder_row);
gtk_style_context_add_class (context, "gedit-document-panel-placeholder-row");
gtk_widget_set_size_request (placeholder_row, -1, height);
return placeholder_row;
}
static void
panel_on_drag_begin (GtkWidget *widget,
GdkDragContext *context)
{
GeditDocumentsPanel *panel = GEDIT_DOCUMENTS_PANEL (widget);
GtkWidget *drag_document_row;
GtkAllocation allocation;
const gchar *name;
GtkWidget *label;
gint width, height;
GtkWidget *image_box;
GtkWidget *box;
GtkStyleContext *style_context;
drag_document_row = panel->drag_document_row;
gtk_widget_get_allocation (drag_document_row, &allocation);
gtk_widget_hide (drag_document_row);
panel->document_row_height = allocation.height;
name = gtk_label_get_label (GTK_LABEL (GEDIT_DOCUMENTS_DOCUMENT_ROW (drag_document_row)->label));
label = gtk_label_new (NULL);
gtk_label_set_markup (GTK_LABEL (label), name);
gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &width, &height);
image_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_widget_set_size_request (image_box, width, height);
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
gtk_box_pack_start (GTK_BOX (box), image_box, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
panel->dnd_window = gtk_window_new (GTK_WINDOW_POPUP);
gtk_widget_set_size_request (panel->dnd_window, allocation.width, allocation.height);
gtk_window_set_screen (GTK_WINDOW (panel->dnd_window),
gtk_widget_get_screen (drag_document_row));
style_context = gtk_widget_get_style_context (panel->dnd_window);
gtk_style_context_add_class (style_context, "gedit-document-panel-dragged-row");
gtk_container_add (GTK_CONTAINER (panel->dnd_window), box);
gtk_widget_show_all (panel->dnd_window);
gtk_widget_set_opacity (panel->dnd_window, 0.8);
gtk_drag_set_icon_widget (context,
panel->dnd_window,
panel->drag_document_row_x,
panel->drag_document_row_y);
}
static gboolean
panel_on_drag_motion (GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
guint time)
{
GeditDocumentsPanel *panel = GEDIT_DOCUMENTS_PANEL (widget);
GeditDocumentsGenericRow *generic_row;
GtkWidget *source_panel;
gint dest_x, dest_y;
gint row_placeholder_index;
gint row_index;
GdkAtom target = gtk_drag_dest_find_target (widget, context, NULL);
if (target != gdk_atom_intern_static_string ("GEDIT_DOCUMENTS_DOCUMENT_ROW"))
{
gdk_drag_status (context, 0, time);
return FALSE;
}
gtk_widget_translate_coordinates (widget, panel->listbox,
x, y,
&dest_x, &dest_y);
generic_row = (GeditDocumentsGenericRow *)gtk_list_box_get_row_at_y (GTK_LIST_BOX (panel->listbox), dest_y);
source_panel = gtk_drag_get_source_widget (context);
if (!panel->row_placeholder)
{
if (!generic_row)
{
/* We don't have a row height to use, so use the source one */
panel->document_row_height = GEDIT_DOCUMENTS_PANEL (source_panel)->document_row_height;
}
else
{
GtkAllocation allocation;
gtk_widget_get_allocation (GTK_WIDGET (generic_row), &allocation);
panel->document_row_height = allocation.height;
}
panel->row_placeholder = create_placeholder_row (panel->document_row_height);
gtk_widget_show (panel->row_placeholder);
g_object_ref_sink (panel->row_placeholder);
}
else if (GTK_WIDGET (generic_row) == panel->row_placeholder)
{
/* cursor on placeholder */
gdk_drag_status (context, GDK_ACTION_MOVE, time);
return TRUE;
}
if (!generic_row)
{
/* cursor on empty space => put the placeholder at end of list */
GList *children = gtk_container_get_children (GTK_CONTAINER (panel->listbox));
row_placeholder_index = g_list_length (children);
g_list_free (children);
}
else
{
row_index = gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (generic_row));
gtk_widget_translate_coordinates (widget, GTK_WIDGET (generic_row),
x, y,
&dest_x, &dest_y);
if (dest_y <= panel->document_row_height / 2 && row_index > 0)
{
row_placeholder_index = row_index;
}
else
{
row_placeholder_index = row_index + 1;
}
}
if (source_panel == widget)
{
/* Adjustment because of hidden source row */
gint source_row_index = gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (panel->drag_document_row));
panel->row_source_row_offset = source_row_index < row_placeholder_index ? -1 : 0;
}
if (panel->row_placeholder_index != row_placeholder_index)
{
if (panel->row_placeholder_index != ROW_OUTSIDE_LISTBOX)
{
gtk_container_remove (GTK_CONTAINER (panel->listbox),
panel->row_placeholder);
if (panel->row_placeholder_index < row_placeholder_index)
{
/* Ajustment because of existing placeholder row */
row_placeholder_index -= 1;
}
}
panel->row_destination_index = panel->row_placeholder_index = row_placeholder_index;
gtk_list_box_insert (GTK_LIST_BOX (panel->listbox),
panel->row_placeholder,
panel->row_placeholder_index);
}
gdk_drag_status (context, GDK_ACTION_MOVE, time);
return TRUE;
}
static void
panel_on_drag_leave (GtkWidget *widget,
GdkDragContext *context,
guint time)
{
GeditDocumentsPanel *panel = GEDIT_DOCUMENTS_PANEL (widget);
if (panel->row_placeholder_index != ROW_OUTSIDE_LISTBOX)
{
gtk_container_remove (GTK_CONTAINER (panel->listbox), panel->row_placeholder);
panel->row_placeholder_index = ROW_OUTSIDE_LISTBOX;
}
}
static gboolean
panel_on_drag_drop (GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
guint time)
{
GeditDocumentsPanel *panel = GEDIT_DOCUMENTS_PANEL (widget);
GdkAtom target = gtk_drag_dest_find_target (widget, context, NULL);
GtkWidget *source_widget = gtk_drag_get_source_widget (context);
if (GEDIT_IS_DOCUMENTS_PANEL (source_widget))
{
gtk_widget_show (GEDIT_DOCUMENTS_PANEL (source_widget)->drag_document_row);
}
if (target == gdk_atom_intern_static_string ("GEDIT_DOCUMENTS_DOCUMENT_ROW"))
{
gtk_drag_get_data (widget, context, target, time);
return TRUE;
}
panel->row_placeholder_index = ROW_OUTSIDE_LISTBOX;
return FALSE;
}
static void
panel_on_drag_data_get (GtkWidget *widget,
GdkDragContext *context,
GtkSelectionData *data,
guint info,
guint time)
{
GeditDocumentsPanel *panel = GEDIT_DOCUMENTS_PANEL (widget);
GdkAtom target = gtk_selection_data_get_target (data);
GdkAtom result;
if (target == gdk_atom_intern_static_string ("GEDIT_DOCUMENTS_DOCUMENT_ROW"))
{
gtk_selection_data_set (data,
target,
8,
(void*)&panel->drag_document_row,
sizeof (gpointer));
return;
}
result = gtk_drag_dest_find_target (widget, context, panel->source_targets);
if (result != GDK_NONE)
{
GeditTab *tab;
GeditDocument *doc;
gchar *full_name;
tab = GEDIT_TAB (GEDIT_DOCUMENTS_DOCUMENT_ROW (panel->drag_document_row)->ref);
doc = gedit_tab_get_document (tab);
if (!gedit_document_is_untitled (doc))
{
GtkSourceFile *file = gedit_document_get_file (doc);
GFile *location = gtk_source_file_get_location (file);
full_name = g_file_get_parse_name (location);
gtk_selection_data_set (data,
target,
8,
(guchar *)full_name,
strlen (full_name));
g_free (full_name);
}
}
gtk_widget_show (panel->drag_document_row);
}
static GeditNotebook *
get_notebook_and_position_from_document_row (GeditDocumentsPanel *panel,
gint row_index,
gint *position)
{
GList *l;
gint index = 0;
GeditDocumentsGroupRow *row;
GList *children = gtk_container_get_children (GTK_CONTAINER (panel->listbox));
gint nb_elements = g_list_length (children);
if (nb_elements == 1)
{
row = children->data;
}
else
{
l = g_list_nth (children, row_index - 1);
while (TRUE)
{
row = l->data;
if (GEDIT_IS_DOCUMENTS_GROUP_ROW (row))
{
break;
}
l = g_list_previous (l);
index += 1;
}
}
g_list_free (children);
*position = index;
return GEDIT_NOTEBOOK (row->ref);
}
static void
panel_on_drag_data_received (GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
GtkSelectionData *data,
guint info,
guint time)
{
GeditDocumentsPanel *panel = GEDIT_DOCUMENTS_PANEL (widget);
GeditDocumentsPanel *source_panel = NULL;
GtkWidget *source_widget = gtk_drag_get_source_widget (context);
if (GEDIT_IS_DOCUMENTS_PANEL (source_widget))
{
source_panel = GEDIT_DOCUMENTS_PANEL (source_widget);
}
GtkWidget **source_row = (void*) gtk_selection_data_get_data (data);
if (source_panel &&
gtk_selection_data_get_target (data) == gdk_atom_intern_static_string ("GEDIT_DOCUMENTS_DOCUMENT_ROW"))
{
gint source_index = gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (*source_row));
/* And finally, we can move the row */
if (source_panel != panel ||
(panel->row_destination_index != source_index &&
panel->row_destination_index != source_index + 1))
{
GeditNotebook *old_notebook, *new_notebook;
gint position;
GeditTab *tab = GEDIT_TAB (GEDIT_DOCUMENTS_DOCUMENT_ROW (*source_row)->ref);
old_notebook = gedit_multi_notebook_get_notebook_for_tab (source_panel->mnb, tab);
new_notebook = get_notebook_and_position_from_document_row (panel,
panel->row_destination_index,
&position);
if (old_notebook == new_notebook)
{
gtk_widget_show (*source_row);
gtk_notebook_reorder_child (GTK_NOTEBOOK (new_notebook),
GTK_WIDGET (tab),
position + panel->row_source_row_offset);
}
else
{
gedit_notebook_move_tab (old_notebook, new_notebook, tab, position);
}
if (tab != gedit_multi_notebook_get_active_tab (panel->mnb))
{
g_signal_handler_block (panel->mnb, panel->tab_switched_handler_id);
gedit_multi_notebook_set_active_tab (panel->mnb, tab);
g_signal_handler_unblock (panel->mnb, panel->tab_switched_handler_id);
}
}
gtk_drag_finish (context, TRUE, FALSE, time);
}
else
{
gtk_drag_finish (context, FALSE, FALSE, time);
}
panel->row_destination_index = panel->row_placeholder_index = ROW_OUTSIDE_LISTBOX;
if (panel->row_placeholder)
{
gtk_widget_destroy (panel->row_placeholder);
panel->row_placeholder = NULL;
}
}
static void
panel_on_drag_end (GtkWidget *widget,
GdkDragContext *context)
{
GeditDocumentsPanel *panel = GEDIT_DOCUMENTS_PANEL (widget);
panel->drag_document_row = NULL;
panel->is_on_drag = FALSE;
gtk_widget_destroy (panel->dnd_window);
panel->dnd_window = NULL;
}
static gboolean
panel_on_drag_failed (GtkWidget *widget,
GdkDragContext *context,
GtkDragResult result)
{
GtkWidget *source_widget = gtk_drag_get_source_widget (context);
if (GEDIT_IS_DOCUMENTS_PANEL (source_widget))
{
gtk_widget_show (GEDIT_DOCUMENTS_PANEL (source_widget)->drag_document_row);
}
return FALSE;
}
static gboolean
panel_on_motion_notify (GtkWidget *widget,
GdkEventMotion *event)
{
GeditDocumentsPanel *panel = GEDIT_DOCUMENTS_PANEL (widget);
if (panel->drag_document_row == NULL || panel->is_on_drag)
{
return FALSE;
}
if (!(event->state & GDK_BUTTON1_MASK))
{
panel->drag_document_row = NULL;
return FALSE;
}
if (gtk_drag_check_threshold (widget,
panel->drag_root_x, panel->drag_root_y,
event->x_root, event->y_root))
{
panel->is_on_drag = TRUE;
gtk_drag_begin_with_coordinates (widget, panel->source_targets, GDK_ACTION_MOVE,
GDK_BUTTON_PRIMARY, (GdkEvent*)event,
-1, -1);
}
return FALSE;
}
static void
gedit_documents_panel_class_init (GeditDocumentsPanelClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->finalize = gedit_documents_panel_finalize;
object_class->dispose = gedit_documents_panel_dispose;
object_class->get_property = gedit_documents_panel_get_property;
object_class->set_property = gedit_documents_panel_set_property;
widget_class->motion_notify_event = panel_on_motion_notify;
widget_class->drag_begin = panel_on_drag_begin;
widget_class->drag_end = panel_on_drag_end;
widget_class->drag_failed = panel_on_drag_failed;
widget_class->drag_motion = panel_on_drag_motion;
widget_class->drag_leave = panel_on_drag_leave;
widget_class->drag_drop = panel_on_drag_drop;
widget_class->drag_data_get = panel_on_drag_data_get;
widget_class->drag_data_received = panel_on_drag_data_received;
properties[PROP_WINDOW] =
g_param_spec_object ("window",
"Window",
"The GeditWindow this GeditDocumentsPanel is associated with",
GEDIT_TYPE_WINDOW,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, LAST_PROP, properties);
}
static void
gedit_documents_panel_init (GeditDocumentsPanel *panel)
{
GtkWidget *sw;
GtkStyleContext *context;
gedit_debug (DEBUG_PANEL);
gtk_orientable_set_orientation (GTK_ORIENTABLE (panel),
GTK_ORIENTATION_VERTICAL);
/* Create the scrolled window */
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_widget_show (sw);
gtk_box_pack_start (GTK_BOX (panel), sw, TRUE, TRUE, 0);
/* Create the listbox */
panel->listbox = gtk_list_box_new ();
gtk_container_add (GTK_CONTAINER (sw), panel->listbox);
panel->adjustment = gtk_list_box_get_adjustment (GTK_LIST_BOX (panel->listbox));
/* Disable focus so it doesn't steal focus each time from the view */
gtk_widget_set_can_focus (panel->listbox, FALSE);
/* Css style */
context = gtk_widget_get_style_context (panel->listbox);
gtk_style_context_add_class (context, "gedit-document-panel");
panel->selection_changed_handler_id = g_signal_connect (panel->listbox,
"row-selected",
G_CALLBACK (listbox_selection_changed),
panel);
panel->is_in_tab_switched = FALSE;
panel->current_selection = NULL;
panel->nb_row_notebook = 0;
panel->nb_row_tab = 0;
/* Drag and drop support */
panel->source_targets = gtk_target_list_new (panel_targets, G_N_ELEMENTS (panel_targets));
gtk_target_list_add_text_targets (panel->source_targets, 0);
gtk_drag_dest_set (GTK_WIDGET (panel), 0,
panel_targets, G_N_ELEMENTS (panel_targets),
GDK_ACTION_MOVE);
gtk_drag_dest_set_track_motion (GTK_WIDGET (panel), TRUE);
panel->drag_document_row = NULL;
panel->row_placeholder = NULL;
panel->row_placeholder_index = ROW_OUTSIDE_LISTBOX;
panel->row_destination_index = ROW_OUTSIDE_LISTBOX;
panel->row_source_row_offset = 0;
panel->is_on_drag = FALSE;
}
GtkWidget *
gedit_documents_panel_new (GeditWindow *window)
{
g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL);
return g_object_new (GEDIT_TYPE_DOCUMENTS_PANEL,
"window", window,
NULL);
}
static void
row_on_close_button_clicked (GtkWidget *close_button,
GtkWidget *row)
{
GeditDocumentsGenericRow *generic_row = (GeditDocumentsGenericRow *)row;
GeditWindow *window = generic_row->panel->window;
GtkWidget *ref;
if (GEDIT_IS_DOCUMENTS_GROUP_ROW (row))
{
ref = GEDIT_DOCUMENTS_GROUP_ROW (row)->ref;
_gedit_cmd_file_close_notebook (window, GEDIT_NOTEBOOK (ref));
}
else if (GEDIT_IS_DOCUMENTS_DOCUMENT_ROW (row))
{
ref = GEDIT_DOCUMENTS_DOCUMENT_ROW (row)->ref;
_gedit_cmd_file_close_tab (GEDIT_TAB (ref), window);
}
else
{
g_assert_not_reached ();
}
}
static gboolean
row_on_button_pressed (GtkWidget *row_event_box,
GdkEventButton *event,
GtkWidget *row)
{
if (gdk_event_get_event_type ((GdkEvent *)event) == GDK_BUTTON_PRESS &&
GEDIT_IS_DOCUMENTS_DOCUMENT_ROW (row))
{
GeditDocumentsDocumentRow *document_row = GEDIT_DOCUMENTS_DOCUMENT_ROW (row);
GeditDocumentsPanel *panel = document_row->panel;
if (event->button == GDK_BUTTON_PRIMARY)
{
/* memorize row and clicked position for possible drag'n drop */
panel->drag_document_row = row;
panel->drag_document_row_x = (gint)event->x;
panel->drag_document_row_y = (gint)event->y;
panel->drag_root_x = event->x_root;
panel->drag_root_y = event->y_root;
return FALSE;
}
panel->drag_document_row = NULL;
if (gdk_event_triggers_context_menu ((GdkEvent *)event))
{
GeditWindow *window = panel->window;
GeditTab *tab = GEDIT_TAB (document_row->ref);
GtkWidget *menu = gedit_notebook_popup_menu_new (window, tab);
g_signal_connect (menu,
"selection-done",
G_CALLBACK (gtk_widget_destroy),
NULL);
gtk_menu_popup_for_device (GTK_MENU (menu),
gdk_event_get_device ((GdkEvent *)event),
NULL, NULL,
NULL, NULL, NULL,
event->button,
event->time);
return TRUE;
}
}
return FALSE;
}
static void
document_row_create_header (GtkWidget *row)
{
GeditDocumentsDocumentRow *document_row = GEDIT_DOCUMENTS_DOCUMENT_ROW (row);
GtkWidget *image_box;
gint width, height;
gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &width, &height);
image_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_widget_set_size_request (image_box, width, height);
document_row->image = gtk_image_new ();
gtk_container_add (GTK_CONTAINER (image_box), document_row->image);
gtk_box_pack_start (GTK_BOX (document_row->box),
image_box, FALSE, FALSE, 0);
/* Set the header on front of all other widget in the row */
gtk_box_reorder_child (GTK_BOX (document_row->box),
image_box, 0);
gtk_widget_show_all (image_box);
}
static GtkWidget *
row_create (GtkWidget *row)
{
GeditDocumentsGenericRow *generic_row = (GeditDocumentsGenericRow *)row;
GtkWidget *event_box;
GtkStyleContext *context;
GtkWidget *image;
GIcon *icon;
gedit_debug (DEBUG_PANEL);
event_box = gtk_event_box_new ();
generic_row->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
gtk_container_add (GTK_CONTAINER (event_box), generic_row->box);
generic_row->label = gtk_label_new (NULL);
gtk_label_set_ellipsize (GTK_LABEL (generic_row->label), PANGO_ELLIPSIZE_END);
gtk_widget_set_halign (generic_row->label, GTK_ALIGN_START);
gtk_widget_set_valign (generic_row->label, GTK_ALIGN_CENTER);
generic_row->status_label = gtk_label_new (NULL);
gtk_widget_set_halign (generic_row->status_label, GTK_ALIGN_END);
gtk_widget_set_valign (generic_row->status_label, GTK_ALIGN_CENTER);
generic_row->close_button = GTK_WIDGET (g_object_new (GTK_TYPE_BUTTON,
"relief", GTK_RELIEF_NONE,
"focus-on-click", FALSE,
NULL));
context = gtk_widget_get_style_context (generic_row->close_button);
gtk_style_context_add_class (context, "flat");
gtk_style_context_add_class (context, "small-button");
icon = g_themed_icon_new_with_default_fallbacks ("window-close-symbolic");
image = gtk_image_new_from_gicon (icon, GTK_ICON_SIZE_MENU);
gtk_widget_show (image);
g_object_unref (icon);
gtk_container_add (GTK_CONTAINER (generic_row->close_button), image);
gtk_box_pack_start (GTK_BOX (generic_row->box),
generic_row->label, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (generic_row->box),
generic_row->status_label, FALSE, FALSE, 0);
gtk_box_pack_end (GTK_BOX (generic_row->box),
generic_row->close_button, FALSE, FALSE, 0);
g_signal_connect (event_box,
"button-press-event",
G_CALLBACK (row_on_button_pressed),
row);
g_signal_connect (generic_row->close_button,
"clicked",
G_CALLBACK (row_on_close_button_clicked),
row);
gtk_widget_set_no_show_all (generic_row->status_label, TRUE);
gtk_widget_show_all (event_box);
return event_box;
}
static gboolean
document_row_query_tooltip (GtkWidget *row,
gint x,
gint y,
gboolean keyboard_tip,
GtkTooltip *tooltip)
{
GeditDocumentsGenericRow *generic_row = (GeditDocumentsGenericRow *)row;
gchar *markup;
if (!GEDIT_IS_DOCUMENTS_DOCUMENT_ROW (row))
{
return FALSE;
}
markup = _gedit_tab_get_tooltip (GEDIT_TAB (generic_row->ref));
gtk_tooltip_set_markup (tooltip, markup);
g_free (markup);
return TRUE;
}
/* Gedit Document Row */
static void
gedit_documents_document_row_class_init (GeditDocumentsDocumentRowClass *klass)
{
}
static void
gedit_documents_document_row_init (GeditDocumentsDocumentRow *row)
{
GtkWidget *row_widget;
GtkStyleContext *context;
gedit_debug (DEBUG_PANEL);
row_widget = row_create (GTK_WIDGET (row));
gtk_container_add (GTK_CONTAINER (row), row_widget);
document_row_create_header (GTK_WIDGET (row));
gtk_widget_set_has_tooltip (GTK_WIDGET (row), TRUE);
/* Css style */
context = gtk_widget_get_style_context (GTK_WIDGET (row));
gtk_style_context_add_class (context, "gedit-document-panel-document-row");
gtk_widget_show_all (GTK_WIDGET (row));
gtk_widget_set_can_focus (GTK_WIDGET (row), FALSE);
}
/* Gedit Group Row */
static void
gedit_documents_group_row_class_init (GeditDocumentsGroupRowClass *klass)
{
}
static void
gedit_documents_group_row_init (GeditDocumentsGroupRow *row)
{
GtkWidget *row_widget;
GtkStyleContext *context;
gedit_debug (DEBUG_PANEL);
row_widget = row_create (GTK_WIDGET (row));
gtk_container_add (GTK_CONTAINER (row), row_widget);
/* Css style */
context = gtk_widget_get_style_context (GTK_WIDGET (row));
gtk_style_context_add_class (context, "gedit-document-panel-group-row");
gtk_widget_show_all (GTK_WIDGET (row));
gtk_widget_set_can_focus (GTK_WIDGET (row), FALSE);
}
static GtkWidget *
gedit_documents_document_row_new (GeditDocumentsPanel *panel,
GeditTab *tab)
{
GeditDocumentsDocumentRow *row;
g_return_val_if_fail (GEDIT_IS_DOCUMENTS_PANEL (panel), NULL);
g_return_val_if_fail (GEDIT_IS_TAB (tab), NULL);
gedit_debug (DEBUG_PANEL);
row = g_object_new (GEDIT_TYPE_DOCUMENTS_DOCUMENT_ROW, NULL);
row->ref = GTK_WIDGET (tab);
row->panel = panel;
g_signal_connect (row->ref,
"notify::name",
G_CALLBACK (document_row_sync_tab_name_and_icon),
row);
g_signal_connect (row->ref,
"notify::state",
G_CALLBACK (document_row_sync_tab_name_and_icon),
row);
g_signal_connect (row,
"query-tooltip",
G_CALLBACK (document_row_query_tooltip),
NULL);
document_row_sync_tab_name_and_icon (GEDIT_TAB (row->ref), NULL, GTK_WIDGET (row));
return GTK_WIDGET (row);
}
static GtkWidget *
gedit_documents_group_row_new (GeditDocumentsPanel *panel,
GeditNotebook *notebook)
{
GeditDocumentsGroupRow *row;
g_return_val_if_fail (GEDIT_IS_DOCUMENTS_PANEL (panel), NULL);
g_return_val_if_fail (GEDIT_IS_NOTEBOOK (notebook), NULL);
gedit_debug (DEBUG_PANEL);
row = g_object_new (GEDIT_TYPE_DOCUMENTS_GROUP_ROW, NULL);
row->ref = GTK_WIDGET (notebook);
row->panel = panel;
group_row_set_notebook_name (GTK_WIDGET (row));
return GTK_WIDGET (row);
}
/* ex:set ts=8 noet: */