X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/6fef2483d9dc1a7c006d2f5967791e0f4c0cf518..01a9232b5e06fc1e24cbd051661d37a46827379d:/src/generic/listctrl.cpp diff --git a/src/generic/listctrl.cpp b/src/generic/listctrl.cpp index 9646986295..5adf868e6b 100644 --- a/src/generic/listctrl.cpp +++ b/src/generic/listctrl.cpp @@ -83,8 +83,8 @@ static const int EXTRA_BORDER_X = 2; static const int EXTRA_BORDER_Y = 2; // offset for the header window -static const int HEADER_OFFSET_X = 1; -static const int HEADER_OFFSET_Y = 1; +static const int HEADER_OFFSET_X = 0; +static const int HEADER_OFFSET_Y = 0; // margin between rows of icons in [small] icon view static const int MARGIN_BETWEEN_ROWS = 6; @@ -98,6 +98,9 @@ static const int WIDTH_COL_DEFAULT = 80; // the space between the image and the text in the report mode static const int IMAGE_MARGIN_IN_REPORT_MODE = 5; +// the space between the image and the text in the report mode in header +static const int HEADER_IMAGE_MARGIN_IN_REPORT_MODE = 2; + // ============================================================================ // private classes // ============================================================================ @@ -1410,7 +1413,11 @@ bool wxListLineData::SetAttributes(wxDC *dc, if ( highlighted ) #ifdef __WXMAC__ { - if (m_owner->HasFocus()) + if (m_owner->HasFocus() +#ifdef __WXMAC__ + && IsControlActive( (ControlRef)m_owner->GetHandle() ) +#endif + ) colText = *wxWHITE; else colText = *wxBLACK; @@ -1470,7 +1477,11 @@ void wxListLineData::Draw( wxDC *dc ) if (highlighted) { int flags = wxCONTROL_SELECTED; - if (m_owner->HasFocus()) + if (m_owner->HasFocus() +#ifdef __WXMAC__ + && IsControlActive( (ControlRef)m_owner->GetHandle() ) +#endif + ) flags |= wxCONTROL_FOCUSED; wxRendererNative::Get().DrawItemSelectionRect( m_owner, *dc, m_gi->m_rectHighlight, flags ); @@ -1529,7 +1540,11 @@ void wxListLineData::DrawInReportMode( wxDC *dc, if (highlighted) { int flags = wxCONTROL_SELECTED; - if (m_owner->HasFocus()) + if (m_owner->HasFocus() +#ifdef __WXMAC__ + && IsControlActive( (ControlRef)m_owner->GetHandle() ) +#endif + ) flags |= wxCONTROL_FOCUSED; wxRendererNative::Get().DrawItemSelectionRect( m_owner, *dc, rectHL, flags ); } @@ -1578,12 +1593,17 @@ void wxListLineData::DrawInReportMode( wxDC *dc, } void wxListLineData::DrawTextFormatted(wxDC *dc, - const wxString &text, + const wxString& textOrig, int col, int x, int yMid, int width) { + // we don't support displaying multiple lines currently (and neither does + // wxMSW FWIW) so just merge all the lines + wxString text(textOrig); + text.Replace(_T("\n"), _T(" ")); + wxCoord w, h; dc->GetTextExtent(text, &w, &h); @@ -1788,15 +1808,8 @@ void wxListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) m_owner->GetColumn( i, item ); int wCol = item.m_width; - // the width of the rect to draw: make it smaller to fit entirely - // inside the column rect -#ifdef __WXMAC__ int cw = wCol; int ch = h; -#else - int cw = wCol - 2; - int ch = h - 2; -#endif int flags = 0; if (!m_parent->IsEnabled()) @@ -1829,7 +1842,6 @@ void wxListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) wLabel += 2 * EXTRA_WIDTH; // and the width of the icon, if any - static const int MARGIN_BETWEEN_TEXT_AND_ICON = 2; int ix = 0, iy = 0; // init them just to suppress the compiler warnings const int image = item.m_image; wxImageList *imageList; @@ -1839,7 +1851,7 @@ void wxListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) if ( imageList ) { imageList->GetSize(image, ix, iy); - wLabel += ix + MARGIN_BETWEEN_TEXT_AND_ICON; + wLabel += ix + HEADER_IMAGE_MARGIN_IN_REPORT_MODE; } } else @@ -1868,6 +1880,10 @@ void wxListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) break; } + // draw the text and image clipping them so that they + // don't overwrite the column boundary + wxDCClipper clipper(dc, x, HEADER_OFFSET_Y, cw, h - 4 ); + // if we have an image, draw it on the right of the label if ( imageList ) { @@ -1875,18 +1891,12 @@ void wxListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) ( image, dc, - xAligned + wLabel - ix - MARGIN_BETWEEN_TEXT_AND_ICON, + xAligned + wLabel - ix - HEADER_IMAGE_MARGIN_IN_REPORT_MODE, HEADER_OFFSET_Y + (h - 4 - iy)/2, wxIMAGELIST_DRAW_TRANSPARENT ); - - cw -= ix + MARGIN_BETWEEN_TEXT_AND_ICON; } - // draw the text clipping it so that it doesn't overwrite the column - // boundary - wxDCClipper clipper(dc, x, HEADER_OFFSET_Y, cw, h - 4 ); - dc.DrawText( item.GetText(), xAligned + EXTRA_WIDTH, h / 2 - hLabel / 2 ); //HEADER_OFFSET_Y + EXTRA_HEIGHT ); @@ -1896,6 +1906,9 @@ void wxListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) void wxListHeaderWindow::DrawCurrent() { +#if 1 + m_owner->SetColumnWidth( m_column, m_currentX - m_minX ); +#else int x1 = m_currentX; int y1 = 0; m_owner->ClientToScreen( &x1, &y1 ); @@ -1918,6 +1931,7 @@ void wxListHeaderWindow::DrawCurrent() dc.SetPen( wxNullPen ); dc.SetBrush( wxNullBrush ); +#endif } void wxListHeaderWindow::OnMouse( wxMouseEvent &event ) @@ -2143,16 +2157,17 @@ bool wxListTextCtrlWrapper::AcceptChanges() { const wxString value = m_text->GetValue(); - if ( value == m_startValue ) - // nothing changed, always accept - return true; - + // notice that we should always call OnRenameAccept() to generate the "end + // label editing" event, even if the user hasn't really changed anything if ( !m_owner->OnRenameAccept(m_itemEdited, value) ) + { // vetoed by the user return false; + } - // accepted, do rename the item - m_owner->SetItemText(m_itemEdited, value); + // accepted, do rename the item (unless nothing changed) + if ( value != m_startValue ) + m_owner->SetItemText(m_itemEdited, value); return true; } @@ -2432,6 +2447,20 @@ wxRect wxListMainWindow::GetLineLabelRect(size_t line) const if ( !InReportView() ) return GetLine(line)->m_gi->m_rectLabel; + int image_x = 0; + wxListLineData *data = GetLine(line); + wxListItemDataList::compatibility_iterator node = data->m_items.GetFirst(); + if (node) + { + wxListItemData *item = node->GetData(); + if ( item->HasImage() ) + { + int ix, iy; + GetImageSize( item->GetImage(), ix, iy ); + image_x = 3 + ix + IMAGE_MARGIN_IN_REPORT_MODE; + } + } + wxRect rect; rect.x = HEADER_OFFSET_X; rect.y = GetLineY(line); @@ -2754,8 +2783,9 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) wxPen pen(GetRuleColour(), 1, wxSOLID); wxSize clientSize = GetClientSize(); - // Don't draw the first one - for ( size_t i = visibleFrom + 1; i <= visibleTo; i++ ) + size_t i = visibleFrom; + if (i == 0) i = 1; // Don't draw the first one + for ( ; i <= visibleTo; i++ ) { dc.SetPen(pen); dc.SetBrush( *wxTRANSPARENT_BRUSH ); @@ -2789,8 +2819,10 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) { int colWidth = GetColumnWidth(col); x += colWidth; - dc.DrawLine(x - dev_x - 2, firstItemRect.GetY() - 1 - dev_y, - x - dev_x - 2, lastItemRect.GetBottom() + 1 - dev_y); + int x_pos = x - dev_x; + if (col < GetColumnCount()-1) x_pos -= 2; + dc.DrawLine(x_pos, firstItemRect.GetY() - 1 - dev_y, + x_pos, lastItemRect.GetBottom() + 1 - dev_y); } } } @@ -2910,8 +2942,15 @@ wxTextCtrl *wxListMainWindow::EditLabel(long item, wxClassInfo* textControlClass // 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 ) + { wxSafeYield(); + // Pending events dispatched by wxSafeYield might have changed the item + // count + if ( (size_t)item >= GetItemCount() ) + return NULL; + } + wxTextCtrl * const text = (wxTextCtrl *)textControlClass->CreateObject(); m_textctrlWrapper = new wxListTextCtrlWrapper(this, text, item); return m_textctrlWrapper->GetText(); @@ -3115,7 +3154,15 @@ void wxListMainWindow::OnMouse( wxMouseEvent &event ) (hitResult == wxLIST_HITTEST_ONITEMLABEL) && HasFlag(wxLC_EDIT_LABELS) ) { - m_renameTimer->Start( 100, true ); + if (InReportView()) + { + wxRect label = GetLineLabelRect( current ); + if (label.Contains( x, y )) + m_renameTimer->Start( 250, true ); + + } + else + m_renameTimer->Start( 250, true ); } } @@ -3283,7 +3330,8 @@ void wxListMainWindow::OnArrowChar(size_t newCurrent, const wxKeyEvent& event) else // !shift { // all previously selected items are unselected unless ctrl is held - if ( !event.ControlDown() ) + // in a multiselection control + if ( !event.ControlDown() || IsSingleSel() ) HighlightAll(false); ChangeCurrent(newCurrent); @@ -3291,10 +3339,9 @@ void wxListMainWindow::OnArrowChar(size_t newCurrent, const wxKeyEvent& event) // refresh the old focus to remove it RefreshLine( oldCurrent ); - if ( !event.ControlDown() ) - { + // in single selection mode we must always have a selected item + if ( !event.ControlDown() || IsSingleSel() ) HighlightLine( m_current, true ); - } } RefreshLine( m_current ); @@ -3474,17 +3521,19 @@ void wxListMainWindow::OnChar( wxKeyEvent &event ) case WXK_SPACE: if ( IsSingleSel() ) { - SendNotify( m_current, wxEVT_COMMAND_LIST_ITEM_ACTIVATED ); - - if ( IsHighlighted(m_current) ) + if ( event.ControlDown() ) { - // don't unselect the item in single selection mode - break; + ReverseHighlight(m_current); + } + else // normal space press + { + SendNotify( m_current, wxEVT_COMMAND_LIST_ITEM_ACTIVATED ); } - //else: select it in ReverseHighlight() below if unselected } - - ReverseHighlight(m_current); + else // multiple selection + { + ReverseHighlight(m_current); + } break; case WXK_RETURN: @@ -3680,6 +3729,19 @@ void wxListMainWindow::SetColumnWidth( int col, int width ) if (width == wxLIST_AUTOSIZE_USEHEADER) { width = GetTextLength(column->GetText()); + width += 2*EXTRA_WIDTH; + + // check for column header's image availability + const int image = column->GetImage(); + if ( image != -1 ) + { + if ( m_small_image_list ) + { + int ix = 0, iy = 0; + m_small_image_list->GetSize(image, ix, iy); + width += ix + HEADER_IMAGE_MARGIN_IN_REPORT_MODE; + } + } } else if ( width == wxLIST_AUTOSIZE ) { @@ -4746,6 +4808,11 @@ int LINKAGEMODE list_ctrl_compare_func_1( wxListLineData **arg1, wxListLineData void wxListMainWindow::SortItems( wxListCtrlCompare fn, long data ) { + // selections won't make sense any more after sorting the items so reset + // them + HighlightAll(false); + ResetCurrent(); + list_ctrl_compare_func_2 = fn; list_ctrl_compare_data = data; m_lines.Sort( list_ctrl_compare_func_1 ); @@ -4758,10 +4825,6 @@ void wxListMainWindow::SortItems( wxListCtrlCompare fn, long data ) void wxListMainWindow::OnScroll(wxScrollWinEvent& event) { - // update our idea of which lines are shown when we redraw the window the - // next time - ResetVisibleLinesRange(); - // FIXME #if ( defined(__WXGTK__) || defined(__WXMAC__) ) && !defined(__WXUNIVERSAL__) wxScrolledWindow::OnScroll(event); @@ -4769,6 +4832,10 @@ void wxListMainWindow::OnScroll(wxScrollWinEvent& event) HandleOnScroll( event ); #endif + // update our idea of which lines are shown when we redraw the window the + // next time + ResetVisibleLinesRange(); + if ( event.GetOrientation() == wxHORIZONTAL && HasHeader() ) { wxGenericListCtrl* lc = GetListCtrl(); @@ -4930,6 +4997,9 @@ bool wxGenericListCtrl::Create(wxWindow *parent, if ( !wxControl::Create( parent, id, pos, size, style, validator, name ) ) return false; + // this window itself shouldn't get the focus, only m_mainWin should + SetCanFocus(false); + // don't create the inner window with the border style &= ~wxBORDER_MASK; @@ -5140,7 +5210,7 @@ wxUIntPtr wxGenericListCtrl::GetItemData( long item ) const return info.m_data; } -bool wxGenericListCtrl::SetItemData( long item, long data ) +bool wxGenericListCtrl::SetItemPtrData( long item, wxUIntPtr data ) { wxListItem info; info.m_mask = wxLIST_MASK_DATA;