what Be's implementation did wrong but instead of taking almost 30 seconds to sort the MIME type database (roughly 1100 entries, and yes, that's why the original FileTypes is that slow when it has to show the internal types), this one needs only 4 ms for the same task (that's an amply 7500x speedup). * Implemented some more missing functions - it's by no means complete yet, though. * Rewrote OutlineListView.h, ListItem.h, and StringItem.h. * Fixed some minor bugs, but there are probably a lot more. * Major cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16349 a95241bf-73f2-0310-859d-f6bbb57e9c96
939 lines
17 KiB
C++
939 lines
17 KiB
C++
/*
|
|
* Copyright 2001-2006, Haiku Inc.
|
|
* Distributed under the terms of the MIT License.
|
|
*
|
|
* Authors:
|
|
* Marc Flerackers ([email protected])
|
|
* Axel Dörfler, [email protected]
|
|
*/
|
|
|
|
//! BOutlineListView represents a "nestable" list view.
|
|
|
|
#include <OutlineListView.h>
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
|
|
/*!
|
|
\brief A simple recursive quick sort implementations for BListItem arrays.
|
|
|
|
We need to implement it ourselves, since the BOutlineListView sort methods
|
|
use a different comparison function than the standard functions.
|
|
*/
|
|
static void
|
|
quick_sort_item_array(BListItem** items, int32 first, int32 last,
|
|
int (*compareFunc)(const BListItem* a, const BListItem* b))
|
|
{
|
|
if (last - 1 <= first)
|
|
return;
|
|
|
|
BListItem* pivot = items[first + (rand() % (last - first))];
|
|
// choose an arbitrary pivot element
|
|
|
|
int32 left = first;
|
|
int32 right = last;
|
|
|
|
do {
|
|
while (compareFunc(items[left], pivot) < 0) {
|
|
left++;
|
|
}
|
|
while (compareFunc(items[right], pivot) > 0) {
|
|
right--;
|
|
}
|
|
|
|
if (left <= right) {
|
|
// swap entries
|
|
BListItem* temp = items[left];
|
|
items[left] = items[right];
|
|
items[right] = temp;
|
|
|
|
left++;
|
|
right--;
|
|
}
|
|
} while (left <= right);
|
|
|
|
// At this point, the elements in the left half are all smaller
|
|
// than the elements in the right half
|
|
|
|
if (first < right) {
|
|
// sort left half
|
|
quick_sort_item_array(items, first, right, compareFunc);
|
|
}
|
|
if (left < last) {
|
|
// sort right half
|
|
quick_sort_item_array(items, left, last, compareFunc);
|
|
}
|
|
}
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
|
BOutlineListView::BOutlineListView(BRect frame, const char* name,
|
|
list_view_type type, uint32 resizeMode, uint32 flags)
|
|
: BListView(frame, name, type, resizeMode, flags)
|
|
{
|
|
}
|
|
|
|
|
|
BOutlineListView::BOutlineListView(BMessage* archive)
|
|
: BListView(archive)
|
|
{
|
|
}
|
|
|
|
|
|
BOutlineListView::~BOutlineListView()
|
|
{
|
|
fFullList.MakeEmpty();
|
|
}
|
|
|
|
|
|
BArchivable *
|
|
BOutlineListView::Instantiate(BMessage* archive)
|
|
{
|
|
if (validate_instantiation(archive, "BOutlineListView"))
|
|
return new BOutlineListView(archive);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
status_t
|
|
BOutlineListView::Archive(BMessage* archive, bool deep) const
|
|
{
|
|
return BListView::Archive(archive, deep);
|
|
}
|
|
|
|
|
|
void
|
|
BOutlineListView::MouseDown(BPoint point)
|
|
{
|
|
MakeFocus();
|
|
|
|
int32 index = IndexOf(point);
|
|
|
|
if (index != -1) {
|
|
BListItem *item = ItemAt(index);
|
|
|
|
if (item->fHasSubitems
|
|
&& LatchRect(ItemFrame(index), item->fLevel).Contains(point)) {
|
|
if (item->IsExpanded())
|
|
Collapse(item);
|
|
else
|
|
Expand(item);
|
|
} else
|
|
BListView::MouseDown(point);
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
BOutlineListView::KeyDown(const char* bytes, int32 numBytes)
|
|
{
|
|
if (numBytes == 1) {
|
|
switch (bytes[0]) {
|
|
case B_RIGHT_ARROW:
|
|
{
|
|
BListItem *item = ItemAt(CurrentSelection());
|
|
if (item && item->fHasSubitems)
|
|
Expand(item);
|
|
return;
|
|
}
|
|
|
|
case B_LEFT_ARROW:
|
|
{
|
|
BListItem *item = ItemAt(CurrentSelection());
|
|
if (item && item->fHasSubitems)
|
|
Collapse(item);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
BListView::KeyDown(bytes, numBytes);
|
|
}
|
|
|
|
|
|
void
|
|
BOutlineListView::FrameMoved(BPoint newPosition)
|
|
{
|
|
BListView::FrameMoved(newPosition);
|
|
}
|
|
|
|
|
|
void
|
|
BOutlineListView::FrameResized(float newWidth, float newHeight)
|
|
{
|
|
BListView::FrameResized(newWidth, newHeight);
|
|
}
|
|
|
|
|
|
void
|
|
BOutlineListView::MouseUp(BPoint where)
|
|
{
|
|
BListView::MouseUp(where);
|
|
}
|
|
|
|
|
|
bool
|
|
BOutlineListView::AddUnder(BListItem* item, BListItem* superitem)
|
|
{
|
|
fFullList.AddItem(item, FullListIndexOf(superitem) + 1);
|
|
|
|
item->fLevel = superitem->OutlineLevel() + 1;
|
|
superitem->fHasSubitems = true;
|
|
|
|
if (superitem->IsItemVisible() && superitem->IsExpanded()) {
|
|
item->SetItemVisible(true);
|
|
|
|
int32 index = BListView::IndexOf(superitem);
|
|
|
|
BListView::AddItem(item, index + 1);
|
|
Invalidate(LatchRect(ItemFrame(index), superitem->OutlineLevel()));
|
|
} else
|
|
item->SetItemVisible(false);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool
|
|
BOutlineListView::AddItem(BListItem* item)
|
|
{
|
|
if (!fFullList.AddItem(item))
|
|
return false;
|
|
|
|
return BListView::AddItem(item);
|
|
}
|
|
|
|
|
|
bool
|
|
BOutlineListView::AddItem(BListItem* item, int32 fullListIndex)
|
|
{
|
|
if (fullListIndex < 0)
|
|
fullListIndex = 0;
|
|
else if (fullListIndex > CountItems())
|
|
fullListIndex = CountItems();
|
|
|
|
fFullList.AddItem(item, fullListIndex);
|
|
|
|
if (item->fLevel > 0) {
|
|
BListItem *super = SuperitemForIndex(fullListIndex, item->fLevel);
|
|
|
|
if (!super->IsItemVisible() || !super->IsExpanded())
|
|
return true;
|
|
}
|
|
|
|
int32 list_index = FindPreviousVisibleIndex(fullListIndex);
|
|
|
|
return BListView::AddItem(item, IndexOf(FullListItemAt(list_index)) + 1);
|
|
}
|
|
|
|
|
|
bool
|
|
BOutlineListView::AddList(BList* newItems)
|
|
{
|
|
printf("BOutlineListView::AddList Not implemented\n");
|
|
return false;
|
|
}
|
|
|
|
|
|
bool
|
|
BOutlineListView::AddList(BList* newItems, int32 fullListIndex)
|
|
{
|
|
printf("BOutlineListView::AddList Not implemented\n");
|
|
return false;
|
|
}
|
|
|
|
|
|
bool
|
|
BOutlineListView::RemoveItem(BListItem* item)
|
|
{
|
|
if (!FullListHasItem(item))
|
|
return false;
|
|
|
|
fFullList.RemoveItem(item);
|
|
if (item->fVisible)
|
|
BListView::RemoveItem(item);
|
|
|
|
// TODO: remove children
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
BListItem*
|
|
BOutlineListView::RemoveItem(int32 fullListIndex)
|
|
{
|
|
BListItem* item = FullListItemAt(fullListIndex);
|
|
if (item == NULL)
|
|
return NULL;
|
|
|
|
fFullList.RemoveItem(fullListIndex);
|
|
if (item->fVisible)
|
|
BListView::RemoveItem(item);
|
|
|
|
// TODO: remove children
|
|
|
|
return item;
|
|
}
|
|
|
|
|
|
bool
|
|
BOutlineListView::RemoveItems(int32 fullListIndex, int32 count)
|
|
{
|
|
printf("BOutlineListView::RemoveItems Not implemented\n");
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
BListItem *
|
|
BOutlineListView::FullListItemAt(int32 fullListIndex) const
|
|
{
|
|
return (BListItem*)fFullList.ItemAt(fullListIndex);
|
|
}
|
|
|
|
|
|
int32
|
|
BOutlineListView::FullListIndexOf(BPoint point) const
|
|
{
|
|
return BListView::IndexOf(point);
|
|
}
|
|
|
|
|
|
int32
|
|
BOutlineListView::FullListIndexOf(BListItem* item) const
|
|
{
|
|
return fFullList.IndexOf(item);
|
|
}
|
|
|
|
|
|
BListItem *
|
|
BOutlineListView::FullListFirstItem() const
|
|
{
|
|
return (BListItem*)fFullList.FirstItem();
|
|
}
|
|
|
|
|
|
BListItem *
|
|
BOutlineListView::FullListLastItem() const
|
|
{
|
|
return (BListItem*)fFullList.LastItem();
|
|
}
|
|
|
|
|
|
bool
|
|
BOutlineListView::FullListHasItem(BListItem *item) const
|
|
{
|
|
return fFullList.HasItem(item);
|
|
}
|
|
|
|
|
|
int32
|
|
BOutlineListView::FullListCountItems() const
|
|
{
|
|
return fFullList.CountItems();
|
|
}
|
|
|
|
|
|
int32
|
|
BOutlineListView::FullListCurrentSelection(int32 index) const
|
|
{
|
|
int32 i = BListView::CurrentSelection(index);
|
|
|
|
BListItem *item = BListView::ItemAt(i);
|
|
if (item)
|
|
return fFullList.IndexOf(item);
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
void
|
|
BOutlineListView::MakeEmpty()
|
|
{
|
|
fFullList.MakeEmpty();
|
|
BListView::MakeEmpty();
|
|
}
|
|
|
|
|
|
bool
|
|
BOutlineListView::FullListIsEmpty() const
|
|
{
|
|
return fFullList.IsEmpty();
|
|
}
|
|
|
|
|
|
void
|
|
BOutlineListView::FullListDoForEach(bool(*func)(BListItem* item))
|
|
{
|
|
fFullList.DoForEach(reinterpret_cast<bool (*)(void*)>(func));
|
|
}
|
|
|
|
|
|
void
|
|
BOutlineListView::FullListDoForEach(bool (*func)(BListItem* item, void* arg),
|
|
void* arg)
|
|
{
|
|
fList.DoForEach(reinterpret_cast<bool (*)(void*, void*)>(func), arg);
|
|
}
|
|
|
|
|
|
BListItem *
|
|
BOutlineListView::Superitem(const BListItem* item)
|
|
{
|
|
int32 index = FullListIndexOf((BListItem*)item);
|
|
if (index == -1)
|
|
return NULL;
|
|
|
|
return SuperitemForIndex(index, item->OutlineLevel());
|
|
}
|
|
|
|
|
|
void
|
|
BOutlineListView::Expand(BListItem* item)
|
|
{
|
|
if (item->IsExpanded() || !FullListHasItem(item))
|
|
return;
|
|
|
|
item->fExpanded = true;
|
|
|
|
uint32 level = item->fLevel;
|
|
uint32 fullIndex = FullListIndexOf(item);
|
|
uint32 index = IndexOf(item) + 1;
|
|
uint32 count = FullListCountItems() - fullIndex - 1;
|
|
BListItem** items = (BListItem**)fFullList.Items() + fullIndex + 1;
|
|
|
|
BFont font;
|
|
GetFont(&font);
|
|
|
|
while (count-- > 0) {
|
|
item = items[0];
|
|
if (item->fLevel <= level)
|
|
break;
|
|
|
|
if (!item->IsItemVisible()) {
|
|
fList.AddItem(item, index++);
|
|
item->Update(this, &font);
|
|
item->SetItemVisible(true);
|
|
}
|
|
|
|
if (item->HasSubitems() && !item->IsExpanded()) {
|
|
// Skip hidden children
|
|
uint32 subLevel = item->fLevel;
|
|
items++;
|
|
|
|
while (--count > 0 && items[0]->fLevel > subLevel)
|
|
items++;
|
|
} else
|
|
items++;
|
|
}
|
|
|
|
_FixupScrollBar();
|
|
Invalidate();
|
|
}
|
|
|
|
|
|
void
|
|
BOutlineListView::Collapse(BListItem* item)
|
|
{
|
|
if (!item->IsExpanded() || !FullListHasItem(item))
|
|
return;
|
|
|
|
item->fExpanded = false;
|
|
|
|
uint32 level = item->fLevel;
|
|
uint32 fullIndex = FullListIndexOf(item);
|
|
uint32 count = FullListCountItems() - fullIndex - 1;
|
|
BListItem** items = (BListItem**)fFullList.Items() + fullIndex + 1;
|
|
|
|
while (count-- > 0) {
|
|
item = items[0];
|
|
if (item->fLevel <= level)
|
|
break;
|
|
|
|
if (item->IsItemVisible()) {
|
|
fList.RemoveItem(item);
|
|
item->SetItemVisible(false);
|
|
}
|
|
|
|
items++;
|
|
}
|
|
|
|
_FixupScrollBar();
|
|
Invalidate();
|
|
}
|
|
|
|
|
|
bool
|
|
BOutlineListView::IsExpanded(int32 fullListIndex)
|
|
{
|
|
BListItem *item = FullListItemAt(fullListIndex);
|
|
if (!item)
|
|
return false;
|
|
|
|
return item->IsExpanded();
|
|
}
|
|
|
|
|
|
BHandler *
|
|
BOutlineListView::ResolveSpecifier(BMessage* msg, int32 index,
|
|
BMessage* specifier, int32 what, const char* property)
|
|
{
|
|
return BListView::ResolveSpecifier(msg, index, specifier, what, property);
|
|
}
|
|
|
|
|
|
status_t
|
|
BOutlineListView::GetSupportedSuites(BMessage* data)
|
|
{
|
|
return BListView::GetSupportedSuites(data);
|
|
}
|
|
|
|
|
|
status_t
|
|
BOutlineListView::Perform(perform_code d, void* arg)
|
|
{
|
|
return BListView::Perform(d, arg);
|
|
}
|
|
|
|
|
|
void
|
|
BOutlineListView::ResizeToPreferred()
|
|
{
|
|
BListView::ResizeToPreferred();
|
|
}
|
|
|
|
|
|
void
|
|
BOutlineListView::GetPreferredSize(float* _width, float* _height)
|
|
{
|
|
BListView::GetPreferredSize(_width, _height);
|
|
}
|
|
|
|
|
|
void
|
|
BOutlineListView::MakeFocus(bool state)
|
|
{
|
|
BListView::MakeFocus(state);
|
|
}
|
|
|
|
|
|
void
|
|
BOutlineListView::AllAttached()
|
|
{
|
|
BListView::AllAttached();
|
|
}
|
|
|
|
|
|
void
|
|
BOutlineListView::AllDetached()
|
|
{
|
|
BListView::AllDetached();
|
|
}
|
|
|
|
|
|
void
|
|
BOutlineListView::DetachedFromWindow()
|
|
{
|
|
BListView::DetachedFromWindow();
|
|
}
|
|
|
|
|
|
void
|
|
BOutlineListView::FullListSortItems(int (*compareFunc)(const BListItem* a,
|
|
const BListItem* b))
|
|
{
|
|
SortItemsUnder(NULL, false, compareFunc);
|
|
}
|
|
|
|
|
|
void
|
|
BOutlineListView::SortItemsUnder(BListItem* underItem, bool oneLevelOnly,
|
|
int (*compareFunc)(const BListItem* a, const BListItem* b))
|
|
{
|
|
// This method is quite complicated: basically, it creates a real tree
|
|
// from the items of the full list, sorts them as needed, and then
|
|
// populates the entries back into the full and display lists
|
|
|
|
int32 firstIndex = FullListIndexOf(underItem) + 1;
|
|
int32 lastIndex = firstIndex;
|
|
BList* tree = _BuildTree(underItem, lastIndex);
|
|
|
|
_SortTree(tree, oneLevelOnly, compareFunc);
|
|
|
|
// Populate to the full list
|
|
_PopulateTree(tree, fFullList, firstIndex, false);
|
|
|
|
// Populate to BListView's list
|
|
firstIndex = fList.IndexOf(underItem) + 1;
|
|
_PopulateTree(tree, fList, firstIndex, true);
|
|
|
|
_DestructTree(tree);
|
|
}
|
|
|
|
|
|
void
|
|
BOutlineListView::_PopulateTree(BList* tree, BList& target,
|
|
int32& firstIndex, bool onlyVisible)
|
|
{
|
|
BListItem** items = (BListItem**)target.Items();
|
|
int32 count = tree->CountItems();
|
|
|
|
for (int32 index = 0; index < count; index++) {
|
|
BListItem* item = (BListItem*)tree->ItemAtFast(index);
|
|
|
|
items[firstIndex++] = item;
|
|
|
|
if (item->HasSubitems() && (!onlyVisible || item->IsExpanded()))
|
|
_PopulateTree(item->fTemporaryList, target, firstIndex, onlyVisible);
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
BOutlineListView::_SortTree(BList* tree, bool oneLevelOnly,
|
|
int (*compareFunc)(const BListItem* a, const BListItem* b))
|
|
{
|
|
// home-brewn quick sort for our compareFunc
|
|
quick_sort_item_array((BListItem**)tree->Items(), 0, tree->CountItems() - 1,
|
|
compareFunc);
|
|
|
|
if (oneLevelOnly)
|
|
return;
|
|
|
|
for (int32 index = tree->CountItems(); index-- > 0;) {
|
|
BListItem* item = (BListItem*)tree->ItemAt(index);
|
|
|
|
if (item->HasSubitems())
|
|
_SortTree(item->fTemporaryList, false, compareFunc);
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
BOutlineListView::_DestructTree(BList* tree)
|
|
{
|
|
for (int32 index = tree->CountItems(); index-- > 0;) {
|
|
BListItem* item = (BListItem*)tree->ItemAt(index);
|
|
|
|
if (item->HasSubitems())
|
|
_DestructTree(item->fTemporaryList);
|
|
}
|
|
|
|
delete tree;
|
|
}
|
|
|
|
|
|
BList*
|
|
BOutlineListView::_BuildTree(BListItem* underItem, int32& fullIndex)
|
|
{
|
|
int32 fullCount = FullListCountItems();
|
|
uint32 level = underItem != NULL ? underItem->OutlineLevel() + 1 : 0;
|
|
BList* list = new BList;
|
|
if (underItem != NULL)
|
|
underItem->fTemporaryList = list;
|
|
|
|
while (fullIndex < fullCount) {
|
|
BListItem *item = FullListItemAt(fullIndex);
|
|
|
|
// If we jump out of the subtree, break out
|
|
if (item->fLevel < level)
|
|
break;
|
|
|
|
if (item->fLevel == level) {
|
|
// If the level matches, put them into the list
|
|
list->AddItem(item);
|
|
}
|
|
|
|
fullIndex++;
|
|
|
|
if (item->HasSubitems()) {
|
|
// we're going deeper
|
|
_BuildTree(item, fullIndex);
|
|
}
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
|
|
int32
|
|
BOutlineListView::CountItemsUnder(BListItem* underItem,
|
|
bool oneLevelOnly) const
|
|
{
|
|
int32 i = IndexOf(underItem);
|
|
if (i == -1)
|
|
return 0;
|
|
|
|
int32 count = 0;
|
|
|
|
while (i < FullListCountItems()) {
|
|
BListItem *item = FullListItemAt(i);
|
|
|
|
// If we jump out of the subtree, return count
|
|
if (item->fLevel < underItem->OutlineLevel())
|
|
return count;
|
|
|
|
// If the level matches, increase count
|
|
if (!oneLevelOnly || item->fLevel == underItem->OutlineLevel() + 1)
|
|
count++;
|
|
|
|
i++;
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
|
|
BListItem *
|
|
BOutlineListView::EachItemUnder(BListItem *underItem, bool oneLevelOnly,
|
|
BListItem *(*eachFunc)(BListItem* item, void* arg), void* arg)
|
|
{
|
|
int32 i = IndexOf(underItem);
|
|
if (i == -1)
|
|
return NULL;
|
|
|
|
while (i < FullListCountItems()) {
|
|
BListItem *item = FullListItemAt(i);
|
|
|
|
// If we jump out of the subtree, return NULL
|
|
if (item->fLevel < underItem->OutlineLevel())
|
|
return NULL;
|
|
|
|
// If the level matches, check the index
|
|
if (!oneLevelOnly || item->fLevel == underItem->OutlineLevel() + 1) {
|
|
item = eachFunc(item, arg);
|
|
if (item != NULL)
|
|
return item;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
BListItem *
|
|
BOutlineListView::ItemUnderAt(BListItem* underItem,
|
|
bool oneLevelOnly, int32 index) const
|
|
{
|
|
int32 i = IndexOf(underItem);
|
|
if (i == -1)
|
|
return NULL;
|
|
|
|
while (i < FullListCountItems()) {
|
|
BListItem *item = FullListItemAt(i);
|
|
|
|
// If we jump out of the subtree, return NULL
|
|
if (item->fLevel < underItem->OutlineLevel())
|
|
return NULL;
|
|
|
|
// If the level matches, check the index
|
|
if (!oneLevelOnly || item->fLevel == underItem->OutlineLevel() + 1) {
|
|
if (index == 0)
|
|
return item;
|
|
|
|
index--;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
bool
|
|
BOutlineListView::DoMiscellaneous(MiscCode code, MiscData* data)
|
|
{
|
|
return BListView::DoMiscellaneous(code, data);
|
|
}
|
|
|
|
|
|
void
|
|
BOutlineListView::MessageReceived(BMessage* msg)
|
|
{
|
|
BListView::MessageReceived(msg);
|
|
}
|
|
|
|
|
|
void BOutlineListView::_ReservedOutlineListView1() {}
|
|
void BOutlineListView::_ReservedOutlineListView2() {}
|
|
void BOutlineListView::_ReservedOutlineListView3() {}
|
|
void BOutlineListView::_ReservedOutlineListView4() {}
|
|
|
|
|
|
int32
|
|
BOutlineListView::FullListIndex(int32 index) const
|
|
{
|
|
BListItem *item = ItemAt(index);
|
|
|
|
if (item == NULL)
|
|
return -1;
|
|
|
|
return FullListIndexOf(item);
|
|
}
|
|
|
|
|
|
int32
|
|
BOutlineListView::ListViewIndex(int32 index) const
|
|
{
|
|
BListItem *item = ItemAt(index);
|
|
|
|
if (item == NULL)
|
|
return -1;
|
|
|
|
return BListView::IndexOf(item);
|
|
}
|
|
|
|
|
|
void
|
|
BOutlineListView::ExpandOrCollapse(BListItem *underItem, bool expand)
|
|
{
|
|
}
|
|
|
|
|
|
BRect
|
|
BOutlineListView::LatchRect(BRect itemRect, int32 level) const
|
|
{
|
|
return BRect(itemRect.left, itemRect.top, itemRect.left
|
|
+ (level * 10.0f + 15.0f), itemRect.bottom);
|
|
}
|
|
|
|
|
|
void
|
|
BOutlineListView::DrawLatch(BRect itemRect, int32 level, bool collapsed,
|
|
bool highlighted, bool misTracked)
|
|
{
|
|
float left = level * 10.0f;
|
|
|
|
if (collapsed) {
|
|
SetHighColor(192, 192, 192);
|
|
|
|
FillTriangle(itemRect.LeftTop() + BPoint(left + 4.0f, 2.0f),
|
|
itemRect.LeftTop() + BPoint(left + 4.0f, 10.0f),
|
|
itemRect.LeftTop() + BPoint(left + 8.0f, 6.0f));
|
|
|
|
SetHighColor(0, 0, 0);
|
|
|
|
StrokeTriangle(itemRect.LeftTop() + BPoint(left + 4.0f, 2.0f),
|
|
itemRect.LeftTop() + BPoint(left + 4.0f, 10.0f),
|
|
itemRect.LeftTop() + BPoint(left + 8.0f, 6.0f));
|
|
} else {
|
|
SetHighColor(192, 192, 192);
|
|
|
|
FillTriangle(itemRect.LeftTop() + BPoint(left + 2.0f, 4.0f),
|
|
itemRect.LeftTop() + BPoint(left + 10.0f, 4.0f),
|
|
itemRect.LeftTop() + BPoint(left + 6.0f, 8.0f));
|
|
|
|
SetHighColor(0, 0, 0);
|
|
|
|
StrokeTriangle(itemRect.LeftTop() + BPoint(left + 2.0f, 4.0f),
|
|
itemRect.LeftTop() + BPoint(left + 10.0f, 4.0f),
|
|
itemRect.LeftTop() + BPoint(left + 6.0f, 8.0f));
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
BOutlineListView::DrawItem(BListItem* item, BRect itemRect, bool complete)
|
|
{
|
|
if (item->fHasSubitems)
|
|
DrawLatch(itemRect, item->fLevel, !item->IsExpanded(), false, false);
|
|
|
|
itemRect.left += (item->fLevel) * 10.0f + 15.0f;
|
|
item->DrawItem(this, itemRect, complete);
|
|
}
|
|
|
|
|
|
BListItem *
|
|
BOutlineListView::RemoveCommon(int32 fullListIndex)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
|
|
BListItem *
|
|
BOutlineListView::RemoveOne(int32 fullListIndex)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
|
|
void
|
|
BOutlineListView::TrackInLatchItem(void *)
|
|
{
|
|
}
|
|
|
|
|
|
void
|
|
BOutlineListView::TrackOutLatchItem(void *)
|
|
{
|
|
}
|
|
|
|
|
|
bool
|
|
BOutlineListView::OutlineSwapItems(int32 a, int32 b)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
|
|
bool
|
|
BOutlineListView::OutlineMoveItem(int32 from, int32 to)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
|
|
bool
|
|
BOutlineListView::OutlineReplaceItem(int32 index, BListItem *item)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
|
|
void
|
|
BOutlineListView::CommonMoveItems(int32 from, int32 count, int32 to)
|
|
{
|
|
}
|
|
|
|
|
|
BListItem *
|
|
BOutlineListView::SuperitemForIndex(int32 fullListIndex, int32 level)
|
|
{
|
|
BListItem *item;
|
|
fullListIndex--;
|
|
|
|
while (fullListIndex >= 0) {
|
|
if ((item = FullListItemAt(fullListIndex))->OutlineLevel() <
|
|
(uint32)level)
|
|
return item;
|
|
|
|
fullListIndex--;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
int32
|
|
BOutlineListView::FindPreviousVisibleIndex(int32 fullListIndex)
|
|
{
|
|
fullListIndex--;
|
|
|
|
while (fullListIndex >= 0) {
|
|
if (FullListItemAt(fullListIndex)->fVisible)
|
|
return fullListIndex;
|
|
|
|
fullListIndex--;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|