17c74b12bSAxel Dörfler/*
2539dc1bcSJohn Scipione * Copyright 2001-2013 Haiku, Inc. All rights reserved.
37c74b12bSAxel Dörfler * Distributed under the terms of the MIT License.
47c74b12bSAxel Dörfler *
57c74b12bSAxel Dörfler * Authors:
67c74b12bSAxel Dörfler *		Marc Flerackers (mflerackers@androme.be)
77c74b12bSAxel Dörfler *		Axel D��rfler, axeld@pinc-software.de
8fef39304SStephan Aßmus *		Rene Gollent (rene@gollent.com)
923079ac1SPhilippe Saint-Pierre *		Philippe Saint-Pierre, stpere@gmail.com
10c19cb4ddSJohn Scipione *		John Scipione, jscipione@gmail.com
117c74b12bSAxel Dörfler */
127c74b12bSAxel Dörfler
13539dc1bcSJohn Scipione
147c74b12bSAxel Dörfler//! BOutlineListView represents a "nestable" list view.
157c74b12bSAxel Dörfler
16539dc1bcSJohn Scipione
17007ed8c5SMarc Flerackers#include <OutlineListView.h>
1808a35638SAxel Dörfler
1908a35638SAxel Dörfler#include <algorithm>
207c74b12bSAxel Dörfler
21585fe26cSDarkWyrm#include <stdio.h>
227c74b12bSAxel Dörfler#include <stdlib.h>
237c74b12bSAxel Dörfler
24c19cb4ddSJohn Scipione#include <ControlLook.h>
2508a35638SAxel Dörfler#include <Window.h>
26007ed8c5SMarc Flerackers
2739fbf550SOliver Tappe#include <binary_compatibility/Interface.h>
2839fbf550SOliver Tappe
2939fbf550SOliver Tappe
3008a35638SAxel Dörflertypedef int (*compare_func)(const BListItem* a, const BListItem* b);
3123079ac1SPhilippe Saint-Pierre
32539dc1bcSJohn Scipione
33ef83ae3eSRene Gollentstruct ListItemComparator {
3408a35638SAxel Dörfler	ListItemComparator(compare_func compareFunc)
3508a35638SAxel Dörfler		:
3608a35638SAxel Dörfler		fCompareFunc(compareFunc)
37ef83ae3eSRene Gollent	{
387c74b12bSAxel Dörfler	}
397c74b12bSAxel Dörfler
4008a35638SAxel Dörfler	bool operator()(const BListItem* a, const BListItem* b) const
41ef83ae3eSRene Gollent	{
42ef83ae3eSRene Gollent		return fCompareFunc(a, b) < 0;
43ef83ae3eSRene Gollent	}
447c74b12bSAxel Dörfler
45ef83ae3eSRene Gollentprivate:
4608a35638SAxel Dörfler	compare_func	fCompareFunc;
47ef83ae3eSRene Gollent};
48ba18b05bSKarsten Heimrich
4908a35638SAxel Dörfler
5008a35638SAxel Dörflerstatic void
5108a35638SAxel Dörfler_GetSubItems(BList& sourceList, BList& destList, BListItem* parent, int32 start)
5208a35638SAxel Dörfler{
5308a35638SAxel Dörfler	for (int32 i = start; i < sourceList.CountItems(); i++) {
5408a35638SAxel Dörfler		BListItem* item = (BListItem*)sourceList.ItemAt(i);
5508a35638SAxel Dörfler		if (item->OutlineLevel() <= parent->OutlineLevel())
5608a35638SAxel Dörfler			break;
5708a35638SAxel Dörfler		destList.AddItem(item);
5808a35638SAxel Dörfler	}
5908a35638SAxel Dörfler}
6008a35638SAxel Dörfler
6108a35638SAxel Dörfler
6208a35638SAxel Dörflerstatic void
6308a35638SAxel Dörfler_DoSwap(BList& list, int32 firstIndex, int32 secondIndex, BList* firstItems,
6408a35638SAxel Dörfler	BList* secondItems)
6508a35638SAxel Dörfler{
6608a35638SAxel Dörfler	BListItem* item = (BListItem*)list.ItemAt(firstIndex);
6708a35638SAxel Dörfler	list.SwapItems(firstIndex, secondIndex);
6808a35638SAxel Dörfler	list.RemoveItems(secondIndex + 1, secondItems->CountItems());
6908a35638SAxel Dörfler	list.RemoveItems(firstIndex + 1, firstItems->CountItems());
7008a35638SAxel Dörfler	list.AddList(secondItems, firstIndex + 1);
7108a35638SAxel Dörfler	int32 newIndex = list.IndexOf(item);
7208a35638SAxel Dörfler	if (newIndex + 1 < list.CountItems())
7308a35638SAxel Dörfler		list.AddList(firstItems, newIndex + 1);
7408a35638SAxel Dörfler	else
7508a35638SAxel Dörfler		list.AddList(firstItems);
7608a35638SAxel Dörfler}
7708a35638SAxel Dörfler
7808a35638SAxel Dörfler
79539dc1bcSJohn Scipione//	#pragma mark - BOutlineListView
807c74b12bSAxel Dörfler
817c74b12bSAxel Dörfler
827c74b12bSAxel DörflerBOutlineListView::BOutlineListView(BRect frame, const char* name,
831e1afb39SJohn Scipione	list_view_type type, uint32 resizingMode, uint32 flags)
841e1afb39SJohn Scipione	:
851e1afb39SJohn Scipione	BListView(frame, name, type, resizingMode, flags)
86007ed8c5SMarc Flerackers{
87007ed8c5SMarc Flerackers}
887c74b12bSAxel Dörfler
897c74b12bSAxel Dörfler
9008a35638SAxel DörflerBOutlineListView::BOutlineListView(const char* name, list_view_type type,
911e1afb39SJohn Scipione	uint32 flags)
921e1afb39SJohn Scipione	:
931e1afb39SJohn Scipione	BListView(name, type, flags)
9408a35638SAxel Dörfler{
9508a35638SAxel Dörfler}
9608a35638SAxel Dörfler
9708a35638SAxel Dörfler
987c74b12bSAxel DörflerBOutlineListView::BOutlineListView(BMessage* archive)
991e1afb39SJohn Scipione	:
1001e1afb39SJohn Scipione	BListView(archive)
101007ed8c5SMarc Flerackers{
102ba18b05bSKarsten Heimrich	int32 i = 0;
103ba18b05bSKarsten Heimrich	BMessage subData;
104ba18b05bSKarsten Heimrich	while (archive->FindMessage("_l_full_items", i++, &subData) == B_OK) {
10508a35638SAxel Dörfler		BArchivable* object = instantiate_object(&subData);
106ba18b05bSKarsten Heimrich		if (!object)
107ba18b05bSKarsten Heimrich			continue;
108ba18b05bSKarsten Heimrich
10908a35638SAxel Dörfler		BListItem* item = dynamic_cast<BListItem*>(object);
110ba18b05bSKarsten Heimrich		if (item)
111ba18b05bSKarsten Heimrich			AddItem(item);
112ba18b05bSKarsten Heimrich	}
113007ed8c5SMarc Flerackers}
1147c74b12bSAxel Dörfler
1157c74b12bSAxel Dörfler
116007ed8c5SMarc FlerackersBOutlineListView::~BOutlineListView()
117007ed8c5SMarc Flerackers{
1187c74b12bSAxel Dörfler	fFullList.MakeEmpty();
119007ed8c5SMarc Flerackers}
1207c74b12bSAxel Dörfler
1217c74b12bSAxel Dörfler
12208a35638SAxel DörflerBArchivable*
1237c74b12bSAxel DörflerBOutlineListView::Instantiate(BMessage* archive)
124007ed8c5SMarc Flerackers{
125007ed8c5SMarc Flerackers	if (validate_instantiation(archive, "BOutlineListView"))
126007ed8c5SMarc Flerackers		return new BOutlineListView(archive);
1277c74b12bSAxel Dörfler
1287c74b12bSAxel Dörfler	return NULL;
129007ed8c5SMarc Flerackers}
1307c74b12bSAxel Dörfler
1317c74b12bSAxel Dörfler
1327c74b12bSAxel Dörflerstatus_t
1337c74b12bSAxel DörflerBOutlineListView::Archive(BMessage* archive, bool deep) const
134007ed8c5SMarc Flerackers{
135ba18b05bSKarsten Heimrich	// Note: We can't call the BListView Archive function here, as we are also
136ba18b05bSKarsten Heimrich	// interested in subitems BOutlineListView can have. They are even stored
137ba18b05bSKarsten Heimrich	// with a different field name (_l_full_items vs. _l_items).
138ba18b05bSKarsten Heimrich
139ba18b05bSKarsten Heimrich	status_t status = BView::Archive(archive, deep);
140ba18b05bSKarsten Heimrich	if (status != B_OK)
141ba18b05bSKarsten Heimrich		return status;
142ba18b05bSKarsten Heimrich
143ba18b05bSKarsten Heimrich	status = archive->AddInt32("_lv_type", fListType);
144ba18b05bSKarsten Heimrich	if (status == B_OK && deep) {
145ba18b05bSKarsten Heimrich		int32 i = 0;
14608a35638SAxel Dörfler		BListItem* item = NULL;
147ba18b05bSKarsten Heimrich		while ((item = static_cast<BListItem*>(fFullList.ItemAt(i++)))) {
148ba18b05bSKarsten Heimrich			BMessage subData;
149ba18b05bSKarsten Heimrich			status = item->Archive(&subData, true);
150ba18b05bSKarsten Heimrich			if (status >= B_OK)
151ba18b05bSKarsten Heimrich				status = archive->AddMessage("_l_full_items", &subData);
152ba18b05bSKarsten Heimrich
153ba18b05bSKarsten Heimrich			if (status < B_OK)
154ba18b05bSKarsten Heimrich				break;
155ba18b05bSKarsten Heimrich		}
156ba18b05bSKarsten Heimrich	}
157ba18b05bSKarsten Heimrich
158ba18b05bSKarsten Heimrich	if (status >= B_OK && InvocationMessage() != NULL)
159ba18b05bSKarsten Heimrich		status = archive->AddMessage("_msg", InvocationMessage());
160ba18b05bSKarsten Heimrich
161ba18b05bSKarsten Heimrich	if (status == B_OK && fSelectMessage != NULL)
162ba18b05bSKarsten Heimrich		status = archive->AddMessage("_2nd_msg", fSelectMessage);
163ba18b05bSKarsten Heimrich
164ba18b05bSKarsten Heimrich	return status;
165007ed8c5SMarc Flerackers}
1667c74b12bSAxel Dörfler
1677c74b12bSAxel Dörfler
1687c74b12bSAxel Dörflervoid
1691e1afb39SJohn ScipioneBOutlineListView::MouseDown(BPoint where)
170007ed8c5SMarc Flerackers{
171007ed8c5SMarc Flerackers	MakeFocus();
172007ed8c5SMarc Flerackers
1731e1afb39SJohn Scipione	int32 index = IndexOf(where);
174007ed8c5SMarc Flerackers
1757c74b12bSAxel Dörfler	if (index != -1) {
17608a35638SAxel Dörfler		BListItem* item = ItemAt(index);
177007ed8c5SMarc Flerackers
1787c74b12bSAxel Dörfler		if (item->fHasSubitems
1791e1afb39SJohn Scipione			&& LatchRect(ItemFrame(index), item->fLevel).Contains(where)) {
180007ed8c5SMarc Flerackers			if (item->IsExpanded())
181007ed8c5SMarc Flerackers				Collapse(item);
182007ed8c5SMarc Flerackers			else
183007ed8c5SMarc Flerackers				Expand(item);
1847c74b12bSAxel Dörfler		} else
1851e1afb39SJohn Scipione			BListView::MouseDown(where);
186007ed8c5SMarc Flerackers	}
187007ed8c5SMarc Flerackers}
1887c74b12bSAxel Dörfler
1897c74b12bSAxel Dörfler
1907c74b12bSAxel Dörflervoid
1917c74b12bSAxel DörflerBOutlineListView::KeyDown(const char* bytes, int32 numBytes)
192007ed8c5SMarc Flerackers{
1937c74b12bSAxel Dörfler	if (numBytes == 1) {
194dd0e375fSRene Gollent		int32 currentSel = CurrentSelection();
1957c74b12bSAxel Dörfler		switch (bytes[0]) {
1967c74b12bSAxel Dörfler			case B_RIGHT_ARROW:
197007ed8c5SMarc Flerackers			{
19808a35638SAxel Dörfler				BListItem* item = ItemAt(currentSel);
199dd0e375fSRene Gollent				if (item && item->fHasSubitems) {
20042272d23SAdrien Destugues					if (!item->IsExpanded())
201dd0e375fSRene Gollent						Expand(item);
202dd0e375fSRene Gollent					else
203dd0e375fSRene Gollent						Select(currentSel + 1);
204dd0e375fSRene Gollent				}
2057c74b12bSAxel Dörfler				return;
206007ed8c5SMarc Flerackers			}
2077c74b12bSAxel Dörfler
2087c74b12bSAxel Dörfler			case B_LEFT_ARROW:
209007ed8c5SMarc Flerackers			{
21008a35638SAxel Dörfler				BListItem* item = ItemAt(currentSel);
211fcdaa0c7SRene Gollent				if (item) {
212fcdaa0c7SRene Gollent					if (item->fHasSubitems)
213fcdaa0c7SRene Gollent						Collapse(item);
214fcdaa0c7SRene Gollent					else {
215fcdaa0c7SRene Gollent						item = Superitem(item);
216fcdaa0c7SRene Gollent						if (item)
217fcdaa0c7SRene Gollent							Select(IndexOf(item));
218fcdaa0c7SRene Gollent					}
219fcdaa0c7SRene Gollent				}
2207c74b12bSAxel Dörfler				return;
221007ed8c5SMarc Flerackers			}
222007ed8c5SMarc Flerackers		}
223007ed8c5SMarc Flerackers	}
2247c74b12bSAxel Dörfler
2257c74b12bSAxel Dörfler	BListView::KeyDown(bytes, numBytes);
226007ed8c5SMarc Flerackers}
2277c74b12bSAxel Dörfler
2287c74b12bSAxel Dörfler
2297c74b12bSAxel Dörflervoid
2307c74b12bSAxel DörflerBOutlineListView::FrameMoved(BPoint newPosition)
231007ed8c5SMarc Flerackers{
2327c74b12bSAxel Dörfler	BListView::FrameMoved(newPosition);
233007ed8c5SMarc Flerackers}
2347c74b12bSAxel Dörfler
2357c74b12bSAxel Dörfler
2367c74b12bSAxel Dörflervoid
2377c74b12bSAxel DörflerBOutlineListView::FrameResized(float newWidth, float newHeight)
238007ed8c5SMarc Flerackers{
2397c74b12bSAxel Dörfler	BListView::FrameResized(newWidth, newHeight);
240007ed8c5SMarc Flerackers}
2417c74b12bSAxel Dörfler
2427c74b12bSAxel Dörfler
2437c74b12bSAxel Dörflervoid
2447c74b12bSAxel DörflerBOutlineListView::MouseUp(BPoint where)
245007ed8c5SMarc Flerackers{
246007ed8c5SMarc Flerackers	BListView::MouseUp(where);
247007ed8c5SMarc Flerackers}
2487c74b12bSAxel Dörfler
2497c74b12bSAxel Dörfler
2507c74b12bSAxel Dörflerbool
2511e1afb39SJohn ScipioneBOutlineListView::AddUnder(BListItem* item, BListItem* superItem)
252007ed8c5SMarc Flerackers{
2531e1afb39SJohn Scipione	if (superItem == NULL)
254b66c6231SAxel Dörfler		return AddItem(item);
255ba18b05bSKarsten Heimrich
2561e1afb39SJohn Scipione	fFullList.AddItem(item, FullListIndexOf(superItem) + 1);
257007ed8c5SMarc Flerackers
2581e1afb39SJohn Scipione	item->fLevel = superItem->OutlineLevel() + 1;
2591e1afb39SJohn Scipione	superItem->fHasSubitems = true;
260007ed8c5SMarc Flerackers
2611e1afb39SJohn Scipione	if (superItem->IsItemVisible() && superItem->IsExpanded()) {
262007ed8c5SMarc Flerackers		item->SetItemVisible(true);
263007ed8c5SMarc Flerackers
2641e1afb39SJohn Scipione		int32 index = BListView::IndexOf(superItem);
265007ed8c5SMarc Flerackers
266007ed8c5SMarc Flerackers		BListView::AddItem(item, index + 1);
2671e1afb39SJohn Scipione		Invalidate(LatchRect(ItemFrame(index), superItem->OutlineLevel()));
2687c74b12bSAxel Dörfler	} else
269007ed8c5SMarc Flerackers		item->SetItemVisible(false);
270007ed8c5SMarc Flerackers
271007ed8c5SMarc Flerackers	return true;
272007ed8c5SMarc Flerackers}
273007ed8c5SMarc Flerackers
2747c74b12bSAxel Dörfler
2757c74b12bSAxel Dörflerbool
2767c74b12bSAxel DörflerBOutlineListView::AddItem(BListItem* item)
2777c74b12bSAxel Dörfler{
278b66c6231SAxel Dörfler	return AddItem(item, FullListCountItems());
279007ed8c5SMarc Flerackers}
2807c74b12bSAxel Dörfler
2817c74b12bSAxel Dörfler
2827c74b12bSAxel Dörflerbool
2837c74b12bSAxel DörflerBOutlineListView::AddItem(BListItem* item, int32 fullListIndex)
284007ed8c5SMarc Flerackers{
285007ed8c5SMarc Flerackers	if (fullListIndex < 0)
286007ed8c5SMarc Flerackers		fullListIndex = 0;
287b66c6231SAxel Dörfler	else if (fullListIndex > FullListCountItems())
288b66c6231SAxel Dörfler		fullListIndex = FullListCountItems();
289007ed8c5SMarc Flerackers
290b66c6231SAxel Dörfler	if (!fFullList.AddItem(item, fullListIndex))
291b66c6231SAxel Dörfler		return false;
292b66c6231SAxel Dörfler
293b66c6231SAxel Dörfler	// Check if this item is visible, and if it is, add it to the
294b66c6231SAxel Dörfler	// other list, too
295007ed8c5SMarc Flerackers
2967c74b12bSAxel Dörfler	if (item->fLevel > 0) {
29708a35638SAxel Dörfler		BListItem* super = _SuperitemForIndex(fullListIndex, item->fLevel);
298b66c6231SAxel Dörfler		if (super == NULL)
299b66c6231SAxel Dörfler			return true;
300007ed8c5SMarc Flerackers
301b66c6231SAxel Dörfler		bool hadSubitems = super->fHasSubitems;
302b66c6231SAxel Dörfler		super->fHasSubitems = true;
303b66c6231SAxel Dörfler
304b66c6231SAxel Dörfler		if (!super->IsItemVisible() || !super->IsExpanded()) {
305b66c6231SAxel Dörfler			item->SetItemVisible(false);
306007ed8c5SMarc Flerackers			return true;
307b66c6231SAxel Dörfler		}
308b66c6231SAxel Dörfler
3091e1afb39SJohn Scipione		if (!hadSubitems) {
3101e1afb39SJohn Scipione			Invalidate(LatchRect(ItemFrame(IndexOf(super)),
3111e1afb39SJohn Scipione				super->OutlineLevel()));
3121e1afb39SJohn Scipione		}
313007ed8c5SMarc Flerackers	}
314007ed8c5SMarc Flerackers
315b66c6231SAxel Dörfler	int32 listIndex = _FindPreviousVisibleIndex(fullListIndex);
316b66c6231SAxel Dörfler
317b66c6231SAxel Dörfler	if (!BListView::AddItem(item, IndexOf(FullListItemAt(listIndex)) + 1)) {
318b66c6231SAxel Dörfler		// adding didn't work out, we need to remove it from the main list again
319b66c6231SAxel Dörfler		fFullList.RemoveItem(fullListIndex);
320b66c6231SAxel Dörfler		return false;
321b66c6231SAxel Dörfler	}
3227c74b12bSAxel Dörfler
323b66c6231SAxel Dörfler	return true;
324007ed8c5SMarc Flerackers}
3257c74b12bSAxel Dörfler
3267c74b12bSAxel Dörfler
3277c74b12bSAxel Dörflerbool
3287c74b12bSAxel DörflerBOutlineListView::AddList(BList* newItems)
329007ed8c5SMarc Flerackers{
330fef39304SStephan Aßmus	return AddList(newItems, FullListCountItems());
331007ed8c5SMarc Flerackers}
3327c74b12bSAxel Dörfler
3337c74b12bSAxel Dörfler
3347c74b12bSAxel Dörflerbool
3357c74b12bSAxel DörflerBOutlineListView::AddList(BList* newItems, int32 fullListIndex)
336007ed8c5SMarc Flerackers{
337fef39304SStephan Aßmus	if ((newItems == NULL) || (newItems->CountItems() == 0))
338fef39304SStephan Aßmus		return false;
339fef39304SStephan Aßmus
340fef39304SStephan Aßmus	for (int32 i = 0; i < newItems->CountItems(); i++)
34108a35638SAxel Dörfler		AddItem((BListItem*)newItems->ItemAt(i), fullListIndex + i);
342fef39304SStephan Aßmus
343fef39304SStephan Aßmus	return true;
344007ed8c5SMarc Flerackers}
3457c74b12bSAxel Dörfler
3467c74b12bSAxel Dörfler
3477c74b12bSAxel Dörflerbool
3487c74b12bSAxel DörflerBOutlineListView::RemoveItem(BListItem* item)
349007ed8c5SMarc Flerackers{
350000d23ffSAxel Dörfler	return _RemoveItem(item, FullListIndexOf(item)) != NULL;
351007ed8c5SMarc Flerackers}
352007ed8c5SMarc Flerackers
3537c74b12bSAxel Dörfler
3547c74b12bSAxel DörflerBListItem*
3551e1afb39SJohn ScipioneBOutlineListView::RemoveItem(int32 fullListIndex)
3567c74b12bSAxel Dörfler{
3571e1afb39SJohn Scipione	return _RemoveItem(FullListItemAt(fullListIndex), fullListIndex);
358007ed8c5SMarc Flerackers}
3597c74b12bSAxel Dörfler
3607c74b12bSAxel Dörfler
3617c74b12bSAxel Dörflerbool
3621e1afb39SJohn ScipioneBOutlineListView::RemoveItems(int32 fullListIndex, int32 count)
363007ed8c5SMarc Flerackers{
3641e1afb39SJohn Scipione	if (fullListIndex >= FullListCountItems())
3651e1afb39SJohn Scipione		fullListIndex = -1;
3661e1afb39SJohn Scipione	if (fullListIndex < 0)
367b754aa3dSAxel Dörfler		return false;
368007ed8c5SMarc Flerackers
369b754aa3dSAxel Dörfler	// TODO: very bad for performance!!
3701e1afb39SJohn Scipione	while (count--)
3711e1afb39SJohn Scipione		BOutlineListView::RemoveItem(fullListIndex);
372b754aa3dSAxel Dörfler
373b754aa3dSAxel Dörfler	return true;
374007ed8c5SMarc Flerackers}
3757c74b12bSAxel Dörfler
3767c74b12bSAxel Dörfler
37708a35638SAxel DörflerBListItem*
3787c74b12bSAxel DörflerBOutlineListView::FullListItemAt(int32 fullListIndex) const
379007ed8c5SMarc Flerackers{
3807c74b12bSAxel Dörfler	return (BListItem*)fFullList.ItemAt(fullListIndex);
381007ed8c5SMarc Flerackers}
3827c74b12bSAxel Dörfler
3837c74b12bSAxel Dörfler
3847c74b12bSAxel Dörflerint32
3851e1afb39SJohn ScipioneBOutlineListView::FullListIndexOf(BPoint where) const
386007ed8c5SMarc Flerackers{
3871e1afb39SJohn Scipione	int32 index = BListView::IndexOf(where);
388ba18b05bSKarsten Heimrich
389fef39304SStephan Aßmus	if (index > 0)
39008a35638SAxel Dörfler		index = _FullListIndex(index);
391fef39304SStephan Aßmus
392fef39304SStephan Aßmus	return index;
393007ed8c5SMarc Flerackers}
3947c74b12bSAxel Dörfler
3957c74b12bSAxel Dörfler
3967c74b12bSAxel Dörflerint32
3977c74b12bSAxel DörflerBOutlineListView::FullListIndexOf(BListItem* item) const
398007ed8c5SMarc Flerackers{
3997c74b12bSAxel Dörfler	return fFullList.IndexOf(item);
400007ed8c5SMarc Flerackers}
4017c74b12bSAxel Dörfler
4027c74b12bSAxel Dörfler
40308a35638SAxel DörflerBListItem*
4047c74b12bSAxel DörflerBOutlineListView::FullListFirstItem() const
405007ed8c5SMarc Flerackers{
4067c74b12bSAxel Dörfler	return (BListItem*)fFullList.FirstItem();
407007ed8c5SMarc Flerackers}
4087c74b12bSAxel Dörfler
4097c74b12bSAxel Dörfler
41008a35638SAxel DörflerBListItem*
4117c74b12bSAxel DörflerBOutlineListView::FullListLastItem() const
412007ed8c5SMarc Flerackers{
4137c74b12bSAxel Dörfler	return (BListItem*)fFullList.LastItem();
414007ed8c5SMarc Flerackers}
4157c74b12bSAxel Dörfler
4167c74b12bSAxel Dörfler
4177c74b12bSAxel Dörflerbool
41808a35638SAxel DörflerBOutlineListView::FullListHasItem(BListItem* item) const
419007ed8c5SMarc Flerackers{
4207c74b12bSAxel Dörfler	return fFullList.HasItem(item);
421007ed8c5SMarc Flerackers}
4227c74b12bSAxel Dörfler
4237c74b12bSAxel Dörfler
4247c74b12bSAxel Dörflerint32
4257c74b12bSAxel DörflerBOutlineListView::FullListCountItems() const
426007ed8c5SMarc Flerackers{
4277c74b12bSAxel Dörfler	return fFullList.CountItems();
428007ed8c5SMarc Flerackers}
4297c74b12bSAxel Dörfler
4307c74b12bSAxel Dörfler
4317c74b12bSAxel Dörflerint32
4327c74b12bSAxel DörflerBOutlineListView::FullListCurrentSelection(int32 index) const
433007ed8c5SMarc Flerackers{
434007ed8c5SMarc Flerackers	int32 i = BListView::CurrentSelection(index);
435007ed8c5SMarc Flerackers
43608a35638SAxel Dörfler	BListItem* item = BListView::ItemAt(i);
437007ed8c5SMarc Flerackers	if (item)
4387c74b12bSAxel Dörfler		return fFullList.IndexOf(item);
4397c74b12bSAxel Dörfler
4407c74b12bSAxel Dörfler	return -1;
441007ed8c5SMarc Flerackers}
4427c74b12bSAxel Dörfler
4437c74b12bSAxel Dörfler
4447c74b12bSAxel Dörflervoid
4457c74b12bSAxel DörflerBOutlineListView::MakeEmpty()
446007ed8c5SMarc Flerackers{
4477c74b12bSAxel Dörfler	fFullList.MakeEmpty();
448007ed8c5SMarc Flerackers	BListView::MakeEmpty();
449007ed8c5SMarc Flerackers}
4507c74b12bSAxel Dörfler
4517c74b12bSAxel Dörfler
4527c74b12bSAxel Dörflerbool
4537c74b12bSAxel DörflerBOutlineListView::FullListIsEmpty() const
454007ed8c5SMarc Flerackers{
4557c74b12bSAxel Dörfler	return fFullList.IsEmpty();
456007ed8c5SMarc Flerackers}
4577c74b12bSAxel Dörfler
4587c74b12bSAxel Dörfler
4597c74b12bSAxel Dörflervoid
4607c74b12bSAxel DörflerBOutlineListView::FullListDoForEach(bool(*func)(BListItem* item))
461007ed8c5SMarc Flerackers{
4627c74b12bSAxel Dörfler	fFullList.DoForEach(reinterpret_cast<bool (*)(void*)>(func));
463007ed8c5SMarc Flerackers}
4647c74b12bSAxel Dörfler
4657c74b12bSAxel Dörfler
4667c74b12bSAxel Dörflervoid
4677c74b12bSAxel DörflerBOutlineListView::FullListDoForEach(bool (*func)(BListItem* item, void* arg),
4687c74b12bSAxel Dörfler	void* arg)
469007ed8c5SMarc Flerackers{
470fef39304SStephan Aßmus	fFullList.DoForEach(reinterpret_cast<bool (*)(void*, void*)>(func), arg);
471007ed8c5SMarc Flerackers}
4727c74b12bSAxel Dörfler
4737c74b12bSAxel Dörfler
47408a35638SAxel DörflerBListItem*
4757c74b12bSAxel DörflerBOutlineListView::Superitem(const BListItem* item)
476007ed8c5SMarc Flerackers{
477007ed8c5SMarc Flerackers	int32 index = FullListIndexOf((BListItem*)item);
478007ed8c5SMarc Flerackers	if (index == -1)
479007ed8c5SMarc Flerackers		return NULL;
4807c74b12bSAxel Dörfler
481b66c6231SAxel Dörfler	return _SuperitemForIndex(index, item->OutlineLevel());
482007ed8c5SMarc Flerackers}
483007ed8c5SMarc Flerackers
4847c74b12bSAxel Dörfler
4857c74b12bSAxel Dörflervoid
4867c74b12bSAxel DörflerBOutlineListView::Expand(BListItem* item)
4877c74b12bSAxel Dörfler{
488c544ccf5SAxel Dörfler	ExpandOrCollapse(item, true);
489007ed8c5SMarc Flerackers}
490007ed8c5SMarc Flerackers
4917c74b12bSAxel Dörfler
4927c74b12bSAxel Dörflervoid
4937c74b12bSAxel DörflerBOutlineListView::Collapse(BListItem* item)
4947c74b12bSAxel Dörfler{
495c544ccf5SAxel Dörfler	ExpandOrCollapse(item, false);
496007ed8c5SMarc Flerackers}
4977c74b12bSAxel Dörfler
4987c74b12bSAxel Dörfler
4997c74b12bSAxel Dörflerbool
5007c74b12bSAxel DörflerBOutlineListView::IsExpanded(int32 fullListIndex)
501007ed8c5SMarc Flerackers{
50208a35638SAxel Dörfler	BListItem* item = FullListItemAt(fullListIndex);
503007ed8c5SMarc Flerackers	if (!item)
504ba18b05bSKarsten Heimrich		return false;
505007ed8c5SMarc Flerackers
506007ed8c5SMarc Flerackers	return item->IsExpanded();
507007ed8c5SMarc Flerackers}
5087c74b12bSAxel Dörfler
5097c74b12bSAxel Dörfler
51008a35638SAxel DörflerBHandler*
5111f424632SJohn ScipioneBOutlineListView::ResolveSpecifier(BMessage* message, int32 index,
5127c74b12bSAxel Dörfler	BMessage* specifier, int32 what, const char* property)
513007ed8c5SMarc Flerackers{
5141f424632SJohn Scipione	return BListView::ResolveSpecifier(message, index, specifier, what,
5151f424632SJohn Scipione		property);
516007ed8c5SMarc Flerackers}
5177c74b12bSAxel Dörfler
5187c74b12bSAxel Dörfler
5197c74b12bSAxel Dörflerstatus_t
5207c74b12bSAxel DörflerBOutlineListView::GetSupportedSuites(BMessage* data)
521007ed8c5SMarc Flerackers{
522007ed8c5SMarc Flerackers	return BListView::GetSupportedSuites(data);
523007ed8c5SMarc Flerackers}
5247c74b12bSAxel Dörfler
5257c74b12bSAxel Dörfler
5267c74b12bSAxel Dörflerstatus_t
52739fbf550SOliver TappeBOutlineListView::Perform(perform_code code, void* _data)
52839fbf550SOliver Tappe{
52939fbf550SOliver Tappe	switch (code) {
53039fbf550SOliver Tappe		case PERFORM_CODE_MIN_SIZE:
53139fbf550SOliver Tappe			((perform_data_min_size*)_data)->return_value
53239fbf550SOliver Tappe				= BOutlineListView::MinSize();
53339fbf550SOliver Tappe			return B_OK;
53439fbf550SOliver Tappe		case PERFORM_CODE_MAX_SIZE:
53539fbf550SOliver Tappe			((perform_data_max_size*)_data)->return_value
53639fbf550SOliver Tappe				= BOutlineListView::MaxSize();
53739fbf550SOliver Tappe			return B_OK;
53839fbf550SOliver Tappe		case PERFORM_CODE_PREFERRED_SIZE:
53939fbf550SOliver Tappe			((perform_data_preferred_size*)_data)->return_value
54039fbf550SOliver Tappe				= BOutlineListView::PreferredSize();
54139fbf550SOliver Tappe			return B_OK;
54239fbf550SOliver Tappe		case PERFORM_CODE_LAYOUT_ALIGNMENT:
54339fbf550SOliver Tappe			((perform_data_layout_alignment*)_data)->return_value
54439fbf550SOliver Tappe				= BOutlineListView::LayoutAlignment();
54539fbf550SOliver Tappe			return B_OK;
54639fbf550SOliver Tappe		case PERFORM_CODE_HAS_HEIGHT_FOR_WIDTH:
54739fbf550SOliver Tappe			((perform_data_has_height_for_width*)_data)->return_value
54839fbf550SOliver Tappe				= BOutlineListView::HasHeightForWidth();
54939fbf550SOliver Tappe			return B_OK;
55039fbf550SOliver Tappe		case PERFORM_CODE_GET_HEIGHT_FOR_WIDTH:
55139fbf550SOliver Tappe		{
55239fbf550SOliver Tappe			perform_data_get_height_for_width* data
55339fbf550SOliver Tappe				= (perform_data_get_height_for_width*)_data;
55408a35638SAxel Dörfler			BOutlineListView::GetHeightForWidth(data->width, &data->min,
55508a35638SAxel Dörfler				&data->max, &data->preferred);
55639fbf550SOliver Tappe			return B_OK;
5573c179024SJérôme Duval		}
55839fbf550SOliver Tappe		case PERFORM_CODE_SET_LAYOUT:
55939fbf550SOliver Tappe		{
56039fbf550SOliver Tappe			perform_data_set_layout* data = (perform_data_set_layout*)_data;
56139fbf550SOliver Tappe			BOutlineListView::SetLayout(data->layout);
56239fbf550SOliver Tappe			return B_OK;
56339fbf550SOliver Tappe		}
564eee4243dSAlex Wilson		case PERFORM_CODE_LAYOUT_INVALIDATED:
56539fbf550SOliver Tappe		{
566eee4243dSAlex Wilson			perform_data_layout_invalidated* data
567eee4243dSAlex Wilson				= (perform_data_layout_invalidated*)_data;
568eee4243dSAlex Wilson			BOutlineListView::LayoutInvalidated(data->descendants);
56939fbf550SOliver Tappe			return B_OK;
57039fbf550SOliver Tappe		}
57139fbf550SOliver Tappe		case PERFORM_CODE_DO_LAYOUT:
57239fbf550SOliver Tappe		{
57339fbf550SOliver Tappe			BOutlineListView::DoLayout();
57439fbf550SOliver Tappe			return B_OK;
57539fbf550SOliver Tappe		}
57639fbf550SOliver Tappe	}
57739fbf550SOliver Tappe
57839fbf550SOliver Tappe	return BListView::Perform(code, _data);
579007ed8c5SMarc Flerackers}
5807c74b12bSAxel Dörfler
5817c74b12bSAxel Dörfler
5827c74b12bSAxel Dörflervoid
5837c74b12bSAxel DörflerBOutlineListView::ResizeToPreferred()
584007ed8c5SMarc Flerackers{
585007ed8c5SMarc Flerackers	BListView::ResizeToPreferred();
586007ed8c5SMarc Flerackers}
5877c74b12bSAxel Dörfler
5887c74b12bSAxel Dörfler
5897c74b12bSAxel Dörflervoid
5907c74b12bSAxel DörflerBOutlineListView::GetPreferredSize(float* _width, float* _height)
591007ed8c5SMarc Flerackers{
59234ac7f7aSAdrien Destugues	int32 count = CountItems();
59334ac7f7aSAdrien Destugues
59434ac7f7aSAdrien Destugues	if (count > 0) {
59534ac7f7aSAdrien Destugues		float maxWidth = 0.0;
59634ac7f7aSAdrien Destugues		for (int32 i = 0; i < count; i++) {
59734ac7f7aSAdrien Destugues			// The item itself does not take his OutlineLevel into account, so
59834ac7f7aSAdrien Destugues			// we must make up for that. Also add space for the latch.
59934ac7f7aSAdrien Destugues			float itemWidth = ItemAt(i)->Width() + be_plain_font->Size()
60034ac7f7aSAdrien Destugues				+ (ItemAt(i)->OutlineLevel() + 1)
60134ac7f7aSAdrien Destugues					* be_control_look->DefaultItemSpacing();
60234ac7f7aSAdrien Destugues			if (itemWidth > maxWidth)
60334ac7f7aSAdrien Destugues				maxWidth = itemWidth;
60434ac7f7aS