]> git.saurik.com Git - wxWidgets.git/blobdiff - src/generic/listctrl.cpp
Prevent crash when m_defGridAttr is NULL
[wxWidgets.git] / src / generic / listctrl.cpp
index 6008a869de6237c3460f6a503ee8deca35229752..9f32c43da4a62f9874dc4951df0b30b68383a783 100644 (file)
 
 #if wxUSE_LISTCTRL
 
-#include "wx/dcscreen.h"
-#include "wx/app.h"
-#include "wx/listctrl.h"
+#ifndef WX_PRECOMP
+    #include "wx/app.h"
+
+    #include "wx/dynarray.h"
+
+    #include "wx/dcscreen.h"
+
+    #include "wx/textctrl.h"
+#endif
+
 #include "wx/imaglist.h"
-#include "wx/dynarray.h"
+#include "wx/listctrl.h"
 
 #ifdef __WXGTK__
-#include <gtk/gtk.h>
-#include "wx/gtk/win_gtk.h"
+    #include <gtk/gtk.h>
+    #include "wx/gtk/win_gtk.h"
 #endif
 
 // ----------------------------------------------------------------------------
@@ -495,6 +502,7 @@ private:
     wxString           *m_res;
     wxListMainWindow   *m_owner;
     wxString            m_startValue;
+    bool                m_finished;
 
 public:
     wxListTextCtrl() {}
@@ -971,8 +979,10 @@ bool wxSelectionStore::SelectRange(size_t itemFrom, size_t itemTo,
                             // stop counting (see comment below)
                             itemsChanged = NULL;
                         }
-
-                        itemsChanged->Add(m_itemsSel[i]);
+                        else
+                        {
+                            itemsChanged->Add(m_itemsSel[i]);
+                        }
                     }
 
                     m_itemsSel.RemoveAt(i);
@@ -2130,6 +2140,7 @@ wxListTextCtrl::wxListTextCtrl( wxWindow *parent,
     (*m_accept) = FALSE;
     (*m_res) = "";
     m_startValue = value;
+    m_finished = FALSE;
 }
 
 void wxListTextCtrl::OnChar( wxKeyEvent &event )
@@ -2142,9 +2153,12 @@ void wxListTextCtrl::OnChar( wxKeyEvent &event )
         if (!wxPendingDelete.Member(this))
             wxPendingDelete.Append(this);
 
-        if ((*m_accept) && ((*m_res) != m_startValue))
+        if ((*m_res) != m_startValue)
             m_owner->OnRenameAccept();
 
+        m_finished = TRUE;
+        m_owner->SetFocus(); // This doesn't work. TODO.
+
         return;
     }
     if (event.m_keyCode == WXK_ESCAPE)
@@ -2155,6 +2169,9 @@ void wxListTextCtrl::OnChar( wxKeyEvent &event )
         if (!wxPendingDelete.Member(this))
             wxPendingDelete.Append(this);
 
+        m_finished = TRUE;
+        m_owner->SetFocus(); // This doesn't work. TODO.
+
         return;
     }
 
@@ -2163,12 +2180,18 @@ void wxListTextCtrl::OnChar( wxKeyEvent &event )
 
 void wxListTextCtrl::OnKeyUp( wxKeyEvent &event )
 {
+    if (m_finished)
+    {
+        event.Skip();
+        return;
+    }
+
     // auto-grow the textctrl:
     wxSize parentSize = m_owner->GetSize();
     wxPoint myPos = GetPosition();
     wxSize mySize = GetSize();
     int sx, sy;
-    GetTextExtent(GetValue() + _T("MM"), &sx, &sy); // FIXME: MM??
+    GetTextExtent(GetValue() + _T("M"), &sx, &sy); // FIXME: MM??
     if (myPos.x + sx > parentSize.x)
         sx = parentSize.x - myPos.x;
     if (mySize.x > sx)
@@ -2178,12 +2201,21 @@ void wxListTextCtrl::OnKeyUp( wxKeyEvent &event )
     event.Skip();
 }
 
-void wxListTextCtrl::OnKillFocus( wxFocusEvent &WXUNUSED(event) )
+void wxListTextCtrl::OnKillFocus( wxFocusEvent &event )
 {
+    if (m_finished)
+    {
+        event.Skip();
+        return;
+    }
+
     if (!wxPendingDelete.Member(this))
         wxPendingDelete.Append(this);
 
-    if ((*m_accept) && ((*m_res) != m_startValue))
+    (*m_accept) = TRUE;
+    (*m_res) = GetValue();
+    
+    if ((*m_res) != m_startValue)
         m_owner->OnRenameAccept();
 }
 
@@ -3888,10 +3920,26 @@ void wxListMainWindow::RecalculatePositions(bool noRefresh)
     else
         iconSpacing = 0;
 
+    // Note that we do not call GetClientSize() here but
+    // GetSize() and substract the border size for sunken
+    // borders manually. This is technically incorrect,
+    // but we need to know the client area's size WITHOUT
+    // scrollbars here. Since we don't know if there are
+    // any scrollbars, we use GetSize() instead. Another
+    // solution would be to call SetScrollbars() here to
+    // remove the scrollbars and call GetClientSize() then,
+    // but this might result in flicker and - worse - will
+    // reset the scrollbars to 0 which is not good at all
+    // if you resize a dialog/window, but don't want to
+    // reset the window scrolling. RR.
+    // Furthermore, we actually do NOT subtract the border
+    // width as 2 pixels is just the extra space which we
+    // need around the actual content in the window. Other-
+    // wise the text would e.g. touch the upper border. RR.
     int clientWidth,
         clientHeight;
-    GetClientSize( &clientWidth, &clientHeight );
-
+    GetSize( &clientWidth, &clientHeight );
+    
     if ( HasFlag(wxLC_REPORT) )
     {
         // all lines have the same height
@@ -3920,13 +3968,26 @@ void wxListMainWindow::RecalculatePositions(bool noRefresh)
         // fit into the window, we recalculate after subtracting an
         // approximated 15 pt for the horizontal scrollbar
 
-        clientHeight -= 4;  // sunken frame
-
         int entireWidth = 0;
 
         for (int tries = 0; tries < 2; tries++)
         {
-            entireWidth = 0;
+            // We start with 4 for the border around all items
+            entireWidth = 4;
+                
+            if (tries == 1)
+            {
+                // Now we have decided that the items do not fit into the
+                // client area. Unfortunately, wxWindows sometimes thinks
+                // that it does fit and therefore NO horizontal scrollbar
+                // is inserted. This looks ugly, so we fudge here and make
+                // the calculated width bigger than was actually has been
+                // calculated. This ensures that wxScrolledWindows puts
+                // a scrollbar at the bottom of its client area.
+                entireWidth += SCROLL_UNIT_X;
+            }
+            
+            // Start at 2,2 so the text does not touch the border
             int x = 2;
             int y = 2;
             int maxWidth = 0;
@@ -3939,7 +4000,7 @@ void wxListMainWindow::RecalculatePositions(bool noRefresh)
                 currentlyVisibleLines++;
                 wxListLineData *line = GetLine(i);
                 line->CalculateSize( &dc, iconSpacing );
-                line->SetPosition( x, y, clientWidth, iconSpacing );
+                line->SetPosition( x, y, clientWidth, iconSpacing );  // Why clientWidth? (FIXME)
 
                 wxSize sizeLine = GetLineSize(i);
 
@@ -3950,8 +4011,8 @@ void wxListMainWindow::RecalculatePositions(bool noRefresh)
                 if (currentlyVisibleLines > m_linesPerPage)
                     m_linesPerPage = currentlyVisibleLines;
 
-                // assume that the size of the next one is the same... (FIXME)
-                if ( y + sizeLine.y - 6 >= clientHeight )
+                // Assume that the size of the next one is the same... (FIXME)
+                if ( y + sizeLine.y >= clientHeight )
                 {
                     currentlyVisibleLines = 0;
                     y = 2;
@@ -3959,17 +4020,21 @@ void wxListMainWindow::RecalculatePositions(bool noRefresh)
                     entireWidth += maxWidth+6;
                     maxWidth = 0;
                 }
+                
+                // We have reached the last item.
                 if ( i == count - 1 )
                     entireWidth += maxWidth;
-                if ((tries == 0) && (entireWidth > clientWidth))
+                    
+                if ( (tries == 0) && (entireWidth+SCROLL_UNIT_X > clientWidth) )
                 {
-                    clientHeight -= 15; // scrollbar height
+                    clientHeight -= 15; // We guess the scrollbar height. (FIXME)
                     m_linesPerPage = 0;
                     currentlyVisibleLines = 0;
                     break;
                 }
+                
                 if ( i == count - 1 )
-                    tries = 1;  // everything fits, no second try required
+                    tries = 1;  // Everything fits, no second try required.
             }
         }
 
@@ -4443,53 +4508,6 @@ void wxListItem::ClearAttributes()
     }
 }
 
-// -------------------------------------------------------------------------------------
-// wxListEvent
-// -------------------------------------------------------------------------------------
-
-IMPLEMENT_DYNAMIC_CLASS(wxListEvent, wxNotifyEvent)
-
-wxListEvent::wxListEvent( wxEventType commandType, int id )
-           : wxNotifyEvent( commandType, id )
-{
-    m_code = 0;
-    m_itemIndex = 0;
-    m_oldItemIndex = 0;
-    m_col = 0;
-    m_cancelled = FALSE;
-    m_pointDrag.x = 0;
-    m_pointDrag.y = 0;
-}
-
-void wxListEvent::CopyObject(wxObject& object_dest) const
-{
-    wxListEvent *obj = (wxListEvent *)&object_dest;
-
-    wxNotifyEvent::CopyObject(object_dest);
-
-    obj->m_code = m_code;
-    obj->m_itemIndex = m_itemIndex;
-    obj->m_oldItemIndex = m_oldItemIndex;
-    obj->m_col = m_col;
-    obj->m_cancelled = m_cancelled;
-    obj->m_pointDrag = m_pointDrag;
-    obj->m_item.m_mask = m_item.m_mask;
-    obj->m_item.m_itemId = m_item.m_itemId;
-    obj->m_item.m_col = m_item.m_col;
-    obj->m_item.m_state = m_item.m_state;
-    obj->m_item.m_stateMask = m_item.m_stateMask;
-    obj->m_item.m_text = m_item.m_text;
-    obj->m_item.m_image = m_item.m_image;
-    obj->m_item.m_data = m_item.m_data;
-    obj->m_item.m_format = m_item.m_format;
-    obj->m_item.m_width = m_item.m_width;
-
-    if ( m_item.HasAttributes() )
-    {
-        obj->m_item.SetTextColour(m_item.GetTextColour());
-    }
-}
-
 // -------------------------------------------------------------------------------------
 // wxListCtrl
 // -------------------------------------------------------------------------------------
@@ -4497,6 +4515,8 @@ void wxListEvent::CopyObject(wxObject& object_dest) const
 IMPLEMENT_DYNAMIC_CLASS(wxListCtrl, wxControl)
 IMPLEMENT_DYNAMIC_CLASS(wxListView, wxListCtrl)
 
+IMPLEMENT_DYNAMIC_CLASS(wxListEvent, wxNotifyEvent)
+
 BEGIN_EVENT_TABLE(wxListCtrl,wxControl)
   EVT_SIZE(wxListCtrl::OnSize)
   EVT_IDLE(wxListCtrl::OnIdle)