Added selection support to Table.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31096 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -82,3 +82,24 @@ AbstractTable::ResizeAllColumnsToPreferred()
|
||||
{
|
||||
BColumnListView::ResizeAllColumnsToPreferred();
|
||||
}
|
||||
|
||||
|
||||
list_view_type
|
||||
AbstractTable::SelectionMode() const
|
||||
{
|
||||
return BColumnListView::SelectionMode();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AbstractTable::SetSelectionMode(list_view_type type)
|
||||
{
|
||||
BColumnListView::SetSelectionMode(type);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AbstractTable::DeselectAll()
|
||||
{
|
||||
BColumnListView::DeselectAll();
|
||||
}
|
||||
|
||||
@@ -33,6 +33,10 @@ public:
|
||||
void ResizeColumnToPreferred(int32 index);
|
||||
void ResizeAllColumnsToPreferred();
|
||||
|
||||
list_view_type SelectionMode() const;
|
||||
void SetSelectionMode(list_view_type type);
|
||||
void DeselectAll();
|
||||
|
||||
protected:
|
||||
class AbstractColumn;
|
||||
|
||||
|
||||
@@ -93,6 +93,83 @@ TableModel::NotifyRowsRemoved(int32 rowIndex, int32 count)
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - TableSelectionModel
|
||||
|
||||
TableSelectionModel::TableSelectionModel(Table* table)
|
||||
:
|
||||
fTable(table),
|
||||
fRows(NULL),
|
||||
fRowCount(-1)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
TableSelectionModel::~TableSelectionModel()
|
||||
{
|
||||
delete[] fRows;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
TableSelectionModel::CountRows()
|
||||
{
|
||||
_Update();
|
||||
|
||||
return fRowCount;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
TableSelectionModel::RowAt(int32 index)
|
||||
{
|
||||
_Update();
|
||||
|
||||
return index >= 0 && index < fRowCount ? fRows[index] : -1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TableSelectionModel::_SelectionChanged()
|
||||
{
|
||||
if (fRowCount >= 0) {
|
||||
fRowCount = -1;
|
||||
delete[] fRows;
|
||||
fRows = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TableSelectionModel::_Update()
|
||||
{
|
||||
if (fRowCount >= 0)
|
||||
return;
|
||||
|
||||
// count the rows
|
||||
fRowCount = 0;
|
||||
BRow* row = NULL;
|
||||
while ((row = fTable->CurrentSelection(row)) != NULL)
|
||||
fRowCount++;
|
||||
|
||||
if (fRowCount == 0)
|
||||
return;
|
||||
|
||||
// allocate row array
|
||||
fRows = new(std::nothrow) int32[fRowCount];
|
||||
if (fRows == NULL) {
|
||||
fRowCount = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// get the rows
|
||||
row = NULL;
|
||||
int32 index = 0;
|
||||
while ((row = fTable->CurrentSelection(row)) != NULL)
|
||||
fRows[index++] = fTable->_ModelIndexOfRow(row);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// #pragma mark - TableListener
|
||||
|
||||
|
||||
@@ -101,6 +178,12 @@ TableListener::~TableListener()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TableListener::TableSelectionChanged(Table* table)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TableListener::TableRowInvoked(Table* table, int32 rowIndex)
|
||||
{
|
||||
@@ -233,7 +316,9 @@ Table::Table(const char* name, uint32 flags, border_style borderStyle,
|
||||
bool showHorizontalScrollbar)
|
||||
:
|
||||
AbstractTable(name, flags, borderStyle, showHorizontalScrollbar),
|
||||
fModel(NULL)
|
||||
fModel(NULL),
|
||||
fSelectionModel(this),
|
||||
fIgnoreSelectionChange(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -242,7 +327,9 @@ Table::Table(TableModel* model, const char* name, uint32 flags,
|
||||
border_style borderStyle, bool showHorizontalScrollbar)
|
||||
:
|
||||
AbstractTable(name, flags, borderStyle, showHorizontalScrollbar),
|
||||
fModel(NULL)
|
||||
fModel(NULL),
|
||||
fSelectionModel(this),
|
||||
fIgnoreSelectionChange(0)
|
||||
{
|
||||
SetTableModel(model);
|
||||
}
|
||||
@@ -287,6 +374,38 @@ Table::SetTableModel(TableModel* model)
|
||||
}
|
||||
|
||||
|
||||
TableSelectionModel*
|
||||
Table::SelectionModel()
|
||||
{
|
||||
return &fSelectionModel;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Table::SelectRow(int32 rowIndex, bool extendSelection)
|
||||
{
|
||||
BRow* row = fRows.ItemAt(rowIndex);
|
||||
if (row == NULL)
|
||||
return;
|
||||
|
||||
if (!extendSelection) {
|
||||
fIgnoreSelectionChange++;
|
||||
DeselectAll();
|
||||
fIgnoreSelectionChange--;
|
||||
}
|
||||
|
||||
AddToSelection(row);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Table::DeselectRow(int32 rowIndex)
|
||||
{
|
||||
if (BRow* row = fRows.ItemAt(rowIndex))
|
||||
Deselect(row);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Table::AddTableListener(TableListener* listener)
|
||||
{
|
||||
@@ -301,6 +420,22 @@ Table::RemoveTableListener(TableListener* listener)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Table::SelectionChanged()
|
||||
{
|
||||
if (fIgnoreSelectionChange > 0)
|
||||
return;
|
||||
|
||||
fSelectionModel._SelectionChanged();
|
||||
|
||||
if (!fListeners.IsEmpty()) {
|
||||
int32 listenerCount = fListeners.CountItems();
|
||||
for (int32 i = listenerCount - 1; i >= 0; i--)
|
||||
fListeners.ItemAt(i)->TableSelectionChanged(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AbstractTable::AbstractColumn*
|
||||
Table::CreateColumn(TableColumn* column)
|
||||
{
|
||||
@@ -367,15 +502,25 @@ Table::ItemInvoked()
|
||||
if (fListeners.IsEmpty())
|
||||
return;
|
||||
|
||||
BRow* row = CurrentSelection();
|
||||
if (row == NULL)
|
||||
return;
|
||||
|
||||
TableField* field = dynamic_cast<TableField*>(row->GetField(0));
|
||||
if (field == NULL)
|
||||
int32 index = _ModelIndexOfRow(CurrentSelection());
|
||||
if (index < 0)
|
||||
return;
|
||||
|
||||
int32 listenerCount = fListeners.CountItems();
|
||||
for (int32 i = listenerCount - 1; i >= 0; i--)
|
||||
fListeners.ItemAt(i)->TableRowInvoked(this, field->RowIndex());
|
||||
fListeners.ItemAt(i)->TableRowInvoked(this, index);
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
Table::_ModelIndexOfRow(BRow* row)
|
||||
{
|
||||
if (row == NULL)
|
||||
return -1;
|
||||
|
||||
TableField* field = dynamic_cast<TableField*>(row->GetField(0));
|
||||
if (field == NULL)
|
||||
return -1;
|
||||
|
||||
return field->RowIndex();
|
||||
}
|
||||
|
||||
@@ -55,10 +55,33 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
class TableSelectionModel {
|
||||
public:
|
||||
TableSelectionModel(Table* table);
|
||||
~TableSelectionModel();
|
||||
|
||||
int32 CountRows();
|
||||
int32 RowAt(int32 index);
|
||||
|
||||
private:
|
||||
friend class Table;
|
||||
|
||||
private:
|
||||
void _SelectionChanged();
|
||||
void _Update();
|
||||
|
||||
private:
|
||||
Table* fTable;
|
||||
int32* fRows;
|
||||
int32 fRowCount;
|
||||
};
|
||||
|
||||
|
||||
class TableListener {
|
||||
public:
|
||||
virtual ~TableListener();
|
||||
|
||||
virtual void TableSelectionChanged(Table* table);
|
||||
virtual void TableRowInvoked(Table* table, int32 rowIndex);
|
||||
};
|
||||
|
||||
@@ -77,10 +100,17 @@ public:
|
||||
void SetTableModel(TableModel* model);
|
||||
TableModel* GetTableModel() const { return fModel; }
|
||||
|
||||
TableSelectionModel* SelectionModel();
|
||||
|
||||
void SelectRow(int32 rowIndex, bool extendSelection);
|
||||
void DeselectRow(int32 rowIndex);
|
||||
|
||||
bool AddTableListener(TableListener* listener);
|
||||
void RemoveTableListener(TableListener* listener);
|
||||
|
||||
protected:
|
||||
virtual void SelectionChanged();
|
||||
|
||||
virtual AbstractColumn* CreateColumn(TableColumn* column);
|
||||
|
||||
private:
|
||||
@@ -92,16 +122,22 @@ private:
|
||||
private:
|
||||
class Column;
|
||||
|
||||
friend class TableSelectionModel;
|
||||
|
||||
typedef BObjectList<TableListener> ListenerList;
|
||||
typedef BObjectList<BRow> RowList;
|
||||
|
||||
private:
|
||||
virtual void ItemInvoked();
|
||||
|
||||
int32 _ModelIndexOfRow(BRow* row);
|
||||
|
||||
private:
|
||||
TableModel* fModel;
|
||||
RowList fRows;
|
||||
TableSelectionModel fSelectionModel;
|
||||
ListenerList fListeners;
|
||||
int32 fIgnoreSelectionChange;
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user