# ColumnListView

Derived from: public BListView

Declared in: ColumnListView.h

Library: none

##

## License

The source code, object code, libraries, and the other components of Santa's Gift Bag are being made publicly available and free to use in freeware and shareware products with a price under $25 (I believe that shareware should be cheap). For overpriced shareware (hehehe) or commercial products, please contact me to negotiate a commercial use license. After all, I did work hard on these classes and invested a lot of time into it. That being said, DON'T WORRY I don't want much. It totally depends on the sort of project you're working on and how much you expect to make off it. If someone makes money using my work, I'd like to get at least a little something for my contribution to that profit.

If any of the components of Santa's Gift Bag are is used in a shareware or commercial product, I get a free copy. The source is made available so that you can improve and extend it as you need. In general it is best to customize these classes through inheritance, leaving the original Santa's Gift Bag source code unmodified, so that you can take advantage of enhancements and bug fixes as they become available.

Feel free to distribute any components of this archive, but you are required to keep the documentation and license with it. If you wish to distribute modified versions, also feel free to do so, but do so in such a manner that it is very clear what was modified, why, how, that it is not an official Santa's Gift Bag release, and you are also required to keep the documentation and license with any modified versions.

## Overview

A ColumnListView displays a list of items that can be structured either in a linear list or an outline form with items grouped under other items. The levels of the outline are indicated by successive levels of indentation.

The items in the list are themselves composed of entries arranged in columns. The ColumnListView displays a bar containing the column headings. The user may drag the columns to reorder or resize them, and those user actions affect all item entries in the column.

## Outline Structure

If a ColumnListView is specified to be hierarchical at construction, it will behave like a BOutlineListView. Otherwise, it will behave like a BListView. In a hierarchical ColumnListView, if an item has other items under it--that is, if the immediately following item in the list is at a deeper level of the outline--it is a superitem; the items grouped under it are its subitems. Superitems are marked by a triangular icon or latch, in the usual interface for hypertext lists. Note that simply adding an item at a level deeper than the preceding item does not automatically make the preceding item a superitem. Superitems should be set as such when they are constructed, or should be set as such using `CLVListItem::SetSuperItem()`. It is important that a sensible outline structure be maintained. `AddItem()` and `AddList()` respect the superitem and level status of the items being added, and therefore allow improper outline structures to be created. This is allowed because it is assumed that the structure will be corrected through the addition of another item or items with the appropriate properties and in the proper position. `Expand()`, `Collapse()`, and `SortItems()` will give bizarre behavior if the outline is not structured properly. These functions can be invoked by user actions, so it is very important not to leave the outline structure in an incorrect state with the window's BLooper unlocked.

The user can collapse or expand sections of the outline by manipulating the latch. When a section is collapsed, only the superitem for that section is visible (and the latch points to the superitem). All items that follow the superitem are hidden, up to the next item that's not at a deeper outline level. When a section is expanded, subitems are visible (and the latch points downward).

## Inherited Functions

The ColumnListView class inherits much of its functionality from the BListView class. However, in a hierarchical ColumnListView, those inherited functions are concerned only with the expanded sections of the list, not with sections that are hidden because they're collapsed. If an inherited function returns an index or takes an index as an argument, the index counts just the items that are shown on-screen (or could be shown on-screen if they were scrolled into the visible region of the view). `DoForEach()` skips items that can't be displayed. `CountItems()` counts items only in the expanded sections of the list. For non-hierarchical ColumnListViews, it is best to use these functions to manipulate the list, as you would for a BListView. These functions are documented in BListView.

However, ColumnListView implements the extra functions that the BOutlineListView class itself defines to deal with all sections of the list, expanded or collapsed. For these functions, an index counts all items in the list, whether visible or not.

The class defines some functions that match those it inherits, but its versions prefix `FullList`... to the function name and don't ignore any items. For example, `FullListCountItems()` counts every item in the list and `FullListDoForEach()` doesn't skip items in collapsed sections.

## Hook Functions

`ColumnWidthChanged()` | Can be implemented to find out when a column's width has been changed, usually by the user dragging the resize handle.
`DisplayOrderChanged()` | Can be implemented to find out when the column order has been changed, usually by the user dragging a column into a new position.
`InitiateDrag()` | Can be implemented to permit users to drag items--for example, to reorder items in the list. Inherited from BListView, documented there.
`SelectionChanged()` | Can be implemented to take collateral action each time the selection changes. Inherited from BListView, documented there.
`SortingChanged()` | Can be implemented to find out when the sorting keys, order or mode changes.

## Constructor and Destructor

### ColumnListView()

``

          ColumnListView(BRect frame, CLVContainerView** containerView, const char* name = NULL,
                   uint32 resizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP,
                   uint32 flags = B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE,
                   list_view_type type = B_SINGLE_SELECTION_LIST, bool hierarchical = false,
                   bool horizontal = true, bool vertical = true, bool scroll_view_corner = true,
                   border_style border = B_NO_BORDER, const BFont* labelFont = be_plain_font)
          ColumnListView(BMessage *archive)    /*Not implemented*/

Initializes the ColumnListView. As is indirectly the case for any BScrollView, the frame rectangle will not be the border of the entire ColumnListView. It will be the border of the ColumnListView itself and column header sections only. If scrollbars and/or a border are requested, the whole ColumnListView (actually the container view) will be larger than the frame rectangle. A ColumnListView should not itself be added directly as a child in a BView hierarchy. Instead, containerView is used to return a pointer to a CLVContainerView that holds the ColumnListView. containerView may not be `NULL`. This container view should be added to the view hierarchy as if it were the ColumnListView itself. The reason for this is ColumnListView inherits from BListView, so that the BListView and ColumnListView functions can be further overridden by custom classes that may inherit from ColumnListView. A result of this structure is that the column header view is actually a sibling, not a child, of the ColumnListView. Thus it is necessary for the column header view and main list view to be contained in another view, the container view. This container view is a BScrollView, which will also contain the horizontal and vertical scroll bars and border, if they are requested. If no scroll bars or border is requested, the BScrollView simply acts like a container BView. It may have made more sense to have ColumnListView inherit from BScrollView, so that the object created by the ColumnListView constructor would be the whole ColumnListView, however then BListView would have been a member of ColumnListView, making it impossible for classes that inherit from ColumnListView to override the BListView functions, and making BListView's list manipulation functions less accessible.

resizingMode and flags are what you would expect for any BView.

type is the same as for a BListView: `B_SINGLE_SELECTION_LIST` or `B_MULTIPLE_SELECTION_LIST`.

horizontal and vertical are used to specify whether horizontal and/or vertical scroll bars should be provided. If scroll bars are provided, it is not necessary for their ranges and proportions to be maintained by the program, as that function is handled by ColumnListView.

border is used to request a border around the ColumnListView and its scrollbars if applicable. The normal border style constants `B_NO_BORDER`, `B_PLAIN_BORDER`, and `B_FANCY_BORDER` apply.

labelFont is used to specify the font used in the column headers. The column headers will be sized vertically to accommodate the requested font.

Construction from an archive is currently not implemented. It isn't high on my priorities, since archival is not something I'm making use of. If someone needs this functionality and fills it in, please send me the modified code so that others can benefit from it.

See also: the BListView constructor, the BScrollBar constructor

### CreateContainer()

``

          virtual CLVContainerView* CreateContainer(bool horizontal, bool vertical,
                   bool scroll_view_corner, border_style border, uint32 resizing_mode,
                   uint32 flags)

Creates the container which will hold the ColumnListView. This can be overridden by derived classes which want to create a container which is itself derived from CLVContainerView, but with specialized behavior beyond the normal CLVContainerView implementation.

### ~ColumnListView()

``

          virtual ~ColumnListView()

Removes all CLVColumns from the ColumnListView and deletes them. Once a CLVColumn has been added to a ColumnListView, the program need not worry about deleting it - it is handled automatically. However, that is not the case if the program removes a column from the ColumnListView using `RemoveColumn()`. If a column is removed, deletion of the CLVColumn is again the program's responsibility.

As is the case for any BListView, CLVListItems are not deleted automatically when the ColumnListView is deleted.

As for any BView, deleting a ColumnListView while it is part of a view hierarchy is an error. Remove the container view, not the ColumnListView from the hierarchy before deleting it. Once the container view has been removed from the view hierarchy, deleting the ColumnListView also deletes the container view, as the container view was created during construction of the ColumnListView. If the container view has been added to a view hierarchy and the window is deleted, or the container view is otherwise deleted automatically, the peculiar situation arises where the container view itself invokes deletion of the ColumnListView. This is not a problem, as ColumnListView knows how to deal with the situation.

## Member Functions

### AddColumn()

          virtual bool AddColumn(CLVColumn* column)

Adds a column. It will be added at the end of the column list. Columns are always identified by the order in which they are added to the ColumnListView. However, the indices are always contiguous from 0-N, so if a column is removed, it will change the index by which the columns which followed it are referred to. For example, if a list had three columns with indices 0, 1, 2, but column 0 is removed, the indices of the remaining columns (formerly 1, 2) will be 0, 1. The order in which the columns are displayed is available through `GetDisplayOrder()` , and can be set using `SetDisplayOrder()` , but the display order is used solely for display - never for identification of the columns. A column may only be added to one ColumnListView at a time, and never more than once to the same ColumnListView without removing it inbetween using `RemoveColumn()` or `RemoveColumns()`. Expander columns may only be added to a hierarchical ColumnListView, and only one Expander column may be added to a ColumnListView.

See also: the CLVColumn constructor, `AddColumnList()`, `CountColumns()`, `ColumnAt()`, `IndexOfColumn(), RemoveColumn()`.

### AddColumnList()

          virtual bool AddColumnList(BList* newColumns)

Adds a list of columns. They will be added at the end of the column list. Columns are always identified by the order in which they are added to the ColumnListView. However, the indices are always contiguous from 0-N, so if a column is removed, it will change the index by which the columns which followed it are referred to. For example, if a list had three columns with indices 0, 1, 2, but column 0 is removed, the indices of the remaining columns (formerly 1, 2) will be 0, 1. The order in which the columns are displayed is available through `GetDisplayOrder()` , and can be set using `SetDisplayOrder()` , but the display order is used solely for display - never for identification of the columns. A column may only be added to one ColumnListView at a time, and never more than once to the same ColumnListView without removing it inbetween using `RemoveColumn()` or `RemoveColumns()`. Expander columns may only be added to a hierarchical ColumnListView, and only one Expander column may be added to a ColumnListView.

See also: the CLVColumn constructor, `AddColumn()`

### AddItem(), AddUnder()

          virtual bool AddItem(BListItem *item)
          virtual bool AddItem(BListItem *item, int32 index)

          virtual bool AddUnder(BListItem *item, BListItem *superitem)

These functions add an item to the list. `AddItem()` adds the item at index--where the index counts all items assigned to the ColumnListView--or, if an index isn't specified, at the end of the list. The two versions of this function override their BListView counterparts to ensure that the item is correctly entered into the outline in a hierarchical ColumnListView. If the item is added to a portion of the list that is collapsed, it won't be visible.

`AddUnder()` adds an item immediately after another item in the list and at one outline level deeper. The level of the item is modified accordingly. Thus, the item already in the list becomes the superitem for the newly added item. If its new superitem is collapsed or is in a collapsed part of the list, the item will not be visible. `AddUnder()` only works for hierarchical ColumnListViews.

Unlike `AddUnder()`, `AddItem()` respects the outline level of the item, and therefore will allow improper outline structures to be created. This is allowed because it is assumed that the structure will be corrected through the addition of another item or items with the appropriate properties and in the proper position. `Expand()`, `Collapse()`, and `SortItems()` will give bizarre behavior if the outline is not structured properly. These functions can be invoked by user actions, so it is very important not to leave the outline structure in an incorrect state with the window's BLooper unlocked.

Adding an item does not automatically sort the list. If necessary, call `SortItems()` once the items have been added.

Sorting the items will rearrange their positions and therefore change their indices, so it is best to refer to items by a CLVListItem* rather than by index.

Even though these functions take a BListItem*, the items must actually be CLVListItems.

See also: `BListView::AddItem(),BOutlineListView::AddUnder()`, the CLVListItem class

### AddList()

          virtual bool AddList(BList *newItems)
          virtual bool AddList(BList *newItems, int32 index)

Adds a group of items to the list just as `AddItem()` adds a single item. The index counts all items assigned to the ColumnListView. The newItems BList must contain pointers to CLVListItem objects. `AddList()` respects the outline level of the item, and therefore will allow improper outline structures to be created. This is allowed because it is assumed that the structure will be corrected through the addition of another item or items with the appropriate properties and in the proper position. `Expand()`, `Collapse()`, and `SortItems()` will give bizarre behavior if the outline is not structured properly. These functions can be invoked by user actions, so it is very important not to leave the outline structure in an incorrect state with the window's BLooper unlocked.

Adding a list does not automatically sort the list. If necessary, call `SortItems()` once the items have been added.

See also: `BListView::AddList()`

### AddScrollViewCorner()

          void AddScrollViewCorner()

Adds a filler view between the horizontal and vertical scroll bars. If you use both horizonal and vertical scroll bars, and the ColumnListView isn't set into the lower right corner of a B_DOCUMENT_WINDOW, then you'll need this to avoid having a hole in your view hierarchy that will leave graphic fragments.

### Archive()

          virtual status_t Archive(BMessage *archive, bool deep = true) const

Currently not implemented. It isn't high on my priorities, since archival is not something I'm making use of. If someone needs this functionality and fills it in, please send me the modified code so that others can benefit from it.

See also: `BListView::Archive()`, `Instantiate()` static function

### Collapse(), Expand()

          void Collapse(CLVListItem *item)

          void Expand(CLVListItem *item)

These functions collapse and expand the section of the list controlled by the item superitem. If item isn't a superitem, it is nevertheless flagged as expanded or collapsed so that it will behave appropriately in case it does become a superitem.

See also: `CLVListItem::SetExpanded()`

### ColumnAt()

          CLVColumn* ColumnAt(int32 column_index) const

Returns the column at the specified index in the ColumnListView.

See also: `AddColumn()`

### ColumnWidthChanged()

          virtual void ColumnWidthChanged(int32 columnIndex, float newWidth)

Used to find out when a column's width has been changed, usually by the user dragging a resize handle, although `ColumnWidthChanged()` is called by `CLVColumn::SetWidth()` regardless of whether the width was changed by the user or by the program.

See also: `CLVColumn::SetWidth()`

### CountColumns()

          int32 CountColumns() const

Returns the number of columns that have been added to the ColumnListView.

See also: `AddColumn()`

### DisplayOrderChanged()

          virtual void DisplayOrderChanged(const int32* order)

Used to find out when the display order of the columns has been changed, usually by the user dragging a column to a new position. order points to an array of int32's the same length as the number of columns. The array will contain the indices of the columns in the order in which they are displayed. For example, if columns A,B,C are identified by indices 0,1,2, and are displayed in the order B,C,A, the order array will contain the numbers 1,2,0.

See also: `GetDisplayOrder()`

### FullListCountItems(), FullListCurrentSelection(), FullListFirstItem(), FullListLastItem(), FullListIndexOf(), FullListItemAt(), FullListHasItem(), FullListIsEmpty(), FullListDoForEach()

          int32 FullListCountItems(void) const

          int32 FullListCurrentSelection(int32 index = 0) const

          CLVListItem *FullListFirstItem(void) const

          CLVListItem *FullListLastItem(void) const

          int32 FullListIndexOf(BPoint point) const
          int32 FullListIndexOf(CLVListItem *item) const

          CLVListItem *FullListItemAt(int32 index) const

          bool FullListHasItem(CLVListItem *item) const

          bool FullListIsEmpty(void) const

          void FullListDoForEach(bool (*func)(CLVListItem *))
          void FullListDoForEach(bool (*func)(CLVListItem *, void *), void *)

These functions parallel a similar set of functions defined in the BListView class. The BListView functions have identical names, but without the `FullList`... prefix. When applied to a ColumnListView object, the inherited functions consider only items in sections of the outline that can be displayed on-screen--that is, they skip over items in collapsed portions of the list if the ColumnListView is hierarchical.

These ColumnListView functions, on the other hand, consider all items in the list. For example, `IndexOf()` and `FullListIndexOf()` both return an index to a given item. However, for `IndexOf()` the index is to the position of the item in the list that can be currently displayed, but for `FullListIndexOf()` it's to the item's position in the full list, including collapsed sections.

These functions should only be used for hierarchical ColumnListViews.

### FullListNumberOfSubitems()

          int32 FullListNumberOfSubitems(const CLVListItem* item) const

In a hierarchical ColumnListView, counts the number of subitems contained under the specified item.

This function should only be used for hierarchical ColumnListViews.

### IndexOfColumn()

          int32 IndexOfColumn(CLVColumn* column) const

Returns the index of the specified column in the ColumnListView.

See also: `AddColumn()`

### IsExpanded()

          bool IsExpanded(int32 index) const

Returns `true` if the item at index is marked as controlling an expanded section of the list, and `false` if it's marked as controlling a collapsed section or if there's no item at that index. If a superitem is expanded, the ColumnListView can display its subitems; if not, the subitems are hidden.

The index passed to this function is the position in the full list of items assigned to the ColumnListView.

See also: `BListItem::IsExpanded()`

### ItemSelectColor(), SetItemSelectColor(),

          rgb_color ItemSelectColor() const
          rgb_color ItemSelectColor(bool window_active) const
          void SetItemSelectColor(bool window_active, rgb_color color) const

``

`ItemSelectColor()` returns the color that should be used for the background highlighting of selected items when the window is active or inactive, depending on the window_active parameter. The function with no argument returns the color that should be used for the background highlighting of selected items in the window's current state. `SetItemSelectColor()` sets the corresponding colors. Note that these in no way affect the rendering of CLVListItems. It is entirely up to the CLVListItems' `DrawItemColumn()` function to call these functions and make use of the result. CLVEasyItem uses the item select colors.

### KeyDown()

          virtual void KeyDown(const char *bytes, int32 numBytes)

Augments the inherited version of `KeyDown()` to allow users to navigate the outline hierarchy using the arrow keys and to expand or collapse sections of the outline using Control-arrow key combinations.

See also: `BListView::KeyDown()`

### MakeEmpty()

          virtual void MakeEmpty(void)

Overrides the BListView version of `MakeEmpty()` to remove all items from the list. The BListView version of this function won't work on a hierarchical ColumnListView.

See also: `BListView::MakeEmpty()`

### MouseDown()

          virtual void MouseDown(BPoint point)

Augments the inherited version of `MouseDown()` to permit users to expand and collapse sections of the outline by clicking on an item's latch.

See also: `BView::MouseDown()`

### RemoveColumn(), RemoveColumns()

          virtual bool RemoveColumn(CLVColumn* column)
          virtual bool RemoveColumns(CLVColumn* column, int32 count)

These functions remove one or more columns from the ColumnListView. Removal of a column will change the index by which the columns which followed it are referred to. For example, if a list had three columns with indices 0, 1, 2, but column 0 is removed, the indices of the remaining columns (formerly 1, 2) will be 0, 1.

See also: CLVColumn, `AddColumn()`, `AddColumns()`

### RemoveItem(), RemoveItems()

          virtual bool RemoveItem(BListItem *item)
          virtual CLVListItem *RemoveItem(int32 index)

          virtual bool RemoveItems(int32 index, int32 count)

These functions work like their BListView counterparts, except that:

- They can remove items from any part of the list, including collapsed sections. The index counts all items assigned to the ColumnListView; the specified item can be hidden if it is in a hierarchical list view.
- If the item being removed is a superitem, they also remove all of its subitems.

Note: The BListView versions of these functions will not produce reliable results when applied to a hierarchical ColumnListView, even if the item being removed is in an expanded section of the list and is not a superitem.

See also: `BListView::RemoveItem()`

### SetDisplayOrder(), GetDisplayOrder()

          virtual bool SetDisplayOrder(const int32* order)

          void GetDisplayOrder(int32* order) const

Sets or returns the display order of the columns. The order array should point to an array of int32's the same length as the number of columns. The array passed as input to `SetDisplayOrder()` should contain the indices of the columns in the order in which they are displayed. For example, if columns A,B,C are identified by indices 0,1,2, and are displayed in the order B,C,A, the order array should contain the numbers 1,2,0. The order array passed to `GetDisplayOrder()` should likewise be an array of int32's the same length as the number of columns, and it will be filled in to indicate the orderof the columns in the same format as the input to `SetDisplayOrder()`. Overriding SetDisplayOrder will not inform you of changes to the column order caused by the user dragging a column. To find out about all changes to column order, override `DisplayOrderChanged()`. Note that `SetDisplayOrder()` also calls `DisplayOrderChanged()`, so `DisplayOrderChanged()` is the most appropriate place for the program to keep track of the display order (saving the order for the next time a document is loaded, for example).

See also: CLVColumn, `DisplayOrderChanged()`

### SetSortFunction()

          void SetSortFunction(CLVCompareFuncPtr compare)

Sets the function used in sorting the list. The sorting function should be defined as follows:

``

`int CompareFunc(const CLVListItem* item1, const CLVListItem* item2, int32 sort_key)`

The compare function should return a negative number if the first item is ordered before the second, a positive number if the second comes before the first, and 0 if the two items are ordered equivalently. compare should assume ascending order, and should perform the comparison using the column specified in the sort_key argument as the sort key.

See also: `SortItems()`

### SetSortKey(), AddSortKey()

          virtual void SetSortKey(int32 columnIndex)

          virtual void AddSortKey(int32 columnIndex)

Sets the column used as the key for sorting items. columnIndex is based on the order in which the columns were added to the ColumnListView, not the display order. Set the sort key to -1 to eliminate sorting. AddSortKey adds a secondary sort key to be used for further sorting of items which are sorted equivalently by the primary sort key. Any number of secondary sort keys may be added.

See also: `SortItems()` `, SetSortFunction(), SetSortMode()`

### SetSortMode(), ReverseSortMode(), GetSorting(), SetSorting(), SortingChanged()

``

          virtual void SetSortMode(int32 columnIndex,CLVSortMode mode)

          void ReverseSortMode(int32 columnIndex)

          int32 GetSorting(int32* sortKeys,CLVSortMode* sortModes) const

          void SetSorting(int32 numberOfKeys, int32* sortKeys, CLVSortMode* sortModes)

          virtual void SortingChanged()

`SetSortMode()` sets the sort mode used for sorting items in the ColumnListView. The sort modes are `NoSort, Ascending`, and `Descending`. Note: sorting will only occur if the key column is shown. Also, setting a sort mode won't cause sorting to occur on the given column; the column must be selected as a sort key as well.`` `ReverseSortMode()` toggles through the three sort modes, calling `SetSortMode()` to accomplish this. `GetSorting()` returns the number of used sort keys, and fills the provided array with the sort keys, in priority order. The sortKeys pointer should point to an array int sortKeys[n], where n is the number of sortable columns in the ColumnListView, and the entries in the array are column indices in priority order, so the first entry is the column index of the primary sorting column, and so on. Likewise, sortModes should point to an array CLVSortMode sortModes[n], where n is the same as for sortKeys, and the mode at sortModes[0] applies to the column whose index is indicated in sortKeys[0], and so on. `SetSorting()` is used to set all sort keys and modes in the same format as returned by `GetSorting()`. `SetSortMode()` should be overridden in order to filter out particular sort modes. This typically should not be necessary. Override `SortingChanged()` to detect changes to the sorting keys, order or mode.

See also: `SortItems()` `, SetSortFunction(), SetSortKey()`

### SortItems()

          void SortItems()

Rearranges the items in the list. The items are sorted using the compareFunc comparison function and the isTrue functions set using `SetSortFunction()`. Using the results returned by compareFunc and istrue, and based on the sort key, sort mode, bool group key and bool group mode the user has selected, the sorting will be performed. In a non-hierarchical ColumnListView, a plain linear sort of the list will be performed. In a hierarchical ColumnListView, the outermost level will be sorted as specified, then for each item which is a superitem, the contents will be sorted accordingly, and so on so that the outline hierarchy is maintained through the sort.

Sorting the items will rearrange their positions and therefore change their indices, so it is best to refer to items by a CLVListItem* rather than by index.

See also: `SetSortFunction(), SetSortKey(), SetSortMode(), Items(), BList::SortItems()`

### Superitem()

          CLVListItem *Superitem(const CLVListItem *item)

Returns the superitem for the item passed as an argument--that is, the item under which the argument item is grouped--or `NULL` if the item is at the outermost level of the outline (level 0) or isn't in the list.

By Brian Tietz

Copyright 1997-2000

Bug reports (including documentation errors) and feature requests can be sent to briant@timelinevista.com.