xref: /haiku/src/apps/debuganalyzer/gui/ListSelectionModel.cpp (revision 446ac6d727e4a6ef4dee1e360de543092e061f10)
1*446ac6d7SIngo Weinhold /*
2*446ac6d7SIngo Weinhold  * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3*446ac6d7SIngo Weinhold  * Distributed under the terms of the MIT License.
4*446ac6d7SIngo Weinhold  */
5*446ac6d7SIngo Weinhold 
6*446ac6d7SIngo Weinhold 
7*446ac6d7SIngo Weinhold #include "ListSelectionModel.h"
8*446ac6d7SIngo Weinhold 
9*446ac6d7SIngo Weinhold 
10*446ac6d7SIngo Weinhold // #pragma mark - ListSelectionModel
11*446ac6d7SIngo Weinhold 
12*446ac6d7SIngo Weinhold 
13*446ac6d7SIngo Weinhold ListSelectionModel::ListSelectionModel()
14*446ac6d7SIngo Weinhold 	:
15*446ac6d7SIngo Weinhold 	fItemCount(0)
16*446ac6d7SIngo Weinhold {
17*446ac6d7SIngo Weinhold }
18*446ac6d7SIngo Weinhold 
19*446ac6d7SIngo Weinhold 
20*446ac6d7SIngo Weinhold ListSelectionModel::~ListSelectionModel()
21*446ac6d7SIngo Weinhold {
22*446ac6d7SIngo Weinhold }
23*446ac6d7SIngo Weinhold 
24*446ac6d7SIngo Weinhold 
25*446ac6d7SIngo Weinhold void
26*446ac6d7SIngo Weinhold ListSelectionModel::Clear()
27*446ac6d7SIngo Weinhold {
28*446ac6d7SIngo Weinhold 	int32 selectedCount = fSelectedItems.Count();
29*446ac6d7SIngo Weinhold 	if (selectedCount > 0) {
30*446ac6d7SIngo Weinhold 		int32 firstSelected = fSelectedItems[0];
31*446ac6d7SIngo Weinhold 		int32 lastSelected = fSelectedItems[selectedCount - 1];
32*446ac6d7SIngo Weinhold 
33*446ac6d7SIngo Weinhold 		fSelectedItems.Clear();
34*446ac6d7SIngo Weinhold 
35*446ac6d7SIngo Weinhold 		_NotifyItemsDeselected(firstSelected, lastSelected - firstSelected + 1);
36*446ac6d7SIngo Weinhold 	}
37*446ac6d7SIngo Weinhold }
38*446ac6d7SIngo Weinhold 
39*446ac6d7SIngo Weinhold 
40*446ac6d7SIngo Weinhold bool
41*446ac6d7SIngo Weinhold ListSelectionModel::SelectItems(int32 itemIndex, int32 count,
42*446ac6d7SIngo Weinhold 	bool extendSelection)
43*446ac6d7SIngo Weinhold {
44*446ac6d7SIngo Weinhold 	int32 endItemIndex = itemIndex + count;
45*446ac6d7SIngo Weinhold 
46*446ac6d7SIngo Weinhold 	int32 index;
47*446ac6d7SIngo Weinhold 	if (extendSelection) {
48*446ac6d7SIngo Weinhold 		if (count <= 0)
49*446ac6d7SIngo Weinhold 			return true;
50*446ac6d7SIngo Weinhold 
51*446ac6d7SIngo Weinhold 		index = _FindItem(itemIndex);
52*446ac6d7SIngo Weinhold 
53*446ac6d7SIngo Weinhold 		// count already selected items
54*446ac6d7SIngo Weinhold 		int32 alreadySelectedCount = _CountSelectedItemsInRange(index,
55*446ac6d7SIngo Weinhold 			endItemIndex);
56*446ac6d7SIngo Weinhold 		if (alreadySelectedCount == count)
57*446ac6d7SIngo Weinhold 			return true;
58*446ac6d7SIngo Weinhold 
59*446ac6d7SIngo Weinhold 		// make room for the new items
60*446ac6d7SIngo Weinhold 		if (!fSelectedItems.InsertUninitialized(index + alreadySelectedCount,
61*446ac6d7SIngo Weinhold 				count - alreadySelectedCount)) {
62*446ac6d7SIngo Weinhold 			return false;
63*446ac6d7SIngo Weinhold 		}
64*446ac6d7SIngo Weinhold 	} else {
65*446ac6d7SIngo Weinhold 		// TODO: Don't clear -- just resize to the right size!
66*446ac6d7SIngo Weinhold 		Clear();
67*446ac6d7SIngo Weinhold 		if (count <= 0)
68*446ac6d7SIngo Weinhold 			return true;
69*446ac6d7SIngo Weinhold 
70*446ac6d7SIngo Weinhold 		index = 0;
71*446ac6d7SIngo Weinhold 		if (!fSelectedItems.AddUninitialized(count))
72*446ac6d7SIngo Weinhold 			return false;
73*446ac6d7SIngo Weinhold 	}
74*446ac6d7SIngo Weinhold 
75*446ac6d7SIngo Weinhold 	for (int32 i = 0; i < count; i++)
76*446ac6d7SIngo Weinhold 		fSelectedItems[index + i] = itemIndex + i;
77*446ac6d7SIngo Weinhold 
78*446ac6d7SIngo Weinhold 	_NotifyItemsSelected(itemIndex, count);
79*446ac6d7SIngo Weinhold 
80*446ac6d7SIngo Weinhold 	return true;
81*446ac6d7SIngo Weinhold }
82*446ac6d7SIngo Weinhold 
83*446ac6d7SIngo Weinhold 
84*446ac6d7SIngo Weinhold void
85*446ac6d7SIngo Weinhold ListSelectionModel::DeselectItems(int32 itemIndex, int32 count)
86*446ac6d7SIngo Weinhold {
87*446ac6d7SIngo Weinhold 	int32 endItemIndex = itemIndex + count;
88*446ac6d7SIngo Weinhold 	int32 index = _FindItem(itemIndex);
89*446ac6d7SIngo Weinhold 
90*446ac6d7SIngo Weinhold 	// count actually selected items
91*446ac6d7SIngo Weinhold 	int32 actuallySelectedCount = _CountSelectedItemsInRange(index,
92*446ac6d7SIngo Weinhold 		endItemIndex);
93*446ac6d7SIngo Weinhold 	if (actuallySelectedCount == 0)
94*446ac6d7SIngo Weinhold 		return;
95*446ac6d7SIngo Weinhold 
96*446ac6d7SIngo Weinhold 	fSelectedItems.Remove(index, actuallySelectedCount);
97*446ac6d7SIngo Weinhold 
98*446ac6d7SIngo Weinhold 	_NotifyItemsDeselected(itemIndex, count);
99*446ac6d7SIngo Weinhold }
100*446ac6d7SIngo Weinhold 
101*446ac6d7SIngo Weinhold 
102*446ac6d7SIngo Weinhold void
103*446ac6d7SIngo Weinhold ListSelectionModel::ItemsAdded(int32 itemIndex, int32 count)
104*446ac6d7SIngo Weinhold {
105*446ac6d7SIngo Weinhold 	if (count <= 0)
106*446ac6d7SIngo Weinhold 		return;
107*446ac6d7SIngo Weinhold 
108*446ac6d7SIngo Weinhold 	// re-index following items
109*446ac6d7SIngo Weinhold 	int32 index = _FindItem(itemIndex);
110*446ac6d7SIngo Weinhold 	int32 selectedCount = fSelectedItems.Count();
111*446ac6d7SIngo Weinhold 	for (int32 i = index; i < selectedCount; i++)
112*446ac6d7SIngo Weinhold 		fSelectedItems[i] += count;
113*446ac6d7SIngo Weinhold }
114*446ac6d7SIngo Weinhold 
115*446ac6d7SIngo Weinhold 
116*446ac6d7SIngo Weinhold void
117*446ac6d7SIngo Weinhold ListSelectionModel::ItemsRemoved(int32 itemIndex, int32 count)
118*446ac6d7SIngo Weinhold {
119*446ac6d7SIngo Weinhold 	if (count <= 0)
120*446ac6d7SIngo Weinhold 		return;
121*446ac6d7SIngo Weinhold 
122*446ac6d7SIngo Weinhold 	int32 index = _FindItem(itemIndex);
123*446ac6d7SIngo Weinhold 
124*446ac6d7SIngo Weinhold 	// count selected items in the range
125*446ac6d7SIngo Weinhold 	int32 actuallySelectedCount = _CountSelectedItemsInRange(index,
126*446ac6d7SIngo Weinhold 		itemIndex + count);
127*446ac6d7SIngo Weinhold 	if (actuallySelectedCount > 0)
128*446ac6d7SIngo Weinhold 		fSelectedItems.Remove(index, actuallySelectedCount);
129*446ac6d7SIngo Weinhold 
130*446ac6d7SIngo Weinhold 	// re-index following items
131*446ac6d7SIngo Weinhold 	int32 selectedCount = fSelectedItems.Count();
132*446ac6d7SIngo Weinhold 	for (int32 i = index; i < selectedCount; i++)
133*446ac6d7SIngo Weinhold 		fSelectedItems[i] -= count;
134*446ac6d7SIngo Weinhold }
135*446ac6d7SIngo Weinhold 
136*446ac6d7SIngo Weinhold 
137*446ac6d7SIngo Weinhold bool
138*446ac6d7SIngo Weinhold ListSelectionModel::AddListener(Listener* listener)
139*446ac6d7SIngo Weinhold {
140*446ac6d7SIngo Weinhold 	return fListeners.AddItem(listener);
141*446ac6d7SIngo Weinhold }
142*446ac6d7SIngo Weinhold 
143*446ac6d7SIngo Weinhold 
144*446ac6d7SIngo Weinhold void
145*446ac6d7SIngo Weinhold ListSelectionModel::RemoveListener(Listener* listener)
146*446ac6d7SIngo Weinhold {
147*446ac6d7SIngo Weinhold 	fListeners.RemoveItem(listener);
148*446ac6d7SIngo Weinhold }
149*446ac6d7SIngo Weinhold 
150*446ac6d7SIngo Weinhold 
151*446ac6d7SIngo Weinhold int32
152*446ac6d7SIngo Weinhold ListSelectionModel::_FindItem(int32 itemIndex) const
153*446ac6d7SIngo Weinhold {
154*446ac6d7SIngo Weinhold 	// binary search the index of the first item >= itemIndex
155*446ac6d7SIngo Weinhold 	int32 lower = 0;
156*446ac6d7SIngo Weinhold 	int32 upper = fSelectedItems.Count();
157*446ac6d7SIngo Weinhold 
158*446ac6d7SIngo Weinhold 	while (lower < upper) {
159*446ac6d7SIngo Weinhold 		int32 mid = (lower + upper) / 2;
160*446ac6d7SIngo Weinhold 
161*446ac6d7SIngo Weinhold 		if (fSelectedItems[mid] < itemIndex)
162*446ac6d7SIngo Weinhold 			lower = mid + 1;
163*446ac6d7SIngo Weinhold 		else
164*446ac6d7SIngo Weinhold 			upper = mid;
165*446ac6d7SIngo Weinhold 	}
166*446ac6d7SIngo Weinhold 
167*446ac6d7SIngo Weinhold 	return lower;
168*446ac6d7SIngo Weinhold }
169*446ac6d7SIngo Weinhold 
170*446ac6d7SIngo Weinhold 
171*446ac6d7SIngo Weinhold int32
172*446ac6d7SIngo Weinhold ListSelectionModel::_CountSelectedItemsInRange(int32 index,
173*446ac6d7SIngo Weinhold 	int32 endItemIndex) const
174*446ac6d7SIngo Weinhold {
175*446ac6d7SIngo Weinhold 	int32 count = 0;
176*446ac6d7SIngo Weinhold 	int32 selectedCount = fSelectedItems.Count();
177*446ac6d7SIngo Weinhold 	for (int32 i = index; i < selectedCount; i++) {
178*446ac6d7SIngo Weinhold 		if (SelectedItemAt(i) >= endItemIndex)
179*446ac6d7SIngo Weinhold 			break;
180*446ac6d7SIngo Weinhold 		count++;
181*446ac6d7SIngo Weinhold 	}
182*446ac6d7SIngo Weinhold 
183*446ac6d7SIngo Weinhold 	return count;
184*446ac6d7SIngo Weinhold }
185*446ac6d7SIngo Weinhold 
186*446ac6d7SIngo Weinhold 
187*446ac6d7SIngo Weinhold void
188*446ac6d7SIngo Weinhold ListSelectionModel::_NotifyItemsSelected(int32 index, int32 count)
189*446ac6d7SIngo Weinhold {
190*446ac6d7SIngo Weinhold 	int32 listenerCount = fListeners.CountItems();
191*446ac6d7SIngo Weinhold 	for (int32 i = listenerCount - 1; i >= 0; i--)
192*446ac6d7SIngo Weinhold 		fListeners.ItemAt(i)->ItemsSelected(this, index, count);
193*446ac6d7SIngo Weinhold }
194*446ac6d7SIngo Weinhold 
195*446ac6d7SIngo Weinhold 
196*446ac6d7SIngo Weinhold void
197*446ac6d7SIngo Weinhold ListSelectionModel::_NotifyItemsDeselected(int32 index, int32 count)
198*446ac6d7SIngo Weinhold {
199*446ac6d7SIngo Weinhold 	int32 listenerCount = fListeners.CountItems();
200*446ac6d7SIngo Weinhold 	for (int32 i = listenerCount - 1; i >= 0; i--)
201*446ac6d7SIngo Weinhold 		fListeners.ItemAt(i)->ItemsDeselected(this, index, count);
202*446ac6d7SIngo Weinhold }
203*446ac6d7SIngo Weinhold 
204*446ac6d7SIngo Weinhold 
205*446ac6d7SIngo Weinhold // #pragma mark - Listener
206*446ac6d7SIngo Weinhold 
207*446ac6d7SIngo Weinhold 
208*446ac6d7SIngo Weinhold ListSelectionModel::Listener::~Listener()
209*446ac6d7SIngo Weinhold {
210*446ac6d7SIngo Weinhold }
211*446ac6d7SIngo Weinhold 
212*446ac6d7SIngo Weinhold 
213*446ac6d7SIngo Weinhold void
214*446ac6d7SIngo Weinhold ListSelectionModel::Listener::ItemsSelected(ListSelectionModel* model,
215*446ac6d7SIngo Weinhold 	int32 index, int32 count)
216*446ac6d7SIngo Weinhold {
217*446ac6d7SIngo Weinhold }
218*446ac6d7SIngo Weinhold 
219*446ac6d7SIngo Weinhold 
220*446ac6d7SIngo Weinhold void
221*446ac6d7SIngo Weinhold ListSelectionModel::Listener::ItemsDeselected(ListSelectionModel* model,
222*446ac6d7SIngo Weinhold 	int32 index, int32 count)
223*446ac6d7SIngo Weinhold {
224*446ac6d7SIngo Weinhold }
225