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