]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/treectrl.cpp
Since wxREADONLY has disappeared, I had to change to wxTE_READONLY
[wxWidgets.git] / src / gtk / treectrl.cpp
CommitLineData
f4e325b3
DP
1/////////////////////////////////////////////////////////////////////////////
2// Name: treectrl.cpp
3// Purpose:
4// Author: Denis Pershin
5// Created: 07/05/98
6// Id: $Id$
7// Copyright: (c) 1998 Denis Pershin and Julian Smart
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11#ifdef __GNUG__
e8cd8b1b 12#pragma implementation "treectrl.h"
f4e325b3
DP
13#endif
14
15#include "wx/gtk/treectrl.h"
16#include "wx/settings.h"
17#include "wx/log.h"
18
19#ifdef USE_GDK_IMLIB
20#include "../gdk_imlib/gdk_imlib.h"
21#endif
22
23//-----------------------------------------------------------------------------
24// wxTreeItem
25//-----------------------------------------------------------------------------
26
27// clicked
28
29void gtk_treeitem_expand_callback(GtkWidget *WXUNUSED(widget), wxTreeItem *treeitem) {
30 treeitem->SendExpanding(treeitem->m_owner);
31 treeitem->SendExpand(treeitem->m_owner);
32};
33
34void gtk_treeitem_collapse_callback( GtkWidget *WXUNUSED(widget), wxTreeItem *treeitem) {
35 treeitem->SendCollapsing(treeitem->m_owner);
36 treeitem->SendCollapse(treeitem->m_owner);
37};
38
39void gtk_treeitem_select_callback( GtkWidget *WXUNUSED(widget), wxTreeItem *treeitem) {
40 treeitem->SendSelChanging(treeitem->m_owner);
41 treeitem->m_state |= wxTREE_STATE_SELECTED;
42 treeitem->SendSelChanged(treeitem->m_owner);
43}
44
45void gtk_treeitem_deselect_callback( GtkWidget *WXUNUSED(widget), wxTreeItem *treeitem) {
46 treeitem->SendSelChanging(treeitem->m_owner);
47 treeitem->m_state &= !wxTREE_STATE_SELECTED;
48 treeitem->SendSelChanged(treeitem->m_owner);
49}
50
51IMPLEMENT_DYNAMIC_CLASS(wxTreeItem, wxObject)
52
53wxTreeItem::wxTreeItem() {
54 m_mask = 0;
55 m_itemId = 0;
56 m_state = 0;
57 m_stateMask = 0;
58 m_image = -1;
59 m_children = 0;
60 m_selectedImage = -1;
61 m_tree = NULL;
62 m_parentwidget = NULL;
63 m_widget = NULL;
64 m_data = 0;
65 m_owner = 0;
66 expand_handler = 0;
67 collapse_handler = 0;
68};
69
70wxTreeItem::wxTreeItem(GtkWidget *parent, const wxTreeItem &item) {
71 m_mask = item.m_mask;
72 m_text = item.m_text;
73 m_itemId = item.m_itemId;
74 m_state = item.m_state;
75 m_stateMask = item.m_stateMask;
76 m_image = item.m_image;
77 m_tree = NULL;
78 m_owner = 0;
79 m_selectedImage = item.m_selectedImage;
80 m_children = item.m_children;
81 m_childlist = item.m_childlist;
82 m_data = item.m_data;
83 m_parentwidget = parent;
84 expand_handler = 0;
85 collapse_handler = 0;
86
87 Create();
88}
89
90void wxTreeItem::Create() {
91 wxASSERT(m_parentwidget != NULL);
92
93 m_widget = GTK_TREE_ITEM(gtk_tree_item_new_with_label ((char *)(const char *)m_text));
94 gtk_container_add (GTK_CONTAINER(m_parentwidget), GTK_WIDGET(m_widget));
95 gtk_widget_show(GTK_WIDGET(m_widget));
96
97 gtk_signal_connect(GTK_OBJECT(m_widget), "select",
98 GTK_SIGNAL_FUNC(gtk_treeitem_select_callback), (gpointer)this );
99
100 gtk_signal_connect(GTK_OBJECT(m_widget), "deselect",
101 GTK_SIGNAL_FUNC(gtk_treeitem_deselect_callback), (gpointer)this );
102
103 if ((m_mask & wxTREE_MASK_CHILDREN) != 0)
104 AddSubtree();
105}
106
107wxTreeItem::~wxTreeItem() {
108 if (m_owner != NULL)
109 SendDelete(m_owner);
110 DeleteChildren();
111 if ((m_widget != NULL) && (m_parentwidget != NULL))
112 gtk_container_remove(GTK_CONTAINER(m_parentwidget),
113 GTK_WIDGET(m_widget));
114// if (m_tree != NULL) {
115// gtk_widget_destroy(GTK_WIDGET(m_tree));
116// m_tree = NULL;
117// }
118
119// if (m_widget != NULL)
120// gtk_widget_destroy(GTK_WIDGET(m_widget));
121}
122
123void wxTreeItem::AddSubtree() {
124 if (m_widget == NULL)
125 return;
126
127 m_tree = GTK_TREE(gtk_tree_new());
128
129 if (expand_handler == 0)
130 expand_handler = gtk_signal_connect(GTK_OBJECT(m_widget), "expand",
131 GTK_SIGNAL_FUNC(gtk_treeitem_expand_callback), (gpointer)this );
132
133 if (collapse_handler == 0)
134 collapse_handler = gtk_signal_connect( GTK_OBJECT(m_widget), "collapse",
135 GTK_SIGNAL_FUNC(gtk_treeitem_collapse_callback), (gpointer)this );
136
137 gtk_tree_item_set_subtree(GTK_TREE_ITEM(m_widget), GTK_WIDGET(m_tree));
138 gtk_widget_show(GTK_WIDGET(m_tree));
139}
140
141void wxTreeItem::AddChild(wxTreeItem *child) {
142 wxASSERT(child != NULL);
143
144 m_childlist.Append(child);
145}
146
147bool wxTreeItem::HasChildren() {
148 return (m_childlist.Number() != 0);
149}
150
151void wxTreeItem::DeleteChildren() {
152 wxTreeItem *item;
153 long no = GetChildrenNumber();
154 for (long i=0; i<no; i++)
155 if ((item = GetChild(i)) != 0)
156 delete item;
157 m_childlist.Clear();
158 m_tree = NULL;
159
160 if ((m_mask & wxTREE_MASK_CHILDREN) != 0)
161 if (m_widget != NULL)
162 if (m_widget->subtree == 0)
163 AddSubtree();
164}
165
166int wxTreeItem::NumberOfVisibleDescendents() {
167 wxTreeItem *item;
168 long no = GetChildrenNumber();
169 long num = 0;
170 for (long i=0; i<no; i++)
171 if ((item = GetChild(i)) != 0)
172 num += item->NumberOfVisibleDescendents();
173
174 num+=no;
175
176 return num;
177}
178
179wxTreeItem *wxTreeItem::FindItem(long itemId) const {
180 if (m_itemId == itemId) return (wxTreeItem*)(this);
181 wxNode *node = m_childlist.First();
182 while (node) {
183 wxTreeItem *item = (wxTreeItem*)node->Data();
184 wxTreeItem *res = item->FindItem( itemId );
185 if (res) return (wxTreeItem*)(res);
186 node = node->Next();
187 };
188 return NULL;
189};
190
191wxTreeItem *wxTreeItem::FindItem(GtkTreeItem *item) const {
192 if (m_widget == item)
193 return (wxTreeItem*)(this);
194 wxNode *node = m_childlist.First();
195 while (node) {
196 wxTreeItem *i = (wxTreeItem*)node->Data();
197 wxTreeItem *res = i->FindItem(item);
198 if (res) return (wxTreeItem*)(res);
199 node = node->Next();
200 };
201 return NULL;
202};
203
204void wxTreeItem::PrepareEvent(wxTreeEvent &event) {
205 event.m_item.m_itemId = m_itemId;
206 event.m_item.m_state = m_state;
207 event.m_item.m_text = m_text;
208 event.m_item.m_image = m_image;
209 event.m_item.m_selectedImage = m_selectedImage;
210 event.m_item.m_children = (GetChildrenNumber() > 0);
211 event.m_item.m_data = m_data;
212 event.m_oldItem = 0;
213 event.m_code = 0;
214// event.m_pointDrag.x = 0;
215// event.m_pointDrag.y = 0;
216};
217
218void wxTreeItem::SendDelete(wxWindow *target) {
219 wxTreeEvent event(wxEVT_COMMAND_TREE_DELETE_ITEM, target->GetId());
220 PrepareEvent(event);
221 event.SetEventObject(target);
222 target->ProcessEvent(event);
223};
224
225void wxTreeItem::SendExpand(wxWindow *target) {
226 wxTreeEvent event(wxEVT_COMMAND_TREE_ITEM_EXPANDED, target->GetId());
227 PrepareEvent(event);
228 event.SetEventObject(target);
229 target->ProcessEvent(event);
230};
231
232void wxTreeItem::SendExpanding(wxWindow *target) {
233 wxTreeEvent event(wxEVT_COMMAND_TREE_ITEM_EXPANDING, target->GetId());
234 PrepareEvent(event);
235 event.SetEventObject(target);
236 target->ProcessEvent(event);
237};
238
239void wxTreeItem::SendCollapse(wxWindow *target) {
240 wxTreeEvent event(wxEVT_COMMAND_TREE_ITEM_COLLAPSED, target->GetId());
241 PrepareEvent(event);
242 event.SetEventObject(target);
243 target->ProcessEvent(event);
244};
245
246void wxTreeItem::SendCollapsing(wxWindow *target) {
247 wxTreeEvent event(wxEVT_COMMAND_TREE_ITEM_COLLAPSING, target->GetId());
248 PrepareEvent(event);
249 event.SetEventObject(target);
250 target->ProcessEvent(event);
251};
252
253void wxTreeItem::SendSelChanged(wxWindow *target) {
254 wxTreeEvent event(wxEVT_COMMAND_TREE_SEL_CHANGED, target->GetId());
255 PrepareEvent(event);
256 event.SetEventObject(target);
257 target->ProcessEvent(event);
258};
259
260void wxTreeItem::SendSelChanging(wxWindow *target) {
261 wxTreeEvent event(wxEVT_COMMAND_TREE_SEL_CHANGING, target->GetId());
262 PrepareEvent(event);
263 event.SetEventObject(target);
264 target->ProcessEvent(event);
265};
266
267//-----------------------------------------------------------------------------
268// wxTreeCtrl
269//-----------------------------------------------------------------------------
270
271IMPLEMENT_DYNAMIC_CLASS(wxTreeCtrl, wxScrolledWindow)
272
273wxTreeCtrl::wxTreeCtrl() {
274 m_current = NULL;
275 m_lastId = 0;
276 m_isCreated = FALSE;
277 m_imageList = NULL;
278 m_smallImageList = NULL;
279};
280
281wxTreeCtrl::wxTreeCtrl(wxWindow *parent, wxWindowID id,
282 const wxPoint& pos, const wxSize& size,
283 long style, const wxString& name ) {
284 m_current = NULL;
285 m_lastId = 0;
286 m_isCreated = FALSE;
287 m_imageList = NULL;
288 m_smallImageList = NULL;
289 Create( parent, id, pos, size, style, name );
290};
291
292wxTreeCtrl::~wxTreeCtrl() {
293 DeleteAllItems();
294};
295
296bool wxTreeCtrl::Create(wxWindow *parent, wxWindowID id,
297 const wxPoint& pos, const wxSize& size,
298 long style, const wxString& name ) {
299 m_needParent = TRUE;
300
301 PreCreation( parent, id, pos, size, style, name );
302
303 m_widget = gtk_scrolled_window_new(NULL, NULL);
304 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(m_widget),
305 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
306
307 m_tree = GTK_TREE(gtk_tree_new());
308
309/*
310 gtk_signal_connect( GTK_OBJECT(m_tree), "selection_changed",
311 GTK_SIGNAL_FUNC(gtk_treectrl_selection_changed_callback), (gpointer)this);
312 gtk_signal_connect( GTK_OBJECT(m_tree), "select_child",
313 GTK_SIGNAL_FUNC(gtk_treectrl_select_child_callback), (gpointer)this);
314 gtk_signal_connect( GTK_OBJECT(m_tree), "unselect_child",
315 GTK_SIGNAL_FUNC(gtk_treectrl_unselect_child_callback), (gpointer)this);
316*/
317
318 gtk_container_add(GTK_CONTAINER(m_widget), GTK_WIDGET(m_tree));
319 gtk_widget_show(GTK_WIDGET(m_tree));
320
321 PostCreation();
322
323 gtk_widget_realize(GTK_WIDGET(m_tree));
324
325 Show(TRUE);
326
327 return TRUE;
328};
329
330int wxTreeCtrl::GetCount() const
331{
332 if (!m_anchor) return 0;
333 return m_anchor->NumberOfVisibleDescendents();
334};
335
336long wxTreeCtrl::InsertItem(long parent, const wxString& label, long data,
337 int image, int selImage, long insertAfter) {
338 wxTreeItem item;
339 item.m_data = data;
340 if (!label.IsNull() || (label == "")) {
341 item.m_text = label;
342 item.m_mask |= wxTREE_MASK_TEXT;
343 };
344
345 if (image >= 0) {
346 item.m_image = image;
347 item.m_mask |= wxTREE_MASK_IMAGE;
348 };
349
350 if (selImage >= 0) {
351 item.m_selectedImage = selImage;
352 item.m_mask |= wxTREE_MASK_SELECTED_IMAGE;
353 };
354
355 return InsertItem(parent, item, insertAfter);
356};
357
358long wxTreeCtrl::InsertItem( long parent, wxTreeItem &info, long WXUNUSED(insertAfter) ) {
359 int oldMask = info.m_mask;
360 long ret = 0;
361 wxTreeItem *p = NULL;
362 wxTreeItem *new_child;
363
364 if (parent == 0) {
365 if (m_anchor)
366 return -1;
367 } else {
368 p = FindItem(parent);
369 if (!p) return -1;
370 };
371
372 if ((info.m_mask & wxTREE_MASK_HANDLE) == 0) {
373 m_lastId++;
374 info.m_itemId = m_lastId;
375 info.m_mask |= wxTREE_MASK_HANDLE;
376 ret = m_lastId;
377 } else
378 ret = info.m_itemId;
379
380 if (p) {
381 if (p->m_tree == NULL)
382 p->AddSubtree();
383
384 new_child = new wxTreeItem(GTK_WIDGET(p->m_tree), info);
385 p->AddChild(new_child);
386 } else {
387 new_child = new wxTreeItem(GTK_WIDGET(m_tree), info);
388 m_anchor = new_child;
389 }
390
391/* Disabled until wxImageList q solved
392 if ((info.m_mask & wxTREE_MASK_IMAGE) == 0) {
393 wxBitmap *bmp;
394
395 if ((bmp = m_imageList->GetItem(info.m_image))->Ok()) {
396 GdkBitmap *mask = NULL;
397 if (bmp->GetMask()) mask = bmp->GetMask()->GetBitmap();
398 GtkWidget *pixmap = gtk_pixmap_new( bmp->GetPixmap(), mask );
399
400 gtk_widget_set_parent(pixmap, GTK_WIDGET(new_child->m_widget));
401 gtk_widget_show(pixmap);
402 GTK_TREE_ITEM(new_child->m_widget)->pixmaps_box = pixmap;
403 }
404 }
405*/
406
407 new_child->m_owner = this;
408
409 info.m_mask = oldMask;
410 return ret;
411};
412
413
414bool wxTreeCtrl::ExpandItem( long item, int action ) {
415 wxTreeItem *i = FindItem( item );
416 if (!i)
417 return FALSE;
418
419 switch (action) {
420 case wxTREE_EXPAND_EXPAND:
421 gtk_tree_item_expand(GTK_TREE_ITEM(i->m_widget));
422 break;
423
424 case wxTREE_EXPAND_COLLAPSE_RESET:
425 case wxTREE_EXPAND_COLLAPSE:
426 gtk_tree_item_collapse(GTK_TREE_ITEM(i->m_widget));
427 break;
428
429 case wxTREE_EXPAND_TOGGLE:
430 if ((i->GetState() & wxTREE_STATE_EXPANDED) == 0)
431 gtk_tree_item_expand(GTK_TREE_ITEM(i->m_widget));
432 else
433 gtk_tree_item_collapse(GTK_TREE_ITEM(i->m_widget));
434 break;
435 }
436
437 return TRUE;
438};
439
440void wxTreeCtrl::DeleteItem( long item )
441{
442 wxTreeItem *pItem = FindItem( item );
443 wxCHECK_RET( pItem != NULL, "wxTreeCtrl::DeleteItem: no such pItem." );
444
445// pItem->m_parent->m_childlist.DeleteObject(pItem);
446}
447
448void wxTreeCtrl::DeleteChildren( long item )
449{
450 wxTreeItem *pItem = FindItem( item );
451 wxCHECK_RET( pItem != NULL, "wxTreeCtrl::DeleteChildren: no such pItem." );
452
453 pItem->DeleteChildren();
454}
455
456bool wxTreeCtrl::DeleteAllItems()
457{
458 delete m_anchor;
459 m_anchor = NULL;
460 return TRUE;
461};
462
463/*
464bool wxTreeCtrl::GetItem( wxTreeItem &info ) const
465{
466 wxTreeItem *i = FindItem( info.m_itemId );
467 if (!i) return FALSE;
468 i->GetItem( info );
469 return TRUE;
470};
471*/
472
473long wxTreeCtrl::GetItemData( long item ) const
474{
475 wxTreeItem *i = FindItem( item );
476 if (!i) return 0;
477 return i->m_data;
478};
479
480wxString wxTreeCtrl::GetItemText( long item ) const
481{
482 wxTreeItem *i = FindItem( item );
483 if (!i) return "";
484 return i->m_text;
485};
486
487int wxTreeCtrl::GetItemImage(long item) const
488{
489 wxTreeItem *i = FindItem( item );
490 return i == 0 ? -1 : i->GetImage();
491}
492
493long wxTreeCtrl::GetParent( long item ) const
494{
495 wxTreeItem *i = FindItem( item );
496 if (!i) return -1;
497/*
498 i = i->m_parent;
499 if (!i) return -1;
500 return i->m_parent->m_itemId;
501*/
502 return -1;
503};
504
505long wxTreeCtrl::GetRootItem() const
506{
507 if (m_anchor) return m_anchor->m_itemId;
508 return -1;
509};
510
511/*
512long wxTreeCtrl::GetSelection() const
513{
514 return m_current ? m_current->GetItemId() : -1;
515};
516
517bool wxTreeCtrl::SelectItem(long itemId)
518{
519 wxTreeItem *pItem = FindItem(itemId);
520 if ( !pItem ) {
521 wxLogDebug("Can't select an item %d which doesn't exist.", itemId);
522
523 return FALSE;
524 }
525
526 SelectItem(pItem);
527
528 return TRUE;
529};
530
531void wxTreeCtrl::SelectItem(wxTreeItem *item, bool bDoEvents )
532{
533 if (m_current != item)
534 {
535 if (m_current)
536 {
537 m_current->SetHilight( FALSE );
538// RefreshLine( m_current );
539 };
540 m_current = item;
541 m_current->SetHilight( TRUE );
542// RefreshLine( m_current );
543
544 if (bDoEvents) m_current->SendSelected( this );
545 }
546}
547*/
548
549bool wxTreeCtrl::ItemHasChildren( long item ) const
550{
551 wxTreeItem *i = FindItem( item );
552 if (!i) return FALSE;
553 return i->HasChildren();
554};
555
556void wxTreeCtrl::SetIndent( int indent )
557{
558 m_indent = indent;
559 Refresh();
560};
561
562int wxTreeCtrl::GetIndent() const
563{
564 return m_indent;
565};
566
567/*
568bool wxTreeCtrl::SetItem( wxTreeItem &info )
569{
570 wxTreeItem *i = FindItem( info.m_itemId );
571 if (!i) return FALSE;
572 wxClientDC dc(this);
573 i->SetItem( info, &dc );
574 Refresh();
575 return TRUE;
576};
577
578bool wxTreeCtrl::SetItemData( long item, long data )
579{
580 wxTreeItem *i = FindItem( item );
581 if (!i) return FALSE;
582 i->m_data = data;
583 return TRUE;
584};
585
586bool wxTreeCtrl::SetItemText( long item, const wxString &text )
587{
588 wxTreeItem *i = FindItem( item );
589 if (!i) return FALSE;
590 wxClientDC dc(this);
591 i->SetText( text, &dc );
592 return TRUE;
593};
594
595void wxTreeCtrl::SetItemImage(long item, int image, int imageSel) const
596{
597 wxTreeItem *i = FindItem( item );
598 if ( i != 0 ) {
599 i->SetImage(image);
600 i->SetSelectedImage(imageSel);
601 }
602}
603
604long wxTreeCtrl::HitTest( const wxPoint& point, int &flags )
605{
606 flags = 0;
607 if (!m_anchor) return -1;
608 return m_anchor->HitTest( point, flags );
609};
610*/
611
612wxImageList *wxTreeCtrl::GetImageList( int which ) const
613{
614 if (which == wxIMAGE_LIST_NORMAL) return m_imageList;
615 return m_smallImageList;
616};
617
618void wxTreeCtrl::SetImageList( wxImageList *imageList, int which )
619{
620 if (which == wxIMAGE_LIST_NORMAL)
621 {
622 if (m_imageList) delete m_imageList;
623 m_imageList = imageList;
624 }
625 else
626 {
627 if (m_smallImageList) delete m_smallImageList;
628 m_smallImageList = imageList;
629 };
630};
631
632wxTreeItem *wxTreeCtrl::FindItem( long itemId ) const {
633 if (!m_anchor) return NULL;
634 return m_anchor->FindItem( itemId );
635 return 0;
636};
637
638wxTreeItem *wxTreeCtrl::FindItem(GtkTreeItem *item) const {
639 if (!m_anchor) return NULL;
640 return m_anchor->FindItem(item);
641 return 0;
642};
643
644//-----------------------------------------------------------------------------
645// wxTreeEvent
646//-----------------------------------------------------------------------------
647
648IMPLEMENT_DYNAMIC_CLASS(wxTreeEvent,wxCommandEvent)
649
650wxTreeEvent::wxTreeEvent( wxEventType commandType, int id ) :
651 wxCommandEvent( commandType, id )
652{
653 m_code = 0;
654 m_oldItem = 0;
655};
656
657/* Bunch of old code might be useful */
658/*
659 wxBitmap *bmp;
660
661 if ((bmp = m_imageList->GetItem(0))->Ok()) {
662 GdkBitmap *mask = NULL;
663 if (bmp->GetMask()) mask = bmp->GetMask()->GetBitmap();
664 GtkWidget *pixmap = gtk_pixmap_new( bmp->GetPixmap(), mask );
665
666 gtk_widget_set_parent(pixmap, GTK_WIDGET(new_child->m_widget));
667 gtk_widget_show(pixmap);
668 GTK_TREE_ITEM(new_child->m_widget)->pixmaps_box = pixmap;
669 }
670
671 if ((bmp = m_imageList->GetItem(1))->Ok()) {
672 GdkBitmap *mask = NULL;
673 if (bmp->GetMask()) mask = bmp->GetMask()->GetBitmap();
674 GtkWidget *pixmap = gtk_pixmap_new( bmp->GetPixmap(), mask );
675
676 gtk_widget_set_parent(pixmap, GTK_WIDGET(new_child->m_widget));
677 gtk_widget_show(pixmap);
678 GTK_TREE_ITEM(new_child->m_widget)->plus_pix_widget = pixmap;
679 }
680
681 if ((bmp = m_imageList->GetItem(2))->Ok()) {
682 GdkBitmap *mask = NULL;
683 if (bmp->GetMask()) mask = bmp->GetMask()->GetBitmap();
684 GtkWidget *pixmap = gtk_pixmap_new( bmp->GetPixmap(), mask );
685
686 gtk_widget_set_parent(pixmap, GTK_WIDGET(new_child->m_widget));
687 gtk_widget_show(pixmap);
688 GTK_TREE_ITEM(new_child->m_widget)->minus_pix_widget = pixmap;
689 }
690
691 if (p)
692 if (p->m_childlist.Number() == 1) {
693 gtk_tree_item_collapse(GTK_TREE_ITEM(p->m_widget));
694 gtk_tree_item_expand(GTK_TREE_ITEM(p->m_widget));
695 }
696*/