Пример #1
0
bool
BListView::_MoveItem(int32 from, int32 to)
{
	// remember item frames before doing anything
	BRect frameFrom = ItemFrame(from);
	BRect frameTo = ItemFrame(to);

	if (!fList.MoveItem(from, to))
		return false;

	// track anchor item
	if (fAnchorIndex == from)
		fAnchorIndex = to;

	// track selection
	if (ItemAt(to)->IsSelected()) {
		_RescanSelection(from, to);
		// though the actually selected items stayed the
		// same, the selection has still changed
		SelectionChanged();
	}

	_RecalcItemTops((to > from) ? from : to);

	// take care of invalidation
	if (Window()) {
		// NOTE: window looper is assumed to be locked!
		Invalidate(frameFrom | frameTo);
	}

	return true;
}
Пример #2
0
BListItem*
BListView::RemoveItem(int32 index)
{
	BListItem *item = ItemAt(index);
	if (!item)
		return NULL;

	if (item->IsSelected())
		Deselect(index);

	if (!fList.RemoveItem(item))
		return NULL;

	if (fFirstSelected != -1 && index < fFirstSelected)
		fFirstSelected--;

	if (fLastSelected != -1 && index < fLastSelected)
		fLastSelected--;

	if (fAnchorIndex != -1 && index < fAnchorIndex)
		fAnchorIndex--;

	_RecalcItemTops(index);

	_InvalidateFrom(index);
	_FixupScrollBar();

	return item;
}
Пример #3
0
bool
BListView::AddList(BList* list, int32 index)
{
	if (!fList.AddList(list, index))
		return false;

	int32 count = fList.CountItems();

	if (fFirstSelected != -1 && index < fFirstSelected)
		fFirstSelected += count;

	if (fLastSelected != -1 && index < fLastSelected)
		fLastSelected += count;

	if (Window()) {
		BFont font;
		GetFont(&font);

		for (int32 i = index; i <= (index + list->CountItems() - 1); i++) {
			ItemAt(i)->SetTop((i > 0) ? ItemAt(i - 1)->Bottom() + 1.0 : 0.0);
			ItemAt(i)->Update(this, &font);
		}

		_RecalcItemTops(index + list->CountItems() - 1);

		_FixupScrollBar();
		Invalidate(); // TODO
	}

	return true;
}
Пример #4
0
bool
BListView::AddItem(BListItem *item, int32 index)
{
	if (!fList.AddItem(item, index))
		return false;

	if (fFirstSelected != -1 && index <= fFirstSelected)
		fFirstSelected++;

	if (fLastSelected != -1 && index <= fLastSelected)
		fLastSelected++;

	if (Window()) {
		BFont font;
		GetFont(&font);
		item->SetTop((index > 0) ? ItemAt(index - 1)->Bottom() + 1.0 : 0.0);

		item->Update(this, &font);
		_RecalcItemTops(index + 1);

		_FixupScrollBar();
		_InvalidateFrom(index);
	}

	return true;
}
Пример #5
0
bool
BListView::_SwapItems(int32 a, int32 b)
{
	// remember frames of items before anyhing happens,
	// the tricky situation is when the two items have
	// a different height
	BRect aFrame = ItemFrame(a);
	BRect bFrame = ItemFrame(b);

	if (!fList.SwapItems(a, b))
		return false;

	if (a == b) {
		// nothing to do, but success nevertheless
		return true;
	}

	// track anchor item
	if (fAnchorIndex == a)
		fAnchorIndex = b;
	else if (fAnchorIndex == b)
		fAnchorIndex = a;

	// track selection
	// NOTE: this is only important if the selection status
	// of both items is not the same
	int32 first = min_c(a, b);
	int32 last = max_c(a, b);
	if (ItemAt(a)->IsSelected() != ItemAt(b)->IsSelected()) {
		if (first < fFirstSelected || last > fLastSelected) {
			_RescanSelection(min_c(first, fFirstSelected),
				max_c(last, fLastSelected));
		}
		// though the actually selected items stayed the
		// same, the selection has still changed
		SelectionChanged();
	}

	ItemAt(a)->SetTop(aFrame.top);
	ItemAt(b)->SetTop(bFrame.top);

	// take care of invalidation
	if (Window()) {
		// NOTE: window looper is assumed to be locked!
		if (aFrame.Height() != bFrame.Height()) {
			_RecalcItemTops(first, last);
			// items in between shifted visually
			Invalidate(aFrame | bFrame);
		} else {
			Invalidate(aFrame);
			Invalidate(bFrame);
		}
	}

	return true;
}
Пример #6
0
void
BListView::SortItems(int (*cmp)(const void *, const void *))
{
	if (_DeselectAll(-1, -1)) {
		SelectionChanged();
		InvokeNotify(fSelectMessage, B_CONTROL_MODIFIED);
	}

	fList.SortItems(cmp);
	_RecalcItemTops(0);
	Invalidate();
}
Пример #7
0
bool
BListView::RemoveItems(int32 index, int32 count)
{
	if (index >= fList.CountItems())
		index = -1;

	if (index < 0)
		return false;

	if (fAnchorIndex != -1 && index < fAnchorIndex)
		fAnchorIndex = index;

	fList.RemoveItems(index, count);
	if (index < fList.CountItems())
		_RecalcItemTops(index);
	Invalidate();
	return true;
}
Пример #8
0
bool
BListView::_ReplaceItem(int32 index, BListItem* item)
{
	if (item == NULL)
		return false;

	BListItem* old = ItemAt(index);
	if (!old)
		return false;

	BRect frame = ItemFrame(index);

	bool selectionChanged = old->IsSelected() != item->IsSelected();

	// replace item
	if (!fList.ReplaceItem(index, item))
		return false;

	// tack selection
	if (selectionChanged) {
		int32 start = min_c(fFirstSelected, index);
		int32 end = max_c(fLastSelected, index);
		_RescanSelection(start, end);
		SelectionChanged();
	}
	_RecalcItemTops(index);

	bool itemHeightChanged = frame != ItemFrame(index);

	// take care of invalidation
	if (Window()) {
		// NOTE: window looper is assumed to be locked!
		if (itemHeightChanged)
			_InvalidateFrom(index);
		else
			Invalidate(frame);
	}

	if (itemHeightChanged)
		_FixupScrollBar();

	return true;
}
Пример #9
0
bool
BOutlineListView::_SwapItems(int32 first, int32 second)
{
	// same item, do nothing
	if (first == second)
		return true;

	// fail, first item out of bounds
	if ((first < 0) || (first >= CountItems()))
		return false;

	// fail, second item out of bounds
	if ((second < 0) || (second >= CountItems()))
		return false;

	int32 firstIndex = min_c(first, second);
	int32 secondIndex = max_c(first, second);
	BListItem* firstItem = ItemAt(firstIndex);
	BListItem* secondItem = ItemAt(secondIndex);
	BList firstSubItems, secondSubItems;

	if (Superitem(firstItem) != Superitem(secondItem))
		return false;
	if (!firstItem->IsItemVisible() || !secondItem->IsItemVisible())
		return false;

	int32 fullFirstIndex = _FullListIndex(firstIndex);
	int32 fullSecondIndex = _FullListIndex(secondIndex);
	_GetSubItems(fFullList, firstSubItems, firstItem, fullFirstIndex + 1);
	_GetSubItems(fFullList, secondSubItems, secondItem, fullSecondIndex + 1);
	_DoSwap(fFullList, fullFirstIndex, fullSecondIndex, &firstSubItems,
		&secondSubItems);

	_CullInvisibleItems(firstSubItems);
	_CullInvisibleItems(secondSubItems);
	_DoSwap(fList, firstIndex, secondIndex, &firstSubItems,
		&secondSubItems);

	_RecalcItemTops(firstIndex);
	_RescanSelection(firstIndex, secondIndex + secondSubItems.CountItems());
	Invalidate(Bounds());
	return true;
}
Пример #10
0
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);

	if (underItem == NULL
		|| (underItem->IsItemVisible() && underItem->IsExpanded())) {
		// Populate to BListView's list
		firstIndex = fList.IndexOf(underItem) + 1;
		lastIndex = firstIndex;
		_PopulateTree(tree, fList, lastIndex, true);

		if (fFirstSelected != -1) {
			// update selection hints
			fFirstSelected = _CalcFirstSelected(0);
			fLastSelected = _CalcLastSelected(CountItems());
		}

		// only invalidate what may have changed
		_RecalcItemTops(firstIndex);
		BRect top = ItemFrame(firstIndex);
		BRect bottom = ItemFrame(lastIndex - 1);
		BRect update(top.left, top.top, bottom.right, bottom.bottom);
		Invalidate(update);
	}

	_DestructTree(tree);
}
Пример #11
0
void
BOutlineListView::ExpandOrCollapse(BListItem* item, bool expand)
{
	if (item->IsExpanded() == expand || !FullListHasItem(item))
		return;

	item->fExpanded = expand;

	// TODO: merge these cases together, they are pretty similar

	if (expand) {
		uint32 level = item->fLevel;
		int32 fullIndex = FullListIndexOf(item);
		int32 index = IndexOf(item) + 1;
		int32 startIndex = index;
		int32 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()) {
				// fix selection hints
				if (index <= fFirstSelected)
					fFirstSelected++;
				if (index <= fLastSelected)
					fLastSelected++;

				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++;
		}
		_RecalcItemTops(startIndex);
	} else {
		// collapse
		uint32 level = item->fLevel;
		int32 fullIndex = FullListIndexOf(item);
		int32 index = IndexOf(item);
		int32 startIndex = index;
		int32 max = FullListCountItems() - fullIndex - 1;
		int32 count = 0;
		bool selectionChanged = false;

		BListItem** items = (BListItem**)fFullList.Items() + fullIndex + 1;

		while (max-- > 0) {
			item = items[0];
			if (item->fLevel <= level)
				break;

			if (item->IsItemVisible()) {
				fList.RemoveItem(item);
				item->SetItemVisible(false);
				if (item->IsSelected()) {
					selectionChanged = true;
					item->Deselect();
				}
				count++;
			}

			items++;
		}

		_RecalcItemTops(startIndex);
		// fix selection hints
		// if the selected item was just removed by collapsing, select its
		// parent
		if (ListType() == B_SINGLE_SELECTION_LIST && selectionChanged)
			fFirstSelected = fLastSelected = index;
		if (index < fFirstSelected && index + count < fFirstSelected) {
				// all items removed were higher than the selection range,
				// adjust the indexes to correspond to their new visible positions
				fFirstSelected -= count;
				fLastSelected -= count;
		}			

		int32 maxIndex = fList.CountItems() - 1;
		if (fFirstSelected > maxIndex)
			fFirstSelected = maxIndex;
		if (fLastSelected > maxIndex)
			fLastSelected = maxIndex;
		if (selectionChanged)
			SelectionChanged();
	}

	_FixupScrollBar();
	Invalidate();
}