// refresh all the controls starting from (and including) the given one
void RefreshColsAfter(unsigned int idx);
+ // return the column at the given position or -1 if it is beyond the
+ // rightmost column and put true into onSeparator output parameter if the
+ // position is near the divider at the right end of this column (notice
+ // that this means that we return column 0 even if the position is over
+ // column 1 but close enough to the divider separating it from column 0)
+ int FindColumnAtPos(int x, bool& onSeparator) const;
+
+
// number of columns in the control currently
unsigned int m_numColumns;
// control, see wxHeaderCtrlSimple for a standalone version
// ----------------------------------------------------------------------------
-#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
+#if 0// defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
#include "wx/msw/headerctrl.h"
#else
#define wxHAS_GENERIC_HEADERCTRL
DECLARE_NO_COPY_CLASS(wxHeaderCtrlSimple)
};
+// ----------------------------------------------------------------------------
+// wxHeaderCtrl events
+// ----------------------------------------------------------------------------
+
+class WXDLLIMPEXP_CORE wxHeaderCtrlEvent : public wxNotifyEvent
+{
+public:
+ wxHeaderCtrlEvent(wxEventType commandType = wxEVT_NULL, int winid = 0)
+ : wxNotifyEvent(commandType, winid)
+ {
+ }
+
+ wxHeaderCtrlEvent(const wxHeaderCtrlEvent& event)
+ : wxNotifyEvent(event),
+ m_col(event.m_col)
+ {
+ }
+
+ int GetColumn() const { return m_col; }
+ void SetColumn(int col) { m_col = col; }
+
+ virtual wxEvent *Clone() const { return new wxHeaderCtrlEvent(*this); }
+
+protected:
+ // the column affected by the event
+ int m_col;
+
+private:
+ DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxHeaderCtrlEvent)
+};
+
+
+extern WXDLLIMPEXP_ADV const wxEventType wxEVT_COMMAND_HEADER_CLICK;
+extern WXDLLIMPEXP_ADV const wxEventType wxEVT_COMMAND_HEADER_RIGHT_CLICK;
+extern WXDLLIMPEXP_ADV const wxEventType wxEVT_COMMAND_HEADER_MIDDLE_CLICK;
+
+extern WXDLLIMPEXP_ADV const wxEventType wxEVT_COMMAND_HEADER_DCLICK;
+extern WXDLLIMPEXP_ADV const wxEventType wxEVT_COMMAND_HEADER_RIGHT_DCLICK;
+extern WXDLLIMPEXP_ADV const wxEventType wxEVT_COMMAND_HEADER_MIDDLE_DCLICK;
+
+typedef void (wxEvtHandler::*wxHeaderCtrlEventFunction)(wxHeaderCtrlEvent&);
+
+#define wxHeaderCtrlEventHandler(func) \
+ (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent( \
+ wxHeaderCtrlEventFunction, &func)
+
+#define wx__DECLARE_HEADER_EVT(evt, id, fn) \
+ wx__DECLARE_EVT1(wxEVT_COMMAND_HEADER_ ## evt, id, wxHeaderCtrlEventHandler(fn))
+
+#define EVT_HEADER_CLICK(id, fn) wx__DECLARE_HEADER_EVT(CLICK, id, fn)
+#define EVT_HEADER_RIGHT_CLICK(id, fn) wx__DECLARE_HEADER_EVT(RIGHT_CLICK, id, fn)
+#define EVT_HEADER_MIDDLE_CLICK(id, fn) wx__DECLARE_HEADER_EVT(MIDDLE_CLICK, id, fn)
+
+#define EVT_HEADER_DCLICK(id, fn) wx__DECLARE_HEADER_EVT(DCLICK, id, fn)
+#define EVT_HEADER_RIGHT_DCLICK(id, fn) wx__DECLARE_HEADER_EVT(RIGHT_DCLICK, id, fn)
+#define EVT_HEADER_MIDDLE_DCLICK(id, fn) wx__DECLARE_HEADER_EVT(MIDDLE_DCLICK, id, fn)
+
#endif // _WX_HEADERCTRL_H_
// override MSW-specific methods needed for new control
virtual WXDWORD MSWGetStyle(long style, WXDWORD *exstyle) const;
+ virtual bool MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result);
// common part of all ctors
void Init();
enum Operation { Set, Insert };
void DoSetOrInsertItem(Operation oper, 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, unsigned int idx, int button);
+
// the image list: initially NULL, created on demand
wxImageList *m_imageList;
wxHD_DRAGDROP.
@endStyleTable
- @beginEventTable{wxHeaderEvent}
- @event{EVT_HEADER_CLICK(id, func)}
- A column heading was clicked.
+ @beginEventTable{wxHeaderCtrlEvent}
+ @event{EVT_HEADER_CLICK(id, func)}
+ A column heading was clicked.
+ @event{EVT_HEADER_RIGHT_CLICK(id, func)}
+ A column heading was right clicked.
+ @event{EVT_HEADER_MIDDLE_CLICK(id, func)}
+ A column heading was clicked with the middle mouse button.
+
+ @event{EVT_HEADER_DCLICK(id, func)}
+ A column heading was double clicked.
+ @event{EVT_HEADER_RIGHT_DCLICK(id, func)}
+ A column heading was right double clicked.
+ @event{EVT_HEADER_MIDDLE_DCLICK(id, func)}
+ A column heading was double clicked with the middle mouse button.
@endEventTable
@library{wxcore}
*/
void RemoveSortIndicator(unsigned int idx);
};
+
+/**
+ @class wxHeaderCtrlEvent
+
+ Event class representing the events generated by wxHeaderCtrl.
+
+ @library{wxcore}
+ @category{ctrl}
+
+ @see wxHeaderCtrl
+*/
+class wxHeaderCtrlEvent : public wxNotifyEvent
+{
+public:
+ /**
+ Return the index of the column affected by this event.
+ */
+ int GetColumn() const;
+};
}
}
+// ============================================================================
+// wxHeaderCtrlEvent implementation
+// ============================================================================
+
+IMPLEMENT_DYNAMIC_CLASS(wxHeaderCtrlEvent, wxNotifyEvent)
+
+const wxEventType wxEVT_COMMAND_HEADER_CLICK = wxNewEventType();
+const wxEventType wxEVT_COMMAND_HEADER_RIGHT_CLICK = wxNewEventType();
+const wxEventType wxEVT_COMMAND_HEADER_MIDDLE_CLICK = wxNewEventType();
+
+const wxEventType wxEVT_COMMAND_HEADER_DCLICK = wxNewEventType();
+const wxEventType wxEVT_COMMAND_HEADER_RIGHT_DCLICK = wxNewEventType();
+const wxEventType wxEVT_COMMAND_HEADER_MIDDLE_DCLICK = wxNewEventType();
static const int EXPANDER_OFFSET = 1;
#endif
-//-----------------------------------------------------------------------------
-// wxDataViewHeaderWindow
-//-----------------------------------------------------------------------------
-
//Below is the compare stuff
//For the generic implements, both the leaf nodes and the nodes are sorted for fast search when needed
static wxDataViewModel * g_model;
static int g_column = -2;
static bool g_asending = true;
+//-----------------------------------------------------------------------------
+// wxDataViewHeaderWindow
+//-----------------------------------------------------------------------------
+
class wxDataViewHeaderWindow : public wxHeaderCtrl
{
public:
wxDataViewCtrl *GetOwner() const
{ return static_cast<wxDataViewCtrl *>(GetParent()); }
-protected:
+private:
virtual wxHeaderColumnBase& GetColumn(unsigned int idx)
{
return *(GetOwner()->GetColumn(idx));
}
-private:
+ bool SendEvent(wxEventType type, unsigned int n)
+ {
+ wxDataViewCtrl * const owner = GetOwner();
+ wxDataViewEvent event(type, owner->GetId());
+
+ event.SetEventObject(owner);
+ event.SetColumn(n);
+ event.SetDataViewColumn(owner->GetColumn(n));
+ event.SetModel(owner->GetModel());
+
+ // for events created by wxDataViewHeaderWindow the
+ // row / value fields are not valid
+ return owner->GetEventHandler()->ProcessEvent(event);
+ }
+
+ void OnClick(wxHeaderCtrlEvent& event)
+ {
+ if ( !SendEvent(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK,
+ event.GetColumn()) )
+ event.Skip();
+ }
+
+ void OnRClick(wxHeaderCtrlEvent& event)
+ {
+ if ( !SendEvent(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK,
+ event.GetColumn()) )
+ event.Skip();
+ }
+
+ DECLARE_EVENT_TABLE()
DECLARE_NO_COPY_CLASS(wxDataViewHeaderWindow)
};
+BEGIN_EVENT_TABLE(wxDataViewHeaderWindow, wxHeaderCtrl)
+ EVT_HEADER_CLICK(wxID_ANY, wxDataViewHeaderWindow::OnClick)
+ EVT_HEADER_RIGHT_CLICK(wxID_ANY, wxDataViewHeaderWindow::OnRClick)
+END_EVENT_TABLE()
+
//-----------------------------------------------------------------------------
// wxDataViewRenameTimer
//-----------------------------------------------------------------------------
return pos;
}
+int wxHeaderCtrl::FindColumnAtPos(int x, bool& onSeparator) const
+{
+ wxHeaderCtrl * const self = const_cast<wxHeaderCtrl *>(this);
+
+ int pos = 0;
+ const unsigned count = GetColumnCount();
+ for ( unsigned n = 0; n < count; n++ )
+ {
+ const wxHeaderColumnBase& col = self->GetColumn(n);
+ if ( col.IsHidden() )
+ continue;
+
+ pos += col.GetWidth();
+
+ // if the column is resizeable, check if we're approximatively over the
+ // line separating it from the next column
+ //
+ // TODO: don't hardcode sensitivity
+ if ( col.IsResizeable() && abs(x - pos) < 8 )
+ {
+ onSeparator = true;
+ return n;
+ }
+
+ // inside this column?
+ if ( x < pos )
+ {
+ onSeparator = false;
+ return n;
+ }
+ }
+
+ return COL_NONE;
+}
+
// ----------------------------------------------------------------------------
// wxHeaderCtrl repainting
// ----------------------------------------------------------------------------
}
}
-void wxHeaderCtrl::OnMouse(wxMouseEvent& event)
+void wxHeaderCtrl::OnMouse(wxMouseEvent& mevent)
{
- event.Skip();
+ mevent.Skip();
+
+ // find if the event is over a column at all
+ bool onSeparator;
+ const unsigned col = FindColumnAtPos(mevent.GetX(), onSeparator);
+ if ( col == COL_NONE )
+ return;
+
+ // update mouse cursor as it moves around
+ if ( mevent.Moving() )
+ {
+ SetCursor(onSeparator ? wxCursor(wxCURSOR_SIZEWE) : wxNullCursor);
+ return;
+ }
+
+ if ( mevent.LeftDown() )
+ {
+ // TODO
+ if ( onSeparator )
+ // resize column
+ ;
+ else
+ // drag column
+ ;
+
+ return;
+ }
+
+ // determine the type of header event corresponding to this mouse event
+ wxEventType evtType;
+ const bool click = mevent.ButtonUp();
+ if ( click || mevent.ButtonDClick() )
+ {
+ switch ( mevent.GetButton() )
+ {
+ case wxMOUSE_BTN_LEFT:
+ evtType = click ? wxEVT_COMMAND_HEADER_CLICK
+ : wxEVT_COMMAND_HEADER_DCLICK;
+ break;
+
+ case wxMOUSE_BTN_RIGHT:
+ evtType = click ? wxEVT_COMMAND_HEADER_RIGHT_CLICK
+ : wxEVT_COMMAND_HEADER_RIGHT_DCLICK;
+ break;
+
+ case wxMOUSE_BTN_MIDDLE:
+ evtType = click ? wxEVT_COMMAND_HEADER_MIDDLE_CLICK
+ : wxEVT_COMMAND_HEADER_MIDDLE_DCLICK;
+ break;
+
+ default:
+ // ignore clicks from other mouse buttons
+ return;
+ }
+
+ wxHeaderCtrlEvent event(evtType, GetId());
+ event.SetEventObject(this);
+ event.SetColumn(col);
+
+ if ( GetEventHandler()->ProcessEvent(event) )
+ mevent.Skip(false);
+ }
}
#endif // wxHAS_GENERIC_HEADERCTRL
#include "wx/msw/wrapcctl.h"
#include "wx/msw/private.h"
+// from src/msw/listctrl.cpp
+extern int WXDLLIMPEXP_CORE wxMSWGetColumnClicked(NMHDR *nmhdr, POINT *ptClick);
+
// ============================================================================
// wxHeaderCtrl implementation
// ============================================================================
}
}
+// ----------------------------------------------------------------------------
+// wxHeaderCtrl events
+// ----------------------------------------------------------------------------
+
+bool wxHeaderCtrl::SendClickEvent(bool dblclk, unsigned int idx, int button)
+{
+ wxEventType evtType;
+ switch ( button )
+ {
+ case 0:
+ evtType = dblclk ? wxEVT_COMMAND_HEADER_DCLICK
+ : wxEVT_COMMAND_HEADER_CLICK;
+ break;
+
+ case 1:
+ evtType = dblclk ? wxEVT_COMMAND_HEADER_RIGHT_DCLICK
+ : wxEVT_COMMAND_HEADER_RIGHT_CLICK;
+ break;
+
+ case 2:
+ evtType = dblclk ? wxEVT_COMMAND_HEADER_MIDDLE_DCLICK
+ : wxEVT_COMMAND_HEADER_MIDDLE_CLICK;
+ break;
+
+ default:
+ wxFAIL_MSG( wxS("unexpected event type") );
+ return false;
+ }
+
+ wxHeaderCtrlEvent event(evtType, GetId());
+ event.SetEventObject(this);
+ event.SetColumn(idx);
+
+ return GetEventHandler()->ProcessEvent(event);
+}
+
+bool wxHeaderCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
+{
+ NMHEADER * const nmhdr = (NMHEADER *)lParam;
+
+ switch ( nmhdr->hdr.code )
+ {
+ case HDN_ITEMCLICK:
+ case HDN_ITEMDBLCLICK:
+ if ( SendClickEvent(nmhdr->hdr.code == HDN_ITEMDBLCLICK,
+ nmhdr->iItem,
+ nmhdr->iButton) )
+ return true;
+ break;
+
+ // although we should get the notifications about the right clicks
+ // via HDN_ITEM[DBL]CLICK too according to MSDN this simply doesn't
+ // happen in practice on any Windows system up to 2003
+ case NM_RCLICK:
+ case NM_RDBLCLK:
+ {
+ POINT pt;
+ const int col = wxMSWGetColumnClicked(&nmhdr->hdr, &pt);
+ if ( col != wxNOT_FOUND )
+ {
+ if ( SendClickEvent(nmhdr->hdr.code == NM_RDBLCLK, col, 1) )
+ return true;
+ }
+ //else: ignore clicks outside any column
+ }
+ break;
+ }
+
+ return wxHeaderCtrlBase::MSWOnNotify(idCtrl, lParam, result);
+}