diff --git a/src/apps/debuganalyzer/Jamfile b/src/apps/debuganalyzer/Jamfile index 97ce2ba4ae..c118a01fa8 100644 --- a/src/apps/debuganalyzer/Jamfile +++ b/src/apps/debuganalyzer/Jamfile @@ -10,6 +10,7 @@ Application DebugAnalyzer MainWindow.cpp Model.cpp ModelLoader.cpp + Table.cpp ThreadsPage.cpp : libcolumnlistview.a libdebug.so be diff --git a/src/apps/debuganalyzer/Table.cpp b/src/apps/debuganalyzer/Table.cpp new file mode 100644 index 0000000000..bc2fa9f616 --- /dev/null +++ b/src/apps/debuganalyzer/Table.cpp @@ -0,0 +1,281 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "Table.h" + +#include + + +// #pragma mark - TableField + +class TableField : public BField { +public: + TableField(int32 rowIndex) + : + fRowIndex(rowIndex) + { + } + + int32 RowIndex() const + { + return fRowIndex; + } + +private: + int32 fRowIndex; +}; + + +// #pragma mark - TableModel + + +TableModel::~TableModel() +{ +} + + +// #pragma mark - TableColumn + + +TableColumn::TableColumn(BColumn* columnDelegate, int32 modelIndex, float width, + float minWidth, float maxWidth, alignment align) + : + BColumn(width, minWidth, maxWidth, align), + fModel(NULL), + fColumnDelegate(columnDelegate), + fModelIndex(modelIndex) +{ +} + + +TableColumn::~TableColumn() +{ +} + + +void +TableColumn::SetTableModel(TableModel* model) +{ + fModel = model; +} + + +void +TableColumn::DrawTitle(BRect rect, BView* targetView) +{ + fColumnDelegate->DrawTitle(rect, targetView); +} + + +void +TableColumn::GetColumnName(BString* into) const +{ + fColumnDelegate->GetColumnName(into); +} + + +void +TableColumn::DrawValue(void* value, BRect rect, BView* targetView) +{ +} + + +int +TableColumn::CompareValues(void* a, void* b) +{ + return 0; +} + + +float +TableColumn::GetPreferredValueWidth(void* value, BView* parent) const +{ + return Width(); +} + + +void +TableColumn::DrawField(BField* _field, BRect rect, BView* targetView) +{ + TableField* field = dynamic_cast(_field); + if (field == NULL) + return; + + void* value = fModel->ValueAt(field->RowIndex(), fModelIndex); + DrawValue(value, rect, targetView); +} + + +int +TableColumn::CompareFields(BField* _field1, BField* _field2) +{ + TableField* field1 = dynamic_cast(_field1); + TableField* field2 = dynamic_cast(_field2); + + if (field1 == field2) + return 0; + + if (field1 == NULL) + return -1; + if (field2 == NULL) + return 1; + + return CompareValues(fModel->ValueAt(field1->RowIndex(), fModelIndex), + fModel->ValueAt(field2->RowIndex(), fModelIndex)); +} + + +float +TableColumn::GetPreferredWidth(BField* _field, BView* parent) const +{ + TableField* field = dynamic_cast(_field); + if (field == NULL) + return Width(); + + void* value = fModel->ValueAt(field->RowIndex(), fModelIndex); + return GetPreferredValueWidth(value, parent); +} + + +// #pragma mark - StringTableColumn + + +StringTableColumn::StringTableColumn(int32 modelIndex, const char* title, + float width, float minWidth, float maxWidth, uint32 truncate, + alignment align) + : + TableColumn(&fColumn, modelIndex, width, minWidth, maxWidth, align), + fColumn(title, width, minWidth, maxWidth, truncate, align), + fField("") +{ +} + + +StringTableColumn::~StringTableColumn() +{ +} + + +void +StringTableColumn::DrawValue(void* value, BRect rect, BView* targetView) +{ + fField.SetString((const char*)value); + fField.SetWidth(Width()); + fColumn.DrawField(&fField, rect, targetView); +} + + +int +StringTableColumn::CompareValues(void* a, void* b) +{ + return strcmp((const char*)a, (const char*)b); +} + + +float +StringTableColumn::GetPreferredValueWidth(void* value, BView* parent) const +{ + fField.SetString((const char*)value); + fField.SetWidth(Width()); + return fColumn.GetPreferredWidth(&fField, parent); +} + + +// #pragma mark - Table + + +Table::Table(const char* name, uint32 flags, border_style borderStyle, + bool showHorizontalScrollbar) + : + BColumnListView(name, flags, borderStyle, showHorizontalScrollbar), + fModel(NULL) +{ +} + + +Table::Table(TableModel* model, const char* name, uint32 flags, + border_style borderStyle, bool showHorizontalScrollbar) + : + BColumnListView(name, flags, borderStyle, showHorizontalScrollbar), + fModel(NULL), + fColumns(20, true) +{ + SetTableModel(model); +} + + +Table::~Table() +{ + for (int32 i = CountColumns() - 1; i >= 0; i--) + RemoveColumn(ColumnAt(i)); +} + + +void +Table::SetTableModel(TableModel* model) +{ + if (model == fModel) + return; + + if (fModel != NULL) { + Clear(); + + for (int32 i = 0; TableColumn* column = fColumns.ItemAt(i); i++) + column->SetTableModel(NULL); + } + + fModel = model; + + if (fModel == NULL) + return; + + for (int32 i = 0; TableColumn* column = fColumns.ItemAt(i); i++) + column->SetTableModel(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); + } +} + + +void +Table::AddColumn(TableColumn* column) +{ + if (column == NULL) + return; + + if (!fColumns.AddItem(column)) + throw std::bad_alloc(); + + column->SetTableModel(fModel); + + BColumnListView::AddColumn(column, column->ModelIndex()); +} diff --git a/src/apps/debuganalyzer/Table.h b/src/apps/debuganalyzer/Table.h new file mode 100644 index 0000000000..bf7ecd7de4 --- /dev/null +++ b/src/apps/debuganalyzer/Table.h @@ -0,0 +1,123 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef TABLE_H +#define TABLE_H + +#include +#include +#include + + +class Table; + + +class TableModel { +public: + virtual ~TableModel(); + + virtual int32 CountColumns() const = 0; + virtual int32 CountRows() const = 0; + + virtual void GetColumnName(int columnIndex, + BString& name) const = 0; + + virtual void* ValueAt(int32 rowIndex, int32 columnIndex) = 0; +}; + + +class TableColumn : private BColumn { +public: + TableColumn(BColumn* columnDelegate, + int32 modelIndex, float width, + float minWidth, float maxWidth, + alignment align); + virtual ~TableColumn(); + + int32 ModelIndex() const { return fModelIndex; } + + float Width() const { return BColumn::Width(); } + +protected: + virtual void DrawTitle(BRect rect, BView* targetView); + virtual void GetColumnName(BString* into) const; + + virtual void DrawValue(void* value, BRect rect, + BView* targetView); + virtual int CompareValues(void* a, void* b); + virtual float GetPreferredValueWidth(void* value, + BView* parent) const; + +private: + virtual void DrawField(BField* field, BRect rect, + BView* targetView); + virtual int CompareFields(BField* field1, BField* field2); + + virtual float GetPreferredWidth(BField* field, + BView* parent) const; + + void SetTableModel(TableModel* model); + // package private + +private: + friend class Table; + +private: + TableModel* fModel; + BColumn* fColumnDelegate; + int32 fModelIndex; +}; + + +class StringTableColumn : public TableColumn { +public: + StringTableColumn(int32 modelIndex, + const char* title, float width, + float minWidth, float maxWidth, + uint32 truncate, + alignment align = B_ALIGN_LEFT); + virtual ~StringTableColumn(); + +protected: + virtual void DrawValue(void* value, BRect rect, + BView* targetView); + virtual int CompareValues(void* a, void* b); + virtual float GetPreferredValueWidth(void* value, + BView* parent) const; + +private: + BStringColumn fColumn; + mutable BStringField fField; +}; + + +class Table : private BColumnListView { +public: + Table(const char* name, uint32 flags, + border_style borderStyle = B_NO_BORDER, + bool showHorizontalScrollbar = true); + Table(TableModel* model, const char* name, + uint32 flags, + border_style borderStyle = B_NO_BORDER, + bool showHorizontalScrollbar = true); + virtual ~Table(); + + BView* ToView() { return this; } + + void SetTableModel(TableModel* model); + TableModel* GetTableModel() const { return fModel; } + + void AddColumn(TableColumn* column); + +private: + typedef BObjectList ColumnList; + +private: + TableModel* fModel; + ColumnList fColumns; +}; + + + +#endif // TABLE_H