+void wxListLineData::DrawInReportMode( wxDC *dc,
+ const wxRect& rect,
+ const wxRect& rectHL,
+ bool highlighted )
+{
+ // TODO: later we should support setting different attributes for
+ // different columns - to do it, just add "col" argument to
+ // GetAttr() and move these lines into the loop below
+ wxListItemAttr *attr = GetAttr();
+ if ( SetAttributes(dc, attr, highlighted) )
+ {
+ dc->DrawRectangle( rectHL );
+ }
+
+ wxCoord x = rect.x + HEADER_OFFSET_X,
+ y = rect.y + (LINE_SPACING + EXTRA_HEIGHT) / 2;
+
+ size_t col = 0;
+ for ( wxListItemDataList::compatibility_iterator node = m_items.GetFirst();
+ node;
+ node = node->GetNext(), col++ )
+ {
+ wxListItemData *item = node->GetData();
+
+ int width = m_owner->GetColumnWidth(col);
+ int xOld = x;
+ x += width;
+
+ if ( item->HasImage() )
+ {
+ int ix, iy;
+ m_owner->DrawImage( item->GetImage(), dc, xOld, y );
+ m_owner->GetImageSize( item->GetImage(), ix, iy );
+
+ ix += IMAGE_MARGIN_IN_REPORT_MODE;
+
+ xOld += ix;
+ width -= ix;
+ }
+
+ wxDCClipper clipper(*dc, xOld, y, width - 8, rect.height);
+
+ if ( item->HasText() )
+ {
+ 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 (w <= width)
+ {
+ // it can, draw it using the items alignment
+ m_owner->GetColumn(col, item);
+ switch ( item.GetAlign() )
+ {
+ default:
+ wxFAIL_MSG( _T("unknown list item format") );
+ // fall through
+
+ case wxLIST_FORMAT_LEFT:
+ // nothing to do
+ break;
+
+ case wxLIST_FORMAT_RIGHT:
+ x += width - w;
+ break;
+
+ case wxLIST_FORMAT_CENTER:
+ x += (width - w) / 2;
+ break;
+ }
+
+ dc->DrawText(text, x, 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
+ wxCoord w_c, h_c;
+ size_t len = text.Length();
+ drawntext = text.Left(len);
+ while (len > 1)
+ {
+ dc->GetTextExtent(drawntext.Last(), &w_c, &h_c);
+ drawntext.RemoveLast();
+ len--;
+ w -= w_c;
+ if (w + base_w <= width)
+ break;
+ }
+
+ // 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( !IsVirtual(), false, _T("unexpected call to Highlight") );
+
+ if ( on == m_highlighted )
+ return false;
+
+ m_highlighted = on;
+
+ return true;
+}
+
+void wxListLineData::ReverseHighlight( void )
+{
+ Highlight(!IsHighlighted());
+}
+
+//-----------------------------------------------------------------------------
+// wxListHeaderWindow
+//-----------------------------------------------------------------------------
+
+IMPLEMENT_DYNAMIC_CLASS(wxListHeaderWindow,wxWindow)
+
+BEGIN_EVENT_TABLE(wxListHeaderWindow,wxWindow)
+ EVT_PAINT (wxListHeaderWindow::OnPaint)
+ EVT_MOUSE_EVENTS (wxListHeaderWindow::OnMouse)
+ EVT_SET_FOCUS (wxListHeaderWindow::OnSetFocus)
+END_EVENT_TABLE()
+
+void wxListHeaderWindow::Init()
+{
+ m_currentCursor = (wxCursor *) NULL;
+ m_isDragging = false;
+ m_dirty = false;
+}
+
+wxListHeaderWindow::wxListHeaderWindow()
+{
+ Init();
+
+ m_owner = (wxListMainWindow *) NULL;
+ m_resizeCursor = (wxCursor *) NULL;
+}
+
+wxListHeaderWindow::wxListHeaderWindow( wxWindow *win,
+ wxWindowID id,
+ wxListMainWindow *owner,
+ const wxPoint& pos,
+ const wxSize& size,
+ long style,
+ const wxString &name )
+ : wxWindow( win, id, pos, size, style, name )
+{
+ Init();
+
+ m_owner = owner;
+ m_resizeCursor = new wxCursor( wxCURSOR_SIZEWE );
+
+#if _USE_VISATTR
+ wxVisualAttributes attr = wxPanel::GetClassDefaultAttributes();
+ SetOwnForegroundColour( attr.colFg );
+ SetOwnBackgroundColour( attr.colBg );
+ if (!m_hasFont)
+ SetOwnFont( attr.font );
+#else
+ SetOwnForegroundColour( wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
+ SetOwnBackgroundColour( wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
+ if (!m_hasFont)
+ SetOwnFont( wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT ));
+#endif
+}
+
+wxListHeaderWindow::~wxListHeaderWindow()
+{
+ delete m_resizeCursor;
+}
+
+#ifdef __WXUNIVERSAL__
+#include "wx/univ/renderer.h"
+#include "wx/univ/theme.h"
+#endif
+
+// shift the DC origin to match the position of the main window horz
+// scrollbar: this allows us to always use logical coords
+void wxListHeaderWindow::AdjustDC(wxDC& dc)
+{
+ int xpix;
+ m_owner->GetScrollPixelsPerUnit( &xpix, NULL );
+
+ int x;
+ m_owner->GetViewStart( &x, NULL );
+
+ // account for the horz scrollbar offset
+ dc.SetDeviceOrigin( -x * xpix, 0 );
+}
+
+void wxListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
+{
+ wxPaintDC dc( this );
+
+ PrepareDC( dc );
+ AdjustDC( dc );
+
+ dc.BeginDrawing();
+
+ dc.SetFont( GetFont() );
+
+ // width and height of the entire header window
+ int w, h;
+ GetClientSize( &w, &h );
+ m_owner->CalcUnscrolledPosition(w, 0, &w, NULL);
+
+ dc.SetBackgroundMode(wxTRANSPARENT);
+
+ dc.SetTextForeground(GetForegroundColour());
+
+ int x = HEADER_OFFSET_X;
+
+ int numColumns = m_owner->GetColumnCount();
+ wxListItem item;
+ for ( int i = 0; i < numColumns && x < w; i++ )