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