1 /*
2 * This file is part of the XForms library package.
3 *
4 * XForms is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as
6 * published by the Free Software Foundation; either version 2.1, or
7 * (at your option) any later version.
8 *
9 * XForms is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with XForms. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18
19 /**
20 * \file tabfolder.c
21 *
22 * This file is part of the XForms library package.
23 * Copyright (c) 1997-2002 By T.C. Zhao
24 * All rights reserved.
25 *
26 * tabbed folder
27 */
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include "include/forms.h"
34 #include "flinternal.h"
35 #include "private/flvasprintf.h"
36
37 typedef struct {
38 FL_OBJECT * canvas;
39 FL_OBJECT * parent; /* the tabfolder object */
40 FL_FORM ** forms; /* the folders */
41 FL_OBJECT ** title; /* the associted tab */
42 int nforms; /* number of folders */
43 int active_folder; /* current active folder */
44 int last_active; /* the previous active folder */
45 int x,
46 y;
47 int max_h;
48 int h_pad,
49 v_pad;
50 int processing_destroy;
51 int auto_fit;
52 int offset;
53 int num_visible;
54 } FLI_TABFOLDER_SPEC;
55
56
57 static void compute_position( FL_OBJECT * );
58 static void switch_folder( FL_OBJECT *,
59 long );
60 static void program_switch( FL_OBJECT *,
61 int );
62 static void get_tabsize( FL_OBJECT *,
63 const char *,
64 int *,
65 int *,
66 int );
67 static void shift_tabs( FL_OBJECT *,
68 int left );
69
70 #define IsFolderClass( ob ) ( ( ob ) && ( ob )->objclass == FL_TABFOLDER )
71
72
73 /***************************************
74 ***************************************/
75
76 static int
handle_tabfolder(FL_OBJECT * ob,int event,FL_Coord mx FL_UNUSED_ARG,FL_Coord my FL_UNUSED_ARG,int key FL_UNUSED_ARG,void * ev)77 handle_tabfolder( FL_OBJECT * ob,
78 int event,
79 FL_Coord mx FL_UNUSED_ARG,
80 FL_Coord my FL_UNUSED_ARG,
81 int key FL_UNUSED_ARG,
82 void * ev )
83 {
84 FL_FORM *folder;
85 FLI_TABFOLDER_SPEC *sp = ob->spec;
86
87 switch ( event )
88 {
89 case FL_RESIZED:
90 if ( ( folder = fl_get_active_folder( ob ) )
91 && sp->auto_fit != FL_NO )
92 {
93 if ( sp->auto_fit == FL_FIT )
94 fl_set_form_size( folder, sp->canvas->w, sp->canvas->h );
95 else if ( folder->w < sp->canvas->w
96 || folder->h < sp->canvas->h )
97 fl_set_form_size( folder, sp->canvas->w, sp->canvas->h );
98 }
99 break;
100
101 case FL_MOVEORIGIN:
102 if ( ( folder = fl_get_active_folder( ob ) ) )
103 {
104 fl_get_winorigin( folder->window, &folder->x, &folder->y );
105
106 /* Don't forget nested folders */
107
108 fli_handle_form( folder, FL_MOVEORIGIN, 0, ev );
109 }
110 break;
111
112 case FL_DRAW:
113 fl_set_object_boxtype( sp->canvas,
114 fli_boxtype2frametype( ob->boxtype ) );
115 sp->processing_destroy = 0;
116 compute_position( ob );
117 break;
118
119 case FL_FREEMEM:
120 fli_safe_free( sp->forms );
121 fli_safe_free( sp->title );
122 fl_free( sp );
123 break;
124 }
125
126 return 0;
127 }
128
129
130 /***************************************
131 * Canvas expose handler.
132 ***************************************/
133
134 static int
canvas_handler(FL_OBJECT * ob,Window win FL_UNUSED_ARG,int w FL_UNUSED_ARG,int h FL_UNUSED_ARG,XEvent * ev FL_UNUSED_ARG,void * data FL_UNUSED_ARG)135 canvas_handler( FL_OBJECT * ob,
136 Window win FL_UNUSED_ARG,
137 int w FL_UNUSED_ARG,
138 int h FL_UNUSED_ARG,
139 XEvent * ev FL_UNUSED_ARG,
140 void * data FL_UNUSED_ARG )
141 {
142 FLI_TABFOLDER_SPEC *sp = ob->u_vdata;
143
144 /* sp->nforms can be zero */
145
146 if ( sp->nforms == 0 || sp->active_folder >= sp->nforms )
147 return 0;
148
149 if ( sp->active_folder >= 0 ) /* regular exposure, not first time */
150 program_switch( sp->title[ sp->active_folder ], sp->active_folder );
151 else if ( sp->last_active >= 0 && sp->last_active < sp->nforms )
152 program_switch( sp->title[ sp->last_active ], sp->last_active );
153
154 return 0;
155 }
156
157
158 /***************************************
159 * Before canvas is destroyed this routine will be called where
160 * we need to close the form that is attached to this canvas
161 ***************************************/
162
163 static int
canvas_cleanup(FL_OBJECT * ob)164 canvas_cleanup( FL_OBJECT * ob )
165 {
166 FLI_TABFOLDER_SPEC *sp = ob->u_vdata;
167
168 if ( sp->active_folder >= 0 && sp->active_folder < sp->nforms )
169 {
170 sp->processing_destroy = 1;
171 if ( sp->forms[ sp->active_folder ]->visible == FL_VISIBLE )
172 fl_hide_form( sp->forms[ sp->active_folder ] );
173
174 sp->last_active = sp->active_folder;
175
176 if ( sp->active_folder >= 0 )
177 fl_set_object_boxtype( sp->title[ sp->active_folder ],
178 ob->parent->type != FL_BOTTOM_TABFOLDER ?
179 FL_TOPTAB_UPBOX : FL_BOTTOMTAB_UPBOX );
180 sp->active_folder = -1;
181 }
182
183 return 0;
184 }
185
186
187 /***************************************
188 * For all the folders set a dummy form callback to prevent
189 * the contained objects from leaking thru to fl_do_forms
190 ***************************************/
191
192 static void
form_cb(FL_OBJECT * ob FL_UNUSED_ARG,void * data FL_UNUSED_ARG)193 form_cb( FL_OBJECT * ob FL_UNUSED_ARG,
194 void * data FL_UNUSED_ARG )
195 {
196 }
197
198
199 /***************************************
200 ***************************************/
201
202 FL_OBJECT *
fl_create_tabfolder(int type,FL_Coord x,FL_Coord y,FL_Coord w,FL_Coord h,const char * label)203 fl_create_tabfolder( int type,
204 FL_Coord x,
205 FL_Coord y,
206 FL_Coord w,
207 FL_Coord h,
208 const char * label )
209 {
210 FL_OBJECT *ob;
211 FLI_TABFOLDER_SPEC *sp;
212 int absbw,
213 oldu = fl_get_coordunit( );;
214
215 ob = fl_make_object( FL_TABFOLDER, type, x, y, w, h, label,
216 handle_tabfolder );
217 fl_set_coordunit( FL_COORD_PIXEL );
218
219 ob->boxtype = FL_UP_BOX;
220 ob->spec = sp = fl_calloc( 1, sizeof *sp );
221
222 absbw = FL_abs( ob->bw );
223
224 sp->parent = ob;
225 sp->forms = NULL;
226 sp->title = NULL;
227 sp->x = ob->x + absbw;
228 sp->y = ob->y + absbw;
229 sp->h_pad = 12;
230 sp->v_pad = 5;
231 sp->auto_fit = FL_NO;
232
233 sp->canvas = fl_create_canvas( FL_SCROLLED_CANVAS, sp->x, sp->y,
234 ob->w - 2 * absbw,
235 ob->h - 2 * absbw, label ? label : "tab" );
236
237 sp->canvas->u_vdata = sp;
238 fl_modify_canvas_prop( sp->canvas, 0, 0, canvas_cleanup );
239 fl_set_object_boxtype( sp->canvas,
240 fli_boxtype2frametype( ob->boxtype ) );
241 fl_add_canvas_handler( sp->canvas, Expose, canvas_handler, 0 );
242
243 fl_set_object_color( sp->canvas, ob->col1, ob->col2 );
244 fl_set_object_bw( sp->canvas, ob->bw );
245 fl_set_object_gravity( sp->canvas, ob->nwgravity, ob->segravity );
246 fl_set_coordunit( oldu );
247
248 fl_add_child( ob, sp->canvas );
249
250 fl_set_object_return( ob, FL_RETURN_END_CHANGED );
251
252 return ob;
253 }
254
255
256 /***************************************
257 ***************************************/
258
259 FL_OBJECT *
fl_add_tabfolder(int type,FL_Coord x,FL_Coord y,FL_Coord w,FL_Coord h,const char * l)260 fl_add_tabfolder( int type,
261 FL_Coord x,
262 FL_Coord y,
263 FL_Coord w,
264 FL_Coord h,
265 const char * l )
266 {
267 FL_OBJECT *obj = fl_create_tabfolder( type, x, y, w, h, l );
268
269 /* Set the default return policy for the object */
270
271 fl_add_object( fl_current_form, obj );
272 return obj;
273 }
274
275
276 /***************************************
277 ***************************************/
278
279 void
fli_detach_form(FL_FORM * form)280 fli_detach_form( FL_FORM * form )
281 {
282 form->attached = 0;
283 if ( form->parent && form->parent->child == form )
284 form->parent->child = 0;
285 form->parent = NULL;
286 }
287
288
289 /***************************************
290 ***************************************/
291
292 int
fl_get_tabfolder_numfolders(FL_OBJECT * ob)293 fl_get_tabfolder_numfolders( FL_OBJECT * ob )
294 {
295 return ( ( FLI_TABFOLDER_SPEC * ) ob->spec )->nforms;
296 }
297
298
299 /***************************************
300 * Tab is switched by the application, no need to invoke the callback
301 * or report back to the user
302 ***************************************/
303
304 static void
program_switch(FL_OBJECT * obj,int folder)305 program_switch( FL_OBJECT * obj,
306 int folder )
307 {
308 FLI_TABFOLDER_SPEC *sp;
309
310 if ( folder >= 0 )
311 {
312 sp = obj->u_vdata;
313 switch_folder( obj, folder );
314 obj->parent->returned = FL_RETURN_NONE;
315
316 /* This handles set_folder while hidden */
317
318 if ( ! obj->visible || ! obj->form->visible == FL_VISIBLE )
319 sp->last_active = folder;
320 }
321 }
322
323
324 /***************************************
325 ***************************************/
326
327 static void
switch_folder(FL_OBJECT * ob,long data)328 switch_folder( FL_OBJECT * ob,
329 long data )
330 {
331 FLI_TABFOLDER_SPEC *sp = ob->u_vdata;
332 FL_FORM *form;
333 Window win;
334 FL_OBJECT *bkob;
335
336 if ( data < 0 || data >= sp->nforms )
337 {
338 M_err( "switch_folder", "Invalid index");
339 return;
340 }
341
342 form = sp->forms[ data ];
343
344 if ( data == sp->active_folder
345 && sp->active_folder >= 0
346 && ! sp->processing_destroy
347 && ( ob->parent->how_return == FL_RETURN_ALWAYS
348 || ob->parent->how_return == FL_RETURN_END ) )
349 {
350 ob->parent->returned |= FL_RETURN_END;
351
352 #if USE_BWC_BS_HACK
353 if ( ! ob->parent->object_callback )
354 ob->parent->returned &= ~ FL_RETURN_END;
355 #endif
356 }
357
358 if ( data == sp->active_folder || sp->processing_destroy )
359 {
360 sp->processing_destroy = 0;
361 return;
362 }
363
364 if ( ! ob->form->window || ! FL_ObjWin( sp->canvas ) )
365 return;
366
367 if ( sp->auto_fit != FL_NO )
368 {
369 if ( sp->auto_fit == FL_FIT )
370 fl_set_form_size( form, sp->canvas->w, sp->canvas->h );
371 else if ( form->w < sp->canvas->w || form->h < sp->canvas->h )
372 fl_set_form_size( form, sp->canvas->w, sp->canvas->h );
373 }
374
375 /* We may have more tabs than can be shown */
376
377 if ( sp->num_visible < sp->nforms - 1 || sp->offset )
378 {
379 if ( ( data && data == sp->offset ) || data > sp->num_visible )
380 {
381 int last;
382
383 shift_tabs( ob, data == sp->offset ? -1 : 1 );
384 sp->title[ data ]->boxtype &= ~ FLI_BROKEN_BOX;
385 sp->title[ data ]->align = FL_ALIGN_CENTER;
386 last = sp->num_visible + sp->offset + 1;
387 last = FL_clamp( last, 0, sp->nforms - 1 );
388 sp->title[ last ]->boxtype |= FLI_BROKEN_BOX;
389 sp->title[ last ]->align = fl_to_inside_lalign( FL_ALIGN_LEFT );
390 fl_redraw_form( ob->form );
391 }
392 }
393
394 win = fl_prepare_form_window( form, 0, FL_NOBORDER, "Folder" );
395
396 /* win reparent eats the reparent event */
397
398 fl_winreparent( win, FL_ObjWin( sp->canvas ) );
399 form->parent_obj = ob;
400 fl_show_form_window( form );
401
402 /* Need to redraw the last selected folder tab */
403
404 if ( sp->active_folder >= 0
405 && sp->forms[ sp->active_folder ]->visible == FL_VISIBLE )
406 {
407 FL_OBJECT *actobj;
408
409 actobj = sp->title[ sp->active_folder ];
410 actobj->col1 = sp->parent->col1;
411
412 fl_set_object_boxtype( actobj,
413 ob->parent->type != FL_BOTTOM_TABFOLDER ?
414 FL_TOPTAB_UPBOX : FL_BOTTOMTAB_UPBOX );
415
416 fl_draw_frame( FL_UP_FRAME, sp->canvas->x, sp->canvas->y, sp->canvas->w,
417 sp->canvas->h, sp->canvas->col1, sp->canvas->bw );
418 fl_hide_form( sp->forms[ sp->active_folder ] );
419 sp->forms[ sp->active_folder ]->parent_obj = NULL;
420 sp->last_active = sp->active_folder;
421 }
422
423 form->parent = ob->form;
424 ob->form->child = form;
425
426 /* Find out the color of the new form */
427
428 if ( ( bkob = form->first ) && bkob->type == FL_NO_BOX )
429 bkob = bkob->next;
430
431 if ( bkob )
432 fl_set_object_color( ob, bkob->col1, ob->col2 );
433
434 fl_set_object_boxtype( ob, ob->parent->type != FL_BOTTOM_TABFOLDER ?
435 FL_SELECTED_TOPTAB_UPBOX :
436 FL_SELECTED_BOTTOMTAB_UPBOX );
437
438 if ( sp->active_folder >= 0 )
439 {
440 ob->parent->returned = FL_RETURN_END | FL_RETURN_CHANGED;
441
442 #if USE_BWC_BS_HACK
443 if ( ! ob->parent->object_callback )
444 ob->parent->returned &= ~ ( FL_RETURN_END | FL_RETURN_CHANGED );
445 #endif
446 }
447
448 sp->active_folder = data;
449 }
450
451
452 /***************************************
453 * Add a new folder to the bunch
454 ***************************************/
455
456 FL_OBJECT *
fl_addto_tabfolder(FL_OBJECT * ob,const char * title,FL_FORM * form)457 fl_addto_tabfolder( FL_OBJECT * ob,
458 const char * title,
459 FL_FORM * form )
460 {
461 FLI_TABFOLDER_SPEC *sp = ob->spec;
462 FL_OBJECT *tab;
463
464 if ( ! IsFolderClass( ob ) )
465 {
466 M_err( "fl_addto_tabfolder", "%s not a folder class",
467 ob ? ob->label : "null" );
468 return 0;
469 }
470
471 if ( ! form || ! title )
472 {
473 M_err( "fl_addto_tabfolder", "Invalid argument(s)" );
474 return 0;
475 }
476
477 if ( form->attached )
478 {
479 M_err( "fl_addto_tabfolder",
480 "Seems as if the form is already attached" );
481 return 0;
482 }
483
484 if ( form->visible == FL_VISIBLE )
485 fl_hide_form( form );
486
487 sp->forms = fl_realloc( sp->forms, ( sp->nforms + 1 ) * sizeof *sp->forms );
488 sp->title = fl_realloc( sp->title, ( sp->nforms + 1 ) * sizeof *sp->title );
489
490 /* Plug the possible object leakage thru fl_do_forms */
491
492 if ( ! form->form_callback )
493 fl_set_form_callback( form, form_cb, NULL );
494
495 sp->forms[ sp->nforms ] = form;
496 form->attached = 1;
497
498 if ( form->pre_attach )
499 form->pre_attach( form );
500
501 tab = sp->title[ sp->nforms ] = fl_create_button( FL_NORMAL_BUTTON,
502 0, 0, 10, 10, title );
503
504 fli_inherit_attributes( ob, tab );
505 fl_set_object_boxtype( tab, ob->type != FL_BOTTOM_TABFOLDER ?
506 FL_TOPTAB_UPBOX : FL_BOTTOMTAB_UPBOX );
507
508 tab->u_vdata = sp;
509 fl_set_object_callback( tab, switch_folder, sp->nforms );
510
511 sp->nforms++;
512 compute_position( ob );
513
514 fl_add_child( ob, tab );
515
516 tab->how_return = FL_RETURN_CHANGED;
517
518 if ( sp->nforms == 1 )
519 {
520 sp->last_active = 0;
521 sp->active_folder = -1;
522 program_switch( sp->title[ sp->last_active ], sp->last_active );
523 }
524
525 /* If first time and the canvas is visible, refresh */
526
527 if ( sp->nforms == 1 && ob->visible )
528 fl_redraw_form( ob->form );
529
530 return tab;
531 }
532
533
534 /***************************************
535 ***************************************/
536
537 static void
get_tabsize(FL_OBJECT * ob,const char * label,int * ww,int * hh,int fudge)538 get_tabsize( FL_OBJECT * ob,
539 const char * label,
540 int * ww,
541 int * hh,
542 int fudge )
543 {
544 int w,
545 h,
546 absbw = FL_abs( ob->bw );
547 FLI_TABFOLDER_SPEC *sp = ob->spec;
548
549 fl_get_string_dimension( ob->lstyle, ob->lsize, label, strlen( label ),
550 &w, &h );
551 w += sp->h_pad + 2 * absbw;
552 h += sp->v_pad + 2 * absbw;
553
554 *hh = h + fudge * absbw;
555 *ww = w;
556
557 return;
558 }
559
560
561 /***************************************
562 ***************************************/
563
564 void
fl_delete_folder_byname(FL_OBJECT * ob,const char * name)565 fl_delete_folder_byname( FL_OBJECT * ob,
566 const char * name )
567 {
568 FLI_TABFOLDER_SPEC *sp = ob->spec;
569 int i,
570 done;
571
572 for ( done = i = 0; ! done && i < sp->nforms; i++ )
573 if ( ! strcmp( sp->title[ i ]->label, name ) )
574 done = i + 1;
575
576 if ( done )
577 fl_delete_folder_bynumber( ob, done );
578
579 }
580
581
582 /***************************************
583 ***************************************/
584
585 void
fl_delete_folder_byname_f(FL_OBJECT * ob,const char * fmt,...)586 fl_delete_folder_byname_f( FL_OBJECT * ob,
587 const char * fmt,
588 ... )
589 {
590 char *buf;
591
592 EXPAND_FORMAT_STRING( buf, fmt );
593 fl_delete_folder_byname( ob, buf );
594 fl_free( buf );
595 }
596
597
598 /***************************************
599 ***************************************/
600
601 void
fl_delete_folder_bynumber(FL_OBJECT * ob,int num)602 fl_delete_folder_bynumber( FL_OBJECT * ob,
603 int num )
604 {
605 int i = num - 1;
606 FLI_TABFOLDER_SPEC *sp = ob->spec;
607 FL_OBJECT *deleted = NULL;
608 FL_FORM *theform = NULL;
609
610 if ( i >= 0 && i < sp->nforms )
611 {
612 int j;
613
614 deleted = sp->title[ i ];
615 fli_detach_form( theform = sp->forms[ i ] );
616
617 for ( j = i + 1; j < sp->nforms; j++ )
618 {
619 sp->title[ j - 1 ] = sp->title[ j ];
620 sp->title[ j - 1 ]->argument = j - 1;
621 sp->forms[ j - 1 ] = sp->forms[ j ];
622 }
623
624 sp->nforms--;
625 sp->forms = fl_realloc( sp->forms, sp->nforms * sizeof *sp->forms );
626 sp->title = fl_realloc( sp->title, sp->nforms * sizeof *sp->title );
627 }
628
629 if ( deleted )
630 {
631 fli_set_object_visibility( deleted, FL_INVISIBLE );
632
633 if ( theform->form_callback == form_cb )
634 theform->form_callback = NULL;
635
636 if ( theform->visible == FL_VISIBLE )
637 fl_hide_form( theform );
638
639 /* Change active folder if need to */
640
641 sp->last_active = -1;
642
643 if ( i < sp->active_folder )
644 sp->active_folder--;
645 else if ( i == sp->active_folder )
646 {
647 sp->active_folder = -1;
648 fl_set_folder_bynumber( ob, i );
649 }
650
651 fl_free_object( deleted );
652
653 fl_redraw_form( ob->form );
654 }
655 }
656
657
658 /***************************************
659 ***************************************/
660
661 FL_FORM *
fl_get_tabfolder_folder_bynumber(FL_OBJECT * ob,int num)662 fl_get_tabfolder_folder_bynumber( FL_OBJECT * ob,
663 int num )
664 {
665 FLI_TABFOLDER_SPEC *sp = ob->spec;
666 int i = num - 1;
667
668 return ( i >= 0 && i < sp->nforms ) ? sp->forms[ i ] : NULL;
669 }
670
671
672 /***************************************
673 ***************************************/
674
675 FL_FORM *
fl_get_tabfolder_folder_byname(FL_OBJECT * ob,const char * name)676 fl_get_tabfolder_folder_byname( FL_OBJECT * ob,
677 const char * name )
678 {
679 int i;
680 FLI_TABFOLDER_SPEC *sp = ob->spec;
681
682 for ( i = 0; i < sp->nforms; i++ )
683 if ( strcmp( sp->title[ i ]->label, name ) == 0 )
684 return fl_get_tabfolder_folder_bynumber( ob, i + 1 );
685
686 return NULL;
687 }
688
689
690 /***************************************
691 ***************************************/
692
693 FL_FORM *
fl_get_tabfolder_folder_byname_f(FL_OBJECT * ob,const char * fmt,...)694 fl_get_tabfolder_folder_byname_f( FL_OBJECT * ob,
695 const char * fmt,
696 ...)
697 {
698 FL_FORM *f;
699 char *buf;
700
701 EXPAND_FORMAT_STRING( buf, fmt );
702 f = fl_get_tabfolder_folder_byname( ob, buf );
703 fl_free( buf );
704 return f;
705 }
706
707
708 /***************************************
709 ***************************************/
710
711 void
fl_delete_folder(FL_OBJECT * ob,FL_FORM * form)712 fl_delete_folder( FL_OBJECT * ob,
713 FL_FORM * form )
714 {
715 int i, done;
716 FLI_TABFOLDER_SPEC *sp = ob->spec;
717
718 for ( done = i = 0; ! done && i < sp->nforms; i++ )
719 if ( form == sp->forms[ i ] )
720 done = i + 1;
721
722 if ( done )
723 fl_delete_folder_bynumber( ob, done );
724 }
725
726
727 /***************************************
728 ***************************************/
729
730 void
fl_set_folder(FL_OBJECT * ob,FL_FORM * form)731 fl_set_folder( FL_OBJECT * ob,
732 FL_FORM * form )
733 {
734 FLI_TABFOLDER_SPEC *sp;
735 int i,
736 done;
737
738 if ( ! IsFolderClass( ob ) )
739 {
740 M_err( "fl_set_folder", "%s is not tabfolder",
741 ob ? ob->label : "null" );
742 return;
743 }
744
745 sp = ob->spec;
746 for ( done = i = 0; ! done && i < sp->nforms; i++ )
747 if ( sp->forms[ i ] == form )
748 {
749 program_switch( sp->title[ i ], i );
750 done = 1;
751 }
752 }
753
754
755 /***************************************
756 ***************************************/
757
758 void
fl_set_folder_byname(FL_OBJECT * ob,const char * name)759 fl_set_folder_byname( FL_OBJECT * ob,
760 const char * name )
761 {
762 FLI_TABFOLDER_SPEC *sp;
763 int i,
764 done;
765
766 if ( ! IsFolderClass( ob ) )
767 {
768 M_err( "fl_set_folder_byname", "%s is not tabfolder",
769 ob ? ob->label : "null" );
770 return;
771 }
772
773 sp = ob->spec;
774 for ( done = i = 0; ! done && i < sp->nforms; i++ )
775 if ( strcmp( sp->title[ i ]->label, name ) == 0 )
776 {
777 program_switch( sp->title[ i ], i );
778 done = 1;
779 }
780 }
781
782
783 /***************************************
784 ***************************************/
785
786 void
fl_set_folder_byname_f(FL_OBJECT * ob,const char * fmt,...)787 fl_set_folder_byname_f( FL_OBJECT * ob,
788 const char * fmt,
789 ... )
790 {
791 char *buf;
792
793 EXPAND_FORMAT_STRING( buf, fmt );
794 fl_set_folder_byname( ob, buf );
795 fl_free( buf );
796 }
797
798
799 /***************************************
800 ***************************************/
801
802 void
fl_set_folder_bynumber(FL_OBJECT * ob,int num)803 fl_set_folder_bynumber( FL_OBJECT * ob,
804 int num )
805 {
806 FLI_TABFOLDER_SPEC *sp;
807 int i = num - 1;
808
809 if ( ! IsFolderClass( ob ) )
810 {
811 M_err( "fl_set_folder_bynumber", "%s is not tabfolder",
812 ob ? ob->label : "null" );
813 return;
814 }
815
816 sp = ob->spec;
817 if ( i >= 0 && i < sp->nforms )
818 program_switch( sp->title[ i ], i );
819 }
820
821
822 /***************************************
823 * Keep tab but replace the folder content
824 ***************************************/
825
826 void
fl_replace_folder_bynumber(FL_OBJECT * ob,int num,FL_FORM * form)827 fl_replace_folder_bynumber( FL_OBJECT * ob,
828 int num,
829 FL_FORM * form )
830 {
831 FLI_TABFOLDER_SPEC *sp = ob->spec;
832 int i = num - 1;
833
834 if ( i >= 0 && i < sp->nforms && sp->forms[ i ] != form )
835 {
836 sp->forms[ i ] = form;
837
838 if ( i == sp->active_folder )
839 {
840 sp->active_folder = -1;
841 program_switch( sp->title[ i ], i );
842 }
843 }
844 }
845
846
847 /***************************************
848 ***************************************/
849
850 int
fl_get_folder_number(FL_OBJECT * ob)851 fl_get_folder_number( FL_OBJECT * ob )
852 {
853 if ( ! IsFolderClass( ob ) )
854 {
855 M_err( "fl_get_folder_number", "%s is not tabfolder",
856 ob ? ob->label : "null" );
857 return 0;
858 }
859
860 return ( ( FLI_TABFOLDER_SPEC * ) ob->spec )->last_active + 1;
861 }
862
863
864 /***************************************
865 ***************************************/
866
867 int
fl_get_active_folder_number(FL_OBJECT * ob)868 fl_get_active_folder_number( FL_OBJECT * ob )
869 {
870 if ( ! IsFolderClass( ob ) )
871 {
872 M_err( "fl_get_active_folder_number", "%s is not tabfolder",
873 ob ? ob->label : "null" );
874 return 0;
875 }
876
877 return ( ( FLI_TABFOLDER_SPEC * ) ob->spec )->active_folder + 1;
878 }
879
880
881 /***************************************
882 ***************************************/
883
884 FL_FORM *
fl_get_folder(FL_OBJECT * ob)885 fl_get_folder( FL_OBJECT * ob )
886 {
887 FLI_TABFOLDER_SPEC *sp;
888
889 if ( ! IsFolderClass( ob ) )
890 {
891 M_err( "fl_get_folder", "%s is not tabfolder",
892 ob ? ob->label : "null" );
893 return NULL;
894 }
895
896 sp = ob->spec;
897 return sp->last_active >= 0 ? sp->forms[ sp->last_active ] : NULL;
898 }
899
900
901 /***************************************
902 ***************************************/
903
904 const char *
fl_get_folder_name(FL_OBJECT * ob)905 fl_get_folder_name( FL_OBJECT * ob )
906 {
907 FLI_TABFOLDER_SPEC *sp;
908
909 if ( ! IsFolderClass( ob ) )
910 {
911 M_err( "fl_get_folder_name", "%s is not tabfolder",
912 ob ? ob->label : "null" );
913 return NULL;
914 }
915
916 sp = ob->spec;
917 return sp->last_active >= 0 ? sp->title[ sp->last_active ]->label : NULL;
918 }
919
920
921 /***************************************
922 ***************************************/
923
924 FL_FORM *
fl_get_active_folder(FL_OBJECT * ob)925 fl_get_active_folder( FL_OBJECT * ob )
926 {
927 FLI_TABFOLDER_SPEC *sp;
928
929 if ( ! IsFolderClass( ob ) )
930 {
931 M_err( "fl_get_active_folder", "%s is not tabfolder",
932 ob ? ob->label : "null" );
933 return NULL;
934 }
935
936 sp = ob->spec;
937
938 return ( sp->forms && sp->active_folder >= 0 ) ?
939 sp->forms[ sp->active_folder ] : NULL;
940 }
941
942
943 /***************************************
944 ***************************************/
945
946 const char *
fl_get_active_folder_name(FL_OBJECT * ob)947 fl_get_active_folder_name( FL_OBJECT * ob )
948 {
949 FLI_TABFOLDER_SPEC *sp;
950
951 if ( ! IsFolderClass( ob ) )
952 {
953 M_err( "fl_get_active_folder_name", "%s is not tabfolder",
954 ob ? ob->label : "null" );
955 return NULL;
956 }
957
958 sp = ob->spec;
959 return sp->active_folder >= 0 ?
960 sp->title[ sp->active_folder ]->label : NULL;
961 }
962
963
964 /***************************************
965 ***************************************/
966
967 void
fl_get_folder_area(FL_OBJECT * ob,FL_Coord * x,FL_Coord * y,FL_Coord * w,FL_Coord * h)968 fl_get_folder_area( FL_OBJECT * ob,
969 FL_Coord * x,
970 FL_Coord * y,
971 FL_Coord * w,
972 FL_Coord * h )
973 {
974 FLI_TABFOLDER_SPEC *sp = ob->spec;
975
976 compute_position( ob );
977 *x = sp->canvas->x;
978 *y = sp->canvas->y;
979 *w = sp->canvas->w;
980 *h = sp->canvas->h;
981 }
982
983
984 /***************************************
985 ***************************************/
986
987 int
fl_get_tabfolder_offset(FL_OBJECT * obj)988 fl_get_tabfolder_offset( FL_OBJECT * obj )
989 {
990 return ( ( FLI_TABFOLDER_SPEC * ) obj->spec )->offset;
991 }
992
993
994 /***************************************
995 ***************************************/
996
997 int
fl_set_tabfolder_offset(FL_OBJECT * obj,int offset)998 fl_set_tabfolder_offset( FL_OBJECT * obj,
999 int offset )
1000 {
1001 FLI_TABFOLDER_SPEC *sp = obj->spec;
1002 int old = sp->offset;
1003
1004 if ( offset < 0 )
1005 offset = 0;
1006 else if ( offset + sp->num_visible + 1 > sp->nforms - 1 )
1007 offset = sp->nforms - sp->num_visible;
1008
1009 if ( offset != sp->offset )
1010 {
1011 shift_tabs( obj, offset - sp->offset );
1012 fl_redraw_form( obj->form );
1013 }
1014
1015 return old;
1016 }
1017
1018
1019 /***************************************
1020 * Compute the position and propagate the parent attributes
1021 ***************************************/
1022
1023 static void
compute_top_position(FL_OBJECT * ob)1024 compute_top_position( FL_OBJECT * ob )
1025 {
1026 FLI_TABFOLDER_SPEC *sp ;
1027 FL_OBJECT *tab;
1028 int i,
1029 max_h = 4;
1030
1031 sp = ob->objclass == FL_TABFOLDER ? ob->spec : ob->u_vdata;
1032
1033 sp->y = ob->y + 1;
1034 sp->x = sp->canvas->x - FL_abs( sp->canvas->bw );
1035
1036 for ( i = 0; i < sp->offset; i++ )
1037 sp->title[ i ]->x = 2000;
1038
1039 /* This gets the fl_get_folder_area() right (single line tab) - even if
1040 empty folder */
1041
1042 if ( sp->nforms == 0 )
1043 {
1044 int junk;
1045 get_tabsize( ob, "AjbY", &junk, &max_h, 1 );
1046 }
1047
1048 for ( i = sp->offset; i < sp->nforms; i++ )
1049 {
1050 tab = sp->title[ i ];
1051 get_tabsize( ob, tab->label, &tab->w, &tab->h, 1 );
1052 if ( tab->h > max_h )
1053 max_h = tab->h;
1054 tab->x = sp->x;
1055 tab->y = sp->y;
1056 sp->x += tab->w + ( ob->bw > 0 );
1057 if ( sp->x < sp->canvas->x + sp->canvas->w - 2 )
1058 {
1059 sp->num_visible = i;
1060 tab->boxtype &= ~ FLI_BROKEN_BOX;
1061 tab->align = FL_ALIGN_CENTER;
1062 tab->visible = 1;
1063 }
1064 else if ( ( tab->w -= sp->x - sp->canvas->x - sp->canvas->w ) > 0 )
1065 {
1066 tab->boxtype |= FLI_BROKEN_BOX;
1067 tab->align = fl_to_inside_lalign( FL_ALIGN_LEFT );
1068 tab->visible = 1;
1069 }
1070 else
1071 {
1072 tab->w = 20;
1073 tab->visible = 0;
1074 }
1075 }
1076
1077 for ( i = 0; i < sp->nforms; i++ )
1078 sp->title[ i ]->h = max_h;
1079
1080 /* This will be the canvas location */
1081
1082 if ( ob->objclass == FL_TABFOLDER )
1083 {
1084 if ( ob->type != FL_BOTTOM_TABFOLDER )
1085 sp->canvas->y = sp->y + max_h - ( ob->bw < 0 );
1086 }
1087 else
1088 {
1089 if ( sp->parent->type != FL_BOTTOM_TABFOLDER )
1090 sp->canvas->y = sp->y + max_h - ( ob->bw < 0 );
1091 }
1092
1093 sp->canvas->h = ob->h - max_h - FL_abs( ob->bw ) - 1;
1094 sp->max_h = max_h;
1095 fl_set_object_color( sp->canvas, ob->col1, ob->col2 );
1096 }
1097
1098
1099 /***************************************
1100 ***************************************/
1101
1102 static void
compute_bottom_position(FL_OBJECT * ob)1103 compute_bottom_position( FL_OBJECT * ob )
1104 {
1105 FLI_TABFOLDER_SPEC *sp;
1106 FL_OBJECT *tab;
1107 int i,
1108 max_h = 4,
1109 absbw = FL_abs( ob->bw );
1110
1111 sp = ob->objclass == FL_TABFOLDER ? ob->spec:ob->u_vdata;
1112 sp->x = ob->x;
1113
1114 if ( sp->nforms == 0 )
1115 {
1116 int junk;
1117 get_tabsize( ob, "AjbY", &junk, &max_h, -1 );
1118 }
1119
1120 for ( i = 0; i < sp->nforms; i++ )
1121 {
1122 tab = sp->title[ i ];
1123 get_tabsize( ob, tab->label, &tab->w, &tab->h, -1 );
1124 if ( tab->h > max_h )
1125 max_h = tab->h;
1126 tab->x = sp->x;
1127 sp->x += tab->w + ( ob->bw > 0 );
1128 }
1129
1130 sp->canvas->h = ob->h - 2 * absbw - max_h - 1;
1131 sp->y = sp->canvas->y + sp->canvas->h + absbw - ( ob->bw < 0 );
1132
1133 for ( i = 0; i < sp->nforms; i++ )
1134 {
1135 sp->title[ i ]->h = max_h;
1136 sp->title[ i ]->y = sp->y;
1137 }
1138
1139 sp->max_h = max_h;
1140 fl_set_object_color( sp->canvas, ob->col1, ob->col2 );
1141 }
1142
1143
1144 /***************************************
1145 ***************************************/
1146
1147 static void
compute_position(FL_OBJECT * ob)1148 compute_position( FL_OBJECT * ob )
1149 {
1150 if ( ob->type == FL_BOTTOM_TABFOLDER )
1151 compute_bottom_position( ob );
1152 else
1153 compute_top_position( ob );
1154 }
1155
1156
1157 /***************************************
1158 ***************************************/
1159
1160 int
fl_set_tabfolder_autofit(FL_OBJECT * ob,int y)1161 fl_set_tabfolder_autofit( FL_OBJECT * ob,
1162 int y )
1163 {
1164 FLI_TABFOLDER_SPEC *sp = ob->spec;
1165 int old = sp->auto_fit;
1166
1167 sp->auto_fit = y;
1168 return old;
1169 }
1170
1171
1172 /***************************************
1173 ***************************************/
1174
1175 static void
shift_tabs(FL_OBJECT * ob,int left)1176 shift_tabs( FL_OBJECT * ob,
1177 int left )
1178 {
1179 FLI_TABFOLDER_SPEC *sp = ob->u_vdata;
1180 int newp = sp->offset + left;
1181
1182 if ( newp < 0 )
1183 newp = 0;
1184
1185 if ( newp == sp->offset )
1186 return;
1187
1188 sp->offset = newp;
1189
1190 compute_position( ob );
1191 }
1192
1193
1194 /***************************************
1195 ***************************************/
1196
1197 void
fli_set_tab_color(FL_OBJECT * obj,FL_COLOR col1,FL_COLOR col2)1198 fli_set_tab_color( FL_OBJECT * obj,
1199 FL_COLOR col1,
1200 FL_COLOR col2 )
1201 {
1202 FLI_TABFOLDER_SPEC *sp = obj->spec;
1203 int i;
1204
1205 for ( i = 0; i < sp->nforms; i++ )
1206 fl_set_object_color( sp->title[ i ], col1, col2 );
1207 }
1208
1209
1210 /***************************************
1211 ***************************************/
1212
1213 void
fli_set_tab_lcolor(FL_OBJECT * obj,FL_COLOR lcol)1214 fli_set_tab_lcolor( FL_OBJECT * obj,
1215 FL_COLOR lcol )
1216 {
1217 FLI_TABFOLDER_SPEC *sp = obj->spec;
1218 int i;
1219
1220 for ( i = 0; i < sp->nforms; i++ )
1221 fl_set_object_lcolor( sp->title[ i ], lcol );
1222 }
1223
1224
1225 /***************************************
1226 ***************************************/
1227
1228 void
fli_set_tab_lsize(FL_OBJECT * obj,int lsize)1229 fli_set_tab_lsize( FL_OBJECT * obj,
1230 int lsize )
1231 {
1232 FLI_TABFOLDER_SPEC *sp = obj->spec;
1233 int i;
1234
1235 for ( i = 0; i < sp->nforms; i++ )
1236 fl_set_object_lsize( sp->title[ i ], lsize );
1237 }
1238
1239
1240 /***************************************
1241 ***************************************/
1242
1243 void
fli_set_tab_lstyle(FL_OBJECT * obj,int lstyle)1244 fli_set_tab_lstyle( FL_OBJECT * obj,
1245 int lstyle )
1246 {
1247 FLI_TABFOLDER_SPEC *sp = obj->spec;
1248 int i;
1249
1250 for ( i = 0; i < sp->nforms; i++ )
1251 fl_set_object_lstyle( sp->title[ i ], lstyle );
1252 }
1253
1254
1255 /***************************************
1256 ***************************************/
1257
1258 void
fli_set_tab_lalign(FL_OBJECT * obj,int align)1259 fli_set_tab_lalign( FL_OBJECT * obj,
1260 int align )
1261 {
1262 FLI_TABFOLDER_SPEC *sp = obj->spec;
1263 int i;
1264
1265 for ( i = 0; i < sp->nforms; i++ )
1266 fl_set_object_lalign( sp->title[ i ], align );
1267 }
1268
1269
1270 /***************************************
1271 ***************************************/
1272
1273 void
fli_set_tab_bw(FL_OBJECT * obj,int bw)1274 fli_set_tab_bw( FL_OBJECT * obj,
1275 int bw )
1276 {
1277 FLI_TABFOLDER_SPEC *sp = obj->spec;
1278 int i;
1279
1280 for ( i = 0; i < sp->nforms; i++ )
1281 fl_set_object_bw( sp->title[ i ], bw );
1282 }
1283
1284
1285 /*
1286 * Local variables:
1287 * tab-width: 4
1288 * indent-tabs-mode: nil
1289 * End:
1290 */
1291