gedit-notebook.c 18.5 KB
Newer Older
Paolo Borelli's avatar
Paolo Borelli committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
/*
 * gedit-notebook.c
 * This file is part of gedit
 *
 * Copyright (C) 2005 - Paolo Maggi 
 *
 * 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, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, 
 * Boston, MA 02111-1307, USA.
 */
 
/*
 * Modified by the gedit Team, 2005. See the AUTHORS file for a 
 * list of people on the gedit Team.  
 * See the ChangeLog files for a list of changes. 
 */

/* This file is a modified version of the epiphany file ephy-notebook.c
 * Here the relevant copyright:
 *
 *  Copyright (C) 2002 Christophe Fergeau
 *  Copyright (C) 2003 Marco Pesenti Gritti
 *  Copyright (C) 2003, 2004 Christian Persch
 *
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <glib-object.h>
#include <glib/gi18n.h>
44
#include <gtk/gtk.h>
Paolo Borelli's avatar
Paolo Borelli committed
45 46

#include "gedit-notebook.h"
47 48
#include "gedit-tab.h"
#include "gedit-tab-label.h"
Paolo Borelli's avatar
Paolo Borelli committed
49
#include "gedit-window.h"
50 51
#include "gedit-enum-types.h"
#include "gedit-settings.h"
52
#include "gedit-marshal.h"
53

Paolo Borelli's avatar
Paolo Borelli committed
54 55
#define GEDIT_NOTEBOOK_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GEDIT_TYPE_NOTEBOOK, GeditNotebookPrivate))

56 57
#define GEDIT_NOTEBOOK_GROUP_NAME "GeditNotebookGroup"

Paolo Borelli's avatar
Paolo Borelli committed
58 59
struct _GeditNotebookPrivate
{
60 61
	GSettings     *ui_settings;

Paolo Borelli's avatar
Paolo Borelli committed
62
	GList         *focused_pages;
63 64 65

	GeditNotebookShowTabsModeType show_tabs_mode;

66 67
	GtkCssProvider *css;

68 69
	guint close_buttons_sensitive : 1;
	guint ignore_focused_page_update : 1;
Paolo Borelli's avatar
Paolo Borelli committed
70 71 72 73
};

G_DEFINE_TYPE(GeditNotebook, gedit_notebook, GTK_TYPE_NOTEBOOK)

74 75 76 77 78 79 80
/* Properties */
enum
{
	PROP_0,
	PROP_SHOW_TABS_MODE
};

Paolo Borelli's avatar
Paolo Borelli committed
81 82 83 84
/* Signals */
enum
{
	TAB_CLOSE_REQUEST,
85
	SHOW_POPUP_MENU,
Paolo Borelli's avatar
Paolo Borelli committed
86 87 88 89 90
	LAST_SIGNAL
};

static guint signals[LAST_SIGNAL] = { 0 };

91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
static void
update_tabs_visibility (GeditNotebook *notebook,
			gboolean       before_inserting)
{
	gboolean show_tabs;

	switch (notebook->priv->show_tabs_mode)
	{
		case GEDIT_NOTEBOOK_SHOW_TABS_NEVER:
			show_tabs = FALSE;
			break;
		case GEDIT_NOTEBOOK_SHOW_TABS_AUTO:
			{
				guint num;

				num = gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook));

				if (before_inserting)
					++num;

				show_tabs = num > 1;
			}
			break;
		case GEDIT_NOTEBOOK_SHOW_TABS_ALWAYS:
		default:
			show_tabs = TRUE;
			break;
	}

	gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook), show_tabs);
}

static void
gedit_notebook_get_property (GObject    *object,
			     guint       prop_id,
			     GValue     *value,
			     GParamSpec *pspec)
{
	GeditNotebook *notebook = GEDIT_NOTEBOOK (object);

	switch (prop_id)
	{
		case PROP_SHOW_TABS_MODE:
			g_value_set_enum (value,
					  notebook->priv->show_tabs_mode);
			break;
		default:
			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
			break;
	}
}

static void
gedit_notebook_set_property (GObject      *object,
			     guint         prop_id,
			     const GValue *value,
			     GParamSpec   *pspec)
{
	GeditNotebook *notebook = GEDIT_NOTEBOOK (object);

	switch (prop_id)
	{
		case PROP_SHOW_TABS_MODE:
			notebook->priv->show_tabs_mode = g_value_get_enum (value);
			update_tabs_visibility (notebook, FALSE);
			break;
		default:
			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
			break;
	}
}

static void
gedit_notebook_dispose (GObject *object)
{
	GeditNotebook *notebook = GEDIT_NOTEBOOK (object);

168 169
	g_clear_object (&notebook->priv->ui_settings);
	g_clear_object (&notebook->priv->css);
170

171 172 173
	G_OBJECT_CLASS (gedit_notebook_parent_class)->dispose (object);
}

174 175 176 177 178 179 180 181 182 183
static void
gedit_notebook_finalize (GObject *object)
{
	GeditNotebook *notebook = GEDIT_NOTEBOOK (object);

	g_list_free (notebook->priv->focused_pages);

	G_OBJECT_CLASS (gedit_notebook_parent_class)->finalize (object);
}

184 185 186 187 188 189 190 191 192 193 194 195 196
static void
gedit_notebook_grab_focus (GtkWidget *widget)
{
	GtkNotebook *nb = GTK_NOTEBOOK (widget);
	GtkWidget *tab;
	gint current_page;

	current_page = gtk_notebook_get_current_page (nb);
	tab = gtk_notebook_get_nth_page (nb, current_page);

	gtk_widget_grab_focus (tab);
}

197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
static gint
find_tab_num_at_pos (GtkNotebook *notebook,
                     gint         screen_x,
                     gint         screen_y)
{
	GtkNotebook *nb = GTK_NOTEBOOK (notebook);
	GtkPositionType tab_pos;
	GtkWidget *page;
	GtkAllocation tab_allocation;
	gint page_num = 0;

	tab_pos = gtk_notebook_get_tab_pos (GTK_NOTEBOOK (notebook));

	while ((page = gtk_notebook_get_nth_page (nb, page_num)))
	{
		GtkWidget *tab;
		gint max_x, max_y, x_root, y_root;

		tab = gtk_notebook_get_tab_label (nb, page);
		g_return_val_if_fail (tab != NULL, -1);

		if (!gtk_widget_get_mapped (GTK_WIDGET (tab)))
		{
			page_num++;
			continue;
		}

		gdk_window_get_origin (gtk_widget_get_window (tab), &x_root, &y_root);

		gtk_widget_get_allocation (tab, &tab_allocation);
		max_x = x_root + tab_allocation.x + tab_allocation.width;
		max_y = y_root + tab_allocation.y + tab_allocation.height;

		if ((tab_pos == GTK_POS_TOP || tab_pos == GTK_POS_BOTTOM) && screen_x <= max_x)
		{
			return page_num;
		}

		if ((tab_pos == GTK_POS_LEFT || tab_pos == GTK_POS_RIGHT) && screen_y <= max_y)
		{
			return page_num;
		}

		page_num++;
	}

	return -1;
}

static gboolean
247
gedit_notebook_button_press (GtkWidget      *widget,
248 249 250 251
                             GdkEventButton *event)
{
	GtkNotebook *nb = GTK_NOTEBOOK (widget);

252
	if (event->type == GDK_BUTTON_PRESS &&
253
	    event->button == GDK_BUTTON_SECONDARY &&
254
	    (event->state & gtk_accelerator_get_default_mod_mask ()) == 0)
255
	{
256
		gint tab_clicked;
257

258 259 260
		tab_clicked = find_tab_num_at_pos (nb, event->x_root, event->y_root);
		if (tab_clicked >= 0)
		{
261
			GtkWidget *tab;
262

263 264 265
			tab = gtk_notebook_get_nth_page (nb, tab_clicked);

			g_signal_emit (G_OBJECT (widget), signals[SHOW_POPUP_MENU], 0, event, tab);
266

267 268 269
			return TRUE;
		}
	}
270

271
	return GTK_WIDGET_CLASS (gedit_notebook_parent_class)->button_press_event (widget, event);
272 273
}

274 275 276 277 278 279 280
/*
 * We need to override this because when we don't show the tabs, like in
 * fullscreen we need to have wrap around too
 */
static gboolean
gedit_notebook_change_current_page (GtkNotebook *notebook,
				    gint         offset)
Paolo Borelli's avatar
Paolo Borelli committed
281
{
282 283
	gboolean wrap_around;
	gint current;
Paolo Borelli's avatar
Paolo Borelli committed
284

285
	current = gtk_notebook_get_current_page (notebook);
Paolo Borelli's avatar
Paolo Borelli committed
286

287
	if (current != -1)
288
	{
289
		current = current + offset;
290

291 292 293 294 295
		g_object_get (gtk_widget_get_settings (GTK_WIDGET (notebook)),
			      "gtk-keynav-wrap-around", &wrap_around,
			      NULL);

		if (wrap_around)
296
		{
297 298 299 300 301 302 303 304
			if (current < 0)
			{
				current = gtk_notebook_get_n_pages (notebook) - 1;
			}
			else if (current >= gtk_notebook_get_n_pages (notebook))
			{
				current = 0;
			}
305 306
		}

307
		gtk_notebook_set_current_page (notebook, current);
308
	}
309
	else
Paolo Borelli's avatar
Paolo Borelli committed
310
	{
311
		gtk_widget_error_bell (GTK_WIDGET (notebook));
Paolo Borelli's avatar
Paolo Borelli committed
312 313
	}

314
	return TRUE;
Paolo Borelli's avatar
Paolo Borelli committed
315 316
}

317 318 319 320
static void
gedit_notebook_switch_page (GtkNotebook *notebook,
                            GtkWidget   *page,
                            guint        page_num)
Paolo Borelli's avatar
Paolo Borelli committed
321
{
322
	GeditNotebook *nb = GEDIT_NOTEBOOK (notebook);
Paolo Borelli's avatar
Paolo Borelli committed
323

324
	if (!nb->priv->ignore_focused_page_update)
Paolo Borelli's avatar
Paolo Borelli committed
325
	{
326 327 328 329 330 331
		gint prev_page;
		GtkWidget *previous_page;

		prev_page = gtk_notebook_get_current_page (notebook);
		previous_page = gtk_notebook_get_nth_page (notebook, prev_page);

332 333 334 335 336
		/* Remove the old page, we dont want to grow unnecessarily
		 * the list */
		if (nb->priv->focused_pages)
		{
			nb->priv->focused_pages =
337
				g_list_remove (nb->priv->focused_pages, previous_page);
338
		}
Paolo Borelli's avatar
Paolo Borelli committed
339

340
		nb->priv->focused_pages = g_list_append (nb->priv->focused_pages,
341
		                                         previous_page);
342
	}
Paolo Borelli's avatar
Paolo Borelli committed
343

344 345
	GTK_NOTEBOOK_CLASS (gedit_notebook_parent_class)->switch_page (notebook, page, page_num);

346 347
	/* give focus to the tab */
	gtk_widget_grab_focus (page);
Paolo Borelli's avatar
Paolo Borelli committed
348 349
}

350 351 352
static void
on_tab_label_destroyed (GtkWidget *tab_label,
                        GeditTab  *tab)
Paolo Borelli's avatar
Paolo Borelli committed
353
{
354
	g_object_set_data (G_OBJECT (tab), "tab-label", NULL);
Paolo Borelli's avatar
Paolo Borelli committed
355 356
}

357 358
static void
close_button_clicked_cb (GeditTabLabel *tab_label, GeditNotebook *notebook)
Paolo Borelli's avatar
Paolo Borelli committed
359
{
360
	GeditTab *tab;
Paolo Borelli's avatar
Paolo Borelli committed
361

362 363
	tab = gedit_tab_label_get_tab (tab_label);
	g_signal_emit (notebook, signals[TAB_CLOSE_REQUEST], 0, tab);
Paolo Borelli's avatar
Paolo Borelli committed
364 365
}

366 367 368
static void
smart_tab_switching_on_closure (GeditNotebook *nb,
				GeditTab      *tab)
Paolo Borelli's avatar
Paolo Borelli committed
369
{
370
	if (nb->priv->focused_pages)
Paolo Borelli's avatar
Paolo Borelli committed
371
	{
372 373
		GList *l;
		GtkWidget *child;
374
		gint page_num;
375 376 377 378

		/* activate the last focused tab */
		l = g_list_last (nb->priv->focused_pages);
		child = GTK_WIDGET (l->data);
379

380 381
		page_num = gtk_notebook_page_num (GTK_NOTEBOOK (nb),
		                                  child);
382

383 384
		gtk_notebook_set_current_page (GTK_NOTEBOOK (nb),
		                               page_num);
Paolo Borelli's avatar
Paolo Borelli committed
385 386 387
	}
}

388 389
static GtkWidget *
get_tab_label (GeditTab *tab)
Paolo Borelli's avatar
Paolo Borelli committed
390
{
391
	GObject *tab_label;
Paolo Borelli's avatar
Paolo Borelli committed
392

393 394 395
	tab_label = g_object_get_data (G_OBJECT (tab), "tab-label");

	return (tab_label != NULL) ? GTK_WIDGET (tab_label) : NULL;
Paolo Borelli's avatar
Paolo Borelli committed
396 397 398
}

static void
399 400 401
gedit_notebook_page_removed (GtkNotebook *notebook,
                             GtkWidget   *page,
                             guint        page_num)
Paolo Borelli's avatar
Paolo Borelli committed
402
{
403 404 405 406
	GeditNotebook *nb = GEDIT_NOTEBOOK (notebook);
	gint num_pages;
	gint curr;
	GtkWidget *tab_label;
Paolo Borelli's avatar
Paolo Borelli committed
407

408
	tab_label = get_tab_label (GEDIT_TAB (page));
Paolo Borelli's avatar
Paolo Borelli committed
409

410
	if (tab_label != NULL)
Paolo Borelli's avatar
Paolo Borelli committed
411
	{
412 413 414 415 416 417
		g_signal_handlers_disconnect_by_func (tab_label,
		                                      G_CALLBACK (on_tab_label_destroyed),
		                                      page);
		g_signal_handlers_disconnect_by_func (tab_label,
		                                      G_CALLBACK (close_button_clicked_cb),
		                                      nb);
Paolo Borelli's avatar
Paolo Borelli committed
418 419
	}

420 421 422
	/* Remove the page from the focused pages list */
	nb->priv->focused_pages =  g_list_remove (nb->priv->focused_pages,
	                                          page);
Paolo Borelli's avatar
Paolo Borelli committed
423

424
	curr = gtk_notebook_get_current_page (notebook);
Paolo Borelli's avatar
Paolo Borelli committed
425

426 427 428
	if (page_num == curr)
	{
		smart_tab_switching_on_closure (nb, GEDIT_TAB (page));
Paolo Borelli's avatar
Paolo Borelli committed
429 430
	}

431
	num_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (nb));
Paolo Borelli's avatar
Paolo Borelli committed
432

433 434
	/* If there is no tabs, calling this is pointless */
	if (num_pages > 0)
Paolo Borelli's avatar
Paolo Borelli committed
435
	{
436
		update_tabs_visibility (nb, FALSE);
Paolo Borelli's avatar
Paolo Borelli committed
437 438 439 440
	}
}

static void
441 442 443
gedit_notebook_page_added (GtkNotebook *notebook,
                           GtkWidget   *page,
                           guint        page_num)
Paolo Borelli's avatar
Paolo Borelli committed
444
{
445 446
	GeditNotebook *nb = GEDIT_NOTEBOOK (notebook);
	GtkWidget *tab_label;
Paolo Borelli's avatar
Paolo Borelli committed
447

448
	tab_label = get_tab_label (GEDIT_TAB (page));
Paolo Borelli's avatar
Paolo Borelli committed
449

450 451 452 453
	g_signal_connect (tab_label,
	                  "destroy",
	                  G_CALLBACK (on_tab_label_destroyed),
	                  page);
Paolo Borelli's avatar
Paolo Borelli committed
454

455 456 457 458
	g_signal_connect (tab_label,
	                  "close-clicked",
	                  G_CALLBACK (close_button_clicked_cb),
	                  nb);
459 460

	update_tabs_visibility (GEDIT_NOTEBOOK (notebook), FALSE);
Paolo Borelli's avatar
Paolo Borelli committed
461 462
}

463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482
static void
gedit_notebook_remove (GtkContainer *container,
                       GtkWidget    *widget)
{
	GeditNotebook *nb;

	/* This is where GtkNotebook will remove the page. By doing so, it
	   will also switch to a new page, messing up our focus list. So we
	   set a flag here to ignore the switch temporarily */

	nb = GEDIT_NOTEBOOK (container);

	nb->priv->ignore_focused_page_update = TRUE;

	GTK_CONTAINER_CLASS (gedit_notebook_parent_class)->remove (container,
	                                                           widget);

	nb->priv->ignore_focused_page_update = FALSE;
}

483 484
static void
gedit_notebook_class_init (GeditNotebookClass *klass)
Paolo Borelli's avatar
Paolo Borelli committed
485
{
486 487 488
	GObjectClass *object_class = G_OBJECT_CLASS (klass);
	GtkWidgetClass *gtkwidget_class = GTK_WIDGET_CLASS (klass);
	GtkNotebookClass *notebook_class = GTK_NOTEBOOK_CLASS (klass);
489
	GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
Paolo Borelli's avatar
Paolo Borelli committed
490

491 492 493 494
	object_class->dispose = gedit_notebook_dispose;
	object_class->finalize = gedit_notebook_finalize;
	object_class->get_property = gedit_notebook_get_property;
	object_class->set_property = gedit_notebook_set_property;
Paolo Borelli's avatar
Paolo Borelli committed
495

496
	gtkwidget_class->grab_focus = gedit_notebook_grab_focus;
497
	gtkwidget_class->button_press_event = gedit_notebook_button_press;
Paolo Borelli's avatar
Paolo Borelli committed
498

499 500 501 502
	notebook_class->change_current_page = gedit_notebook_change_current_page;
	notebook_class->switch_page = gedit_notebook_switch_page;
	notebook_class->page_removed = gedit_notebook_page_removed;
	notebook_class->page_added = gedit_notebook_page_added;
Paolo Borelli's avatar
Paolo Borelli committed
503

504 505
	container_class->remove = gedit_notebook_remove;

506 507 508 509 510 511 512
	g_object_class_install_property (object_class, PROP_SHOW_TABS_MODE,
					 g_param_spec_enum ("show-tabs-mode",
							    "Show Tabs Mode",
							    "When tabs should be shown",
							    GEDIT_TYPE_NOTEBOOK_SHOW_TABS_MODE_TYPE,
							    GEDIT_NOTEBOOK_SHOW_TABS_ALWAYS,
							    G_PARAM_READWRITE));
Paolo Borelli's avatar
Paolo Borelli committed
513

514 515 516 517 518 519 520 521 522 523
	signals[TAB_CLOSE_REQUEST] =
		g_signal_new ("tab-close-request",
			      G_OBJECT_CLASS_TYPE (object_class),
			      G_SIGNAL_RUN_LAST,
			      G_STRUCT_OFFSET (GeditNotebookClass, tab_close_request),
			      NULL, NULL,
			      g_cclosure_marshal_VOID__OBJECT,
			      G_TYPE_NONE,
			      1,
			      GEDIT_TYPE_TAB);
Paolo Borelli's avatar
Paolo Borelli committed
524

525 526 527 528 529 530
	signals[SHOW_POPUP_MENU] =
		g_signal_new ("show-popup-menu",
			      G_OBJECT_CLASS_TYPE (object_class),
			      G_SIGNAL_RUN_FIRST,
			      G_STRUCT_OFFSET (GeditNotebookClass, show_popup_menu),
			      NULL, NULL,
531
			      gedit_marshal_VOID__BOXED_OBJECT,
532
			      G_TYPE_NONE,
533 534 535
			      2,
			      GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE,
			      GEDIT_TYPE_TAB);
536

537
	g_type_class_add_private (object_class, sizeof (GeditNotebookPrivate));
Paolo Borelli's avatar
Paolo Borelli committed
538 539
}

540 541 542 543 544 545 546
/**
 * gedit_notebook_new:
 *
 * Creates a new #GeditNotebook object.
 *
 * Returns: a new #GeditNotebook
 */
Paolo Borelli's avatar
Paolo Borelli committed
547 548 549 550 551 552 553 554 555 556 557
GtkWidget *
gedit_notebook_new (void)
{
	return GTK_WIDGET (g_object_new (GEDIT_TYPE_NOTEBOOK, NULL));
}

static void
gedit_notebook_init (GeditNotebook *notebook)
{
	notebook->priv = GEDIT_NOTEBOOK_GET_PRIVATE (notebook);

558 559 560
	notebook->priv->ui_settings = g_settings_new ("org.gnome.gedit.preferences.ui");

	notebook->priv->show_tabs_mode = GEDIT_NOTEBOOK_SHOW_TABS_ALWAYS;
Paolo Borelli's avatar
Paolo Borelli committed
561 562 563 564
	notebook->priv->close_buttons_sensitive = TRUE;
	
	gtk_notebook_set_scrollable (GTK_NOTEBOOK (notebook), TRUE);
	gtk_notebook_set_show_border (GTK_NOTEBOOK (notebook), FALSE);
565
	gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook), TRUE);
566 567
	gtk_notebook_set_group_name (GTK_NOTEBOOK (notebook),
	                             GEDIT_NOTEBOOK_GROUP_NAME);
568
	gtk_container_set_border_width (GTK_CONTAINER (notebook), 0);
569

570 571 572 573 574
	g_settings_bind (notebook->priv->ui_settings,
			 GEDIT_SETTINGS_SHOW_TABS_MODE,
			 notebook,
			 "show-tabs-mode",
			 G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
Paolo Borelli's avatar
Paolo Borelli committed
575 576 577
}

static GtkWidget *
578 579
create_tab_label (GeditNotebook *nb,
		  GeditTab      *tab)
Paolo Borelli's avatar
Paolo Borelli committed
580
{
581
	GtkWidget *tab_label;
Paolo Borelli's avatar
Paolo Borelli committed
582

583
	tab_label = gedit_tab_label_new (tab);
Paolo Borelli's avatar
Paolo Borelli committed
584

585
	g_object_set_data (G_OBJECT (tab), "tab-label", tab_label);
Paolo Borelli's avatar
Paolo Borelli committed
586

587 588
	return tab_label;
}
Paolo Borelli's avatar
Paolo Borelli committed
589

590 591 592 593 594 595 596 597 598
/**
 * gedit_notebook_add_tab:
 * @nb: a #GeditNotebook
 * @tab: a #GeditTab
 * @position: the position where the @tab should be added
 * @jump_to: %TRUE to set the @tab as active
 *
 * Adds the specified @tab to the @nb.
 */
Paolo Borelli's avatar
Paolo Borelli committed
599 600 601 602 603 604
void
gedit_notebook_add_tab (GeditNotebook *nb,
		        GeditTab      *tab,
		        gint           position,
		        gboolean       jump_to)
{
605
	GtkWidget *tab_label;
Paolo Borelli's avatar
Paolo Borelli committed
606 607 608 609

	g_return_if_fail (GEDIT_IS_NOTEBOOK (nb));
	g_return_if_fail (GEDIT_IS_TAB (tab));

610
	tab_label = create_tab_label (nb, tab);
611

Paolo Borelli's avatar
Paolo Borelli committed
612 613
	gtk_notebook_insert_page (GTK_NOTEBOOK (nb), 
				  GTK_WIDGET (tab),
614
				  tab_label,
Paolo Borelli's avatar
Paolo Borelli committed
615
				  position);
616 617 618 619 620 621
	gtk_notebook_set_tab_reorderable (GTK_NOTEBOOK (nb),
	                                  GTK_WIDGET (tab),
	                                  TRUE);
	gtk_notebook_set_tab_detachable (GTK_NOTEBOOK (nb),
	                                 GTK_WIDGET (tab),
	                                 TRUE);
622

Paolo Borelli's avatar
Paolo Borelli committed
623
	/* The signal handler may have reordered the tabs */
624
	position = gtk_notebook_page_num (GTK_NOTEBOOK (nb),
Paolo Borelli's avatar
Paolo Borelli committed
625 626 627 628 629
					  GTK_WIDGET (tab));

	if (jump_to)
	{
		gtk_notebook_set_current_page (GTK_NOTEBOOK (nb), position);
630
		gtk_widget_grab_focus (GTK_WIDGET (tab));
Paolo Borelli's avatar
Paolo Borelli committed
631 632 633
	}
}

634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658
/**
 * gedit_notebook_move_tab:
 * @src: a #GeditNotebook
 * @dest: a #GeditNotebook
 * @tab: a #GeditTab
 * @dest_position: the position for @tab
 *
 * Moves @tab from @src to @dest.
 * If dest_position is greater than or equal to the number of tabs
 * of the destination nootebook or negative, tab will be moved to the
 * end of the tabs.
 */
void
gedit_notebook_move_tab (GeditNotebook *src,
                         GeditNotebook *dest,
                         GeditTab      *tab,
                         gint           dest_position)
{
	g_return_if_fail (GEDIT_IS_NOTEBOOK (src));
	g_return_if_fail (GEDIT_IS_NOTEBOOK (dest));
	g_return_if_fail (src != dest);
	g_return_if_fail (GEDIT_IS_TAB (tab));

	/* make sure the tab isn't destroyed while we move it */
	g_object_ref (tab);
659
	gtk_container_remove (GTK_CONTAINER (src), GTK_WIDGET (tab));
660 661
	gedit_notebook_add_tab (dest, tab, dest_position, TRUE);
	g_object_unref (tab);
Paolo Borelli's avatar
Paolo Borelli committed
662 663
}

664 665 666 667 668 669
/**
 * gedit_notebook_remove_all_tabs:
 * @nb: a #GeditNotebook
 *
 * Removes all #GeditTab from @nb.
 */
Paolo Borelli's avatar
Paolo Borelli committed
670 671
void
gedit_notebook_remove_all_tabs (GeditNotebook *nb)
672 673 674
{
	GList *tabs, *t;

Paolo Borelli's avatar
Paolo Borelli committed
675
	g_return_if_fail (GEDIT_IS_NOTEBOOK (nb));
676

Paolo Borelli's avatar
Paolo Borelli committed
677 678 679
	g_list_free (nb->priv->focused_pages);
	nb->priv->focused_pages = NULL;

680 681 682 683 684 685 686 687 688
	/* Remove tabs in reverse order since it is faster
	 * due to how gtknotebook works */
	tabs = gtk_container_get_children (GTK_CONTAINER (nb));
	for (t = g_list_last (tabs); t != NULL; t = t->prev)
	{
		gtk_container_remove (GTK_CONTAINER (nb), GTK_WIDGET (t->data));
	}

	g_list_free (tabs);
Paolo Borelli's avatar
Paolo Borelli committed
689 690 691 692 693 694
}

static void
set_close_buttons_sensitivity (GeditTab      *tab,
                               GeditNotebook *nb)
{
695 696 697 698 699 700
	GtkWidget *tab_label;

	tab_label = get_tab_label (tab);

	gedit_tab_label_set_close_button_sensitive (GEDIT_TAB_LABEL (tab_label),
						    nb->priv->close_buttons_sensitive);
Paolo Borelli's avatar
Paolo Borelli committed
701 702
}

703 704 705 706 707 708 709
/**
 * gedit_notebook_set_close_buttons_sensitive:
 * @nb: a #GeditNotebook
 * @sensitive: %TRUE to make the buttons sensitive
 *
 * Sets whether the close buttons in the tabs of @nb are sensitive.
 */
Paolo Borelli's avatar
Paolo Borelli committed
710 711 712 713 714
void
gedit_notebook_set_close_buttons_sensitive (GeditNotebook *nb,
					    gboolean       sensitive)
{
	g_return_if_fail (GEDIT_IS_NOTEBOOK (nb));
715

Paolo Borelli's avatar
Paolo Borelli committed
716
	sensitive = (sensitive != FALSE);
717

Paolo Borelli's avatar
Paolo Borelli committed
718 719
	if (sensitive == nb->priv->close_buttons_sensitive)
		return;
720

Paolo Borelli's avatar
Paolo Borelli committed
721
	nb->priv->close_buttons_sensitive = sensitive;
722

Paolo Borelli's avatar
Paolo Borelli committed
723 724 725 726 727
	gtk_container_foreach (GTK_CONTAINER (nb),
			       (GtkCallback)set_close_buttons_sensitivity,
			       nb);
}

728 729 730 731 732 733 734 735
/**
 * gedit_notebook_get_close_buttons_sensitive:
 * @nb: a #GeditNotebook
 *
 * Whether the close buttons are sensitive.
 *
 * Returns: %TRUE if the close buttons are sensitive
 */
Paolo Borelli's avatar
Paolo Borelli committed
736 737 738 739
gboolean
gedit_notebook_get_close_buttons_sensitive (GeditNotebook *nb)
{
	g_return_val_if_fail (GEDIT_IS_NOTEBOOK (nb), TRUE);
740

Paolo Borelli's avatar
Paolo Borelli committed
741 742 743
	return nb->priv->close_buttons_sensitive;
}

744
/* ex:set ts=8 noet: */