+}
+
+void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
+{
+ // Note: a wxPaintDC must be constructed even if no drawing is
+ // done (a Windows requirement).
+ wxPaintDC dc( this );
+
+ if (m_dirty)
+ {
+ // postpone redrawing until the next OnIdle() call to minimize flicker
+ return;
+ }
+
+ PrepareDC( dc );
+
+ int dev_x, dev_y;
+ CalcScrolledPosition( 0, 0, &dev_x, &dev_y );
+
+ if ( GetItemCount() == 0 )
+ {
+ // empty control. nothing to draw
+ return;
+ }
+
+ dc.BeginDrawing();
+
+ dc.SetFont( GetFont() );
+
+ 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;
+ line->GetSize( dummy, lineSpacing );
+ lineSpacing += 1;
+
+ int y_s = m_yScroll*GetScrollPos( wxVERTICAL );
+
+ size_t i_to = y_s / lineSpacing + m_visibleLines+2;
+ if (i_to >= m_lines.GetCount())
+ i_to = m_lines.GetCount();
+
+ size_t i;
+ for (i = y_s / lineSpacing; i < i_to; i++)
+ {
+ m_lines[i].Draw( &dc );
+ // Draw horizontal rule if required
+ if (m_mode & 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)) && (m_mode & 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 ((m_mode & 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 // !report mode
+ {
+ size_t count = GetItemCount();
+ for (size_t i = 0; i < count; i++)
+ m_lines[i].Draw( &dc );
+ }
+
+ if (m_current)
+ m_current->DrawRubberBand( &dc, m_hasFocus );
+
+ dc.EndDrawing();
+}
+
+void wxListMainWindow::HilightAll( bool on )
+{
+ size_t count = GetItemCount();
+ for (size_t i = 0; i < count; i++)
+ {
+ wxListLineData *line = &m_lines[i];
+ if (line->IsHilighted() != on)
+ {
+ line->Hilight( on );
+ RefreshLine( line );
+ }
+ }
+}
+
+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 );
+}
+
+void wxListMainWindow::FocusLine( wxListLineData *WXUNUSED(line) )
+{
+// SendNotify( line, wxEVT_COMMAND_LIST_ITEM_FOCUSSED );
+}
+
+void wxListMainWindow::UnfocusLine( wxListLineData *WXUNUSED(line) )
+{
+// SendNotify( line, wxEVT_COMMAND_LIST_ITEM_UNFOCUSSED );
+}
+
+void wxListMainWindow::SelectLine( wxListLineData *line )
+{
+ SendNotify( line, wxEVT_COMMAND_LIST_ITEM_SELECTED );
+}
+
+void wxListMainWindow::DeselectLine( wxListLineData *line )
+{
+ SendNotify( line, wxEVT_COMMAND_LIST_ITEM_DESELECTED );
+}
+
+void wxListMainWindow::DeleteLine( wxListLineData *line )
+{
+ SendNotify( line, wxEVT_COMMAND_LIST_DELETE_ITEM );
+}
+
+/* *** */
+
+void wxListMainWindow::EditLabel( long item )
+{
+ wxCHECK_RET( (item >= 0) && (item < GetItemCount()),
+ wxT("wrong index in wxListCtrl::Edit()") );
+
+ m_currentEdit = (size_t)item;
+
+ wxListEvent le( wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT, GetParent()->GetId() );
+ le.SetEventObject( GetParent() );
+ le.m_itemIndex = item;
+ wxListLineData *data = GetLine(m_currentEdit);
+ wxCHECK_RET( data, _T("invalid index in EditLabel()") );
+ data->GetItem( 0, le.m_item );
+ GetParent()->GetEventHandler()->ProcessEvent( le );
+
+ if (!le.IsAllowed())
+ return;
+
+ // We have to call this here because the label in
+ // question might just have been added and no screen
+ // update taken place.
+ if (m_dirty) wxYield();
+
+ wxString s = data->GetText(0);
+ int x = 0;
+ int y = 0;
+ int w = 0;
+ int h = 0;
+ data->GetLabelExtent( x, y, w, h );
+
+ wxClientDC dc(this);
+ PrepareDC( dc );
+ x = dc.LogicalToDeviceX( x );
+ y = dc.LogicalToDeviceY( y );
+
+ wxListTextCtrl *text = new wxListTextCtrl(
+ this, -1, &m_renameAccept, &m_renameRes, this, s, wxPoint(x-4,y-4), wxSize(w+11,h+8) );
+ text->SetFocus();
+}
+
+void wxListMainWindow::OnRenameTimer()
+{
+ wxCHECK_RET( m_current, wxT("invalid m_current") );
+
+ Edit( m_lines.Index( *m_current ) );
+}
+
+void wxListMainWindow::OnRenameAccept()
+{
+ wxListEvent le( wxEVT_COMMAND_LIST_END_LABEL_EDIT, GetParent()->GetId() );
+ le.SetEventObject( GetParent() );
+ le.m_itemIndex = m_currentEdit;
+
+ wxListLineData *data = GetLine(m_currentEdit);
+ wxCHECK_RET( data, _T("invalid index in OnRenameAccept()") );
+
+ data->GetItem( 0, le.m_item );
+ le.m_item.m_text = m_renameRes;
+ GetParent()->GetEventHandler()->ProcessEvent( le );
+
+ if (!le.IsAllowed()) return;
+
+ wxListItem info;
+ info.m_mask = wxLIST_MASK_TEXT;
+ info.m_itemId = le.m_itemIndex;
+ info.m_text = m_renameRes;
+ info.SetTextColour(le.m_item.GetTextColour());
+ SetItem( info );
+}
+
+void wxListMainWindow::OnMouse( wxMouseEvent &event )
+{
+ event.SetEventObject( GetParent() );
+ if (GetParent()->GetEventHandler()->ProcessEvent( event)) return;
+
+ if (!m_current) return;
+ if (m_dirty) return;
+ if ( !(event.Dragging() || event.ButtonDown() || event.LeftUp() || event.ButtonDClick()) ) return;
+
+ int x = event.GetX();
+ int y = event.GetY();
+ CalcUnscrolledPosition( x, y, &x, &y );
+
+ /* Did we actually hit an item ? */
+ long hitResult = 0;
+ wxListLineData *line = (wxListLineData *) NULL;
+
+ size_t idx;
+ for (idx = 0; idx < m_lines.GetCount(); idx++)
+ {
+ line = &m_lines[idx];
+ hitResult = line->IsHit( x, y );
+ if (hitResult)
+ break;
+ line = (wxListLineData *) NULL;
+ }
+
+ if (event.Dragging())
+ {
+ if (m_dragCount == 0)
+ m_dragStart = wxPoint(x,y);
+
+ m_dragCount++;
+
+ if (m_dragCount != 3) return;
+
+ int command = event.RightIsDown() ? wxEVT_COMMAND_LIST_BEGIN_RDRAG
+ : wxEVT_COMMAND_LIST_BEGIN_DRAG;
+
+ wxListEvent le( command, GetParent()->GetId() );
+ le.SetEventObject( GetParent() );
+ le.m_pointDrag = m_dragStart;
+ GetParent()->GetEventHandler()->ProcessEvent( le );
+
+ return;
+ }
+ else
+ {
+ m_dragCount = 0;
+ }
+
+ if (!line) return;
+
+ bool forceClick = FALSE;
+ if (event.ButtonDClick())
+ {
+ m_renameTimer->Stop();
+ m_lastOnSame = FALSE;
+
+ if ( idx == m_lineBeforeLastClicked )
+ {
+ m_usedKeys = FALSE;
+
+ SendNotify( line, wxEVT_COMMAND_LIST_ITEM_ACTIVATED );
+
+ return;
+ }
+ else
+ {
+ // the first click was on another item, so don't interpret this as
+ // a double click, but as a simple click instead
+ forceClick = TRUE;
+ }
+ }
+
+ if (event.LeftUp() && m_lastOnSame)
+ {
+ m_usedKeys = FALSE;
+ if ((line == m_current) &&
+ (hitResult == wxLIST_HITTEST_ONITEMLABEL) &&
+ (m_mode & wxLC_EDIT_LABELS) )
+ {
+ m_renameTimer->Start( 100, TRUE );
+ }
+ m_lastOnSame = FALSE;
+ return;
+ }
+
+ if (event.RightDown())
+ {
+ SendNotify( line, wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK,
+ event.GetPosition() );
+ return;
+ }
+
+ if (event.MiddleDown())
+ {
+ SendNotify( line, wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK );
+ return;
+ }
+
+ if ( event.LeftDown() || forceClick )
+ {
+ m_lineBeforeLastClicked = m_lineLastClicked;
+ m_lineLastClicked = idx;
+
+ m_usedKeys = FALSE;
+ wxListLineData *oldCurrent = m_current;
+ if (m_mode & wxLC_SINGLE_SEL)
+ {
+ m_current = line;
+ HilightAll( FALSE );
+ m_current->ReverseHilight();
+ RefreshLine( m_current );
+ }
+ else
+ {
+ if (event.ControlDown())
+ {
+ m_current = line;
+ m_current->ReverseHilight();
+ RefreshLine( m_current );
+ }
+ else if (event.ShiftDown())
+ {
+ size_t j;
+
+ m_current = line;
+
+ int numOfCurrent = -1;
+ for (j = 0; j < m_lines.GetCount(); j++)
+ {
+ wxListLineData *test_line = &m_lines[j];
+ numOfCurrent++;
+ if (test_line == oldCurrent) break;
+ }
+
+ int numOfLine = -1;
+
+ for (j = 0; j < m_lines.GetCount(); j++)
+ {
+ wxListLineData *test_line = &m_lines[j];
+ numOfLine++;
+ if (test_line == line) break;
+ }
+
+ if (numOfLine < numOfCurrent)
+ {
+ int i = numOfLine;
+ numOfLine = numOfCurrent;
+ numOfCurrent = i;
+ }
+
+ for (int i = 0; i <= numOfLine-numOfCurrent; i++)
+ {
+ wxListLineData *test_line= &m_lines[numOfCurrent + i];
+ test_line->Hilight(TRUE);
+ RefreshLine( test_line );
+ }
+ }
+ else
+ {
+ m_current = line;
+ HilightAll( FALSE );
+ m_current->ReverseHilight();
+ RefreshLine( m_current );
+ }
+ }
+ if (m_current != oldCurrent)
+ {
+ RefreshLine( oldCurrent );
+ UnfocusLine( oldCurrent );
+ FocusLine( m_current );
+ }
+
+ // forceClick is only set if the previous click was on another item
+ m_lastOnSame = !forceClick && (m_current == oldCurrent);
+
+ return;
+ }
+}
+
+void wxListMainWindow::MoveToFocus()
+{
+ if (!m_current) return;
+
+ int item_x = 0;
+ int item_y = 0;
+ int item_w = 0;
+ int item_h = 0;
+ m_current->GetExtent( item_x, item_y, item_w, item_h );
+
+ int client_w = 0;
+ int client_h = 0;
+ GetClientSize( &client_w, &client_h );
+
+ int view_x = m_xScroll*GetScrollPos( wxHORIZONTAL );
+ int view_y = m_yScroll*GetScrollPos( wxVERTICAL );
+
+ if (m_mode & wxLC_REPORT)
+ {
+ 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 );
+ }
+ else
+ {
+ if (item_x-view_x < 5)
+ Scroll( (item_x-5)/m_xScroll, -1 );
+ if (item_x+item_w-5 > view_x+client_w)
+ Scroll( (item_x+item_w-client_w+15)/m_xScroll, -1 );
+ }
+}
+
+void wxListMainWindow::OnArrowChar( wxListLineData *newCurrent, bool shiftDown )
+{
+ if ((m_mode & wxLC_SINGLE_SEL) || (m_usedKeys == FALSE)) m_current->Hilight( FALSE );
+ wxListLineData *oldCurrent = m_current;
+ m_current = newCurrent;
+ if (shiftDown || (m_mode & wxLC_SINGLE_SEL)) m_current->Hilight( TRUE );
+ RefreshLine( m_current );
+ RefreshLine( oldCurrent );
+ FocusLine( m_current );
+ UnfocusLine( oldCurrent );
+ MoveToFocus();
+}
+
+void wxListMainWindow::OnKeyDown( wxKeyEvent &event )
+{
+ wxWindow *parent = GetParent();
+
+ /* we propagate the key event up */
+ wxKeyEvent ke( wxEVT_KEY_DOWN );
+ ke.m_shiftDown = event.m_shiftDown;
+ ke.m_controlDown = event.m_controlDown;
+ ke.m_altDown = event.m_altDown;
+ ke.m_metaDown = event.m_metaDown;
+ ke.m_keyCode = event.m_keyCode;
+ ke.m_x = event.m_x;
+ ke.m_y = event.m_y;
+ ke.SetEventObject( parent );
+ if (parent->GetEventHandler()->ProcessEvent( ke )) return;
+
+ event.Skip();
+}
+
+void wxListMainWindow::OnChar( wxKeyEvent &event )
+{
+ wxWindow *parent = GetParent();
+
+ /* we send a list_key event up */
+ if ( m_current )
+ {
+ wxListEvent le( wxEVT_COMMAND_LIST_KEY_DOWN, GetParent()->GetId() );
+ le.m_itemIndex = GetIndexOfLine( m_current );
+ m_current->GetItem( 0, le.m_item );
+ le.m_code = (int)event.KeyCode();
+ le.SetEventObject( parent );
+ parent->GetEventHandler()->ProcessEvent( le );
+ }
+
+ /* we propagate the char event up */
+ wxKeyEvent ke( wxEVT_CHAR );
+ ke.m_shiftDown = event.m_shiftDown;
+ ke.m_controlDown = event.m_controlDown;
+ ke.m_altDown = event.m_altDown;
+ ke.m_metaDown = event.m_metaDown;
+ ke.m_keyCode = event.m_keyCode;
+ ke.m_x = event.m_x;
+ ke.m_y = event.m_y;
+ ke.SetEventObject( parent );
+ if (parent->GetEventHandler()->ProcessEvent( ke )) return;
+
+ if (event.KeyCode() == WXK_TAB)
+ {
+ wxNavigationKeyEvent nevent;
+ nevent.SetWindowChange( event.ControlDown() );
+ nevent.SetDirection( !event.ShiftDown() );
+ nevent.SetEventObject( GetParent()->GetParent() );
+ nevent.SetCurrentFocus( m_parent );
+ if (GetParent()->GetParent()->GetEventHandler()->ProcessEvent( nevent )) return;
+ }
+
+ /* no item -> nothing to do */
+ if (!m_current)
+ {
+ event.Skip();
+ return;
+ }
+
+ switch (event.KeyCode())
+ {
+ case WXK_UP:
+ {
+ int index = m_lines.Index(*m_current);
+ if (index != wxNOT_FOUND && index > 0)
+ OnArrowChar( &m_lines[index-1], event.ShiftDown() );
+ break;
+ }
+ case WXK_DOWN:
+ {
+ int index = m_lines.Index(*m_current);
+ if (index != wxNOT_FOUND && (size_t)index < m_lines.GetCount()-1)
+ OnArrowChar( &m_lines[index+1], event.ShiftDown() );
+ break;
+ }
+ case WXK_END:
+ {
+ if (!IsEmpty())
+ OnArrowChar( &m_lines.Last(), event.ShiftDown() );
+ break;
+ }
+ case WXK_HOME:
+ {
+ if (!IsEmpty())
+ OnArrowChar( &m_lines[0], event.ShiftDown() );
+ break;
+ }
+ case WXK_PRIOR:
+ {
+ int steps = 0;
+ int index = m_lines.Index(*m_current);
+ if (m_mode & wxLC_REPORT)
+ {
+ steps = m_visibleLines-1;
+ }
+ else
+ {
+ steps = index % m_visibleLines;
+ }
+ if (index != wxNOT_FOUND)
+ {
+ index -= steps;
+ if (index < 0) index = 0;
+ OnArrowChar( &m_lines[index], event.ShiftDown() );
+ }
+ break;
+ }
+ case WXK_NEXT:
+ {
+ int steps = 0;
+ int index = m_lines.Index(*m_current);
+ if (m_mode & wxLC_REPORT)
+ {
+ steps = m_visibleLines-1;
+ }
+ else
+ {
+ steps = m_visibleLines-(index % m_visibleLines)-1;
+ }
+
+ if (index != wxNOT_FOUND)
+ {
+ index += steps;
+ if ((size_t)index >= m_lines.GetCount())
+ index = m_lines.GetCount()-1;
+ OnArrowChar( &m_lines[index], event.ShiftDown() );
+ }
+ break;
+ }
+ case WXK_LEFT:
+ {
+ if (!(m_mode & wxLC_REPORT))
+ {
+ int index = m_lines.Index(*m_current);
+ if (index != wxNOT_FOUND)
+ {
+ index -= m_visibleLines;
+ if (index < 0) index = 0;
+ OnArrowChar( &m_lines[index], event.ShiftDown() );
+ }
+ }
+ break;
+ }
+ case WXK_RIGHT:
+ {
+ if (!(m_mode & wxLC_REPORT))
+ {
+ int index = m_lines.Index(*m_current);
+ if (index != wxNOT_FOUND)
+ {
+ index += m_visibleLines;
+ if ((size_t)index >= m_lines.GetCount())
+ index = m_lines.GetCount()-1;
+ OnArrowChar( &m_lines[index], event.ShiftDown() );
+ }
+ }
+ break;
+ }
+ case WXK_SPACE:
+ {
+ if (m_mode & wxLC_SINGLE_SEL)
+ {
+ wxListEvent le( wxEVT_COMMAND_LIST_ITEM_ACTIVATED, GetParent()->GetId() );
+ le.SetEventObject( GetParent() );
+ le.m_itemIndex = GetIndexOfLine( m_current );
+ m_current->GetItem( 0, le.m_item );
+ GetParent()->GetEventHandler()->ProcessEvent( le );
+ }
+ else
+ {
+ m_current->ReverseHilight();
+ RefreshLine( m_current );
+ }
+ break;
+ }
+ case WXK_INSERT:
+ {
+ if (!(m_mode & wxLC_SINGLE_SEL))
+ {
+ wxListLineData *oldCurrent = m_current;
+ m_current->ReverseHilight();
+ int index = m_lines.Index( *m_current ) + 1;
+ if ( (size_t)index < m_lines.GetCount() )
+ m_current = &m_lines[index];
+ RefreshLine( oldCurrent );
+ RefreshLine( m_current );
+ UnfocusLine( oldCurrent );
+ FocusLine( m_current );
+ MoveToFocus();
+ }
+ break;
+ }
+ case WXK_RETURN:
+ case WXK_EXECUTE:
+ {
+ wxListEvent le( wxEVT_COMMAND_LIST_ITEM_ACTIVATED, GetParent()->GetId() );
+ le.SetEventObject( GetParent() );
+ le.m_itemIndex = GetIndexOfLine( m_current );
+ m_current->GetItem( 0, le.m_item );
+ GetParent()->GetEventHandler()->ProcessEvent( le );
+ break;
+ }
+ default:
+ {
+ event.Skip();
+ return;
+ }
+ }
+ m_usedKeys = TRUE;
+}
+
+#ifdef __WXGTK__
+extern wxWindow *g_focusWindow;
+#endif
+
+void wxListMainWindow::OnSetFocus( wxFocusEvent &WXUNUSED(event) )
+{
+ m_hasFocus = TRUE;
+ RefreshLine( m_current );
+
+ if (!GetParent()) return;
+
+#ifdef __WXGTK__
+ g_focusWindow = GetParent();
+#endif
+
+ wxFocusEvent event( wxEVT_SET_FOCUS, GetParent()->GetId() );
+ event.SetEventObject( GetParent() );
+ GetParent()->GetEventHandler()->ProcessEvent( event );
+}
+
+void wxListMainWindow::OnKillFocus( wxFocusEvent &WXUNUSED(event) )
+{
+ m_hasFocus = FALSE;
+ RefreshLine( m_current );
+}
+
+void wxListMainWindow::OnSize( wxSizeEvent &WXUNUSED(event) )
+{
+/*
+ We don't even allow the wxScrolledWindow::AdjustScrollbars() call
+
+*/
+ m_dirty = TRUE;
+}
+
+void wxListMainWindow::DrawImage( int index, wxDC *dc, int x, int y )
+{
+ if ((m_mode & wxLC_ICON) && (m_normal_image_list))
+ {
+ m_normal_image_list->Draw( index, *dc, x, y, wxIMAGELIST_DRAW_TRANSPARENT );
+ return;
+ }
+ if ((m_mode & wxLC_SMALL_ICON) && (m_small_image_list))
+ {
+ m_small_image_list->Draw( index, *dc, x, y, wxIMAGELIST_DRAW_TRANSPARENT );
+ }
+ if ((m_mode & wxLC_LIST) && (m_small_image_list))
+ {
+ m_small_image_list->Draw( index, *dc, x, y, wxIMAGELIST_DRAW_TRANSPARENT );
+ }
+ if ((m_mode & wxLC_REPORT) && (m_small_image_list))
+ {
+ m_small_image_list->Draw( index, *dc, x, y, wxIMAGELIST_DRAW_TRANSPARENT );
+ return;
+ }
+}
+
+void wxListMainWindow::GetImageSize( int index, int &width, int &height )
+{
+ if ((m_mode & wxLC_ICON) && (m_normal_image_list))
+ {
+ m_normal_image_list->GetSize( index, width, height );
+ return;
+ }
+ if ((m_mode & wxLC_SMALL_ICON) && (m_small_image_list))
+ {
+ m_small_image_list->GetSize( index, width, height );
+ return;
+ }
+ if ((m_mode & wxLC_LIST) && (m_small_image_list))
+ {
+ m_small_image_list->GetSize( index, width, height );
+ return;
+ }
+ if ((m_mode & wxLC_REPORT) && (m_small_image_list))
+ {
+ m_small_image_list->GetSize( index, width, height );
+ return;
+ }
+ width = 0;
+ height = 0;
+}
+
+int wxListMainWindow::GetTextLength( wxString &s )
+{
+ wxClientDC dc( this );
+ wxCoord lw = 0;
+ wxCoord lh = 0;
+ dc.GetTextExtent( s, &lw, &lh );
+ return lw + 6;
+}
+
+int wxListMainWindow::GetIndexOfLine( const wxListLineData *line )
+{
+ return m_lines.Index(*line);
+}
+
+void wxListMainWindow::SetImageList( wxImageList *imageList, int which )
+{
+ m_dirty = TRUE;
+
+ // calc the spacing from the icon size
+ int width = 0,
+ height = 0;
+ if ((imageList) && (imageList->GetImageCount()) )
+ {
+ imageList->GetSize(0, width, height);
+ }
+
+ if (which == wxIMAGE_LIST_NORMAL)
+ {
+ m_normal_image_list = imageList;
+ m_normal_spacing = width + 8;
+ }
+
+ if (which == wxIMAGE_LIST_SMALL)
+ {
+ m_small_image_list = imageList;
+ m_small_spacing = width + 14;
+ }
+}
+
+void wxListMainWindow::SetItemSpacing( int spacing, bool isSmall )
+{
+ m_dirty = TRUE;
+ if (isSmall)
+ {
+ m_small_spacing = spacing;
+ }
+ else
+ {
+ m_normal_spacing = spacing;
+ }
+}
+
+int wxListMainWindow::GetItemSpacing( bool isSmall )
+{
+ return isSmall ? m_small_spacing : m_normal_spacing;
+}
+
+void wxListMainWindow::SetColumn( int col, wxListItem &item )
+{
+ m_dirty = TRUE;
+ wxListHeaderDataList::Node *node = m_columns.Item( col );
+ if (node)
+ {
+ if (item.m_width == wxLIST_AUTOSIZE_USEHEADER)
+ item.m_width = GetTextLength( item.m_text )+7;
+ wxListHeaderData *column = node->GetData();
+ column->SetItem( item );
+ }
+
+ wxListHeaderWindow *headerWin = ((wxListCtrl*) GetParent())->m_headerWin;
+ if ( headerWin )
+ headerWin->m_dirty = TRUE;
+}
+
+void wxListMainWindow::SetColumnWidth( int col, int width )
+{
+ wxCHECK_RET( m_mode & wxLC_REPORT,
+ _T("SetColumnWidth() can only be called in report mode.") );
+
+ m_dirty = TRUE;
+
+ if (width == wxLIST_AUTOSIZE_USEHEADER)
+ {
+ // TODO do use the header
+ width = 80;
+ }
+ else if (width == wxLIST_AUTOSIZE)
+ {
+ wxClientDC dc(this);
+ dc.SetFont( GetFont() );
+ int max = 10;
+
+ for (size_t i = 0; i < m_lines.GetCount(); i++)
+ {
+ wxListLineData *line = &m_lines[i];
+ wxListItemDataList::Node *n = line->m_items.Item( col );
+ if (n)
+ {
+ wxListItemData *item = n->GetData();
+ int current = 0, ix = 0, iy = 0;
+ wxCoord lx = 0, ly = 0;
+ if (item->HasImage())
+ {
+ GetImageSize( item->GetImage(), ix, iy );
+ current = ix + 5;
+ }
+ if (item->HasText())
+ {
+ wxString str = item->GetText();
+ dc.GetTextExtent( str, &lx, &ly );
+ current += lx;
+ }
+ if (current > max)
+ max = current;
+ }
+ }
+ width = max+10;
+ }
+
+ wxListHeaderDataList::Node *node = m_columns.Item( col );
+ if (node)
+ {
+ wxListHeaderData *column = node->GetData();
+ column->SetWidth( width );
+ }
+
+ size_t count = m_lines.GetCount();
+ for (size_t i = 0; i < count; i++)
+ {
+ wxListLineData *line = &m_lines[i];
+ wxListItemDataList::Node *n = line->m_items.Item( col );
+ if (n)
+ {
+ wxListItemData *item = n->GetData();
+ item->SetSize( width, -1 );
+ }
+ }
+
+ wxListHeaderWindow *headerWin = ((wxListCtrl*) GetParent())->m_headerWin;
+ if ( headerWin )
+ headerWin->m_dirty = TRUE;
+}
+
+void wxListMainWindow::GetColumn( int col, wxListItem &item )
+{
+ wxListHeaderDataList::Node *node = m_columns.Item( col );
+ if (node)
+ {
+ wxListHeaderData *column = node->GetData();
+ column->GetItem( item );
+ }
+ else
+ {
+ item.m_format = 0;
+ item.m_width = 0;
+ item.m_text = _T("");
+ item.m_image = 0;
+ item.m_data = 0;
+ }
+}
+
+int wxListMainWindow::GetColumnWidth( int col )
+{
+ wxListHeaderDataList::Node *node = m_columns.Item( col );
+ wxCHECK_MSG( node, 0, _T("invalid column index") );
+
+ wxListHeaderData *column = node->GetData();
+ return column->GetWidth();
+}
+
+int wxListMainWindow::GetColumnCount()
+{
+ return m_columns.GetCount();
+}
+
+int wxListMainWindow::GetCountPerPage()
+{
+ return m_visibleLines;
+}
+
+void wxListMainWindow::SetItem( wxListItem &item )
+{
+ m_dirty = TRUE;
+ if (item.m_itemId >= 0 && (size_t)item.m_itemId < m_lines.GetCount())
+ {
+ wxListLineData *line = &m_lines[(size_t)item.m_itemId];
+ if (m_mode & wxLC_REPORT) item.m_width = GetColumnWidth( item.m_col )-3;
+ line->SetItem( item.m_col, item );
+ }
+}
+
+void wxListMainWindow::SetItemState( long item, long state, long stateMask )
+{
+ wxCHECK_RET( item >= 0 && (size_t)item < m_lines.GetCount(),
+ _T("invalid list ctrl item index in SetItem") );
+
+ // m_dirty = TRUE; no recalcs needed
+
+ wxListLineData *oldCurrent = m_current;
+
+ if ( stateMask & wxLIST_STATE_FOCUSED )
+ {
+ wxListLineData *line = &m_lines[(size_t)item];
+ if ( state & wxLIST_STATE_FOCUSED )
+ {
+ // don't do anything if this item is already focused
+ if ( line != m_current )
+ {
+ 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 );
+ }
+ }
+ else // unfocus
+ {
+ // don't do anything if this item is not focused
+ if ( line == m_current )
+ {
+ UnfocusLine( m_current );
+ m_current = NULL;
+ }
+ }
+ }
+
+ if ( stateMask & wxLIST_STATE_SELECTED )
+ {
+ bool on = (state & wxLIST_STATE_SELECTED) != 0;
+ if (!on && (m_mode & wxLC_SINGLE_SEL))
+ return;
+
+ wxListLineData *line = &m_lines[(size_t)item];
+ if (m_mode & wxLC_SINGLE_SEL)
+ {
+ UnfocusLine( m_current );
+ m_current = line;
+ FocusLine( m_current );
+ if (oldCurrent)
+ oldCurrent->Hilight( FALSE );
+ RefreshLine( m_current );
+ if (oldCurrent)
+ RefreshLine( oldCurrent );
+ }
+
+ if (on != line->IsHilighted())
+ {
+ line->Hilight( on );
+ RefreshLine( line );
+ }
+ }
+}
+
+int wxListMainWindow::GetItemState( long item, long stateMask )
+{
+ int ret = wxLIST_STATE_DONTCARE;
+ if (stateMask & wxLIST_STATE_FOCUSED)
+ {
+ if (item >= 0 && (size_t)item < m_lines.GetCount())
+ {
+ wxListLineData *line = &m_lines[(size_t)item];
+ if (line == m_current) ret |= wxLIST_STATE_FOCUSED;
+ }
+ }
+ if (stateMask & wxLIST_STATE_SELECTED)
+ {
+ if (item >= 0 && (size_t)item < m_lines.GetCount())
+ {
+ wxListLineData *line = &m_lines[(size_t)item];
+ if (line->IsHilighted()) ret |= wxLIST_STATE_SELECTED;
+ }
+ }
+ return ret;
+}
+
+void wxListMainWindow::GetItem( wxListItem &item )
+{
+ if (item.m_itemId >= 0 && (size_t)item.m_itemId < m_lines.GetCount())
+ {
+ wxListLineData *line = &m_lines[(size_t)item.m_itemId];
+ line->GetItem( item.m_col, item );
+ }
+ else
+ {
+ item.m_mask = 0;
+ item.m_text = _T("");
+ item.m_image = 0;
+ item.m_data = 0;
+ }
+}
+
+int wxListMainWindow::GetItemCount() const
+{
+ return IsVirtual() ? m_countVirt : m_lines.GetCount();
+}
+
+void wxListMainWindow::SetItemCount(long count)
+{
+ m_countVirt = count;
+
+ Refresh();
+}
+
+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
+ {
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = 0;
+ rect.height = 0;
+ }
+}
+
+bool wxListMainWindow::GetItemPosition(long item, wxPoint& pos)
+{
+ wxRect rect;
+ this->GetItemRect(item,rect);
+ pos.x=rect.x; pos.y=rect.y;
+ return TRUE;
+}
+
+int wxListMainWindow::GetSelectedItemCount()
+{
+ int ret = 0;
+ for (size_t i = 0; i < m_lines.GetCount(); i++)
+ {
+ if (m_lines[i].IsHilighted()) ret++;
+ }
+ return ret;
+}
+
+void wxListMainWindow::SetMode( long mode )
+{
+ m_dirty = TRUE;
+ m_mode = mode;
+
+ DeleteEverything();
+
+ if (m_mode & wxLC_REPORT)
+ {
+#if wxUSE_GENERIC_LIST_EXTENSIONS
+ m_xScroll = 15;
+#else
+ m_xScroll = 0;
+#endif
+ m_yScroll = 15;
+ }
+ else
+ {
+ m_xScroll = 15;
+ m_yScroll = 0;
+ }
+}
+
+long wxListMainWindow::GetMode() const
+{
+ return m_mode;
+}
+
+void wxListMainWindow::CalculatePositions()
+{
+ if ( IsEmpty() )
+ return;
+
+ wxClientDC dc( this );
+ dc.SetFont( GetFont() );
+
+ int iconSpacing = 0;
+ if (m_mode & wxLC_ICON) iconSpacing = m_normal_spacing;
+ if (m_mode & wxLC_SMALL_ICON) iconSpacing = m_small_spacing;
+
+ // we take the first line (which also can be an icon or
+ // an a text item in wxLC_ICON and wxLC_LIST modes) to
+ // measure the size of the line
+
+ int lineWidth = 0;
+ int lineHeight = 0;
+ int lineSpacing = 0;
+
+ wxListLineData *line = &m_lines[0];
+ line->CalculateSize( &dc, iconSpacing );
+ int dummy = 0;
+ line->GetSize( dummy, lineSpacing );
+ lineSpacing += 1;
+
+ int clientWidth = 0;
+ int clientHeight = 0;
+
+ 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;
+ int scroll_pos = GetScrollPos( wxVERTICAL );
+#if wxUSE_GENERIC_LIST_EXTENSIONS
+ int x_scroll_pos = GetScrollPos( wxHORIZONTAL );
+#else
+ SetScrollbars( m_xScroll, m_yScroll, 0, entireHeight/m_yScroll +1, 0, scroll_pos, TRUE );
+#endif
+ GetClientSize( &clientWidth, &clientHeight );
+
+ int entireWidth = 0 ;
+ for (size_t j = 0; j < m_lines.GetCount(); j++)
+ {
+ wxListLineData *line = &m_lines[j];
+ line->CalculateSize( &dc, iconSpacing );
+ line->SetPosition( &dc, x, y, clientWidth );
+ int col_x = 2;
+ for (int i = 0; i < GetColumnCount(); i++)
+ {
+ line->SetColumnPosition( i, col_x );
+ col_x += GetColumnWidth( i );
+ }
+ entireWidth = wxMax( entireWidth , col_x ) ;
+#if wxUSE_GENERIC_LIST_EXTENSIONS
+ line->SetPosition( &dc, x, y, col_x );
+#endif
+ y += lineSpacing; // one pixel blank line between items
+ }
+ m_visibleLines = clientHeight / lineSpacing;
+#if wxUSE_GENERIC_LIST_EXTENSIONS
+ SetScrollbars( m_xScroll, m_yScroll, entireWidth/m_xScroll +1, entireHeight/m_yScroll +1, x_scroll_pos , scroll_pos, TRUE );
+#endif
+ }
+ else
+ {
+ // at first we try without any scrollbar. if the items don't
+ // fit into the window, we recalculate after subtracting an
+ // approximated 15 pt for the horizontal scrollbar
+
+ GetSize( &clientWidth, &clientHeight );
+ clientHeight -= 4; // sunken frame
+
+ int entireWidth = 0;
+
+ for (int tries = 0; tries < 2; tries++)
+ {
+ entireWidth = 0;
+ int x = 2;
+ int y = 2;
+ int maxWidth = 0;
+ m_visibleLines = 0;
+ int m_currentVisibleLines = 0;
+ for (size_t i = 0; i < m_lines.GetCount(); i++)
+ {
+ m_currentVisibleLines++;
+ wxListLineData *line = &m_lines[i];
+ line->CalculateSize( &dc, iconSpacing );
+ line->SetPosition( &dc, x, y, clientWidth );
+ line->GetSize( lineWidth, lineHeight );
+ if (lineWidth > maxWidth) maxWidth = lineWidth;
+ y += lineSpacing;
+ if (m_currentVisibleLines > m_visibleLines)
+ m_visibleLines = m_currentVisibleLines;
+ if (y+lineSpacing-6 >= clientHeight) // -6 for earlier "line breaking"
+ {
+ m_currentVisibleLines = 0;
+ y = 2;
+ x += maxWidth+6;
+ entireWidth += maxWidth+6;
+ maxWidth = 0;
+ }
+ if (i == m_lines.GetCount()-1) entireWidth += maxWidth;
+ if ((tries == 0) && (entireWidth > clientWidth))
+ {
+ clientHeight -= 15; // scrollbar height
+ m_visibleLines = 0;
+ m_currentVisibleLines = 0;
+ break;
+ }
+ if (i == m_lines.GetCount()-1) tries = 1; // everything fits, no second try required
+ }
+ }
+
+ int scroll_pos = GetScrollPos( wxHORIZONTAL );
+ SetScrollbars( m_xScroll, m_yScroll, (entireWidth+15) / m_xScroll, 0, scroll_pos, 0, TRUE );
+ }
+}
+
+void wxListMainWindow::RealizeChanges()
+{
+ if (!m_current)
+ {
+ if ( !IsEmpty() )
+ m_current = &m_lines[0];
+ }
+ if (m_current)
+ {
+ FocusLine( m_current );
+ // TODO: MSW doesn't automatically hilight the
+ // first item.
+ // if (m_mode & wxLC_SINGLE_SEL) m_current->Hilight( TRUE );
+ }
+}