themes: Workaround for bug where a background color of RGB 0,0,0 in Black color schem...
[ntk.git] / src / Fl_Browser.cxx
blobd62b4f4db28f16dc41602437c5015e032aa3cf00
1 //
2 // "$Id: Fl_Browser.cxx 8736 2011-05-24 20:00:56Z AlbrechtS $"
3 //
4 // Browser widget for the Fast Light Tool Kit (FLTK).
5 //
6 // Copyright 1998-2010 by Bill Spitzak and others.
7 //
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Library General Public
10 // License as published by the Free Software Foundation; either
11 // version 2 of the License, or (at your option) any later version.
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Library General Public License for more details.
18 // You should have received a copy of the GNU Library General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 // USA.
23 // Please report all bugs and problems on the following page:
25 // http://www.fltk.org/str.php
28 #include <FL/Fl.H>
29 #include <FL/Fl_Browser.H>
30 #include <FL/fl_draw.H>
31 #include "flstring.h"
32 #include <stdlib.h>
33 #include <math.h>
35 #if defined(FL_DLL) // really needed for c'tors for MS VC++ only
36 #include <FL/Fl_Hold_Browser.H>
37 #include <FL/Fl_Multi_Browser.H>
38 #include <FL/Fl_Select_Browser.H>
39 #endif
41 // I modified this from the original Forms data to use a linked list
42 // so that the number of items in the browser and size of those items
43 // is unlimited. The only problem is that the old browser used an
44 // index number to identify a line, and it is slow to convert from/to
45 // a pointer. I use a cache of the last match to try to speed this up.
47 // Also added the ability to "hide" a line. This sets its height to
48 // zero, so the Fl_Browser_ cannot pick it.
50 #define SELECTED 1
51 #define NOTDISPLAYED 2
53 // WARNING:
54 // Fl_File_Chooser.cxx also has a definition of this structure (FL_BLINE).
55 // Changes to FL_BLINE *must* be reflected in Fl_File_Chooser.cxx as well.
56 // This hack in Fl_File_Chooser should be solved.
58 struct FL_BLINE { // data is in a linked list of these
59 FL_BLINE* prev;
60 FL_BLINE* next;
61 void* data;
62 Fl_Image* icon;
63 short length; // sizeof(txt)-1, may be longer than string
64 char flags; // selected, displayed
65 char txt[1]; // start of allocated array
68 /**
69 Returns the very first item in the list.
70 Example of use:
71 \code
72 // Walk the browser from beginning to end
73 for ( void *i=item_first(); i; i=item_next(i) ) {
74 printf("item label='%s'\n", item_text(i));
76 \endcode
77 \returns The first item, or NULL if list is empty.
78 \see item_first(), item_last(), item_next(), item_prev()
80 void* Fl_Browser::item_first() const {return first;}
82 /**
83 Returns the next item after \p item.
84 \param[in] item The 'current' item
85 \returns The next item after \p item, or NULL if there are none after this one.
86 \see item_first(), item_last(), item_next(), item_prev()
88 void* Fl_Browser::item_next(void* item) const {return ((FL_BLINE*)item)->next;}
90 /**
91 Returns the previous item before \p item.
92 \param[in] item The 'current' item
93 \returns The previous item before \p item, or NULL if there none before this one.
94 \see item_first(), item_last(), item_next(), item_prev()
96 void* Fl_Browser::item_prev(void* item) const {return ((FL_BLINE*)item)->prev;}
98 /**
99 Returns the very last item in the list.
100 Example of use:
101 \code
102 // Walk the browser in reverse, from end to start
103 for ( void *i=item_last(); i; i=item_prev(i) ) {
104 printf("item label='%s'\n", item_text(i));
106 \endcode
107 \returns The last item, or NULL if list is empty.
108 \see item_first(), item_last(), item_next(), item_prev()
110 void* Fl_Browser::item_last() const {return last;}
113 See if \p item is selected.
114 \param[in] item The item whose selection state is to be checked.
115 \returns 1 if selected, 0 if not.
116 \see select(), selected(), value(), item_select(), item_selected()
118 int Fl_Browser::item_selected(void* item) const {
119 return ((FL_BLINE*)item)->flags&SELECTED;
122 Change the selection state of \p item to the value \p val.
123 \param[in] item The item to be changed.
124 \param[in] val The new selection state: 1 selects, 0 de-selects.
125 \see select(), selected(), value(), item_select(), item_selected()
127 void Fl_Browser::item_select(void *item, int val) {
128 if (val) ((FL_BLINE*)item)->flags |= SELECTED;
129 else ((FL_BLINE*)item)->flags &= ~SELECTED;
133 Returns the label text for \p item.
134 \param[in] item The item whose label text is returned.
135 \returns The item's text string. (Can be NULL)
137 const char *Fl_Browser::item_text(void *item) const {
138 return ((FL_BLINE*)item)->txt;
142 Returns the item for specified \p line.
144 Note: This call is slow. It's fine for e.g. responding to user
145 clicks, but slow if called often, such as in a tight sorting loop.
146 Finding an item 'by line' involves a linear lookup on the internal
147 linked list. The performance hit can be significant if the browser's
148 contents is large, and the method is called often (e.g. during a sort).
149 If you're writing a subclass, use the protected methods item_first(),
150 item_next(), etc. to access the internal linked list more efficiently.
152 \param[in] line The line number of the item to return. (1 based)
153 \retval item that was found.
154 \retval NULL if line is out of range.
155 \see item_at(), find_line(), lineno()
157 FL_BLINE* Fl_Browser::find_line(int line) const {
158 int n; FL_BLINE* l;
159 if (line == cacheline) return cache;
160 if (cacheline && line > (cacheline/2) && line < ((cacheline+lines)/2)) {
161 n = cacheline; l = cache;
162 } else if (line <= (lines/2)) {
163 n = 1; l = first;
164 } else {
165 n = lines; l = last;
167 for (; n < line && l; n++) l = l->next;
168 for (; n > line && l; n--) l = l->prev;
169 ((Fl_Browser*)this)->cacheline = line;
170 ((Fl_Browser*)this)->cache = l;
171 return l;
175 Returns line number corresponding to \p item, or zero if not found.
176 Caveat: See efficiency note in find_line().
177 \param[in] item The item to be found
178 \returns The line number of the item, or 0 if not found.
179 \see item_at(), find_line(), lineno()
181 int Fl_Browser::lineno(void *item) const {
182 FL_BLINE* l = (FL_BLINE*)item;
183 if (!l) return 0;
184 if (l == cache) return cacheline;
185 if (l == first) return 1;
186 if (l == last) return lines;
187 if (!cache) {
188 ((Fl_Browser*)this)->cache = first;
189 ((Fl_Browser*)this)->cacheline = 1;
191 // assume it is near cache, search both directions:
192 FL_BLINE* b = cache->prev;
193 int bnum = cacheline-1;
194 FL_BLINE* f = cache->next;
195 int fnum = cacheline+1;
196 int n = 0;
197 for (;;) {
198 if (b == l) {n = bnum; break;}
199 if (f == l) {n = fnum; break;}
200 if (b) {b = b->prev; bnum--;}
201 if (f) {f = f->next; fnum++;}
203 ((Fl_Browser*)this)->cache = l;
204 ((Fl_Browser*)this)->cacheline = n;
205 return n;
209 Removes the item at the specified \p line.
210 Caveat: See efficiency note in find_line().
211 You must call redraw() to make any changes visible.
212 \param[in] line The line number to be removed. (1 based) Must be in range!
213 \returns Pointer to browser item that was removed (and is no longer valid).
214 \see add(), insert(), remove(), swap(int,int), clear()
216 FL_BLINE* Fl_Browser::_remove(int line) {
217 FL_BLINE* ttt = find_line(line);
218 deleting(ttt);
220 cacheline = line-1;
221 cache = ttt->prev;
222 lines--;
223 full_height_ -= item_height(ttt);
224 if (ttt->prev) ttt->prev->next = ttt->next;
225 else first = ttt->next;
226 if (ttt->next) ttt->next->prev = ttt->prev;
227 else last = ttt->prev;
229 return(ttt);
233 Remove entry for given \p line number, making the browser one line shorter.
234 You must call redraw() to make any changes visible.
235 \param[in] line Line to be removed. (1 based) \n
236 If \p line is out of range, no action is taken.
237 \see add(), insert(), remove(), swap(int,int), clear()
239 void Fl_Browser::remove(int line) {
240 if (line < 1 || line > lines) return;
241 free(_remove(line));
245 Insert specified \p item above \p line.
246 If \p line > size() then the line is added to the end.
248 Caveat: See efficiency note in find_line().
250 \param[in] line The new line will be inserted above this line (1 based).
251 \param[in] item The item to be added.
253 void Fl_Browser::insert(int line, FL_BLINE* item) {
254 if (!first) {
255 item->prev = item->next = 0;
256 first = last = item;
257 } else if (line <= 1) {
258 inserting(first, item);
259 item->prev = 0;
260 item->next = first;
261 item->next->prev = item;
262 first = item;
263 } else if (line > lines) {
264 item->prev = last;
265 item->prev->next = item;
266 item->next = 0;
267 last = item;
268 } else {
269 FL_BLINE* n = find_line(line);
270 inserting(n, item);
271 item->next = n;
272 item->prev = n->prev;
273 item->prev->next = item;
274 n->prev = item;
276 cacheline = line;
277 cache = item;
278 lines++;
279 full_height_ += item_height(item);
280 redraw_line(item);
284 Insert a new entry whose label is \p newtext \e above given \p line, optional data \p d.
286 Text may contain format characters; see format_char() for details.
287 \p newtext is copied using the strdup() function, and can be NULL to make a blank line.
289 The optional void * argument \p d will be the data() of the new item.
291 \param[in] line Line position for insert. (1 based) \n
292 If \p line > size(), the entry will be added at the end.
293 \param[in] newtext The label text for the new line.
294 \param[in] d Optional pointer to user data to be associated with the new line.
296 void Fl_Browser::insert(int line, const char* newtext, void* d) {
297 int l = strlen(newtext);
298 FL_BLINE* t = (FL_BLINE*)malloc(sizeof(FL_BLINE)+l);
299 t->length = (short)l;
300 t->flags = 0;
301 strcpy(t->txt, newtext);
302 t->data = d;
303 t->icon = 0;
304 insert(line, t);
308 Line \p from is removed and reinserted at \p to.
309 Note: \p to is calculated \e after line \p from gets removed.
310 \param[in] to Destination line number (calculated \e after line \p from is removed)
311 \param[in] from Line number of item to be moved
313 void Fl_Browser::move(int to, int from) {
314 if (from < 1 || from > lines) return;
315 insert(to, _remove(from));
319 Sets the text for the specified \p line to \p newtext.
321 Text may contain format characters; see format_char() for details.
322 \p newtext is copied using the strdup() function, and can be NULL to make a blank line.
324 Does nothing if \p line is out of range.
326 \param[in] line The line of the item whose text will be changed. (1 based)
327 \param[in] newtext The new string to be assigned to the item.
329 void Fl_Browser::text(int line, const char* newtext) {
330 if (line < 1 || line > lines) return;
331 FL_BLINE* t = find_line(line);
332 int l = strlen(newtext);
333 if (l > t->length) {
334 FL_BLINE* n = (FL_BLINE*)malloc(sizeof(FL_BLINE)+l);
335 replacing(t, n);
336 cache = n;
337 n->data = t->data;
338 n->icon = t->icon;
339 n->length = (short)l;
340 n->flags = t->flags;
341 n->prev = t->prev;
342 if (n->prev) n->prev->next = n; else first = n;
343 n->next = t->next;
344 if (n->next) n->next->prev = n; else last = n;
345 free(t);
346 t = n;
348 strcpy(t->txt, newtext);
349 redraw_line(t);
353 Sets the user data for specified \p line to \p d.
354 Does nothing if \p line is out of range.
355 \param[in] line The line of the item whose data() is to be changed. (1 based)
356 \param[in] d The new data to be assigned to the item. (can be NULL)
358 void Fl_Browser::data(int line, void* d) {
359 if (line < 1 || line > lines) return;
360 find_line(line)->data = d;
364 Returns height of \p item in pixels.
365 This takes into account embedded \@ codes within the text() label.
366 \param[in] item The item whose height is returned.
367 \returns The height of the item in pixels.
368 \see item_height(), item_width(),\n
369 incr_height(), full_height()
371 int Fl_Browser::item_height(void *item) const {
372 FL_BLINE* l = (FL_BLINE*)item;
373 if (l->flags & NOTDISPLAYED) return 0;
375 int hmax = 2; // use 2 to insure we don't return a zero!
377 if (!l->txt[0]) {
378 // For blank lines set the height to exactly 1 line!
379 fl_font(textfont(), textsize());
380 int hh = fl_height();
381 if (hh > hmax) hmax = hh;
382 } else {
383 const int* i = column_widths();
384 long int dummy;
385 // do each column separately as they may all set different fonts:
386 for (char* str = l->txt; str && *str; str++) {
387 Fl_Font font = textfont(); // default font
388 int tsize = textsize(); // default size
389 while (*str==format_char()) {
390 str++;
391 switch (*str++) {
392 case 'l': case 'L': tsize = 24; break;
393 case 'm': case 'M': tsize = 18; break;
394 case 's': tsize = 11; break;
395 case 'b': font = (Fl_Font)(font|FL_BOLD); break;
396 case 'i': font = (Fl_Font)(font|FL_ITALIC); break;
397 case 'f': case 't': font = FL_COURIER; break;
398 case 'B':
399 case 'C': dummy = strtol(str, &str, 10); break;// skip a color number
400 case 'F': font = (Fl_Font)strtol(str,&str,10); break;
401 case 'S': tsize = strtol(str,&str,10); break;
402 case 0: case '@': str--;
403 case '.': goto END_FORMAT;
406 END_FORMAT:
407 char* ptr = str;
408 if (ptr && *i++) str = strchr(str, column_char());
409 else str = NULL;
410 if((!str && *ptr) || (str && ptr < str)) {
411 fl_font(font, tsize); int hh = fl_height();
412 if (hh > hmax) hmax = hh;
414 if (!str || !*str) break;
418 if (l->icon && (l->icon->h()+2)>hmax) {
419 hmax = l->icon->h() + 2; // leave 2px above/below
421 return hmax; // previous version returned hmax+2!
425 Returns width of \p item in pixels.
426 This takes into account embedded \@ codes within the text() label.
427 \param[in] item The item whose width is returned.
428 \returns The width of the item in pixels.
429 \see item_height(), item_width(),\n
430 incr_height(), full_height()
432 int Fl_Browser::item_width(void *item) const {
433 FL_BLINE* l=(FL_BLINE*)item;
434 char* str = l->txt;
435 const int* i = column_widths();
436 int ww = 0;
438 while (*i) { // add up all tab-separated fields
439 char* e;
440 e = strchr(str, column_char());
441 if (!e) break; // last one occupied by text
442 str = e+1;
443 ww += *i++;
446 // OK, we gotta parse the string and find the string width...
447 int tsize = textsize();
448 Fl_Font font = textfont();
449 int done = 0;
451 while (*str == format_char_ && str[1] && str[1] != format_char_) {
452 long int dummy;
453 str ++;
454 switch (*str++) {
455 case 'l': case 'L': tsize = 24; break;
456 case 'm': case 'M': tsize = 18; break;
457 case 's': tsize = 11; break;
458 case 'b': font = (Fl_Font)(font|FL_BOLD); break;
459 case 'i': font = (Fl_Font)(font|FL_ITALIC); break;
460 case 'f': case 't': font = FL_COURIER; break;
461 case 'B':
462 case 'C': dummy = strtol(str, &str, 10); break;// skip a color number
463 case 'F': font = (Fl_Font)strtol(str, &str, 10); break;
464 case 'S': tsize = strtol(str, &str, 10); break;
465 case '.':
466 done = 1;
467 break;
468 case '@':
469 str--;
470 done = 1;
473 if (done)
474 break;
477 if (*str == format_char_ && str[1])
478 str ++;
480 if (ww==0 && l->icon) ww = l->icon->w();
482 fl_font(font, tsize);
483 return ww + int(fl_width(str)) + 6;
487 The height of the entire list of all visible() items in pixels.
488 This returns the accumulated height of *all* the items in the browser
489 that are not hidden with hide(), including items scrolled off screen.
490 \returns The accumulated size of all the visible items in pixels.
491 \see item_height(), item_width(),\n
492 incr_height(), full_height()
494 int Fl_Browser::full_height() const {
495 return full_height_;
499 The default 'average' item height (including inter-item spacing) in pixels.
500 This currently returns textsize() + 2.
501 \returns The value in pixels.
502 \see item_height(), item_width(),\n
503 incr_height(), full_height()
505 int Fl_Browser::incr_height() const {
506 return textsize()+2;
510 Draws \p item at the position specified by \p X \p Y \p W \p H.
511 The \p W and \p H values are used for clipping.
512 Should only be called within the context of an FLTK draw().
513 \param[in] item The item to be drawn
514 \param[in] X,Y,W,H position and size.
516 void Fl_Browser::item_draw(void* item, int X, int Y, int W, int H) const {
517 FL_BLINE* l = (FL_BLINE*)item;
518 char* str = l->txt;
519 const int* i = column_widths();
521 bool first = true; // for icon
522 while (W > 6) { // do each tab-separated field
523 int w1 = W; // width for this field
524 char* e = 0; // pointer to end of field or null if none
525 if (*i) { // find end of field and temporarily replace with 0
526 e = strchr(str, column_char());
527 if (e) {*e = 0; w1 = *i++;}
529 // Icon drawing code
530 if (first) {
531 first = false;
532 if (l->icon) {
533 l->icon->draw(X+2,Y+1); // leave 2px left, 1px above
534 int iconw = l->icon->w()+2;
535 X += iconw; W -= iconw; w1 -= iconw;
538 int tsize = textsize();
539 Fl_Font font = textfont();
540 Fl_Color lcol = textcolor();
541 Fl_Align talign = FL_ALIGN_LEFT;
542 // check for all the @-lines recognized by XForms:
543 //#if defined(__GNUC__)
544 //#warning FIXME This maybe needs to be more UTF8 aware now...?
545 //#endif /*__GNUC__*/
546 while (*str == format_char() && *++str && *str != format_char()) {
547 long int dummy;
548 switch (*str++) {
549 case 'l': case 'L': tsize = 24; break;
550 case 'm': case 'M': tsize = 18; break;
551 case 's': tsize = 11; break;
552 case 'b': font = (Fl_Font)(font|FL_BOLD); break;
553 case 'i': font = (Fl_Font)(font|FL_ITALIC); break;
554 case 'f': case 't': font = FL_COURIER; break;
555 case 'c': talign = FL_ALIGN_CENTER; break;
556 case 'r': talign = FL_ALIGN_RIGHT; break;
557 case 'B':
558 if (!(l->flags & SELECTED)) {
559 fl_color((Fl_Color)strtol(str, &str, 10));
560 fl_rectf(X, Y, w1, H);
561 } else dummy = strtol(str, &str, 10);
562 break;
563 case 'C':
564 lcol = (Fl_Color)strtol(str, &str, 10);
565 break;
566 case 'F':
567 font = (Fl_Font)strtol(str, &str, 10);
568 break;
569 case 'N':
570 lcol = FL_INACTIVE_COLOR;
571 break;
572 case 'S':
573 tsize = strtol(str, &str, 10);
574 break;
575 case '-':
576 fl_color(FL_DARK3);
577 fl_line(X+3, Y+H/2, X+w1-3, Y+H/2);
578 fl_color(FL_LIGHT3);
579 fl_line(X+3, Y+H/2+1, X+w1-3, Y+H/2+1);
580 break;
581 case 'u':
582 case '_':
583 fl_color(lcol);
584 fl_line(X+3, Y+H-1, X+w1-3, Y+H-1);
585 break;
586 case '.':
587 goto BREAK;
588 case '@':
589 str--; goto BREAK;
592 BREAK:
593 fl_font(font, tsize);
594 if (l->flags & SELECTED)
595 lcol = fl_contrast(lcol, selection_color());
596 if (!active_r()) lcol = fl_inactive(lcol);
597 fl_color(lcol);
598 fl_draw(str, X+3, Y, w1-6, H, e ? Fl_Align(talign|FL_ALIGN_CLIP) : talign, 0, 0);
599 if (!e) break; // no more fields...
600 *e = column_char(); // put the separator back
601 X += w1;
602 W -= w1;
603 str = e+1;
607 static const int no_columns[1] = {0};
610 The constructor makes an empty browser.
611 \param[in] X,Y,W,H position and size.
612 \param[in] L label string, may be NULL.
614 Fl_Browser::Fl_Browser(int X, int Y, int W, int H, const char *L)
615 : Fl_Browser_(X, Y, W, H, L) {
616 column_widths_ = no_columns;
617 lines = 0;
618 full_height_ = 0;
619 cacheline = 0;
620 format_char_ = '@';
621 column_char_ = '\t';
622 first = last = cache = 0;
626 Updates the browser so that \p line is shown at position \p pos.
627 \param[in] line line number. (1 based)
628 \param[in] pos position.
629 \see topline(), middleline(), bottomline()
631 void Fl_Browser::lineposition(int line, Fl_Line_Position pos) {
632 if (line<1) line = 1;
633 if (line>lines) line = lines;
634 int p = 0;
636 FL_BLINE* l;
637 for (l=first; l && line>1; l = l->next) {
638 line--; p += item_height(l);
640 if (l && (pos == BOTTOM)) p += item_height (l);
642 int final = p, X, Y, W, H;
643 bbox(X, Y, W, H);
645 switch(pos) {
646 case TOP: break;
647 case BOTTOM: final -= H; break;
648 case MIDDLE: final -= H/2; break;
651 if (final > (full_height() - H)) final = full_height() -H;
652 position(final);
656 Returns the line that is currently visible at the top of the browser.
657 If there is no vertical scrollbar then this will always return 1.
658 \returns The lineno() of the top() of the browser.
660 int Fl_Browser::topline() const {
661 return lineno(top());
665 Removes all the lines in the browser.
666 \see add(), insert(), remove(), swap(int,int), clear()
668 void Fl_Browser::clear() {
669 for (FL_BLINE* l = first; l;) {
670 FL_BLINE* n = l->next;
671 free(l);
672 l = n;
674 full_height_ = 0;
675 first = 0;
676 last = 0;
677 lines = 0;
678 new_list();
682 Adds a new line to the end of the browser.
684 The text string \p newtext may contain format characters; see format_char() for details.
685 \p newtext is copied using the strdup() function, and can be NULL to make a blank line.
687 The optional void* argument \p d will be the data() for the new item.
689 \param[in] newtext The label text used for the added item
690 \param[in] d Optional user data() for the item (0 if unspecified)
691 \see add(), insert(), remove(), swap(int,int), clear()
693 void Fl_Browser::add(const char* newtext, void* d) {
694 insert(lines+1, newtext, d);
695 //Fl_Browser_::display(last);
699 Returns the label text for the specified \p line.
700 Return value can be NULL if \p line is out of range or unset.
701 The parameter \p line is 1 based.
702 \param[in] line The line number of the item whose text is returned. (1 based)
703 \returns The text string (can be NULL)
705 const char* Fl_Browser::text(int line) const {
706 if (line < 1 || line > lines) return 0;
707 return find_line(line)->txt;
711 Returns the user data() for specified \p line.
712 Return value can be NULL if \p line is out of range or no user data() was defined.
713 The parameter \p line is 1 based (1 will be the first item in the list).
714 \param[in] line The line number of the item whose data() is returned. (1 based)
715 \returns The user data pointer (can be NULL)
718 void* Fl_Browser::data(int line) const {
719 if (line < 1 || line > lines) return 0;
720 return find_line(line)->data;
724 Sets the selection state of the item at \p line to the value \p val.
725 If \p val is not specified, the default is 1 (selects the item).
726 \param[in] line The line number of the item to be changed. (1 based)
727 \param[in] val The new selection state (1=select, 0=de-select).
728 \returns 1 if the state changed, 0 if not.
729 \see select(), selected(), value(), item_select(), item_selected()
731 int Fl_Browser::select(int line, int val) {
732 if (line < 1 || line > lines) return 0;
733 return Fl_Browser_::select(find_line(line), val);
737 Returns 1 if specified \p line is selected, 0 if not.
738 \param[in] line The line being checked (1 based)
739 \returns 1 if item selected, 0 if not.
740 \see select(), selected(), value(), item_select(), item_selected()
742 int Fl_Browser::selected(int line) const {
743 if (line < 1 || line > lines) return 0;
744 return find_line(line)->flags & SELECTED;
748 Makes \p line visible, and available for selection by user.
749 Opposite of hide(int).
750 This changes the full_height() if the state was changed.
751 redraw() is called automatically if a change occurred.
752 \param[in] line The line to be shown. (1 based)
753 \see show(int), hide(int), display(), visible(), make_visible()
755 void Fl_Browser::show(int line) {
756 FL_BLINE* t = find_line(line);
757 if (t->flags & NOTDISPLAYED) {
758 t->flags &= ~NOTDISPLAYED;
759 full_height_ += item_height(t);
760 if (Fl_Browser_::displayed(t)) redraw();
765 Makes \p line invisible, preventing selection by the user.
766 The line can still be selected under program control.
767 This changes the full_height() if the state was changed.
768 When a line is made invisible, lines below it are moved up in the display.
769 redraw() is called automatically if a change occurred.
770 \param[in] line The line to be hidden. (1 based)
771 \see show(int), hide(int), display(), visible(), make_visible()
773 void Fl_Browser::hide(int line) {
774 FL_BLINE* t = find_line(line);
775 if (!(t->flags & NOTDISPLAYED)) {
776 full_height_ -= item_height(t);
777 t->flags |= NOTDISPLAYED;
778 if (Fl_Browser_::displayed(t)) redraw();
783 For back compatibility.
784 This calls show(line) if \p val is true, and hide(line) otherwise.
785 If \p val is not specified, the default is 1 (makes the line visible).
786 \see show(int), hide(int), display(), visible(), make_visible()
788 void Fl_Browser::display(int line, int val) {
789 if (line < 1 || line > lines) return;
790 if (val) show(line); else hide(line);
794 Returns non-zero if the specified \p line is visible, 0 if hidden.
795 Use show(int), hide(int), or make_visible(int) to change an item's visible state.
796 \param[in] line The line in the browser to be tested. (1 based)
797 \see show(int), hide(int), display(), visible(), make_visible()
799 int Fl_Browser::visible(int line) const {
800 if (line < 1 || line > lines) return 0;
801 return !(find_line(line)->flags&NOTDISPLAYED);
805 Returns the line number of the currently selected line, or 0 if none.
806 \returns The line number of current selection, or 0 if none selected.
807 \see select(), selected(), value(), item_select(), item_selected()
809 int Fl_Browser::value() const {
810 return lineno(selection());
814 Swap the two items \p a and \p b.
815 Uses swapping() to ensure list updates correctly.
816 \param[in] a,b The two items to be swapped.
817 \see swap(int,int), item_swap()
819 void Fl_Browser::swap(FL_BLINE *a, FL_BLINE *b) {
821 if ( a == b || !a || !b) return; // nothing to do
822 swapping(a, b);
823 FL_BLINE *aprev = a->prev;
824 FL_BLINE *anext = a->next;
825 FL_BLINE *bprev = b->prev;
826 FL_BLINE *bnext = b->next;
827 if ( b->prev == a ) { // A ADJACENT TO B
828 if ( aprev ) aprev->next = b; else first = b;
829 b->next = a;
830 a->next = bnext;
831 b->prev = aprev;
832 a->prev = b;
833 if ( bnext ) bnext->prev = a; else last = a;
834 } else if ( a->prev == b ) { // B ADJACENT TO A
835 if ( bprev ) bprev->next = a; else first = a;
836 a->next = b;
837 b->next = anext;
838 a->prev = bprev;
839 b->prev = a;
840 if ( anext ) anext->prev = b; else last = b;
841 } else { // A AND B NOT ADJACENT
842 // handle prev's
843 b->prev = aprev;
844 if ( anext ) anext->prev = b; else last = b;
845 a->prev = bprev;
846 if ( bnext ) bnext->prev = a; else last = a;
847 // handle next's
848 if ( aprev ) aprev->next = b; else first = b;
849 b->next = anext;
850 if ( bprev ) bprev->next = a; else first = a;
851 a->next = bnext;
853 // Disable cache -- we played around with positions
854 cacheline = 0;
855 cache = 0;
859 Swaps two browser lines \p a and \p b.
860 You must call redraw() to make any changes visible.
861 \param[in] a,b The two lines to be swapped. (both 1 based)
862 \see swap(int,int), item_swap()
864 void Fl_Browser::swap(int a, int b) {
865 if (a < 1 || a > lines || b < 1 || b > lines) return;
866 FL_BLINE* ai = find_line(a);
867 FL_BLINE* bi = find_line(b);
868 swap(ai,bi);
872 Set the image icon for \p line to the value \p icon.
873 Caller is responsible for keeping the icon allocated.
874 The \p line is automatically redrawn.
875 \param[in] line The line to be modified. If out of range, nothing is done.
876 \param[in] icon The image icon to be assigned to the \p line.
877 If NULL, any previous icon is removed.
879 void Fl_Browser::icon(int line, Fl_Image* icon) {
881 if (line<1 || line > lines) return;
883 FL_BLINE* bl = find_line(line);
885 int old_h = bl->icon ? bl->icon->h()+2 : 0; // init with *old* icon height
886 bl->icon = 0; // remove icon, if any
887 int th = item_height(bl); // height of text only
888 int new_h = icon ? icon->h()+2 : 0; // init with *new* icon height
889 if (th > old_h) old_h = th;
890 if (th > new_h) new_h = th;
891 int dh = new_h - old_h;
892 full_height_ += dh; // do this *always*
894 bl->icon = icon; // set new icon
895 if (dh>0) {
896 redraw(); // icon larger than item? must redraw widget
897 } else {
898 redraw_line(bl); // icon same or smaller? can redraw just this line
900 replacing(bl,bl); // recalc Fl_Browser_::max_width et al
904 Returns the icon currently defined for \p line.
905 If no icon is defined, NULL is returned.
906 \param[in] line The line whose icon is returned.
907 \returns The icon defined, or NULL if none.
909 Fl_Image* Fl_Browser::icon(int line) const {
910 FL_BLINE* l = find_line(line);
911 return(l ? l->icon : NULL);
915 Removes the icon for \p line.
916 It's ok to remove an icon if none has been defined.
917 \param[in] line The line whose icon is to be removed.
919 void Fl_Browser::remove_icon(int line) {
920 icon(line,0);
924 The following constructors must not be in the header file(s) if we
925 build a shared object (DLL). Instead they are defined here to force
926 the constructor (and default destructor as well) to be defined in
927 the DLL and exported (STR #2632, #2645).
929 Note: if you change any of them, do the same changes in the specific
930 header file as well. This redundant definition was chosen to enable
931 inline constructors in the header files (for static linking) as well
932 as those here for dynamic linking (Windows DLL).
934 #if defined(FL_DLL)
936 Fl_Hold_Browser::Fl_Hold_Browser(int X,int Y,int W,int H,const char *L)
937 : Fl_Browser(X,Y,W,H,L) {type(FL_HOLD_BROWSER);}
939 Fl_Multi_Browser::Fl_Multi_Browser(int X,int Y,int W,int H,const char *L)
940 : Fl_Browser(X,Y,W,H,L) {type(FL_MULTI_BROWSER);}
942 Fl_Select_Browser::Fl_Select_Browser(int X,int Y,int W,int H,const char *L)
943 : Fl_Browser(X,Y,W,H,L) {type(FL_SELECT_BROWSER);}
945 #endif // FL_DLL
948 // End of "$Id: Fl_Browser.cxx 8736 2011-05-24 20:00:56Z AlbrechtS $".