// end any drag operation currently in progress (resizing or reordering)
void EndDragging();
- // and the resizing operation currently in progress and generate an event
- // about it with its cancelled flag set if width is -1
- void EndResizing(int width);
+ // start (if m_colBeingResized is -1) or continue resizing the column
+ //
+ // this generates wxEVT_COMMAND_HEADER_BEGIN_RESIZE/RESIZING events and can
+ // cancel the operation if the user handler decides so
+ void StartOrContinueResizing(unsigned int col, int xPhysical);
+
+ // end the resizing operation currently in progress and generate an event
+ // about it with its cancelled flag set if xPhysical is -1
+ void EndResizing(int xPhysical);
+
+ // constrain the given position to be larger than the start position of the
+ // given column plus its minimal width and return the effective width
+ int ConstrainByMinWidth(unsigned int col, int& xPhysical);
// update the current position of the resizing marker if xPhysical is a
// valid physical coordinate value or remove it entirely if it is -1
event.Veto();
}
- void OnResizing(wxHeaderCtrlEvent& event)
- {
- const wxHeaderColumnBase& col = GetColumn(event.GetColumn());
-
- const int minWidth = col.GetMinWidth();
- if ( event.GetWidth() < minWidth )
- event.Veto();
- }
-
void OnEndResize(wxHeaderCtrlEvent& event)
{
if ( !event.IsCancelled() )
EVT_HEADER_RIGHT_CLICK(wxID_ANY, wxDataViewHeaderWindow::OnRClick)
EVT_HEADER_BEGIN_RESIZE(wxID_ANY, wxDataViewHeaderWindow::OnBeginResize)
- EVT_HEADER_RESIZING(wxID_ANY, wxDataViewHeaderWindow::OnResizing)
EVT_HEADER_END_RESIZE(wxID_ANY, wxDataViewHeaderWindow::OnEndResize)
END_EVENT_TABLE()
SetCursor(wxNullCursor);
}
-void wxHeaderCtrl::EndResizing(int width)
+int wxHeaderCtrl::ConstrainByMinWidth(unsigned int col, int& xPhysical)
+{
+ const int xStart = GetColStart(col);
+
+ // notice that GetMinWidth() returns 0 if there is no minimal width so it
+ // still makes sense to use it even in this case
+ const int xMinEnd = xStart + GetColumn(col).GetMinWidth();
+
+ if ( xPhysical < xMinEnd )
+ xPhysical = xMinEnd;
+
+ return xPhysical - xStart;
+}
+
+void wxHeaderCtrl::StartOrContinueResizing(unsigned int col, int xPhysical)
+{
+ wxHeaderCtrlEvent event(IsResizing() ? wxEVT_COMMAND_HEADER_RESIZING
+ : wxEVT_COMMAND_HEADER_BEGIN_RESIZE,
+ GetId());
+ event.SetEventObject(this);
+ event.SetColumn(col);
+
+ event.SetWidth(ConstrainByMinWidth(col, xPhysical));
+
+ if ( GetEventHandler()->ProcessEvent(event) && !event.IsAllowed() )
+ {
+ if ( IsResizing() )
+ {
+ ReleaseMouse();
+ EndResizing(-1);
+ }
+ //else: nothing to do -- we just don't start to resize
+ }
+ else // go ahead with resizing
+ {
+ if ( !IsResizing() )
+ {
+ m_colBeingResized = col;
+ SetCursor(wxCursor(wxCURSOR_SIZEWE));
+ CaptureMouse();
+ }
+ //else: we had already done the above when we started
+
+ UpdateResizingMarker(xPhysical);
+ }
+}
+
+void wxHeaderCtrl::EndResizing(int xPhysical)
{
wxASSERT_MSG( IsResizing(), "shouldn't be called if we're not resizing" );
// if dragging was cancelled we must have already lost the mouse capture so
// don't try to release it
- if ( width != -1 )
+ if ( xPhysical != -1 )
ReleaseMouse();
wxHeaderCtrlEvent event(wxEVT_COMMAND_HEADER_END_RESIZE, GetId());
event.SetEventObject(this);
event.SetColumn(m_colBeingResized);
- if ( width == -1 )
+ if ( xPhysical == -1 )
event.SetCancelled();
else
- event.SetWidth(width);
+ event.SetWidth(ConstrainByMinWidth(m_colBeingResized, xPhysical));
GetEventHandler()->ProcessEvent(event);
if ( IsResizing() )
{
if ( mevent.LeftUp() )
- EndResizing(xPhysical - GetColStart(m_colBeingResized));
+ EndResizing(xPhysical);
else // update the live separator position
- UpdateResizingMarker(xPhysical);
+ StartOrContinueResizing(m_colBeingResized, xPhysical);
return;
}
if ( onSeparator )
{
// start resizing the column
- m_colBeingResized = col;
- SetCursor(wxCursor(wxCURSOR_SIZEWE));
- CaptureMouse();
- UpdateResizingMarker(xPhysical);
+ wxASSERT_MSG( !IsResizing(), "reentering resize mode?" );
+ StartOrContinueResizing(col, xPhysical);
}
else // on column itself
{
wxEventType evtType = wxEVT_NULL;
int idx = nmhdr->iItem;
int width = 0;
+ bool cancelled = false;
const UINT code = nmhdr->hdr.code;
switch ( code )
{
case HDN_ENDTRACKA:
case HDN_ENDTRACKW:
+ width = nmhdr->pitem->cxy;
+
if ( evtType == wxEVT_NULL )
+ {
evtType = wxEVT_COMMAND_HEADER_END_RESIZE;
- width = nmhdr->pitem->cxy;
+ // don't generate events with invalid width
+ const int minWidth = GetColumn(idx).GetMinWidth();
+ if ( width < minWidth )
+ width = minWidth;
+ }
+ break;
+
+ case HDN_ITEMCHANGING:
+ if ( nmhdr->pitem && (nmhdr->pitem->mask & HDI_WIDTH) )
+ {
+ // prevent the column from being shrunk beneath its min width
+ if ( nmhdr->pitem->cxy < GetColumn(idx).GetMinWidth() )
+ {
+ *result = TRUE;
+
+ return true;
+ }
+ }
+ break;
+
+ case NM_RELEASEDCAPTURE:
+ cancelled = true;
break;
}
event.SetEventObject(this);
event.SetColumn(idx);
event.SetWidth(width);
+ if ( cancelled )
+ event.SetCancelled();
if ( GetEventHandler()->ProcessEvent(event) )
{