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: treelay.cpp 35650 2005-09-23 12:56:45Z MR $ 8// Copyright: (c) 1998 Julian Smart 9// Licence: wxWindows licence 10/////////////////////////////////////////////////////////////////////////////// 11 12// For compilers that support precompilation, includes "wx.h". 13#include "wx/wxprec.h" 14 15#ifdef __BORLANDC__ 16#pragma hdrstop 17#endif 18 19#ifndef WX_PRECOMP 20#include "wx/dc.h" 21#include "wx/event.h" 22#endif 23 24#include "wx/deprecated/setup.h" 25 26#if wxUSE_TREELAYOUT 27 28#include "wx/deprecated/treelay.h" 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 != wxID_ANY) 50 SetTopNode(topId); 51 52 long actualTopId = GetTopNode(); 53 long id = actualTopId; 54 while (id != wxID_ANY) 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) 74{ 75 long id = GetTopNode(); 76 while (id != wxID_ANY) 77 { 78 if (NodeActive(id)) 79 DrawNode(id, dc); 80 id = GetNextNode(id); 81 } 82} 83 84void wxTreeLayout::DrawBranches(wxDC& dc) 85{ 86 long id = GetTopNode(); 87 while (id != wxID_ANY) 88 { 89 if (GetNodeParent(id) != wxID_ANY) 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{ 101 wxChar buf[80]; 102 wxString name(GetNodeName(id)); 103 if (name != wxT("")) 104 wxSprintf(buf, wxT("%s"), (const wxChar*) name); 105 else 106 wxSprintf(buf, wxT("<unnamed>")); 107 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)); 129 if (name != wxT("")) 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.GetCount(); 142 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 != wxID_ANY) 155 GetNodeSize(parentId, &x, &y, dc); 156 SetNodeX(nodeId, (long)(GetNodeX(parentId) + m_xSpacing + x)); 157 } 158 159 wxList::compatibility_iterator node = children.GetFirst(); 160 while (node) 161 { 162 CalcLayout((long)node->GetData(), level+1, dc); 163 node = node->GetNext(); 164 } 165 166 // Y Calculations 167 long averageY; 168 ActivateNode(nodeId, true); 169 170 if (n > 0) 171 { 172 averageY = 0; 173 node = children.GetFirst(); 174 while (node) 175 { 176 averageY += GetNodeY((long)node->GetData()); 177 node = node->GetNext(); 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); 187 188 m_lastY = m_lastY + y + m_ySpacing; 189 } 190 } 191 else 192 { 193 // Top to bottom 194 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 != wxID_ANY) 204 GetNodeSize(parentId, &x, &y, dc); 205 SetNodeY(nodeId, (long)(GetNodeY(parentId) + m_ySpacing + y)); 206 } 207 208 wxList::compatibility_iterator node = children.GetFirst(); 209 while (node) 210 { 211 CalcLayout((long)node->GetData(), level+1, dc); 212 node = node->GetNext(); 213 } 214 215 // X Calculations 216 long averageX; 217 ActivateNode(nodeId, true); 218 219 if (n > 0) 220 { 221 averageX = 0; 222 node = children.GetFirst(); 223 while (node) 224 { 225 averageX += GetNodeX((long)node->GetData()); 226 node = node->GetNext(); 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); 236 237 m_lastX = m_lastX + x + m_xSpacing; 238 } 239 } 240} 241 242/* 243 * Tree with storage 244 * 245 */ 246 247IMPLEMENT_DYNAMIC_CLASS(wxTreeLayoutStored, wxTreeLayout) 248 249wxTreeLayoutStored::wxTreeLayoutStored(int n):wxTreeLayout() 250{ 251 m_nodes = NULL; 252 m_maxNodes = 0; 253 Initialize(n); 254} 255 256wxTreeLayoutStored::~wxTreeLayoutStored(void) 257{ 258 if (m_nodes) 259 delete[] m_nodes; 260} 261 262void wxTreeLayoutStored::Initialize(int n) 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 = wxT(""); 272 m_nodes[i].m_active = false; 273 m_nodes[i].m_parentId = wxID_ANY; 274 m_nodes[i].m_x = 0; 275 m_nodes[i].m_y = 0; 276 } 277 m_num = 0; 278} 279 280long wxTreeLayoutStored::AddChild(const wxString& name, const wxString& parent) 281{ 282 if (m_num < (m_maxNodes -1 )) 283 { 284 long i = -1; 285 if (parent != wxT("")) 286 i = NameToId(parent); 287 else m_parentNode = m_num; 288 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 ++; 294 295 return (m_num - 1); 296 } 297 else 298 return -1; 299} 300 301long wxTreeLayoutStored::AddChild(const wxString& name, long parent) 302{ 303 if (m_num < (m_maxNodes -1 ) && parent < m_num) 304 { 305 long i = -1; 306 if (parent != -1) 307 { 308 i = parent; 309 } 310 else 311 { 312 m_parentNode = m_num; 313 } 314 315 m_nodes[m_num].m_parentId = i; 316 m_nodes[m_num].m_name = name; 317 m_nodes[m_num].m_x = m_nodes[m_num].m_y = 0; 318 m_nodes[m_num].m_clientData = 0; 319 m_num ++; 320 321 return (m_num - 1); 322 } 323 else 324 return -1; 325} 326 327long wxTreeLayoutStored::NameToId(const wxString& name) 328{ 329 long i; 330 for (i = 0; i < m_num; i++) 331 if (name == m_nodes[i].m_name) 332 return i; 333 return -1; 334} 335 336void wxTreeLayoutStored::GetChildren(long id, wxList& list) 337{ 338 long currentId = GetTopNode(); 339 while (currentId != wxID_ANY) 340 { 341 if (id == GetNodeParent(currentId)) 342 list.Append((wxObject *)currentId); 343 currentId = GetNextNode(currentId); 344 } 345} 346 347wxStoredNode* wxTreeLayoutStored::GetNode(long idx) const 348{ 349 wxASSERT(idx < m_num); 350 351 return &m_nodes[idx]; 352}; 353 354long wxTreeLayoutStored::GetNodeX(long id) 355{ 356 wxASSERT(id < m_num); 357 358 return (long)m_nodes[id].m_x; 359} 360 361long wxTreeLayoutStored::GetNodeY(long id) 362{ 363 wxASSERT(id < m_num); 364 365 return (long)m_nodes[id].m_y; 366} 367 368void wxTreeLayoutStored::SetNodeX(long id, long x) 369{ 370 wxASSERT(id < m_num); 371 372 m_nodes[id].m_x = (int)x; 373} 374 375void wxTreeLayoutStored::SetNodeY(long id, long y) 376{ 377 wxASSERT(id < m_num); 378 379 m_nodes[id].m_y = (int)y; 380} 381 382void wxTreeLayoutStored::SetNodeName(long id, const wxString& name) 383{ 384 wxASSERT(id < m_num); 385 386 m_nodes[id].m_name = name; 387} 388 389wxString wxTreeLayoutStored::GetNodeName(long id) 390{ 391 wxASSERT(id < m_num); 392 393 return m_nodes[id].m_name; 394} 395 396long wxTreeLayoutStored::GetNodeParent(long id) 397{ 398 if (id != wxID_ANY) 399 { 400 wxASSERT(id < m_num); 401 402 return m_nodes[id].m_parentId; 403 } 404 else 405 return wxNOT_FOUND; 406} 407 408long wxTreeLayoutStored::GetNextNode(long id) 409{ 410 wxASSERT(id < m_num); 411 412 if ((id != wxID_ANY) && (id < (m_num - 1))) 413 return id + 1; 414 else 415 return wxNOT_FOUND; 416} 417 418void wxTreeLayoutStored::SetClientData(long id, long clientData) 419{ 420 wxASSERT(id < m_num); 421 422 m_nodes[id].m_clientData = clientData; 423} 424 425long wxTreeLayoutStored::GetClientData(long id) const 426{ 427 wxASSERT(id < m_num); 428 429 return m_nodes[id].m_clientData; 430} 431 432void wxTreeLayoutStored::ActivateNode(long id, bool active) 433{ 434 wxASSERT(id < m_num); 435 436 m_nodes[id].m_active = active; 437} 438 439bool wxTreeLayoutStored::NodeActive(long id) 440{ 441 wxASSERT(id < m_num); 442 443 return m_nodes[id].m_active; 444} 445 446wxString wxTreeLayoutStored::HitTest(wxMouseEvent& event, wxDC& dc) 447{ 448 wxPoint pt = event.GetPosition(); 449 wxCoord x = pt.x; 450 wxCoord y = pt.y; 451 452 int i; 453 for (i = 0; i < m_maxNodes; i++) 454 { 455 long width, height; 456 dc.GetTextExtent(m_nodes[i].m_name, &width, &height); 457 458 if ( (x >= (m_nodes[i].m_x-10)) && (x < (m_nodes[i].m_x + width+10)) && 459 (y >= m_nodes[i].m_y-10) && (y < (m_nodes[i].m_y + height+10)) ) 460 { 461 return m_nodes[i].m_name; 462 } 463 } 464 465 return wxString( wxT("") ); 466} 467 468#endif 469 // wxUSE_TREELAYOUT 470