]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/deprecated/treelay.cpp
fix for [ 1060093 ] wxURI && wxStringBufferLength part 2 - query and fragment not...
[wxWidgets.git] / contrib / src / deprecated / treelay.cpp
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
39 IMPLEMENT_ABSTRACT_CLASS(wxTreeLayout, wxObject)
40
41 wxTreeLayout::wxTreeLayout()
42 {
43 m_xSpacing = 16;
44 m_ySpacing = 20;
45 m_topMargin = 5;
46 m_leftMargin = 5;
47 m_orientation = false;
48 m_parentNode = 0;
49 }
50
51 void wxTreeLayout::DoLayout(wxDC& dc, long topId)
52 {
53 if (topId != wxID_ANY)
54 SetTopNode(topId);
55
56 long actualTopId = GetTopNode();
57 long id = actualTopId;
58 while (id != wxID_ANY)
59 {
60 SetNodeX(id, 0);
61 SetNodeY(id, 0);
62 ActivateNode(id, false);
63 id = GetNextNode(id);
64 }
65 m_lastY = m_topMargin;
66 m_lastX = m_leftMargin;
67 CalcLayout(actualTopId, 0, dc);
68 }
69
70 void wxTreeLayout::Draw(wxDC& dc)
71 {
72 dc.Clear();
73 DrawBranches(dc);
74 DrawNodes(dc);
75 }
76
77 void wxTreeLayout::DrawNodes(wxDC& dc)
78 {
79 long id = GetTopNode();
80 while (id != wxID_ANY)
81 {
82 if (NodeActive(id))
83 DrawNode(id, dc);
84 id = GetNextNode(id);
85 }
86 }
87
88 void wxTreeLayout::DrawBranches(wxDC& dc)
89 {
90 long id = GetTopNode();
91 while (id != wxID_ANY)
92 {
93 if (GetNodeParent(id) != wxID_ANY)
94 {
95 long parent = GetNodeParent(id);
96 if (NodeActive(parent))
97 DrawBranch(parent, id, dc);
98 }
99 id = GetNextNode(id);
100 }
101 }
102
103 void 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
118 void 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
126 void wxTreeLayout::Initialize(void)
127 {
128 }
129
130 void 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
141 void wxTreeLayout::CalcLayout(long nodeId, int level, wxDC& dc)
142 {
143 wxList children;
144 GetChildren(nodeId, children);
145 int n = children.GetCount();
146
147 if (m_orientation == false)
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);
158 if (parentId != wxID_ANY)
159 GetNodeSize(parentId, &x, &y, dc);
160 SetNodeX(nodeId, (long)(GetNodeX(parentId) + m_xSpacing + x));
161 }
162
163 wxList::compatibility_iterator node = children.GetFirst();
164 while (node)
165 {
166 CalcLayout((long)node->GetData(), level+1, dc);
167 node = node->GetNext();
168 }
169
170 // Y Calculations
171 long averageY;
172 ActivateNode(nodeId, true);
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);
207 if (parentId != wxID_ANY)
208 GetNodeSize(parentId, &x, &y, dc);
209 SetNodeY(nodeId, (long)(GetNodeY(parentId) + m_ySpacing + y));
210 }
211
212 wxList::compatibility_iterator node = children.GetFirst();
213 while (node)
214 {
215 CalcLayout((long)node->GetData(), level+1, dc);
216 node = node->GetNext();
217 }
218
219 // X Calculations
220 long averageX;
221 ActivateNode(nodeId, true);
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
251 IMPLEMENT_DYNAMIC_CLASS(wxTreeLayoutStored, wxTreeLayout)
252
253 wxTreeLayoutStored::wxTreeLayoutStored(int n):wxTreeLayout()
254 {
255 m_nodes = NULL;
256 m_maxNodes = 0;
257 Initialize(n);
258 }
259
260 wxTreeLayoutStored::~wxTreeLayoutStored(void)
261 {
262 if (m_nodes)
263 delete[] m_nodes;
264 }
265
266 void 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("");
276 m_nodes[i].m_active = false;
277 m_nodes[i].m_parentId = wxID_ANY;
278 m_nodes[i].m_x = 0;
279 m_nodes[i].m_y = 0;
280 }
281 m_num = 0;
282 }
283
284 long 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
305 long 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 }
314 else
315 {
316 m_parentNode = m_num;
317 }
318
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 ++;
324
325 return (m_num - 1);
326 }
327 else
328 return -1;
329 }
330
331 long 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
340 void wxTreeLayoutStored::GetChildren(long id, wxList& list)
341 {
342 long currentId = GetTopNode();
343 while (currentId != wxID_ANY)
344 {
345 if (id == GetNodeParent(currentId))
346 list.Append((wxObject *)currentId);
347 currentId = GetNextNode(currentId);
348 }
349 }
350
351 wxStoredNode* wxTreeLayoutStored::GetNode(long idx) const
352 {
353 wxASSERT(idx < m_num);
354
355 return &m_nodes[idx];
356 };
357
358 long wxTreeLayoutStored::GetNodeX(long id)
359 {
360 wxASSERT(id < m_num);
361
362 return (long)m_nodes[id].m_x;
363 }
364
365 long wxTreeLayoutStored::GetNodeY(long id)
366 {
367 wxASSERT(id < m_num);
368
369 return (long)m_nodes[id].m_y;
370 }
371
372 void wxTreeLayoutStored::SetNodeX(long id, long x)
373 {
374 wxASSERT(id < m_num);
375
376 m_nodes[id].m_x = (int)x;
377 }
378
379 void wxTreeLayoutStored::SetNodeY(long id, long y)
380 {
381 wxASSERT(id < m_num);
382
383 m_nodes[id].m_y = (int)y;
384 }
385
386 void wxTreeLayoutStored::SetNodeName(long id, const wxString& name)
387 {
388 wxASSERT(id < m_num);
389
390 m_nodes[id].m_name = name;
391 }
392
393 wxString wxTreeLayoutStored::GetNodeName(long id)
394 {
395 wxASSERT(id < m_num);
396
397 return m_nodes[id].m_name;
398 }
399
400 long wxTreeLayoutStored::GetNodeParent(long id)
401 {
402 if (id != wxID_ANY)
403 {
404 wxASSERT(id < m_num);
405
406 return m_nodes[id].m_parentId;
407 }
408 else
409 return wxNOT_FOUND;
410 }
411
412 long wxTreeLayoutStored::GetNextNode(long id)
413 {
414 wxASSERT(id < m_num);
415
416 if ((id != wxID_ANY) && (id < (m_num - 1)))
417 return id + 1;
418 else
419 return wxNOT_FOUND;
420 }
421
422 void wxTreeLayoutStored::SetClientData(long id, long clientData)
423 {
424 wxASSERT(id < m_num);
425
426 m_nodes[id].m_clientData = clientData;
427 }
428
429 long wxTreeLayoutStored::GetClientData(long id) const
430 {
431 wxASSERT(id < m_num);
432
433 return m_nodes[id].m_clientData;
434 }
435
436 void wxTreeLayoutStored::ActivateNode(long id, bool active)
437 {
438 wxASSERT(id < m_num);
439
440 m_nodes[id].m_active = active;
441 }
442
443 bool wxTreeLayoutStored::NodeActive(long id)
444 {
445 wxASSERT(id < m_num);
446
447 return m_nodes[id].m_active;
448 }
449
450 wxString 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