X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/a756f210019dd5b51331b7181c816d3882146a30..6cc687bfee071b5328f9e48d1708795287006bb7:/src/generic/listctrl.cpp diff --git a/src/generic/listctrl.cpp b/src/generic/listctrl.cpp index f61435dac0..3b9727dd86 100644 --- a/src/generic/listctrl.cpp +++ b/src/generic/listctrl.cpp @@ -50,7 +50,7 @@ #include "wx/imaglist.h" #include "wx/listctrl.h" -#ifdef __WXGTK__ +#if defined(__WXGTK__) #include #include "wx/gtk/win_gtk.h" #endif @@ -124,7 +124,7 @@ static const int IMAGE_MARGIN_IN_REPORT_MODE = 5; int CMPFUNC_CONV wxSizeTCmpFn(size_t n1, size_t n2) { return n1 - n2; } -WX_DEFINE_SORTED_EXPORTED_ARRAY(size_t, wxIndexArray); +WX_DEFINE_SORTED_EXPORTED_ARRAY_LONG(size_t, wxIndexArray); // this class is used to store the selected items in the virtual list control // (but it is not tied to list control and so can be used with other controls @@ -435,7 +435,7 @@ protected: wxCursor *m_resizeCursor; bool m_isDragging; - // column being resized + // column being resized or -1 int m_column; // divider line position in logical (unscrolled) coords @@ -473,6 +473,8 @@ private: // common part of all ctors void Init(); + void SendListEvent(wxEventType type, wxPoint pos); + DECLARE_DYNAMIC_CLASS(wxListHeaderWindow) DECLARE_EVENT_TABLE() }; @@ -518,7 +520,7 @@ public: void OnKillFocus( wxFocusEvent &event ); private: - DECLARE_DYNAMIC_CLASS(wxListTextCtrl); + DECLARE_DYNAMIC_CLASS(wxListTextCtrl) DECLARE_EVENT_TABLE() }; @@ -627,6 +629,8 @@ public: void Freeze(); void Thaw(); + void SetFocus(); + void OnRenameTimer(); void OnRenameAccept(); @@ -857,7 +861,7 @@ private: // if this is > 0, the control is frozen and doesn't redraw itself size_t m_freezeCount; - DECLARE_DYNAMIC_CLASS(wxListMainWindow); + DECLARE_DYNAMIC_CLASS(wxListMainWindow) DECLARE_EVENT_TABLE() }; @@ -1749,7 +1753,7 @@ void wxListLineData::ReverseHighlight( void ) // wxListHeaderWindow //----------------------------------------------------------------------------- -IMPLEMENT_DYNAMIC_CLASS(wxListHeaderWindow,wxWindow); +IMPLEMENT_DYNAMIC_CLASS(wxListHeaderWindow,wxWindow) BEGIN_EVENT_TABLE(wxListHeaderWindow,wxWindow) EVT_PAINT (wxListHeaderWindow::OnPaint) @@ -1796,7 +1800,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; @@ -1804,7 +1808,8 @@ 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; @@ -1865,7 +1870,7 @@ void wxListHeaderWindow::AdjustDC(wxDC& dc) void wxListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) { -#ifdef __WXGTK__ +#if defined(__WXGTK__) wxClientDC dc( this ); #else wxPaintDC dc( this ); @@ -1949,9 +1954,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 ); @@ -1980,6 +1985,9 @@ void wxListHeaderWindow::OnMouse( wxMouseEvent &event ) if (m_isDragging) { + SendListEvent(wxEVT_COMMAND_LIST_COL_DRAGGING, + event.GetPosition()); + // we don't draw the line beyond our window, but we allow dragging it // there int w = 0; @@ -1997,6 +2005,8 @@ void wxListHeaderWindow::OnMouse( wxMouseEvent &event ) m_isDragging = FALSE; m_dirty = TRUE; m_owner->SetColumnWidth( m_column, m_currentX - m_minX ); + SendListEvent(wxEVT_COMMAND_LIST_COL_END_DRAG, + event.GetPosition()); } else { @@ -2019,8 +2029,9 @@ void wxListHeaderWindow::OnMouse( wxMouseEvent &event ) int xpos = 0; // find the column where this event occured - int countCol = m_owner->GetColumnCount(); - for (int col = 0; col < countCol; col++) + int col, + countCol = m_owner->GetColumnCount(); + for (col = 0; col < countCol; col++) { xpos += m_owner->GetColumnWidth( col ); m_column = col; @@ -2041,6 +2052,9 @@ void wxListHeaderWindow::OnMouse( wxMouseEvent &event ) m_minX = xpos; } + if ( col == countCol ) + m_column = -1; + if (event.LeftDown() || event.RightUp()) { if (hit_border && event.LeftDown()) @@ -2049,25 +2063,15 @@ void wxListHeaderWindow::OnMouse( wxMouseEvent &event ) m_currentX = x; DrawCurrent(); CaptureMouse(); + SendListEvent(wxEVT_COMMAND_LIST_COL_BEGIN_DRAG, + event.GetPosition()); } else // click on a column { - wxWindow *parent = GetParent(); - wxListEvent le( event.LeftDown() + SendListEvent( event.LeftDown() ? wxEVT_COMMAND_LIST_COL_CLICK : wxEVT_COMMAND_LIST_COL_RIGHT_CLICK, - parent->GetId() ); - le.SetEventObject( parent ); - le.m_pointDrag = event.GetPosition(); - - // the position should be relative to the parent window, not - // this one for compatibility with MSW and common sense: the - // user code doesn't know anything at all about this header - // window, so why should it get positions relative to it? - le.m_pointDrag.y -= GetSize().y; - - le.m_col = m_column; - parent->GetEventHandler()->ProcessEvent( le ); + event.GetPosition()); } } else if (event.Moving()) @@ -2095,6 +2099,23 @@ void wxListHeaderWindow::OnSetFocus( wxFocusEvent &WXUNUSED(event) ) m_owner->SetFocus(); } +void wxListHeaderWindow::SendListEvent(wxEventType type, wxPoint pos) +{ + wxWindow *parent = GetParent(); + wxListEvent le( type, parent->GetId() ); + le.SetEventObject( parent ); + le.m_pointDrag = pos; + + // the position should be relative to the parent window, not + // this one for compatibility with MSW and common sense: the + // user code doesn't know anything at all about this header + // window, so why should it get positions relative to it? + le.m_pointDrag.y -= GetSize().y; + + le.m_col = m_column; + parent->GetEventHandler()->ProcessEvent( le ); +} + //----------------------------------------------------------------------------- // wxListRenameTimer (internal) //----------------------------------------------------------------------------- @@ -2113,7 +2134,7 @@ void wxListRenameTimer::Notify() // wxListTextCtrl (internal) //----------------------------------------------------------------------------- -IMPLEMENT_DYNAMIC_CLASS(wxListTextCtrl,wxTextCtrl); +IMPLEMENT_DYNAMIC_CLASS(wxListTextCtrl,wxTextCtrl) BEGIN_EVENT_TABLE(wxListTextCtrl,wxTextCtrl) EVT_CHAR (wxListTextCtrl::OnChar) @@ -2157,7 +2178,7 @@ void wxListTextCtrl::OnChar( wxKeyEvent &event ) m_owner->OnRenameAccept(); m_finished = TRUE; - m_owner->SetFocus(); // This doesn't work. TODO. + m_owner->SetFocus(); return; } @@ -2170,7 +2191,7 @@ void wxListTextCtrl::OnChar( wxKeyEvent &event ) wxPendingDelete.Append(this); m_finished = TRUE; - m_owner->SetFocus(); // This doesn't work. TODO. + m_owner->SetFocus(); return; } @@ -2191,7 +2212,7 @@ void wxListTextCtrl::OnKeyUp( wxKeyEvent &event ) wxPoint myPos = GetPosition(); wxSize mySize = GetSize(); int sx, sy; - GetTextExtent(GetValue() + _T("M"), &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) @@ -2214,7 +2235,7 @@ void wxListTextCtrl::OnKillFocus( wxFocusEvent &event ) (*m_accept) = TRUE; (*m_res) = GetValue(); - + if ((*m_res) != m_startValue) m_owner->OnRenameAccept(); } @@ -2223,7 +2244,7 @@ void wxListTextCtrl::OnKillFocus( wxFocusEvent &event ) // wxListMainWindow //----------------------------------------------------------------------------- -IMPLEMENT_DYNAMIC_CLASS(wxListMainWindow,wxScrolledWindow); +IMPLEMENT_DYNAMIC_CLASS(wxListMainWindow,wxScrolledWindow) BEGIN_EVENT_TABLE(wxListMainWindow,wxScrolledWindow) EVT_PAINT (wxListMainWindow::OnPaint) @@ -2471,7 +2492,10 @@ long wxListMainWindow::HitTestLine(size_t line, int x, int y) const if ( ld->HasImage() && GetLineIconRect(line).Inside(x, y) ) return wxLIST_HITTEST_ONITEMICON; - if ( ld->HasText() ) + // VS: Testing for "ld->HasText() || InReportView()" instead of + // "ld->HasText()" is needed to make empty lines in report view + // possible + if ( ld->HasText() || InReportView() ) { wxRect rect = InReportView() ? GetLineRect(line) : GetLineLabelRect(line); @@ -2659,14 +2683,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); @@ -2680,26 +2696,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() @@ -2935,14 +2931,10 @@ void wxListMainWindow::EditLabel( long item ) if (m_dirty) wxSafeYield(); - wxClientDC dc(this); - PrepareDC( dc ); - wxString s = data->GetText(0); wxRect rectLabel = GetLineLabelRect(m_currentEdit); - rectLabel.x = dc.LogicalToDeviceX( rectLabel.x ); - rectLabel.y = dc.LogicalToDeviceY( rectLabel.y ); + CalcScrolledPosition(rectLabel.x, rectLabel.y, &rectLabel.x, &rectLabel.y); wxListTextCtrl *text = new wxListTextCtrl ( @@ -3073,7 +3065,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 ); @@ -3423,9 +3423,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) ) { @@ -3443,10 +3459,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 ); @@ -3939,7 +3951,7 @@ void wxListMainWindow::RecalculatePositions(bool noRefresh) int clientWidth, clientHeight; GetSize( &clientWidth, &clientHeight ); - + if ( HasFlag(wxLC_REPORT) ) { // all lines have the same height @@ -3974,7 +3986,7 @@ void wxListMainWindow::RecalculatePositions(bool noRefresh) { // 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 @@ -3986,7 +3998,7 @@ void wxListMainWindow::RecalculatePositions(bool noRefresh) // 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; @@ -4020,11 +4032,11 @@ 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+SCROLL_UNIT_X > clientWidth) ) { clientHeight -= 15; // We guess the scrollbar height. (FIXME) @@ -4032,7 +4044,7 @@ void wxListMainWindow::RecalculatePositions(bool noRefresh) currentlyVisibleLines = 0; break; } - + if ( i == count - 1 ) tries = 1; // Everything fits, no second try required. } @@ -4168,6 +4180,9 @@ void wxListMainWindow::DeleteColumn( int col ) m_dirty = TRUE; m_columns.DeleteNode( node ); + + // invalidate it as it has to be recalculated + m_headerWidth = 0; } void wxListMainWindow::DoDeleteAllItems() @@ -4362,6 +4377,9 @@ void wxListMainWindow::InsertColumn( long col, wxListItem &item ) { m_columns.Append( column ); } + + // invalidate it as it has to be recalculated + m_headerWidth = 0; } } @@ -4414,10 +4432,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(); } }