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 >
C/C++ Source or Header  |  2002-11-04  |  10KB  |  472 lines

  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Name:        treelay.h
  3. // Purpose:     wxTreeLayout class
  4. // Author:      Julian Smart
  5. // Modified by:
  6. // Created:     7/4/98
  7. // RCS-ID:      $Id: treelay.cpp,v 1.7.2.1 2002/10/29 21:47:58 RR Exp $
  8. // Copyright:   (c) 1998 Julian Smart
  9. // Licence:     wxWindows licence
  10. ///////////////////////////////////////////////////////////////////////////////
  11.  
  12. #ifdef __GNUG__
  13. #pragma implementation "wxtree.h"
  14. #endif
  15.  
  16. // For compilers that support precompilation, includes "wx.h".
  17. #include "wx/wxprec.h"
  18.  
  19. #ifdef __BORLANDC__
  20. #pragma hdrstop
  21. #endif
  22.  
  23. #ifndef WX_PRECOMP
  24. #include "wx/dc.h"
  25. #include "wx/event.h"
  26. #endif
  27.  
  28. #if wxUSE_TREELAYOUT
  29.  
  30. #include "wx/treelay.h"
  31.  
  32. /*
  33.  * Abstract tree
  34.  *
  35.  */
  36.  
  37. IMPLEMENT_ABSTRACT_CLASS(wxTreeLayout, wxObject)
  38.  
  39. wxTreeLayout::wxTreeLayout()
  40. {
  41.     m_xSpacing = 16;
  42.     m_ySpacing = 20;
  43.     m_topMargin = 5;
  44.     m_leftMargin = 5;
  45.     m_orientation = FALSE;
  46.     m_parentNode = 0;
  47. }
  48.  
  49. void wxTreeLayout::DoLayout(wxDC& dc, long topId)
  50. {
  51.     if (topId != -1)
  52.         SetTopNode(topId);
  53.  
  54.     long actualTopId = GetTopNode();
  55.     long id = actualTopId;
  56.     while (id != -1)
  57.     {
  58.         SetNodeX(id, 0);
  59.         SetNodeY(id, 0);
  60.         ActivateNode(id, FALSE);
  61.         id = GetNextNode(id);
  62.     }
  63.     m_lastY = m_topMargin;
  64.     m_lastX = m_leftMargin;
  65.     CalcLayout(actualTopId, 0, dc);
  66. }
  67.  
  68. void wxTreeLayout::Draw(wxDC& dc)
  69. {
  70.     dc.Clear();
  71.     DrawBranches(dc);
  72.     DrawNodes(dc);
  73. }
  74.  
  75. void wxTreeLayout::DrawNodes(wxDC& dc)
  76. {
  77.     long id = GetTopNode();
  78.     while (id != -1)
  79.     {
  80.         if (NodeActive(id))
  81.             DrawNode(id, dc);
  82.         id = GetNextNode(id);
  83.     }
  84. }
  85.  
  86. void wxTreeLayout::DrawBranches(wxDC& dc)
  87. {
  88.     long id = GetTopNode();
  89.     while (id != -1)
  90.     {
  91.         if (GetNodeParent(id) > -1)
  92.         {
  93.             long parent = GetNodeParent(id);
  94.             if (NodeActive(parent))
  95.                 DrawBranch(parent, id, dc);
  96.         }
  97.         id = GetNextNode(id);
  98.     }
  99. }
  100.  
  101. void wxTreeLayout::DrawNode(long id, wxDC& dc)
  102. {
  103.     wxChar buf[80];
  104.     wxString name(GetNodeName(id));
  105.     if (name != wxT(""))
  106.         wxSprintf(buf, wxT("%s"), (const wxChar*) name);
  107.     else
  108.         wxSprintf(buf, wxT("<unnamed>"));
  109.  
  110.     long x = 80;
  111.     long y = 20;
  112.     dc.GetTextExtent(buf, &x, &y);
  113.     dc.DrawText(buf, GetNodeX(id), (long)(GetNodeY(id) - (y/2.0)));
  114. }
  115.  
  116. void wxTreeLayout::DrawBranch(long from, long to, wxDC& dc)
  117. {
  118.     long w, h;
  119.     GetNodeSize(from, &w, &h, dc);
  120.     dc.DrawLine(GetNodeX(from)+w, GetNodeY(from),
  121.         GetNodeX(to), GetNodeY(to));
  122. }
  123.  
  124. void wxTreeLayout::Initialize(void)
  125. {
  126. }
  127.  
  128. void wxTreeLayout::GetNodeSize(long id, long *x, long *y, wxDC& dc)
  129. {
  130.     wxString name(GetNodeName(id));
  131.     if (name != wxT(""))
  132.         dc.GetTextExtent(name, x, y);
  133.     else
  134.     {
  135.         *x = 70; *y = 20;
  136.     }
  137. }
  138.  
  139. void wxTreeLayout::CalcLayout(long nodeId, int level, wxDC& dc)
  140. {
  141.     wxList children;
  142.     GetChildren(nodeId, children);
  143.     int n = children.Number();
  144.  
  145.     if (m_orientation == FALSE)
  146.     {
  147.         // Left to right
  148.         // X Calculations
  149.         if (level == 0)
  150.             SetNodeX(nodeId, m_leftMargin);
  151.         else
  152.         {
  153.             long x = 0;
  154.             long y = 0;
  155.             long parentId = GetNodeParent(nodeId);
  156.             if (parentId != -1)
  157.                 GetNodeSize(parentId, &x, &y, dc);
  158.             SetNodeX(nodeId, (long)(GetNodeX(parentId) + m_xSpacing + x));
  159.         }
  160.  
  161.         wxNode *node = children.First();
  162.         while (node)
  163.         {
  164.             CalcLayout((long)node->Data(), level+1, dc);
  165.             node = node->Next();
  166.         }
  167.  
  168.         // Y Calculations
  169.         long averageY;
  170.         ActivateNode(nodeId, TRUE);
  171.  
  172.         if (n > 0)
  173.         {
  174.             averageY = 0;
  175.             node = children.First();
  176.             while (node)
  177.             {
  178.                 averageY += GetNodeY((long)node->Data());
  179.                 node = node->Next();
  180.             }
  181.             averageY = averageY / n;
  182.             SetNodeY(nodeId, averageY);
  183.         }
  184.         else
  185.         {
  186.             SetNodeY(nodeId, m_lastY);
  187.             long x, y;
  188.             GetNodeSize(nodeId, &x, &y, dc);
  189.  
  190.             m_lastY = m_lastY + y + m_ySpacing;
  191.         }
  192.     }
  193.     else
  194.     {
  195.         // Top to bottom
  196.  
  197.         // Y Calculations
  198.         if (level == 0)
  199.             SetNodeY(nodeId, m_topMargin);
  200.         else
  201.         {
  202.             long x = 0;
  203.             long y = 0;
  204.             long parentId = GetNodeParent(nodeId);
  205.             if (parentId != -1)
  206.                 GetNodeSize(parentId, &x, &y, dc);
  207.             SetNodeY(nodeId, (long)(GetNodeY(parentId) + m_ySpacing + y));
  208.         }
  209.  
  210.         wxNode *node = children.First();
  211.         while (node)
  212.         {
  213.             CalcLayout((long)node->Data(), level+1, dc);
  214.             node = node->Next();
  215.         }
  216.  
  217.         // X Calculations
  218.         long averageX;
  219.         ActivateNode(nodeId, TRUE);
  220.  
  221.         if (n > 0)
  222.         {
  223.             averageX = 0;
  224.             node = children.First();
  225.             while (node)
  226.             {
  227.                 averageX += GetNodeX((long)node->Data());
  228.                 node = node->Next();
  229.             }
  230.             averageX = averageX / n;
  231.             SetNodeX(nodeId, averageX);
  232.         }
  233.         else
  234.         {
  235.             SetNodeX(nodeId, m_lastX);
  236.             long x, y;
  237.             GetNodeSize(nodeId, &x, &y, dc);
  238.  
  239.             m_lastX = m_lastX + x + m_xSpacing;
  240.         }
  241.     }
  242. }
  243.  
  244. /*
  245.  * Tree with storage
  246.  *
  247.  */
  248.  
  249. IMPLEMENT_DYNAMIC_CLASS(wxTreeLayoutStored, wxTreeLayout)
  250.  
  251. wxTreeLayoutStored::wxTreeLayoutStored(int n):wxTreeLayout()
  252. {
  253.     m_nodes = NULL;
  254.     m_maxNodes = 0;
  255.     Initialize(n);
  256. }
  257.  
  258. wxTreeLayoutStored::~wxTreeLayoutStored(void)
  259. {
  260.     if (m_nodes)
  261.         delete[] m_nodes;
  262. }
  263.  
  264. void wxTreeLayoutStored::Initialize(int n)
  265. {
  266.     m_maxNodes = n;
  267.     wxTreeLayout::Initialize();
  268.     if (m_nodes) delete[] m_nodes;
  269.     m_nodes = new wxStoredNode[m_maxNodes];
  270.     int i;
  271.     for (i = 0; i < n; i++)
  272.     {
  273.         m_nodes[i].m_name = wxT("");
  274.         m_nodes[i].m_active = FALSE;
  275.         m_nodes[i].m_parentId = -1;
  276.         m_nodes[i].m_x = 0;
  277.         m_nodes[i].m_y = 0;
  278.     }
  279.     m_num = 0;
  280. }
  281.  
  282. long wxTreeLayoutStored::AddChild(const wxString& name, const wxString& parent)
  283. {
  284.     if (m_num < (m_maxNodes -1 ))
  285.     {
  286.         long i = -1;
  287.         if (parent != wxT(""))
  288.             i = NameToId(parent);
  289.         else m_parentNode = m_num;
  290.  
  291.         m_nodes[m_num].m_parentId = i;
  292.         m_nodes[m_num].m_name = name;
  293.         m_nodes[m_num].m_x = m_nodes[m_num].m_y = 0;
  294.         m_nodes[m_num].m_clientData = 0;
  295.         m_num ++;
  296.  
  297.         return (m_num - 1);
  298.     }
  299.     else
  300.         return -1;
  301. }
  302.  
  303. long wxTreeLayoutStored::AddChild(const wxString& name, long parent)
  304. {
  305.     if (m_num < (m_maxNodes -1 ) && parent < m_num)
  306.     {
  307.         long i = -1;
  308.         if (parent != -1)
  309.         {
  310.           i = parent;
  311.         }
  312.         else 
  313.         {
  314.           m_parentNode = m_num;
  315.         }
  316.         
  317.         m_nodes[m_num].m_parentId = i;
  318.         m_nodes[m_num].m_name = name;
  319.         m_nodes[m_num].m_x = m_nodes[m_num].m_y = 0;
  320.         m_nodes[m_num].m_clientData = 0;
  321.         m_num ++;
  322.         
  323.         return (m_num - 1);
  324.     }
  325.     else
  326.         return -1;
  327. }
  328.  
  329. long wxTreeLayoutStored::NameToId(const wxString& name)
  330. {
  331.     long i;
  332.     for (i = 0; i < m_num; i++)
  333.         if (name == m_nodes[i].m_name)
  334.             return i;
  335.         return -1;
  336. }
  337.  
  338. void wxTreeLayoutStored::GetChildren(long id, wxList& list)
  339. {
  340.     long currentId = GetTopNode();
  341.     while (currentId != -1)
  342.     {
  343.         if (id == GetNodeParent(currentId))
  344.             list.Append((wxObject *)currentId);
  345.         currentId = GetNextNode(currentId);
  346.     }
  347. }
  348.  
  349. wxStoredNode* wxTreeLayoutStored::GetNode(long idx) const
  350. {
  351.     wxASSERT(idx < m_num);
  352.  
  353.     return &m_nodes[idx];
  354. };
  355.  
  356. long wxTreeLayoutStored::GetNodeX(long id)
  357. {
  358.     wxASSERT(id < m_num);
  359.  
  360.     return (long)m_nodes[id].m_x;
  361. }
  362.  
  363. long wxTreeLayoutStored::GetNodeY(long id)
  364. {
  365.     wxASSERT(id < m_num);
  366.  
  367.     return (long)m_nodes[id].m_y;
  368. }
  369.  
  370. void wxTreeLayoutStored::SetNodeX(long id, long x)
  371. {
  372.     wxASSERT(id < m_num);
  373.  
  374.     m_nodes[id].m_x = (int)x;
  375. }
  376.  
  377. void wxTreeLayoutStored::SetNodeY(long id, long y)
  378. {
  379.     wxASSERT(id < m_num);
  380.  
  381.     m_nodes[id].m_y = (int)y;
  382. }
  383.  
  384. void wxTreeLayoutStored::SetNodeName(long id, const wxString& name)
  385. {
  386.     wxASSERT(id < m_num);
  387.  
  388.     m_nodes[id].m_name = name;
  389. }
  390.  
  391. wxString wxTreeLayoutStored::GetNodeName(long id)
  392. {
  393.     wxASSERT(id < m_num);
  394.  
  395.     return m_nodes[id].m_name;
  396. }
  397.  
  398. long wxTreeLayoutStored::GetNodeParent(long id)
  399. {
  400.     if (id != -1)
  401.     {
  402.         wxASSERT(id < m_num);
  403.  
  404.         return m_nodes[id].m_parentId;
  405.     }
  406.     else
  407.         return -1;
  408. }
  409.  
  410. long wxTreeLayoutStored::GetNextNode(long id)
  411. {
  412.     wxASSERT(id < m_num);
  413.  
  414.     if ((id != -1) && (id < (m_num - 1)))
  415.         return id + 1;
  416.     else
  417.         return -1;
  418. }
  419.  
  420. void wxTreeLayoutStored::SetClientData(long id, long clientData)
  421. {
  422.     wxASSERT(id < m_num);
  423.  
  424.     m_nodes[id].m_clientData = clientData;
  425. }
  426.  
  427. long wxTreeLayoutStored::GetClientData(long id) const
  428. {
  429.     wxASSERT(id < m_num);
  430.  
  431.     return m_nodes[id].m_clientData;
  432. }
  433.  
  434. void wxTreeLayoutStored::ActivateNode(long id, bool active)
  435. {
  436.     wxASSERT(id < m_num);
  437.  
  438.     m_nodes[id].m_active = active;
  439. }
  440.  
  441. bool wxTreeLayoutStored::NodeActive(long id)
  442. {
  443.     wxASSERT(id < m_num);
  444.  
  445.     return m_nodes[id].m_active;
  446. }
  447.  
  448. wxString wxTreeLayoutStored::HitTest(wxMouseEvent& event, wxDC& dc)
  449. {
  450.     wxPoint pt = event.GetPosition();
  451.     wxCoord x = pt.x;
  452.     wxCoord y = pt.y;
  453.  
  454.     int i;
  455.     for (i = 0; i < m_maxNodes; i++)
  456.     {
  457.         long width, height;
  458.         dc.GetTextExtent(m_nodes[i].m_name, &width, &height);
  459.  
  460.         if ( (x >= (m_nodes[i].m_x-10)) && (x < (m_nodes[i].m_x + width+10)) &&
  461.             (y >= m_nodes[i].m_y-10) && (y < (m_nodes[i].m_y + height+10)) )
  462.         {
  463.             return m_nodes[i].m_name;
  464.         }
  465.     }
  466.  
  467.     return wxString( wxT("") );
  468. }
  469.  
  470. #endif
  471.     // wxUSE_TREELAYOUT
  472.