]>
Commit | Line | Data |
---|---|---|
c801d85f KB |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: treectrl.cpp | |
f135ff73 | 3 | // Purpose: generic tree control implementation |
c801d85f KB |
4 | // Author: Robert Roebling |
5 | // Created: 01/02/97 | |
f135ff73 | 6 | // Modified: 22/10/98 - almost total rewrite, simpler interface (VZ) |
389cdc7a | 7 | // Id: $Id$ |
c801d85f | 8 | // Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem |
29d87bba | 9 | // Licence: wxWindows licence |
c801d85f KB |
10 | ///////////////////////////////////////////////////////////////////////////// |
11 | ||
f135ff73 VZ |
12 | // ============================================================================= |
13 | // declarations | |
14 | // ============================================================================= | |
15 | ||
16 | // ----------------------------------------------------------------------------- | |
17 | // headers | |
18 | // ----------------------------------------------------------------------------- | |
19 | ||
c801d85f | 20 | #ifdef __GNUG__ |
f135ff73 | 21 | #pragma implementation "treectrl.h" |
c801d85f KB |
22 | #endif |
23 | ||
24 | #include "wx/treectrl.h" | |
25 | #include "wx/settings.h" | |
389cdc7a | 26 | #include "wx/log.h" |
f135ff73 VZ |
27 | #include "wx/intl.h" |
28 | #include "wx/dynarray.h" | |
29 | #include "wx/dcclient.h" | |
df875e59 | 30 | #include "wx/imaglist.h" |
c801d85f | 31 | |
f135ff73 VZ |
32 | // ----------------------------------------------------------------------------- |
33 | // array types | |
34 | // ----------------------------------------------------------------------------- | |
c801d85f | 35 | |
f135ff73 | 36 | WX_DEFINE_ARRAY(wxGenericTreeItem *, wxArrayTreeItems); |
c801d85f | 37 | |
f135ff73 VZ |
38 | // ----------------------------------------------------------------------------- |
39 | // private classes | |
40 | // ----------------------------------------------------------------------------- | |
41 | ||
42 | // a tree item | |
43 | class WXDLLEXPORT wxGenericTreeItem | |
c801d85f | 44 | { |
f135ff73 VZ |
45 | public: |
46 | // ctors & dtor | |
47 | wxGenericTreeItem() { m_data = NULL; } | |
48 | wxGenericTreeItem( wxGenericTreeItem *parent, | |
49 | const wxString& text, | |
50 | wxDC& dc, | |
51 | int image, int selImage, | |
52 | wxTreeItemData *data ); | |
53 | ||
54 | inline ~wxGenericTreeItem(); | |
55 | ||
56 | // trivial accessors | |
57 | wxArrayTreeItems& GetChildren() { return m_children; } | |
58 | ||
59 | const wxString& GetText() const { return m_text; } | |
60 | int GetImage() const { return m_image; } | |
61 | int GetSelectedImage() const { return m_selImage; } | |
62 | wxTreeItemData *GetData() const { return m_data; } | |
63 | ||
64 | void SetText( const wxString &text, wxDC& dc ); | |
65 | void SetImage(int image) { m_image = image; } | |
66 | void SetSelectedImage(int image) { m_selImage = image; } | |
67 | void SetData(wxTreeItemData *data) { m_data = data; } | |
68 | ||
69 | void SetHasPlus(bool has = TRUE) { m_hasPlus = has; } | |
70 | ||
71 | int GetX() const { return m_x; } | |
72 | int GetY() const { return m_y; } | |
73 | ||
74 | void SetHeight(int h) { m_height = h; } | |
75 | ||
76 | void SetX(int x) { m_x = x; } | |
77 | void SetY(int y) { m_y = y; } | |
78 | ||
79 | wxGenericTreeItem *GetParent() const { return m_parent; } | |
c801d85f | 80 | |
f135ff73 VZ |
81 | // operations |
82 | void Reset(); | |
83 | ||
4832f7c0 VZ |
84 | // get count of all children (and grand children if 'recursively') |
85 | size_t GetChildrenCount(bool recursively = TRUE) const; | |
f135ff73 VZ |
86 | |
87 | void Insert(wxGenericTreeItem *child, size_t index) | |
88 | { m_children.Insert(child, index); } | |
89 | ||
90 | void SetCross( int x, int y ); | |
91 | void GetSize( int &x, int &y ); | |
92 | ||
93 | // return the item at given position (or NULL if no item), onButton is TRUE | |
94 | // if the point belongs to the item's button, otherwise it lies on the | |
95 | // button's label | |
96 | wxGenericTreeItem *HitTest( const wxPoint& point, bool &onButton ); | |
97 | ||
98 | void Expand() { m_isCollapsed = FALSE; } | |
99 | void Collapse() { m_isCollapsed = TRUE; } | |
100 | ||
101 | void SetHilight( bool set = TRUE ) { m_hasHilight = set; } | |
102 | ||
103 | // status inquiries | |
104 | bool HasChildren() const { return !m_children.IsEmpty(); } | |
105 | bool HasHilight() const { return m_hasHilight; } | |
106 | bool IsExpanded() const { return !m_isCollapsed; } | |
107 | bool HasPlus() const { return m_hasPlus || HasChildren(); } | |
108 | ||
109 | private: | |
110 | wxString m_text; | |
111 | ||
112 | int m_image, | |
113 | m_selImage; | |
114 | ||
115 | wxTreeItemData *m_data; | |
4832f7c0 | 116 | |
f135ff73 VZ |
117 | // @@ probably should use bitfields to save size |
118 | bool m_isCollapsed, | |
119 | m_hasHilight, // same as focused | |
120 | m_hasPlus; // used for item which doesn't have | |
121 | // children but still has a [+] button | |
122 | ||
123 | int m_x, m_y; | |
124 | long m_height, m_width; | |
125 | int m_xCross, m_yCross; | |
126 | int m_level; | |
127 | wxArrayTreeItems m_children; | |
128 | wxGenericTreeItem *m_parent; | |
129 | }; | |
130 | ||
131 | // ============================================================================= | |
132 | // implementation | |
133 | // ============================================================================= | |
134 | ||
135 | // ----------------------------------------------------------------------------- | |
c801d85f | 136 | // wxTreeEvent |
f135ff73 | 137 | // ----------------------------------------------------------------------------- |
c801d85f | 138 | |
f135ff73 | 139 | IMPLEMENT_DYNAMIC_CLASS(wxTreeEvent, wxCommandEvent) |
c801d85f | 140 | |
f135ff73 VZ |
141 | wxTreeEvent::wxTreeEvent( wxEventType commandType, int id ) |
142 | : wxCommandEvent( commandType, id ) | |
c801d85f KB |
143 | { |
144 | m_code = 0; | |
f135ff73 | 145 | m_itemOld = (wxGenericTreeItem *)NULL; |
edaa81ae | 146 | } |
c801d85f | 147 | |
f135ff73 | 148 | // ----------------------------------------------------------------------------- |
c801d85f | 149 | // wxGenericTreeItem |
f135ff73 | 150 | // ----------------------------------------------------------------------------- |
c801d85f | 151 | |
f135ff73 VZ |
152 | wxGenericTreeItem::wxGenericTreeItem(wxGenericTreeItem *parent, |
153 | const wxString& text, | |
154 | wxDC& dc, | |
155 | int image, int selImage, | |
156 | wxTreeItemData *data) | |
157 | : m_text(text) | |
c801d85f | 158 | { |
f135ff73 VZ |
159 | m_image = image; |
160 | m_selImage = selImage; | |
161 | m_data = data; | |
162 | m_x = m_y = 0; | |
163 | m_xCross = m_yCross = 0; | |
164 | ||
165 | m_level = 0; | |
166 | ||
167 | m_isCollapsed = TRUE; | |
c801d85f | 168 | m_hasHilight = FALSE; |
df875e59 | 169 | m_hasPlus = FALSE; |
c801d85f | 170 | |
c801d85f | 171 | m_parent = parent; |
f135ff73 VZ |
172 | |
173 | dc.GetTextExtent( m_text, &m_width, &m_height ); | |
edaa81ae | 174 | } |
c801d85f | 175 | |
f135ff73 | 176 | wxGenericTreeItem::~wxGenericTreeItem() |
c801d85f | 177 | { |
f135ff73 | 178 | delete m_data; |
4832f7c0 | 179 | |
f135ff73 VZ |
180 | size_t count = m_children.Count(); |
181 | for ( size_t n = 0; n < count; n++ ) | |
182 | delete m_children[n]; | |
edaa81ae | 183 | } |
c801d85f | 184 | |
f135ff73 | 185 | void wxGenericTreeItem::SetText( const wxString &text, wxDC& dc ) |
c801d85f KB |
186 | { |
187 | m_text = text; | |
f135ff73 VZ |
188 | |
189 | dc.GetTextExtent( m_text, &m_width, &m_height ); | |
edaa81ae | 190 | } |
c801d85f | 191 | |
74bedbeb | 192 | void wxGenericTreeItem::Reset() |
c801d85f | 193 | { |
f135ff73 VZ |
194 | m_text.Empty(); |
195 | m_image = | |
196 | m_selImage = -1; | |
197 | m_data = NULL; | |
198 | m_x = m_y = | |
199 | m_height = m_width = 0; | |
200 | m_xCross = | |
c801d85f | 201 | m_yCross = 0; |
74bedbeb | 202 | |
f135ff73 | 203 | m_level = 0; |
c801d85f | 204 | |
f135ff73 VZ |
205 | m_children.Empty(); |
206 | m_isCollapsed = TRUE; | |
c801d85f | 207 | |
f135ff73 | 208 | m_parent = (wxGenericTreeItem *)NULL; |
edaa81ae | 209 | } |
c801d85f | 210 | |
4832f7c0 | 211 | size_t wxGenericTreeItem::GetChildrenCount(bool recursively) const |
c801d85f | 212 | { |
f135ff73 | 213 | size_t count = m_children.Count(); |
4832f7c0 VZ |
214 | if ( !recursively ) |
215 | return count; | |
216 | ||
f135ff73 VZ |
217 | size_t total = count; |
218 | for ( size_t n = 0; n < count; n++ ) | |
c801d85f | 219 | { |
4832f7c0 | 220 | total += m_children[n]->GetChildrenCount(); |
edaa81ae | 221 | } |
c801d85f | 222 | |
f135ff73 | 223 | return total; |
edaa81ae | 224 | } |
c801d85f KB |
225 | |
226 | void wxGenericTreeItem::SetCross( int x, int y ) | |
227 | { | |
228 | m_xCross = x; | |
229 | m_yCross = y; | |
edaa81ae | 230 | } |
c801d85f KB |
231 | |
232 | void wxGenericTreeItem::GetSize( int &x, int &y ) | |
233 | { | |
f135ff73 | 234 | // FIXME what does this all mean?? |
df875e59 | 235 | if ( y < m_y ) y = m_y; |
c801d85f KB |
236 | int width = m_x + m_width; |
237 | if (width > x) x = width; | |
f135ff73 | 238 | |
df875e59 | 239 | if (IsExpanded()) |
c801d85f | 240 | { |
df875e59 RR |
241 | size_t count = m_children.Count(); |
242 | for ( size_t n = 0; n < count; n++ ) | |
4832f7c0 | 243 | { |
df875e59 RR |
244 | m_children[n]->GetSize( x, y ); |
245 | } | |
edaa81ae RR |
246 | } |
247 | } | |
c801d85f | 248 | |
f135ff73 VZ |
249 | wxGenericTreeItem *wxGenericTreeItem::HitTest( const wxPoint& point, |
250 | bool &onButton ) | |
c801d85f | 251 | { |
f135ff73 | 252 | if ((point.y > m_y) && (point.y < m_y + m_height)) |
c801d85f | 253 | { |
f135ff73 VZ |
254 | // FIXME why +5? |
255 | if ((point.x > m_xCross-5) && (point.x < m_xCross+5) && | |
256 | (point.y > m_yCross-5) && (point.y < m_yCross+5) && | |
f9f950fc | 257 | (IsExpanded() || HasPlus())) |
c801d85f | 258 | { |
f135ff73 VZ |
259 | onButton = TRUE; |
260 | return this; | |
edaa81ae | 261 | } |
f135ff73 | 262 | |
c801d85f KB |
263 | if ((point.x > m_x) && (point.x < m_x+m_width)) |
264 | { | |
f135ff73 VZ |
265 | onButton = FALSE; |
266 | return this; | |
edaa81ae | 267 | } |
c801d85f KB |
268 | } |
269 | else | |
270 | { | |
e2414cbe | 271 | if (!m_isCollapsed) |
c801d85f | 272 | { |
f135ff73 VZ |
273 | size_t count = m_children.Count(); |
274 | for ( size_t n = 0; n < count; n++ ) | |
e2414cbe | 275 | { |
f135ff73 VZ |
276 | wxGenericTreeItem *res = m_children[n]->HitTest( point, onButton ); |
277 | if ( res != NULL ) | |
278 | return res; | |
edaa81ae RR |
279 | } |
280 | } | |
281 | } | |
f135ff73 VZ |
282 | |
283 | return NULL; | |
edaa81ae | 284 | } |
c801d85f | 285 | |
f135ff73 VZ |
286 | // ----------------------------------------------------------------------------- |
287 | // wxTreeCtrl implementation | |
288 | // ----------------------------------------------------------------------------- | |
289 | ||
290 | IMPLEMENT_DYNAMIC_CLASS(wxTreeCtrl, wxScrolledWindow) | |
291 | ||
292 | BEGIN_EVENT_TABLE(wxTreeCtrl,wxScrolledWindow) | |
293 | EVT_PAINT (wxTreeCtrl::OnPaint) | |
294 | EVT_MOUSE_EVENTS (wxTreeCtrl::OnMouse) | |
295 | EVT_CHAR (wxTreeCtrl::OnChar) | |
296 | EVT_SET_FOCUS (wxTreeCtrl::OnSetFocus) | |
297 | EVT_KILL_FOCUS (wxTreeCtrl::OnKillFocus) | |
298 | END_EVENT_TABLE() | |
299 | ||
300 | // ----------------------------------------------------------------------------- | |
301 | // construction/destruction | |
302 | // ----------------------------------------------------------------------------- | |
303 | void wxTreeCtrl::Init() | |
c801d85f | 304 | { |
f135ff73 VZ |
305 | m_current = |
306 | m_anchor = (wxGenericTreeItem *) NULL; | |
307 | m_hasFocus = FALSE; | |
308 | ||
309 | m_xScroll = 0; | |
310 | m_yScroll = 0; | |
311 | m_lineHeight = 10; | |
312 | m_indent = 15; | |
313 | ||
314 | m_hilightBrush = new wxBrush | |
315 | ( | |
316 | wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHT), | |
317 | wxSOLID | |
318 | ); | |
319 | ||
320 | m_imageListNormal = | |
321 | m_imageListState = (wxImageList *) NULL; | |
edaa81ae | 322 | } |
c801d85f | 323 | |
f135ff73 VZ |
324 | bool wxTreeCtrl::Create(wxWindow *parent, wxWindowID id, |
325 | const wxPoint& pos, const wxSize& size, | |
326 | long style, const wxString& name ) | |
c801d85f | 327 | { |
f135ff73 VZ |
328 | Init(); |
329 | ||
330 | wxScrolledWindow::Create( parent, id, pos, size, style, name ); | |
331 | ||
332 | SetBackgroundColour( *wxWHITE ); | |
333 | m_dottedPen = wxPen( *wxBLACK, 0, 0 ); | |
334 | ||
335 | return TRUE; | |
edaa81ae | 336 | } |
c801d85f | 337 | |
f135ff73 | 338 | wxTreeCtrl::~wxTreeCtrl() |
c801d85f | 339 | { |
f135ff73 VZ |
340 | wxDELETE( m_hilightBrush ); |
341 | wxDELETE( m_anchor ); | |
edaa81ae | 342 | } |
c801d85f | 343 | |
f135ff73 VZ |
344 | // ----------------------------------------------------------------------------- |
345 | // accessors | |
346 | // ----------------------------------------------------------------------------- | |
347 | ||
348 | size_t wxTreeCtrl::GetCount() const | |
c801d85f | 349 | { |
4832f7c0 | 350 | return m_anchor == NULL ? 0u : m_anchor->GetChildrenCount(); |
edaa81ae | 351 | } |
c801d85f | 352 | |
f135ff73 | 353 | void wxTreeCtrl::SetIndent(unsigned int indent) |
c801d85f | 354 | { |
f135ff73 VZ |
355 | m_indent = indent; |
356 | Refresh(); | |
357 | } | |
74bedbeb | 358 | |
4832f7c0 VZ |
359 | size_t wxTreeCtrl::GetChildrenCount(const wxTreeItemId& item, bool recursively) |
360 | { | |
361 | wxCHECK_MSG( item.IsOk(), 0u, "invalid tree item" ); | |
362 | ||
363 | return item.m_pItem->GetChildrenCount(recursively); | |
364 | } | |
365 | ||
f135ff73 VZ |
366 | // ----------------------------------------------------------------------------- |
367 | // functions to work with tree items | |
368 | // ----------------------------------------------------------------------------- | |
74bedbeb | 369 | |
f135ff73 VZ |
370 | wxString wxTreeCtrl::GetItemText(const wxTreeItemId& item) const |
371 | { | |
4832f7c0 VZ |
372 | wxCHECK_MSG( item.IsOk(), "", "invalid tree item" ); |
373 | ||
f135ff73 | 374 | return item.m_pItem->GetText(); |
edaa81ae | 375 | } |
74bedbeb | 376 | |
f135ff73 | 377 | int wxTreeCtrl::GetItemImage(const wxTreeItemId& item) const |
74bedbeb | 378 | { |
4832f7c0 VZ |
379 | wxCHECK_MSG( item.IsOk(), -1, "invalid tree item" ); |
380 | ||
f135ff73 | 381 | return item.m_pItem->GetImage(); |
edaa81ae | 382 | } |
c801d85f | 383 | |
f135ff73 | 384 | int wxTreeCtrl::GetItemSelectedImage(const wxTreeItemId& item) const |
c801d85f | 385 | { |
4832f7c0 VZ |
386 | wxCHECK_MSG( item.IsOk(), -1, "invalid tree item" ); |
387 | ||
f135ff73 | 388 | return item.m_pItem->GetSelectedImage(); |
edaa81ae | 389 | } |
c801d85f | 390 | |
f135ff73 | 391 | wxTreeItemData *wxTreeCtrl::GetItemData(const wxTreeItemId& item) const |
c801d85f | 392 | { |
4832f7c0 VZ |
393 | wxCHECK_MSG( item.IsOk(), NULL, "invalid tree item" ); |
394 | ||
f135ff73 | 395 | return item.m_pItem->GetData(); |
edaa81ae | 396 | } |
c801d85f | 397 | |
f135ff73 VZ |
398 | void wxTreeCtrl::SetItemText(const wxTreeItemId& item, const wxString& text) |
399 | { | |
4832f7c0 VZ |
400 | wxCHECK_RET( item.IsOk(), "invalid tree item" ); |
401 | ||
f135ff73 | 402 | wxClientDC dc(this); |
de646ed1 | 403 | item.m_pItem->SetText(text, dc); |
f135ff73 | 404 | } |
c801d85f | 405 | |
f135ff73 VZ |
406 | void wxTreeCtrl::SetItemImage(const wxTreeItemId& item, int image) |
407 | { | |
4832f7c0 VZ |
408 | wxCHECK_RET( item.IsOk(), "invalid tree item" ); |
409 | ||
de646ed1 | 410 | item.m_pItem->SetImage(image); |
f135ff73 | 411 | } |
c801d85f | 412 | |
f135ff73 | 413 | void wxTreeCtrl::SetItemSelectedImage(const wxTreeItemId& item, int image) |
c801d85f | 414 | { |
4832f7c0 VZ |
415 | wxCHECK_RET( item.IsOk(), "invalid tree item" ); |
416 | ||
de646ed1 | 417 | item.m_pItem->SetSelectedImage(image); |
edaa81ae | 418 | } |
c801d85f | 419 | |
f135ff73 | 420 | void wxTreeCtrl::SetItemData(const wxTreeItemId& item, wxTreeItemData *data) |
c801d85f | 421 | { |
4832f7c0 VZ |
422 | wxCHECK_RET( item.IsOk(), "invalid tree item" ); |
423 | ||
de646ed1 | 424 | item.m_pItem->SetData(data); |
edaa81ae | 425 | } |
c801d85f | 426 | |
f135ff73 | 427 | void wxTreeCtrl::SetItemHasChildren(const wxTreeItemId& item, bool has) |
c801d85f | 428 | { |
4832f7c0 VZ |
429 | wxCHECK_RET( item.IsOk(), "invalid tree item" ); |
430 | ||
f135ff73 | 431 | item.m_pItem->SetHasPlus(has); |
edaa81ae | 432 | } |
c801d85f | 433 | |
f135ff73 VZ |
434 | // ----------------------------------------------------------------------------- |
435 | // item status inquiries | |
436 | // ----------------------------------------------------------------------------- | |
437 | ||
df875e59 | 438 | bool wxTreeCtrl::IsVisible(const wxTreeItemId& WXUNUSED(item)) const |
c801d85f | 439 | { |
f135ff73 VZ |
440 | wxFAIL_MSG("not implemented"); |
441 | ||
c801d85f | 442 | return TRUE; |
edaa81ae | 443 | } |
c801d85f | 444 | |
f135ff73 | 445 | bool wxTreeCtrl::ItemHasChildren(const wxTreeItemId& item) const |
c801d85f | 446 | { |
4832f7c0 VZ |
447 | wxCHECK_MSG( item.IsOk(), FALSE, "invalid tree item" ); |
448 | ||
f135ff73 | 449 | return !item.m_pItem->GetChildren().IsEmpty(); |
edaa81ae | 450 | } |
c801d85f | 451 | |
f135ff73 | 452 | bool wxTreeCtrl::IsExpanded(const wxTreeItemId& item) const |
c801d85f | 453 | { |
4832f7c0 VZ |
454 | wxCHECK_MSG( item.IsOk(), FALSE, "invalid tree item" ); |
455 | ||
f135ff73 VZ |
456 | return item.m_pItem->IsExpanded(); |
457 | } | |
29d87bba | 458 | |
f135ff73 VZ |
459 | bool wxTreeCtrl::IsSelected(const wxTreeItemId& item) const |
460 | { | |
4832f7c0 VZ |
461 | wxCHECK_MSG( item.IsOk(), FALSE, "invalid tree item" ); |
462 | ||
f135ff73 VZ |
463 | return item.m_pItem->HasHilight(); |
464 | } | |
29d87bba | 465 | |
f135ff73 VZ |
466 | // ----------------------------------------------------------------------------- |
467 | // navigation | |
468 | // ----------------------------------------------------------------------------- | |
29d87bba | 469 | |
f135ff73 VZ |
470 | wxTreeItemId wxTreeCtrl::GetParent(const wxTreeItemId& item) const |
471 | { | |
472 | wxCHECK_MSG( item.IsOk(), NULL, "invalid tree item" ); | |
389cdc7a | 473 | |
f135ff73 VZ |
474 | return item.m_pItem->GetParent(); |
475 | } | |
29d87bba | 476 | |
f135ff73 VZ |
477 | wxTreeItemId wxTreeCtrl::GetFirstChild(const wxTreeItemId& item, long& cookie) const |
478 | { | |
479 | wxCHECK_MSG( item.IsOk(), NULL, "invalid tree item" ); | |
29d87bba | 480 | |
f135ff73 VZ |
481 | cookie = 0; |
482 | return GetNextChild(item, cookie); | |
483 | } | |
29d87bba | 484 | |
f135ff73 VZ |
485 | wxTreeItemId wxTreeCtrl::GetNextChild(const wxTreeItemId& item, long& cookie) const |
486 | { | |
487 | wxCHECK_MSG( item.IsOk(), NULL, "invalid tree item" ); | |
29d87bba | 488 | |
4832f7c0 VZ |
489 | wxArrayTreeItems& children = item.m_pItem->GetChildren(); |
490 | if ( (size_t)cookie < children.Count() ) | |
491 | { | |
492 | return item.m_pItem->GetChildren().Item(cookie++); | |
493 | } | |
494 | else | |
495 | { | |
496 | // there are no more of them | |
497 | return NULL; | |
498 | } | |
f135ff73 | 499 | } |
29d87bba | 500 | |
f135ff73 VZ |
501 | wxTreeItemId wxTreeCtrl::GetNextSibling(const wxTreeItemId& item) const |
502 | { | |
503 | wxCHECK_MSG( item.IsOk(), NULL, "invalid tree item" ); | |
504 | ||
505 | wxGenericTreeItem *i = item.m_pItem; | |
506 | wxGenericTreeItem *parent = i->GetParent(); | |
507 | if ( parent == NULL ) | |
508 | { | |
509 | // root item doesn't have any siblings | |
510 | return NULL; | |
edaa81ae | 511 | } |
4832f7c0 | 512 | |
f135ff73 VZ |
513 | wxArrayTreeItems& siblings = parent->GetChildren(); |
514 | int index = siblings.Index(i); | |
515 | wxASSERT( index != NOT_FOUND ); // I'm not a child of my parent? | |
29d87bba | 516 | |
f135ff73 | 517 | size_t n = (size_t)(index + 1); |
de646ed1 | 518 | return n == siblings.Count() ? (wxGenericTreeItem*)NULL : siblings[n]; |
edaa81ae | 519 | } |
c801d85f | 520 | |
f135ff73 | 521 | wxTreeItemId wxTreeCtrl::GetPrevSibling(const wxTreeItemId& item) const |
c801d85f | 522 | { |
f135ff73 VZ |
523 | wxCHECK_MSG( item.IsOk(), NULL, "invalid tree item" ); |
524 | ||
525 | wxGenericTreeItem *i = item.m_pItem; | |
526 | wxGenericTreeItem *parent = i->GetParent(); | |
527 | if ( parent == NULL ) | |
c801d85f | 528 | { |
f135ff73 VZ |
529 | // root item doesn't have any siblings |
530 | return NULL; | |
edaa81ae | 531 | } |
4832f7c0 | 532 | |
f135ff73 VZ |
533 | wxArrayTreeItems& siblings = parent->GetChildren(); |
534 | int index = siblings.Index(i); | |
535 | wxASSERT( index != NOT_FOUND ); // I'm not a child of my parent? | |
29d87bba | 536 | |
de646ed1 | 537 | return index == 0 ? (wxGenericTreeItem*)NULL : siblings[(size_t)(index - 1)]; |
f135ff73 | 538 | } |
389cdc7a | 539 | |
f135ff73 VZ |
540 | wxTreeItemId wxTreeCtrl::GetFirstVisibleItem() const |
541 | { | |
542 | wxFAIL_MSG("not implemented"); | |
29d87bba | 543 | |
f135ff73 VZ |
544 | return NULL; |
545 | } | |
29d87bba | 546 | |
f135ff73 VZ |
547 | wxTreeItemId wxTreeCtrl::GetNextVisible(const wxTreeItemId& item) const |
548 | { | |
549 | wxCHECK_MSG( item.IsOk(), NULL, "invalid tree item" ); | |
29d87bba | 550 | |
f135ff73 | 551 | wxFAIL_MSG("not implemented"); |
29d87bba | 552 | |
f135ff73 VZ |
553 | return NULL; |
554 | } | |
29d87bba | 555 | |
f135ff73 VZ |
556 | wxTreeItemId wxTreeCtrl::GetPrevVisible(const wxTreeItemId& item) const |
557 | { | |
558 | wxCHECK_MSG( item.IsOk(), NULL, "invalid tree item" ); | |
29d87bba | 559 | |
f135ff73 | 560 | wxFAIL_MSG("not implemented"); |
29d87bba | 561 | |
f135ff73 | 562 | return NULL; |
edaa81ae | 563 | } |
c801d85f | 564 | |
f135ff73 VZ |
565 | // ----------------------------------------------------------------------------- |
566 | // operations | |
567 | // ----------------------------------------------------------------------------- | |
568 | ||
569 | wxTreeItemId wxTreeCtrl::DoInsertItem(const wxTreeItemId& parentId, | |
570 | size_t previous, | |
571 | const wxString& text, | |
572 | int image, int selImage, | |
573 | wxTreeItemData *data) | |
c801d85f | 574 | { |
f135ff73 VZ |
575 | wxGenericTreeItem *parent = parentId.m_pItem; |
576 | if ( !parent ) | |
577 | { | |
578 | // should we give a warning here? | |
579 | return AddRoot(text, image, selImage, data); | |
580 | } | |
4832f7c0 | 581 | |
f135ff73 VZ |
582 | wxClientDC dc(this); |
583 | wxGenericTreeItem *item = new wxGenericTreeItem(parent, | |
584 | text, dc, | |
585 | image, selImage, | |
586 | data); | |
74bedbeb | 587 | |
f135ff73 | 588 | if ( data != NULL ) |
c801d85f | 589 | { |
f135ff73 VZ |
590 | data->m_pItem = item; |
591 | } | |
74bedbeb | 592 | |
f135ff73 | 593 | parent->Insert( item, previous ); |
29d87bba | 594 | |
f135ff73 | 595 | CalculatePositions(); |
389cdc7a | 596 | |
f135ff73 VZ |
597 | int cw, ch; |
598 | GetClientSize( &cw, &ch ); | |
74bedbeb | 599 | |
f135ff73 | 600 | PrepareDC( dc ); |
74bedbeb | 601 | |
f135ff73 | 602 | wxRectangle rect; |
4832f7c0 | 603 | rect.x = dc.LogicalToDeviceX( 0 ); |
f135ff73 VZ |
604 | rect.y = 0; |
605 | rect.width = 10000; // @@@ not very elegant... | |
d4c99d6f | 606 | rect.height = ch; |
74bedbeb | 607 | |
f135ff73 VZ |
608 | if ( previous != 0 ) |
609 | { | |
610 | rect.y = dc.LogicalToDeviceY( parent->GetChildren().Item(previous)->GetY() ); | |
611 | } | |
612 | else // it's the 1st child | |
613 | { | |
614 | rect.y = dc.LogicalToDeviceY( parent->GetY() ); | |
615 | } | |
c801d85f | 616 | |
f135ff73 | 617 | AdjustMyScrollbars(); |
389cdc7a | 618 | |
f135ff73 VZ |
619 | if ( rect.height > 0 ) |
620 | Refresh( FALSE, &rect ); | |
389cdc7a | 621 | |
f135ff73 | 622 | return item; |
4c681997 RR |
623 | } |
624 | ||
f135ff73 VZ |
625 | wxTreeItemId wxTreeCtrl::AddRoot(const wxString& text, |
626 | int image, int selImage, | |
627 | wxTreeItemData *data) | |
4c681997 | 628 | { |
f135ff73 | 629 | wxCHECK_MSG( !m_anchor, NULL, "tree can have only one root" ); |
389cdc7a | 630 | |
f135ff73 VZ |
631 | wxClientDC dc(this); |
632 | m_anchor = new wxGenericTreeItem((wxGenericTreeItem *)NULL, text, dc, | |
633 | image, selImage, data); | |
634 | if ( data != NULL ) | |
635 | { | |
636 | data->m_pItem = m_anchor; | |
637 | } | |
389cdc7a | 638 | |
f135ff73 | 639 | AdjustMyScrollbars(); |
a32dd690 | 640 | Refresh(); |
a32dd690 | 641 | |
f135ff73 | 642 | return m_anchor; |
edaa81ae | 643 | } |
c801d85f | 644 | |
f135ff73 VZ |
645 | wxTreeItemId wxTreeCtrl::PrependItem(const wxTreeItemId& parent, |
646 | const wxString& text, | |
647 | int image, int selImage, | |
648 | wxTreeItemData *data) | |
c801d85f | 649 | { |
f135ff73 | 650 | return DoInsertItem(parent, 0u, text, image, selImage, data); |
edaa81ae | 651 | } |
c801d85f | 652 | |
f135ff73 VZ |
653 | wxTreeItemId wxTreeCtrl::InsertItem(const wxTreeItemId& parentId, |
654 | const wxTreeItemId& idPrevious, | |
655 | const wxString& text, | |
656 | int image, int selImage, | |
657 | wxTreeItemData *data) | |
c801d85f | 658 | { |
f135ff73 VZ |
659 | wxGenericTreeItem *parent = parentId.m_pItem; |
660 | if ( !parent ) | |
661 | { | |
662 | // should we give a warning here? | |
663 | return AddRoot(text, image, selImage, data); | |
664 | } | |
c801d85f | 665 | |
f135ff73 VZ |
666 | int index = parent->GetChildren().Index(idPrevious.m_pItem); |
667 | wxASSERT_MSG( index != NOT_FOUND, | |
668 | "previous item in wxTreeCtrl::InsertItem() is not a sibling" ); | |
669 | return DoInsertItem(parentId, (size_t)index, text, image, selImage, data); | |
edaa81ae | 670 | } |
c801d85f | 671 | |
f135ff73 VZ |
672 | wxTreeItemId wxTreeCtrl::AppendItem(const wxTreeItemId& parentId, |
673 | const wxString& text, | |
674 | int image, int selImage, | |
675 | wxTreeItemData *data) | |
74bedbeb | 676 | { |
f135ff73 VZ |
677 | wxGenericTreeItem *parent = parentId.m_pItem; |
678 | if ( !parent ) | |
679 | { | |
680 | // should we give a warning here? | |
681 | return AddRoot(text, image, selImage, data); | |
682 | } | |
683 | ||
684 | return DoInsertItem(parent, parent->GetChildren().Count(), text, | |
685 | image, selImage, data); | |
74bedbeb VZ |
686 | } |
687 | ||
f135ff73 | 688 | void wxTreeCtrl::Delete(const wxTreeItemId& itemId) |
c801d85f | 689 | { |
f135ff73 VZ |
690 | wxGenericTreeItem *item = itemId.m_pItem; |
691 | ||
692 | delete item; | |
693 | ||
694 | Refresh(); | |
edaa81ae | 695 | } |
c801d85f | 696 | |
f135ff73 | 697 | void wxTreeCtrl::DeleteAllItems() |
c801d85f | 698 | { |
f135ff73 VZ |
699 | if ( m_anchor ) |
700 | { | |
701 | delete m_anchor; | |
702 | m_anchor = NULL; | |
703 | ||
704 | Refresh(); | |
705 | } | |
edaa81ae RR |
706 | } |
707 | ||
f135ff73 | 708 | void wxTreeCtrl::Expand(const wxTreeItemId& itemId) |
edaa81ae | 709 | { |
f135ff73 VZ |
710 | wxGenericTreeItem *item = itemId.m_pItem; |
711 | ||
712 | if ( item->IsExpanded() ) | |
713 | return; | |
714 | ||
715 | wxTreeEvent event( wxEVT_COMMAND_TREE_ITEM_EXPANDING, GetId() ); | |
716 | event.m_item = item; | |
717 | event.SetEventObject( this ); | |
718 | if ( ProcessEvent( event ) && event.m_code ) | |
719 | { | |
720 | // cancelled by program | |
721 | return; | |
722 | } | |
4832f7c0 | 723 | |
f135ff73 VZ |
724 | item->Expand(); |
725 | ||
726 | RefreshSubtree(item); | |
727 | ||
728 | event.SetEventType(wxEVT_COMMAND_TREE_ITEM_EXPANDED); | |
729 | ProcessEvent( event ); | |
edaa81ae RR |
730 | } |
731 | ||
f135ff73 | 732 | void wxTreeCtrl::Collapse(const wxTreeItemId& itemId) |
edaa81ae | 733 | { |
f135ff73 VZ |
734 | wxGenericTreeItem *item = itemId.m_pItem; |
735 | ||
736 | if ( !item->IsExpanded() ) | |
737 | return; | |
738 | ||
739 | wxTreeEvent event( wxEVT_COMMAND_TREE_ITEM_COLLAPSING, GetId() ); | |
740 | event.m_item = item; | |
741 | event.SetEventObject( this ); | |
742 | if ( ProcessEvent( event ) && event.m_code ) | |
edaa81ae | 743 | { |
f135ff73 VZ |
744 | // cancelled by program |
745 | return; | |
746 | } | |
4832f7c0 | 747 | |
f135ff73 VZ |
748 | item->Collapse(); |
749 | ||
750 | wxArrayTreeItems& children = item->GetChildren(); | |
751 | size_t count = children.Count(); | |
752 | for ( size_t n = 0; n < count; n++ ) | |
753 | { | |
754 | Collapse(children[n]); | |
edaa81ae | 755 | } |
f135ff73 VZ |
756 | |
757 | CalculatePositions(); | |
758 | ||
759 | RefreshSubtree(item); | |
760 | ||
761 | event.SetEventType(wxEVT_COMMAND_TREE_ITEM_COLLAPSED); | |
762 | ProcessEvent( event ); | |
edaa81ae | 763 | } |
c801d85f | 764 | |
f135ff73 | 765 | void wxTreeCtrl::CollapseAndReset(const wxTreeItemId& item) |
c801d85f | 766 | { |
f135ff73 VZ |
767 | Collapse(item); |
768 | Delete(item); | |
edaa81ae | 769 | } |
c801d85f | 770 | |
f135ff73 | 771 | void wxTreeCtrl::Toggle(const wxTreeItemId& itemId) |
c801d85f | 772 | { |
f135ff73 | 773 | wxGenericTreeItem *item = itemId.m_pItem; |
389cdc7a | 774 | |
f135ff73 VZ |
775 | if ( item->IsExpanded() ) |
776 | Collapse(itemId); | |
777 | else | |
778 | Expand(itemId); | |
779 | } | |
389cdc7a | 780 | |
f135ff73 VZ |
781 | void wxTreeCtrl::Unselect() |
782 | { | |
783 | if ( m_current ) | |
784 | { | |
785 | m_current->SetHilight( FALSE ); | |
786 | RefreshLine( m_current ); | |
787 | } | |
edaa81ae | 788 | } |
c801d85f | 789 | |
f135ff73 | 790 | void wxTreeCtrl::SelectItem(const wxTreeItemId& itemId) |
389cdc7a | 791 | { |
f135ff73 VZ |
792 | wxGenericTreeItem *item = itemId.m_pItem; |
793 | ||
794 | if ( m_current != item ) | |
389cdc7a | 795 | { |
f135ff73 VZ |
796 | wxTreeEvent event( wxEVT_COMMAND_TREE_SEL_CHANGING, GetId() ); |
797 | event.m_item = item; | |
798 | event.m_itemOld = m_current; | |
799 | event.SetEventObject( this ); | |
800 | if ( ProcessEvent( event ) && event.WasVetoed() ) | |
801 | return; | |
802 | ||
803 | if ( m_current ) | |
389cdc7a VZ |
804 | { |
805 | m_current->SetHilight( FALSE ); | |
806 | RefreshLine( m_current ); | |
edaa81ae | 807 | } |
f135ff73 | 808 | |
389cdc7a VZ |
809 | m_current = item; |
810 | m_current->SetHilight( TRUE ); | |
811 | RefreshLine( m_current ); | |
812 | ||
f135ff73 VZ |
813 | event.SetEventType(wxEVT_COMMAND_TREE_SEL_CHANGED); |
814 | ProcessEvent( event ); | |
389cdc7a VZ |
815 | } |
816 | } | |
817 | ||
df875e59 | 818 | void wxTreeCtrl::EnsureVisible(const wxTreeItemId& WXUNUSED(item)) |
c801d85f | 819 | { |
f135ff73 | 820 | wxFAIL_MSG("not implemented"); |
edaa81ae | 821 | } |
c801d85f | 822 | |
df875e59 | 823 | void wxTreeCtrl::ScrollTo(const wxTreeItemId& WXUNUSED(item)) |
c801d85f | 824 | { |
f135ff73 | 825 | wxFAIL_MSG("not implemented"); |
edaa81ae | 826 | } |
c801d85f | 827 | |
df875e59 RR |
828 | wxTextCtrl *wxTreeCtrl::EditLabel( const wxTreeItemId& WXUNUSED(item), |
829 | wxClassInfo* WXUNUSED(textCtrlClass) ) | |
c801d85f | 830 | { |
f135ff73 | 831 | wxFAIL_MSG("not implemented"); |
c801d85f | 832 | |
f135ff73 | 833 | return NULL; |
edaa81ae | 834 | } |
c801d85f | 835 | |
f135ff73 | 836 | wxTextCtrl *wxTreeCtrl::GetEditControl() const |
c801d85f | 837 | { |
f135ff73 | 838 | wxFAIL_MSG("not implemented"); |
c801d85f | 839 | |
f135ff73 | 840 | return NULL; |
edaa81ae | 841 | } |
c801d85f | 842 | |
df875e59 | 843 | void wxTreeCtrl::EndEditLabel(const wxTreeItemId& WXUNUSED(item), bool WXUNUSED(discardChanges)) |
74bedbeb | 844 | { |
f135ff73 | 845 | wxFAIL_MSG("not implemented"); |
74bedbeb VZ |
846 | } |
847 | ||
df875e59 RR |
848 | void wxTreeCtrl::SortChildren( const wxTreeItemId& WXUNUSED(item), |
849 | wxTreeItemCmpFunc *WXUNUSED(cmpFunction)) | |
edaa81ae | 850 | { |
f135ff73 | 851 | wxFAIL_MSG("not implemented"); |
edaa81ae RR |
852 | } |
853 | ||
f135ff73 VZ |
854 | // ----------------------------------------------------------------------------- |
855 | // images are not currently supported, but we still provide stubs for these | |
856 | // functions | |
857 | // ----------------------------------------------------------------------------- | |
858 | wxImageList *wxTreeCtrl::GetImageList() const | |
edaa81ae | 859 | { |
f135ff73 | 860 | return m_imageListNormal; |
edaa81ae RR |
861 | } |
862 | ||
f135ff73 | 863 | wxImageList *wxTreeCtrl::GetStateImageList() const |
c801d85f | 864 | { |
f135ff73 | 865 | return m_imageListState; |
edaa81ae | 866 | } |
c801d85f | 867 | |
f135ff73 | 868 | void wxTreeCtrl::SetImageList(wxImageList *imageList) |
e2414cbe | 869 | { |
f135ff73 | 870 | m_imageListNormal = imageList; |
edaa81ae | 871 | } |
e2414cbe | 872 | |
f135ff73 | 873 | void wxTreeCtrl::SetStateImageList(wxImageList *imageList) |
e2414cbe | 874 | { |
f135ff73 | 875 | m_imageListState = imageList; |
edaa81ae | 876 | } |
e2414cbe | 877 | |
f135ff73 VZ |
878 | // ----------------------------------------------------------------------------- |
879 | // helpers | |
880 | // ----------------------------------------------------------------------------- | |
74bedbeb | 881 | void wxTreeCtrl::AdjustMyScrollbars() |
c801d85f KB |
882 | { |
883 | if (m_anchor) | |
884 | { | |
885 | int x = 0; | |
886 | int y = 0; | |
887 | m_anchor->GetSize( x, y ); | |
888 | y += 2*m_lineHeight; | |
889 | int x_pos = GetScrollPos( wxHORIZONTAL ); | |
890 | int y_pos = GetScrollPos( wxVERTICAL ); | |
891 | SetScrollbars( 10, 10, x/10, y/10, x_pos, y_pos ); | |
892 | } | |
893 | else | |
894 | { | |
895 | SetScrollbars( 0, 0, 0, 0 ); | |
edaa81ae RR |
896 | } |
897 | } | |
c801d85f | 898 | |
16c1f7f3 | 899 | void wxTreeCtrl::PaintLevel( wxGenericTreeItem *item, wxDC &dc, int level, int &y ) |
c801d85f | 900 | { |
4c681997 | 901 | int horizX = level*m_indent; |
389cdc7a | 902 | |
f135ff73 VZ |
903 | item->SetX( horizX+33 ); |
904 | item->SetY( y-m_lineHeight/3 ); | |
905 | item->SetHeight( m_lineHeight ); | |
389cdc7a | 906 | |
4c681997 RR |
907 | item->SetCross( horizX+15, y ); |
908 | ||
c801d85f | 909 | int oldY = y; |
389cdc7a | 910 | |
d4c99d6f | 911 | int exposed_x = dc.LogicalToDeviceX( 0 ); |
f135ff73 | 912 | int exposed_y = dc.LogicalToDeviceY( item->GetY()-2 ); |
4832f7c0 | 913 | |
df875e59 | 914 | if (IsExposed( exposed_x, exposed_y, 10000, m_lineHeight+4 )) // 10000 = very much |
c801d85f | 915 | { |
4c681997 RR |
916 | int startX = horizX; |
917 | int endX = horizX + 10; | |
29d87bba | 918 | |
4c681997 | 919 | if (!item->HasChildren()) endX += 20; |
4832f7c0 | 920 | |
389cdc7a | 921 | dc.DrawLine( startX, y, endX, y ); |
29d87bba | 922 | |
f135ff73 VZ |
923 | if (item->HasPlus()) |
924 | { | |
925 | dc.DrawLine( horizX+20, y, horizX+30, y ); | |
926 | dc.SetPen( *wxGREY_PEN ); | |
927 | dc.DrawRectangle( horizX+10, y-4, 11, 9 ); | |
928 | dc.SetPen( *wxBLACK_PEN ); | |
929 | dc.DrawLine( horizX+13, y, horizX+18, y ); | |
930 | ||
931 | if (!item->IsExpanded()) | |
932 | dc.DrawLine( horizX+15, y-2, horizX+15, y+3 ); | |
933 | } | |
c801d85f | 934 | |
f135ff73 VZ |
935 | if (item->HasHilight()) |
936 | { | |
937 | dc.SetTextForeground( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_HIGHLIGHTTEXT ) ); | |
938 | dc.SetBrush( *m_hilightBrush ); | |
4832f7c0 | 939 | |
df875e59 RR |
940 | long text_w = 0; |
941 | long text_h = 0; | |
942 | dc.GetTextExtent( item->GetText(), &text_w, &text_h ); | |
4832f7c0 | 943 | |
df875e59 RR |
944 | int image_h = 0; |
945 | int image_w = 0; | |
946 | if (item->GetImage() != -1) | |
c801d85f | 947 | { |
df875e59 RR |
948 | m_imageListNormal->GetSize( item->GetImage(), image_w, image_h ); |
949 | image_w += 4; | |
29d87bba | 950 | } |
4832f7c0 | 951 | |
df875e59 RR |
952 | if (m_hasFocus) |
953 | dc.SetPen( *wxBLACK_PEN ); | |
29d87bba | 954 | else |
389cdc7a | 955 | dc.SetPen( *wxTRANSPARENT_PEN ); |
4832f7c0 | 956 | |
df875e59 | 957 | dc.DrawRectangle( item->GetX()-2, item->GetY()-2, image_w+text_w+4, text_h+4 ); |
4832f7c0 | 958 | |
df875e59 RR |
959 | if (item->GetImage() != -1) |
960 | { | |
961 | dc.SetClippingRegion( item->GetX(), item->GetY(), image_w-2, text_h ); | |
962 | m_imageListNormal->Draw( item->GetImage(), dc, item->GetX(), item->GetY()-1, wxIMAGELIST_DRAW_TRANSPARENT ); | |
963 | dc.DestroyClippingRegion(); | |
edaa81ae | 964 | } |
df875e59 | 965 | dc.DrawText( item->GetText(), image_w+item->GetX(), item->GetY() ); |
f135ff73 VZ |
966 | |
967 | dc.SetPen( *wxBLACK_PEN ); | |
968 | dc.SetTextForeground( *wxBLACK ); | |
969 | dc.SetBrush( *wxWHITE_BRUSH ); | |
970 | } | |
971 | else | |
972 | { | |
973 | dc.SetBrush( *wxWHITE_BRUSH ); | |
974 | dc.SetPen( *wxTRANSPARENT_PEN ); | |
4832f7c0 | 975 | |
df875e59 RR |
976 | long text_w = 0; |
977 | long text_h = 0; | |
978 | dc.GetTextExtent( item->GetText(), &text_w, &text_h ); | |
4832f7c0 | 979 | |
df875e59 RR |
980 | int image_h = 0; |
981 | int image_w = 0; | |
982 | if (item->GetImage() != -1) | |
983 | { | |
984 | m_imageListNormal->GetSize( item->GetImage(), image_w, image_h ); | |
985 | image_w += 4; | |
986 | } | |
4832f7c0 | 987 | |
df875e59 | 988 | dc.DrawRectangle( item->GetX()-2, item->GetY()-2, image_w+text_w+4, text_h+4 ); |
4832f7c0 | 989 | |
df875e59 RR |
990 | if (item->GetImage() != -1) |
991 | { | |
992 | dc.SetClippingRegion( item->GetX(), item->GetY(), image_w-2, text_h ); | |
993 | m_imageListNormal->Draw( item->GetImage(), dc, item->GetX(), item->GetY()-1, wxIMAGELIST_DRAW_TRANSPARENT ); | |
994 | dc.DestroyClippingRegion(); | |
995 | } | |
4832f7c0 | 996 | |
df875e59 | 997 | dc.DrawText( item->GetText(), image_w+item->GetX(), item->GetY() ); |
f135ff73 VZ |
998 | dc.SetPen( *wxBLACK_PEN ); |
999 | } | |
edaa81ae | 1000 | } |
4c681997 | 1001 | |
f135ff73 VZ |
1002 | if ( !item->IsExpanded() ) |
1003 | return; | |
e2414cbe | 1004 | |
389cdc7a VZ |
1005 | int semiOldY = y; |
1006 | ||
f135ff73 VZ |
1007 | wxArrayTreeItems& children = item->GetChildren(); |
1008 | size_t count = children.Count(); | |
1009 | for ( size_t n = 0; n < count; n++ ) | |
4c681997 | 1010 | { |
c801d85f | 1011 | y += m_lineHeight; |
e2414cbe | 1012 | semiOldY = y; |
389cdc7a | 1013 | |
f135ff73 | 1014 | PaintLevel( children[n], dc, level+1, y ); |
edaa81ae | 1015 | } |
4c681997 | 1016 | |
e2414cbe | 1017 | dc.DrawLine( horizX+15, oldY+5, horizX+15, semiOldY ); |
4c681997 | 1018 | } |
c801d85f | 1019 | |
f135ff73 VZ |
1020 | // ----------------------------------------------------------------------------- |
1021 | // wxWindows callbacks | |
1022 | // ----------------------------------------------------------------------------- | |
1023 | ||
c801d85f KB |
1024 | void wxTreeCtrl::OnPaint( const wxPaintEvent &WXUNUSED(event) ) |
1025 | { | |
f135ff73 VZ |
1026 | if ( !m_anchor ) |
1027 | return; | |
c801d85f | 1028 | |
d4c99d6f RR |
1029 | wxPaintDC dc(this); |
1030 | PrepareDC( dc ); | |
29d87bba | 1031 | |
d4c99d6f | 1032 | dc.SetFont( wxSystemSettings::GetSystemFont( wxSYS_SYSTEM_FONT ) ); |
29d87bba | 1033 | |
d4c99d6f RR |
1034 | dc.SetPen( m_dottedPen ); |
1035 | m_lineHeight = (int)(dc.GetCharHeight() + 4); | |
29d87bba | 1036 | |
c801d85f | 1037 | int y = m_lineHeight / 2 + 2; |
d4c99d6f | 1038 | PaintLevel( m_anchor, dc, 0, y ); |
edaa81ae | 1039 | } |
c801d85f KB |
1040 | |
1041 | void wxTreeCtrl::OnSetFocus( const wxFocusEvent &WXUNUSED(event) ) | |
1042 | { | |
1043 | m_hasFocus = TRUE; | |
f135ff73 VZ |
1044 | if ( m_current ) |
1045 | RefreshLine( m_current ); | |
edaa81ae | 1046 | } |
c801d85f KB |
1047 | |
1048 | void wxTreeCtrl::OnKillFocus( const wxFocusEvent &WXUNUSED(event) ) | |
1049 | { | |
1050 | m_hasFocus = FALSE; | |
f135ff73 VZ |
1051 | if ( m_current ) |
1052 | RefreshLine( m_current ); | |
edaa81ae | 1053 | } |
c801d85f KB |
1054 | |
1055 | void wxTreeCtrl::OnChar( wxKeyEvent &event ) | |
1056 | { | |
f135ff73 | 1057 | // TODO process '+', '-' (expand/collapse branch) and cursor keys |
c801d85f | 1058 | event.Skip(); |
edaa81ae | 1059 | } |
c801d85f KB |
1060 | |
1061 | void wxTreeCtrl::OnMouse( const wxMouseEvent &event ) | |
1062 | { | |
f135ff73 VZ |
1063 | if ( !(event.LeftDown() || event.LeftDClick()) ) |
1064 | return; | |
1065 | ||
1066 | if ( !m_anchor ) | |
1067 | return; | |
29d87bba | 1068 | |
c801d85f KB |
1069 | wxClientDC dc(this); |
1070 | PrepareDC(dc); | |
1071 | long x = dc.DeviceToLogicalX( (long)event.GetX() ); | |
1072 | long y = dc.DeviceToLogicalY( (long)event.GetY() ); | |
29d87bba | 1073 | |
f135ff73 VZ |
1074 | bool onButton = FALSE; |
1075 | wxGenericTreeItem *item = m_anchor->HitTest( wxPoint(x,y), onButton ); | |
1076 | if ( item == NULL ) | |
29d87bba | 1077 | return; |
29d87bba | 1078 | |
389cdc7a | 1079 | SelectItem(item); |
29d87bba | 1080 | |
f135ff73 VZ |
1081 | if ( event.LeftDClick() ) |
1082 | { | |
1083 | wxTreeEvent event( wxEVT_COMMAND_TREE_KEY_DOWN, GetId() ); | |
1084 | event.m_item = item; | |
1085 | event.m_code = 0; | |
1086 | event.SetEventObject( this ); | |
1087 | ProcessEvent( event ); | |
1088 | } | |
29d87bba | 1089 | |
f135ff73 | 1090 | if ( onButton ) |
c801d85f | 1091 | { |
f135ff73 | 1092 | Toggle( item ); |
edaa81ae RR |
1093 | } |
1094 | } | |
c801d85f | 1095 | |
f135ff73 VZ |
1096 | // ----------------------------------------------------------------------------- |
1097 | // ----------------------------------------------------------------------------- | |
1098 | void wxTreeCtrl::CalculateLevel( wxGenericTreeItem *item, | |
1099 | wxDC &dc, | |
1100 | int level, | |
1101 | int &y ) | |
c801d85f | 1102 | { |
4c681997 | 1103 | int horizX = level*m_indent; |
389cdc7a | 1104 | |
f135ff73 VZ |
1105 | item->SetX( horizX+33 ); |
1106 | item->SetY( y-m_lineHeight/3-2 ); | |
1107 | item->SetHeight( m_lineHeight ); | |
4c681997 | 1108 | |
f135ff73 VZ |
1109 | if ( item->IsExpanded() ) |
1110 | return; | |
389cdc7a | 1111 | |
f135ff73 VZ |
1112 | wxArrayTreeItems& children = item->GetChildren(); |
1113 | size_t count = children.Count(); | |
1114 | for ( size_t n = 0; n < count; n++ ) | |
c801d85f | 1115 | { |
c801d85f | 1116 | y += m_lineHeight; |
f135ff73 | 1117 | CalculateLevel( children[n], dc, level+1, y ); |
edaa81ae RR |
1118 | } |
1119 | } | |
c801d85f | 1120 | |
74bedbeb | 1121 | void wxTreeCtrl::CalculatePositions() |
c801d85f | 1122 | { |
f135ff73 | 1123 | if ( !m_anchor ) |
29d87bba VZ |
1124 | return; |
1125 | ||
c801d85f KB |
1126 | wxClientDC dc(this); |
1127 | PrepareDC( dc ); | |
29d87bba | 1128 | |
c801d85f | 1129 | dc.SetFont( wxSystemSettings::GetSystemFont( wxSYS_SYSTEM_FONT ) ); |
29d87bba | 1130 | |
c801d85f KB |
1131 | dc.SetPen( m_dottedPen ); |
1132 | m_lineHeight = (int)(dc.GetCharHeight() + 4); | |
29d87bba | 1133 | |
c801d85f KB |
1134 | int y = m_lineHeight / 2 + 2; |
1135 | CalculateLevel( m_anchor, dc, 0, y ); | |
edaa81ae | 1136 | } |
c801d85f | 1137 | |
f135ff73 | 1138 | void wxTreeCtrl::RefreshSubtree(wxGenericTreeItem *item) |
c801d85f | 1139 | { |
f135ff73 VZ |
1140 | wxClientDC dc(this); |
1141 | PrepareDC(dc); | |
4832f7c0 | 1142 | |
f135ff73 VZ |
1143 | int cw = 0; |
1144 | int ch = 0; | |
1145 | GetClientSize( &cw, &ch ); | |
4832f7c0 | 1146 | |
f135ff73 VZ |
1147 | wxRect rect; |
1148 | rect.x = dc.LogicalToDeviceX( 0 ); | |
1149 | rect.width = cw; | |
1150 | rect.y = dc.LogicalToDeviceY( item->GetY() ); | |
1151 | rect.height = ch; | |
1152 | ||
1153 | Refresh( TRUE, &rect ); | |
1154 | ||
1155 | AdjustMyScrollbars(); | |
edaa81ae | 1156 | } |
c801d85f KB |
1157 | |
1158 | void wxTreeCtrl::RefreshLine( wxGenericTreeItem *item ) | |
1159 | { | |
c801d85f KB |
1160 | wxClientDC dc(this); |
1161 | PrepareDC( dc ); | |
f135ff73 | 1162 | |
c801d85f | 1163 | wxRect rect; |
f135ff73 VZ |
1164 | rect.x = dc.LogicalToDeviceX( item->GetX() - 2 ); |
1165 | rect.y = dc.LogicalToDeviceY( item->GetY() - 2 ); | |
c801d85f | 1166 | rect.width = 1000; |
f135ff73 VZ |
1167 | rect.height = dc.GetCharHeight() + 6; |
1168 | ||
c801d85f | 1169 | Refresh( TRUE, &rect ); |
edaa81ae | 1170 | } |
c801d85f | 1171 |