1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
3 * anjuta-notebook-tabber
4 * Copyright (C) Johannes Schmid 2010 <jhs@gnome.org>
6 * anjuta-notebook-tabber is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * anjuta-notebook-tabber is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "anjuta-tabber.h"
23 * SECTION:anjuta-tabber
24 * @title: AnjutaTabber
25 * @short_description: Tab widget
27 * @stability: Unstable
28 * @include: libanjuta/anjuta-tabber.h
31 struct _AnjutaTabberPriv
33 GtkNotebook
* notebook
;
37 GdkWindow
* event_window
;
46 #define ANJUTA_TABBER_GET_PRIVATE(o) \
47 (G_TYPE_INSTANCE_GET_PRIVATE ((o), ANJUTA_TYPE_TABBER, AnjutaTabberPriv))
50 G_DEFINE_TYPE (AnjutaTabber
, anjuta_tabber
, GTK_TYPE_CONTAINER
);
53 anjuta_tabber_init (AnjutaTabber
*object
)
55 AnjutaTabber
* tabber
= ANJUTA_TABBER (object
);
56 AnjutaTabberPriv
* priv
;
58 GtkStyleContext
* context
;
60 tabber
->priv
= ANJUTA_TABBER_GET_PRIVATE (tabber
);
63 priv
->children
= NULL
;
64 priv
->active_page
= 0;
66 gtk_widget_set_has_window (GTK_WIDGET(tabber
), FALSE
);
68 context
= gtk_widget_get_style_context (GTK_WIDGET (tabber
));
69 gtk_style_context_add_class (context
, GTK_STYLE_CLASS_NOTEBOOK
);
70 gtk_style_context_add_class (context
, GTK_STYLE_CLASS_TOP
);
74 * anjuta_tabber_notebook_page_removed:
76 * Called when a page is removed from the associated notebook. Removes
77 * the tab for this page
80 anjuta_tabber_notebook_page_removed (GtkNotebook
* notebook
,
81 GtkWidget
* notebook_child
,
85 GtkWidget
* child
= g_list_nth_data (tabber
->priv
->children
, page_num
);
86 gtk_container_remove (GTK_CONTAINER (tabber
), child
);
90 anjuta_tabber_notebook_switch_page (GtkNotebook
* notebook
,
95 tabber
->priv
->active_page
= page_num
;
96 gtk_widget_queue_draw (GTK_WIDGET (tabber
));
100 anjuta_tabber_finalize (GObject
*object
)
102 G_OBJECT_CLASS (anjuta_tabber_parent_class
)->finalize (object
);
106 anjuta_tabber_dispose (GObject
*object
)
108 AnjutaTabber
* tabber
= ANJUTA_TABBER (object
);
109 g_signal_handlers_disconnect_by_func (tabber
->priv
->notebook
,
110 anjuta_tabber_notebook_page_removed
,
112 g_signal_handlers_disconnect_by_func (tabber
->priv
->notebook
,
113 anjuta_tabber_notebook_switch_page
,
116 G_OBJECT_CLASS (anjuta_tabber_parent_class
)->dispose (object
);
120 * anjuta_tabber_connect_notebook:
122 * Connect signals to associated notebook
126 anjuta_tabber_connect_notebook (AnjutaTabber
* tabber
)
128 g_signal_connect (tabber
->priv
->notebook
, "page-removed",
129 G_CALLBACK(anjuta_tabber_notebook_page_removed
), tabber
);
130 g_signal_connect (tabber
->priv
->notebook
, "switch-page",
131 G_CALLBACK(anjuta_tabber_notebook_switch_page
), tabber
);
135 anjuta_tabber_set_property (GObject
*object
, guint prop_id
, const GValue
*value
, GParamSpec
*pspec
)
137 g_return_if_fail (ANJUTA_IS_TABBER (object
));
139 AnjutaTabber
* tabber
= ANJUTA_TABBER (object
);
144 tabber
->priv
->notebook
= g_value_get_object (value
);
145 anjuta_tabber_connect_notebook (tabber
);
148 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
154 anjuta_tabber_get_property (GObject
*object
, guint prop_id
, GValue
*value
, GParamSpec
*pspec
)
156 g_return_if_fail (ANJUTA_IS_TABBER (object
));
161 g_value_set_object (value
, object
);
164 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
169 static GtkRegionFlags
170 anjuta_tabber_get_region_flags (AnjutaTabber
* tabber
, gint page_num
)
172 GtkRegionFlags flags
= 0;
174 if ((page_num
+ 1) % 2 == 0)
175 flags
|= GTK_REGION_EVEN
;
177 flags
|= GTK_REGION_ODD
;
180 flags
|= GTK_REGION_FIRST
;
182 if (page_num
== (g_list_length (tabber
->priv
->children
) - 1))
183 flags
|= GTK_REGION_LAST
;
189 anjuta_tabber_setup_style_context (AnjutaTabber
* tabber
, GtkStyleContext
* context
,
190 GList
* child
, GtkStateFlags
* state_flags
,
191 GtkRegionFlags
* region_flags
)
195 GtkRegionFlags region
;
198 page_num
= g_list_position (tabber
->priv
->children
, child
);
199 current
= page_num
== tabber
->priv
->active_page
;
201 region
= anjuta_tabber_get_region_flags (tabber
, page_num
);
203 gtk_style_context_add_region (context
, GTK_STYLE_REGION_TAB
, region
);
205 if (gtk_widget_get_direction (GTK_WIDGET (tabber
)) == GTK_TEXT_DIR_LTR
)
206 gtk_style_context_set_junction_sides (context
,
207 GTK_JUNCTION_CORNER_TOPLEFT
);
209 gtk_style_context_set_junction_sides (context
,
210 GTK_JUNCTION_CORNER_TOPRIGHT
);
212 state
= gtk_style_context_get_state (context
);
214 state
|= GTK_STATE_FLAG_ACTIVE
;
216 state
&= ~GTK_STATE_FLAG_ACTIVE
;
217 gtk_style_context_set_state (context
, state
);
220 *state_flags
= state
;
222 *region_flags
= region
;
226 anjuta_tabber_get_preferred_width (GtkWidget
* widget
,
230 g_return_if_fail (ANJUTA_IS_TABBER (widget
));
232 AnjutaTabber
* tabber
= ANJUTA_TABBER (widget
);
233 GtkStyleContext
* context
;
243 gtk_widget_style_get (GTK_WIDGET (tabber
->priv
->notebook
),
244 "focus-line-width", &focus_width
,
245 "focus-padding", &focus_pad
,
246 "tab-curvature", &tab_curvature
,
247 "tab-overlap", &tab_overlap
,
250 context
= gtk_widget_get_style_context (widget
);
252 for (child
= tabber
->priv
->children
; child
!= NULL
; child
= g_list_next (child
))
255 GtkBorder tab_padding
;
258 gint child_preferred
;
259 gint extra_space
= 2 * (tab_curvature
- tab_overlap
);
261 /* Get the padding of the tab */
262 gtk_style_context_save (context
);
263 anjuta_tabber_setup_style_context (tabber
, context
, child
, &state
, NULL
);
264 gtk_style_context_get_padding (context
, state
, &tab_padding
);
265 gtk_style_context_restore (context
);
267 xpadding
= 2 * (focus_width
+ focus_pad
) + tab_padding
.left
+ tab_padding
.right
;
269 if (child
->prev
== NULL
)
270 extra_space
+= tab_overlap
;
271 if (child
->next
== NULL
)
272 extra_space
+= tab_overlap
;
274 gtk_widget_get_preferred_width (GTK_WIDGET (child
->data
), &child_min
, &child_preferred
);
277 *minimum
+= child_min
+ xpadding
+ extra_space
;
281 *preferred
+= child_preferred
+ xpadding
+ extra_space
;
287 anjuta_tabber_get_preferred_height (GtkWidget
* widget
,
291 g_return_if_fail (ANJUTA_IS_TABBER (widget
));
293 AnjutaTabber
* tabber
= ANJUTA_TABBER (widget
);
294 GtkStyleContext
* context
;
299 gtk_widget_style_get (GTK_WIDGET (tabber
),
300 "focus-line-width", &focus_width
,
301 "focus-padding", &focus_pad
,
304 context
= gtk_widget_get_style_context (widget
);
306 for (child
= tabber
->priv
->children
; child
!= NULL
; child
= g_list_next (child
))
309 GtkBorder tab_padding
;
312 gint child_preferred
;
314 /* Get the padding of the tab */
315 gtk_style_context_save (context
);
316 anjuta_tabber_setup_style_context (tabber
, context
, child
, &state
, NULL
);
317 gtk_style_context_get_padding (context
, state
, &tab_padding
);
318 gtk_style_context_restore (context
);
320 ypadding
= 2 * (focus_width
+ focus_pad
) + tab_padding
.top
+ tab_padding
.bottom
;
322 gtk_widget_get_preferred_height (GTK_WIDGET (child
->data
), &child_min
, &child_preferred
);
325 *minimum
= MAX(*minimum
, child_min
+ ypadding
);
329 *preferred
= MAX(*preferred
, child_preferred
+ ypadding
);
336 anjuta_tabber_size_allocate(GtkWidget
* widget
, GtkAllocation
* allocation
)
338 g_return_if_fail (ANJUTA_IS_TABBER (widget
));
339 AnjutaTabber
* tabber
= ANJUTA_TABBER (widget
);
341 GtkStyleContext
* context
;
347 gint n_children
= g_list_length (tabber
->priv
->children
);
352 context
= gtk_widget_get_style_context (widget
);
354 gtk_widget_style_get (GTK_WIDGET (tabber
),
355 "focus-line-width", &focus_width
,
356 "focus-padding", &focus_pad
,
357 "tab-curvature", &tab_curvature
,
358 "tab-overlap", &tab_overlap
,
361 focus_space
= focus_width
+ focus_pad
;
362 tab_space
= tab_curvature
- tab_overlap
;
364 gtk_widget_set_allocation (widget
, allocation
);
366 switch (gtk_widget_get_direction (widget
))
368 case GTK_TEXT_DIR_RTL
:
369 x
= allocation
->x
+ allocation
->width
;
371 case GTK_TEXT_DIR_LTR
:
376 if (gtk_widget_get_realized (widget
))
378 gdk_window_move_resize (tabber
->priv
->event_window
,
379 allocation
->x
, allocation
->y
,
380 allocation
->width
, allocation
->height
);
381 if (gtk_widget_get_mapped (widget
))
382 gdk_window_show_unraised (tabber
->priv
->event_window
);
389 gboolean use_natural
= FALSE
;
391 gint extra_space
= 0;
392 gint real_width
= allocation
->width
;
394 /* Calculate the total space that is used for padding/overlap */
395 total_space
= 2 * tab_curvature
396 + 2 * tab_space
* (n_children
- 1)
397 + 2 * focus_space
* n_children
;
399 for (child
= tabber
->priv
->children
; child
!= NULL
; child
= g_list_next (child
))
402 GtkBorder tab_padding
;
404 /* Get the padding of the tab */
405 gtk_style_context_save (context
);
406 anjuta_tabber_setup_style_context (tabber
, context
, child
, &state
, NULL
);
407 gtk_style_context_get_padding (context
, state
, &tab_padding
);
408 gtk_style_context_restore (context
);
410 total_space
+= tab_padding
.left
+ tab_padding
.right
;
413 /* Check if we have enough space for all widgets natural size */
414 child_equal
= (real_width
- total_space
) / n_children
;
419 /* Calculate the total width of the tabs */
420 total_width
= total_space
;
421 for (child
= tabber
->priv
->children
; child
!= NULL
; child
= g_list_next (child
))
423 GtkWidget
* child_widget
= GTK_WIDGET (child
->data
);
426 gtk_widget_get_preferred_width (child_widget
, NULL
,
429 total_width
+= natural
;
431 if (natural
< child_equal
)
432 extra_space
+= child_equal
- natural
;
435 use_natural
= (total_width
<= real_width
);
436 child_equal
+= extra_space
/ n_children
;
438 for (child
= tabber
->priv
->children
; child
!= NULL
; child
= g_list_next (child
))
440 GtkWidget
* child_widget
= GTK_WIDGET (child
->data
);
442 GtkBorder tab_padding
, active_padding
;
443 GtkAllocation child_alloc
;
446 gint begin_tab
= tab_space
;
447 gint end_tab
= tab_space
;
449 /* Get the padding of the tab */
450 gtk_style_context_save (context
);
451 anjuta_tabber_setup_style_context (tabber
, context
, child
, &state
, NULL
);
452 gtk_style_context_get_padding (context
, state
, &tab_padding
);
453 gtk_style_context_get_padding (context
, state
| GTK_STATE_ACTIVE
, &active_padding
);
454 gtk_style_context_restore (context
);
456 if (child
->prev
== NULL
)
457 begin_tab
= tab_curvature
;
458 if (child
->next
== NULL
)
459 end_tab
= tab_curvature
;
461 gtk_widget_get_preferred_width (child_widget
, &minimal
,
466 child_alloc
.width
= natural
;
470 if (natural
< child_equal
)
471 child_alloc
.width
= natural
;
473 child_alloc
.width
= child_equal
;
475 /* The active pad is by definition at least the same height
476 * as the inactive one. Therefore we always use the padding of the
477 * active tab to calculate the height and y position of the child.
479 child_alloc
.height
= allocation
->height
- 2 * focus_space
480 - active_padding
.top
- active_padding
.bottom
;
481 child_alloc
.y
= allocation
->y
+ focus_space
+ active_padding
.top
;
483 switch (gtk_widget_get_direction (widget
))
485 case GTK_TEXT_DIR_RTL
:
486 child_alloc
.x
= x
- focus_space
- tab_padding
.right
487 - begin_tab
- child_alloc
.width
;
488 x
= child_alloc
.x
- focus_space
- tab_padding
.left
- end_tab
;
490 case GTK_TEXT_DIR_LTR
:
492 child_alloc
.x
= x
+ focus_space
+ tab_padding
.left
+ begin_tab
;
493 x
= child_alloc
.x
+ child_alloc
.width
+ focus_space
494 + tab_padding
.right
+ end_tab
;
497 gtk_widget_size_allocate (child_widget
, &child_alloc
);
503 anjuta_tabber_draw_tab (AnjutaTabber
* tabber
, cairo_t
* cr
, GList
* child
)
505 GtkWidget
* widget
= GTK_WIDGET (tabber
);
506 GtkWidget
* tab
= GTK_WIDGET (child
->data
);
518 GtkRegionFlags region_flags
;
519 GtkBorder tab_padding
;
521 GtkAllocation widget_alloc
;
523 GtkStyleContext
* context
= gtk_widget_get_style_context (widget
);
525 current
= g_list_position (tabber
->priv
->children
, child
) == tabber
->priv
->active_page
;
527 gtk_widget_style_get (widget
,
528 "focus-line-width", &focus_width
,
529 "focus-padding", &focus_pad
,
530 "tab-curvature", &tab_curvature
,
531 "tab-overlap", &tab_overlap
,
534 focus_space
= focus_pad
+ focus_width
;
536 /* Get border/padding for tab */
537 gtk_style_context_save (context
);
538 anjuta_tabber_setup_style_context (tabber
, context
, child
, &state
, ®ion_flags
);
539 gtk_style_context_get_padding (context
, state
, &tab_padding
);
541 gtk_widget_get_allocation (widget
, &widget_alloc
);
542 gtk_widget_get_allocation (tab
, &alloc
);
544 tab_begin
= tab_curvature
- tab_overlap
;
545 tab_end
= tab_curvature
- tab_overlap
;
547 if (region_flags
| GTK_REGION_FIRST
)
548 tab_begin
+= tab_overlap
;
549 if (region_flags
| GTK_REGION_LAST
)
550 tab_end
+= tab_overlap
;
552 alloc
.x
-= widget_alloc
.x
;
553 alloc
.x
-= tab_begin
;
554 alloc
.x
-= focus_space
+ tab_padding
.left
;
555 alloc
.y
-= widget_alloc
.y
;
556 alloc
.y
-= focus_space
+ tab_padding
.top
;
557 alloc
.width
+= 2 * focus_space
+ tab_padding
.left
+ tab_padding
.right
558 + tab_begin
+ tab_end
;
559 alloc
.height
+= 2 * focus_space
+ tab_padding
.top
+ tab_padding
.bottom
;
561 gtk_render_extension (context
,
569 if (gtk_widget_has_focus (widget
) &&
572 GtkAllocation allocation
;
574 gtk_widget_get_allocation (tab
, &allocation
);
576 gtk_render_focus (context
, cr
,
577 allocation
.x
- focus_space
,
578 allocation
.y
- focus_space
,
579 allocation
.width
+ 2 * focus_space
,
580 allocation
.height
+ 2 * focus_space
);
583 gtk_style_context_restore (context
);
587 anjuta_tabber_draw (GtkWidget
* widget
, cairo_t
* cr
)
589 AnjutaTabber
* tabber
;
593 g_return_val_if_fail (ANJUTA_IS_TABBER (widget
), FALSE
);
595 tabber
= ANJUTA_TABBER (widget
);
597 if (!tabber
->priv
->children
)
600 current_tab
= g_list_nth (tabber
->priv
->children
, tabber
->priv
->active_page
);
602 /* Draw the current tab last since it overlaps the others */
603 for (child
= tabber
->priv
->children
; child
!= current_tab
; child
= g_list_next (child
))
605 anjuta_tabber_draw_tab (tabber
, cr
, child
);
607 for (child
= g_list_last (tabber
->priv
->children
); child
!= current_tab
; child
= g_list_previous (child
))
609 anjuta_tabber_draw_tab (tabber
, cr
, child
);
611 anjuta_tabber_draw_tab (tabber
, cr
, current_tab
);
613 return GTK_WIDGET_CLASS (anjuta_tabber_parent_class
)->draw (widget
, cr
);
617 * anjuta_tabber_get_widget_coordinates:
618 * @widget: widget for the coordinates
619 * @event: event to get coordinates from
620 * @x: return location for x coordinate
621 * @y: return location for y coordinate
623 * Returns: %TRUE if coordinates were set, %FALSE otherwise
626 anjuta_tabber_get_widget_coordinates (GtkWidget
*widget
,
631 GdkWindow
*window
= ((GdkEventAny
*)event
)->window
;
634 if (!gdk_event_get_coords (event
, &tx
, &ty
))
637 while (window
&& window
!= gtk_widget_get_window (widget
))
639 gint window_x
, window_y
;
641 gdk_window_get_position (window
, &window_x
, &window_y
);
645 window
= gdk_window_get_parent (window
);
660 anjuta_tabber_button_press_event (GtkWidget
* widget
, GdkEventButton
* event
)
662 AnjutaTabber
* tabber
= ANJUTA_TABBER (widget
);
665 if (event
->button
== 1)
668 if (!anjuta_tabber_get_widget_coordinates (widget
, (GdkEvent
*) event
, &x
, &y
))
671 for (child
= tabber
->priv
->children
; child
!= NULL
; child
= g_list_next (child
))
674 gtk_widget_get_allocation (GTK_WIDGET (child
->data
), &alloc
);
676 if (alloc
.x
<= x
&& (alloc
.x
+ alloc
.width
) >= x
&&
677 alloc
.y
<= y
&& (alloc
.y
+ alloc
.height
) >= y
)
679 gint page
= g_list_position (tabber
->priv
->children
, child
);
680 gtk_notebook_set_current_page (tabber
->priv
->notebook
, page
);
690 anjuta_tabber_realize (GtkWidget
*widget
)
693 GdkWindowAttr attributes
;
694 GtkAllocation allocation
;
695 AnjutaTabber
* tabber
= ANJUTA_TABBER (widget
);
697 gtk_widget_set_realized (widget
, TRUE
);
699 window
= gtk_widget_get_parent_window (widget
);
700 gtk_widget_set_window (widget
, window
);
701 g_object_ref (window
);
703 gtk_widget_get_allocation (widget
, &allocation
);
705 attributes
.window_type
= GDK_WINDOW_CHILD
;
706 attributes
.x
= allocation
.x
;
707 attributes
.y
= allocation
.y
;
708 attributes
.width
= allocation
.width
;
709 attributes
.height
= allocation
.height
;
710 attributes
.wclass
= GDK_INPUT_ONLY
;
711 attributes
.event_mask
= gtk_widget_get_events (widget
);
712 attributes
.event_mask
|= (GDK_BUTTON_PRESS_MASK
);
714 tabber
->priv
->event_window
= gdk_window_new (gtk_widget_get_parent_window (widget
),
715 &attributes
, GDK_WA_X
| GDK_WA_Y
);
716 gdk_window_set_user_data (tabber
->priv
->event_window
, tabber
);
720 anjuta_tabber_unrealize (GtkWidget
*widget
)
722 AnjutaTabber
* tabber
= ANJUTA_TABBER (widget
);
723 gdk_window_set_user_data (tabber
->priv
->event_window
, NULL
);
724 gdk_window_destroy (tabber
->priv
->event_window
);
725 tabber
->priv
->event_window
= NULL
;
727 GTK_WIDGET_CLASS (anjuta_tabber_parent_class
)->unrealize (widget
);
731 anjuta_tabber_map (GtkWidget
* widget
)
733 AnjutaTabber
* tabber
= ANJUTA_TABBER (widget
);
734 gtk_widget_set_mapped (widget
, TRUE
);
736 gdk_window_show_unraised (tabber
->priv
->event_window
);
738 GTK_WIDGET_CLASS (anjuta_tabber_parent_class
)->map (widget
);
742 anjuta_tabber_unmap (GtkWidget
* widget
)
744 AnjutaTabber
* tabber
= ANJUTA_TABBER (widget
);
746 gtk_widget_set_mapped (widget
, FALSE
);
747 gdk_window_hide (tabber
->priv
->event_window
);
749 GTK_WIDGET_CLASS (anjuta_tabber_parent_class
)->unmap (widget
);
754 anjuta_tabber_add (GtkContainer
* container
, GtkWidget
* widget
)
756 g_return_if_fail (ANJUTA_IS_TABBER (container
));
757 g_return_if_fail (GTK_IS_WIDGET (widget
));
759 AnjutaTabber
* tabber
= ANJUTA_TABBER (container
);
760 gboolean visible
= gtk_widget_get_visible (widget
);
762 tabber
->priv
->children
= g_list_append (tabber
->priv
->children
, widget
);
763 gtk_widget_set_parent (widget
, GTK_WIDGET (tabber
));
766 gtk_container_resize_children (GTK_CONTAINER (tabber
));
767 gtk_widget_queue_resize (widget
);
772 anjuta_tabber_remove (GtkContainer
* container
, GtkWidget
* widget
)
774 g_return_if_fail (ANJUTA_IS_TABBER (container
));
775 g_return_if_fail (GTK_IS_WIDGET (widget
));
777 AnjutaTabber
* tabber
= ANJUTA_TABBER (container
);
778 gboolean visible
= gtk_widget_get_visible (widget
);
780 gtk_widget_unparent (widget
);
781 tabber
->priv
->children
= g_list_remove (tabber
->priv
->children
, widget
);
783 if (tabber
->priv
->active_page
> 0)
784 tabber
->priv
->active_page
--;
787 gtk_widget_queue_resize (GTK_WIDGET (tabber
));
791 anjuta_tabber_forall (GtkContainer
* container
,
792 gboolean include_internals
,
793 GtkCallback callback
,
794 gpointer callback_data
)
796 g_return_if_fail (ANJUTA_IS_TABBER (container
));
797 AnjutaTabber
* tabber
= ANJUTA_TABBER (container
);
799 for (child
= tabber
->priv
->children
; child
!= NULL
; child
= g_list_next (child
))
801 (* callback
) (GTK_WIDGET(child
->data
), callback_data
);
805 static GtkWidgetPath
*
806 anjuta_tabber_get_path_for_child (GtkContainer
* container
,
809 AnjutaTabber
* tabber
= ANJUTA_TABBER (container
);
815 path
= GTK_CONTAINER_CLASS (anjuta_tabber_parent_class
)->get_path_for_child (container
, widget
);
817 page_num
= g_list_index (tabber
->priv
->children
, widget
);
821 tabber_pos
= gtk_widget_path_length (path
) - 2;
822 gtk_widget_path_iter_add_region (path
, tabber_pos
, GTK_STYLE_REGION_TAB
,
823 anjuta_tabber_get_region_flags (tabber
, page_num
));
828 anjuta_tabber_class_init (AnjutaTabberClass
*klass
)
830 GObjectClass
* object_class
= G_OBJECT_CLASS (klass
);
831 GtkWidgetClass
* widget_class
= GTK_WIDGET_CLASS (klass
);
832 GtkContainerClass
* container_class
= GTK_CONTAINER_CLASS (klass
);
834 object_class
->finalize
= anjuta_tabber_finalize
;
835 object_class
->dispose
= anjuta_tabber_dispose
;
836 object_class
->set_property
= anjuta_tabber_set_property
;
837 object_class
->get_property
= anjuta_tabber_get_property
;
839 widget_class
->get_preferred_height
= anjuta_tabber_get_preferred_height
;
840 widget_class
->get_preferred_width
= anjuta_tabber_get_preferred_width
;
841 widget_class
->size_allocate
= anjuta_tabber_size_allocate
;
842 widget_class
->draw
= anjuta_tabber_draw
;
843 widget_class
->button_press_event
= anjuta_tabber_button_press_event
;
844 widget_class
->realize
= anjuta_tabber_realize
;
845 widget_class
->unrealize
= anjuta_tabber_unrealize
;
846 widget_class
->map
= anjuta_tabber_map
;
847 widget_class
->unmap
= anjuta_tabber_unmap
;
849 container_class
->add
= anjuta_tabber_add
;
850 container_class
->remove
= anjuta_tabber_remove
;
851 container_class
->forall
= anjuta_tabber_forall
;
852 container_class
->get_path_for_child
= anjuta_tabber_get_path_for_child
;
854 g_object_class_install_property (object_class
,
856 g_param_spec_object ("notebook",
858 "GtkNotebook the tabber is associated with",
860 G_PARAM_CONSTRUCT_ONLY
| G_PARAM_WRITABLE
));
862 /* Install some notebook properties */
863 gtk_widget_class_install_style_property (widget_class
,
864 g_param_spec_int ("tab-overlap", "", "",
869 gtk_widget_class_install_style_property (widget_class
,
870 g_param_spec_int ("tab-curvature", "", "",
876 g_type_class_add_private (klass
, sizeof (AnjutaTabberPriv
));
881 * @notebook: the GtkNotebook the tabber should be associated with
883 * Creates a new AnjutaTabber widget
885 * Returns: newly created AnjutaTabber widget
887 GtkWidget
* anjuta_tabber_new (GtkNotebook
* notebook
)
890 tabber
= GTK_WIDGET (g_object_new (ANJUTA_TYPE_TABBER
, "notebook", notebook
, NULL
));
896 * anjuta_tabber_add_tab:
897 * @tabber: a AnjutaTabber widget
898 * @tab_label: widget used as tab label
900 * Adds a tab to the AnjutaTabber widget
902 void anjuta_tabber_add_tab (AnjutaTabber
* tabber
, GtkWidget
* tab_label
)
904 gtk_container_add (GTK_CONTAINER (tabber
), tab_label
);