X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/6327cdd57cd324afc284c4ef04a1a8eb6eab6e55..6f026b5b63fe7ccb025e84509886f74772b9df13:/src/generic/headerctrlg.cpp diff --git a/src/generic/headerctrlg.cpp b/src/generic/headerctrlg.cpp index e7e4333c5f..6dcccfdce8 100644 --- a/src/generic/headerctrlg.cpp +++ b/src/generic/headerctrlg.cpp @@ -3,7 +3,6 @@ // Purpose: generic wxHeaderCtrl implementation // Author: Vadim Zeitlin // Created: 2008-12-03 -// RCS-ID: $Id$ // Copyright: (c) 2008 Vadim Zeitlin // Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// @@ -23,8 +22,7 @@ #pragma hdrstop #endif -#ifndef WX_PRECOMP -#endif // WX_PRECOMP +#if wxUSE_HEADERCTRL #include "wx/headerctrl.h" @@ -40,8 +38,6 @@ namespace { -const unsigned NO_SORT = (unsigned)-1; - const unsigned COL_NONE = (unsigned)-1; } // anonymous namespace @@ -92,32 +88,12 @@ wxHeaderCtrl::~wxHeaderCtrl() void wxHeaderCtrl::DoSetCount(unsigned int count) { - // update the column indices array if necessary - if ( count > m_numColumns ) - { - // all new columns have default positions equal to their indices - for ( unsigned n = m_numColumns; n < count; n++ ) - m_colIndices.push_back(n); - } - else if ( count < m_numColumns ) - { - // filter out all the positions which are invalid now while keeping the - // order of the remaining ones - wxArrayInt colIndices; - for ( unsigned n = 0; n < m_numColumns; n++ ) - { - const unsigned idx = m_colIndices[n]; - if ( idx < count ) - colIndices.push_back(idx); - } - - wxASSERT_MSG( colIndices.size() == count, "logic error" ); - - m_colIndices = colIndices; - } + // update the column indices order array before changing m_numColumns + DoResizeColumnIndices(m_colIndices, count); m_numColumns = count; + InvalidateBestSize(); Refresh(); } @@ -128,6 +104,8 @@ unsigned int wxHeaderCtrl::DoGetCount() const void wxHeaderCtrl::DoUpdate(unsigned int idx) { + InvalidateBestSize(); + // we need to refresh not only this column but also the ones after it in // case it was shown or hidden or its width changed -- it would be nice to // avoid doing this unnecessary by storing the old column width (TODO) @@ -152,17 +130,20 @@ void wxHeaderCtrl::DoScrollHorz(int dx) wxSize wxHeaderCtrl::DoGetBestSize() const { + wxWindow *win = GetParent(); + int height = wxRendererNative::Get().GetHeaderButtonHeight( win ); + // the vertical size is rather arbitrary but it looks better if we leave // some space around the text - return wxSize(IsEmpty() ? DEFAULT_ITEM_WIDTH - : GetColEnd(GetColumnCount() - 1), - (7*GetCharHeight())/4); + const wxSize size(IsEmpty() ? wxHeaderCtrlBase::DoGetBestSize().x + : GetColEnd(GetColumnCount() - 1), + height ); // (7*GetCharHeight())/4); + CacheBestSize(size); + return size; } int wxHeaderCtrl::GetColStart(unsigned int idx) const { - wxHeaderCtrl * const self = const_cast(this); - int pos = m_scrollOffset; for ( unsigned n = 0; ; n++ ) { @@ -170,7 +151,7 @@ int wxHeaderCtrl::GetColStart(unsigned int idx) const if ( i == idx ) break; - const wxHeaderColumnBase& col = self->GetColumn(i); + const wxHeaderColumn& col = GetColumn(i); if ( col.IsShown() ) pos += col.GetWidth(); } @@ -182,25 +163,23 @@ int wxHeaderCtrl::GetColEnd(unsigned int idx) const { int x = GetColStart(idx); - return x + const_cast(this)->GetColumn(idx).GetWidth(); + return x + GetColumn(idx).GetWidth(); } unsigned int wxHeaderCtrl::FindColumnAtPoint(int x, bool *onSeparator) const { - wxHeaderCtrl * const self = const_cast(this); - int pos = 0; const unsigned count = GetColumnCount(); for ( unsigned n = 0; n < count; n++ ) { const unsigned idx = m_colIndices[n]; - const wxHeaderColumnBase& col = self->GetColumn(idx); + const wxHeaderColumn& col = GetColumn(idx); if ( col.IsHidden() ) continue; pos += col.GetWidth(); - // if the column is resizeable, check if we're approximatively over the + // if the column is resizable, check if we're approximatively over the // line separating it from the next column // // TODO: don't hardcode sensitivity @@ -220,6 +199,8 @@ unsigned int wxHeaderCtrl::FindColumnAtPoint(int x, bool *onSeparator) const } } + if ( onSeparator ) + *onSeparator = false; return COL_NONE; } @@ -274,26 +255,14 @@ void wxHeaderCtrl::ClearMarkers() dcover.Clear(); } -void wxHeaderCtrl::UpdateResizingMarker(int xPhysical) -{ - wxClientDC dc(this); - - wxDCOverlay dcover(m_overlay, &dc); - dcover.Clear(); - - // unfortunately drawing the marker over the parent window doesn't work as - // it's usually covered by another window (the main control view) so just - // draw the marker over the header itself, even if it makes it not very - // useful - dc.SetPen(*wxLIGHT_GREY_PEN); - dc.DrawLine(xPhysical, 0, xPhysical, GetClientSize().y); -} - void wxHeaderCtrl::EndDragging() { - ClearMarkers(); - - m_overlay.Reset(); + // We currently only use markers for reordering, not for resizing + if (IsReordering()) + { + ClearMarkers(); + m_overlay.Reset(); + } // don't use the special dragging cursor any more SetCursor(wxNullCursor); @@ -308,7 +277,7 @@ void wxHeaderCtrl::CancelDragging() unsigned int& col = IsResizing() ? m_colBeingResized : m_colBeingReordered; - wxHeaderCtrlEvent event(wxEVT_COMMAND_HEADER_DRAGGING_CANCELLED, GetId()); + wxHeaderCtrlEvent event(wxEVT_HEADER_DRAGGING_CANCELLED, GetId()); event.SetEventObject(this); event.SetColumn(col); @@ -333,8 +302,8 @@ int wxHeaderCtrl::ConstrainByMinWidth(unsigned int col, int& xPhysical) void wxHeaderCtrl::StartOrContinueResizing(unsigned int col, int xPhysical) { - wxHeaderCtrlEvent event(IsResizing() ? wxEVT_COMMAND_HEADER_RESIZING - : wxEVT_COMMAND_HEADER_BEGIN_RESIZE, + wxHeaderCtrlEvent event(IsResizing() ? wxEVT_HEADER_RESIZING + : wxEVT_HEADER_BEGIN_RESIZE, GetId()); event.SetEventObject(this); event.SetColumn(col); @@ -360,7 +329,6 @@ void wxHeaderCtrl::StartOrContinueResizing(unsigned int col, int xPhysical) } //else: we had already done the above when we started - UpdateResizingMarker(xPhysical); } } @@ -372,7 +340,7 @@ void wxHeaderCtrl::EndResizing(int xPhysical) ReleaseMouse(); - wxHeaderCtrlEvent event(wxEVT_COMMAND_HEADER_END_RESIZE, GetId()); + wxHeaderCtrlEvent event(wxEVT_HEADER_END_RESIZE, GetId()); event.SetEventObject(this); event.SetColumn(m_colBeingResized); event.SetWidth(ConstrainByMinWidth(m_colBeingResized, xPhysical)); @@ -413,7 +381,7 @@ void wxHeaderCtrl::UpdateReorderingMarker(int xPhysical) void wxHeaderCtrl::StartReordering(unsigned int col, int xPhysical) { - wxHeaderCtrlEvent event(wxEVT_COMMAND_HEADER_BEGIN_REORDER, GetId()); + wxHeaderCtrlEvent event(wxEVT_HEADER_BEGIN_REORDER, GetId()); event.SetEventObject(this); event.SetColumn(col); @@ -429,10 +397,12 @@ void wxHeaderCtrl::StartReordering(unsigned int col, int xPhysical) SetCursor(wxCursor(wxCURSOR_HAND)); CaptureMouse(); - UpdateReorderingMarker(xPhysical); + // do not call UpdateReorderingMarker() here: we don't want to give + // feedback for reordering until the user starts to really move the mouse + // as he might want to just click on the column and not move it at all } -void wxHeaderCtrl::EndReordering(int xPhysical) +bool wxHeaderCtrl::EndReordering(int xPhysical) { wxASSERT_MSG( IsReordering(), "shouldn't be called if we're not reordering" ); @@ -440,20 +410,33 @@ void wxHeaderCtrl::EndReordering(int xPhysical) ReleaseMouse(); - wxHeaderCtrlEvent event(wxEVT_COMMAND_HEADER_END_REORDER, GetId()); - event.SetEventObject(this); - event.SetColumn(m_colBeingReordered); + const int colOld = m_colBeingReordered, + colNew = FindColumnAtPoint(xPhysical); - const unsigned pos = GetColumnPos(FindColumnAtPoint(xPhysical)); - event.SetNewOrder(pos); + m_colBeingReordered = COL_NONE; - if ( !GetEventHandler()->ProcessEvent(event) || event.IsAllowed() ) + if ( xPhysical - GetColStart(colOld) == m_dragOffset ) + return false; + + if ( colNew != colOld ) { - // do reorder the columns - DoMoveCol(m_colBeingReordered, pos); + wxHeaderCtrlEvent event(wxEVT_HEADER_END_REORDER, GetId()); + event.SetEventObject(this); + event.SetColumn(colOld); + + const unsigned pos = GetColumnPos(FindColumnAtPoint(xPhysical)); + event.SetNewOrder(pos); + + if ( !GetEventHandler()->ProcessEvent(event) || event.IsAllowed() ) + { + // do reorder the columns + DoMoveCol(colOld, pos); + } } - m_colBeingReordered = COL_NONE; + // whether we moved the column or not, the user did move the mouse and so + // did try to do it so return true + return true; } // ---------------------------------------------------------------------------- @@ -473,28 +456,7 @@ wxArrayInt wxHeaderCtrl::DoGetColumnsOrder() const void wxHeaderCtrl::DoMoveCol(unsigned int idx, unsigned int pos) { - const unsigned count = m_colIndices.size(); - - wxArrayInt colIndices; - colIndices.reserve(count); - for ( unsigned n = 0; n < count; n++ ) - { - // NB: order of checks is important for this to work when the new - // column position is the same as the old one - - // insert the column at its new position - if ( colIndices.size() == pos ) - colIndices.push_back(idx); - - // delete the column from its old position - const unsigned idxOld = m_colIndices[n]; - if ( idxOld == idx ) - continue; - - colIndices.push_back(idxOld); - } - - m_colIndices = colIndices; + MoveColumnInOrderArray(m_colIndices, idx, pos); Refresh(); } @@ -518,6 +480,11 @@ void wxHeaderCtrl::OnPaint(wxPaintEvent& WXUNUSED(event)) int w, h; GetClientSize(&w, &h); +#ifdef __WXGTK__ +// int vw; +// GetVirtualSize(&vw, NULL); +#endif + wxAutoBufferedPaintDC dc(this); dc.SetBackground(GetBackgroundColour()); @@ -531,11 +498,11 @@ void wxHeaderCtrl::OnPaint(wxPaintEvent& WXUNUSED(event)) for ( unsigned int i = 0; i < count; i++ ) { const unsigned idx = m_colIndices[i]; - const wxHeaderColumnBase& col = GetColumn(idx); + const wxHeaderColumn& col = GetColumn(idx); if ( col.IsHidden() ) continue; - const int colWidth = col.GetWidth(); + int colWidth = col.GetWidth(); wxHeaderSortIconType sortArrow; if ( col.IsSortKey() ) @@ -559,11 +526,22 @@ void wxHeaderCtrl::OnPaint(wxPaintEvent& WXUNUSED(event)) state = wxCONTROL_DISABLED; } + if (i == 0) + state |= wxCONTROL_SPECIAL; + wxHeaderButtonParams params; params.m_labelText = col.GetTitle(); params.m_labelBitmap = col.GetBitmap(); params.m_labelAlignment = col.GetAlignment(); +#ifdef __WXGTK__ + if (i == count-1) + { +// colWidth = wxMax( colWidth, vw - xpos ); + state |= wxCONTROL_DIRTY; + } +#endif + wxRendererNative::Get().DrawHeaderButton ( this, @@ -625,12 +603,18 @@ void wxHeaderCtrl::OnMouse(wxMouseEvent& mevent) if ( IsReordering() ) { - if ( mevent.LeftUp() ) - EndReordering(xPhysical); - else // update the column position + if ( !mevent.LeftUp() ) + { + // update the column position UpdateReorderingMarker(xPhysical); - return; + return; + } + + // finish reordering and continue to generate a click event below if we + // didn't really reorder anything + if ( EndReordering(xPhysical) ) + return; } @@ -695,23 +679,23 @@ void wxHeaderCtrl::OnMouse(wxMouseEvent& mevent) // treat left double clicks on separator specially if ( onSeparator && dblclk ) { - evtType = wxEVT_COMMAND_HEADER_SEPARATOR_DCLICK; + evtType = wxEVT_HEADER_SEPARATOR_DCLICK; } else // not double click on separator { - evtType = click ? wxEVT_COMMAND_HEADER_CLICK - : wxEVT_COMMAND_HEADER_DCLICK; + evtType = click ? wxEVT_HEADER_CLICK + : wxEVT_HEADER_DCLICK; } break; case wxMOUSE_BTN_RIGHT: - evtType = click ? wxEVT_COMMAND_HEADER_RIGHT_CLICK - : wxEVT_COMMAND_HEADER_RIGHT_DCLICK; + evtType = click ? wxEVT_HEADER_RIGHT_CLICK + : wxEVT_HEADER_RIGHT_DCLICK; break; case wxMOUSE_BTN_MIDDLE: - evtType = click ? wxEVT_COMMAND_HEADER_MIDDLE_CLICK - : wxEVT_COMMAND_HEADER_MIDDLE_DCLICK; + evtType = click ? wxEVT_HEADER_MIDDLE_CLICK + : wxEVT_HEADER_MIDDLE_DCLICK; break; default: @@ -732,3 +716,5 @@ void wxHeaderCtrl::OnMouse(wxMouseEvent& mevent) } #endif // wxHAS_GENERIC_HEADERCTRL + +#endif // wxUSE_HEADERCTRL