## class fltk::Browser

### Class Hierarchy

    fltk::Widget
       |
       +----fltk::Group
               |
               +----fltk::Menu
                       |
                       +----fltk::Browser
                               |
                               +----fltk::MultiBrowser

### Include Files

    #include <fltk/Browser.h>

### Description

The `fltk::Browser` widget displays a scrolling vertical list of text widgets, possibly with a hierachial arrangement.

The items may be created as child widgets (usually the same widgets as are used to create menus: fltk::Item widgets, or fltk::ItemGroup widgets to make a hierarchy). Alternatively you can build simple text lists by using the add() method, which will create the child widgets for you (and even create a hierarchy if you put slashes in the text). You can also us an fltk::List which allows you to control the storage by dynamically creating a "fake" widget for the browser to use to draw each item.

All the functions used to add, remove, or modify items in the list are defined by the base class fltk::Menu. See that for much more information.

For a simple constant list you can populate the list by calling `browser->add("text of item")` once for each item. If you give the browser a callback you can find out what item was selected with `browser->value();`, the first item is zero (this is different from older versions of fltk that started at 1!), and will be negative if no item is selected. You can change the selected item with `browser->value(n)`.

The subclass fltk::MultiBrowser lets the user select more than one item at the same time.

#### Callbacks

You can control when callbacks are done with the `when()` method. The following values are useful, the default value is `fltk::WHEN_RELEASE`.

- `fltk::WHEN_NEVER` - Callback is never done. `changed()` can be used to see if the user has modified the browser.
- `fltk::WHEN_CHANGED` - Callback is done whenever the user changes the current item. If they drag the mouse through items the callback is done for each one, and the callback is done for each keystroke that changes the selected item.
- `fltk::WHEN_RELEASE` - Callback is done when the user releases the mouse and the selected item has changed, and on any keystroke that changes the item.
- `fltk::WHEN_RELEASE_ALWAYS` - Callback is done when the user releases the mouse even if the current item has not changed, and on any arrow keystroke even when at the top or bottom of the browser. You must use this if you want to detect the user double-clicking an item.
- `fltk::WHEN_ENTER_KEY` - Callback is only done if the user hits the Enter key and some item is selected. In the current version the callback is also done if the user double-clicks a non-parent item.

### Methods

- fltk::Browser
- ~Browser
- box_height
- box_width
- column_widths
- current_index
- current_level
- current_position
- focus_index
- focus_level
- focus_position
- format_char
- goto_focus

- goto_index
- goto_position
- goto_top
- height
- hscrollbar
- indented
- item_is_parent
- item_is_visible
- make_item_visible
- next
- next_visible
- previous_visible
- scrollbar

- set_focus
- set_item_opened
- set_item_visible
- topline
- topline
- value
- value
- width
- xposition
- xposition
- yposition
- yposition

#### fltk::Browser::Browser(int, int, int, int, const char * = 0)

The constructor makes an empty browser.

#### fltk::Browser::~Browser(void)

The destructor deletes all the list items (because they are child fltk::Widgets of an fltk::Group) and destroys the browser.

#### int width() const

The width of the longest item in the browser, measured in pixels. If this is changed (by adding or deleting items or opening or closing a parent item) then layout() must be called before this is correct.

#### int height() const

The height of all the visible items in the browser, measured in pixels. If this is changed (by adding or deleting items or opening or closing a parent item) then `layout()` must be called before this is correct.

#### int box_width() const

The width of the display area of the browser in pixels, this is `w()` minus the edges of the `box()` minus the width of the vertical scrollbar, if visible. If this is changed (by resizing the widget, adding or deleting items or opening or closing a parent item such that the scrollbar visibility changes) then layout() must be called before this is correct.

#### int box_height() const

The height of the display area of the browser in pixels, this is `h()` minus the edges of the `box()` minus the height of the horizontal scrollbar, if visible. If this is changed (by resizing the widget, adding or deleting items or opening or closing a parent item such that the scrollbar visibility changes) then layout() must be called before this is correct.

#### int xposition() const

Current horizontal scrolling pozition. Normally zero.

#### void xposition(int);

Set the horizontal scrolling to a certain value.

#### int yposition() const

Current vertical scrolling position. This is the location, in pixels, of the top of the visible display, relative to the pixel position of the top of the first item.

#### void yposition(int);

Set the vertical scrolling to a certain value.

#### bool indented() const
void indented(bool v)

Turn this on to for space to be reserved for open/close boxes drawn to the left of top-level items. You usually want this for a hierarchial browser. This should be off for a flat browser, or to emulate Windows Explorer where "my computer" does not have an open/close to the left of it. The default value is `false`.

#### fltk::Scrollbar scrollbar;
fltk::Scrollbar hscrollbar;

The scrollbars are accessable as instance variables. You can alter their width or other attributes to customize the browser to your liking.

#### fltk::Widget* goto_top();

Because of the hierarchial structure it is difficult to identify an item in the browser. Instead of passing an identifier to all the calls that can modify an item, the browser provides several calls to set the "current" item and then calls to modify the current item.

This call sets the current item to the very first visible item in the browser. It returns the widget for that item, or null if the browser is empty.

If you have invisible items in the browser you should use `goto_index(0)` if you want to go to the first item even if it is invisible.

#### fltk::Widget* goto_focus()

Set the current item to the "focus" (the item with the dotted square in an `fltk::MultiBrowser`, and the selected item in a normal `fltk::Browser`.

#### fltk::Widget* goto_position(int y);

Set the current item to one at or before y pixels from top of the first item.

#### fltk::Widget* goto_index(const int* indexes, int level);

Go to a nested item. indexes must contain level+1 index numbers. The first number indicates the top-level item number, the second indicates the child number of that parent, and so on. This sets the current item to the given item. If the values are out of range then null is returned, otherwise the widget for that item.

#### fltk::Widget* goto_index(int);
fltk::Widget* goto_index(int,int);
fltk::Widget* goto_index(int,int,int);
fltk::Widget* goto_index(int,int,int,int);
fltk::Widget* goto_index(int,int,int,int,int);

These are the same as passing the number of arguments minus one as the level and the arguments as the index array to `goto_index()`. Passing a negative number as the first argument will set it to a special "no item" state where `select_only_this()` will do `deselect()`

#### fltk::Widget* item();

This is in fact a method on the base fltk::Menu class. This returns the widget that was jumped to by the last goto_index() or other similar call.

#### bool item_is_visible() const;

Return true if the item would be visible to the user if the browser was scrolled to the correct location. This means that the `fltk::INVISIBLE` flag is not set on it, and all parents of it are open and visible as well.

#### bool item_is_parent() const;

Return true if the current item is a parent. Notice that it may have zero children.

#### fltk::Widget* next();

Move the current item to the next item. If if is a parent it moves to the first child. If not a parent, it moves to the next child of it's parent. If it is the last child it moves to the parent's brother. Repeatedly calling this will visit every child of the browser. This returns the widget. If the current widget is the last one this returns null, but the current widget remains on the last one.

#### fltk::Widget* next_visible();

Move the current item to the next visible item. Invisible items are either hidden because their parent is closed or because they had `hide()` called on them.

#### fltk::Widget* previous_visible();

Move the current item to the previous visible item. Invisible items are either hidden because their parent is closed or because they had `hide()` called on them.

#### bool set_focus();

Change the focus (the selected item, or in an fltk::MultiBrowser the item that has a dotted box around it, and the current item selected with `goto_index()`. This calls make_item_visible().

#### void make_item_visible(enum = NOSCROLL)

This makes the current item visible to the user.

First it turns off the `fltk::INVISIBLE` flag on the current item, and turns off the `fltk::INVISIBLE` flag and opens (turning on the `fltk::VALUE` flag) all parent items. These flag changes cause flags_changed() to be called on any fltk::List that you have assigned to the browser.

The browser is then scrolled by calling `yposition()` so the item is visible. The optional argument tells how to scroll. If not specified (or the default value of `fltk::Browser::NOSCROLL` is given) then the browser is scrolled as little as possible to show the item. If it is `fltk::Browser::TOP` then the item is put at the top of the browser. If it is `fltk::Browser::MIDDLE` then the item is centered vertically in the browser. If it is `fltk::Browser::BOTTOM` then the item is put at the bottom of the browser.

This does nothing if the current item is null.

#### void damage_item();

Tell the browser to redraw the current item. Do this if you know it has changed appearance. This is better than redrawing the entire browser because it will blink a lot less.

#### bool set_item_opened(bool value);

If the current item is a parent, set the open state (the `fltk::VALUE` flags) to the given value and redraw the browser correctly. Returns true if the state was actually changed, returns false if it was already in that state.

#### bool set_item_visible(bool value);

Turn off or on the `fltk::INVISIBLE` flag on the given item and redraw the browser if necessary. Returns true if the state was actually changed, returns false if it was already in that state.

#### int current_level() const;

Return the nesting level of the current item (how many parents it has).

#### const int& current_index() const;

Return an array of `current_level()+1` indexes saying which child at each level includes the current item.

#### int current_position() const

Return the y position, in pixels, of the top edge of the current item. You may also want the height, which is in `item()->height()`.

#### int focus_level() const

Return the nesting level of the focus (how many parents it has). The focus is the selected item the user sees.

#### const int& focus_index() const

Return an array of `focus_level()+1` indexes saying which child at each level includes the focus.

#### int focus_position() const

Return the y position, in pixels, of the top edge of the focus item.

#### void value(int v)

Same as `goto_index(v);set_focus();`, to change the current item in a non-hierarchial browser.

#### int value() const;

Returns `focus_index(v)[0]`, to get the current item in a non-hierarchial browser.

#### char format_char() const;
void format_char(char c);

Sent to the `fltk::draw()` function to control the interpretation of leading symbol characters. This defaults to `'@'`.

#### const int *column_widths() const;
void column_widths(const int *pWidths)

Sets the horizontal locations that each `'\t'` character in an item should start printing text at. These are measured from the left edge of the browser, including any area for the open/close + glyphs.

#### int topline() const

Return the index of the top-level item that is at the top of the browser.

#### void topline(int line)

Same as `goto_index(line); make_item_visible(TOP);`.

This is the description of '@' commands, it should be moved to the fltk::draw() documentation:

A string of formatting codes at the start of each column are stripped off and used to modify how the rest of the line is printed:

- `@.` Print rest of line, don't look for more '@' signs
- `@@` Print rest of line starting with '@'
- `@l` Use a large (24 point) font
- `@m` Use a medium large (18 point) font
- `@s` Use a small (11 point) font
- `@b` Use a bold font (adds fltk::BOLD to font)
- `@i` Use an italic font (adds fltk::ITALIC to font)
- `@f` or `@t` Use a `fixed-pitch` font (sets font to fltk::COURIER)
- `@c` Center the line horizontally
- `@r` Right-justify the text
- `@B0, @B1, ... @B255` Fill the backgound with fltk::color(n)
- `@C0, @C1, ... @C255` Use fltk::color(n) to draw the text
- `@F0, @F1, ...` Use fltk::font(n) to draw the text
- `@S1, @S2, ...` Use point size n to draw the text
- `@u` or `@_` Underline the text.
- `@-` draw an engraved line through the middle.

Notice that the `@.` command can be used to reliably terminate the parsing. To print a random string in a random color, use `sprintf("@C%d@.%s", color, string)` and it will work even if the string starts with a digit or has the format character in it.