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