Files
bullet3/examples/ThirdPartyLibs/Gwen/Controls/TreeNode.cpp
erwincoumans ab8f16961e Code-style consistency improvement:
Apply clang-format-all.sh using the _clang-format file through all the cpp/.h files.
make sure not to apply it to certain serialization structures, since some parser expects the * as part of the name, instead of type.
This commit contains no other changes aside from adding and applying clang-format-all.sh
2018-09-23 14:17:31 -07:00

339 lines
6.8 KiB
C++

/*
GWEN
Copyright (c) 2010 Facepunch Studios
See license in Gwen.h
*/
#include "Gwen/Controls/TreeNode.h"
#include "Gwen/Controls/TreeControl.h"
#include "Gwen/Utility.h"
using namespace Gwen;
using namespace Gwen::Controls;
class OpenToggleButton : public Button
{
GWEN_CONTROL_INLINE(OpenToggleButton, Button)
{
SetIsToggle(true);
SetTabable(false);
}
virtual void RenderFocus(Skin::Base* /*skin*/) {}
virtual void Render(Skin::Base* skin)
{
skin->DrawTreeButton(this, GetToggleState());
}
};
const int TreeIndentation = 14;
const int BranchLength = 16;
GWEN_CONTROL_CONSTRUCTOR(TreeNode)
{
m_TreeControl = NULL;
m_ToggleButton = new OpenToggleButton(this);
m_ToggleButton->SetBounds(2, 2, 13, 13);
m_ToggleButton->onToggle.Add(this, &TreeNode::OnToggleButtonPress);
m_Title = new Button(this);
m_Title->Dock(Pos::Top);
m_Title->SetMargin(Margin(BranchLength, 0, 0, 0));
m_Title->SetAlignment(Pos::Left | Pos::CenterV);
m_Title->SetShouldDrawBackground(false);
m_Title->onDoubleClick.Add(this, &TreeNode::OnDoubleClickName);
m_Title->onDown.Add(this, &TreeNode::OnClickName);
m_Title->SetHeight(16);
m_InnerPanel = new Base(this);
m_InnerPanel->Dock(Pos::Top);
m_InnerPanel->SetHeight(100);
m_InnerPanel->SetMargin(Margin(TreeIndentation, 1, 0, 0));
m_InnerPanel->Hide();
m_bRoot = false;
m_bSelected = false;
m_bSelectable = true;
}
void TreeNode::Render(Skin::Base* skin)
{
int iBottom = 0;
if (m_InnerPanel->Children.size() > 0)
{
iBottom = m_InnerPanel->Children.back()->Y() + m_InnerPanel->Y();
}
skin->DrawTreeNode(this, m_InnerPanel->Visible(), IsSelected(), m_Title->Height(), m_Title->TextRight(), m_ToggleButton->Y() + m_ToggleButton->Height() * 0.5, iBottom, GetParent() == m_TreeControl);
}
TreeNode* TreeNode::AddNode(const UnicodeString& strLabel)
{
// int sz = sizeof(TreeNode);
TreeNode* node = new TreeNode(this);
node->SetText(strLabel);
node->Dock(Pos::Top);
node->SetRoot(this->DynamicCastTreeControl() != NULL);
node->SetTreeControl(m_TreeControl);
if (m_TreeControl)
{
m_TreeControl->OnNodeAdded(node);
}
return node;
}
TreeNode* TreeNode::AddNode(const String& strLabel)
{
return AddNode(Utility::StringToUnicode(strLabel));
}
void TreeNode::Layout(Skin::Base* skin)
{
if (m_ToggleButton)
{
if (m_InnerPanel->NumChildren() == 0)
{
m_ToggleButton->Hide();
m_ToggleButton->SetToggleState(false);
m_InnerPanel->Hide();
}
else
{
m_ToggleButton->Show();
m_InnerPanel->SizeToChildren(false, true);
}
}
BaseClass::Layout(skin);
}
//too many calls to PostLayout...
//int numCalls = 0xfd;
void TreeNode::PostLayout(Skin::Base* /*skin*/)
{
//int bla = numCalls&0xffff;
//if (bla==0)
// printf("TreeNode::PostLayout numCalls = %d\n", numCalls);
//numCalls++;
if (SizeToChildren(false, true))
{
InvalidateParent();
}
}
void TreeNode::SetText(const UnicodeString& text) { m_Title->SetText(text); };
void TreeNode::SetText(const String& text) { m_Title->SetText(text); };
UnicodeString TreeNode::GetText() const
{
UnicodeString bla = m_Title->GetText();
return bla;
}
void TreeNode::Open()
{
m_InnerPanel->Show();
if (m_ToggleButton) m_ToggleButton->SetToggleState(true);
Invalidate();
if (m_TreeControl)
m_TreeControl->ForceUpdateScrollBars();
}
void TreeNode::Close()
{
m_InnerPanel->Hide();
if (m_ToggleButton) m_ToggleButton->SetToggleState(false);
Invalidate();
if (m_TreeControl)
m_TreeControl->ForceUpdateScrollBars();
}
void TreeNode::ExpandAll()
{
Open();
Base::List& children = m_InnerPanel->GetChildren();
for (Base::List::iterator iter = children.begin(); iter != children.end(); ++iter)
{
TreeNode* pChild = (*iter)->DynamicCastTreeNode();
if (!pChild) continue;
pChild->ExpandAll();
}
}
Button* TreeNode::GetButton() { return m_Title; }
void TreeNode::OnToggleButtonPress(Base* /*control*/)
{
if (m_ToggleButton->GetToggleState())
{
Open();
}
else
{
Close();
}
}
void TreeNode::OnDoubleClickName(Base* /*control*/)
{
if (!m_ToggleButton->Visible()) return;
m_ToggleButton->Toggle();
}
void TreeNode::OnClickName(Base* /*control*/)
{
onNamePress.Call(this);
SetSelected(!IsSelected());
}
void TreeNode::SetSelected(bool b)
{
if (!m_bSelectable) return;
if (m_bSelected == b) return;
m_bSelected = b;
onSelectChange.Call(this);
if (m_bSelected)
onSelect.Call(this);
else
onUnselect.Call(this);
}
void TreeNode::DeselectAll()
{
m_bSelected = false;
Base::List& children = m_InnerPanel->GetChildren();
for (Base::List::iterator iter = children.begin(); iter != children.end(); ++iter)
{
TreeNode* pChild = (*iter)->DynamicCastTreeNode();
if (!pChild) continue;
pChild->DeselectAll();
}
}
void TreeNode::iterate(int action, int* curIndex, int* targetIndex)
{
Gwen::String name = Gwen::Utility::UnicodeToString(m_Title->GetText());
// int actualIndex = curIndex? *curIndex : -1;
//printf("iterated over item %d with name = %s\n", actualIndex, name.c_str());
if (action == ITERATE_ACTION_SELECT)
{
if (curIndex && targetIndex)
{
if ((*curIndex) == (*targetIndex))
{
SetSelected(true);
*targetIndex = -1;
}
}
}
if (IsSelected())
{
//printf("current selected: name = %s\n", name.c_str());
switch (action)
{
case ITERATE_ACTION_DESELECT_INDEX:
{
if (targetIndex && curIndex)
{
if (*targetIndex == *curIndex)
SetSelected(false);
}
break;
}
case ITERATE_ACTION_FIND_SELECTED_INDEX:
{
if (targetIndex && curIndex)
{
*targetIndex = *curIndex;
}
break;
}
case ITERATE_ACTION_OPEN:
{
Open();
break;
}
case ITERATE_ACTION_CLOSE:
{
//either close or select parent
if (this->GetChildren().size())
{
if (m_ToggleButton && m_ToggleButton->GetToggleState())
{
Close();
}
else
{
TreeNode* pChild = (GetParent())->DynamicCastTreeNode();
TreeControl* pChild2 = (GetParent())->DynamicCastTreeControl();
if (pChild && !pChild2)
{
SetSelected(false);
pChild->SetSelected(true);
}
}
}
else
{
TreeNode* pChild = (GetParent())->DynamicCastTreeNode();
TreeControl* pChild2 = (GetParent())->DynamicCastTreeControl();
if (pChild && !pChild2)
{
SetSelected(false);
pChild->SetSelected(true);
}
}
break;
}
default:
{
}
};
}
if (curIndex)
(*curIndex)++;
bool needsRecursion = true;
if (action == ITERATE_ACTION_FIND_SELECTED_INDEX || action == ITERATE_ACTION_SELECT || action == ITERATE_ACTION_DESELECT_INDEX)
{
if (m_ToggleButton && !m_ToggleButton->GetToggleState())
{
needsRecursion = false;
}
}
if (needsRecursion)
{
Base::List& children = m_InnerPanel->GetChildren();
for (Base::List::iterator iter = children.begin(); iter != children.end(); ++iter)
{
TreeNode* pChild = (*iter)->DynamicCastTreeNode();
if (!pChild)
continue;
pChild->iterate(action, curIndex, targetIndex);
}
}
}