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
) {
32 treeitem
->SendExpanding(treeitem
->m_owner
);
33 treeitem
->SendExpand(treeitem
->m_owner
);
36 void gtk_treeitem_collapse_callback( GtkWidget
*WXUNUSED(widget
), wxTreeItem
*treeitem
) {
39 treeitem
->SendCollapsing(treeitem
->m_owner
);
40 treeitem
->SendCollapse(treeitem
->m_owner
);
43 void gtk_treeitem_select_callback( GtkWidget
*WXUNUSED(widget
), wxTreeItem
*treeitem
) {
44 treeitem
->SendSelChanging(treeitem
->m_owner
);
45 treeitem
->m_state
|= wxTREE_STATE_SELECTED
;
46 treeitem
->SendSelChanged(treeitem
->m_owner
);
49 void gtk_treeitem_deselect_callback( GtkWidget
*WXUNUSED(widget
), wxTreeItem
*treeitem
) {
50 treeitem
->SendSelChanging(treeitem
->m_owner
);
51 treeitem
->m_state
&= !wxTREE_STATE_SELECTED
;
52 treeitem
->SendSelChanged(treeitem
->m_owner
);
55 IMPLEMENT_DYNAMIC_CLASS(wxTreeItem
, wxObject
)
57 wxTreeItem::wxTreeItem() {
66 m_parentwidget
= NULL
;
74 wxTreeItem::wxTreeItem(GtkWidget
*parent
, const wxTreeItem
&item
) {
77 m_itemId
= item
.m_itemId
;
78 m_state
= item
.m_state
;
79 m_stateMask
= item
.m_stateMask
;
80 m_image
= item
.m_image
;
83 m_selectedImage
= item
.m_selectedImage
;
84 m_children
= item
.m_children
;
85 m_childlist
= item
.m_childlist
;
87 m_parentwidget
= parent
;
94 void wxTreeItem::Create() {
95 wxASSERT(m_parentwidget
!= NULL
);
97 m_widget
= GTK_TREE_ITEM(gtk_tree_item_new_with_label ((char *)(const char *)m_text
));
98 gtk_container_add (GTK_CONTAINER(m_parentwidget
), GTK_WIDGET(m_widget
));
99 gtk_widget_show(GTK_WIDGET(m_widget
));
103 gtk_signal_connect(GTK_OBJECT(m_widget
), "select",
104 GTK_SIGNAL_FUNC(gtk_treeitem_select_callback
), (gpointer
)this );
106 gtk_signal_connect(GTK_OBJECT(m_widget
), "deselect",
107 GTK_SIGNAL_FUNC(gtk_treeitem_deselect_callback
), (gpointer
)this );
109 if (expand_handler
== 0)
110 expand_handler
= gtk_signal_connect(GTK_OBJECT(m_widget
), "expand",
111 GTK_SIGNAL_FUNC(gtk_treeitem_expand_callback
), (gpointer
)this );
113 if (collapse_handler
== 0)
114 collapse_handler
= gtk_signal_connect( GTK_OBJECT(m_widget
), "collapse",
115 GTK_SIGNAL_FUNC(gtk_treeitem_collapse_callback
), (gpointer
)this );
117 if ((m_mask
& wxTREE_MASK_CHILDREN
) != 0)
121 wxTreeItem::~wxTreeItem() {
125 if ((m_widget
!= NULL
) && (m_parentwidget
!= NULL
))
126 gtk_container_remove(GTK_CONTAINER(m_parentwidget
),
127 GTK_WIDGET(m_widget
));
128 // if (m_tree != NULL) {
129 // gtk_widget_destroy(GTK_WIDGET(m_tree));
133 // if (m_widget != NULL)
134 // gtk_widget_destroy(GTK_WIDGET(m_widget));
137 void wxTreeItem::AddSubtree() {
138 if (m_widget
== NULL
)
141 m_tree
= GTK_TREE(gtk_tree_new());
142 gtk_tree_item_set_subtree(GTK_TREE_ITEM(m_widget
), GTK_WIDGET(m_tree
));
143 gtk_widget_show(GTK_WIDGET(m_tree
));
146 gtk_tree_item_expand(m_widget
);
147 gtk_tree_item_collapse(m_widget
);
151 void wxTreeItem::AddChild(wxTreeItem
*child
) {
152 wxASSERT(child
!= NULL
);
154 m_childlist
.Append(child
);
157 bool wxTreeItem::HasChildren() {
158 return (m_childlist
.Number() != 0);
161 void wxTreeItem::DeleteChildren() {
164 long no
= GetChildrenNumber();
165 for (long i
=0; i
<no
; i
++)
166 if ((item
= GetChild(i
)) != 0)
170 if ((no
== 0) && (m_widget
!= NULL
))
171 gtk_tree_item_remove_subtree(m_widget
);
175 if ((m_mask
& wxTREE_MASK_CHILDREN
) != 0)
176 if (m_widget
!= NULL
)
177 if (m_widget
->subtree
== 0)
181 int wxTreeItem::NumberOfVisibleDescendents() {
183 long no
= GetChildrenNumber();
185 for (long i
=0; i
<no
; i
++)
186 if ((item
= GetChild(i
)) != 0)
187 num
+= item
->NumberOfVisibleDescendents();
194 wxTreeItem
*wxTreeItem::FindItem(long itemId
) const {
195 if (m_itemId
== itemId
) return (wxTreeItem
*)(this);
196 wxNode
*node
= m_childlist
.First();
198 wxTreeItem
*item
= (wxTreeItem
*)node
->Data();
199 wxTreeItem
*res
= item
->FindItem( itemId
);
200 if (res
) return (wxTreeItem
*)(res
);
206 wxTreeItem
*wxTreeItem::FindItem(GtkTreeItem
*item
) const {
207 if (m_widget
== item
)
208 return (wxTreeItem
*)(this);
209 wxNode
*node
= m_childlist
.First();
211 wxTreeItem
*i
= (wxTreeItem
*)node
->Data();
212 wxTreeItem
*res
= i
->FindItem(item
);
213 if (res
) return (wxTreeItem
*)(res
);
219 void wxTreeItem::PrepareEvent(wxTreeEvent
&event
) {
220 event
.m_item
.m_itemId
= m_itemId
;
221 event
.m_item
.m_state
= m_state
;
222 event
.m_item
.m_text
= m_text
;
223 event
.m_item
.m_image
= m_image
;
224 event
.m_item
.m_selectedImage
= m_selectedImage
;
225 event
.m_item
.m_children
= (GetChildrenNumber() > 0);
226 event
.m_item
.m_data
= m_data
;
229 // event.m_pointDrag.x = 0;
230 // event.m_pointDrag.y = 0;
233 void wxTreeItem::SendDelete(wxWindow
*target
) {
234 wxTreeEvent
event(wxEVT_COMMAND_TREE_DELETE_ITEM
, target
->GetId());
236 event
.SetEventObject(target
);
237 target
->ProcessEvent(event
);
240 void wxTreeItem::SendExpand(wxWindow
*target
) {
241 wxTreeEvent
event(wxEVT_COMMAND_TREE_ITEM_EXPANDED
, target
->GetId());
243 event
.SetEventObject(target
);
244 target
->ProcessEvent(event
);
247 void wxTreeItem::SendExpanding(wxWindow
*target
) {
248 wxTreeEvent
event(wxEVT_COMMAND_TREE_ITEM_EXPANDING
, target
->GetId());
250 event
.SetEventObject(target
);
251 target
->ProcessEvent(event
);
254 void wxTreeItem::SendCollapse(wxWindow
*target
) {
255 wxTreeEvent
event(wxEVT_COMMAND_TREE_ITEM_COLLAPSED
, target
->GetId());
257 event
.SetEventObject(target
);
258 target
->ProcessEvent(event
);
261 void wxTreeItem::SendCollapsing(wxWindow
*target
) {
262 wxTreeEvent
event(wxEVT_COMMAND_TREE_ITEM_COLLAPSING
, target
->GetId());
264 event
.SetEventObject(target
);
265 target
->ProcessEvent(event
);
268 void wxTreeItem::SendSelChanged(wxWindow
*target
) {
269 wxTreeEvent
event(wxEVT_COMMAND_TREE_SEL_CHANGED
, target
->GetId());
271 event
.SetEventObject(target
);
272 target
->ProcessEvent(event
);
275 void wxTreeItem::SendSelChanging(wxWindow
*target
) {
276 wxTreeEvent
event(wxEVT_COMMAND_TREE_SEL_CHANGING
, target
->GetId());
278 event
.SetEventObject(target
);
279 target
->ProcessEvent(event
);
282 //-----------------------------------------------------------------------------
284 //-----------------------------------------------------------------------------
286 IMPLEMENT_DYNAMIC_CLASS(wxTreeCtrl
, wxScrolledWindow
)
288 wxTreeCtrl::wxTreeCtrl() {
293 m_smallImageList
= NULL
;
296 wxTreeCtrl::wxTreeCtrl(wxWindow
*parent
, wxWindowID id
,
297 const wxPoint
& pos
, const wxSize
& size
,
298 long style
, const wxString
& name
) {
303 m_smallImageList
= NULL
;
304 Create( parent
, id
, pos
, size
, style
, name
);
307 wxTreeCtrl::~wxTreeCtrl() {
311 bool wxTreeCtrl::Create(wxWindow
*parent
, wxWindowID id
,
312 const wxPoint
& pos
, const wxSize
& size
,
313 long style
, const wxString
& name
) {
316 PreCreation( parent
, id
, pos
, size
, style
, name
);
318 m_widget
= gtk_scrolled_window_new(NULL
, NULL
);
319 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(m_widget
),
320 GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
322 m_tree
= GTK_TREE(gtk_tree_new());
325 gtk_signal_connect( GTK_OBJECT(m_tree), "selection_changed",
326 GTK_SIGNAL_FUNC(gtk_treectrl_selection_changed_callback), (gpointer)this);
327 gtk_signal_connect( GTK_OBJECT(m_tree), "select_child",
328 GTK_SIGNAL_FUNC(gtk_treectrl_select_child_callback), (gpointer)this);
329 gtk_signal_connect( GTK_OBJECT(m_tree), "unselect_child",
330 GTK_SIGNAL_FUNC(gtk_treectrl_unselect_child_callback), (gpointer)this);
333 gtk_container_add(GTK_CONTAINER(m_widget
), GTK_WIDGET(m_tree
));
334 gtk_widget_show(GTK_WIDGET(m_tree
));
338 gtk_widget_realize(GTK_WIDGET(m_tree
));
345 int wxTreeCtrl::GetCount() const
347 if (!m_anchor
) return 0;
348 return m_anchor
->NumberOfVisibleDescendents();
351 long wxTreeCtrl::InsertItem(long parent
, const wxString
& label
,
352 int image
, int selImage
, long insertAfter
) {
354 if (!label
.IsNull() || (label
== "")) {
356 item
.m_mask
|= wxTREE_MASK_TEXT
;
360 item
.m_image
= image
;
361 item
.m_mask
|= wxTREE_MASK_IMAGE
;
365 item
.m_selectedImage
= selImage
;
366 item
.m_mask
|= wxTREE_MASK_SELECTED_IMAGE
;
369 return InsertItem(parent
, item
, insertAfter
);
372 long wxTreeCtrl::InsertItem( long parent
, wxTreeItem
&info
, long WXUNUSED(insertAfter
) ) {
373 int oldMask
= info
.m_mask
;
375 wxTreeItem
*p
= NULL
;
376 wxTreeItem
*new_child
;
382 p
= FindItem(parent
);
386 if ((info
.m_mask
& wxTREE_MASK_HANDLE
) == 0) {
388 info
.m_itemId
= m_lastId
;
389 info
.m_mask
|= wxTREE_MASK_HANDLE
;
395 if (p
->m_tree
== NULL
)
398 new_child
= new wxTreeItem(GTK_WIDGET(p
->m_tree
), info
);
399 p
->AddChild(new_child
);
400 gtk_widget_draw_default(GTK_WIDGET(m_tree
));
402 new_child
= new wxTreeItem(GTK_WIDGET(m_tree
), info
);
403 m_anchor
= new_child
;
406 /* Disabled until wxImageList q solved >>> seems it solved */
409 if ((new_child->m_mask & wxTREE_MASK_IMAGE) != 0) {
410 if (m_imageList != NULL) {
411 // if ((bmp = m_imageList->GetBitmap(new_child->m_image)) != NULL) {
412 if ((bmp = m_imageList->GetBitmap(0)) != NULL) {
414 GdkBitmap *mask = NULL;
415 if (bmp->GetMask()) mask = bmp->GetMask()->GetBitmap();
416 GtkWidget *pixmap = gtk_pixmap_new(bmp->GetPixmap(), mask);
418 gtk_widget_unref(new_child->m_widget->plus_pix_widget);
419 gtk_container_remove(GTK_CONTAINER(new_child->m_widget->pixmaps_box),
420 new_child->m_widget->plus_pix_widget);
421 gtk_container_add(GTK_CONTAINER(new_child->m_widget->pixmaps_box),
423 gtk_widget_show(pixmap);
424 GTK_TREE_ITEM(new_child->m_widget)->plus_pix_widget = pixmap;
428 if ((bmp = m_imageList->GetBitmap(1)) != NULL) {
430 GdkBitmap *mask = NULL;
431 if (bmp->GetMask()) mask = bmp->GetMask()->GetBitmap();
432 GtkWidget *pixmap = gtk_pixmap_new(bmp->GetPixmap(), mask);
434 gtk_widget_unref(new_child->m_widget->minus_pix_widget);
435 //gtk_container_remove(GTK_CONTAINER(new_child->m_widget->pixmaps_box),
436 // new_child->m_widget->plus_pix_widget);
437 //gtk_container_add(GTK_CONTAINER(new_child->m_widget->pixmaps_box),
439 gtk_widget_show(pixmap);
440 GTK_TREE_ITEM(new_child->m_widget)->minus_pix_widget = pixmap;
447 new_child
->m_owner
= this;
449 info
.m_mask
= oldMask
;
454 bool wxTreeCtrl::ExpandItem( long item
, int action
) {
455 wxTreeItem
*i
= FindItem( item
);
460 case wxTREE_EXPAND_EXPAND
:
461 gtk_tree_item_expand(GTK_TREE_ITEM(i
->m_widget
));
464 case wxTREE_EXPAND_COLLAPSE_RESET
:
465 case wxTREE_EXPAND_COLLAPSE
:
466 gtk_tree_item_collapse(GTK_TREE_ITEM(i
->m_widget
));
469 case wxTREE_EXPAND_TOGGLE
:
470 if ((i
->GetState() & wxTREE_STATE_EXPANDED
) == 0)
471 gtk_tree_item_expand(GTK_TREE_ITEM(i
->m_widget
));
473 gtk_tree_item_collapse(GTK_TREE_ITEM(i
->m_widget
));
480 void wxTreeCtrl::DeleteItem( long item
)
482 wxTreeItem
*pItem
= FindItem( item
);
483 wxCHECK_RET( pItem
!= NULL
, "wxTreeCtrl::DeleteItem: no such pItem." );
485 // pItem->m_parent->m_childlist.DeleteObject(pItem);
488 void wxTreeCtrl::DeleteChildren( long item
)
490 wxTreeItem
*pItem
= FindItem( item
);
491 wxCHECK_RET( pItem
!= NULL
, "wxTreeCtrl::DeleteChildren: no such pItem." );
493 pItem
->DeleteChildren();
496 bool wxTreeCtrl::DeleteAllItems()
504 bool wxTreeCtrl::GetItem( wxTreeItem &info ) const
506 wxTreeItem *i = FindItem( info.m_itemId );
507 if (!i) return FALSE;
513 long wxTreeCtrl::GetItemData( long item
) const
515 wxTreeItem
*i
= FindItem( item
);
520 wxString
wxTreeCtrl::GetItemText( long item
) const
522 wxTreeItem
*i
= FindItem( item
);
527 int wxTreeCtrl::GetItemImage(long item
) const
529 wxTreeItem
*i
= FindItem( item
);
530 return i
== 0 ? -1 : i
->GetImage();
533 long wxTreeCtrl::GetParent( long item
) const
535 wxTreeItem
*i
= FindItem( item
);
540 return i->m_parent->m_itemId;
545 long wxTreeCtrl::GetRootItem() const
547 if (m_anchor
) return m_anchor
->m_itemId
;
552 long wxTreeCtrl::GetSelection() const
554 return m_current ? m_current->GetItemId() : -1;
557 bool wxTreeCtrl::SelectItem(long itemId)
559 wxTreeItem *pItem = FindItem(itemId);
561 wxLogDebug("Can't select an item %d which doesn't exist.", itemId);
571 void wxTreeCtrl::SelectItem(wxTreeItem *item, bool bDoEvents )
573 if (m_current != item)
577 m_current->SetHilight( FALSE );
578 // RefreshLine( m_current );
581 m_current->SetHilight( TRUE );
582 // RefreshLine( m_current );
584 if (bDoEvents) m_current->SendSelected( this );
589 bool wxTreeCtrl::ItemHasChildren( long item
) const
591 wxTreeItem
*i
= FindItem( item
);
592 if (!i
) return FALSE
;
593 return i
->HasChildren();
596 void wxTreeCtrl::SetIndent( int indent
)
602 int wxTreeCtrl::GetIndent() const
608 bool wxTreeCtrl::SetItem( wxTreeItem &info )
610 wxTreeItem *i = FindItem( info.m_itemId );
611 if (!i) return FALSE;
613 i->SetItem( info, &dc );
618 bool wxTreeCtrl::SetItemData( long item, long data )
620 wxTreeItem *i = FindItem( item );
621 if (!i) return FALSE;
626 bool wxTreeCtrl::SetItemText( long item, const wxString &text )
628 wxTreeItem *i = FindItem( item );
629 if (!i) return FALSE;
631 i->SetText( text, &dc );
635 void wxTreeCtrl::SetItemImage(long item, int image, int imageSel) const
637 wxTreeItem *i = FindItem( item );
640 i->SetSelectedImage(imageSel);
644 long wxTreeCtrl::HitTest( const wxPoint& point, int &flags )
647 if (!m_anchor) return -1;
648 return m_anchor->HitTest( point, flags );
652 wxImageList
*wxTreeCtrl::GetImageList( int which
) const
654 if (which
== wxIMAGE_LIST_NORMAL
) return m_imageList
;
655 return m_smallImageList
;
658 void wxTreeCtrl::SetImageList( wxImageList
*imageList
, int which
)
660 if (which
== wxIMAGE_LIST_NORMAL
)
662 if (m_imageList
) delete m_imageList
;
663 m_imageList
= imageList
;
667 if (m_smallImageList
) delete m_smallImageList
;
668 m_smallImageList
= imageList
;
672 wxTreeItem
*wxTreeCtrl::FindItem( long itemId
) const {
673 if (!m_anchor
) return NULL
;
674 return m_anchor
->FindItem( itemId
);
678 wxTreeItem
*wxTreeCtrl::FindItem(GtkTreeItem
*item
) const {
679 if (!m_anchor
) return NULL
;
680 return m_anchor
->FindItem(item
);
684 //-----------------------------------------------------------------------------
686 //-----------------------------------------------------------------------------
688 IMPLEMENT_DYNAMIC_CLASS(wxTreeEvent
,wxCommandEvent
)
690 wxTreeEvent::wxTreeEvent( wxEventType commandType
, int id
) :
691 wxCommandEvent( commandType
, id
)
697 /* Bunch of old code might be useful */
701 if ((bmp = m_imageList->GetItem(0))->Ok()) {
702 GdkBitmap *mask = NULL;
703 if (bmp->GetMask()) mask = bmp->GetMask()->GetBitmap();
704 GtkWidget *pixmap = gtk_pixmap_new( bmp->GetPixmap(), mask );
706 gtk_widget_set_parent(pixmap, GTK_WIDGET(new_child->m_widget));
707 gtk_widget_show(pixmap);
708 GTK_TREE_ITEM(new_child->m_widget)->pixmaps_box = pixmap;
711 if ((bmp = m_imageList->GetItem(1))->Ok()) {
712 GdkBitmap *mask = NULL;
713 if (bmp->GetMask()) mask = bmp->GetMask()->GetBitmap();
714 GtkWidget *pixmap = gtk_pixmap_new( bmp->GetPixmap(), mask );
716 gtk_widget_set_parent(pixmap, GTK_WIDGET(new_child->m_widget));
717 gtk_widget_show(pixmap);
718 GTK_TREE_ITEM(new_child->m_widget)->plus_pix_widget = pixmap;
721 if ((bmp = m_imageList->GetItem(2))->Ok()) {
722 GdkBitmap *mask = NULL;
723 if (bmp->GetMask()) mask = bmp->GetMask()->GetBitmap();
724 GtkWidget *pixmap = gtk_pixmap_new( bmp->GetPixmap(), mask );
726 gtk_widget_set_parent(pixmap, GTK_WIDGET(new_child->m_widget));
727 gtk_widget_show(pixmap);
728 GTK_TREE_ITEM(new_child->m_widget)->minus_pix_widget = pixmap;
732 if (p->m_childlist.Number() == 1) {
733 gtk_tree_item_collapse(GTK_TREE_ITEM(p->m_widget));
734 gtk_tree_item_expand(GTK_TREE_ITEM(p->m_widget));