diff --git a/src/apps/debuganalyzer/gui/table/AbstractTable.cpp b/src/apps/debuganalyzer/gui/table/AbstractTable.cpp index c2e8463465..bd9d33e8cd 100644 --- a/src/apps/debuganalyzer/gui/table/AbstractTable.cpp +++ b/src/apps/debuganalyzer/gui/table/AbstractTable.cpp @@ -10,10 +10,10 @@ #include "table/TableColumn.h" -// #pragma mark - AbstractTableModel +// #pragma mark - AbstractTableModelBase -AbstractTableModel::~AbstractTableModel() +AbstractTableModelBase::~AbstractTableModelBase() { } diff --git a/src/apps/debuganalyzer/gui/table/AbstractTable.h b/src/apps/debuganalyzer/gui/table/AbstractTable.h index 3bfa917c95..6326b1c069 100644 --- a/src/apps/debuganalyzer/gui/table/AbstractTable.h +++ b/src/apps/debuganalyzer/gui/table/AbstractTable.h @@ -12,9 +12,9 @@ class TableColumn; -class AbstractTableModel { +class AbstractTableModelBase { public: - virtual ~AbstractTableModel(); + virtual ~AbstractTableModelBase(); virtual int32 CountColumns() const = 0; }; @@ -53,7 +53,7 @@ public: AbstractColumn(TableColumn* tableColumn); virtual ~AbstractColumn(); - virtual void SetModel(AbstractTableModel* model) = 0; + virtual void SetModel(AbstractTableModelBase* model) = 0; TableColumn* GetTableColumn() const { return fTableColumn; } diff --git a/src/apps/debuganalyzer/gui/table/Table.cpp b/src/apps/debuganalyzer/gui/table/Table.cpp index 044e4ca73a..72f2fd3d43 100644 --- a/src/apps/debuganalyzer/gui/table/Table.cpp +++ b/src/apps/debuganalyzer/gui/table/Table.cpp @@ -29,6 +29,28 @@ private: }; +// #pragma mark - TableModelListener + + +TableModelListener::~TableModelListener() +{ +} + + +void +TableModelListener::TableRowsAdded(TableModel* model, int32 rowIndex, + int32 count) +{ +} + + +void +TableModelListener::TableRowsRemoved(TableModel* model, int32 rowIndex, + int32 count) +{ +} + + // #pragma mark - TableModel @@ -37,6 +59,40 @@ TableModel::~TableModel() } +void +TableModel::AddListener(TableModelListener* listener) +{ + fListeners.Add(listener); +} + + +void +TableModel::RemoveListener(TableModelListener* listener) +{ + fListeners.Remove(listener); +} + + +void +TableModel::NotifyRowsAdded(int32 rowIndex, int32 count) +{ + for (ListenerList::Iterator it = fListeners.GetIterator(); + TableModelListener* listener = it.Next();) { + listener->TableRowsAdded(this, rowIndex, count); + } +} + + +void +TableModel::NotifyRowsRemoved(int32 rowIndex, int32 count) +{ + for (ListenerList::Iterator it = fListeners.GetIterator(); + TableModelListener* listener = it.Next();) { + listener->TableRowsRemoved(this, rowIndex, count); + } +} + + // #pragma mark - TableListener @@ -60,7 +116,7 @@ public: TableColumn* tableColumn); virtual ~Column(); - virtual void SetModel(AbstractTableModel* model); + virtual void SetModel(AbstractTableModelBase* model); protected: virtual void DrawTitle(BRect rect, BView* targetView); @@ -91,7 +147,7 @@ Table::Column::~Column() void -Table::Column::SetModel(AbstractTableModel* model) +Table::Column::SetModel(AbstractTableModelBase* model) { fModel = dynamic_cast(model); } @@ -196,6 +252,8 @@ Table::~Table() { for (int32 i = CountColumns() - 1; i >= 0; i--) RemoveColumn(ColumnAt(i)); + + // rows are deleted by the BColumnListView destructor automatically } @@ -206,6 +264,9 @@ Table::SetTableModel(TableModel* model) return; if (fModel != NULL) { + fModel->RemoveListener(this); + + fRows.MakeEmpty(); Clear(); for (int32 i = 0; AbstractColumn* column = fColumns.ItemAt(i); i++) @@ -217,38 +278,12 @@ Table::SetTableModel(TableModel* model) if (fModel == NULL) return; + fModel->AddListener(this); + for (int32 i = 0; AbstractColumn* column = fColumns.ItemAt(i); i++) column->SetModel(fModel); - // create the rows - int32 rowCount = fModel->CountRows(); - int32 columnCount = fModel->CountColumns(); - - for (int32 i = 0; i < rowCount; i++) { - // create row - BRow* row = new(std::nothrow) BRow(); - if (row == NULL) { - // TODO: Report error! - return; - } - - // add dummy fields to row - for (int32 columnIndex = 0; columnIndex < columnCount; columnIndex++) { - // It would be nice to create only a single field and set it for all - // columns, but the row takes ultimate ownership, so it have to be - // individual objects. - TableField* field = new(std::nothrow) TableField(i); - if (field == NULL) { - // TODO: Report error! - return; - } - - row->SetField(field, columnIndex); - } - - // add row - AddRow(row); - } + TableRowsAdded(fModel, 0, fModel->CountRows()); } @@ -273,6 +308,59 @@ Table::CreateColumn(TableColumn* column) } +void +Table::TableRowsAdded(TableModel* model, int32 rowIndex, int32 count) +{ + // create the rows + int32 endRow = rowIndex + count; + int32 columnCount = fModel->CountColumns(); + + for (int32 i = rowIndex; i < endRow; i++) { + // create row + BRow* row = new(std::nothrow) BRow(); + if (row == NULL) { + // TODO: Report error! + return; + } + + // add dummy fields to row + for (int32 columnIndex = 0; columnIndex < columnCount; columnIndex++) { + // It would be nice to create only a single field and set it for all + // columns, but the row takes ultimate ownership, so it have to be + // individual objects. + TableField* field = new(std::nothrow) TableField(i); + if (field == NULL) { + // TODO: Report error! + return; + } + + row->SetField(field, columnIndex); + } + + // add row + if (!fRows.AddItem(row, i)) { + // TODO: Report error! + delete row; + return; + } + + AddRow(row, i); + } +} + + +void +Table::TableRowsRemoved(TableModel* model, int32 rowIndex, int32 count) +{ + for (int32 i = rowIndex + count - 1; i >= rowIndex; i--) { + if (BRow* row = fRows.RemoveItemAt(i)) { + RemoveRow(row); + delete row; + } + } +} + + void Table::ItemInvoked() { diff --git a/src/apps/debuganalyzer/gui/table/Table.h b/src/apps/debuganalyzer/gui/table/Table.h index d51d7aeeff..caec074621 100644 --- a/src/apps/debuganalyzer/gui/table/Table.h +++ b/src/apps/debuganalyzer/gui/table/Table.h @@ -7,6 +7,9 @@ #include +#include +#include + #include "table/AbstractTable.h" #include "table/TableColumn.h" @@ -14,9 +17,21 @@ class Table; +class TableModel; -class TableModel : public AbstractTableModel { +class TableModelListener : public DoublyLinkedListLinkImpl { +public: + virtual ~TableModelListener(); + + virtual void TableRowsAdded(TableModel* model, + int32 rowIndex, int32 count); + virtual void TableRowsRemoved(TableModel* model, + int32 rowIndex, int32 count); +}; + + +class TableModel : public AbstractTableModelBase { public: virtual ~TableModel(); @@ -24,6 +39,19 @@ public: virtual bool GetValueAt(int32 rowIndex, int32 columnIndex, Variant& value) = 0; + + virtual void AddListener(TableModelListener* listener); + virtual void RemoveListener(TableModelListener* listener); + +protected: + typedef DoublyLinkedList ListenerList; + +protected: + void NotifyRowsAdded(int32 rowIndex, int32 count); + void NotifyRowsRemoved(int32 rowIndex, int32 count); + +protected: + ListenerList fListeners; }; @@ -35,7 +63,7 @@ public: }; -class Table : public AbstractTable { +class Table : public AbstractTable, private TableModelListener { public: Table(const char* name, uint32 flags, border_style borderStyle = B_NO_BORDER, @@ -55,16 +83,24 @@ public: protected: virtual AbstractColumn* CreateColumn(TableColumn* column); +private: + virtual void TableRowsAdded(TableModel* model, + int32 rowIndex, int32 count); + virtual void TableRowsRemoved(TableModel* model, + int32 rowIndex, int32 count); + private: class Column; typedef BObjectList ListenerList; + typedef BObjectList RowList; private: virtual void ItemInvoked(); private: TableModel* fModel; + RowList fRows; ListenerList fListeners; }; diff --git a/src/apps/debuganalyzer/gui/table/TreeTable.cpp b/src/apps/debuganalyzer/gui/table/TreeTable.cpp index 0955d68033..6e9cde0a2c 100644 --- a/src/apps/debuganalyzer/gui/table/TreeTable.cpp +++ b/src/apps/debuganalyzer/gui/table/TreeTable.cpp @@ -60,7 +60,7 @@ public: TableColumn* tableColumn); virtual ~Column(); - virtual void SetModel(AbstractTableModel* model); + virtual void SetModel(AbstractTableModelBase* model); protected: virtual void DrawTitle(BRect rect, BView* targetView); @@ -91,7 +91,7 @@ TreeTable::Column::~Column() void -TreeTable::Column::SetModel(AbstractTableModel* model) +TreeTable::Column::SetModel(AbstractTableModelBase* model) { fModel = dynamic_cast(model); } diff --git a/src/apps/debuganalyzer/gui/table/TreeTable.h b/src/apps/debuganalyzer/gui/table/TreeTable.h index 25f00db50d..4542a94427 100644 --- a/src/apps/debuganalyzer/gui/table/TreeTable.h +++ b/src/apps/debuganalyzer/gui/table/TreeTable.h @@ -16,7 +16,7 @@ class TreeTable; -class TreeTableModel : public AbstractTableModel { +class TreeTableModel : public AbstractTableModelBase { public: virtual ~TreeTableModel();