X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/0ddefeb07f03c1beac0dea55617ea50f3fdbcd8b..9d2cef1c694eb0c34ae4b9c9bd7ab04e3255301d:/src/generic/listctrl.cpp diff --git a/src/generic/listctrl.cpp b/src/generic/listctrl.cpp index 6008a869de..850879e1ce 100644 --- a/src/generic/listctrl.cpp +++ b/src/generic/listctrl.cpp @@ -37,15 +37,22 @@ #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 -#include "wx/gtk/win_gtk.h" +#if defined(__WXGTK__) + #include + #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() {} @@ -618,6 +626,8 @@ public: // suspend/resume redrawing the control void Freeze(); void Thaw(); + + void SetFocus(); void OnRenameTimer(); void OnRenameAccept(); @@ -819,7 +829,7 @@ protected: #ifdef __WXMAC__ return *wxWHITE; #else - return wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DLIGHT); + return wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT); #endif } @@ -971,8 +981,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); @@ -1585,7 +1597,7 @@ bool wxListLineData::SetAttributes(wxDC *dc, wxColour colText; if ( highlighted ) { - colText = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHTTEXT); + colText = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT); } else { @@ -1776,7 +1788,7 @@ wxListHeaderWindow::wxListHeaderWindow( wxWindow *win, m_owner = owner; m_resizeCursor = new wxCursor( wxCURSOR_SIZEWE ); - SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE ) ); + SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); } wxListHeaderWindow::~wxListHeaderWindow() @@ -1786,7 +1798,7 @@ wxListHeaderWindow::~wxListHeaderWindow() void wxListHeaderWindow::DoDrawRect( wxDC *dc, int x, int y, int w, int h ) { -#ifdef __WXGTK__ +#if defined(__WXGTK__) && !defined(__WXUNIVERSAL__) GtkStateType state = m_parent->IsEnabled() ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE; @@ -1794,14 +1806,15 @@ void wxListHeaderWindow::DoDrawRect( wxDC *dc, int x, int y, int w, int h ) gtk_paint_box (m_wxwindow->style, GTK_PIZZA(m_wxwindow)->bin_window, state, GTK_SHADOW_OUT, - (GdkRectangle*) NULL, m_wxwindow, "button", + (GdkRectangle*) NULL, m_wxwindow, + (char *)"button", // const_cast x-1, y-1, w+2, h+2); #elif defined( __WXMAC__ ) const int m_corner = 1; dc->SetBrush( *wxTRANSPARENT_BRUSH ); - dc->SetPen( wxPen( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNSHADOW ) , 1 , wxSOLID ) ); + dc->SetPen( wxPen( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNSHADOW ) , 1 , wxSOLID ) ); dc->DrawLine( x+w-m_corner+1, y, x+w, y+h ); // right (outer) dc->DrawRectangle( x, y+h, w+1, 1 ); // bottom (outer) @@ -1825,7 +1838,7 @@ void wxListHeaderWindow::DoDrawRect( wxDC *dc, int x, int y, int w, int h ) dc->DrawLine( x+w-m_corner+1, y, x+w, y+h ); // right (outer) dc->DrawRectangle( x, y+h, w+1, 1 ); // bottom (outer) - wxPen pen( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNSHADOW ), 1, wxSOLID ); + wxPen pen( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNSHADOW ), 1, wxSOLID ); dc->SetPen( pen ); dc->DrawLine( x+w-m_corner, y, x+w-1, y+h ); // right (inner) @@ -1855,7 +1868,7 @@ void wxListHeaderWindow::AdjustDC(wxDC& dc) void wxListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) { -#ifdef __WXGTK__ +#if defined(__WXGTK__) wxClientDC dc( this ); #else wxPaintDC dc( this ); @@ -1939,9 +1952,9 @@ void wxListHeaderWindow::DrawCurrent() { int x1 = m_currentX; int y1 = 0; - ClientToScreen( &x1, &y1 ); + m_owner->ClientToScreen( &x1, &y1 ); - int x2 = m_currentX-1; + int x2 = m_currentX; int y2 = 0; m_owner->GetClientSize( NULL, &y2 ); m_owner->ClientToScreen( &x2, &y2 ); @@ -2130,6 +2143,7 @@ wxListTextCtrl::wxListTextCtrl( wxWindow *parent, (*m_accept) = FALSE; (*m_res) = ""; m_startValue = value; + m_finished = FALSE; } void wxListTextCtrl::OnChar( wxKeyEvent &event ) @@ -2142,9 +2156,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(); + return; } if (event.m_keyCode == WXK_ESCAPE) @@ -2155,6 +2172,9 @@ void wxListTextCtrl::OnChar( wxKeyEvent &event ) if (!wxPendingDelete.Member(this)) wxPendingDelete.Append(this); + m_finished = TRUE; + m_owner->SetFocus(); + return; } @@ -2163,12 +2183,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("MM"), &sx, &sy); if (myPos.x + sx > parentSize.x) sx = parentSize.x - myPos.x; if (mySize.x > sx) @@ -2178,12 +2204,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(); } @@ -2275,7 +2310,7 @@ wxListMainWindow::wxListMainWindow( wxWindow *parent, m_highlightBrush = new wxBrush ( - wxSystemSettings::GetSystemColour + wxSystemSettings::GetColour ( wxSYS_COLOUR_HIGHLIGHT ), @@ -2284,7 +2319,7 @@ wxListMainWindow::wxListMainWindow( wxWindow *parent, m_highlightUnfocusedBrush = new wxBrush ( - wxSystemSettings::GetSystemColour + wxSystemSettings::GetColour ( wxSYS_COLOUR_BTNSHADOW ), @@ -2297,7 +2332,7 @@ wxListMainWindow::wxListMainWindow( wxWindow *parent, InitScrolling(); SetScrollbars( m_xScroll, m_yScroll, 0, 0, 0, 0 ); - SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_LISTBOX ) ); + SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_LISTBOX ) ); } wxListMainWindow::~wxListMainWindow() @@ -2627,14 +2662,6 @@ void wxListMainWindow::RefreshSelected() to = GetItemCount() - 1; } - // VZ: this code would work fine if wxGTK wxWindow::Refresh() were - // reasonable, i.e. if it only generated one expose event for - // several calls to it - as it is, each Refresh() results in a - // repaint which provokes flicker too horrible to be seen - // - // when/if wxGTK is fixed, this code should be restored as normally it - // should generate _less_ flicker than the version below -#ifndef __WXGTK__ if ( HasCurrent() && m_current >= from && m_current <= to ) { RefreshLine(m_current); @@ -2648,26 +2675,6 @@ void wxListMainWindow::RefreshSelected() RefreshLine(line); } } -#else // __WXGTK__ - size_t selMin = (size_t)-1, - selMax = 0; - - for ( size_t line = from; line <= to; line++ ) - { - if ( IsHighlighted(line) || (line == m_current) ) - { - if ( line < selMin ) - selMin = line; - if ( line > selMax ) - selMax = line; - } - } - - if ( selMin != (size_t)-1 ) - { - RefreshLines(selMin, selMax); - } -#endif // !__WXGTK__/__WXGTK__ } void wxListMainWindow::Freeze() @@ -3041,7 +3048,15 @@ void wxListMainWindow::OnMouse( wxMouseEvent &event ) m_renameTimer->Stop(); m_lastOnSame = FALSE; +#ifdef __WXGTK__ + // FIXME: wxGTK generates bad sequence of events prior to doubleclick + // ("down, up, down, double, up" while other ports + // do "down, up, double, up"). We have to have this hack + // in place till somebody fixes wxGTK... if ( current == m_lineBeforeLastClicked ) +#else + if ( current == m_lineLastClicked ) +#endif { SendNotify( current, wxEVT_COMMAND_LIST_ITEM_ACTIVATED ); @@ -3391,9 +3406,25 @@ void wxListMainWindow::OnChar( wxKeyEvent &event ) // focus handling // ---------------------------------------------------------------------------- -#ifdef __WXGTK__ -extern wxWindow *g_focusWindow; -#endif +void wxListMainWindow::SetFocus() +{ + // VS: wxListMainWindow derives from wxPanel (via wxScrolledWindow) and wxPanel + // overrides SetFocus in such way that it does never change focus from + // panel's child to the panel itself. Unfortunately, we must be able to change + // focus to the panel from wxListTextCtrl because the text control should + // disappear when the user clicks outside it. + + wxWindow *oldFocus = FindFocus(); + + if ( oldFocus && oldFocus->GetParent() == this ) + { + wxWindow::SetFocus(); + } + else + { + wxScrolledWindow::SetFocus(); + } +} void wxListMainWindow::OnSetFocus( wxFocusEvent &WXUNUSED(event) ) { @@ -3411,10 +3442,6 @@ void wxListMainWindow::OnSetFocus( wxFocusEvent &WXUNUSED(event) ) if ( !GetParent() ) return; -#ifdef __WXGTK__ - g_focusWindow = GetParent(); -#endif - wxFocusEvent event( wxEVT_SET_FOCUS, GetParent()->GetId() ); event.SetEventObject( GetParent() ); GetParent()->GetEventHandler()->ProcessEvent( event ); @@ -3888,10 +3915,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 +3963,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 +3995,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 +4006,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 +4015,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. } } @@ -4349,10 +4409,8 @@ void wxListMainWindow::OnScroll(wxScrollWinEvent& event) wxListCtrl* lc = GetListCtrl(); wxCHECK_RET( lc, _T("no listctrl window?") ); - lc->m_headerWin->Refresh() ; -#ifdef __WXMAC__ - lc->m_headerWin->MacUpdateImmediately() ; -#endif + lc->m_headerWin->Refresh(); + lc->m_headerWin->Update(); } } @@ -4443,53 +4501,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 +4508,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)