[Haiku-commits] r31269 - haiku/trunk/src/apps/debuganalyzer/gui/table
bonefish at BerliOS
bonefish at mail.berlios.de
Sat Jun 27 18:41:47 CEST 2009
Author: bonefish
Date: 2009-06-27 18:41:46 +0200 (Sat, 27 Jun 2009)
New Revision: 31269
ViewCVS: http://svn.berlios.de/viewcvs/haiku?rev=31269&view=rev
Modified:
haiku/trunk/src/apps/debuganalyzer/gui/table/TreeTable.cpp
haiku/trunk/src/apps/debuganalyzer/gui/table/TreeTable.h
Log:
Added support for tree table model listeners (mutation events), selection, and
collapsing/expanding nodes.
Modified: haiku/trunk/src/apps/debuganalyzer/gui/table/TreeTable.cpp
===================================================================
--- haiku/trunk/src/apps/debuganalyzer/gui/table/TreeTable.cpp 2009-06-27 16:39:42 UTC (rev 31268)
+++ haiku/trunk/src/apps/debuganalyzer/gui/table/TreeTable.cpp 2009-06-27 16:41:46 UTC (rev 31269)
@@ -29,6 +29,120 @@
};
+// #pragma mark - TreeTablePath
+
+
+TreeTablePath::TreeTablePath()
+{
+}
+
+
+TreeTablePath::TreeTablePath(const TreeTablePath& other)
+{
+ *this = other;
+}
+
+
+TreeTablePath::TreeTablePath(const TreeTablePath& other, int32 childIndex)
+{
+ *this = other;
+ AddComponent(childIndex);
+}
+
+
+TreeTablePath::~TreeTablePath()
+{
+}
+
+
+bool
+TreeTablePath::AddComponent(int32 childIndex)
+{
+ try {
+ fComponents.push_back(childIndex);
+ return true;
+ } catch (...) {
+ return false;
+ }
+}
+
+void
+TreeTablePath::Clear()
+{
+ fComponents.clear();
+}
+
+
+int32
+TreeTablePath::CountComponents() const
+{
+ return fComponents.size();
+}
+
+
+int32
+TreeTablePath::ComponentAt(int32 index) const
+{
+ if (index < 0 || (size_t)index >= fComponents.size())
+ return -1;
+ return fComponents[index];
+}
+
+
+TreeTablePath&
+TreeTablePath::operator=(const TreeTablePath& other)
+{
+ try {
+ fComponents = other.fComponents;
+ } catch (...) {
+ }
+ return *this;
+}
+
+
+bool
+TreeTablePath::operator==(const TreeTablePath& other) const
+{
+ return fComponents == other.fComponents;
+}
+
+
+bool
+TreeTablePath::operator!=(const TreeTablePath& other) const
+{
+ return fComponents != other.fComponents;
+}
+
+
+// #pragma mark - TreeTableModelListener
+
+
+TreeTableModelListener::~TreeTableModelListener()
+{
+}
+
+
+void
+TreeTableModelListener::TableNodesAdded(TreeTableModel* model,
+ const TreeTablePath& path, int32 childIndex, int32 count)
+{
+}
+
+
+void
+TreeTableModelListener::TableNodesRemoved(TreeTableModel* model,
+ const TreeTablePath& path, int32 childIndex, int32 count)
+{
+}
+
+
+void
+TreeTableModelListener::TableNodesChanged(TreeTableModel* model,
+ const TreeTablePath& path, int32 childIndex, int32 count)
+{
+}
+
+
// #pragma mark - TreeTableModel
@@ -37,6 +151,69 @@
}
+void*
+TreeTableModel::NodeForPath(const TreeTablePath& path) const
+{
+ void* node = Root();
+
+ int32 count = path.CountComponents();
+ for (int32 i = 0; node != NULL && i < count; i++)
+ node = ChildAt(node, path.ComponentAt(i));
+
+ return node;
+}
+
+
+bool
+TreeTableModel::AddListener(TreeTableModelListener* listener)
+{
+ return fListeners.AddItem(listener);
+}
+
+
+void
+TreeTableModel::RemoveListener(TreeTableModelListener* listener)
+{
+ fListeners.RemoveItem(listener);
+}
+
+
+void
+TreeTableModel::NotifyNodesAdded(const TreeTablePath& path, int32 childIndex,
+ int32 count)
+{
+ int32 listenerCount = fListeners.CountItems();
+ for (int32 i = listenerCount - 1; i >= 0; i--) {
+ TreeTableModelListener* listener = fListeners.ItemAt(i);
+ listener->TableNodesAdded(this, path, childIndex, count);
+ }
+}
+
+
+void
+TreeTableModel::NotifyNodesRemoved(const TreeTablePath& path, int32 childIndex,
+ int32 count)
+{
+ int32 listenerCount = fListeners.CountItems();
+ for (int32 i = listenerCount - 1; i >= 0; i--) {
+ TreeTableModelListener* listener = fListeners.ItemAt(i);
+ listener->TableNodesRemoved(this, path, childIndex, count);
+ }
+}
+
+
+void
+TreeTableModel::NotifyNodesChanged(const TreeTablePath& path, int32 childIndex,
+ int32 count)
+{
+ int32 listenerCount = fListeners.CountItems();
+ for (int32 i = listenerCount - 1; i >= 0; i--) {
+ TreeTableModelListener* listener = fListeners.ItemAt(i);
+ listener->TableNodesChanged(this, path, childIndex, count);
+ }
+}
+
+
// #pragma mark - TreeTableListener
@@ -46,11 +223,18 @@
void
-TreeTableListener::TreeTableNodeInvoked(TreeTable* table, void* node)
+TreeTableListener::TreeTableSelectionChanged(TreeTable* table)
{
}
+void
+TreeTableListener::TreeTableNodeInvoked(TreeTable* table,
+ const TreeTablePath& path)
+{
+}
+
+
// #pragma mark - Column
@@ -170,6 +354,259 @@
}
+// #pragma mark - TreeTableRow
+
+
+class TreeTableRow : public BRow {
+public:
+ TreeTableRow(TreeTableNode* node)
+ :
+ fNode(node)
+ {
+ }
+
+ TreeTableNode* Node()
+ {
+ return fNode;
+ }
+
+private:
+ TreeTableNode* fNode;
+};
+
+
+// #pragma mark - TreeTableNode
+
+
+class TreeTableNode {
+public:
+ TreeTableNode(TreeTableNode* parent);
+ ~TreeTableNode();
+
+ status_t Init(void* modelObject, int32 columnCount);
+ void DetachRow();
+
+ TreeTableNode* Parent() const { return fParent; }
+ TreeTableRow* Row() const { return fRow; }
+ void* ModelObject() const;
+
+ bool AddChild(TreeTableNode* child, int32 index);
+ TreeTableNode* RemoveChild(int32 index);
+
+ int32 CountChildren() const;
+ TreeTableNode* ChildAt(int32 index);
+ int32 IndexOf(TreeTableNode* child);
+
+private:
+ typedef BObjectList<TreeTableNode> NodeList;
+
+private:
+ TreeTableNode* fParent;
+ TreeTableRow* fRow;
+ NodeList* fChildren;
+};
+
+
+TreeTableNode::TreeTableNode(TreeTableNode* parent)
+ :
+ fParent(parent),
+ fRow(NULL),
+ fChildren(NULL)
+{
+}
+
+
+TreeTableNode::~TreeTableNode()
+{
+ delete fChildren;
+ delete fRow;
+}
+
+
+status_t
+TreeTableNode::Init(void* modelObject, int32 columnCount)
+{
+ // create row
+ fRow = new(std::nothrow) TreeTableRow(this);
+ if (fRow == NULL)
+ return B_NO_MEMORY;
+
+ // 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.
+ TreeTableField* field = new(std::nothrow) TreeTableField(modelObject);
+ if (field == NULL)
+ return B_NO_MEMORY;
+
+ fRow->SetField(field, columnIndex);
+ }
+
+ return B_OK;
+}
+
+
+void
+TreeTableNode::DetachRow()
+{
+
+ fRow = NULL;
+
+ if (fChildren != NULL) {
+ for (int32 i = 0; TreeTableNode* child = fChildren->ItemAt(i); i++)
+ child->DetachRow();
+ }
+}
+
+
+void*
+TreeTableNode::ModelObject() const
+{
+ TreeTableField* field = dynamic_cast<TreeTableField*>(fRow->GetField(0));
+ return field->Object();
+}
+
+
+bool
+TreeTableNode::AddChild(TreeTableNode* child, int32 index)
+{
+ if (fChildren == NULL) {
+ fChildren = new(std::nothrow) NodeList(10, true);
+ if (fChildren == NULL)
+ return false;
+ }
+
+ return fChildren->AddItem(child, index);
+}
+
+
+TreeTableNode*
+TreeTableNode::RemoveChild(int32 index)
+{
+ return fChildren != NULL ? fChildren->RemoveItemAt(index) : NULL;
+}
+
+
+int32
+TreeTableNode::CountChildren() const
+{
+ return fChildren != NULL ? fChildren->CountItems() : 0;
+}
+
+
+TreeTableNode*
+TreeTableNode::ChildAt(int32 index)
+{
+ return fChildren != NULL ? fChildren->ItemAt(index) : NULL;
+}
+
+
+int32
+TreeTableNode::IndexOf(TreeTableNode* child)
+{
+ return fChildren != NULL ? fChildren->IndexOf(child) : -1;
+}
+
+
+// #pragma mark - TreeTableSelectionModel
+
+
+TreeTableSelectionModel::TreeTableSelectionModel(TreeTable* table)
+ :
+ fTreeTable(table),
+ fNodes(NULL),
+ fNodeCount(-1)
+{
+}
+
+
+TreeTableSelectionModel::~TreeTableSelectionModel()
+{
+ delete[] fNodes;
+}
+
+
+int32
+TreeTableSelectionModel::CountNodes()
+{
+ _Update();
+
+ return fNodeCount;
+}
+
+
+void*
+TreeTableSelectionModel::NodeAt(int32 index)
+{
+ if (TreeTableNode* node = _NodeAt(index))
+ return node->ModelObject();
+ return NULL;
+}
+
+
+bool
+TreeTableSelectionModel::GetPathAt(int32 index, TreeTablePath& _path)
+{
+ if (TreeTableNode* node = _NodeAt(index)) {
+ fTreeTable->_GetPathForNode(node, _path);
+ return true;
+ }
+
+ return false;
+}
+
+
+void
+TreeTableSelectionModel::_SelectionChanged()
+{
+ if (fNodeCount >= 0) {
+ fNodeCount = -1;
+ delete[] fNodes;
+ fNodes = NULL;
+ }
+}
+
+
+void
+TreeTableSelectionModel::_Update()
+{
+ if (fNodeCount >= 0)
+ return;
+
+ // count the nodes
+ fNodeCount = 0;
+ BRow* row = NULL;
+ while ((row = fTreeTable->CurrentSelection(row)) != NULL)
+ fNodeCount++;
+
+ if (fNodeCount == 0)
+ return;
+
+ // allocate node array
+ fNodes = new(std::nothrow) TreeTableNode*[fNodeCount];
+ if (fNodes == NULL) {
+ fNodeCount = 0;
+ return;
+ }
+
+ // get the nodes
+ row = NULL;
+ int32 index = 0;
+ while ((row = fTreeTable->CurrentSelection(row)) != NULL)
+ fNodes[index++] = dynamic_cast<TreeTableRow*>(row)->Node();
+}
+
+
+TreeTableNode*
+TreeTableSelectionModel::_NodeAt(int32 index)
+{
+ _Update();
+
+ return index >= 0 && index < fNodeCount ? fNodes[index] : NULL;
+}
+
+
// #pragma mark - Table
@@ -177,7 +614,10 @@
bool showHorizontalScrollbar)
:
AbstractTable(name, flags, borderStyle, showHorizontalScrollbar),
- fModel(NULL)
+ fModel(NULL),
+ fRootNode(NULL),
+ fSelectionModel(this),
+ fIgnoreSelectionChange(0)
{
}
@@ -186,7 +626,10 @@
border_style borderStyle, bool showHorizontalScrollbar)
:
AbstractTable(name, flags, borderStyle, showHorizontalScrollbar),
- fModel(NULL)
+ fModel(NULL),
+ fRootNode(NULL),
+ fSelectionModel(this),
+ fIgnoreSelectionChange(0)
{
SetTreeTableModel(model);
}
@@ -194,18 +637,28 @@
TreeTable::~TreeTable()
{
+ SetTreeTableModel(NULL);
+
for (int32 i = CountColumns() - 1; i >= 0; i--)
RemoveColumn(ColumnAt(i));
}
-void
+bool
TreeTable::SetTreeTableModel(TreeTableModel* model)
{
if (model == fModel)
- return;
+ return true;
if (fModel != NULL) {
+ fModel->RemoveListener(this);
+
+ if (fRootNode != NULL) {
+ fRootNode->DetachRow();
+ delete fRootNode;
+ fRootNode = NULL;
+ }
+
Clear();
for (int32 i = 0; AbstractColumn* column = fColumns.ItemAt(i); i++)
@@ -215,54 +668,100 @@
fModel = model;
if (fModel == NULL)
- return;
+ return true;
+ fRootNode = new(std::nothrow) TreeTableNode(NULL);
+ if (fRootNode == NULL)
+ return false;
+
+ if (fRootNode->Init(fModel->Root(), fModel->CountColumns()) != B_OK) {
+ delete fRootNode;
+ fRootNode = NULL;
+ return false;
+ }
+
+ fModel->AddListener(this);
+
for (int32 i = 0; AbstractColumn* column = fColumns.ItemAt(i); i++)
column->SetModel(fModel);
// recursively create the rows
- _AddChildRows(fModel->Root(), NULL, fModel->CountColumns());
+ if (!_AddChildRows(fRootNode, 0, fModel->CountChildren(fModel->Root()),
+ fModel->CountColumns())) {
+ SetTreeTableModel(NULL);
+ return false;
+ }
+
+ return true;
}
+TreeTableSelectionModel*
+TreeTable::SelectionModel()
+{
+ return &fSelectionModel;
+}
+
+
void
-TreeTable::_AddChildRows(void* parent, BRow* parentRow, int32 columnCount)
+TreeTable::SelectNode(const TreeTablePath& path, bool extendSelection)
{
- int32 childCount = fModel->CountChildren(parent);
- for (int32 i = 0; i < childCount; i++) {
- void* child = fModel->ChildAt(parent, i);
+ TreeTableNode* node = _NodeForPath(path);
+ if (node == NULL)
+ return;
- // create row
- BRow* row = new(std::nothrow) BRow();
- if (row == NULL) {
- // TODO: Report error!
- return;
- }
+ if (!extendSelection) {
+ fIgnoreSelectionChange++;
+ DeselectAll();
+ fIgnoreSelectionChange--;
+ }
- // 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.
- TreeTableField* field = new(std::nothrow) TreeTableField(child);
- if (field == NULL) {
- // TODO: Report error!
- return;
- }
+ AddToSelection(node->Row());
+}
- row->SetField(field, columnIndex);
- }
- // add row
- AddRow(row, parentRow);
+void
+TreeTable::DeselectNode(const TreeTablePath& path)
+{
+ if (TreeTableNode* node = _NodeForPath(path))
+ Deselect(node->Row());
+}
- // recursively create children
- _AddChildRows(child, row, columnCount);
- }
+
+void
+TreeTable::DeselectAllNodes()
+{
+ DeselectAll();
}
bool
+TreeTable::IsNodeExpanded(const TreeTablePath& path) const
+{
+ if (TreeTableNode* node = _NodeForPath(path))
+ node->Row()->IsExpanded();
+ return false;
+}
+
+
+void
+TreeTable::SetNodeExpanded(const TreeTablePath& path, bool expanded,
+ bool expandAncestors)
+{
+ if (TreeTableNode* node = _NodeForPath(path))
+ _SetNodeExpanded(node, expanded, expandAncestors);
+}
+
+
+void
+TreeTable::ScrollToNode(const TreeTablePath& path)
+{
+ if (TreeTableNode* node = _NodeForPath(path))
+ BColumnListView::ScrollTo(node->Row());
+}
+
+
+bool
TreeTable::AddTreeTableListener(TreeTableListener* listener)
{
return fListeners.AddItem(listener);
@@ -276,6 +775,22 @@
}
+void
+TreeTable::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)->TreeTableSelectionChanged(this);
+ }
+}
+
+
AbstractTable::AbstractColumn*
TreeTable::CreateColumn(TableColumn* column)
{
@@ -284,20 +799,142 @@
void
+TreeTable::TableNodesAdded(TreeTableModel* model, const TreeTablePath& path,
+ int32 childIndex, int32 count)
+{
+ TreeTableNode* node = _NodeForPath(path);
+ if (node == NULL)
+ return;
+
+ _AddChildRows(node, childIndex, count, fModel->CountColumns());
+}
+
+
+void
+TreeTable::TableNodesRemoved(TreeTableModel* model, const TreeTablePath& path,
+ int32 childIndex, int32 count)
+{
+ TreeTableNode* node = _NodeForPath(path);
+ if (node == NULL)
+ return;
+
+ _RemoveChildRows(node, childIndex, count);
+}
+
+
+void
+TreeTable::TableNodesChanged(TreeTableModel* model, const TreeTablePath& path,
+ int32 childIndex, int32 count)
+{
+ TreeTableNode* node = _NodeForPath(path);
+ if (node == NULL)
+ return;
+
+ int32 endIndex = childIndex + count;
+ for (int32 i = childIndex; i < endIndex; i++) {
+ if (TreeTableNode* child = node->ChildAt(i))
+ UpdateRow(child->Row());
+ }
+}
+
+
+void
TreeTable::ItemInvoked()
{
if (fListeners.IsEmpty())
return;
- BRow* row = CurrentSelection();
+ TreeTableRow* row = dynamic_cast<TreeTableRow*>(CurrentSelection());
if (row == NULL)
return;
- TreeTableField* field = dynamic_cast<TreeTableField*>(row->GetField(0));
- if (field == NULL)
- return;
+ TreeTablePath path;
+ _GetPathForNode(row->Node(), path);
int32 listenerCount = fListeners.CountItems();
for (int32 i = listenerCount - 1; i >= 0; i--)
- fListeners.ItemAt(i)->TreeTableNodeInvoked(this, field->Object());
+ fListeners.ItemAt(i)->TreeTableNodeInvoked(this, path);
}
+
+
+bool
+TreeTable::_AddChildRows(TreeTableNode* parentNode, int32 childIndex,
+ int32 count, int32 columnCount)
+{
+ int32 childEndIndex = childIndex + count;
+ for (int32 i = childIndex; i < childEndIndex; i++) {
+ void* child = fModel->ChildAt(parentNode->ModelObject(), i);
+
+ // create node
+ TreeTableNode* node = new(std::nothrow) TreeTableNode(parentNode);
+ if (node == NULL || node->Init(child, columnCount) != B_OK
+ || !parentNode->AddChild(node, i)) {
+ delete node;
+ return false;
+ }
+
+ // add row
+ AddRow(node->Row(), i,
+ parentNode != fRootNode ? parentNode->Row() : NULL);
+
+ // recursively create children
+ if (!_AddChildRows(node, 0, fModel->CountChildren(child), columnCount))
+ return false;
+ }
+
+ return true;
+}
+
+
+void
+TreeTable::_RemoveChildRows(TreeTableNode* parentNode, int32 childIndex,
+ int32 count)
+{
+ for (int32 i = childIndex + count - 1; i >= childIndex; i--) {
+ if (TreeTableNode* child = parentNode->RemoveChild(i)) {
+ int32 childCount = child->CountChildren();
+ if (childCount > 0)
+ _RemoveChildRows(child, 0, childCount);
+
+ RemoveRow(child->Row());
+ delete child;
+ }
+ }
+}
+
+
+void
+TreeTable::_SetNodeExpanded(TreeTableNode* node, bool expanded,
+ bool expandAncestors)
+{
+ if (expanded && expandAncestors && node != fRootNode)
+ _SetNodeExpanded(node->Parent(), true, true);
+
+ BColumnListView::ExpandOrCollapse(node->Row(), expanded);
+}
+
+
+TreeTableNode*
+TreeTable::_NodeForPath(const TreeTablePath& path) const
+{
+ TreeTableNode* node = fRootNode;
+
+ int32 count = path.CountComponents();
+ for (int32 i = 0; node != NULL && i < count; i++)
+ node = node->ChildAt(path.ComponentAt(i));
+
+ return node;
+}
+
+
+void
+TreeTable::_GetPathForNode(TreeTableNode* node, TreeTablePath& _path) const
+{
+ if (node == fRootNode) {
+ _path.Clear();
+ return;
+ }
+
+ _GetPathForNode(node->Parent(), _path);
+ _path.AddComponent(node->Parent()->IndexOf(node));
+}
Modified: haiku/trunk/src/apps/debuganalyzer/gui/table/TreeTable.h
===================================================================
--- haiku/trunk/src/apps/debuganalyzer/gui/table/TreeTable.h 2009-06-27 16:39:42 UTC (rev 31268)
+++ haiku/trunk/src/apps/debuganalyzer/gui/table/TreeTable.h 2009-06-27 16:41:46 UTC (rev 31269)
@@ -5,6 +5,8 @@
#ifndef TREE_TABLE_H
#define TREE_TABLE_H
+#include <vector>
+
#include <ColumnTypes.h>
#include <Variant.h>
@@ -13,8 +15,53 @@
class TreeTable;
+class TreeTableModel;
+class TreeTableNode;
+class TreeTableRow;
+class TreeTablePath {
+public:
+ TreeTablePath();
+ TreeTablePath(const TreeTablePath& other);
+ TreeTablePath(const TreeTablePath& other,
+ int32 childIndex);
+ ~TreeTablePath();
+
+ bool AddComponent(int32 childIndex);
+ void Clear();
+
+ int32 CountComponents() const;
+ int32 ComponentAt(int32 index) const;
+
+ TreeTablePath& operator=(const TreeTablePath& other);
+ bool operator==(const TreeTablePath& other) const;
+ bool operator!=(const TreeTablePath& other) const;
+
+private:
+ typedef std::vector<int32> ComponentVector;
+
+private:
+ ComponentVector fComponents;
+};
+
+
+class TreeTableModelListener {
+public:
+ virtual ~TreeTableModelListener();
+
+ virtual void TableNodesAdded(TreeTableModel* model,
+ const TreeTablePath& path, int32 childIndex,
+ int32 count);
+ virtual void TableNodesRemoved(TreeTableModel* model,
+ const TreeTablePath& path, int32 childIndex,
+ int32 count);
+ virtual void TableNodesChanged(TreeTableModel* model,
+ const TreeTablePath& path, int32 childIndex,
+ int32 count);
+};
+
+
class TreeTableModel : public AbstractTableModelBase {
public:
virtual ~TreeTableModel();
@@ -27,19 +74,64 @@
virtual bool GetValueAt(void* object, int32 columnIndex,
BVariant& value) = 0;
+
+ virtual void* NodeForPath(const TreeTablePath& path) const;
+
+ virtual bool AddListener(TreeTableModelListener* listener);
+ virtual void RemoveListener(
+ TreeTableModelListener* listener);
+
+protected:
+ typedef BObjectList<TreeTableModelListener> ListenerList;
+
+protected:
+ void NotifyNodesAdded(const TreeTablePath& path,
+ int32 childIndex, int32 count);
+ void NotifyNodesRemoved(const TreeTablePath& path,
+ int32 childIndex, int32 count);
+ void NotifyNodesChanged(const TreeTablePath& path,
+ int32 childIndex, int32 count);
+
+protected:
+ ListenerList fListeners;
};
+class TreeTableSelectionModel {
+public:
+ TreeTableSelectionModel(TreeTable* table);
+ ~TreeTableSelectionModel();
+
+ int32 CountNodes();
+ void* NodeAt(int32 index);
+ bool GetPathAt(int32 index, TreeTablePath& _path);
+
+private:
+ friend class TreeTable;
+
+private:
+ void _SelectionChanged();
+ void _Update();
+ TreeTableNode* _NodeAt(int32 index);
+
+private:
+ TreeTable* fTreeTable;
+ TreeTableNode** fNodes;
+ int32 fNodeCount;
+};
+
+
class TreeTableListener {
public:
virtual ~TreeTableListener();
+ virtual void TreeTableSelectionChanged(TreeTable* table);
virtual void TreeTableNodeInvoked(TreeTable* table,
- void* node);
+ const TreeTablePath& path);
};
-class TreeTable : public AbstractTable {
+class TreeTable : public AbstractTable, private TreeTableModelListener {
public:
TreeTable(const char* name, uint32 flags,
border_style borderStyle = B_NO_BORDER,
@@ -50,31 +142,74 @@
bool showHorizontalScrollbar = true);
virtual ~TreeTable();
- void SetTreeTableModel(TreeTableModel* model);
+ bool SetTreeTableModel(TreeTableModel* model);
TreeTableModel* GetTreeTableModel() const { return fModel; }
+ TreeTableSelectionModel* SelectionModel();
+
+ void SelectNode(const TreeTablePath& path,
+ bool extendSelection);
+ void DeselectNode(const TreeTablePath& path);
+ void DeselectAllNodes();
+
+ bool IsNodeExpanded(const TreeTablePath& path) const;
+ void SetNodeExpanded(const TreeTablePath& path,
+ bool expanded,
+ bool expandAncestors = false);
+
+ void ScrollToNode(const TreeTablePath& path);
+
bool AddTreeTableListener(
TreeTableListener* listener);
void RemoveTreeTableListener(
TreeTableListener* listener);
protected:
+ virtual void SelectionChanged();
+
virtual AbstractColumn* CreateColumn(TableColumn* column);
private:
+ virtual void TableNodesAdded(TreeTableModel* model,
[... truncated: 44 lines follow ...]
More information about the Haiku-commits
mailing list