diff --git a/src/apps/debuganalyzer/gui/table/AbstractTable.cpp b/src/apps/debuganalyzer/gui/table/AbstractTable.cpp index bd9d33e8cd..67eb0f7a08 100644 --- a/src/apps/debuganalyzer/gui/table/AbstractTable.cpp +++ b/src/apps/debuganalyzer/gui/table/AbstractTable.cpp @@ -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(); +} diff --git a/src/apps/debuganalyzer/gui/table/AbstractTable.h b/src/apps/debuganalyzer/gui/table/AbstractTable.h index 6326b1c069..54122d6fb7 100644 --- a/src/apps/debuganalyzer/gui/table/AbstractTable.h +++ b/src/apps/debuganalyzer/gui/table/AbstractTable.h @@ -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; diff --git a/src/apps/debuganalyzer/gui/table/Table.cpp b/src/apps/debuganalyzer/gui/table/Table.cpp index 72f2fd3d43..36f47c3f28 100644 --- a/src/apps/debuganalyzer/gui/table/Table.cpp +++ b/src/apps/debuganalyzer/gui/table/Table.cpp @@ -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(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(row->GetField(0)); + if (field == NULL) + return -1; + + return field->RowIndex(); } diff --git a/src/apps/debuganalyzer/gui/table/Table.h b/src/apps/debuganalyzer/gui/table/Table.h index caec074621..d7417b2929 100644 --- a/src/apps/debuganalyzer/gui/table/Table.h +++ b/src/apps/debuganalyzer/gui/table/Table.h @@ -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 ListenerList; typedef BObjectList RowList; private: virtual void ItemInvoked(); + int32 _ModelIndexOfRow(BRow* row); + private: TableModel* fModel; RowList fRows; + TableSelectionModel fSelectionModel; ListenerList fListeners; + int32 fIgnoreSelectionChange; };