]> git.saurik.com Git - wxWidgets.git/blame - src/generic/treelay.cpp
changed Refresh to take Rect as client coordinates not window coordinates
[wxWidgets.git] / src / generic / treelay.cpp
CommitLineData
babc9758
JS
1///////////////////////////////////////////////////////////////////////////////
2// Name: treelay.h
3// Purpose: wxTreeLayout class
4// Author: Julian Smart
44845072 5// Modified by:
babc9758
JS
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".
44845072 17#include "wx/wxprec.h"
babc9758
JS
18
19#ifdef __BORLANDC__
20#pragma hdrstop
21#endif
22
23#ifndef WX_PRECOMP
babc9758
JS
24#endif
25
26#if wxUSE_TREELAYOUT
27
44845072 28#include "wx/treelay.h"
babc9758
JS
29
30/*
31 * Abstract tree
32 *
33 */
34
35IMPLEMENT_ABSTRACT_CLASS(wxTreeLayout, wxObject)
36
37wxTreeLayout::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
47void wxTreeLayout::DoLayout(wxDC& dc, long topId)
48{
49 if (topId != -1)
50 SetTopNode(topId);
44845072 51
babc9758
JS
52 long actualTopId = GetTopNode();
53 long id = actualTopId;
54 while (id != -1)
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
66void wxTreeLayout::Draw(wxDC& dc)
67{
68 dc.Clear();
69 DrawBranches(dc);
70 DrawNodes(dc);
71}
72
73void wxTreeLayout::DrawNodes(wxDC& dc)
44845072 74{
babc9758
JS
75 long id = GetTopNode();
76 while (id != -1)
77 {
78 if (NodeActive(id))
79 DrawNode(id, dc);
80 id = GetNextNode(id);
81 }
82}
83
84void wxTreeLayout::DrawBranches(wxDC& dc)
44845072 85{
babc9758
JS
86 long id = GetTopNode();
87 while (id != -1)
88 {
89 if (GetNodeParent(id) > -1)
90 {
91 long parent = GetNodeParent(id);
92 if (NodeActive(parent))
93 DrawBranch(parent, id, dc);
94 }
95 id = GetNextNode(id);
96 }
97}
98
99void wxTreeLayout::DrawNode(long id, wxDC& dc)
100{
f6bcfd97 101 wxChar buf[80];
babc9758 102 wxString name(GetNodeName(id));
f6bcfd97
BP
103 if (name != wxT(""))
104 wxSprintf(buf, wxT("%s"), (const wxChar*) name);
babc9758 105 else
f6bcfd97 106 wxSprintf(buf, wxT("<unnamed>"));
44845072 107
babc9758
JS
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
114void 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
122void wxTreeLayout::Initialize(void)
123{
124}
125
126void wxTreeLayout::GetNodeSize(long id, long *x, long *y, wxDC& dc)
127{
128 wxString name(GetNodeName(id));
f6bcfd97 129 if (name != wxT(""))
babc9758
JS
130 dc.GetTextExtent(name, x, y);
131 else
132 {
133 *x = 70; *y = 20;
134 }
135}
136
137void wxTreeLayout::CalcLayout(long nodeId, int level, wxDC& dc)
138{
139 wxList children;
140 GetChildren(nodeId, children);
141 int n = children.Number();
44845072 142
babc9758
JS
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 != -1)
155 GetNodeSize(parentId, &x, &y, dc);
156 SetNodeX(nodeId, (long)(GetNodeX(parentId) + m_xSpacing + x));
157 }
44845072 158
babc9758
JS
159 wxNode *node = children.First();
160 while (node)
161 {
162 CalcLayout((long)node->Data(), level+1, dc);
163 node = node->Next();
164 }
44845072 165
babc9758
JS
166 // Y Calculations
167 long averageY;
168 ActivateNode(nodeId, TRUE);
44845072 169
babc9758
JS
170 if (n > 0)
171 {
172 averageY = 0;
173 node = children.First();
174 while (node)
175 {
176 averageY += GetNodeY((long)node->Data());
177 node = node->Next();
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);
44845072 187
babc9758
JS
188 m_lastY = m_lastY + y + m_ySpacing;
189 }
190 }
191 else
192 {
193 // Top to bottom
44845072 194
babc9758
JS
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 != -1)
204 GetNodeSize(parentId, &x, &y, dc);
205 SetNodeY(nodeId, (long)(GetNodeY(parentId) + m_ySpacing + y));
206 }
44845072 207
babc9758
JS
208 wxNode *node = children.First();
209 while (node)
210 {
211 CalcLayout((long)node->Data(), level+1, dc);
212 node = node->Next();
213 }
44845072 214
babc9758
JS
215 // X Calculations
216 long averageX;
217 ActivateNode(nodeId, TRUE);
44845072 218
babc9758
JS
219 if (n > 0)
220 {
221 averageX = 0;
222 node = children.First();
223 while (node)
224 {
225 averageX += GetNodeX((long)node->Data());
226 node = node->Next();
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);
44845072 236
babc9758
JS
237 m_lastX = m_lastX + x + m_xSpacing;
238 }
239 }
240}
241
242/*
243 * Tree with storage
244 *
245 */
246
94799627 247IMPLEMENT_DYNAMIC_CLASS(wxTreeLayoutStored, wxTreeLayout)
babc9758 248
94799627 249wxTreeLayoutStored::wxTreeLayoutStored(int n):wxTreeLayout()
babc9758
JS
250{
251 m_nodes = NULL;
252 m_maxNodes = 0;
253 Initialize(n);
254}
255
94799627 256wxTreeLayoutStored::~wxTreeLayoutStored(void)
babc9758
JS
257{
258 if (m_nodes)
259 delete[] m_nodes;
260}
261
94799627 262void wxTreeLayoutStored::Initialize(int n)
babc9758
JS
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 = "";
272 m_nodes[i].m_active = FALSE;
273 m_nodes[i].m_parentId = -1;
274 m_nodes[i].m_x = 0;
275 m_nodes[i].m_y = 0;
276 }
277 m_num = 0;
278}
279
94799627 280long wxTreeLayoutStored::AddChild(const wxString& name, const wxString& parent)
babc9758
JS
281{
282 if (m_num < (m_maxNodes -1 ))
283 {
284 long i = -1;
f6bcfd97 285 if (parent != wxT(""))
babc9758
JS
286 i = NameToId(parent);
287 else m_parentNode = m_num;
44845072 288
babc9758
JS
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 ++;
44845072 294
babc9758
JS
295 return (m_num - 1);
296 }
297 else
298 return -1;
299}
300
94799627 301long wxTreeLayoutStored::NameToId(const wxString& name)
babc9758
JS
302{
303 long i;
304 for (i = 0; i < m_num; i++)
305 if (name == m_nodes[i].m_name)
306 return i;
307 return -1;
308}
309
94799627 310void wxTreeLayoutStored::GetChildren(long id, wxList& list)
babc9758
JS
311{
312 long currentId = GetTopNode();
313 while (currentId != -1)
314 {
315 if (id == GetNodeParent(currentId))
316 list.Append((wxObject *)currentId);
317 currentId = GetNextNode(currentId);
318 }
319}
320
94799627 321wxStoredNode* wxTreeLayoutStored::GetNode(long idx) const
babc9758
JS
322{
323 wxASSERT(idx < m_num);
44845072 324
babc9758
JS
325 return &m_nodes[idx];
326};
327
94799627 328long wxTreeLayoutStored::GetNodeX(long id)
babc9758
JS
329{
330 wxASSERT(id < m_num);
44845072 331
babc9758
JS
332 return (long)m_nodes[id].m_x;
333}
334
94799627 335long wxTreeLayoutStored::GetNodeY(long id)
babc9758
JS
336{
337 wxASSERT(id < m_num);
44845072 338
babc9758
JS
339 return (long)m_nodes[id].m_y;
340}
341
94799627 342void wxTreeLayoutStored::SetNodeX(long id, long x)
babc9758
JS
343{
344 wxASSERT(id < m_num);
44845072 345
babc9758
JS
346 m_nodes[id].m_x = (int)x;
347}
348
94799627 349void wxTreeLayoutStored::SetNodeY(long id, long y)
babc9758
JS
350{
351 wxASSERT(id < m_num);
44845072 352
babc9758
JS
353 m_nodes[id].m_y = (int)y;
354}
355
94799627 356void wxTreeLayoutStored::SetNodeName(long id, const wxString& name)
babc9758
JS
357{
358 wxASSERT(id < m_num);
44845072 359
babc9758
JS
360 m_nodes[id].m_name = name;
361}
362
94799627 363wxString wxTreeLayoutStored::GetNodeName(long id)
babc9758
JS
364{
365 wxASSERT(id < m_num);
44845072 366
babc9758
JS
367 return m_nodes[id].m_name;
368}
369
94799627 370long wxTreeLayoutStored::GetNodeParent(long id)
babc9758
JS
371{
372 if (id != -1)
373 {
374 wxASSERT(id < m_num);
44845072 375
babc9758
JS
376 return m_nodes[id].m_parentId;
377 }
378 else
379 return -1;
380}
381
94799627 382long wxTreeLayoutStored::GetNextNode(long id)
babc9758
JS
383{
384 wxASSERT(id < m_num);
44845072 385
babc9758
JS
386 if ((id != -1) && (id < (m_num - 1)))
387 return id + 1;
388 else
389 return -1;
390}
391
94799627 392void wxTreeLayoutStored::SetClientData(long id, long clientData)
babc9758
JS
393{
394 wxASSERT(id < m_num);
44845072 395
babc9758
JS
396 m_nodes[id].m_clientData = clientData;
397}
398
94799627 399long wxTreeLayoutStored::GetClientData(long id) const
babc9758
JS
400{
401 wxASSERT(id < m_num);
44845072 402
babc9758
JS
403 return m_nodes[id].m_clientData;
404}
405
94799627 406void wxTreeLayoutStored::ActivateNode(long id, bool active)
babc9758
JS
407{
408 wxASSERT(id < m_num);
44845072 409
babc9758
JS
410 m_nodes[id].m_active = active;
411}
412
94799627 413bool wxTreeLayoutStored::NodeActive(long id)
babc9758
JS
414{
415 wxASSERT(id < m_num);
44845072 416
babc9758
JS
417 return m_nodes[id].m_active;
418}
419
94799627 420wxString wxTreeLayoutStored::HitTest(wxMouseEvent& event, wxDC& dc)
babc9758
JS
421{
422 wxPoint pt = event.GetPosition();
423 wxCoord x = pt.x;
424 wxCoord y = pt.y;
44845072 425
babc9758
JS
426 int i;
427 for (i = 0; i < m_maxNodes; i++)
428 {
babc9758
JS
429 long width, height;
430 dc.GetTextExtent(m_nodes[i].m_name, &width, &height);
44845072 431
babc9758
JS
432 if ( (x >= (m_nodes[i].m_x-10)) && (x < (m_nodes[i].m_x + width+10)) &&
433 (y >= m_nodes[i].m_y-10) && (y < (m_nodes[i].m_y + height+10)) )
434 {
435 return m_nodes[i].m_name;
436 }
437 }
44845072 438
babc9758
JS
439 return wxString("");
440}
441
442#endif
443 // wxUSE_TREELAYOUT