]> git.saurik.com Git - wxWidgets.git/blame - utils/wxtree/src/wxtree.cpp
Cured BC++ makefile bug; wxGrid fix; updated Motif install.txt
[wxWidgets.git] / utils / wxtree / src / wxtree.cpp
CommitLineData
4414cc1d
JS
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
34IMPLEMENT_ABSTRACT_CLASS(wxTreeLayout, wxObject)
35
36wxTreeLayout::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
46void 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
65void wxTreeLayout::Draw(wxDC& dc)
66{
67 dc.Clear();
68 DrawBranches(dc);
69 DrawNodes(dc);
70}
71
72void 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
83void 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
98void 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
113void 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
121void wxTreeLayout::Initialize(void)
122{
123}
124
125void 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
136void 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
246IMPLEMENT_DYNAMIC_CLASS(wxStoredTree, wxTreeLayout)
247
248wxStoredTree::wxStoredTree(int n):wxTreeLayout()
249{
250 m_nodes = NULL;
251 m_maxNodes = 0;
252 Initialize(n);
253}
254
255wxStoredTree::~wxStoredTree(void)
256{
257 if (m_nodes)
258 delete[] m_nodes;
259}
260
261void 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
279long 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
300long 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
309void 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
6dd2244b 320wxStoredNode* wxStoredTree::GetNode(long idx) const
4414cc1d
JS
321{
322 wxASSERT(idx < m_num);
323
324 return &m_nodes[idx];
325};
326
327long wxStoredTree::GetNodeX(long id)
328{
329 wxASSERT(id < m_num);
330
331 return (long)m_nodes[id].m_x;
332}
333
334long wxStoredTree::GetNodeY(long id)
335{
336 wxASSERT(id < m_num);
337
338 return (long)m_nodes[id].m_y;
339}
340
341void wxStoredTree::SetNodeX(long id, long x)
342{
343 wxASSERT(id < m_num);
344
345 m_nodes[id].m_x = (int)x;
346}
347
348void wxStoredTree::SetNodeY(long id, long y)
349{
350 wxASSERT(id < m_num);
351
352 m_nodes[id].m_y = (int)y;
353}
354
355void wxStoredTree::SetNodeName(long id, const wxString& name)
356{
357 wxASSERT(id < m_num);
358
359 m_nodes[id].m_name = name;
360}
361
362wxString wxStoredTree::GetNodeName(long id)
363{
364 wxASSERT(id < m_num);
365
366 return m_nodes[id].m_name;
367}
368
369long 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
381long 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
391void wxStoredTree::SetClientData(long id, long clientData)
392{
393 wxASSERT(id < m_num);
394
395 m_nodes[id].m_clientData = clientData;
396}
397
398long wxStoredTree::GetClientData(long id) const
399{
400 wxASSERT(id < m_num);
401
402 return m_nodes[id].m_clientData;
403}
404
405void wxStoredTree::ActivateNode(long id, bool active)
406{
407 wxASSERT(id < m_num);
408
409 m_nodes[id].m_active = active;
410}
411
412bool wxStoredTree::NodeActive(long id)
413{
414 wxASSERT(id < m_num);
415
416 return m_nodes[id].m_active;
417}
418
419wxString 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}