1 /* GSequencer - Advanced GTK Sequencer
2  * Copyright (C) 2005-2020 Joël Krähemann
3  *
4  * This file is part of GSequencer.
5  *
6  * GSequencer is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GSequencer is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with GSequencer.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <ags/widget/ags_notebook.h>
21 
22 #include <stdlib.h>
23 
24 void ags_notebook_class_init(AgsNotebookClass *notebook);
25 void ags_notebook_init(AgsNotebook *notebook);
26 void ags_notebook_set_property(GObject *gobject,
27 			       guint prop_id,
28 			       const GValue *value,
29 			       GParamSpec *param_spec);
30 void ags_notebook_get_property(GObject *gobject,
31 			       guint prop_id,
32 			       GValue *value,
33 			       GParamSpec *param_spec);
34 void ags_notebook_finalize(GObject *gobject);
35 
36 void ags_notebook_get_preferred_width(GtkWidget *widget,
37 				      gint *minimal_width,
38 				      gint *natural_width);
39 void ags_notebook_get_preferred_height(GtkWidget *widget,
40 				       gint *minimal_height,
41 				       gint *natural_height);
42 void ags_notebook_size_allocate(AgsNotebook *notebook,
43 				GtkAllocation *allocation);
44 
45 void ags_notebook_scroll_prev_callback(GtkWidget *button,
46 				       AgsNotebook *notebook);
47 void ags_notebook_scroll_next_callback(GtkWidget *button,
48 				       AgsNotebook *notebook);
49 
50 /**
51  * SECTION:ags_notebook
52  * @short_description: selection widget
53  * @title: AgsNotebook
54  * @section_id:
55  * @include: ags/widget/ags_notebook.h
56  *
57  * The #AgsNotebook lets you select/deselect tabs and assign data to them.
58  */
59 
60 enum{
61   PROP_0,
62   PROP_PREFIX,
63 };
64 
65 static gpointer ags_notebook_parent_class = NULL;
66 
67 GType
ags_notebook_get_type(void)68 ags_notebook_get_type(void)
69 {
70   static volatile gsize g_define_type_id__volatile = 0;
71 
72   if(g_once_init_enter (&g_define_type_id__volatile)){
73     GType ags_type_notebook = 0;
74 
75     static const GTypeInfo ags_notebook_info = {
76       sizeof (AgsNotebookClass),
77       NULL, /* base_init */
78       NULL, /* base_finalize */
79       (GClassInitFunc) ags_notebook_class_init,
80       NULL, /* class_finalize */
81       NULL, /* class_data */
82       sizeof (AgsNotebook),
83       0,    /* n_preallocs */
84       (GInstanceInitFunc) ags_notebook_init,
85     };
86 
87     ags_type_notebook = g_type_register_static(GTK_TYPE_VBOX,
88 					       "AgsNotebook", &ags_notebook_info,
89 					       0);
90 
91     g_once_init_leave(&g_define_type_id__volatile, ags_type_notebook);
92   }
93 
94   return g_define_type_id__volatile;
95 }
96 
97 void
ags_notebook_class_init(AgsNotebookClass * notebook)98 ags_notebook_class_init(AgsNotebookClass *notebook)
99 {
100   GObjectClass *gobject;
101   GtkWidgetClass *widget;
102 
103   GParamSpec *param_spec;
104 
105   ags_notebook_parent_class = g_type_class_peek_parent(notebook);
106 
107   /* GObjectClass */
108   gobject = (GObjectClass *) notebook;
109 
110   gobject->set_property = ags_notebook_set_property;
111   gobject->get_property = ags_notebook_get_property;
112 
113   gobject->finalize = ags_notebook_finalize;
114 
115   /**
116    * AgsNotebook:prefix:
117    *
118    * The prefix used to do enumerated labels.
119    *
120    * Since: 3.0.0
121    */
122   param_spec = g_param_spec_string("prefix",
123 				   "enumeration prefix",
124 				   "The label's enumeration prefix",
125 				   AGS_NOTEBOOK_TAB_DEFAULT_PREFIX,
126 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
127   g_object_class_install_property(gobject,
128 				  PROP_PREFIX,
129 				  param_spec);
130 
131   /* GtkWidgetClass */
132   widget = (GtkWidgetClass *) notebook;
133 
134   widget->get_preferred_width = ags_notebook_get_preferred_width;
135   widget->get_preferred_height = ags_notebook_get_preferred_height;
136   widget->size_allocate = ags_notebook_size_allocate;
137 }
138 
139 void
ags_notebook_init(AgsNotebook * notebook)140 ags_notebook_init(AgsNotebook *notebook)
141 {
142   GtkArrow *arrow;
143 
144   notebook->flags = 0;
145 
146   notebook->tab_width = AGS_NOTEBOOK_TAB_DEFAULT_WIDTH;
147   notebook->tab_height = AGS_NOTEBOOK_TAB_DEFAULT_HEIGHT;
148 
149   notebook->prefix = g_strdup(AGS_NOTEBOOK_TAB_DEFAULT_PREFIX);
150 
151   /* navigation */
152   notebook->navigation = (GtkHBox *) gtk_hbox_new(FALSE,
153 						  0);
154   gtk_box_pack_start(GTK_BOX(notebook),
155 		     GTK_WIDGET(notebook->navigation),
156 		     FALSE, FALSE,
157 		     0);
158 
159   /* arrow left */
160   arrow = (GtkArrow *) gtk_arrow_new(GTK_ARROW_LEFT,
161 				     GTK_SHADOW_NONE);
162   notebook->scroll_prev = g_object_new(GTK_TYPE_BUTTON,
163 				       "child", arrow,
164 				       "relief", GTK_RELIEF_NONE,
165 				       NULL);
166   gtk_box_pack_start(GTK_BOX(notebook->navigation),
167 		     GTK_WIDGET(notebook->scroll_prev),
168 		     FALSE, FALSE,
169 		     0);
170 
171   g_signal_connect(G_OBJECT(notebook->scroll_prev), "clicked",
172 		   G_CALLBACK(ags_notebook_scroll_prev_callback), notebook);
173 
174   /* arrow right */
175   arrow = (GtkArrow *) gtk_arrow_new(GTK_ARROW_RIGHT,
176 				     GTK_SHADOW_NONE);
177   notebook->scroll_next = g_object_new(GTK_TYPE_BUTTON,
178 				       "child", arrow,
179 				       "relief", GTK_RELIEF_NONE,
180 				       NULL);
181   gtk_box_pack_start(GTK_BOX(notebook->navigation),
182 		     GTK_WIDGET(notebook->scroll_next),
183 		     FALSE, FALSE,
184 		     0);
185 
186   g_signal_connect(G_OBJECT(notebook->scroll_next), "clicked",
187 		   G_CALLBACK(ags_notebook_scroll_next_callback), notebook);
188 
189   /* viewport with selection */
190   notebook->viewport = (GtkViewport *) gtk_viewport_new(NULL,
191 							NULL);
192   gtk_container_add(GTK_CONTAINER(notebook->navigation),
193 		    GTK_WIDGET(notebook->viewport));
194 
195   notebook->hbox = (GtkHBox *) gtk_hbox_new(FALSE,
196 					    0);
197   gtk_container_add((GtkContainer *) notebook->viewport,
198 		    (GtkWidget *) notebook->hbox);
199 
200   notebook->tab = NULL;
201   notebook->tab_free_func = ags_notebook_tab_free;
202 }
203 
204 void
ags_notebook_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)205 ags_notebook_set_property(GObject *gobject,
206 			  guint prop_id,
207 			  const GValue *value,
208 			  GParamSpec *param_spec)
209 {
210   AgsNotebook *notebook;
211 
212   notebook = AGS_NOTEBOOK(gobject);
213 
214   switch(prop_id){
215   case PROP_PREFIX:
216     {
217       gchar *prefix;
218 
219       prefix = g_value_get_string(value);
220 
221       if(notebook->prefix == prefix){
222 	return;
223       }
224 
225       g_free(notebook->prefix);
226 
227       notebook->prefix = g_strdup(prefix);
228     }
229     break;
230   default:
231     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
232     break;
233   }
234 }
235 
236 void
ags_notebook_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)237 ags_notebook_get_property(GObject *gobject,
238 			  guint prop_id,
239 			  GValue *value,
240 			  GParamSpec *param_spec)
241 {
242   AgsNotebook *notebook;
243 
244   notebook = AGS_NOTEBOOK(gobject);
245 
246   switch(prop_id){
247   case PROP_PREFIX:
248     {
249       g_value_set_string(value, notebook->prefix);
250     }
251     break;
252   default:
253     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
254     break;
255   }
256 }
257 
258 void
ags_notebook_finalize(GObject * gobject)259 ags_notebook_finalize(GObject *gobject)
260 {
261   AgsNotebook *notebook;
262 
263   notebook = AGS_NOTEBOOK(gobject);
264 
265   g_free(notebook->prefix);
266 
267   if(notebook->tab_free_func != NULL){
268     g_list_free_full(notebook->tab,
269 		     (GDestroyNotify) notebook->tab_free_func);
270   }else{
271     g_list_free_full(notebook->tab,
272 		     g_free);
273   }
274 
275   /* call parent */
276   G_OBJECT_CLASS(ags_notebook_parent_class)->finalize(gobject);
277 }
278 
279 void
ags_notebook_get_preferred_width(GtkWidget * widget,gint * minimal_width,gint * natural_width)280 ags_notebook_get_preferred_width(GtkWidget *widget,
281 				 gint *minimal_width,
282 				 gint *natural_width)
283 {
284   minimal_width =
285     natural_width = NULL;
286 }
287 
288 void
ags_notebook_get_preferred_height(GtkWidget * widget,gint * minimal_height,gint * natural_height)289 ags_notebook_get_preferred_height(GtkWidget *widget,
290 				  gint *minimal_height,
291 				  gint *natural_height)
292 {
293   minimal_height[0] =
294     natural_height[0] = AGS_NOTEBOOK_TAB_DEFAULT_HEIGHT;
295 }
296 
297 void
ags_notebook_size_allocate(AgsNotebook * notebook,GtkAllocation * allocation)298 ags_notebook_size_allocate(AgsNotebook *notebook,
299 			   GtkAllocation *allocation)
300 {
301   GtkAllocation child_allocation;
302   GtkRequisition child_requisition;
303 
304   GList *list, *list_start;
305 
306   guint x;
307 
308   if(allocation->width < (2 * AGS_NOTEBOOK_TAB_DEFAULT_HEIGHT) + (5 * AGS_NOTEBOOK_TAB_DEFAULT_WIDTH)){
309     allocation->width = (2 * AGS_NOTEBOOK_TAB_DEFAULT_HEIGHT) + (5 * AGS_NOTEBOOK_TAB_DEFAULT_WIDTH);
310   }
311 
312   allocation->height = AGS_NOTEBOOK_TAB_DEFAULT_HEIGHT;
313 
314   GTK_WIDGET_CLASS(ags_notebook_parent_class)->size_allocate(notebook,
315 							     allocation);
316 
317   /*  */
318   gtk_widget_get_child_requisition((GtkWidget *) notebook->navigation,
319 				   &child_requisition);
320 
321   child_allocation.x = allocation->x;
322   child_allocation.y = allocation->y;
323 
324   child_allocation.width = 2 * AGS_NOTEBOOK_TAB_DEFAULT_HEIGHT;
325   child_allocation.height = AGS_NOTEBOOK_TAB_DEFAULT_HEIGHT;
326 
327   gtk_widget_size_allocate((GtkWidget *) notebook->navigation,
328 			   &child_allocation);
329 
330   /*  */
331   gtk_widget_get_child_requisition((GtkWidget *) notebook->scroll_prev,
332 				   &child_requisition);
333 
334   child_allocation.x = allocation->x;
335   child_allocation.y = allocation->y;
336 
337   child_allocation.width = AGS_NOTEBOOK_TAB_DEFAULT_HEIGHT;
338   child_allocation.height = AGS_NOTEBOOK_TAB_DEFAULT_HEIGHT;
339 
340   gtk_widget_size_allocate((GtkWidget *) notebook->scroll_prev,
341 			   &child_allocation);
342 
343   gtk_widget_get_child_requisition(gtk_bin_get_child((GtkBin *) notebook->scroll_prev),
344 				   &child_requisition);
345 
346   child_allocation.x = allocation->x + 4;
347   child_allocation.y = allocation->y + 4;
348 
349   child_allocation.width = AGS_NOTEBOOK_TAB_DEFAULT_HEIGHT - 8;
350   child_allocation.height = AGS_NOTEBOOK_TAB_DEFAULT_HEIGHT - 8;
351 
352   gtk_widget_size_allocate(gtk_bin_get_child((GtkBin *) notebook->scroll_prev),
353 			   &child_allocation);
354 
355   /*  */
356   gtk_widget_get_child_requisition((GtkWidget *) notebook->scroll_next,
357 				   &child_requisition);
358 
359   child_allocation.x = allocation->x + AGS_NOTEBOOK_TAB_DEFAULT_HEIGHT;
360   child_allocation.y = allocation->y;
361 
362   child_allocation.width = AGS_NOTEBOOK_TAB_DEFAULT_HEIGHT;
363   child_allocation.height = AGS_NOTEBOOK_TAB_DEFAULT_HEIGHT;
364 
365   gtk_widget_size_allocate((GtkWidget *) notebook->scroll_next,
366 			   &child_allocation);
367 
368   gtk_widget_get_child_requisition(gtk_bin_get_child((GtkBin *) notebook->scroll_next),
369 				   &child_requisition);
370 
371   child_allocation.x = allocation->x + AGS_NOTEBOOK_TAB_DEFAULT_HEIGHT + 4;
372   child_allocation.y = allocation->y + 4;
373 
374   child_allocation.width = AGS_NOTEBOOK_TAB_DEFAULT_HEIGHT - 8;
375   child_allocation.height = AGS_NOTEBOOK_TAB_DEFAULT_HEIGHT - 8;
376 
377   gtk_widget_size_allocate(gtk_bin_get_child((GtkBin *) notebook->scroll_next),
378 			   &child_allocation);
379 
380 
381   /*  */
382   gtk_widget_get_child_requisition((GtkWidget *) notebook->viewport,
383 				   &child_requisition);
384 
385   child_allocation.x = allocation->x + 2 * AGS_NOTEBOOK_TAB_DEFAULT_HEIGHT;
386   child_allocation.y = allocation->y;
387 
388   child_allocation.width = allocation->width - 2 * AGS_NOTEBOOK_TAB_DEFAULT_HEIGHT;
389   child_allocation.height = AGS_NOTEBOOK_TAB_DEFAULT_HEIGHT;
390 
391   gtk_widget_size_allocate((GtkWidget *) notebook->viewport,
392 			   &child_allocation);
393 
394   /*  */
395   list_start =
396     list = gtk_container_get_children((GtkContainer *) notebook->hbox);
397 
398   /*  */
399   gtk_widget_get_child_requisition((GtkWidget *) notebook->hbox,
400 				   &child_requisition);
401 
402   child_allocation.x = 0;
403   child_allocation.y = 0;
404 
405   child_allocation.width = g_list_length(list) * AGS_NOTEBOOK_TAB_DEFAULT_WIDTH;
406 
407   if(child_allocation.width < allocation->width - 2 * AGS_NOTEBOOK_TAB_DEFAULT_HEIGHT){
408     child_allocation.width = allocation->width - 2 * AGS_NOTEBOOK_TAB_DEFAULT_HEIGHT;
409   }
410 
411   child_allocation.height = AGS_NOTEBOOK_TAB_DEFAULT_HEIGHT;
412 
413   gtk_widget_size_allocate((GtkWidget *) notebook->hbox,
414 			   &child_allocation);
415 
416   x = 0;
417 
418   while(list != NULL){
419     gtk_widget_get_child_requisition((GtkWidget *) list->data,
420 				     &child_requisition);
421 
422     child_allocation.x = x;
423     child_allocation.y = 0;
424 
425     child_allocation.width = AGS_NOTEBOOK_TAB_DEFAULT_WIDTH;
426     child_allocation.height = AGS_NOTEBOOK_TAB_DEFAULT_HEIGHT;
427 
428     gtk_widget_size_allocate(list->data,
429 			     &child_allocation);
430 
431     x += AGS_NOTEBOOK_TAB_DEFAULT_WIDTH;
432     list = list->next;
433   }
434 
435   g_list_free(list_start);
436   //  gtk_widget_size_allocate(notebook->hbox);
437 }
438 
439 void
ags_notebook_scroll_prev_callback(GtkWidget * button,AgsNotebook * notebook)440 ags_notebook_scroll_prev_callback(GtkWidget *button,
441 				  AgsNotebook *notebook)
442 {
443   GtkAdjustment *adjustment;
444 
445   adjustment = gtk_viewport_get_hadjustment(notebook->viewport);
446 
447   if(gtk_adjustment_get_value(adjustment) - gtk_adjustment_get_step_increment(adjustment) > 0){
448     gtk_adjustment_set_value(adjustment,
449 			     gtk_adjustment_get_value(adjustment) - gtk_adjustment_get_step_increment(adjustment));
450   }else{
451     gtk_adjustment_set_value(adjustment,
452 			     0.0);
453   }
454 
455   gtk_widget_show_all((GtkWidget *) notebook->hbox);
456 }
457 
458 void
ags_notebook_scroll_next_callback(GtkWidget * button,AgsNotebook * notebook)459 ags_notebook_scroll_next_callback(GtkWidget *button,
460 				  AgsNotebook *notebook)
461 {
462   GtkAdjustment *adjustment;
463 
464   adjustment = gtk_viewport_get_hadjustment(notebook->viewport);
465 
466   if(gtk_adjustment_get_value(adjustment) + gtk_adjustment_get_step_increment(adjustment) < gtk_adjustment_get_upper(adjustment) - gtk_adjustment_get_page_size(adjustment)){
467     gtk_adjustment_set_value(adjustment,
468 			     gtk_adjustment_get_value(adjustment) + gtk_adjustment_get_step_increment(adjustment));
469   }else{
470     gtk_adjustment_set_value(adjustment,
471 			     gtk_adjustment_get_upper(adjustment) - gtk_adjustment_get_page_size(adjustment));
472   }
473 
474   gtk_widget_show_all((GtkWidget *) notebook->hbox);
475 }
476 
477 /**
478  * ags_notebook_tab_alloc:
479  *
480  * Allocate #AgsNotebookTab-struct.
481  *
482  * Returns: (type gpointer) (transfer full): the newly allocated #AgsNotebookTab-struct
483  *
484  * Since: 3.0.0
485  */
486 AgsNotebookTab*
ags_notebook_tab_alloc()487 ags_notebook_tab_alloc()
488 {
489   AgsNotebookTab *notebook_tab;
490 
491   notebook_tab = (AgsNotebookTab *) g_malloc(sizeof(AgsNotebookTab));
492 
493   notebook_tab->data = NULL;
494   notebook_tab->toggle = NULL;
495 
496   return(notebook_tab);
497 }
498 
499 /**
500  * ags_notebook_tab_free:
501  * @tab: (type gpointer) (transfer full): the #AgsNotebookTab-struct
502  *
503  * Free @tab's memory.
504  *
505  * Since: 3.0.0
506  */
507 void
ags_notebook_tab_free(AgsNotebookTab * tab)508 ags_notebook_tab_free(AgsNotebookTab *tab)
509 {
510   if(tab == NULL){
511     return;
512   }
513 
514   g_free(tab->data);
515 
516   g_free(tab);
517 }
518 
519 /**
520  * ags_notebook_tab_set_data:
521  * @notebook: the #AgsNotebook
522  * @position: the tab's position
523  * @data: the data to set
524  *
525  * Set the data field of #AgsNotebookTab-struct at @position.
526  *
527  * Since: 3.0.0
528  */
529 void
ags_notebook_tab_set_data(AgsNotebook * notebook,gint position,gpointer data)530 ags_notebook_tab_set_data(AgsNotebook *notebook,
531 			  gint position,
532 			  gpointer data)
533 {
534   GList *tab;
535 
536   if(!AGS_IS_NOTEBOOK(notebook) ||
537      position < 0){
538     return;
539   }
540 
541   tab = g_list_nth(notebook->tab,
542 		   position);
543 
544   if(tab != NULL &&
545      tab->data != NULL){
546     AGS_NOTEBOOK_TAB(tab->data)->data = data;
547   }
548 }
549 
550 /**
551  * ags_notebook_tab_index:
552  * @notebook: the #AgsNotebook
553  * @data: the assigned data
554  *
555  * Retrieve tab index assigned with @data.
556  *
557  * Returns: the position as integer
558  *
559  * Since: 3.0.0
560  */
561 gint
ags_notebook_tab_index(AgsNotebook * notebook,gpointer data)562 ags_notebook_tab_index(AgsNotebook *notebook,
563 		       gpointer data)
564 {
565   GList *list;
566   gint i;
567 
568   if(!AGS_IS_NOTEBOOK(notebook)){
569     return(-1);
570   }
571 
572   list = notebook->tab;
573 
574   for(i = g_list_length(notebook->tab) - 1; list != NULL; i--){
575     if(AGS_NOTEBOOK_TAB(list->data)->data == data){
576       return(i);
577     }
578 
579     list = list->next;
580   }
581 
582   return(-1);
583 }
584 
585 /**
586  * ags_notebook_next_active_tab:
587  * @notebook: the #AgsNotebook
588  * @position: the position as integer
589  *
590  * Get next active tab following @position.
591  *
592  * Returns: the position of next active tab as integer
593  *
594  * Since: 3.0.0
595  */
596 gint
ags_notebook_next_active_tab(AgsNotebook * notebook,gint position)597 ags_notebook_next_active_tab(AgsNotebook *notebook,
598 			     gint position)
599 {
600   GList *list, *list_start;
601   gint i;
602 
603   if(!AGS_IS_NOTEBOOK(notebook)){
604     return(-1);
605   }
606 
607   list_start = g_list_copy(notebook->tab);
608   list_start =
609     list = g_list_reverse(list_start);
610 
611   list = g_list_nth(list,
612 		    position);
613 
614   for(i = 0; list != NULL;){
615     if(gtk_toggle_button_get_active(AGS_NOTEBOOK_TAB(list->data)->toggle)){
616       g_list_free(list_start);
617       return(position + i);
618     }
619 
620     /* iterate */
621     list = list->next;
622 
623     i++;
624   }
625 
626   g_list_free(list_start);
627 
628   return(-1);
629 }
630 
631 /**
632  * ags_notebook_add_tab:
633  * @notebook: the #AgsNotebook
634  *
635  * Add a new #AgsNotebookTab-struct to @notebook.
636  *
637  * Returns: the position as integer
638  *
639  * Since: 3.0.0
640  */
641 gint
ags_notebook_add_tab(AgsNotebook * notebook)642 ags_notebook_add_tab(AgsNotebook *notebook)
643 {
644   AgsNotebookTab *tab;
645   GtkViewport *viewport;
646 
647   GtkAdjustment *adjustment;
648 
649   gchar *str;
650 
651   gint tab_index;
652   gint length;
653   guint width;
654 
655   if(!AGS_IS_NOTEBOOK(notebook)){
656     return(-1);
657   }
658 
659   /* new tab */
660   tab = ags_notebook_tab_alloc();
661 
662   notebook->tab = g_list_prepend(notebook->tab,
663 				 tab);
664   tab_index = g_list_length(notebook->tab);
665 
666   str = NULL;
667 
668   if((AGS_NOTEBOOK_TAB_PREFIXED_LABEL & (notebook->flags)) != 0 &&
669      (AGS_NOTEBOOK_TAB_ENUMERATE & (notebook->flags)) != 0){
670     str = g_strdup_printf("%s %d",
671 			  notebook->prefix,
672 			  tab_index);
673   }else if((AGS_NOTEBOOK_TAB_PREFIXED_LABEL & (notebook->flags)) != 0){
674     str = g_strdup_printf("%s",
675 			  notebook->prefix);
676   }else if((AGS_NOTEBOOK_TAB_ENUMERATE & (notebook->flags)) != 0){
677     str = g_strdup_printf("%d",
678 			  tab_index);
679   }
680 
681   tab->toggle = (GtkToggleButton *) g_object_new(GTK_TYPE_TOGGLE_BUTTON,
682 						 "label", str,
683 						 "xalign", 0.0,
684 						 "yalign", 0.0,
685 						 "active", TRUE,
686 						 NULL);
687   gtk_widget_set_size_request((GtkWidget *) tab->toggle,
688 			      AGS_NOTEBOOK_TAB_DEFAULT_WIDTH, AGS_NOTEBOOK_TAB_DEFAULT_HEIGHT);
689   gtk_box_pack_start(GTK_BOX(notebook->hbox),
690 		     GTK_WIDGET(tab->toggle),
691 		     FALSE, FALSE,
692 		     0);
693 
694   gtk_widget_show_all((GtkWidget *) notebook->hbox);
695 
696   g_free(str);
697 
698   return(tab_index);
699 }
700 
701 /**
702  * ags_notebook_add_tab_with_label:
703  * @notebook: the #AgsNotebook
704  * @label: the label
705  *
706  * Add a new #AgsNotebookTab-struct to @notebook and set specified @label.
707  *
708  * Returns: the position as integer
709  *
710  * Since: 3.0.0
711  */
712 gint
ags_notebook_add_tab_with_label(AgsNotebook * notebook,gchar * label)713 ags_notebook_add_tab_with_label(AgsNotebook *notebook,
714 				gchar *label)
715 {
716   GList *tab;
717 
718   gint position;
719 
720   if(!AGS_IS_NOTEBOOK(notebook)){
721     return(-1);
722   }
723 
724   position = ags_notebook_add_tab(notebook);
725 
726   tab = g_list_nth(notebook->tab,
727 		   position);
728 
729   if(tab != NULL){
730     g_object_set(AGS_NOTEBOOK_TAB(tab->data)->toggle,
731 		 "label", label,
732 		 NULL);
733   }
734 
735   return(position);
736 }
737 
738 /**
739  * ags_notebook_insert_tab:
740  * @notebook: the #AgsNotebook
741  * @position: the position as integer
742  *
743  * Insert a new #AgsNotebookTab-struct to @notebook.
744  *
745  * Since: 3.0.0
746  */
747 void
ags_notebook_insert_tab(AgsNotebook * notebook,gint position)748 ags_notebook_insert_tab(AgsNotebook *notebook,
749 			gint position)
750 {
751   AgsNotebookTab *tab;
752 
753   GtkAdjustment *adjustment;
754 
755   gint length;
756   guint width;
757 
758   if(!AGS_IS_NOTEBOOK(notebook)){
759     return;
760   }
761 
762   /* insert tab */
763   length = g_list_length(notebook->tab);
764 
765   tab = ags_notebook_tab_alloc();
766   notebook->tab = g_list_insert(notebook->tab,
767 				tab,
768 				length - position);
769 
770   tab->toggle = (GtkToggleButton *) gtk_toggle_button_new_with_label(g_strdup_printf("%s %d",
771 										     notebook->prefix,
772 										     position + 1));
773   g_object_set(tab->toggle,
774 	       "xalign", 0.0,
775 	       "yalign", 0.0,
776 	       NULL);
777   gtk_widget_set_size_request((GtkWidget *) tab->toggle,
778 			      AGS_NOTEBOOK_TAB_DEFAULT_WIDTH, AGS_NOTEBOOK_TAB_DEFAULT_HEIGHT);
779   gtk_box_pack_start(GTK_BOX(notebook->hbox),
780 		     GTK_WIDGET(tab->toggle),
781 		     FALSE, FALSE,
782 		     0);
783   gtk_box_reorder_child(GTK_BOX(notebook->hbox),
784 			GTK_WIDGET(tab->toggle),
785 			position);
786 
787   gtk_widget_show_all((GtkWidget *) notebook->hbox);
788 }
789 
790 /**
791  * ags_notebook_insert_tab_with_label:
792  * @notebook: the #AgsNotebook
793  * @label: the label as string
794  * @position: the position as integer
795  *
796  * Insert a new #AgsNotebookTab-struct to @notebook at @position and set specified @label.
797  *
798  * Since: 3.0.0
799  */
800 void
ags_notebook_insert_tab_with_label(AgsNotebook * notebook,gchar * label,gint position)801 ags_notebook_insert_tab_with_label(AgsNotebook *notebook,
802 				   gchar *label,
803 				   gint position)
804 {
805   GList *tab;
806 
807   if(!AGS_IS_NOTEBOOK(notebook)){
808     return;
809   }
810 
811   ags_notebook_insert_tab(notebook,
812 			  position);
813 
814   tab = g_list_nth(notebook->tab,
815 		   position);
816 
817   if(tab != NULL){
818     g_object_set(AGS_NOTEBOOK_TAB(tab->data)->toggle,
819 		 "label", label,
820 		 NULL);
821   }
822 }
823 
824 /**
825  * ags_notebook_remove_tab:
826  * @notebook: the #AgsNotebook
827  * @position: the position of the tab
828  *
829  * Remove #AgsNotebookTab at @position.
830  *
831  * Since: 3.0.0
832  */
833 void
ags_notebook_remove_tab(AgsNotebook * notebook,gint position)834 ags_notebook_remove_tab(AgsNotebook *notebook,
835 			gint position)
836 {
837   AgsNotebookTab *tab;
838 
839   gint length;
840 
841   if(!AGS_IS_NOTEBOOK(notebook) ||
842      notebook->tab == NULL ||
843      position < 0){
844     return;
845   }
846 
847   length = g_list_length(notebook->tab);
848 
849   tab = g_list_nth_data(notebook->tab,
850 			length - position - 1);
851 
852   if(tab != NULL){
853     notebook->tab = g_list_remove(notebook->tab,
854 				  tab);
855     gtk_widget_destroy(GTK_WIDGET(tab->toggle));
856 
857     if(notebook->tab_free_func != NULL){
858       notebook->tab_free_func(tab);
859     }
860   }
861 }
862 
863 /**
864  * ags_notebook_remove_tab_with_data:
865  * @notebook: the #AgsNotebook
866  * @data: the data to lookup
867  *
868  * Remove #AgsNotebookTab assigned with @data.
869  *
870  * Since: 3.0.0
871  */
872 void
ags_notebook_remove_tab_with_data(AgsNotebook * notebook,gpointer data)873 ags_notebook_remove_tab_with_data(AgsNotebook *notebook,
874 				  gpointer data)
875 {
876   gint position;
877 
878   if(!AGS_IS_NOTEBOOK(notebook)){
879     return;
880   }
881 
882   position = ags_notebook_tab_index(notebook,
883 				    data);
884   ags_notebook_remove_tab(notebook,
885 			  position);
886 }
887 
888 /**
889  * ags_notebook_new:
890  *
891  * Create a new #AgsNotebook.
892  *
893  * Returns: a new #AgsNotebook
894  *
895  * Since: 3.0.0
896  */
897 AgsNotebook*
ags_notebook_new()898 ags_notebook_new()
899 {
900   AgsNotebook *notebook;
901 
902   notebook = (AgsNotebook *) g_object_new(AGS_TYPE_NOTEBOOK, NULL);
903 
904   return(notebook);
905 }
906