xref: /haiku/src/apps/debuganalyzer/gui/ListSelectionModel.cpp (revision 63481b10d3fbbc39c40a71af242f21ae42eb2cd4)
1446ac6d7SIngo Weinhold /*
2446ac6d7SIngo Weinhold  * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3446ac6d7SIngo Weinhold  * Distributed under the terms of the MIT License.
4446ac6d7SIngo Weinhold  */
5446ac6d7SIngo Weinhold 
6446ac6d7SIngo Weinhold 
7446ac6d7SIngo Weinhold #include "ListSelectionModel.h"
8446ac6d7SIngo Weinhold 
9446ac6d7SIngo Weinhold 
10446ac6d7SIngo Weinhold // #pragma mark - ListSelectionModel
11446ac6d7SIngo Weinhold 
12446ac6d7SIngo Weinhold 
ListSelectionModel()13446ac6d7SIngo Weinhold ListSelectionModel::ListSelectionModel()
14446ac6d7SIngo Weinhold {
15446ac6d7SIngo Weinhold }
16446ac6d7SIngo Weinhold 
17446ac6d7SIngo Weinhold 
ListSelectionModel(const ListSelectionModel & other)18*63481b10SIngo Weinhold ListSelectionModel::ListSelectionModel(const ListSelectionModel& other)
19*63481b10SIngo Weinhold {
20*63481b10SIngo Weinhold 	*this = other;
21*63481b10SIngo Weinhold }
22*63481b10SIngo Weinhold 
23*63481b10SIngo Weinhold 
~ListSelectionModel()24446ac6d7SIngo Weinhold ListSelectionModel::~ListSelectionModel()
25446ac6d7SIngo Weinhold {
26446ac6d7SIngo Weinhold }
27446ac6d7SIngo Weinhold 
28446ac6d7SIngo Weinhold 
29446ac6d7SIngo Weinhold void
Clear()30446ac6d7SIngo Weinhold ListSelectionModel::Clear()
31446ac6d7SIngo Weinhold {
32446ac6d7SIngo Weinhold 	int32 selectedCount = fSelectedItems.Count();
33446ac6d7SIngo Weinhold 	if (selectedCount > 0) {
34446ac6d7SIngo Weinhold 		int32 firstSelected = fSelectedItems[0];
35446ac6d7SIngo Weinhold 		int32 lastSelected = fSelectedItems[selectedCount - 1];
36446ac6d7SIngo Weinhold 
37446ac6d7SIngo Weinhold 		fSelectedItems.Clear();
38446ac6d7SIngo Weinhold 
39446ac6d7SIngo Weinhold 		_NotifyItemsDeselected(firstSelected, lastSelected - firstSelected + 1);
40446ac6d7SIngo Weinhold 	}
41446ac6d7SIngo Weinhold }
42446ac6d7SIngo Weinhold 
43446ac6d7SIngo Weinhold 
44446ac6d7SIngo Weinhold bool
SelectItems(int32 itemIndex,int32 count,bool extendSelection)45446ac6d7SIngo Weinhold ListSelectionModel::SelectItems(int32 itemIndex, int32 count,
46446ac6d7SIngo Weinhold 	bool extendSelection)
47446ac6d7SIngo Weinhold {
48446ac6d7SIngo Weinhold 	int32 endItemIndex = itemIndex + count;
49446ac6d7SIngo Weinhold 
50446ac6d7SIngo Weinhold 	int32 index;
51446ac6d7SIngo Weinhold 	if (extendSelection) {
52446ac6d7SIngo Weinhold 		if (count <= 0)
53446ac6d7SIngo Weinhold 			return true;
54446ac6d7SIngo Weinhold 
55446ac6d7SIngo Weinhold 		index = _FindItem(itemIndex);
56446ac6d7SIngo Weinhold 
57446ac6d7SIngo Weinhold 		// count already selected items
58446ac6d7SIngo Weinhold 		int32 alreadySelectedCount = _CountSelectedItemsInRange(index,
59446ac6d7SIngo Weinhold 			endItemIndex);
60446ac6d7SIngo Weinhold 		if (alreadySelectedCount == count)
61446ac6d7SIngo Weinhold 			return true;
62446ac6d7SIngo Weinhold 
63446ac6d7SIngo Weinhold 		// make room for the new items
64446ac6d7SIngo Weinhold 		if (!fSelectedItems.InsertUninitialized(index + alreadySelectedCount,
65446ac6d7SIngo Weinhold 				count - alreadySelectedCount)) {
66446ac6d7SIngo Weinhold 			return false;
67446ac6d7SIngo Weinhold 		}
68446ac6d7SIngo Weinhold 	} else {
69446ac6d7SIngo Weinhold 		// TODO: Don't clear -- just resize to the right size!
70446ac6d7SIngo Weinhold 		Clear();
71446ac6d7SIngo Weinhold 		if (count <= 0)
72446ac6d7SIngo Weinhold 			return true;
73446ac6d7SIngo Weinhold 
74446ac6d7SIngo Weinhold 		index = 0;
75446ac6d7SIngo Weinhold 		if (!fSelectedItems.AddUninitialized(count))
76446ac6d7SIngo Weinhold 			return false;
77446ac6d7SIngo Weinhold 	}
78446ac6d7SIngo Weinhold 
79446ac6d7SIngo Weinhold 	for (int32 i = 0; i < count; i++)
80446ac6d7SIngo Weinhold 		fSelectedItems[index + i] = itemIndex + i;
81446ac6d7SIngo Weinhold 
82446ac6d7SIngo Weinhold 	_NotifyItemsSelected(itemIndex, count);
83446ac6d7SIngo Weinhold 
84446ac6d7SIngo Weinhold 	return true;
85446ac6d7SIngo Weinhold }
86446ac6d7SIngo Weinhold 
87446ac6d7SIngo Weinhold 
88446ac6d7SIngo Weinhold void
DeselectItems(int32 itemIndex,int32 count)89446ac6d7SIngo Weinhold ListSelectionModel::DeselectItems(int32 itemIndex, int32 count)
90446ac6d7SIngo Weinhold {
91446ac6d7SIngo Weinhold 	int32 endItemIndex = itemIndex + count;
92446ac6d7SIngo Weinhold 	int32 index = _FindItem(itemIndex);
93446ac6d7SIngo Weinhold 
94446ac6d7SIngo Weinhold 	// count actually selected items
95446ac6d7SIngo Weinhold 	int32 actuallySelectedCount = _CountSelectedItemsInRange(index,
96446ac6d7SIngo Weinhold 		endItemIndex);
97446ac6d7SIngo Weinhold 	if (actuallySelectedCount == 0)
98446ac6d7SIngo Weinhold 		return;
99446ac6d7SIngo Weinhold 
100446ac6d7SIngo Weinhold 	fSelectedItems.Remove(index, actuallySelectedCount);
101446ac6d7SIngo Weinhold 
102446ac6d7SIngo Weinhold 	_NotifyItemsDeselected(itemIndex, count);
103446ac6d7SIngo Weinhold }
104446ac6d7SIngo Weinhold 
105446ac6d7SIngo Weinhold 
106446ac6d7SIngo Weinhold void
ItemsAdded(int32 itemIndex,int32 count)107446ac6d7SIngo Weinhold ListSelectionModel::ItemsAdded(int32 itemIndex, int32 count)
108446ac6d7SIngo Weinhold {
109446ac6d7SIngo Weinhold 	if (count <= 0)
110446ac6d7SIngo Weinhold 		return;
111446ac6d7SIngo Weinhold 
112446ac6d7SIngo Weinhold 	// re-index following items
113446ac6d7SIngo Weinhold 	int32 index = _FindItem(itemIndex);
114446ac6d7SIngo Weinhold 	int32 selectedCount = fSelectedItems.Count();
115446ac6d7SIngo Weinhold 	for (int32 i = index; i < selectedCount; i++)
116446ac6d7SIngo Weinhold 		fSelectedItems[i] += count;
117446ac6d7SIngo Weinhold }
118446ac6d7SIngo Weinhold 
119446ac6d7SIngo Weinhold 
120446ac6d7SIngo Weinhold void
ItemsRemoved(int32 itemIndex,int32 count)121446ac6d7SIngo Weinhold ListSelectionModel::ItemsRemoved(int32 itemIndex, int32 count)
122446ac6d7SIngo Weinhold {
123446ac6d7SIngo Weinhold 	if (count <= 0)
124446ac6d7SIngo Weinhold 		return;
125446ac6d7SIngo Weinhold 
126446ac6d7SIngo Weinhold 	int32 index = _FindItem(itemIndex);
127446ac6d7SIngo Weinhold 
128446ac6d7SIngo Weinhold 	// count selected items in the range
129446ac6d7SIngo Weinhold 	int32 actuallySelectedCount = _CountSelectedItemsInRange(index,
130446ac6d7SIngo Weinhold 		itemIndex + count);
131446ac6d7SIngo Weinhold 	if (actuallySelectedCount > 0)
132446ac6d7SIngo Weinhold 		fSelectedItems.Remove(index, actuallySelectedCount);
133446ac6d7SIngo Weinhold 
134446ac6d7SIngo Weinhold 	// re-index following items
135446ac6d7SIngo Weinhold 	int32 selectedCount = fSelectedItems.Count();
136446ac6d7SIngo Weinhold 	for (int32 i = index; i < selectedCount; i++)
137446ac6d7SIngo Weinhold 		fSelectedItems[i] -= count;
138446ac6d7SIngo Weinhold }
139446ac6d7SIngo Weinhold 
140446ac6d7SIngo Weinhold 
141446ac6d7SIngo Weinhold bool
AddListener(Listener * listener)142446ac6d7SIngo Weinhold ListSelectionModel::AddListener(Listener* listener)
143446ac6d7SIngo Weinhold {
144446ac6d7SIngo Weinhold 	return fListeners.AddItem(listener);
145446ac6d7SIngo Weinhold }
146446ac6d7SIngo Weinhold 
147446ac6d7SIngo Weinhold 
148446ac6d7SIngo Weinhold void
RemoveListener(Listener * listener)149446ac6d7SIngo Weinhold ListSelectionModel::RemoveListener(Listener* listener)
150446ac6d7SIngo Weinhold {
151446ac6d7SIngo Weinhold 	fListeners.RemoveItem(listener);
152446ac6d7SIngo Weinhold }
153446ac6d7SIngo Weinhold 
154446ac6d7SIngo Weinhold 
155*63481b10SIngo Weinhold ListSelectionModel&
operator =(const ListSelectionModel & other)156*63481b10SIngo Weinhold ListSelectionModel::operator=(const ListSelectionModel& other)
157*63481b10SIngo Weinhold {
158*63481b10SIngo Weinhold 	Clear();
159*63481b10SIngo Weinhold 
160*63481b10SIngo Weinhold 	fSelectedItems = other.fSelectedItems;
161*63481b10SIngo Weinhold 
162*63481b10SIngo Weinhold 	int32 selectedCount = CountSelectedItems();
163*63481b10SIngo Weinhold 	if (selectedCount > 0) {
164*63481b10SIngo Weinhold 		int32 firstSelected = fSelectedItems[0];
165*63481b10SIngo Weinhold 		int32 lastSelected = fSelectedItems[selectedCount - 1];
166*63481b10SIngo Weinhold 		_NotifyItemsDeselected(firstSelected, lastSelected - firstSelected + 1);
167*63481b10SIngo Weinhold 	}
168*63481b10SIngo Weinhold 
169*63481b10SIngo Weinhold 	return *this;
170*63481b10SIngo Weinhold }
171*63481b10SIngo Weinhold 
172*63481b10SIngo Weinhold 
173446ac6d7SIngo Weinhold int32
_FindItem(int32 itemIndex) const174446ac6d7SIngo Weinhold ListSelectionModel::_FindItem(int32 itemIndex) const
175446ac6d7SIngo Weinhold {
176446ac6d7SIngo Weinhold 	// binary search the index of the first item >= itemIndex
177446ac6d7SIngo Weinhold 	int32 lower = 0;
178446ac6d7SIngo Weinhold 	int32 upper = fSelectedItems.Count();
179446ac6d7SIngo Weinhold 
180446ac6d7SIngo Weinhold 	while (lower < upper) {
181446ac6d7SIngo Weinhold 		int32 mid = (lower + upper) / 2;
182446ac6d7SIngo Weinhold 
183446ac6d7SIngo Weinhold 		if (fSelectedItems[mid] < itemIndex)
184446ac6d7SIngo Weinhold 			lower = mid + 1;
185446ac6d7SIngo Weinhold 		else
186446ac6d7SIngo Weinhold 			upper = mid;
187446ac6d7SIngo Weinhold 	}
188446ac6d7SIngo Weinhold 
189446ac6d7SIngo Weinhold 	return lower;
190446ac6d7SIngo Weinhold }
191446ac6d7SIngo Weinhold 
192446ac6d7SIngo Weinhold 
193446ac6d7SIngo Weinhold int32
_CountSelectedItemsInRange(int32 index,int32 endItemIndex) const194446ac6d7SIngo Weinhold ListSelectionModel::_CountSelectedItemsInRange(int32 index,
195446ac6d7SIngo Weinhold 	int32 endItemIndex) const
196446ac6d7SIngo Weinhold {
197446ac6d7SIngo Weinhold 	int32 count = 0;
198446ac6d7SIngo Weinhold 	int32 selectedCount = fSelectedItems.Count();
199446ac6d7SIngo Weinhold 	for (int32 i = index; i < selectedCount; i++) {
200446ac6d7SIngo Weinhold 		if (SelectedItemAt(i) >= endItemIndex)
201446ac6d7SIngo Weinhold 			break;
202446ac6d7SIngo Weinhold 		count++;
203446ac6d7SIngo Weinhold 	}
204446ac6d7SIngo Weinhold 
205446ac6d7SIngo Weinhold 	return count;
206446ac6d7SIngo Weinhold }
207446ac6d7SIngo Weinhold 
208446ac6d7SIngo Weinhold 
209446ac6d7SIngo Weinhold void
_NotifyItemsSelected(int32 index,int32 count)210446ac6d7SIngo Weinhold ListSelectionModel::_NotifyItemsSelected(int32 index, int32 count)
211446ac6d7SIngo Weinhold {
212446ac6d7SIngo Weinhold 	int32 listenerCount = fListeners.CountItems();
213446ac6d7SIngo Weinhold 	for (int32 i = listenerCount - 1; i >= 0; i--)
214446ac6d7SIngo Weinhold 		fListeners.ItemAt(i)->ItemsSelected(this, index, count);
215446ac6d7SIngo Weinhold }
216446ac6d7SIngo Weinhold 
217446ac6d7SIngo Weinhold 
218446ac6d7SIngo Weinhold void
_NotifyItemsDeselected(int32 index,int32 count)219446ac6d7SIngo Weinhold ListSelectionModel::_NotifyItemsDeselected(int32 index, int32 count)
220446ac6d7SIngo Weinhold {
221446ac6d7SIngo Weinhold 	int32 listenerCount = fListeners.CountItems();
222446ac6d7SIngo Weinhold 	for (int32 i = listenerCount - 1; i >= 0; i--)
223446ac6d7SIngo Weinhold 		fListeners.ItemAt(i)->ItemsDeselected(this, index, count);
224446ac6d7SIngo Weinhold }
225446ac6d7SIngo Weinhold 
226446ac6d7SIngo Weinhold 
227446ac6d7SIngo Weinhold // #pragma mark - Listener
228446ac6d7SIngo Weinhold 
229446ac6d7SIngo Weinhold 
~Listener()230446ac6d7SIngo Weinhold ListSelectionModel::Listener::~Listener()
231446ac6d7SIngo Weinhold {
232446ac6d7SIngo Weinhold }
233446ac6d7SIngo Weinhold 
234446ac6d7SIngo Weinhold 
235446ac6d7SIngo Weinhold void
ItemsSelected(ListSelectionModel * model,int32 index,int32 count)236446ac6d7SIngo Weinhold ListSelectionModel::Listener::ItemsSelected(ListSelectionModel* model,
237446ac6d7SIngo Weinhold 	int32 index, int32 count)
238446ac6d7SIngo Weinhold {
239446ac6d7SIngo Weinhold }
240446ac6d7SIngo Weinhold 
241446ac6d7SIngo Weinhold 
242446ac6d7SIngo Weinhold void
ItemsDeselected(ListSelectionModel * model,int32 index,int32 count)243446ac6d7SIngo Weinhold ListSelectionModel::Listener::ItemsDeselected(ListSelectionModel* model,
244446ac6d7SIngo Weinhold 	int32 index, int32 count)
245446ac6d7SIngo Weinhold {
246446ac6d7SIngo Weinhold }
247