20 : wxPanel(parent, wxID_ANY), m_config(config) {
21 SetBackgroundColour(m_config.panelColour);
36 long treeStyle = wxTR_HAS_BUTTONS | wxTR_MULTIPLE;
38 treeStyle |= wxTR_NO_LINES;
47 treeFont.SetPointSize(
m_config.fontSize);
139 wxString nodeName = wxString(child->
GetName().c_str()).Lower();
141 if (nodeName.Find(searchLower) == wxNOT_FOUND)
170 if (remainingDepth <= 0 || !item.IsOk())
176 wxTreeItemIdValue checkCookie;
177 wxTreeItemId firstChild =
m_treeCtrl->GetFirstChild(item, checkCookie);
178 if (firstChild.IsOk()) {
179 wxTreeItemData *data =
m_treeCtrl->GetItemData(firstChild);
191 wxTreeItemIdValue cookie;
192 wxTreeItemId child =
m_treeCtrl->GetFirstChild(item, cookie);
193 while (child.IsOk()) {
195 child =
m_treeCtrl->GetNextChild(item, cookie);
200 if (!item.IsOk() || !
m_treeCtrl->ItemHasChildren(item))
207 wxTreeItemIdValue checkCookie;
208 wxTreeItemId firstChild =
m_treeCtrl->GetFirstChild(item, checkCookie);
209 if (firstChild.IsOk()) {
210 wxTreeItemData *data =
m_treeCtrl->GetItemData(firstChild);
219 wxTreeItemIdValue cookie;
220 wxTreeItemId child =
m_treeCtrl->GetFirstChild(item, cookie);
221 while (child.IsOk()) {
223 child =
m_treeCtrl->GetNextChild(item, cookie);
234 wxArrayTreeItemIds selections;
235 size_t count =
m_treeCtrl->GetSelections(selections);
243 if (!
m_config.syncSelectionWithCanvas)
266 return "Unknown Node";
302 wxTreeItemId searchStart = start.IsOk() ? start :
m_treeCtrl->GetRootItem();
303 if (!searchStart.IsOk())
304 return wxTreeItemId();
307 if (currentNode && currentNode->
GetId() == nodeId) {
311 wxTreeItemIdValue cookie;
312 wxTreeItemId child =
m_treeCtrl->GetFirstChild(searchStart, cookie);
313 while (child.IsOk()) {
317 child =
m_treeCtrl->GetNextChild(searchStart, cookie);
320 return wxTreeItemId();
325 return wxTreeItemId();
328 std::vector<EmberCore::ITreeNode *> path;
331 path.push_back(current);
334 std::reverse(path.begin(), path.end());
336 wxTreeItemId currentItem =
m_treeCtrl->GetRootItem();
337 if (!currentItem.IsOk())
338 return wxTreeItemId();
341 if (!rootNode || rootNode->
GetId() != path[0]->GetId())
342 return wxTreeItemId();
344 for (
size_t i = 1; i < path.size(); ++i) {
346 wxTreeItemIdValue checkCookie;
347 wxTreeItemId firstChild =
m_treeCtrl->GetFirstChild(currentItem, checkCookie);
360 wxTreeItemIdValue cookie;
361 wxTreeItemId child =
m_treeCtrl->GetFirstChild(currentItem, cookie);
363 while (child.IsOk()) {
365 if (childNode && childNode->
GetId() == path[i]->GetId()) {
370 child =
m_treeCtrl->GetNextChild(currentItem, cookie);
373 return wxTreeItemId();
386 if (!
m_treeCtrl->GetBoundingRect(item, itemRect,
true))
389 int clientWidth =
m_treeCtrl->GetClientSize().GetWidth();
392 if (itemRect.x < margin) {
393 int pos =
m_treeCtrl->GetScrollPos(wxHORIZONTAL);
394 m_treeCtrl->SetScrollPos(wxHORIZONTAL, std::max(0, pos - (margin - itemRect.x)),
true);
396 }
else if (itemRect.x > clientWidth - 100) {
397 int pos =
m_treeCtrl->GetScrollPos(wxHORIZONTAL);
398 m_treeCtrl->SetScrollPos(wxHORIZONTAL, pos + (itemRect.x - margin),
true);
404 if (!from.IsOk() || !to.IsOk())
407 std::vector<wxTreeItemId> allItems;
408 std::function<void(
const wxTreeItemId &)> collectItems = [&](
const wxTreeItemId &item) {
411 allItems.push_back(item);
413 wxTreeItemIdValue cookie;
414 wxTreeItemId child =
m_treeCtrl->GetFirstChild(item, cookie);
415 while (child.IsOk()) {
417 child =
m_treeCtrl->GetNextChild(item, cookie);
422 wxTreeItemId root =
m_treeCtrl->GetRootItem();
427 int fromIdx = -1, toIdx = -1;
428 for (
size_t i = 0; i < allItems.size(); ++i) {
429 if (allItems[i] == from)
430 fromIdx =
static_cast<int>(i);
431 if (allItems[i] == to)
432 toIdx =
static_cast<int>(i);
435 if (fromIdx < 0 || toIdx < 0)
439 std::swap(fromIdx, toIdx);
442 for (
int i = fromIdx; i <= toIdx; ++i) {
452 wxTreeItemId item =
event.GetItem();
462 wxTreeItemIdValue cookie;
463 wxTreeItemId firstChild =
m_treeCtrl->GetFirstChild(item, cookie);
464 if (firstChild.IsOk()) {
465 wxTreeItemData *data =
m_treeCtrl->GetItemData(firstChild);
493 wxTreeItemId selectedItem =
event.GetItem();
494 if (!selectedItem.IsOk()) {
503 if (
m_config.syncSelectionWithCanvas) {
521 if (contextMenu.GetMenuItemCount() > 0) {
522 contextMenu.Bind(wxEVT_COMMAND_MENU_SELECTED,
524 PopupMenu(&contextMenu);
BehaviorTreeProjectDialog::OnProjectNameChanged BehaviorTreeProjectDialog::OnRemoveFiles wxEND_EVENT_TABLE() BehaviorTreeProjectDialog
Abstract interface for tree nodes that can be visualized.
virtual size_t GetId() const =0
virtual size_t GetChildCount() const =0
virtual ITreeNode * GetParent() const =0
virtual bool AreChildrenVisible() const =0
virtual bool HasChildren() const
virtual void SetChildrenVisible(bool visible)=0
virtual const String & GetName() const =0
virtual ITreeNode * GetChild(size_t index) const =0
virtual void SetVisualState(VisualState state)=0
Base class for hierarchy tabs operating on ITreeNode.
EmberCore::ITreeNode * GetSelectedNode() const
Returns the currently selected node, or nullptr.
void SelectNodeById(size_t nodeId)
Selects the tree item with the given node ID.
wxTreeItemId ExpandPathToNode(EmberCore::ITreeNode *node)
Expands path from root to node and returns its item ID.
virtual void OnSelectionChanged(EmberCore::ITreeNode *node)
Called when selection changes; subclasses may override.
virtual void OnNodeActivated(EmberCore::ITreeNode *node)
Hook called when a node is double-clicked/activated.
SelectionCallback m_selectionCallback
void AddFilteredNodes(const wxTreeItemId &parentItem, EmberCore::ITreeNode *node)
void ExpandTreeToDepth(const wxTreeItemId &item, int remainingDepth)
virtual void OnContextMenuCommand(int id, EmberCore::ITreeNode *node)
Hook to handle context menu command.
wxSearchCtrl * m_searchCtrl
void CollapseAll()
Collapses all tree items.
virtual wxString GetNodeDisplayText(EmberCore::ITreeNode *node) const
Returns display text for a node; subclasses may override.
virtual void OnNodeExpanding(EmberCore::ITreeNode *node)
Called when a node is expanding; used for lazy loading.
void RefreshTree()
Rebuilds the tree from the current structure.
void ScrollToItemHorizontally(const wxTreeItemId &item)
Scrolls horizontally so the item is visible.
void OnTreeItemCollapsing(wxTreeEvent &event)
void ClearTree()
Clears the tree and removes all items.
EmberCore::ITreeNode * GetNodeFromItem(const wxTreeItemId &item) const
Extracts ITreeNode from a tree item (or nullptr if DummyTreeItemData).
void ApplyConfig(const TreeHierarchyConfig &config)
Applies new configuration and refreshes the tree.
void OnTreeItemRightClick(wxTreeEvent &event)
void OnTreeItemExpanding(wxTreeEvent &event)
virtual void OnNodeCollapsing(EmberCore::ITreeNode *node)
Called when a node is collapsing.
LayoutInvalidationCallback m_layoutInvalidationCb
void OnSearchTextChanged(wxCommandEvent &event)
wxTreeItemId m_lastSelectedItem
void ExpandTreeByVisibility(const wxTreeItemId &item)
wxTreeItemId FindItemById(size_t nodeId, const wxTreeItemId &start=wxTreeItemId())
Finds tree item by node ID, optionally starting from given item.
virtual void OnPopulateContextMenu(EmberCore::ITreeNode *node, wxMenu &menu)
Hook to populate context menu for a node.
std::shared_ptr< EmberCore::ITreeStructure > m_tree
TreeHierarchyConfig m_config
void ExpandAll()
Expands all tree items.
void OnSearchEnter(wxCommandEvent &event)
void AddChildrenToItem(const wxTreeItemId &parentItem, EmberCore::ITreeNode *node)
void OnTreeItemActivated(wxTreeEvent &event)
void SelectRange(const wxTreeItemId &from, const wxTreeItemId &to)
Selects a range of items from from to to.
void OnTreeSelectionChanged(wxTreeEvent &event)
void SetTree(std::shared_ptr< EmberCore::ITreeStructure > tree)
Sets the tree structure to display.
Standard layout constants for consistent UI spacing and sizing.
wxBEGIN_EVENT_TABLE(Panel, wxPanel) EVT_SIZE(Panel
Placeholder tree item data for lazy loading (children not yet populated).
Configuration for TreeHierarchyTab appearance and behavior.
wxTreeItemData storing a pointer to ITreeNode.
EmberCore::ITreeNode * node