implement click events in wxHeaderCtrl
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@57178 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -74,6 +74,14 @@ private:
|
||||
// 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;
|
||||
|
||||
|
@@ -120,7 +120,7 @@ private:
|
||||
// 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
|
||||
@@ -236,4 +236,61 @@ private:
|
||||
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_
|
||||
|
@@ -60,6 +60,7 @@ private:
|
||||
|
||||
// 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();
|
||||
@@ -70,6 +71,10 @@ private:
|
||||
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;
|
||||
|
@@ -49,9 +49,20 @@
|
||||
wxHD_DRAGDROP.
|
||||
@endStyleTable
|
||||
|
||||
@beginEventTable{wxHeaderEvent}
|
||||
@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}
|
||||
@@ -285,3 +296,22 @@ public:
|
||||
*/
|
||||
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;
|
||||
};
|
||||
|
@@ -132,3 +132,16 @@ void wxHeaderCtrlSimple::RemoveSortIndicator()
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 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();
|
||||
|
@@ -67,16 +67,16 @@ static const int EXPANDER_OFFSET = 4;
|
||||
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:
|
||||
@@ -88,16 +88,50 @@ 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
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@@ -145,6 +145,41 @@ int wxHeaderCtrl::GetColStart(unsigned int idx) const
|
||||
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
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -242,9 +277,70 @@ void wxHeaderCtrl::OnPaint(wxPaintEvent& WXUNUSED(event))
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
@@ -33,6 +33,9 @@
|
||||
#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
|
||||
// ============================================================================
|
||||
@@ -250,3 +253,73 @@ void wxHeaderCtrl::DoSetOrInsertItem(Operation oper, unsigned int idx)
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// 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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user