Added class ListSelectionModel, representing a selection of list (i.e. indexed)

elements.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34567 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2009-12-08 21:46:49 +00:00
parent 1031a2b4ca
commit 446ac6d727
3 changed files with 328 additions and 0 deletions

View File

@ -13,6 +13,7 @@ MergeObject DebugAnalyzer_gui.o
AbstractGeneralPage.cpp
ColorCheckBox.cpp
HeaderView.cpp
ListSelectionModel.cpp
SubWindow.cpp
SubWindowManager.cpp
:

View File

@ -0,0 +1,224 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "ListSelectionModel.h"
// #pragma mark - ListSelectionModel
ListSelectionModel::ListSelectionModel()
:
fItemCount(0)
{
}
ListSelectionModel::~ListSelectionModel()
{
}
void
ListSelectionModel::Clear()
{
int32 selectedCount = fSelectedItems.Count();
if (selectedCount > 0) {
int32 firstSelected = fSelectedItems[0];
int32 lastSelected = fSelectedItems[selectedCount - 1];
fSelectedItems.Clear();
_NotifyItemsDeselected(firstSelected, lastSelected - firstSelected + 1);
}
}
bool
ListSelectionModel::SelectItems(int32 itemIndex, int32 count,
bool extendSelection)
{
int32 endItemIndex = itemIndex + count;
int32 index;
if (extendSelection) {
if (count <= 0)
return true;
index = _FindItem(itemIndex);
// count already selected items
int32 alreadySelectedCount = _CountSelectedItemsInRange(index,
endItemIndex);
if (alreadySelectedCount == count)
return true;
// make room for the new items
if (!fSelectedItems.InsertUninitialized(index + alreadySelectedCount,
count - alreadySelectedCount)) {
return false;
}
} else {
// TODO: Don't clear -- just resize to the right size!
Clear();
if (count <= 0)
return true;
index = 0;
if (!fSelectedItems.AddUninitialized(count))
return false;
}
for (int32 i = 0; i < count; i++)
fSelectedItems[index + i] = itemIndex + i;
_NotifyItemsSelected(itemIndex, count);
return true;
}
void
ListSelectionModel::DeselectItems(int32 itemIndex, int32 count)
{
int32 endItemIndex = itemIndex + count;
int32 index = _FindItem(itemIndex);
// count actually selected items
int32 actuallySelectedCount = _CountSelectedItemsInRange(index,
endItemIndex);
if (actuallySelectedCount == 0)
return;
fSelectedItems.Remove(index, actuallySelectedCount);
_NotifyItemsDeselected(itemIndex, count);
}
void
ListSelectionModel::ItemsAdded(int32 itemIndex, int32 count)
{
if (count <= 0)
return;
// re-index following items
int32 index = _FindItem(itemIndex);
int32 selectedCount = fSelectedItems.Count();
for (int32 i = index; i < selectedCount; i++)
fSelectedItems[i] += count;
}
void
ListSelectionModel::ItemsRemoved(int32 itemIndex, int32 count)
{
if (count <= 0)
return;
int32 index = _FindItem(itemIndex);
// count selected items in the range
int32 actuallySelectedCount = _CountSelectedItemsInRange(index,
itemIndex + count);
if (actuallySelectedCount > 0)
fSelectedItems.Remove(index, actuallySelectedCount);
// re-index following items
int32 selectedCount = fSelectedItems.Count();
for (int32 i = index; i < selectedCount; i++)
fSelectedItems[i] -= count;
}
bool
ListSelectionModel::AddListener(Listener* listener)
{
return fListeners.AddItem(listener);
}
void
ListSelectionModel::RemoveListener(Listener* listener)
{
fListeners.RemoveItem(listener);
}
int32
ListSelectionModel::_FindItem(int32 itemIndex) const
{
// binary search the index of the first item >= itemIndex
int32 lower = 0;
int32 upper = fSelectedItems.Count();
while (lower < upper) {
int32 mid = (lower + upper) / 2;
if (fSelectedItems[mid] < itemIndex)
lower = mid + 1;
else
upper = mid;
}
return lower;
}
int32
ListSelectionModel::_CountSelectedItemsInRange(int32 index,
int32 endItemIndex) const
{
int32 count = 0;
int32 selectedCount = fSelectedItems.Count();
for (int32 i = index; i < selectedCount; i++) {
if (SelectedItemAt(i) >= endItemIndex)
break;
count++;
}
return count;
}
void
ListSelectionModel::_NotifyItemsSelected(int32 index, int32 count)
{
int32 listenerCount = fListeners.CountItems();
for (int32 i = listenerCount - 1; i >= 0; i--)
fListeners.ItemAt(i)->ItemsSelected(this, index, count);
}
void
ListSelectionModel::_NotifyItemsDeselected(int32 index, int32 count)
{
int32 listenerCount = fListeners.CountItems();
for (int32 i = listenerCount - 1; i >= 0; i--)
fListeners.ItemAt(i)->ItemsDeselected(this, index, count);
}
// #pragma mark - Listener
ListSelectionModel::Listener::~Listener()
{
}
void
ListSelectionModel::Listener::ItemsSelected(ListSelectionModel* model,
int32 index, int32 count)
{
}
void
ListSelectionModel::Listener::ItemsDeselected(ListSelectionModel* model,
int32 index, int32 count)
{
}

View File

@ -0,0 +1,103 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef LIST_SELECTION_MODEL_H
#define LIST_SELECTION_MODEL_H
#include <SupportDefs.h>
#include <ObjectList.h>
#include "../debugger/util/Array.h"
class ListSelectionModel {
public:
class Listener;
public:
ListSelectionModel();
~ListSelectionModel();
int32 CountSelectedItems() const
{ return fSelectedItems.Count(); }
int32 SelectedItemAt(int32 index) const;
bool IsItemSelected(int32 itemIndex) const;
void Clear();
bool SelectItem(int32 itemIndex,
bool extendSelection);
bool SelectItems(int32 itemIndex, int32 count,
bool extendSelection);
void DeselectItem(int32 itemIndex);
void DeselectItems(int32 itemIndex, int32 count);
void ItemsAdded(int32 itemIndex, int32 count);
void ItemsRemoved(int32 itemIndex, int32 count);
bool AddListener(Listener* listener);
void RemoveListener(Listener* listener);
private:
typedef BObjectList<Listener> ListenerList;
private:
int32 _FindItem(int32 itemIndex) const;
int32 _CountSelectedItemsInRange(int32 index,
int32 endItemIndex) const;
void _NotifyItemsSelected(int32 index, int32 count);
void _NotifyItemsDeselected(int32 index,
int32 count);
private:
int32 fItemCount;
Array<int32> fSelectedItems;
ListenerList fListeners;
};
class ListSelectionModel::Listener {
public:
virtual ~Listener();
virtual void ItemsSelected(ListSelectionModel* model,
int32 index, int32 count);
virtual void ItemsDeselected(ListSelectionModel* model,
int32 index, int32 count);
};
inline bool
ListSelectionModel::IsItemSelected(int32 itemIndex) const
{
int32 index = _FindItem(itemIndex);
return index < fSelectedItems.Count() && fSelectedItems[index] == itemIndex;
}
inline int32
ListSelectionModel::SelectedItemAt(int32 index) const
{
return index >= 0 && index < fSelectedItems.Count()
? fSelectedItems[index] : -1;
}
inline bool
ListSelectionModel::SelectItem(int32 itemIndex, bool extendSelection)
{
return SelectItems(itemIndex, 1, extendSelection);
}
inline void
ListSelectionModel::DeselectItem(int32 itemIndex)
{
DeselectItems(itemIndex, 1);
}
#endif // LIST_SELECTION_MODEL_H