X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/29e461a210d5d83a8fe88a9bd9dceaf8abc32816..ff8cb900da92489dd87712e409bfd4c1f5eacfb8:/src/gtk/dataview.cpp diff --git a/src/gtk/dataview.cpp b/src/gtk/dataview.cpp index a50f37aa30..a44600da4e 100644 --- a/src/gtk/dataview.cpp +++ b/src/gtk/dataview.cpp @@ -25,7 +25,6 @@ #endif #include "wx/stockitem.h" -#include "wx/calctrl.h" #include "wx/popupwin.h" #include "wx/listimpl.cpp" @@ -35,6 +34,7 @@ #include "wx/gtk/private/gdkconv.h" #include "wx/gtk/private/list.h" +#include "wx/gtk/private/event.h" using namespace wxGTKImpl; class wxGtkDataViewModelNotifier; @@ -380,6 +380,7 @@ public: // Insert into m_nodes so that the order of nodes in m_nodes is the // same as the order of their corresponding IDs in m_children: const unsigned int count = m_nodes.GetCount(); + bool inserted = false; for (unsigned i = 0; i < count; i++) { wxGtkTreeModelNode *node = m_nodes[i]; @@ -387,9 +388,12 @@ public: if ( (unsigned)posInChildren >= pos ) { m_nodes.Insert(child, i); + inserted = true; break; } } + if ( !inserted ) + m_nodes.Add(child); m_children.Insert( id, pos ); } @@ -428,6 +432,20 @@ public: } } + // returns position of child node for given item in children list or wxNOT_FOUND + int FindChildByItem(const wxDataViewItem& item) const + { + const void* itemId = item.GetID(); + const wxGtkTreeModelChildren& nodes = m_children; + const int len = nodes.size(); + for ( int i = 0; i < len; i++ ) + { + if ( nodes[i] == itemId ) + return i; + } + return wxNOT_FOUND; + } + wxGtkTreeModelNode* GetParent() { return m_parent; } wxGtkTreeModelNodes &GetNodes() @@ -1206,7 +1224,6 @@ struct _GtkWxCellRenderer /*< private >*/ wxDataViewCustomRenderer *cell; - guint32 last_click; }; struct _GtkWxCellRendererClass @@ -1291,7 +1308,6 @@ static void gtk_wx_cell_renderer_init (GtkWxCellRenderer *cell) { cell->cell = NULL; - cell->last_click = 0; } static void @@ -1507,37 +1523,27 @@ gtk_wx_cell_renderer_activate( unsigned int model_col = cell->GetOwner()->GetModelColumn(); - if (!event) + if ( !event ) { - bool ret = false; - // activated by - if (cell->Activate( renderrect, model, item, model_col )) - ret = true; - - return ret; + return cell->ActivateCell(renderrect, model, item, model_col, NULL); } - else if (event->type == GDK_BUTTON_PRESS) + else if ( event->type == GDK_BUTTON_PRESS ) { - GdkEventButton *button_event = (GdkEventButton*) event; - wxPoint pt( ((int) button_event->x) - renderrect.x, - ((int) button_event->y) - renderrect.y ); - - bool ret = false; - if (button_event->button == 1) + GdkEventButton *button_event = (GdkEventButton*)event; + if ( button_event->button == 1 ) { - if (cell->LeftClick( pt, renderrect, model, item, model_col )) - ret = true; - // TODO: query system double-click time - if (button_event->time - wxrenderer->last_click < 400) - if (cell->Activate( renderrect, model, item, model_col )) - ret = true; - } - wxrenderer->last_click = button_event->time; + wxMouseEvent mouse_event(wxEVT_LEFT_DOWN); + InitMouseEvent(ctrl, mouse_event, button_event); - return ret; + mouse_event.m_x -= renderrect.x; + mouse_event.m_y -= renderrect.y; + + return cell->ActivateCell(renderrect, model, item, model_col, &mouse_event); + } } + wxLogDebug("unexpected event type in gtk_wx_cell_renderer_activate()"); return false; } @@ -2564,11 +2570,13 @@ void wxDataViewProgressRenderer::GTKSetLabel() // Take care to not use GetOwner() here if the label is empty, we can be // called from ctor when GetOwner() is still NULL in this case. - g_value_set_string( &gvalue, - m_label.empty() ? "" - : wxGTK_CONV_FONT(m_label, - GetOwner()->GetOwner()->GetFont()) - ); + wxScopedCharBuffer buf; + if ( m_label.empty() ) + buf = wxScopedCharBuffer::CreateNonOwned(""); + else + buf = wxGTK_CONV_FONT(m_label, GetOwner()->GetOwner()->GetFont()); + + g_value_set_string( &gvalue, buf); g_object_set_property( G_OBJECT(m_renderer), "text", &gvalue ); g_value_unset( &gvalue ); @@ -2793,108 +2801,6 @@ bool wxDataViewChoiceByIndexRenderer::GetValue( wxVariant &value ) const return true; } -// --------------------------------------------------------- -// wxDataViewDateRenderer -// --------------------------------------------------------- - -class wxDataViewDateRendererPopupTransient: public wxPopupTransientWindow -{ -public: - wxDataViewDateRendererPopupTransient( wxWindow* parent, wxDateTime *value, - wxDataViewModel *model, const wxDataViewItem &item, unsigned int col ) : - wxPopupTransientWindow( parent, wxBORDER_SIMPLE ) - { - m_model = model; - m_item = item; - m_col = col; - m_cal = new wxCalendarCtrl( this, -1, *value ); - wxBoxSizer *sizer = new wxBoxSizer( wxHORIZONTAL ); - sizer->Add( m_cal, 1, wxGROW ); - SetSizer( sizer ); - sizer->Fit( this ); - } - - virtual void OnDismiss() - { - } - - void OnCalendar( wxCalendarEvent &event ); - - wxCalendarCtrl *m_cal; - wxDataViewModel *m_model; - wxDataViewItem m_item; - unsigned int m_col; - -private: - DECLARE_EVENT_TABLE() -}; - -BEGIN_EVENT_TABLE(wxDataViewDateRendererPopupTransient,wxPopupTransientWindow) - EVT_CALENDAR( -1, wxDataViewDateRendererPopupTransient::OnCalendar ) -END_EVENT_TABLE() - -void wxDataViewDateRendererPopupTransient::OnCalendar( wxCalendarEvent &event ) -{ - m_model->ChangeValue( event.GetDate(), m_item, m_col ); - DismissAndNotify(); -} - -IMPLEMENT_CLASS(wxDataViewDateRenderer, wxDataViewCustomRenderer) - -wxDataViewDateRenderer::wxDataViewDateRenderer( const wxString &varianttype, - wxDataViewCellMode mode, int align ) : - wxDataViewCustomRenderer( varianttype, mode, align ) -{ - SetMode(mode); - SetAlignment(align); -} - -bool wxDataViewDateRenderer::SetValue( const wxVariant &value ) -{ - m_date = value.GetDateTime(); - - return true; -} - -bool wxDataViewDateRenderer::GetValue( wxVariant &WXUNUSED(value) ) const -{ - return false; -} - -bool wxDataViewDateRenderer::Render( wxRect cell, wxDC *dc, int state ) -{ - dc->SetFont( GetOwner()->GetOwner()->GetFont() ); - wxString tmp = m_date.FormatDate(); - RenderText( tmp, 0, cell, dc, state ); - return true; -} - -wxSize wxDataViewDateRenderer::GetSize() const -{ - wxString tmp = m_date.FormatDate(); - wxCoord x,y,d; - GetView()->GetTextExtent( tmp, &x, &y, &d ); - return wxSize(x,y+d); -} - -bool wxDataViewDateRenderer::Activate( const wxRect& WXUNUSED(cell), wxDataViewModel *model, - const wxDataViewItem &item, unsigned int col ) -{ - wxVariant variant; - model->GetValue( variant, item, col ); - wxDateTime value = variant.GetDateTime(); - - wxDataViewDateRendererPopupTransient *popup = new wxDataViewDateRendererPopupTransient( - GetOwner()->GetOwner()->GetParent(), &value, model, item, col ); - wxPoint pos = wxGetMousePosition(); - popup->Move( pos ); - popup->Layout(); - popup->Popup( popup->m_cal ); - - return true; -} - - // --------------------------------------------------------- // wxDataViewIconTextRenderer // --------------------------------------------------------- @@ -3282,14 +3188,6 @@ bool wxDataViewColumn::IsSortable() const return gtk_tree_view_column_get_clickable( column ); } -void wxDataViewColumn::SetAsSortKey( bool WXUNUSED(sort) ) -{ - // it might not make sense to have this function in wxHeaderColumn at - // all in fact, changing of the sort order should only be done using the - // associated control API - wxFAIL_MSG( "not implemented" ); -} - bool wxDataViewColumn::IsSortKey() const { GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(m_column); @@ -3790,15 +3688,56 @@ bool wxDataViewCtrlInternal::ItemAdded( const wxDataViewItem &parent, const wxDa wxCHECK_MSG(parent_node, false, "Did you forget a call to ItemAdded()? The parent node is unknown to the wxGtkTreeModel"); - wxDataViewItemArray siblings; - m_wx_model->GetChildren(parent, siblings); - int itemPos = siblings.Index(item, /*fromEnd=*/true); - wxCHECK_MSG( itemPos != wxNOT_FOUND, false, "adding non-existent item?" ); + wxDataViewItemArray modelSiblings; + m_wx_model->GetChildren(parent, modelSiblings); + const int modelSiblingsSize = modelSiblings.size(); + + int posInModel = modelSiblings.Index(item, /*fromEnd=*/true); + wxCHECK_MSG( posInModel != wxNOT_FOUND, false, "adding non-existent item?" ); + + const wxGtkTreeModelChildren& nodeSiblings = parent_node->GetChildren(); + const int nodeSiblingsSize = nodeSiblings.size(); + + int nodePos = 0; + + if ( posInModel == modelSiblingsSize - 1 ) + { + nodePos = nodeSiblingsSize; + } + else if ( modelSiblingsSize == nodeSiblingsSize + 1 ) + { + // This is the simple case when our node tree already matches the + // model and only this one item is missing. + nodePos = posInModel; + } + else + { + // It's possible that a larger discrepancy between the model and + // our realization exists. This can happen e.g. when adding a bunch + // of items to the model and then calling ItemsAdded() just once + // afterwards. In this case, we must find the right position by + // looking at sibling items. + + // append to the end if we won't find a better position: + nodePos = nodeSiblingsSize; + + for ( int nextItemPos = posInModel + 1; + nextItemPos < modelSiblingsSize; + nextItemPos++ ) + { + int nextNodePos = parent_node->FindChildByItem(modelSiblings[nextItemPos]); + if ( nextNodePos != wxNOT_FOUND ) + { + nodePos = nextNodePos; + break; + } + } + } if (m_wx_model->IsContainer( item )) - parent_node->InsertNode( new wxGtkTreeModelNode( parent_node, item, this ), itemPos ); + parent_node->InsertNode( new wxGtkTreeModelNode( parent_node, item, this ), nodePos ); else - parent_node->InsertLeaf( item.GetID(), itemPos ); + parent_node->InsertLeaf( item.GetID(), nodePos ); } ScheduleRefresh(); @@ -4540,22 +4479,21 @@ gtk_dataview_button_press_callback( GtkWidget *WXUNUSED(widget), GtkTreeViewColumn *column = NULL; gint cell_x = 0; gint cell_y = 0; - if (gtk_tree_view_get_path_at_pos( + gtk_tree_view_get_path_at_pos + ( GTK_TREE_VIEW(dv->GtkGetTreeView()), (int) gdk_event->x, (int) gdk_event->y, path.ByRef(), &column, &cell_x, - &cell_y)) - { - if (path) - { - wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU, dv->GetId() ); - event.SetItem(dv->GTKPathToItem(path)); - event.SetModel( dv->GetModel() ); - return dv->HandleWindowEvent( event ); - } - } + &cell_y + ); + + wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU, dv->GetId() ); + if (path) + event.SetItem(dv->GTKPathToItem(path)); + event.SetModel( dv->GetModel() ); + return dv->HandleWindowEvent( event ); } return FALSE; @@ -4618,6 +4556,8 @@ bool wxDataViewCtrl::Create(wxWindow *parent, m_treeview = gtk_tree_view_new(); gtk_container_add (GTK_CONTAINER (m_widget), m_treeview); + m_focusWidget = GTK_WIDGET(m_treeview); + g_signal_connect (m_treeview, "size_allocate", G_CALLBACK (gtk_dataviewctrl_size_callback), this);