1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Denis Pershin
7 // Copyright: (c) 1998 Denis Pershin and Julian Smart
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
12 #pragma implementation "treectrl.h"
15 #include "wx/gtk/treectrl.h"
16 #include "wx/settings.h"
20 #include "../gdk_imlib/gdk_imlib.h"
23 //-----------------------------------------------------------------------------
25 //-----------------------------------------------------------------------------
29 void gtk_treeitem_expand_callback(GtkWidget
*WXUNUSED(widget
), wxTreeItem
*treeitem
) {
30 treeitem
->SendExpanding(treeitem
->m_owner
);
31 treeitem
->SendExpand(treeitem
->m_owner
);
34 void gtk_treeitem_collapse_callback( GtkWidget
*WXUNUSED(widget
), wxTreeItem
*treeitem
) {
35 treeitem
->SendCollapsing(treeitem
->m_owner
);
36 treeitem
->SendCollapse(treeitem
->m_owner
);
39 void 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
);
45 void 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
);
51 IMPLEMENT_DYNAMIC_CLASS(wxTreeItem
, wxObject
)
53 wxTreeItem::wxTreeItem() {
62 m_parentwidget
= NULL
;
70 wxTreeItem::wxTreeItem(GtkWidget
*parent
, const wxTreeItem
&item
) {
73 m_itemId
= item
.m_itemId
;
74 m_state
= item
.m_state
;
75 m_stateMask
= item
.m_stateMask
;
76 m_image
= item
.m_image
;
79 m_selectedImage
= item
.m_selectedImage
;
80 m_children
= item
.m_children
;
81 m_childlist
= item
.m_childlist
;
83 m_parentwidget
= parent
;
90 void wxTreeItem::Create() {
91 wxASSERT(m_parentwidget
!= NULL
);
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
));
97 gtk_signal_connect(GTK_OBJECT(m_widget
), "select",
98 GTK_SIGNAL_FUNC(gtk_treeitem_select_callback
), (gpointer
)this );
100 gtk_signal_connect(GTK_OBJECT(m_widget
), "deselect",
101 GTK_SIGNAL_FUNC(gtk_treeitem_deselect_callback
), (gpointer
)this );
103 if ((m_mask
& wxTREE_MASK_CHILDREN
) != 0)
107 wxTreeItem::~wxTreeItem() {
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));
119 // if (m_widget != NULL)
120 // gtk_widget_destroy(GTK_WIDGET(m_widget));
123 void wxTreeItem::AddSubtree() {
124 if (m_widget
== NULL
)
127 m_tree
= GTK_TREE(gtk_tree_new());
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 );
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 );
137 gtk_tree_item_set_subtree(GTK_TREE_ITEM(m_widget
), GTK_WIDGET(m_tree
));
138 gtk_widget_show(GTK_WIDGET(m_tree
));
141 void wxTreeItem::AddChild(wxTreeItem
*child
) {
142 wxASSERT(child
!= NULL
);
144 m_childlist
.Append(child
);
147 bool wxTreeItem::HasChildren() {
148 return (m_childlist
.Number() != 0);
151 void wxTreeItem::DeleteChildren() {
153 long no
= GetChildrenNumber();
154 for (long i
=0; i
<no
; i
++)
155 if ((item
= GetChild(i
)) != 0)
160 if ((m_mask
& wxTREE_MASK_CHILDREN
) != 0)
161 if (m_widget
!= NULL
)
162 if (m_widget
->subtree
== 0)
166 int wxTreeItem::NumberOfVisibleDescendents() {
168 long no
= GetChildrenNumber();
170 for (long i
=0; i
<no
; i
++)
171 if ((item
= GetChild(i
)) != 0)
172 num
+= item
->NumberOfVisibleDescendents();
179 wxTreeItem
*wxTreeItem::FindItem(long itemId
) const {
180 if (m_itemId
== itemId
) return (wxTreeItem
*)(this);
181 wxNode
*node
= m_childlist
.First();
183 wxTreeItem
*item
= (wxTreeItem
*)node
->Data();
184 wxTreeItem
*res
= item
->FindItem( itemId
);
185 if (res
) return (wxTreeItem
*)(res
);
191 wxTreeItem
*wxTreeItem::FindItem(GtkTreeItem
*item
) const {
192 if (m_widget
== item
)
193 return (wxTreeItem
*)(this);
194 wxNode
*node
= m_childlist
.First();
196 wxTreeItem
*i
= (wxTreeItem
*)node
->Data();
197 wxTreeItem
*res
= i
->FindItem(item
);
198 if (res
) return (wxTreeItem
*)(res
);
204 void 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
;
214 // event.m_pointDrag.x = 0;
215 // event.m_pointDrag.y = 0;
218 void wxTreeItem::SendDelete(wxWindow
*target
) {
219 wxTreeEvent
event(wxEVT_COMMAND_TREE_DELETE_ITEM
, target
->GetId());
221 event
.SetEventObject(target
);
222 target
->ProcessEvent(event
);
225 void wxTreeItem::SendExpand(wxWindow
*target
) {
226 wxTreeEvent
event(wxEVT_COMMAND_TREE_ITEM_EXPANDED
, target
->GetId());
228 event
.SetEventObject(target
);
229 target
->ProcessEvent(event
);
232 void wxTreeItem::SendExpanding(wxWindow
*target
) {
233 wxTreeEvent
event(wxEVT_COMMAND_TREE_ITEM_EXPANDING
, target
->GetId());
235 event
.SetEventObject(target
);
236 target
->ProcessEvent(event
);
239 void wxTreeItem::SendCollapse(wxWindow
*target
) {
240 wxTreeEvent
event(wxEVT_COMMAND_TREE_ITEM_COLLAPSED
, target
->GetId());
242 event
.SetEventObject(target
);
243 target
->ProcessEvent(event
);
246 void wxTreeItem::SendCollapsing(wxWindow
*target
) {
247 wxTreeEvent
event(wxEVT_COMMAND_TREE_ITEM_COLLAPSING
, target
->GetId());
249 event
.SetEventObject(target
);
250 target
->ProcessEvent(event
);
253 void wxTreeItem::SendSelChanged(wxWindow
*target
) {
254 wxTreeEvent
event(wxEVT_COMMAND_TREE_SEL_CHANGED
, target
->GetId());
256 event
.SetEventObject(target
);
257 target
->ProcessEvent(event
);
260 void wxTreeItem::SendSelChanging(wxWindow
*target
) {
261 wxTreeEvent
event(wxEVT_COMMAND_TREE_SEL_CHANGING
, target
->GetId());
263 event
.SetEventObject(target
);
264 target
->ProcessEvent(event
);
267 //-----------------------------------------------------------------------------
269 //-----------------------------------------------------------------------------
271 IMPLEMENT_DYNAMIC_CLASS(wxTreeCtrl
, wxScrolledWindow
)
273 wxTreeCtrl::wxTreeCtrl() {
278 m_smallImageList
= NULL
;
281 wxTreeCtrl::wxTreeCtrl(wxWindow
*parent
, wxWindowID id
,
282 const wxPoint
& pos
, const wxSize
& size
,
283 long style
, const wxString
& name
) {
288 m_smallImageList
= NULL
;
289 Create( parent
, id
, pos
, size
, style
, name
);
292 wxTreeCtrl::~wxTreeCtrl() {
296 bool wxTreeCtrl::Create(wxWindow
*parent
, wxWindowID id
,
297 const wxPoint
& pos
, const wxSize
& size
,
298 long style
, const wxString
& name
) {
301 PreCreation( parent
, id
, pos
, size
, style
, name
);
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
);
307 m_tree
= GTK_TREE(gtk_tree_new());
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);
318 gtk_container_add(GTK_CONTAINER(m_widget
), GTK_WIDGET(m_tree
));
319 gtk_widget_show(GTK_WIDGET(m_tree
));
323 gtk_widget_realize(GTK_WIDGET(m_tree
));
330 int wxTreeCtrl::GetCount() const
332 if (!m_anchor
) return 0;
333 return m_anchor
->NumberOfVisibleDescendents();
336 long wxTreeCtrl::InsertItem(long parent
, const wxString
& label
, long data
,
337 int image
, int selImage
, long insertAfter
) {
340 if (!label
.IsNull() || (label
== "")) {
342 item
.m_mask
|= wxTREE_MASK_TEXT
;
346 item
.m_image
= image
;
347 item
.m_mask
|= wxTREE_MASK_IMAGE
;
351 item
.m_selectedImage
= selImage
;
352 item
.m_mask
|= wxTREE_MASK_SELECTED_IMAGE
;
355 return InsertItem(parent
, item
, insertAfter
);
358 long wxTreeCtrl::InsertItem( long parent
, wxTreeItem
&info
, long WXUNUSED(insertAfter
) ) {
359 int oldMask
= info
.m_mask
;
361 wxTreeItem
*p
= NULL
;
362 wxTreeItem
*new_child
;
368 p
= FindItem(parent
);
372 if ((info
.m_mask
& wxTREE_MASK_HANDLE
) == 0) {
374 info
.m_itemId
= m_lastId
;
375 info
.m_mask
|= wxTREE_MASK_HANDLE
;
381 if (p
->m_tree
== NULL
)
384 new_child
= new wxTreeItem(GTK_WIDGET(p
->m_tree
), info
);
385 p
->AddChild(new_child
);
387 new_child
= new wxTreeItem(GTK_WIDGET(m_tree
), info
);
388 m_anchor
= new_child
;
391 /* Disabled until wxImageList q solved
392 if ((info.m_mask & wxTREE_MASK_IMAGE) == 0) {
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 );
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;
407 new_child
->m_owner
= this;
409 info
.m_mask
= oldMask
;
414 bool wxTreeCtrl::ExpandItem( long item
, int action
) {
415 wxTreeItem
*i
= FindItem( item
);
420 case wxTREE_EXPAND_EXPAND
:
421 gtk_tree_item_expand(GTK_TREE_ITEM(i
->m_widget
));
424 case wxTREE_EXPAND_COLLAPSE_RESET
:
425 case wxTREE_EXPAND_COLLAPSE
:
426 gtk_tree_item_collapse(GTK_TREE_ITEM(i
->m_widget
));
429 case wxTREE_EXPAND_TOGGLE
:
430 if ((i
->GetState() & wxTREE_STATE_EXPANDED
) == 0)
431 gtk_tree_item_expand(GTK_TREE_ITEM(i
->m_widget
));
433 gtk_tree_item_collapse(GTK_TREE_ITEM(i
->m_widget
));
440 void wxTreeCtrl::DeleteItem( long item
)
442 wxTreeItem
*pItem
= FindItem( item
);
443 wxCHECK_RET( pItem
!= NULL
, "wxTreeCtrl::DeleteItem: no such pItem." );
445 // pItem->m_parent->m_childlist.DeleteObject(pItem);
448 void wxTreeCtrl::DeleteChildren( long item
)
450 wxTreeItem
*pItem
= FindItem( item
);
451 wxCHECK_RET( pItem
!= NULL
, "wxTreeCtrl::DeleteChildren: no such pItem." );
453 pItem
->DeleteChildren();
456 bool wxTreeCtrl::DeleteAllItems()
464 bool wxTreeCtrl::GetItem( wxTreeItem &info ) const
466 wxTreeItem *i = FindItem( info.m_itemId );
467 if (!i) return FALSE;
473 long wxTreeCtrl::GetItemData( long item
) const
475 wxTreeItem
*i
= FindItem( item
);
480 wxString
wxTreeCtrl::GetItemText( long item
) const
482 wxTreeItem
*i
= FindItem( item
);
487 int wxTreeCtrl::GetItemImage(long item
) const
489 wxTreeItem
*i
= FindItem( item
);
490 return i
== 0 ? -1 : i
->GetImage();
493 long wxTreeCtrl::GetParent( long item
) const
495 wxTreeItem
*i
= FindItem( item
);
500 return i->m_parent->m_itemId;
505 long wxTreeCtrl::GetRootItem() const
507 if (m_anchor
) return m_anchor
->m_itemId
;
512 long wxTreeCtrl::GetSelection() const
514 return m_current ? m_current->GetItemId() : -1;
517 bool wxTreeCtrl::SelectItem(long itemId)
519 wxTreeItem *pItem = FindItem(itemId);
521 wxLogDebug("Can't select an item %d which doesn't exist.", itemId);
531 void wxTreeCtrl::SelectItem(wxTreeItem *item, bool bDoEvents )
533 if (m_current != item)
537 m_current->SetHilight( FALSE );
538 // RefreshLine( m_current );
541 m_current->SetHilight( TRUE );
542 // RefreshLine( m_current );
544 if (bDoEvents) m_current->SendSelected( this );
549 bool wxTreeCtrl::ItemHasChildren( long item
) const
551 wxTreeItem
*i
= FindItem( item
);
552 if (!i
) return FALSE
;
553 return i
->HasChildren();
556 void wxTreeCtrl::SetIndent( int indent
)
562 int wxTreeCtrl::GetIndent() const
568 bool wxTreeCtrl::SetItem( wxTreeItem &info )
570 wxTreeItem *i = FindItem( info.m_itemId );
571 if (!i) return FALSE;
573 i->SetItem( info, &dc );
578 bool wxTreeCtrl::SetItemData( long item, long data )
580 wxTreeItem *i = FindItem( item );
581 if (!i) return FALSE;
586 bool wxTreeCtrl::SetItemText( long item, const wxString &text )
588 wxTreeItem *i = FindItem( item );
589 if (!i) return FALSE;
591 i->SetText( text, &dc );
595 void wxTreeCtrl::SetItemImage(long item, int image, int imageSel) const
597 wxTreeItem *i = FindItem( item );
600 i->SetSelectedImage(imageSel);
604 long wxTreeCtrl::HitTest( const wxPoint& point, int &flags )
607 if (!m_anchor) return -1;
608 return m_anchor->HitTest( point, flags );
612 wxImageList
*wxTreeCtrl::GetImageList( int which
) const
614 if (which
== wxIMAGE_LIST_NORMAL
) return m_imageList
;
615 return m_smallImageList
;
618 void wxTreeCtrl::SetImageList( wxImageList
*imageList
, int which
)
620 if (which
== wxIMAGE_LIST_NORMAL
)
622 if (m_imageList
) delete m_imageList
;
623 m_imageList
= imageList
;
627 if (m_smallImageList
) delete m_smallImageList
;
628 m_smallImageList
= imageList
;
632 wxTreeItem
*wxTreeCtrl::FindItem( long itemId
) const {
633 if (!m_anchor
) return NULL
;
634 return m_anchor
->FindItem( itemId
);
638 wxTreeItem
*wxTreeCtrl::FindItem(GtkTreeItem
*item
) const {
639 if (!m_anchor
) return NULL
;
640 return m_anchor
->FindItem(item
);
644 //-----------------------------------------------------------------------------
646 //-----------------------------------------------------------------------------
648 IMPLEMENT_DYNAMIC_CLASS(wxTreeEvent
,wxCommandEvent
)
650 wxTreeEvent::wxTreeEvent( wxEventType commandType
, int id
) :
651 wxCommandEvent( commandType
, id
)
657 /* Bunch of old code might be useful */
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 );
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;
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 );
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;
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 );
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;
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));