vfs: check userland buffers before reading them.
[haiku.git] / src / apps / debuganalyzer / gui / ListSelectionModel.cpp
blobd1ea40d16a6f73769690294b2a798ab1b2add266
1 /*
2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
7 #include "ListSelectionModel.h"
10 // #pragma mark - ListSelectionModel
13 ListSelectionModel::ListSelectionModel()
18 ListSelectionModel::ListSelectionModel(const ListSelectionModel& other)
20 *this = other;
24 ListSelectionModel::~ListSelectionModel()
29 void
30 ListSelectionModel::Clear()
32 int32 selectedCount = fSelectedItems.Count();
33 if (selectedCount > 0) {
34 int32 firstSelected = fSelectedItems[0];
35 int32 lastSelected = fSelectedItems[selectedCount - 1];
37 fSelectedItems.Clear();
39 _NotifyItemsDeselected(firstSelected, lastSelected - firstSelected + 1);
44 bool
45 ListSelectionModel::SelectItems(int32 itemIndex, int32 count,
46 bool extendSelection)
48 int32 endItemIndex = itemIndex + count;
50 int32 index;
51 if (extendSelection) {
52 if (count <= 0)
53 return true;
55 index = _FindItem(itemIndex);
57 // count already selected items
58 int32 alreadySelectedCount = _CountSelectedItemsInRange(index,
59 endItemIndex);
60 if (alreadySelectedCount == count)
61 return true;
63 // make room for the new items
64 if (!fSelectedItems.InsertUninitialized(index + alreadySelectedCount,
65 count - alreadySelectedCount)) {
66 return false;
68 } else {
69 // TODO: Don't clear -- just resize to the right size!
70 Clear();
71 if (count <= 0)
72 return true;
74 index = 0;
75 if (!fSelectedItems.AddUninitialized(count))
76 return false;
79 for (int32 i = 0; i < count; i++)
80 fSelectedItems[index + i] = itemIndex + i;
82 _NotifyItemsSelected(itemIndex, count);
84 return true;
88 void
89 ListSelectionModel::DeselectItems(int32 itemIndex, int32 count)
91 int32 endItemIndex = itemIndex + count;
92 int32 index = _FindItem(itemIndex);
94 // count actually selected items
95 int32 actuallySelectedCount = _CountSelectedItemsInRange(index,
96 endItemIndex);
97 if (actuallySelectedCount == 0)
98 return;
100 fSelectedItems.Remove(index, actuallySelectedCount);
102 _NotifyItemsDeselected(itemIndex, count);
106 void
107 ListSelectionModel::ItemsAdded(int32 itemIndex, int32 count)
109 if (count <= 0)
110 return;
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;
120 void
121 ListSelectionModel::ItemsRemoved(int32 itemIndex, int32 count)
123 if (count <= 0)
124 return;
126 int32 index = _FindItem(itemIndex);
128 // count selected items in the range
129 int32 actuallySelectedCount = _CountSelectedItemsInRange(index,
130 itemIndex + count);
131 if (actuallySelectedCount > 0)
132 fSelectedItems.Remove(index, actuallySelectedCount);
134 // re-index following items
135 int32 selectedCount = fSelectedItems.Count();
136 for (int32 i = index; i < selectedCount; i++)
137 fSelectedItems[i] -= count;
141 bool
142 ListSelectionModel::AddListener(Listener* listener)
144 return fListeners.AddItem(listener);
148 void
149 ListSelectionModel::RemoveListener(Listener* listener)
151 fListeners.RemoveItem(listener);
155 ListSelectionModel&
156 ListSelectionModel::operator=(const ListSelectionModel& other)
158 Clear();
160 fSelectedItems = other.fSelectedItems;
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);
169 return *this;
173 int32
174 ListSelectionModel::_FindItem(int32 itemIndex) const
176 // binary search the index of the first item >= itemIndex
177 int32 lower = 0;
178 int32 upper = fSelectedItems.Count();
180 while (lower < upper) {
181 int32 mid = (lower + upper) / 2;
183 if (fSelectedItems[mid] < itemIndex)
184 lower = mid + 1;
185 else
186 upper = mid;
189 return lower;
193 int32
194 ListSelectionModel::_CountSelectedItemsInRange(int32 index,
195 int32 endItemIndex) const
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++;
205 return count;
209 void
210 ListSelectionModel::_NotifyItemsSelected(int32 index, int32 count)
212 int32 listenerCount = fListeners.CountItems();
213 for (int32 i = listenerCount - 1; i >= 0; i--)
214 fListeners.ItemAt(i)->ItemsSelected(this, index, count);
218 void
219 ListSelectionModel::_NotifyItemsDeselected(int32 index, int32 count)
221 int32 listenerCount = fListeners.CountItems();
222 for (int32 i = listenerCount - 1; i >= 0; i--)
223 fListeners.ItemAt(i)->ItemsDeselected(this, index, count);
227 // #pragma mark - Listener
230 ListSelectionModel::Listener::~Listener()
235 void
236 ListSelectionModel::Listener::ItemsSelected(ListSelectionModel* model,
237 int32 index, int32 count)
242 void
243 ListSelectionModel::Listener::ItemsDeselected(ListSelectionModel* model,
244 int32 index, int32 count)