]> git.saurik.com Git - wxWidgets.git/commitdiff
implement column resizing events in wxHeaderCtrl
authorVadim Zeitlin <vadim@wxwidgets.org>
Mon, 8 Dec 2008 14:40:42 +0000 (14:40 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Mon, 8 Dec 2008 14:40:42 +0000 (14:40 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@57190 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/generic/dataview.h
include/wx/generic/headerctrlg.h
include/wx/headerctrl.h
include/wx/msw/headerctrl.h
interface/wx/headerctrl.h
src/common/headerctrlcmn.cpp
src/generic/datavgen.cpp
src/generic/headerctrlg.cpp
src/msw/headerctrl.cpp

index 05ce149b3d2b7335b88dd94ed1cc6683a39ad661..953c2931427478ebdfa2376f7fc3eec5b47855f7 100644 (file)
@@ -359,11 +359,6 @@ private:
         m_sortAscending = true;
     }
 
         m_sortAscending = true;
     }
 
-    // like SetWidth() but does not ask the header window of the
-    // wxDataViewCtrl to reflect the width-change.
-    void SetInternalWidth(int width);
-
-
     wxString m_title;
     int m_width,
         m_minWidth;
     wxString m_title;
     int m_width,
         m_minWidth;
@@ -482,8 +477,11 @@ public:     // utility functions not part of the API
     // called by header window after reorder
     void ColumnMoved( wxDataViewColumn* col, unsigned int new_pos );
 
     // called by header window after reorder
     void ColumnMoved( wxDataViewColumn* col, unsigned int new_pos );
 
-    // updates the header window after a change in a column setting
-    void OnColumnChange();
+    // update the display after a change to an individual column
+    void OnColumnChange(unsigned int idx);
+
+    // update after a change to the number of columns
+    void OnColumnsCountChanged();
 
     wxWindow *GetMainWindow() { return (wxWindow*) m_clientArea; }
 
 
     wxWindow *GetMainWindow() { return (wxWindow*) m_clientArea; }
 
index 7c86e97730d2a9c50790789e56b5621bd6320a32..756d9c53cb1b957eb084f16367342a77b4d41e67 100644 (file)
@@ -13,6 +13,7 @@
 
 #include "wx/event.h"
 #include "wx/vector.h"
 
 #include "wx/event.h"
 #include "wx/vector.h"
+#include "wx/overlay.h"
 
 // ----------------------------------------------------------------------------
 // wxHeaderCtrl
 
 // ----------------------------------------------------------------------------
 // wxHeaderCtrl
@@ -64,6 +65,7 @@ private:
     // event handlers
     void OnPaint(wxPaintEvent& event);
     void OnMouse(wxMouseEvent& event);
     // event handlers
     void OnPaint(wxPaintEvent& event);
     void OnMouse(wxMouseEvent& event);
+    void OnCaptureLost(wxMouseCaptureLostEvent& event);
 
     // return the horizontal start position of the given column
     int GetColStart(unsigned int idx) const;
 
     // return the horizontal start position of the given column
     int GetColStart(unsigned int idx) const;
@@ -84,6 +86,17 @@ private:
     // column 1 but close enough to the divider separating it from column 0)
     int FindColumnAtPos(int x, bool& onSeparator) const;
 
     // column 1 but close enough to the divider separating it from column 0)
     int FindColumnAtPos(int x, bool& onSeparator) const;
 
+    // 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);
+
+    // update the current position of the resizing marker if xPhysical is a
+    // valid physical coordinate value or remove it entirely if it is -1
+    void UpdateResizingMarker(int xPhysical);
+
 
     // number of columns in the control currently
     unsigned int m_numColumns;
 
     // number of columns in the control currently
     unsigned int m_numColumns;
@@ -91,9 +104,16 @@ private:
     // index of the column under mouse or -1 if none
     unsigned int m_hover;
 
     // index of the column under mouse or -1 if none
     unsigned int m_hover;
 
+    // the column being resized or -1 if there is no resizing operation in
+    // progress
+    unsigned int m_colBeingResized;
+
     // the horizontal scroll offset
     int m_scrollOffset;
 
     // the horizontal scroll offset
     int m_scrollOffset;
 
+    // the overlay display used during the dragging operations
+    wxOverlay m_overlay;
+
 
     DECLARE_EVENT_TABLE()
     DECLARE_NO_COPY_CLASS(wxHeaderCtrl)
 
     DECLARE_EVENT_TABLE()
     DECLARE_NO_COPY_CLASS(wxHeaderCtrl)
index bf3a6632ba1837e6890ccf67bf2390a647fe8e48..51481efb67020999048219ac7c0f126d51d43869 100644 (file)
@@ -269,25 +269,45 @@ class WXDLLIMPEXP_CORE wxHeaderCtrlEvent : public wxNotifyEvent
 {
 public:
     wxHeaderCtrlEvent(wxEventType commandType = wxEVT_NULL, int winid = 0)
 {
 public:
     wxHeaderCtrlEvent(wxEventType commandType = wxEVT_NULL, int winid = 0)
-        : wxNotifyEvent(commandType, winid)
+        : wxNotifyEvent(commandType, winid),
+          m_col(-1),
+          m_width(0),
+          m_cancelled(false)
     {
     }
 
     wxHeaderCtrlEvent(const wxHeaderCtrlEvent& event)
         : wxNotifyEvent(event),
     {
     }
 
     wxHeaderCtrlEvent(const wxHeaderCtrlEvent& event)
         : wxNotifyEvent(event),
-          m_col(event.m_col)
+          m_col(event.m_col),
+          m_width(event.m_width),
+          m_cancelled(event.m_cancelled)
     {
     }
 
     {
     }
 
+    // the column which this event pertains to: valid for all header events
     int GetColumn() const { return m_col; }
     void SetColumn(int col) { m_col = col; }
 
     int GetColumn() const { return m_col; }
     void SetColumn(int col) { m_col = col; }
 
+    // the width of the column: valid for column resizing/dragging events only
+    int GetWidth() const { return m_width; }
+    void SetWidth(int width) { m_width = width; }
+
+    // was the drag operation cancelled or did it complete successfully?
+    bool IsCancelled() const { return m_cancelled; }
+    void SetCancelled() { m_cancelled = true; }
+
     virtual wxEvent *Clone() const { return new wxHeaderCtrlEvent(*this); }
 
 protected:
     // the column affected by the event
     int m_col;
 
     virtual wxEvent *Clone() const { return new wxHeaderCtrlEvent(*this); }
 
 protected:
     // the column affected by the event
     int m_col;
 
+    // the current width for the dragging events
+    int m_width;
+
+    // was the drag operation cancelled?
+    bool m_cancelled;
+
 private:
     DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxHeaderCtrlEvent)
 };
 private:
     DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxHeaderCtrlEvent)
 };
@@ -303,6 +323,10 @@ extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_HEADER_MIDDLE_DCLICK;
 
 extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_HEADER_SEPARATOR_DCLICK;
 
 
 extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_HEADER_SEPARATOR_DCLICK;
 
+extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_HEADER_BEGIN_DRAG;
+extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_HEADER_DRAGGING;
+extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_HEADER_END_DRAG;
+
 typedef void (wxEvtHandler::*wxHeaderCtrlEventFunction)(wxHeaderCtrlEvent&);
 
 #define wxHeaderCtrlEventHandler(func) \
 typedef void (wxEvtHandler::*wxHeaderCtrlEventFunction)(wxHeaderCtrlEvent&);
 
 #define wxHeaderCtrlEventHandler(func) \
@@ -322,4 +346,8 @@ typedef void (wxEvtHandler::*wxHeaderCtrlEventFunction)(wxHeaderCtrlEvent&);
 
 #define EVT_HEADER_SEPARATOR_DCLICK(id, fn) wx__DECLARE_HEADER_EVT(SEPARATOR_DCLICK, id, fn)
 
 
 #define EVT_HEADER_SEPARATOR_DCLICK(id, fn) wx__DECLARE_HEADER_EVT(SEPARATOR_DCLICK, id, fn)
 
+#define EVT_HEADER_BEGIN_DRAG(id, fn) wx__DECLARE_HEADER_EVT(BEGIN_DRAG, id, fn)
+#define EVT_HEADER_DRAGGING(id, fn) wx__DECLARE_HEADER_EVT(DRAGGING, id, fn)
+#define EVT_HEADER_END_DRAG(id, fn) wx__DECLARE_HEADER_EVT(END_DRAG, id, fn)
+
 #endif // _WX_HEADERCTRL_H_
 #endif // _WX_HEADERCTRL_H_
index 8a48ef0d56661d1d4ebc678a94ce9fc973a6dc8e..b0a3ae5c0b902fa39babfa23ebc92000b5f914e1 100644 (file)
@@ -71,13 +71,10 @@ private:
     enum Operation { Set, Insert };
     void DoSetOrInsertItem(Operation oper, unsigned int idx);
 
     enum Operation { Set, Insert };
     void DoSetOrInsertItem(Operation oper, unsigned int idx);
 
-    // send an event of the given type for the given column, return true if it
-    // was processed
-    bool SendEvent(wxEventType evtType, unsigned int idx);
-
-    // send a click or double click event (depending on dblclk value) for the
-    // click with the given button on the given item
-    bool SendClickEvent(bool dblclk, int button, unsigned int idx);
+    // get the event type corresponding to a click or double click event
+    // (depending on dblclk value) with the specified (using MSW convention)
+    // mouse button
+    wxEventType GetClickEventType(bool dblclk, int button);
 
 
     // the image list: initially NULL, created on demand
 
 
     // the image list: initially NULL, created on demand
index cca13106383d3444e2e7a5f05de9780a12dc130c..8bb10c924d2043ab6d260a2cd433b72e7d3c1be7 100644 (file)
             (this action is commonly used to resize the column to fit its
             contents width and the control provides UpdateColumnWidthToFit() method
             to make implementing this easier).
             (this action is commonly used to resize the column to fit its
             contents width and the control provides UpdateColumnWidthToFit() method
             to make implementing this easier).
+
+        @event{EVT_HEADER_BEGIN_DRAG(id, func)}
+            The user started to drag the column with the specified index (this
+            can only happen if wxHeaderColumn::IsResizeable() returned true for
+            this column). The event can be vetoed to prevent the control from
+            being resized, if it isn't, the dragging and end drag events will
+            be generated later.
+        @event{EVT_HEADER_DRAGGING(id, func)}
+            The user is dragging the column with the specified index and its
+            current width is wxHeaderCtrlEvent::GetWidth(). The event can be
+            vetoed to stop the dragging operation completely at any time.
+        @event{EVT_HEADER_END_DRAG(id, func)}
+            The user stopped dragging the column. If
+            wxHeaderCtrlEvent::IsCancelled() returns @true, nothing should
+            be done, otherwise the column should normally be resized to the
+            value of wxHeaderCtrlEvent::GetWidth().
     @endEventTable
 
     @library{wxcore}
     @endEventTable
 
     @library{wxcore}
@@ -389,6 +405,22 @@ class wxHeaderCtrlEvent : public wxNotifyEvent
 public:
     /**
         Return the index of the column affected by this event.
 public:
     /**
         Return the index of the column affected by this event.
+
+        This method can be called for all header control events.
      */
     int GetColumn() const;
      */
     int GetColumn() const;
+
+    /**
+        Return the current width of the column.
+
+        This method can only be called for the dragging events.
+     */
+    int GetWidth() const;
+
+    /**
+        Return @true if the drag operation was cancelled.
+
+        This method can only be called for the end drag event.
+     */
+    bool IsCancelled() const;
 };
 };
index a424e924d2a759630055011f2f31bad8a4a0feeb..f17c3f8d71092b264bb40ce9ec685f954da70236 100644 (file)
@@ -177,3 +177,7 @@ const wxEventType wxEVT_COMMAND_HEADER_RIGHT_DCLICK = wxNewEventType();
 const wxEventType wxEVT_COMMAND_HEADER_MIDDLE_DCLICK = wxNewEventType();
 
 const wxEventType wxEVT_COMMAND_HEADER_SEPARATOR_DCLICK = wxNewEventType();
 const wxEventType wxEVT_COMMAND_HEADER_MIDDLE_DCLICK = wxNewEventType();
 
 const wxEventType wxEVT_COMMAND_HEADER_SEPARATOR_DCLICK = wxNewEventType();
+
+const wxEventType wxEVT_COMMAND_HEADER_BEGIN_DRAG = wxNewEventType();
+const wxEventType wxEVT_COMMAND_HEADER_DRAGGING = wxNewEventType();
+const wxEventType wxEVT_COMMAND_HEADER_END_DRAG = wxNewEventType();
index 0fbcc1510c6f2e9656ff62c625ad984b4ac0766e..3091a3adcab44d1186181f32f980c584f4cd0d98 100644 (file)
@@ -102,6 +102,7 @@ protected:
 
         int widthContents = owner->GetBestColumnWidth(idx);
         owner->GetColumn(idx)->SetWidth(wxMax(widthTitle, widthContents));
 
         int widthContents = owner->GetBestColumnWidth(idx);
         owner->GetColumn(idx)->SetWidth(wxMax(widthTitle, widthContents));
+        owner->OnColumnChange(idx);
 
         return true;
     }
 
         return true;
     }
@@ -136,6 +137,28 @@ private:
             event.Skip();
     }
 
             event.Skip();
     }
 
+    void OnBeginDrag(wxHeaderCtrlEvent& event)
+    {
+        if ( !GetColumn(event.GetColumn()).IsResizeable() )
+            event.Veto();
+    }
+
+    void OnDragging(wxHeaderCtrlEvent& event)
+    {
+        const wxHeaderColumnBase& col = GetColumn(event.GetColumn());
+
+        const int minWidth = col.GetMinWidth();
+        if ( event.GetWidth() < minWidth )
+            event.Veto();
+    }
+
+    void OnEndDrag(wxHeaderCtrlEvent& event)
+    {
+        const unsigned col = event.GetColumn();
+        GetColumn(col).SetWidth(event.GetWidth());
+        GetOwner()->OnColumnChange(col);
+    }
+
     DECLARE_EVENT_TABLE()
     DECLARE_NO_COPY_CLASS(wxDataViewHeaderWindow)
 };
     DECLARE_EVENT_TABLE()
     DECLARE_NO_COPY_CLASS(wxDataViewHeaderWindow)
 };
@@ -143,6 +166,10 @@ private:
 BEGIN_EVENT_TABLE(wxDataViewHeaderWindow, wxHeaderCtrl)
     EVT_HEADER_CLICK(wxID_ANY, wxDataViewHeaderWindow::OnClick)
     EVT_HEADER_RIGHT_CLICK(wxID_ANY, wxDataViewHeaderWindow::OnRClick)
 BEGIN_EVENT_TABLE(wxDataViewHeaderWindow, wxHeaderCtrl)
     EVT_HEADER_CLICK(wxID_ANY, wxDataViewHeaderWindow::OnClick)
     EVT_HEADER_RIGHT_CLICK(wxID_ANY, wxDataViewHeaderWindow::OnRClick)
+
+    EVT_HEADER_BEGIN_DRAG(wxID_ANY, wxDataViewHeaderWindow::OnBeginDrag)
+    EVT_HEADER_DRAGGING(wxID_ANY, wxDataViewHeaderWindow::OnDragging)
+    EVT_HEADER_END_DRAG(wxID_ANY, wxDataViewHeaderWindow::OnEndDrag)
 END_EVENT_TABLE()
 
 //-----------------------------------------------------------------------------
 END_EVENT_TABLE()
 
 //-----------------------------------------------------------------------------
@@ -3288,7 +3315,7 @@ bool wxDataViewCtrl::AppendColumn( wxDataViewColumn *col )
         return false;
 
     m_cols.Append( col );
         return false;
 
     m_cols.Append( col );
-    OnColumnChange();
+    OnColumnsCountChanged();
     return true;
 }
 
     return true;
 }
 
@@ -3298,7 +3325,7 @@ bool wxDataViewCtrl::PrependColumn( wxDataViewColumn *col )
         return false;
 
     m_cols.Insert( col );
         return false;
 
     m_cols.Insert( col );
-    OnColumnChange();
+    OnColumnsCountChanged();
     return true;
 }
 
     return true;
 }
 
@@ -3308,11 +3335,19 @@ bool wxDataViewCtrl::InsertColumn( unsigned int pos, wxDataViewColumn *col )
         return false;
 
     m_cols.Insert( pos, col );
         return false;
 
     m_cols.Insert( pos, col );
-    OnColumnChange();
+    OnColumnsCountChanged();
     return true;
 }
 
     return true;
 }
 
-void wxDataViewCtrl::OnColumnChange()
+void wxDataViewCtrl::OnColumnChange(unsigned int idx)
+{
+    if ( m_headerArea )
+        m_headerArea->UpdateColumn(idx);
+
+    m_clientArea->UpdateDisplay();
+}
+
+void wxDataViewCtrl::OnColumnsCountChanged()
 {
     if (m_headerArea)
         m_headerArea->SetColumnCount(GetColumnCount());
 {
     if (m_headerArea)
         m_headerArea->SetColumnCount(GetColumnCount());
@@ -3335,20 +3370,9 @@ unsigned int wxDataViewCtrl::GetColumnCount() const
     return m_cols.GetCount();
 }
 
     return m_cols.GetCount();
 }
 
-wxDataViewColumn* wxDataViewCtrl::GetColumn( unsigned int pos ) const
+wxDataViewColumn* wxDataViewCtrl::GetColumn( unsigned int idx ) const
 {
 {
-    wxDataViewColumnList::const_iterator iter;
-    unsigned int i = 0;
-    for (iter = m_cols.begin(); iter!=m_cols.end(); iter++)
-    {
-        if (i == pos)
-            return *iter;
-
-        if ((*iter)->IsHidden())
-            continue;
-        i ++;
-    }
-    return NULL;
+    return m_cols[idx];
 }
 
 void wxDataViewCtrl::ColumnMoved( wxDataViewColumn* col, unsigned int new_pos )
 }
 
 void wxDataViewCtrl::ColumnMoved( wxDataViewColumn* col, unsigned int new_pos )
@@ -3371,7 +3395,7 @@ bool wxDataViewCtrl::DeleteColumn( wxDataViewColumn *column )
         return false;
 
     m_cols.Erase(ret);
         return false;
 
     m_cols.Erase(ret);
-    OnColumnChange();
+    OnColumnsCountChanged();
 
     return true;
 }
 
     return true;
 }
@@ -3379,7 +3403,7 @@ bool wxDataViewCtrl::DeleteColumn( wxDataViewColumn *column )
 bool wxDataViewCtrl::ClearColumns()
 {
     m_cols.Clear();
 bool wxDataViewCtrl::ClearColumns()
 {
     m_cols.Clear();
-    OnColumnChange();
+    OnColumnsCountChanged();
     return true;
 }
 
     return true;
 }
 
index 8d8adc9fc42c2a9bdae0ccdc98f82d47274c471a..be040a5ac6745d0083ff121854c30384102d428d 100644 (file)
@@ -57,7 +57,8 @@ const unsigned COL_NONE = (unsigned)-1;
 void wxHeaderCtrl::Init()
 {
     m_numColumns = 0;
 void wxHeaderCtrl::Init()
 {
     m_numColumns = 0;
-    m_hover = COL_NONE;
+    m_hover =
+    m_colBeingResized = COL_NONE;
     m_scrollOffset = 0;
 }
 
     m_scrollOffset = 0;
 }
 
@@ -209,6 +210,55 @@ void wxHeaderCtrl::RefreshColsAfter(unsigned int idx)
     RefreshRect(rect);
 }
 
     RefreshRect(rect);
 }
 
+// ----------------------------------------------------------------------------
+// wxHeaderCtrl dragging
+// ----------------------------------------------------------------------------
+
+void wxHeaderCtrl::UpdateResizingMarker(int xPhysical)
+{
+    // 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
+    wxClientDC dc(this);
+
+    wxDCOverlay dcover(m_overlay, &dc);
+    dcover.Clear();
+
+    if ( xPhysical != -1 )
+    {
+        dc.SetPen(*wxLIGHT_GREY_PEN);
+        dc.DrawLine(xPhysical, 0, xPhysical, GetClientSize().y);
+    }
+}
+
+void wxHeaderCtrl::EndDragging()
+{
+    UpdateResizingMarker(-1);
+
+    m_overlay.Reset();
+}
+
+void wxHeaderCtrl::EndResizing(int width)
+{
+    wxASSERT_MSG( m_colBeingResized != COL_NONE,
+                  "shouldn't be called if we're not resizing" );
+
+    EndDragging();
+
+    wxHeaderCtrlEvent event(wxEVT_COMMAND_HEADER_END_DRAG, GetId());
+    event.SetEventObject(this);
+    event.SetColumn(m_colBeingResized);
+    if ( width == -1 )
+        event.SetCancelled();
+    else
+        event.SetWidth(width);
+
+    GetEventHandler()->ProcessEvent(event);
+
+    m_colBeingResized = COL_NONE;
+}
+
 // ----------------------------------------------------------------------------
 // wxHeaderCtrl event handlers
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // wxHeaderCtrl event handlers
 // ----------------------------------------------------------------------------
@@ -217,6 +267,8 @@ BEGIN_EVENT_TABLE(wxHeaderCtrl, wxHeaderCtrlBase)
     EVT_PAINT(wxHeaderCtrl::OnPaint)
 
     EVT_MOUSE_EVENTS(wxHeaderCtrl::OnMouse)
     EVT_PAINT(wxHeaderCtrl::OnPaint)
 
     EVT_MOUSE_EVENTS(wxHeaderCtrl::OnMouse)
+
+    EVT_MOUSE_CAPTURE_LOST(wxHeaderCtrl::OnCaptureLost)
 END_EVENT_TABLE()
 
 void wxHeaderCtrl::OnPaint(wxPaintEvent& WXUNUSED(event))
 END_EVENT_TABLE()
 
 void wxHeaderCtrl::OnPaint(wxPaintEvent& WXUNUSED(event))
@@ -283,18 +335,42 @@ void wxHeaderCtrl::OnPaint(wxPaintEvent& WXUNUSED(event))
     }
 }
 
     }
 }
 
+void wxHeaderCtrl::OnCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(event))
+{
+    if ( m_colBeingResized != COL_NONE )
+        EndResizing(-1);
+}
+
 void wxHeaderCtrl::OnMouse(wxMouseEvent& mevent)
 {
 void wxHeaderCtrl::OnMouse(wxMouseEvent& mevent)
 {
+    // do this in advance to allow simply returning if we're not interested,
+    // we'll undo it if we do handle the event below
     mevent.Skip();
 
     mevent.Skip();
 
+
     // account for the control displacement
     // account for the control displacement
-    const int x = mevent.GetX() - m_scrollOffset;
+    const int xPhysical = mevent.GetX();
+    const int xLogical = xPhysical - m_scrollOffset;
+
+    // first deal with the [continuation of any] dragging operations in
+    // progress
+    if ( m_colBeingResized != COL_NONE )
+    {
+        if ( mevent.LeftUp() )
+            EndResizing(xLogical - GetColStart(m_colBeingResized));
+        else // update the live separator position
+            UpdateResizingMarker(xPhysical);
+
+        return;
+    }
+
 
     // find if the event is over a column at all
     bool onSeparator;
     const unsigned col = mevent.Leaving()
                             ? (onSeparator = false, COL_NONE)
 
     // find if the event is over a column at all
     bool onSeparator;
     const unsigned col = mevent.Leaving()
                             ? (onSeparator = false, COL_NONE)
-                            : FindColumnAtPos(x, onSeparator);
+                            : FindColumnAtPos(xLogical, onSeparator);
+
 
     // update the highlighted column if it changed
     if ( col != m_hover )
 
     // update the highlighted column if it changed
     if ( col != m_hover )
@@ -306,9 +382,6 @@ void wxHeaderCtrl::OnMouse(wxMouseEvent& mevent)
         RefreshColIfNotNone(m_hover);
     }
 
         RefreshColIfNotNone(m_hover);
     }
 
-    if ( col == COL_NONE )
-        return;
-
     // update mouse cursor as it moves around
     if ( mevent.Moving() )
     {
     // update mouse cursor as it moves around
     if ( mevent.Moving() )
     {
@@ -316,20 +389,30 @@ void wxHeaderCtrl::OnMouse(wxMouseEvent& mevent)
         return;
     }
 
         return;
     }
 
+    // all the other events only make sense when they happen over a column
+    if ( col == COL_NONE )
+        return;
+
+
+    // enter various dragging modes on left mouse press
     if ( mevent.LeftDown() )
     {
     if ( mevent.LeftDown() )
     {
-        // TODO
         if ( onSeparator )
         if ( onSeparator )
-            // resize column
-            ;
-        else
-            // drag column
+        {
+            // start resizing the column
+            m_colBeingResized = col;
+            UpdateResizingMarker(xPhysical);
+        }
+        else // on column itself
+        {
+            // TODO: drag column
             ;
             ;
+        }
 
         return;
     }
 
 
         return;
     }
 
-    // determine the type of header event corresponding to this mouse event
+    // determine the type of header event corresponding to click events
     wxEventType evtType = wxEVT_NULL;
     const bool click = mevent.ButtonUp(),
                dblclk = mevent.ButtonDClick();
     wxEventType evtType = wxEVT_NULL;
     const bool click = mevent.ButtonUp(),
                dblclk = mevent.ButtonDClick();
index 8df0e8286cc0dac891205cfcb858bfd3d103a667..e60b1bbc1bd9d50f427471d66b6566f9787460d6 100644 (file)
@@ -260,16 +260,7 @@ void wxHeaderCtrl::DoSetOrInsertItem(Operation oper, unsigned int idx)
 // wxHeaderCtrl events
 // ----------------------------------------------------------------------------
 
 // wxHeaderCtrl events
 // ----------------------------------------------------------------------------
 
-bool wxHeaderCtrl::SendEvent(wxEventType evtType, unsigned int idx)
-{
-    wxHeaderCtrlEvent event(evtType, GetId());
-    event.SetEventObject(this);
-    event.SetColumn(idx);
-
-    return GetEventHandler()->ProcessEvent(event);
-}
-
-bool wxHeaderCtrl::SendClickEvent(bool dblclk, int button, unsigned int idx)
+wxEventType wxHeaderCtrl::GetClickEventType(bool dblclk, int button)
 {
     wxEventType evtType;
     switch ( button )
 {
     wxEventType evtType;
     switch ( button )
@@ -291,23 +282,27 @@ bool wxHeaderCtrl::SendClickEvent(bool dblclk, int button, unsigned int idx)
 
         default:
             wxFAIL_MSG( wxS("unexpected event type") );
 
         default:
             wxFAIL_MSG( wxS("unexpected event type") );
-            return false;
+            evtType = wxEVT_NULL;
     }
 
     }
 
-    return SendEvent(evtType, idx);
+    return evtType;
 }
 
 bool wxHeaderCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
 {
     NMHEADER * const nmhdr = (NMHEADER *)lParam;
 
 }
 
 bool wxHeaderCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
 {
     NMHEADER * const nmhdr = (NMHEADER *)lParam;
 
-    const int idx = nmhdr->iItem;
+    wxEventType evtType = wxEVT_NULL;
+    int idx = nmhdr->iItem;
+    int width = 0;
     switch ( const UINT code = nmhdr->hdr.code )
     {
     switch ( const UINT code = nmhdr->hdr.code )
     {
+        // click events
+        // ------------
+
         case HDN_ITEMCLICK:
         case HDN_ITEMDBLCLICK:
         case HDN_ITEMCLICK:
         case HDN_ITEMDBLCLICK:
-            if ( SendClickEvent(code == HDN_ITEMDBLCLICK, nmhdr->iButton, idx) )
-                return true;
+            evtType = GetClickEventType(code == HDN_ITEMDBLCLICK, nmhdr->iButton);
             break;
 
             // although we should get the notifications about the right clicks
             break;
 
             // although we should get the notifications about the right clicks
@@ -317,22 +312,66 @@ bool wxHeaderCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
         case NM_RDBLCLK:
             {
                 POINT pt;
         case NM_RDBLCLK:
             {
                 POINT pt;
-                const int col = wxMSWGetColumnClicked(&nmhdr->hdr, &pt);
-                if ( col != wxNOT_FOUND )
-                {
-                    if ( SendClickEvent(code == NM_RDBLCLK, 1, col) )
-                        return true;
-                }
+                idx = wxMSWGetColumnClicked(&nmhdr->hdr, &pt);
+                if ( idx != wxNOT_FOUND )
+                    evtType = GetClickEventType(code == NM_RDBLCLK, 1);
                 //else: ignore clicks outside any column
             }
             break;
 
         case HDN_DIVIDERDBLCLICK:
                 //else: ignore clicks outside any column
             }
             break;
 
         case HDN_DIVIDERDBLCLICK:
-            if ( SendEvent(wxEVT_COMMAND_HEADER_SEPARATOR_DCLICK, idx) )
-                return true;
+            evtType = wxEVT_COMMAND_HEADER_SEPARATOR_DCLICK;
+            break;
+
+
+        // column resizing events
+        // ----------------------
+
+        // see comments in wxListCtrl::MSWOnNotify() for why we catch both
+        // ASCII and Unicode versions of this message
+        case HDN_BEGINTRACKA:
+        case HDN_BEGINTRACKW:
+            evtType = wxEVT_COMMAND_HEADER_BEGIN_DRAG;
+            // fall through
+
+        case HDN_TRACKA:
+        case HDN_TRACKW:
+            if ( evtType == wxEVT_NULL )
+                evtType = wxEVT_COMMAND_HEADER_DRAGGING;
+            // fall through
+
+        case HDN_ENDTRACKA:
+        case HDN_ENDTRACKW:
+            if ( evtType == wxEVT_NULL )
+                evtType = wxEVT_COMMAND_HEADER_END_DRAG;
+
+            width = nmhdr->pitem->cxy;
             break;
     }
 
             break;
     }
 
+
+    // do generate the corresponding wx event
+    if ( evtType != wxEVT_NULL )
+    {
+        wxHeaderCtrlEvent event(evtType, GetId());
+        event.SetEventObject(this);
+        event.SetColumn(idx);
+        event.SetWidth(width);
+
+        if ( GetEventHandler()->ProcessEvent(event) )
+        {
+            if ( !event.IsAllowed() )
+            {
+                // all of HDN_BEGIN{DRAG,TRACK}, HDN_TRACK and HDN_ITEMCHANGING
+                // interpret TRUE return value as meaning to stop the control
+                // default handling of the message
+                *result = TRUE;
+            }
+
+            return true;
+        }
+    }
+
     return wxHeaderCtrlBase::MSWOnNotify(idCtrl, lParam, result);
 }
 
     return wxHeaderCtrlBase::MSWOnNotify(idCtrl, lParam, result);
 }