X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/b31989e20882186006e2b2c4b8062ba8394b539d..39bc7d8020c1925e6bcb2dc51f126c4bad1341b7:/src/generic/listctrl.cpp diff --git a/src/generic/listctrl.cpp b/src/generic/listctrl.cpp index 6cfc4bec2c..85505af13f 100644 --- a/src/generic/listctrl.cpp +++ b/src/generic/listctrl.cpp @@ -47,8 +47,26 @@ #include "wx/textctrl.h" #endif -#include "wx/imaglist.h" -#include "wx/listctrl.h" +// under Win32 we always use the native version and also may use the generic +// one, however some things should be done only if we use only the generic +// version +#if defined(__WIN32__) && !defined(__WXUNIVERSAL__) + #define HAVE_NATIVE_LISTCTRL +#endif + +// if we have the native control, wx/listctrl.h declares it and not this one +#ifdef HAVE_NATIVE_LISTCTRL + #include "wx/generic/listctrl.h" +#else // !HAVE_NATIVE_LISTCTRL + #include "wx/listctrl.h" + + // if we have a native version, its implementation file does all this + IMPLEMENT_DYNAMIC_CLASS(wxListItem, wxObject) + IMPLEMENT_DYNAMIC_CLASS(wxListView, wxListCtrl) + IMPLEMENT_DYNAMIC_CLASS(wxListEvent, wxNotifyEvent) + + IMPLEMENT_DYNAMIC_CLASS(wxListCtrl, wxGenericListCtrl) +#endif // HAVE_NATIVE_LISTCTRL/!HAVE_NATIVE_LISTCTRL #if defined(__WXGTK__) #include @@ -144,7 +162,7 @@ public: void SetItemCount(size_t count) { m_count = count; } // special case of SetItemCount(0) - void Clear() { m_itemsSel.Clear(); m_count = 0; } + void Clear() { m_itemsSel.Clear(); m_count = 0; m_defaultState = FALSE; } // must be called when a new item is inserted/added void OnItemAdd(size_t item) { wxFAIL_MSG( _T("TODO") ); } @@ -413,6 +431,10 @@ private: const wxListItemAttr *attr, bool highlight); + // draw the text on the DC with the correct justification; also add an + // ellipsis if the text is too large to fit in the current width + void DrawTextFormatted(wxDC *dc, const wxString &text, int col, int x, int y, int width); + // these are only used by GetImage/SetImage above, we don't support images // with subitems at the public API level yet void SetImage( int index, int image ); @@ -454,7 +476,7 @@ public: const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, long style = 0, - const wxString &name = "wxlistctrlcolumntitles" ); + const wxString &name = wxT("wxlistctrlcolumntitles") ); virtual ~wxListHeaderWindow(); @@ -646,7 +668,7 @@ public: void GetImageSize( int index, int &width, int &height ) const; int GetTextLength( const wxString &s ) const; - void SetImageList( wxGenericImageList *imageList, int which ); + void SetImageList( wxImageListType *imageList, int which ); void SetItemSpacing( int spacing, bool isSmall = FALSE ); int GetItemSpacing( bool isSmall = FALSE ); @@ -775,8 +797,8 @@ public: wxColour *m_highlightColour; int m_xScroll, m_yScroll; - wxGenericImageList *m_small_image_list; - wxGenericImageList *m_normal_image_list; + wxImageListType *m_small_image_list; + wxImageListType *m_normal_image_list; int m_small_spacing; int m_normal_spacing; bool m_hasFocus; @@ -871,6 +893,8 @@ private: DECLARE_DYNAMIC_CLASS(wxListMainWindow) DECLARE_EVENT_TABLE() + + friend class wxGenericListCtrl; }; // ============================================================================ @@ -1728,15 +1752,69 @@ void wxListLineData::DrawInReportMode( wxDC *dc, width -= ix; } - wxDCClipper clipper(*dc, xOld, y, width, rect.height); + wxDCClipper clipper(*dc, xOld, y, width - 8, rect.height); if ( item->HasText() ) { - dc->DrawText( item->GetText(), xOld, y ); + DrawTextFormatted(dc, item->GetText(), col, xOld, y, width - 8); } } } +void wxListLineData::DrawTextFormatted(wxDC *dc, + const wxString &text, + int col, + int x, + int y, + int width) +{ + wxString drawntext, ellipsis; + wxCoord w, h, base_w; + wxListItem item; + + // determine if the string can fit inside the current width + dc->GetTextExtent(text, &w, &h); + + // if it can, draw it + if (w <= width) + { + m_owner->GetColumn(col, item); + if (item.m_format == wxLIST_FORMAT_LEFT) + dc->DrawText(text, x, y); + else if (item.m_format == wxLIST_FORMAT_RIGHT) + dc->DrawText(text, x + width - w, y); + else if (item.m_format == wxLIST_FORMAT_CENTER) + dc->DrawText(text, x + ((width - w) / 2), y); + } + else // otherwise, truncate and add an ellipsis if possible + { + // determine the base width + ellipsis = wxString(wxT("...")); + dc->GetTextExtent(ellipsis, &base_w, &h); + + // continue until we have enough space or only one character left + drawntext = text.Left(text.Length() - 1); + while (drawntext.Length() > 1) + { + dc->GetTextExtent(drawntext, &w, &h); + if (w + base_w <= width) + break; + drawntext = drawntext.Left(drawntext.Length() - 1); + } + + // if still not enough space, remove ellipsis characters + while (ellipsis.Length() > 0 && w + base_w > width) + { + ellipsis = ellipsis.Left(ellipsis.Length() - 1); + dc->GetTextExtent(ellipsis, &base_w, &h); + } + + // now draw the text + dc->DrawText(drawntext, x, y); + dc->DrawText(ellipsis, x + w, y); + } +} + bool wxListLineData::Highlight( bool on ) { wxCHECK_MSG( !m_owner->IsVirtual(), FALSE, _T("unexpected call to Highlight") ); @@ -1803,6 +1881,11 @@ wxListHeaderWindow::~wxListHeaderWindow() delete m_resizeCursor; } +#ifdef __WXUNIVERSAL__ +#include "wx/univ/renderer.h" +#include "wx/univ/theme.h" +#endif + void wxListHeaderWindow::DoDrawRect( wxDC *dc, int x, int y, int w, int h ) { #if defined(__WXGTK__) && !defined(__WXUNIVERSAL__) @@ -1816,7 +1899,11 @@ void wxListHeaderWindow::DoDrawRect( wxDC *dc, int x, int y, int w, int h ) (GdkRectangle*) NULL, m_wxwindow, (char *)"button", // const_cast x-1, y-1, w+2, h+2); -#elif defined( __WXMAC__ ) +#elif defined(__WXUNIVERSAL__) + wxTheme *theme = wxTheme::Get(); + wxRenderer *renderer = theme->GetRenderer(); + renderer->DrawBorder( *dc, wxBORDER_RAISED, wxRect(x,y,w,h), 0 ); +#elif defined(__WXMAC__) const int m_corner = 1; dc->SetBrush( *wxTRANSPARENT_BRUSH ); @@ -1922,7 +2009,7 @@ void wxListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) int image = item.m_image; if ( image != -1 ) { - wxGenericImageList *imageList = m_owner->m_small_image_list; + wxImageListType *imageList = m_owner->m_small_image_list; if ( imageList ) { int ix, iy; @@ -2280,8 +2367,8 @@ void wxListMainWindow::Init() m_headerWidth = m_lineHeight = 0; - m_small_image_list = (wxGenericImageList *) NULL; - m_normal_image_list = (wxGenericImageList *) NULL; + m_small_image_list = (wxImageListType *) NULL; + m_normal_image_list = (wxImageListType *) NULL; m_small_spacing = 30; m_normal_spacing = 40; @@ -2664,22 +2751,24 @@ void wxListMainWindow::RefreshAfter( size_t lineFrom ) { if ( HasFlag(wxLC_REPORT) ) { - size_t visibleFrom; - GetVisibleLinesRange(&visibleFrom, NULL); + size_t visibleFrom, visibleTo; + GetVisibleLinesRange(&visibleFrom, &visibleTo); if ( lineFrom < visibleFrom ) lineFrom = visibleFrom; + else if ( lineFrom > visibleTo ) + return; wxRect rect; rect.x = 0; rect.y = GetLineY(lineFrom); + CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y ); wxSize size = GetClientSize(); rect.width = size.x; // refresh till the bottom of the window rect.height = size.y - rect.y; - CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y ); RefreshRect( rect ); } else // !report @@ -2806,7 +2895,8 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) wxPen pen(GetRuleColour(), 1, wxSOLID); wxSize clientSize = GetClientSize(); - for ( size_t i = visibleFrom; i <= visibleTo; i++ ) + // Don't draw the first one + for ( size_t i = visibleFrom+1; i <= visibleTo; i++ ) { dc.SetPen(pen); dc.SetBrush( *wxTRANSPARENT_BRUSH ); @@ -2815,12 +2905,12 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) } // Draw last horizontal rule - if ( visibleTo > visibleFrom ) + if ( visibleTo == GetItemCount() - 1 ) { dc.SetPen(pen); dc.SetBrush( *wxTRANSPARENT_BRUSH ); - dc.DrawLine(0 - dev_x, m_lineTo*lineHeight, - clientSize.x - dev_x , m_lineTo*lineHeight ); + dc.DrawLine(0 - dev_x, (m_lineTo+1)*lineHeight, + clientSize.x - dev_x , (m_lineTo+1)*lineHeight ); } } @@ -2832,8 +2922,8 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) int col = 0; wxRect firstItemRect; wxRect lastItemRect; - GetItemRect(0, firstItemRect); - GetItemRect(GetItemCount() - 1, lastItemRect); + GetItemRect(visibleFrom, firstItemRect); + GetItemRect(visibleTo, lastItemRect); int x = firstItemRect.GetX(); dc.SetPen(pen); dc.SetBrush(* wxTRANSPARENT_BRUSH); @@ -2841,8 +2931,8 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) { int colWidth = GetColumnWidth(col); x += colWidth; - dc.DrawLine(x - dev_x, firstItemRect.GetY() - 1 - dev_y, - x - dev_x, lastItemRect.GetBottom() + 1 - dev_y); + dc.DrawLine(x - dev_x - 2, firstItemRect.GetY() - 1 - dev_y, + x - dev_x - 2, lastItemRect.GetBottom() + 1 - dev_y); } } } @@ -3067,15 +3157,7 @@ void wxListMainWindow::OnMouse( wxMouseEvent &event ) m_renameTimer->Stop(); m_lastOnSame = FALSE; -#ifdef __WXGTK__ - // FIXME: wxGTK generates bad sequence of events prior to doubleclick - // ("down, up, down, double, up" while other ports - // do "down, up, double, up"). We have to have this hack - // in place till somebody fixes wxGTK... - if ( current == m_lineBeforeLastClicked ) -#else if ( current == m_lineLastClicked ) -#endif { SendNotify( current, wxEVT_COMMAND_LIST_ITEM_ACTIVATED ); @@ -3529,7 +3611,7 @@ int wxListMainWindow::GetTextLength( const wxString &s ) const return lw + AUTOSIZE_COL_MARGIN; } -void wxListMainWindow::SetImageList( wxGenericImageList *imageList, int which ) +void wxListMainWindow::SetImageList( wxImageListType *imageList, int which ) { m_dirty = TRUE; @@ -3724,16 +3806,10 @@ void wxListMainWindow::SetItem( wxListItem &item ) line->SetItem( item.m_col, item ); } - if ( InReportView() ) - { - // just refresh the line to show the new value of the text/image - RefreshLine((size_t)id); - } - else // !report - { - // refresh everything (resulting in horrible flicker - FIXME!) - m_dirty = TRUE; - } + // update the item on screen + wxRect rectItem; + GetItemRect(id, rectItem); + RefreshRect(rectItem); } void wxListMainWindow::SetItemState( long litem, long state, long stateMask ) @@ -4348,7 +4424,10 @@ void wxListMainWindow::InsertItem( wxListItem &item ) int mode = 0; if ( HasFlag(wxLC_REPORT) ) + { mode = wxLC_REPORT; + ResetVisibleLinesRange(); + } else if ( HasFlag(wxLC_LIST) ) mode = wxLC_LIST; else if ( HasFlag(wxLC_ICON) ) @@ -4496,45 +4575,22 @@ void wxListMainWindow::GetVisibleLinesRange(size_t *from, size_t *to) *to = m_lineTo; } -// ------------------------------------------------------------------------------------- -// wxListItem -// ------------------------------------------------------------------------------------- - -#if !defined(__WIN32__) -IMPLEMENT_DYNAMIC_CLASS(wxListItem, wxObject) -#endif - // ------------------------------------------------------------------------------------- // wxGenericListCtrl // ------------------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS(wxGenericListCtrl, wxControl) -#if !defined(__WIN32__) -IMPLEMENT_DYNAMIC_CLASS(wxListView, wxGenericListCtrl) - -IMPLEMENT_DYNAMIC_CLASS(wxListEvent, wxNotifyEvent) -#endif - BEGIN_EVENT_TABLE(wxGenericListCtrl,wxControl) EVT_SIZE(wxGenericListCtrl::OnSize) EVT_IDLE(wxGenericListCtrl::OnIdle) END_EVENT_TABLE() -#if !defined(__WXMSW__) || defined(__WIN16__) || defined(__WXUNIVERSAL__) -/* - * wxListCtrl has to be a real class or we have problems with - * the run-time information. - */ - -IMPLEMENT_DYNAMIC_CLASS(wxListCtrl, wxGenericListCtrl) -#endif - wxGenericListCtrl::wxGenericListCtrl() { - m_imageListNormal = (wxGenericImageList *) NULL; - m_imageListSmall = (wxGenericImageList *) NULL; - m_imageListState = (wxGenericImageList *) NULL; + m_imageListNormal = (wxImageListType *) NULL; + m_imageListSmall = (wxImageListType *) NULL; + m_imageListState = (wxImageListType *) NULL; m_ownsImageListNormal = m_ownsImageListSmall = @@ -4575,7 +4631,7 @@ bool wxGenericListCtrl::Create(wxWindow *parent, { m_imageListNormal = m_imageListSmall = - m_imageListState = (wxGenericImageList *) NULL; + m_imageListState = (wxImageListType *) NULL; m_ownsImageListNormal = m_ownsImageListSmall = m_ownsImageListState = FALSE; @@ -4871,7 +4927,9 @@ void wxGenericListCtrl::SetTextColour(const wxColour& col) long wxGenericListCtrl::GetTopItem() const { - return 0; + size_t top; + m_mainWin->GetVisibleLinesRange(&top, NULL); + return (long)top; } long wxGenericListCtrl::GetNextItem( long item, int geom, int state ) const @@ -4879,7 +4937,7 @@ long wxGenericListCtrl::GetNextItem( long item, int geom, int state ) const return m_mainWin->GetNextItem( item, geom, state ); } -wxGenericImageList *wxGenericListCtrl::GetImageList(int which) const +wxImageListType *wxGenericListCtrl::GetImageList(int which) const { if (which == wxIMAGE_LIST_NORMAL) { @@ -4893,10 +4951,10 @@ wxGenericImageList *wxGenericListCtrl::GetImageList(int which) const { return m_imageListState; } - return (wxGenericImageList *) NULL; + return (wxImageListType *) NULL; } -void wxGenericListCtrl::SetImageList( wxGenericImageList *imageList, int which ) +void wxGenericListCtrl::SetImageList( wxImageListType *imageList, int which ) { if ( which == wxIMAGE_LIST_NORMAL ) { @@ -4920,7 +4978,7 @@ void wxGenericListCtrl::SetImageList( wxGenericImageList *imageList, int which ) m_mainWin->SetImageList( imageList, which ); } -void wxGenericListCtrl::AssignImageList(wxGenericImageList *imageList, int which) +void wxGenericListCtrl::AssignImageList(wxImageListType *imageList, int which) { SetImageList(imageList, which); if ( which == wxIMAGE_LIST_NORMAL )