home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
wxos2240.zip
/
wxWindows-2.4.0
/
src
/
generic
/
treelay.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
2002-11-04
|
10KB
|
472 lines
///////////////////////////////////////////////////////////////////////////////
// Name: treelay.h
// Purpose: wxTreeLayout class
// Author: Julian Smart
// Modified by:
// Created: 7/4/98
// RCS-ID: $Id: treelay.cpp,v 1.7.2.1 2002/10/29 21:47:58 RR Exp $
// Copyright: (c) 1998 Julian Smart
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
#ifdef __GNUG__
#pragma implementation "wxtree.h"
#endif
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/dc.h"
#include "wx/event.h"
#endif
#if wxUSE_TREELAYOUT
#include "wx/treelay.h"
/*
* Abstract tree
*
*/
IMPLEMENT_ABSTRACT_CLASS(wxTreeLayout, wxObject)
wxTreeLayout::wxTreeLayout()
{
m_xSpacing = 16;
m_ySpacing = 20;
m_topMargin = 5;
m_leftMargin = 5;
m_orientation = FALSE;
m_parentNode = 0;
}
void wxTreeLayout::DoLayout(wxDC& dc, long topId)
{
if (topId != -1)
SetTopNode(topId);
long actualTopId = GetTopNode();
long id = actualTopId;
while (id != -1)
{
SetNodeX(id, 0);
SetNodeY(id, 0);
ActivateNode(id, FALSE);
id = GetNextNode(id);
}
m_lastY = m_topMargin;
m_lastX = m_leftMargin;
CalcLayout(actualTopId, 0, dc);
}
void wxTreeLayout::Draw(wxDC& dc)
{
dc.Clear();
DrawBranches(dc);
DrawNodes(dc);
}
void wxTreeLayout::DrawNodes(wxDC& dc)
{
long id = GetTopNode();
while (id != -1)
{
if (NodeActive(id))
DrawNode(id, dc);
id = GetNextNode(id);
}
}
void wxTreeLayout::DrawBranches(wxDC& dc)
{
long id = GetTopNode();
while (id != -1)
{
if (GetNodeParent(id) > -1)
{
long parent = GetNodeParent(id);
if (NodeActive(parent))
DrawBranch(parent, id, dc);
}
id = GetNextNode(id);
}
}
void wxTreeLayout::DrawNode(long id, wxDC& dc)
{
wxChar buf[80];
wxString name(GetNodeName(id));
if (name != wxT(""))
wxSprintf(buf, wxT("%s"), (const wxChar*) name);
else
wxSprintf(buf, wxT("<unnamed>"));
long x = 80;
long y = 20;
dc.GetTextExtent(buf, &x, &y);
dc.DrawText(buf, GetNodeX(id), (long)(GetNodeY(id) - (y/2.0)));
}
void wxTreeLayout::DrawBranch(long from, long to, wxDC& dc)
{
long w, h;
GetNodeSize(from, &w, &h, dc);
dc.DrawLine(GetNodeX(from)+w, GetNodeY(from),
GetNodeX(to), GetNodeY(to));
}
void wxTreeLayout::Initialize(void)
{
}
void wxTreeLayout::GetNodeSize(long id, long *x, long *y, wxDC& dc)
{
wxString name(GetNodeName(id));
if (name != wxT(""))
dc.GetTextExtent(name, x, y);
else
{
*x = 70; *y = 20;
}
}
void wxTreeLayout::CalcLayout(long nodeId, int level, wxDC& dc)
{
wxList children;
GetChildren(nodeId, children);
int n = children.Number();
if (m_orientation == FALSE)
{
// Left to right
// X Calculations
if (level == 0)
SetNodeX(nodeId, m_leftMargin);
else
{
long x = 0;
long y = 0;
long parentId = GetNodeParent(nodeId);
if (parentId != -1)
GetNodeSize(parentId, &x, &y, dc);
SetNodeX(nodeId, (long)(GetNodeX(parentId) + m_xSpacing + x));
}
wxNode *node = children.First();
while (node)
{
CalcLayout((long)node->Data(), level+1, dc);
node = node->Next();
}
// Y Calculations
long averageY;
ActivateNode(nodeId, TRUE);
if (n > 0)
{
averageY = 0;
node = children.First();
while (node)
{
averageY += GetNodeY((long)node->Data());
node = node->Next();
}
averageY = averageY / n;
SetNodeY(nodeId, averageY);
}
else
{
SetNodeY(nodeId, m_lastY);
long x, y;
GetNodeSize(nodeId, &x, &y, dc);
m_lastY = m_lastY + y + m_ySpacing;
}
}
else
{
// Top to bottom
// Y Calculations
if (level == 0)
SetNodeY(nodeId, m_topMargin);
else
{
long x = 0;
long y = 0;
long parentId = GetNodeParent(nodeId);
if (parentId != -1)
GetNodeSize(parentId, &x, &y, dc);
SetNodeY(nodeId, (long)(GetNodeY(parentId) + m_ySpacing + y));
}
wxNode *node = children.First();
while (node)
{
CalcLayout((long)node->Data(), level+1, dc);
node = node->Next();
}
// X Calculations
long averageX;
ActivateNode(nodeId, TRUE);
if (n > 0)
{
averageX = 0;
node = children.First();
while (node)
{
averageX += GetNodeX((long)node->Data());
node = node->Next();
}
averageX = averageX / n;
SetNodeX(nodeId, averageX);
}
else
{
SetNodeX(nodeId, m_lastX);
long x, y;
GetNodeSize(nodeId, &x, &y, dc);
m_lastX = m_lastX + x + m_xSpacing;
}
}
}
/*
* Tree with storage
*
*/
IMPLEMENT_DYNAMIC_CLASS(wxTreeLayoutStored, wxTreeLayout)
wxTreeLayoutStored::wxTreeLayoutStored(int n):wxTreeLayout()
{
m_nodes = NULL;
m_maxNodes = 0;
Initialize(n);
}
wxTreeLayoutStored::~wxTreeLayoutStored(void)
{
if (m_nodes)
delete[] m_nodes;
}
void wxTreeLayoutStored::Initialize(int n)
{
m_maxNodes = n;
wxTreeLayout::Initialize();
if (m_nodes) delete[] m_nodes;
m_nodes = new wxStoredNode[m_maxNodes];
int i;
for (i = 0; i < n; i++)
{
m_nodes[i].m_name = wxT("");
m_nodes[i].m_active = FALSE;
m_nodes[i].m_parentId = -1;
m_nodes[i].m_x = 0;
m_nodes[i].m_y = 0;
}
m_num = 0;
}
long wxTreeLayoutStored::AddChild(const wxString& name, const wxString& parent)
{
if (m_num < (m_maxNodes -1 ))
{
long i = -1;
if (parent != wxT(""))
i = NameToId(parent);
else m_parentNode = m_num;
m_nodes[m_num].m_parentId = i;
m_nodes[m_num].m_name = name;
m_nodes[m_num].m_x = m_nodes[m_num].m_y = 0;
m_nodes[m_num].m_clientData = 0;
m_num ++;
return (m_num - 1);
}
else
return -1;
}
long wxTreeLayoutStored::AddChild(const wxString& name, long parent)
{
if (m_num < (m_maxNodes -1 ) && parent < m_num)
{
long i = -1;
if (parent != -1)
{
i = parent;
}
else
{
m_parentNode = m_num;
}
m_nodes[m_num].m_parentId = i;
m_nodes[m_num].m_name = name;
m_nodes[m_num].m_x = m_nodes[m_num].m_y = 0;
m_nodes[m_num].m_clientData = 0;
m_num ++;
return (m_num - 1);
}
else
return -1;
}
long wxTreeLayoutStored::NameToId(const wxString& name)
{
long i;
for (i = 0; i < m_num; i++)
if (name == m_nodes[i].m_name)
return i;
return -1;
}
void wxTreeLayoutStored::GetChildren(long id, wxList& list)
{
long currentId = GetTopNode();
while (currentId != -1)
{
if (id == GetNodeParent(currentId))
list.Append((wxObject *)currentId);
currentId = GetNextNode(currentId);
}
}
wxStoredNode* wxTreeLayoutStored::GetNode(long idx) const
{
wxASSERT(idx < m_num);
return &m_nodes[idx];
};
long wxTreeLayoutStored::GetNodeX(long id)
{
wxASSERT(id < m_num);
return (long)m_nodes[id].m_x;
}
long wxTreeLayoutStored::GetNodeY(long id)
{
wxASSERT(id < m_num);
return (long)m_nodes[id].m_y;
}
void wxTreeLayoutStored::SetNodeX(long id, long x)
{
wxASSERT(id < m_num);
m_nodes[id].m_x = (int)x;
}
void wxTreeLayoutStored::SetNodeY(long id, long y)
{
wxASSERT(id < m_num);
m_nodes[id].m_y = (int)y;
}
void wxTreeLayoutStored::SetNodeName(long id, const wxString& name)
{
wxASSERT(id < m_num);
m_nodes[id].m_name = name;
}
wxString wxTreeLayoutStored::GetNodeName(long id)
{
wxASSERT(id < m_num);
return m_nodes[id].m_name;
}
long wxTreeLayoutStored::GetNodeParent(long id)
{
if (id != -1)
{
wxASSERT(id < m_num);
return m_nodes[id].m_parentId;
}
else
return -1;
}
long wxTreeLayoutStored::GetNextNode(long id)
{
wxASSERT(id < m_num);
if ((id != -1) && (id < (m_num - 1)))
return id + 1;
else
return -1;
}
void wxTreeLayoutStored::SetClientData(long id, long clientData)
{
wxASSERT(id < m_num);
m_nodes[id].m_clientData = clientData;
}
long wxTreeLayoutStored::GetClientData(long id) const
{
wxASSERT(id < m_num);
return m_nodes[id].m_clientData;
}
void wxTreeLayoutStored::ActivateNode(long id, bool active)
{
wxASSERT(id < m_num);
m_nodes[id].m_active = active;
}
bool wxTreeLayoutStored::NodeActive(long id)
{
wxASSERT(id < m_num);
return m_nodes[id].m_active;
}
wxString wxTreeLayoutStored::HitTest(wxMouseEvent& event, wxDC& dc)
{
wxPoint pt = event.GetPosition();
wxCoord x = pt.x;
wxCoord y = pt.y;
int i;
for (i = 0; i < m_maxNodes; i++)
{
long width, height;
dc.GetTextExtent(m_nodes[i].m_name, &width, &height);
if ( (x >= (m_nodes[i].m_x-10)) && (x < (m_nodes[i].m_x + width+10)) &&
(y >= m_nodes[i].m_y-10) && (y < (m_nodes[i].m_y + height+10)) )
{
return m_nodes[i].m_name;
}
}
return wxString( wxT("") );
}
#endif
// wxUSE_TREELAYOUT