]> git.saurik.com Git - wxWidgets.git/blobdiff - src/generic/listctrl.cpp
renamed wxWave to wxSound
[wxWidgets.git] / src / generic / listctrl.cpp
index 5bed03921da555c67400ff8911c4414dc0aedb0e..394e27505cde8397c53863c66c1ed48cf09b144b 100644 (file)
@@ -106,9 +106,7 @@ DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_CACHE_HINT)
 // // the height of the header window (FIXME: should depend on its font!)
 // static const int HEADER_HEIGHT = 23;
 
-// the scrollbar units
 static const int SCROLL_UNIT_X = 15;
-static const int SCROLL_UNIT_Y = 15;
 
 // the spacing between the lines (in report mode)
 static const int LINE_SPACING = 0;
@@ -282,6 +280,18 @@ public:
 
         // the part to be highlighted
         wxRect m_rectHighlight;
+
+        // extend all our rects to be centered inside theo ne of given width
+        void ExtendWidth(wxCoord w)
+        {
+            wxASSERT_MSG( m_rectAll.width <= w,
+                            _T("width can only be increased") );
+
+            m_rectAll.width = w;
+            m_rectLabel.x = m_rectAll.x + (w - m_rectLabel.width)/2;
+            m_rectIcon.x = m_rectAll.x + (w - m_rectIcon.width)/2;
+            m_rectHighlight.x = m_rectAll.x + (w - m_rectHighlight.width)/2;
+        }
     } *m_gi;
 
     // is this item selected? [NB: not used in virtual mode]
@@ -1115,96 +1125,89 @@ void wxListLineData::CalculateSize( wxDC *dc, int spacing )
 
     wxListItemData *item = node->GetData();
 
+    wxString s;
+    wxCoord lw, lh;
+
     switch ( GetMode() )
     {
         case wxLC_ICON:
         case wxLC_SMALL_ICON:
-            {
-                m_gi->m_rectAll.width = spacing;
+            m_gi->m_rectAll.width = spacing;
 
-                wxString s = item->GetText();
+            s = item->GetText();
 
-                wxCoord lw, lh;
-                if ( s.empty() )
-                {
-                    lh =
-                    m_gi->m_rectLabel.width =
-                    m_gi->m_rectLabel.height = 0;
-                }
-                else // has label
-                {
-                    dc->GetTextExtent( s, &lw, &lh );
-                    if (lh < SCROLL_UNIT_Y)
-                        lh = SCROLL_UNIT_Y;
-                    lw += EXTRA_WIDTH;
-                    lh += EXTRA_HEIGHT;
-
-                    m_gi->m_rectAll.height = spacing + lh;
-                    if (lw > spacing)
-                        m_gi->m_rectAll.width = lw;
-
-                    m_gi->m_rectLabel.width = lw;
-                    m_gi->m_rectLabel.height = lh;
-                }
-
-                if (item->HasImage())
-                {
-                    int w, h;
-                    m_owner->GetImageSize( item->GetImage(), w, h );
-                    m_gi->m_rectIcon.width = w + 8;
-                    m_gi->m_rectIcon.height = h + 8;
-
-                    if ( m_gi->m_rectIcon.width > m_gi->m_rectAll.width )
-                        m_gi->m_rectAll.width = m_gi->m_rectIcon.width;
-                    if ( m_gi->m_rectIcon.height + lh > m_gi->m_rectAll.height - 4 )
-                        m_gi->m_rectAll.height = m_gi->m_rectIcon.height + lh + 4;
-                }
-
-                if ( item->HasText() )
-                {
-                    m_gi->m_rectHighlight.width = m_gi->m_rectLabel.width;
-                    m_gi->m_rectHighlight.height = m_gi->m_rectLabel.height;
-                }
-                else // no text, highlight the icon
-                {
-                    m_gi->m_rectHighlight.width = m_gi->m_rectIcon.width;
-                    m_gi->m_rectHighlight.height = m_gi->m_rectIcon.height;
-                }
+            if ( s.empty() )
+            {
+                lh =
+                m_gi->m_rectLabel.width =
+                m_gi->m_rectLabel.height = 0;
             }
-            break;
-
-        case wxLC_LIST:
+            else // has label
             {
-                wxString s = item->GetTextForMeasuring();
-
-                wxCoord lw,lh;
                 dc->GetTextExtent( s, &lw, &lh );
-                if (lh < SCROLL_UNIT_Y)
-                    lh = SCROLL_UNIT_Y;
                 lw += EXTRA_WIDTH;
                 lh += EXTRA_HEIGHT;
 
+                m_gi->m_rectAll.height = spacing + lh;
+                if (lw > spacing)
+                    m_gi->m_rectAll.width = lw;
+
                 m_gi->m_rectLabel.width = lw;
                 m_gi->m_rectLabel.height = lh;
+            }
 
-                m_gi->m_rectAll.width = lw;
-                m_gi->m_rectAll.height = lh;
+            if (item->HasImage())
+            {
+                int w, h;
+                m_owner->GetImageSize( item->GetImage(), w, h );
+                m_gi->m_rectIcon.width = w + 8;
+                m_gi->m_rectIcon.height = h + 8;
+
+                if ( m_gi->m_rectIcon.width > m_gi->m_rectAll.width )
+                    m_gi->m_rectAll.width = m_gi->m_rectIcon.width;
+                if ( m_gi->m_rectIcon.height + lh > m_gi->m_rectAll.height - 4 )
+                    m_gi->m_rectAll.height = m_gi->m_rectIcon.height + lh + 4;
+            }
 
-                if (item->HasImage())
-                {
-                    int w, h;
-                    m_owner->GetImageSize( item->GetImage(), w, h );
-                    m_gi->m_rectIcon.width = w;
-                    m_gi->m_rectIcon.height = h;
-
-                    m_gi->m_rectAll.width += 4 + w;
-                    if (h > m_gi->m_rectAll.height)
-                        m_gi->m_rectAll.height = h;
-                }
+            if ( item->HasText() )
+            {
+                m_gi->m_rectHighlight.width = m_gi->m_rectLabel.width;
+                m_gi->m_rectHighlight.height = m_gi->m_rectLabel.height;
+            }
+            else // no text, highlight the icon
+            {
+                m_gi->m_rectHighlight.width = m_gi->m_rectIcon.width;
+                m_gi->m_rectHighlight.height = m_gi->m_rectIcon.height;
+            }
+            break;
+
+        case wxLC_LIST:
+            s = item->GetTextForMeasuring();
+
+            dc->GetTextExtent( s, &lw, &lh );
+            lw += EXTRA_WIDTH;
+            lh += EXTRA_HEIGHT;
 
-                m_gi->m_rectHighlight.width = m_gi->m_rectAll.width;
-                m_gi->m_rectHighlight.height = m_gi->m_rectAll.height;
+            m_gi->m_rectLabel.width = lw;
+            m_gi->m_rectLabel.height = lh;
+
+            m_gi->m_rectAll.width = lw;
+            m_gi->m_rectAll.height = lh;
+
+            if (item->HasImage())
+            {
+                int w, h;
+                m_owner->GetImageSize( item->GetImage(), w, h );
+                m_gi->m_rectIcon.width = w;
+                m_gi->m_rectIcon.height = h;
+
+                m_gi->m_rectAll.width += 4 + w;
+                if (h > m_gi->m_rectAll.height)
+                    m_gi->m_rectAll.height = h;
             }
+
+            m_gi->m_rectHighlight.width = m_gi->m_rectAll.width;
+            m_gi->m_rectHighlight.height = m_gi->m_rectAll.height;
             break;
 
         case wxLC_REPORT:
@@ -1446,20 +1449,31 @@ void wxListLineData::Draw( wxDC *dc )
         dc->DrawRectangle( m_gi->m_rectHighlight );
     }
 
+    // just for debugging to better see where the items are
+#if 0
+    dc->SetPen(*wxRED_PEN);
+    dc->SetBrush(*wxTRANSPARENT_BRUSH);
+    dc->DrawRectangle( m_gi->m_rectAll );
+    dc->SetPen(*wxGREEN_PEN);
+    dc->DrawRectangle( m_gi->m_rectIcon );
+#endif // 0
+
     wxListItemData *item = node->GetData();
     if (item->HasImage())
     {
-        wxRect rectIcon = m_gi->m_rectIcon;
-        m_owner->DrawImage( item->GetImage(), dc,
-                            rectIcon.x, rectIcon.y );
+        // centre the image inside our rectangle, this looks nicer when items
+        // ae aligned in a row
+        const wxRect& rectIcon = m_gi->m_rectIcon;
+
+        m_owner->DrawImage(item->GetImage(), dc, rectIcon.x, rectIcon.y);
     }
 
     if (item->HasText())
     {
-        wxRect rectLabel = m_gi->m_rectLabel;
+        const wxRect& rectLabel = m_gi->m_rectLabel;
 
         wxDCClipper clipper(*dc, rectLabel);
-        dc->DrawText( item->GetText(), rectLabel.x, rectLabel.y );
+        dc->DrawText(item->GetText(), rectLabel.x, rectLabel.y);
     }
 }
 
@@ -2084,11 +2098,11 @@ void wxListTextCtrl::OnKillFocus( wxFocusEvent &event )
     {
         // We must finish regardless of success, otherwise we'll get focus problems
         Finish();
-    
+
         if ( !AcceptChanges() )
             m_owner->OnRenameCancelled( m_itemEdited );
     }
-        
+
     event.Skip();
 }
 
@@ -2179,7 +2193,7 @@ wxListMainWindow::wxListMainWindow( wxWindow *parent,
     wxSize sz = size;
     sz.y = 25;
 
-    SetScrollbars( SCROLL_UNIT_X, SCROLL_UNIT_Y, 0, 0, 0, 0 );
+    SetScrollbars( 0, 0, 0, 0, 0, 0 );
 
     SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_LISTBOX ) );
 }
@@ -2247,8 +2261,6 @@ wxListLineData *wxListMainWindow::GetDummyLine() const
 
 wxCoord wxListMainWindow::GetLineHeight() const
 {
-    wxASSERT_MSG( HasFlag(wxLC_REPORT), _T("only works in report mode") );
-
     // we cache the line height as calling GetTextExtent() is slow
     if ( !m_lineHeight )
     {
@@ -2260,9 +2272,6 @@ wxCoord wxListMainWindow::GetLineHeight() const
         wxCoord y;
         dc.GetTextExtent(_T("H"), NULL, &y);
 
-        if ( y < SCROLL_UNIT_Y )
-            y = SCROLL_UNIT_Y;
-
         if ( m_small_image_list && m_small_image_list->GetImageCount() )
         {
             int iw = 0;
@@ -2662,7 +2671,6 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
         {
             wxPen pen(GetRuleColour(), 1, wxSOLID);
 
-            int col = 0;
             wxRect firstItemRect;
             wxRect lastItemRect;
             GetItemRect(visibleFrom, firstItemRect);
@@ -2670,7 +2678,7 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
             int x = firstItemRect.GetX();
             dc.SetPen(pen);
             dc.SetBrush(* wxTRANSPARENT_BRUSH);
-            for (col = 0; col < GetColumnCount(); col++)
+            for (int col = 0; col < GetColumnCount(); col++)
             {
                 int colWidth = GetColumnWidth(col);
                 x += colWidth;
@@ -2814,23 +2822,13 @@ bool wxListMainWindow::OnRenameAccept(size_t itemEdit, const wxString& value)
                 le.IsAllowed();
 }
 
-#ifdef __VMS__ // Ignore unreacheable code
-# pragma message disable initnotreach
-#endif
-
 void wxListMainWindow::OnRenameCancelled(size_t itemEdit)
 {
-    // wxMSW seems not to notify the program about
-    // cancelled label edits.
-    return;
-
     // let owner know that the edit was cancelled
     wxListEvent le( wxEVT_COMMAND_LIST_END_LABEL_EDIT, GetParent()->GetId() );
-    
-    // These only exist for wxTreeCtrl, which should probably be changed
-    // le.m_editCancelled = TRUE;
-    // le.m_label = wxEmptyString;
-    
+
+    le.SetEditCanceled(TRUE);
+
     le.SetEventObject( GetParent() );
     le.m_itemIndex = itemEdit;
 
@@ -2841,9 +2839,6 @@ void wxListMainWindow::OnRenameCancelled(size_t itemEdit)
 
     GetEventHandler()->ProcessEvent( le );
 }
-#ifdef __VMS__
-# pragma message enable initnotreach
-#endif
 
 void wxListMainWindow::OnMouse( wxMouseEvent &event )
 {
@@ -3030,8 +3025,10 @@ void wxListMainWindow::MoveToItem(size_t item)
     int client_w, client_h;
     GetClientSize( &client_w, &client_h );
 
+    const int hLine = GetLineHeight();
+
     int view_x = SCROLL_UNIT_X*GetScrollPos( wxHORIZONTAL );
-    int view_y = SCROLL_UNIT_Y*GetScrollPos( wxVERTICAL );
+    int view_y = hLine*GetScrollPos( wxVERTICAL );
 
     if ( HasFlag(wxLC_REPORT) )
     {
@@ -3040,9 +3037,9 @@ void wxListMainWindow::MoveToItem(size_t item)
         ResetVisibleLinesRange();
 
         if (rect.y < view_y )
-            Scroll( -1, rect.y/SCROLL_UNIT_Y );
+            Scroll( -1, rect.y/hLine );
         if (rect.y+rect.height+5 > view_y+client_h)
-            Scroll( -1, (rect.y+rect.height-client_h+SCROLL_UNIT_Y)/SCROLL_UNIT_Y );
+            Scroll( -1, (rect.y+rect.height-client_h+hLine)/hLine );
     }
     else // !report
     {
@@ -3189,15 +3186,7 @@ void wxListMainWindow::OnChar( wxKeyEvent &event )
 
         case WXK_PRIOR:
             {
-                int steps = 0;
-                if ( HasFlag(wxLC_REPORT) )
-                {
-                    steps = m_linesPerPage - 1;
-                }
-                else
-                {
-                    steps = m_current % m_linesPerPage;
-                }
+                int steps = HasFlag(wxLC_REPORT) ? m_linesPerPage - 1 : m_current % m_linesPerPage;
 
                 int index = m_current - steps;
                 if (index < 0)
@@ -3209,15 +3198,9 @@ void wxListMainWindow::OnChar( wxKeyEvent &event )
 
         case WXK_NEXT:
             {
-                int steps = 0;
-                if ( HasFlag(wxLC_REPORT) )
-                {
-                    steps = m_linesPerPage - 1;
-                }
-                else
-                {
-                    steps = m_linesPerPage - (m_current % m_linesPerPage) - 1;
-                }
+                int steps = HasFlag(wxLC_REPORT)
+                               ? m_linesPerPage - 1
+                               : m_linesPerPage - (m_current % m_linesPerPage) - 1;
 
                 size_t index = m_current + steps;
                 size_t count = GetItemCount();
@@ -3304,6 +3287,14 @@ void wxListMainWindow::SetFocus()
 
 void wxListMainWindow::OnSetFocus( wxFocusEvent &WXUNUSED(event) )
 {
+    if ( GetParent() )
+    {
+        wxFocusEvent event( wxEVT_SET_FOCUS, GetParent()->GetId() );
+        event.SetEventObject( GetParent() );
+        if ( GetParent()->GetEventHandler()->ProcessEvent( event) )
+            return;
+    }
+
     // wxGTK sends us EVT_SET_FOCUS events even if we had never got
     // EVT_KILL_FOCUS before which means that we finish by redrawing the items
     // which are already drawn correctly resulting in horrible flicker - avoid
@@ -3314,19 +3305,18 @@ void wxListMainWindow::OnSetFocus( wxFocusEvent &WXUNUSED(event) )
 
         RefreshSelected();
     }
-
-    if ( !GetParent() )
-        return;
-
-    wxFocusEvent event( wxEVT_SET_FOCUS, GetParent()->GetId() );
-    event.SetEventObject( GetParent() );
-    GetParent()->GetEventHandler()->ProcessEvent( event );
 }
 
 void wxListMainWindow::OnKillFocus( wxFocusEvent &WXUNUSED(event) )
 {
+    if ( GetParent() )
+    {
+        wxFocusEvent event( wxEVT_KILL_FOCUS, GetParent()->GetId() );
+        event.SetEventObject( GetParent() );
+        if ( GetParent()->GetEventHandler()->ProcessEvent( event) )
+            return;
+    }
     m_hasFocus = FALSE;
-
     RefreshSelected();
 }
 
@@ -3863,11 +3853,11 @@ void wxListMainWindow::RecalculatePositions(bool noRefresh)
         clientHeight;
     GetSize( &clientWidth, &clientHeight );
 
+    const int lineHeight = GetLineHeight();
+
     if ( HasFlag(wxLC_REPORT) )
     {
         // all lines have the same height and we scroll one line per step
-        int lineHeight = GetLineHeight();
-
         int entireHeight = count*lineHeight + LINE_SPACING;
 
         m_linesPerPage = clientHeight / lineHeight;
@@ -3892,7 +3882,10 @@ void wxListMainWindow::RecalculatePositions(bool noRefresh)
             int x = EXTRA_BORDER_X;
             int y = EXTRA_BORDER_Y;
 
-            for ( size_t i = 0; i < count; i++ )
+            wxCoord widthMax = 0;
+
+            size_t i;
+            for ( i = 0; i < count; i++ )
             {
                 wxListLineData *line = GetLine(i);
                 line->CalculateSize( &dc, iconSpacing );
@@ -3902,6 +3895,9 @@ void wxListMainWindow::RecalculatePositions(bool noRefresh)
 
                 if ( HasFlag(wxLC_ALIGN_TOP) )
                 {
+                    if ( sizeLine.x > widthMax )
+                        widthMax = sizeLine.x;
+
                     y += sizeLine.y;
                 }
                 else // wxLC_ALIGN_LEFT
@@ -3910,12 +3906,24 @@ void wxListMainWindow::RecalculatePositions(bool noRefresh)
                 }
             }
 
+            if ( HasFlag(wxLC_ALIGN_TOP) )
+            {
+                // traverse the items again and tweak their sizes so that they are
+                // all the same in a row
+                for ( i = 0; i < count; i++ )
+                {
+                    wxListLineData *line = GetLine(i);
+                    line->m_gi->ExtendWidth(widthMax);
+                }
+            }
+
+
             SetScrollbars
             (
                 SCROLL_UNIT_X,
-                SCROLL_UNIT_Y,
+                lineHeight,
                 (x + SCROLL_UNIT_X) / SCROLL_UNIT_X,
-                (y + SCROLL_UNIT_Y) / SCROLL_UNIT_Y,
+                (y + lineHeight) / lineHeight,
                 GetScrollPos( wxHORIZONTAL ),
                 GetScrollPos( wxVERTICAL ),
                 TRUE
@@ -3927,13 +3935,11 @@ void wxListMainWindow::RecalculatePositions(bool noRefresh)
             // the window, we recalculate after subtracting the space taken by the
             // scrollbar
 
-            int entireWidth = 0,
-                entireHeight = 0;
+            int entireWidth = 0;
 
             for (int tries = 0; tries < 2; tries++)
             {
                 entireWidth = 2*EXTRA_BORDER_X;
-                entireHeight = 2*EXTRA_BORDER_Y;
 
                 if (tries == 1)
                 {
@@ -3985,7 +3991,6 @@ void wxListMainWindow::RecalculatePositions(bool noRefresh)
                         clientHeight -= wxSystemSettings::
                                             GetMetric(wxSYS_HSCROLL_Y);
                         m_linesPerPage = 0;
-                        currentlyVisibleLines = 0;
                         break;
                     }
 
@@ -3997,7 +4002,7 @@ void wxListMainWindow::RecalculatePositions(bool noRefresh)
             SetScrollbars
             (
                 SCROLL_UNIT_X,
-                SCROLL_UNIT_Y,
+                lineHeight,
                 (entireWidth + SCROLL_UNIT_X) / SCROLL_UNIT_X,
                 0,
                 GetScrollPos( wxHORIZONTAL ),
@@ -4302,18 +4307,39 @@ void wxListMainWindow::InsertItem( wxListItem &item )
 
     m_dirty = TRUE;
 
+    #if 0
+    // this is unused variable
     int mode = 0;
+    #endif
     if ( HasFlag(wxLC_REPORT) )
     {
+        #if 0
+        // this is unused variable
         mode = wxLC_REPORT;
+        #endif
         ResetVisibleLinesRange();
     }
     else if ( HasFlag(wxLC_LIST) )
+        #if 0
+        // this is unused variable
         mode = wxLC_LIST;
+        #else
+        {}
+        #endif
     else if ( HasFlag(wxLC_ICON) )
+        #if 0
+        // this is unused variable
         mode = wxLC_ICON;
+        #else
+        {}
+        #endif
     else if ( HasFlag(wxLC_SMALL_ICON) )
+        #if 0
+        // this is unused variable
         mode = wxLC_ICON;  // no typo
+        #else
+        {}
+        #endif
     else
     {
         wxFAIL_MSG( _T("unknown mode") );
@@ -4327,6 +4353,14 @@ void wxListMainWindow::InsertItem( wxListItem &item )
 
     m_dirty = TRUE;
 
+    // If an item is selected at or below the point of insertion, we need to
+    // increment the member variables because the current row's index has gone
+    // up by one
+    if ( HasCurrent() && m_current >= id )
+    {
+        m_current++;
+    }
+
     SendNotify(id, wxEVT_COMMAND_LIST_INSERT_ITEM);
 
     RefreshLines(id, GetItemCount() - 1);
@@ -4511,11 +4545,24 @@ wxGenericListCtrl::~wxGenericListCtrl()
 
 void wxGenericListCtrl::CalculateAndSetHeaderHeight()
 {
-    // we use the letter "H" for calculating the needed space, basing on the current font
-    int w, h;
-    m_headerWin->GetTextExtent(wxT("H"), &w, &h);
-    m_headerHeight = h + 2 * HEADER_OFFSET_Y + EXTRA_HEIGHT;
-    m_headerWin->SetSize(m_headerWin->GetSize().x, m_headerHeight);
+    if ( m_headerWin )
+    {
+        // we use 'g' to get the descent, too
+        int w, h, d;
+        m_headerWin->GetTextExtent(wxT("Hg"), &w, &h, &d);
+        h += d + 2 * HEADER_OFFSET_Y + EXTRA_HEIGHT;
+
+        // only update if changed
+        if ( h != m_headerHeight )
+        {
+            m_headerHeight = h;
+
+            m_headerWin->SetSize(m_headerWin->GetSize().x, m_headerHeight);
+
+            if ( HasFlag(wxLC_REPORT) && !HasFlag(wxLC_NO_HEADER) )
+                ResizeReportView(TRUE);
+        }
+    }
 }
 
 void wxGenericListCtrl::CreateHeaderWindow()
@@ -4548,6 +4595,8 @@ bool wxGenericListCtrl::Create(wxWindow *parent,
     m_mainWin = (wxListMainWindow*) NULL;
     m_headerWin = (wxListHeaderWindow*) NULL;
 
+    m_headerHeight = 0;
+
     if ( !(style & wxLC_MASK_TYPE) )
     {
         style = style | wxLC_LIST;
@@ -5110,7 +5159,7 @@ void wxGenericListCtrl::ResizeReportView(bool showHeader)
 void wxGenericListCtrl::OnInternalIdle()
 {
     wxWindow::OnInternalIdle();
-    
+
     // do it only if needed
     if ( !m_mainWin->m_dirty )
         return;
@@ -5245,7 +5294,8 @@ int wxGenericListCtrl::OnGetItemImage(long WXUNUSED(item)) const
     return -1;
 }
 
-wxListItemAttr *wxGenericListCtrl::OnGetItemAttr(long item) const
+wxListItemAttr *
+wxGenericListCtrl::OnGetItemAttr(long WXUNUSED_UNLESS_DEBUG(item)) const
 {
     wxASSERT_MSG( item >= 0 && item < GetItemCount(),
                   _T("invalid item index in OnGetItemAttr()") );