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