X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/f6bcfd974ef26faf6f91a62cac09827e09463fd1..87df17a11b0017d31c09f767bd921abb27193bee:/src/generic/listctrl.cpp?ds=sidebyside diff --git a/src/generic/listctrl.cpp b/src/generic/listctrl.cpp index 63e50fb380..ba33085757 100644 --- a/src/generic/listctrl.cpp +++ b/src/generic/listctrl.cpp @@ -25,10 +25,36 @@ #include "wx/generic/imaglist.h" #include "wx/dynarray.h" +#ifdef __WXGTK__ +#include +#include "wx/gtk/win_gtk.h" +#endif + #ifndef wxUSE_GENERIC_LIST_EXTENSIONS #define wxUSE_GENERIC_LIST_EXTENSIONS 1 #endif +// ---------------------------------------------------------------------------- +// events +// ---------------------------------------------------------------------------- + +DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_DRAG) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_RDRAG) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_END_LABEL_EDIT) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ITEM) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_GET_INFO) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_SET_INFO) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_SELECTED) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_DESELECTED) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_KEY_DOWN) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_INSERT_ITEM) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_CLICK) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_ACTIVATED) + // ============================================================================ // private classes // ============================================================================ @@ -259,6 +285,7 @@ public: const wxValidator& validator = wxDefaultValidator, const wxString &name = "listctrltextctrl" ); void OnChar( wxKeyEvent &event ); + void OnKeyUp( wxKeyEvent &event ); void OnKillFocus( wxFocusEvent &event ); private: @@ -310,7 +337,9 @@ public: void RefreshLine( wxListLineData *line ); void OnPaint( wxPaintEvent &event ); void HilightAll( bool on ); - void SendNotify( wxListLineData *line, wxEventType command ); + void SendNotify( wxListLineData *line, + wxEventType command, + wxPoint point = wxDefaultPosition ); void FocusLine( wxListLineData *line ); void UnfocusLine( wxListLineData *line ); void SelectLine( wxListLineData *line ); @@ -730,6 +759,23 @@ void wxListLineData::CalculateSize( wxDC *dc, int spacing ) m_bound_all.width = 0; m_bound_all.height = 0; wxNode *node = m_items.First(); + if (node) + { + wxListItemData *item = (wxListItemData*)node->Data(); + if (item->HasImage()) + { + int w = 0; + int h = 0; + m_owner->GetImageSize( item->GetImage(), w, h ); + m_bound_icon.width = w; + m_bound_icon.height = h; + } + else + { + m_bound_icon.width = 0; + m_bound_icon.height = 0; + } + } while (node) { wxListItemData *item = (wxListItemData*)node->Data(); @@ -746,6 +792,8 @@ void wxListLineData::CalculateSize( wxDC *dc, int spacing ) m_bound_all.height = lh; node = node->Next(); } + m_bound_label.width = m_bound_all.width; + m_bound_label.height = m_bound_all.height; break; } } @@ -1173,6 +1221,15 @@ wxListHeaderWindow::~wxListHeaderWindow( void ) void wxListHeaderWindow::DoDrawRect( wxDC *dc, int x, int y, int w, int h ) { +#ifdef __WXGTK__ + GtkStateType state = GTK_STATE_NORMAL; + if (!m_parent->IsEnabled()) state = GTK_STATE_INSENSITIVE; + + x = dc->XLOG2DEV( x ); + + gtk_paint_box (m_wxwindow->style, GTK_PIZZA(m_wxwindow)->bin_window, state, GTK_SHADOW_OUT, + (GdkRectangle*) NULL, m_wxwindow, "button", x-1, y-1, w+2, h+2); +#else const int m_corner = 1; dc->SetBrush( *wxTRANSPARENT_BRUSH ); @@ -1192,6 +1249,7 @@ void wxListHeaderWindow::DoDrawRect( wxDC *dc, int x, int y, int w, int h ) dc->DrawRectangle( x, y, 1, h ); // left (outer) dc->DrawLine( x, y+h-1, x+1, y+h-1 ); dc->DrawLine( x+w-1, y, x+w-1, y+1 ); +#endif } // shift the DC origin to match the position of the main window horz @@ -1212,7 +1270,12 @@ void wxListHeaderWindow::AdjustDC(wxDC& dc) void wxListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) { +#ifdef __WXGTK__ + wxClientDC dc( this ); +#else wxPaintDC dc( this ); +#endif + PrepareDC( dc ); AdjustDC( dc ); @@ -1231,7 +1294,8 @@ void wxListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) // do *not* use the listctrl colour for headers - one day we will have a // function to set it separately - dc.SetTextForeground( *wxBLACK ); + //dc.SetTextForeground( *wxBLACK ); + dc.SetTextForeground(wxSystemSettings::GetSystemColour( wxSYS_COLOUR_WINDOWTEXT )); int x = 1; // left of the header rect const int y = 1; // top @@ -1297,12 +1361,12 @@ void wxListHeaderWindow::OnMouse( wxMouseEvent &event ) { // we want to work with logical coords #if wxUSE_GENERIC_LIST_EXTENSIONS - int x, y; - m_owner->CalcUnscrolledPosition(event.GetX(), event.GetY(), &x, &y); + int x; + m_owner->CalcUnscrolledPosition(event.GetX(), 0, &x, NULL); #else // !wxUSE_GENERIC_LIST_EXTENSIONS int x = event.GetX(); - int y = event.GetY(); #endif // wxUSE_GENERIC_LIST_EXTENSIONS + int y = event.GetY(); if (m_isDragging) { @@ -1434,6 +1498,7 @@ IMPLEMENT_DYNAMIC_CLASS(wxListTextCtrl,wxTextCtrl); BEGIN_EVENT_TABLE(wxListTextCtrl,wxTextCtrl) EVT_CHAR (wxListTextCtrl::OnChar) + EVT_KEY_UP (wxListTextCtrl::OnKeyUp) EVT_KILL_FOCUS (wxListTextCtrl::OnKillFocus) END_EVENT_TABLE() @@ -1487,6 +1552,21 @@ void wxListTextCtrl::OnChar( wxKeyEvent &event ) event.Skip(); } +void wxListTextCtrl::OnKeyUp( wxKeyEvent &event ) +{ + // auto-grow the textctrl: + wxSize parentSize = m_owner->GetSize(); + wxPoint myPos = GetPosition(); + wxSize mySize = GetSize(); + int sx, sy; + GetTextExtent(GetValue() + _T("MM"), &sx, &sy); + if (myPos.x + sx > parentSize.x) sx = parentSize.x - myPos.x; + if (mySize.x > sx) sx = mySize.x; + SetSize(sx, -1); + + event.Skip(); +} + void wxListTextCtrl::OnKillFocus( wxFocusEvent &WXUNUSED(event) ) { if (!wxPendingDelete.Member(this)) @@ -1615,6 +1695,10 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) wxPaintDC dc( this ); PrepareDC( dc ); + int dev_x = 0; + int dev_y = 0; + CalcScrolledPosition( 0, 0, &dev_x, &dev_y ); + if (m_dirty) return; if (m_lines.GetCount() == 0) return; @@ -1625,6 +1709,9 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) if (m_mode & wxLC_REPORT) { + wxPen pen(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DLIGHT), 1, wxSOLID); + wxSize clientSize = GetClientSize(); + int lineSpacing = 0; wxListLineData *line = &m_lines[0]; int dummy = 0; @@ -1635,9 +1722,44 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) size_t i_to = y_s / lineSpacing + m_visibleLines+2; if (i_to >= m_lines.GetCount()) i_to = m_lines.GetCount(); - for (size_t i = y_s / lineSpacing; i < i_to; i++) + size_t i; + for (i = y_s / lineSpacing; i < i_to; i++) { m_lines[i].Draw( &dc ); + // Draw horizontal rule if required + if (GetWindowStyle() & wxLC_HRULES) + { + dc.SetPen(pen); + dc.SetBrush(* wxTRANSPARENT_BRUSH); + dc.DrawLine(0 - dev_x , i*lineSpacing , clientSize.x - dev_x , i*lineSpacing ); + } + } + + // Draw last horizontal rule + if ((i > (size_t) (y_s / lineSpacing)) && (GetWindowStyle() & wxLC_HRULES)) + { + dc.SetPen(pen); + dc.SetBrush(* wxTRANSPARENT_BRUSH); + dc.DrawLine(0 - dev_x , i*lineSpacing , clientSize.x - dev_x , i*lineSpacing ); + } + + // Draw vertical rules if required + if ((GetWindowStyle() & wxLC_VRULES) && (GetItemCount() > 0)) + { + int col = 0; + wxRect firstItemRect; + wxRect lastItemRect; + GetItemRect(0, firstItemRect); + GetItemRect(GetItemCount() - 1, lastItemRect); + int x = firstItemRect.GetX(); + dc.SetPen(pen); + dc.SetBrush(* wxTRANSPARENT_BRUSH); + for (col = 0; col < GetColumnCount(); col++) + { + int colWidth = GetColumnWidth(col); + x += colWidth ; + dc.DrawLine(x - dev_x, firstItemRect.GetY() - 1 - dev_y, x - dev_x, lastItemRect.GetBottom() + 1 - dev_y); + } } } else @@ -1664,11 +1786,18 @@ void wxListMainWindow::HilightAll( bool on ) } } -void wxListMainWindow::SendNotify( wxListLineData *line, wxEventType command ) +void wxListMainWindow::SendNotify( wxListLineData *line, + wxEventType command, + wxPoint point ) { wxListEvent le( command, GetParent()->GetId() ); le.SetEventObject( GetParent() ); le.m_itemIndex = GetIndexOfLine( line ); + + // set only for events which have position + if ( point != wxDefaultPosition ) + le.m_pointDrag = point; + line->GetItem( 0, le.m_item ); GetParent()->GetEventHandler()->ProcessEvent( le ); // GetParent()->GetEventHandler()->AddPendingEvent( le ); @@ -1703,7 +1832,7 @@ void wxListMainWindow::DeleteLine( wxListLineData *line ) void wxListMainWindow::EditLabel( long item ) { - wxCHECK_RET( ((size_t)item < m_lines.GetCount()), + wxCHECK_RET( ((size_t)item < m_lines.GetCount()), wxT("wrong index in wxListCtrl::Edit()") ); m_currentEdit = &m_lines[(size_t)item]; @@ -1768,6 +1897,7 @@ void wxListMainWindow::OnRenameAccept() void wxListMainWindow::OnMouse( wxMouseEvent &event ) { + event.SetEventObject( GetParent() ); if (GetParent()->GetEventHandler()->ProcessEvent( event)) return; if (!m_current) return; @@ -1798,8 +1928,8 @@ void wxListMainWindow::OnMouse( wxMouseEvent &event ) if (m_dragCount != 3) return; - int command = wxEVT_COMMAND_LIST_BEGIN_DRAG; - if (event.RightIsDown()) command = wxEVT_COMMAND_LIST_BEGIN_RDRAG; + int command = event.RightIsDown() ? wxEVT_COMMAND_LIST_BEGIN_RDRAG + : wxEVT_COMMAND_LIST_BEGIN_DRAG; wxListEvent le( command, GetParent()->GetId() ); le.SetEventObject( GetParent() ); @@ -1852,7 +1982,8 @@ void wxListMainWindow::OnMouse( wxMouseEvent &event ) if (event.RightDown()) { - SendNotify( line, wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK ); + SendNotify( line, wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, + event.GetPosition() ); return; } @@ -1887,7 +2018,7 @@ void wxListMainWindow::OnMouse( wxMouseEvent &event ) else if (event.ShiftDown()) { size_t j; - + m_current = line; int numOfCurrent = -1; @@ -1962,8 +2093,8 @@ void wxListMainWindow::MoveToFocus() if (m_mode & wxLC_REPORT) { - if (item_y-5 < view_y ) - Scroll( -1, (item_y-5)/m_yScroll ); + if (item_y < view_y ) + Scroll( -1, (item_y)/m_yScroll ); if (item_y+item_h+5 > view_y+client_h) Scroll( -1, (item_y+item_h-client_h+15)/m_yScroll ); } @@ -2095,7 +2226,7 @@ void wxListMainWindow::OnChar( wxKeyEvent &event ) if (index != wxNOT_FOUND) { index -= steps; - if (index < 0) index = 0; + if (index < 0) index = 0; OnArrowChar( &m_lines[index], event.ShiftDown() ); } break; @@ -2116,7 +2247,7 @@ void wxListMainWindow::OnChar( wxKeyEvent &event ) if (index != wxNOT_FOUND) { index += steps; - if ((size_t)index >= m_lines.GetCount()) + if ((size_t)index >= m_lines.GetCount()) index = m_lines.GetCount()-1; OnArrowChar( &m_lines[index], event.ShiftDown() ); } @@ -2144,7 +2275,7 @@ void wxListMainWindow::OnChar( wxKeyEvent &event ) if (index != wxNOT_FOUND) { index += m_visibleLines; - if ((size_t)index >= m_lines.GetCount()) + if ((size_t)index >= m_lines.GetCount()) index = m_lines.GetCount()-1; OnArrowChar( &m_lines[index], event.ShiftDown() ); } @@ -2381,7 +2512,7 @@ void wxListMainWindow::SetColumnWidth( int col, int width ) wxClientDC dc(this); dc.SetFont( GetFont() ); int max = 10; - + for (size_t i = 0; i < m_lines.GetCount(); i++) { wxListLineData *line = &m_lines[i]; @@ -2499,6 +2630,7 @@ void wxListMainWindow::SetItemState( long item, long state, long stateMask ) UnfocusLine( m_current ); m_current = line; FocusLine( m_current ); + if ((m_mode & wxLC_SINGLE_SEL) && oldCurrent) oldCurrent->Hilight( FALSE ); RefreshLine( m_current ); if (oldCurrent) RefreshLine( oldCurrent ); } @@ -2547,7 +2679,7 @@ int wxListMainWindow::GetItemState( long item, long stateMask ) if (item >= 0 && (size_t)item < m_lines.GetCount()) { wxListLineData *line = &m_lines[(size_t)item]; - if (line->IsHilighted()) ret |= wxLIST_STATE_FOCUSED; + if (line->IsHilighted()) ret |= wxLIST_STATE_SELECTED; } } return ret; @@ -2579,6 +2711,7 @@ void wxListMainWindow::GetItemRect( long index, wxRect &rect ) if (index >= 0 && (size_t)index < m_lines.GetCount()) { m_lines[(size_t)index].GetRect( rect ); + this->CalcScrolledPosition(rect.x,rect.y,&rect.x,&rect.y); } else { @@ -2591,18 +2724,9 @@ void wxListMainWindow::GetItemRect( long index, wxRect &rect ) bool wxListMainWindow::GetItemPosition(long item, wxPoint& pos) { - if (item >= 0 && (size_t)item < m_lines.GetCount()) - { - wxRect rect; - m_lines[(size_t)item].GetRect( rect ); - pos.x = rect.x; - pos.y = rect.y; - } - else - { - pos.x = 0; - pos.y = 0; - } + wxRect rect; + this->GetItemRect(item,rect); + pos.x=rect.x; pos.y=rect.y; return TRUE; } @@ -2674,6 +2798,9 @@ void wxListMainWindow::CalculatePositions() if (m_mode & wxLC_REPORT) { + // scroll one line per step + m_yScroll = lineSpacing; + int x = 4; int y = 1; int entireHeight = m_lines.GetCount() * lineSpacing + 2; @@ -2681,7 +2808,7 @@ void wxListMainWindow::CalculatePositions() #if wxUSE_GENERIC_LIST_EXTENSIONS int x_scroll_pos = GetScrollPos( wxHORIZONTAL ); #else - SetScrollbars( m_xScroll, m_yScroll, 0, (entireHeight+15) / m_yScroll, 0, scroll_pos, TRUE ); + SetScrollbars( m_xScroll, m_yScroll, 0, entireHeight/m_yScroll +1, 0, scroll_pos, TRUE ); #endif GetClientSize( &clientWidth, &clientHeight ); @@ -2703,9 +2830,9 @@ void wxListMainWindow::CalculatePositions() #endif y += lineSpacing; // one pixel blank line between items } - m_visibleLines = clientHeight / lineSpacing; + m_visibleLines = clientHeight / lineSpacing; #if wxUSE_GENERIC_LIST_EXTENSIONS - SetScrollbars( m_xScroll, m_yScroll, entireWidth / m_xScroll , (entireHeight+15) / m_yScroll, x_scroll_pos , scroll_pos, TRUE ); + SetScrollbars( m_xScroll, m_yScroll, entireWidth/m_xScroll +1, entireHeight/m_yScroll +1, x_scroll_pos , scroll_pos, TRUE ); #endif } else @@ -2879,7 +3006,7 @@ long wxListMainWindow::FindItem(long start, const wxString& str, bool WXUNUSED(p long pos = start; wxString tmp = str; if (pos < 0) pos = 0; - for (size_t i = pos; i < m_lines.GetCount(); i++) + for (size_t i = (size_t)pos; i < m_lines.GetCount(); i++) { wxListLineData *line = &m_lines[i]; wxString s = ""; @@ -2894,7 +3021,7 @@ long wxListMainWindow::FindItem(long start, long data) { long pos = start; if (pos < 0) pos = 0; - for (size_t i = pos; i < m_lines.GetCount(); i++) + for (size_t i = (size_t)pos; i < m_lines.GetCount(); i++) { wxListLineData *line = &m_lines[i]; wxListItem item; @@ -2914,7 +3041,7 @@ long wxListMainWindow::HitTest( int x, int y, int &flags ) { wxListLineData *line = &m_lines[i]; long ret = line->IsHit( x, y ); - if (ret & flags) + if (ret) // & flags) // No: flags is output-only so may be garbage at this point { flags = (int)ret; return count; @@ -2953,6 +3080,7 @@ void wxListMainWindow::InsertItem( wxListItem &item ) else { m_lines.Add( line ); + item.m_itemId = m_lines.GetCount()-1; } } @@ -3001,7 +3129,8 @@ void wxListMainWindow::SortItems( wxListCtrlCompare fn, long data ) void wxListMainWindow::OnScroll(wxScrollWinEvent& event) { - wxScrolledWindow::OnScroll( event ) ; + wxScrolledWindow::OnScroll( event ) ; + #if wxUSE_GENERIC_LIST_EXTENSIONS if (event.GetOrientation() == wxHORIZONTAL && ( m_mode & wxLC_REPORT )) @@ -3125,12 +3254,16 @@ wxListCtrl::wxListCtrl() m_imageListNormal = (wxImageList *) NULL; m_imageListSmall = (wxImageList *) NULL; m_imageListState = (wxImageList *) NULL; + m_ownsImageListNormal = m_ownsImageListSmall = m_ownsImageListState = FALSE; m_mainWin = (wxListMainWindow*) NULL; m_headerWin = (wxListHeaderWindow*) NULL; } wxListCtrl::~wxListCtrl() { + if (m_ownsImageListNormal) delete m_imageListNormal; + if (m_ownsImageListSmall) delete m_imageListSmall; + if (m_ownsImageListState) delete m_imageListState; } bool wxListCtrl::Create(wxWindow *parent, @@ -3144,6 +3277,7 @@ bool wxListCtrl::Create(wxWindow *parent, m_imageListNormal = (wxImageList *) NULL; m_imageListSmall = (wxImageList *) NULL; m_imageListState = (wxImageList *) NULL; + m_ownsImageListNormal = m_ownsImageListSmall = m_ownsImageListState = FALSE; m_mainWin = (wxListMainWindow*) NULL; m_headerWin = (wxListHeaderWindow*) NULL; @@ -3441,9 +3575,39 @@ wxImageList *wxListCtrl::GetImageList(int which) const void wxListCtrl::SetImageList( wxImageList *imageList, int which ) { + if ( which == wxIMAGE_LIST_NORMAL ) + { + if (m_ownsImageListNormal) delete m_imageListNormal; + m_imageListNormal = imageList; + m_ownsImageListNormal = FALSE; + } + else if ( which == wxIMAGE_LIST_SMALL ) + { + if (m_ownsImageListSmall) delete m_imageListSmall; + m_imageListSmall = imageList; + m_ownsImageListSmall = FALSE; + } + else if ( which == wxIMAGE_LIST_STATE ) + { + if (m_ownsImageListState) delete m_imageListState; + m_imageListState = imageList; + m_ownsImageListState = FALSE; + } + m_mainWin->SetImageList( imageList, which ); } +void wxListCtrl::AssignImageList(wxImageList *imageList, int which) +{ + SetImageList(imageList, which); + if ( which == wxIMAGE_LIST_NORMAL ) + m_ownsImageListNormal = TRUE; + else if ( which == wxIMAGE_LIST_SMALL ) + m_ownsImageListSmall = TRUE; + else if ( which == wxIMAGE_LIST_STATE ) + m_ownsImageListState = TRUE; +} + bool wxListCtrl::Arrange( int WXUNUSED(flag) ) { return 0;