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