// return the horizontal start position of the given column
int GetColStart(unsigned int idx) const;
- // refresh the given column [only]
+ // refresh the given column [only]; idx must be valid
void RefreshCol(unsigned int idx);
+ // refresh the given column if idx is valid
+ void RefreshColIfNotNone(unsigned int idx);
+
// refresh all the controls starting from (and including) the given one
void RefreshColsAfter(unsigned int idx);
// notice that the classes in this header are defined in the core library even
// although currently they're only used by wxGrid which is in wxAdv because we
// plan to use it in wxListCtrl which is in core too in the future
+class WXDLLIMPEXP_FWD_CORE wxHeaderCtrlEvent;
// ----------------------------------------------------------------------------
// constants
// information for the given column
virtual wxHeaderColumnBase& GetColumn(unsigned int idx) = 0;
+ // this method is called from the default EVT_HEADER_SEPARATOR_DCLICK
+ // handler to update the fitting column width of the given column, it
+ // should return true if the width was really updated
+ virtual bool UpdateColumnWidthToFit(unsigned int WXUNUSED(idx),
+ int WXUNUSED(widthTitle))
+ {
+ return false;
+ }
+
private:
// methods implementing our public API and defined in platform-specific
// implementations
// this window doesn't look nice with the border so don't use it by default
virtual wxBorder GetDefaultBorder() const { return wxBORDER_NONE; }
+
+ // event handlers
+ void OnSeparatorDClick(wxHeaderCtrlEvent& event);
+
+ DECLARE_EVENT_TABLE()
};
// ----------------------------------------------------------------------------
extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_HEADER_RIGHT_DCLICK;
extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_HEADER_MIDDLE_DCLICK;
+extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_HEADER_SEPARATOR_DCLICK;
+
typedef void (wxEvtHandler::*wxHeaderCtrlEventFunction)(wxHeaderCtrlEvent&);
#define wxHeaderCtrlEventHandler(func) \
#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)
+#define EVT_HEADER_SEPARATOR_DCLICK(id, fn) wx__DECLARE_HEADER_EVT(SEPARATOR_DCLICK, id, fn)
+
#endif // _WX_HEADERCTRL_H_
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, unsigned int idx, int button);
+ bool SendClickEvent(bool dblclk, int button, unsigned int idx);
// the image list: initially NULL, created on demand
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.
+
+ @event{EVT_HEADER_SEPARATOR_DCLICK(id, func)}
+ Separator to the right of the specified column was double clicked
+ (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).
@endEventTable
@library{wxcore}
SetColumnCount().
*/
virtual wxHeaderColumnBase& GetColumn(unsigned int idx) = 0;
+
+ /**
+ Method which may be implemented by the derived classes to allow double
+ clicking the column separator to resize the column to fit its contents.
+
+ When a separator is double clicked, the default handler of
+ EVT_HEADER_SEPARATOR_DCLICK event calls this function and refreshes the
+ column if it returns @true so to implement the resizing of the column
+ to fit its width on header double click you need to implement this
+ method using logic similar to this example:
+ @code
+ class MyHeaderCtrl : public wxHeaderColumnBase
+ {
+ public:
+ ...
+
+ void SetWidth(int width) { m_width = width; }
+ virtual int GetWidth() const { return m_width; }
+
+ private:
+ int m_width;
+ };
+
+ class MyHeaderCtrl : public wxHeaderCtrl
+ {
+ public:
+ protected:
+ virtual wxHeaderColumnBase& GetColumn(unsigned int idx)
+ {
+ return m_cols[idx];
+ }
+
+ virtual bool UpdateColumnWidthToFit(unsigned int idx, int widthTitle)
+ {
+ int widthContents = ... compute minimal width for column idx ...
+ m_cols[idx].SetWidth(wxMax(widthContents, widthTitle));
+ return true;
+ }
+
+ wxVector<MyHeaderColumn> m_cols;
+ };
+ @endcode
+
+ Base class version simply returns @false.
+
+ @param width
+ Contains minimal width needed to display the column header itself
+ and will usually be used as a starting point for the fitting width
+ calculation.
+ @return
+ @true to indicate that the column was resized, i.e. GetColumn() now
+ returns the new width value, and so must be refreshed or @false
+ meaning that the control didn't reach to the separator double click.
+ */
+ virtual bool UpdateColumnWidthToFit(unsigned int idx, int widthTitle);
};
extern WXDLLIMPEXP_DATA_CORE(const char) wxHeaderCtrlNameStr[] = "wxHeaderCtrl";
+BEGIN_EVENT_TABLE(wxHeaderCtrlBase, wxControl)
+ EVT_HEADER_SEPARATOR_DCLICK(wxID_ANY, wxHeaderCtrlBase::OnSeparatorDClick)
+END_EVENT_TABLE()
+
void wxHeaderCtrlBase::ScrollWindow(int dx,
int WXUNUSED_UNLESS_DEBUG(dy),
const wxRect * WXUNUSED_UNLESS_DEBUG(rect))
DoScrollHorz(dx);
}
+void wxHeaderCtrlBase::OnSeparatorDClick(wxHeaderCtrlEvent& event)
+{
+ const unsigned col = event.GetColumn();
+
+ int w = wxWindowBase::GetTextExtent(GetColumn(col).GetTitle()).x;
+ w += 2*GetCharWidth(); // add some arbitrary margins around text
+
+ if ( !UpdateColumnWidthToFit(col, w) )
+ event.Skip();
+ else
+ UpdateColumn(col);
+}
+
// ============================================================================
// wxHeaderCtrlSimple implementation
// ============================================================================
const wxEventType wxEVT_COMMAND_HEADER_DCLICK = wxNewEventType();
const wxEventType wxEVT_COMMAND_HEADER_RIGHT_DCLICK = wxNewEventType();
const wxEventType wxEVT_COMMAND_HEADER_MIDDLE_DCLICK = wxNewEventType();
+
+const wxEventType wxEVT_COMMAND_HEADER_SEPARATOR_DCLICK = wxNewEventType();
wxDataViewCtrl *GetOwner() const
{ return static_cast<wxDataViewCtrl *>(GetParent()); }
-private:
+protected:
+ // implement/override wxHeaderCtrl functions by forwarding them to the main
+ // control
virtual wxHeaderColumnBase& GetColumn(unsigned int idx)
{
return *(GetOwner()->GetColumn(idx));
}
+ virtual bool UpdateColumnWidthToFit(unsigned int idx, int widthTitle)
+ {
+ wxDataViewCtrl * const owner = GetOwner();
+
+ int widthContents = owner->GetBestColumnWidth(idx);
+ owner->GetColumn(idx)->SetWidth(wxMax(widthTitle, widthContents));
+
+ return true;
+ }
+
+private:
bool SendEvent(wxEventType type, unsigned int n)
{
wxDataViewCtrl * const owner = GetOwner();
// wxHeaderCtrl event handlers
// ----------------------------------------------------------------------------
-BEGIN_EVENT_TABLE(wxHeaderCtrl, wxControl)
+BEGIN_EVENT_TABLE(wxHeaderCtrl, wxHeaderCtrlBase)
EVT_PAINT(wxHeaderCtrl::OnPaint)
EVT_MOUSE_EVENTS(wxHeaderCtrl::OnMouse)
}
// determine the type of header event corresponding to this mouse event
- wxEventType evtType;
- const bool click = mevent.ButtonUp();
- if ( click || mevent.ButtonDClick() )
+ wxEventType evtType = wxEVT_NULL;
+ const bool click = mevent.ButtonUp(),
+ dblclk = mevent.ButtonDClick();
+ if ( click || dblclk )
{
switch ( mevent.GetButton() )
{
case wxMOUSE_BTN_LEFT:
- evtType = click ? wxEVT_COMMAND_HEADER_CLICK
- : wxEVT_COMMAND_HEADER_DCLICK;
+ // treat left double clicks on separator specially
+ if ( onSeparator && dblclk )
+ {
+ evtType = wxEVT_COMMAND_HEADER_SEPARATOR_DCLICK;
+ }
+ else // not double click on separator
+ {
+ evtType = click ? wxEVT_COMMAND_HEADER_CLICK
+ : wxEVT_COMMAND_HEADER_DCLICK;
+ }
break;
case wxMOUSE_BTN_RIGHT:
default:
// ignore clicks from other mouse buttons
- return;
+ ;
}
+ }
+
+ if ( evtType == wxEVT_NULL )
+ return;
- wxHeaderCtrlEvent event(evtType, GetId());
- event.SetEventObject(this);
- event.SetColumn(col);
+ wxHeaderCtrlEvent event(evtType, GetId());
+ event.SetEventObject(this);
+ event.SetColumn(col);
- if ( GetEventHandler()->ProcessEvent(event) )
- mevent.Skip(false);
- }
+ if ( GetEventHandler()->ProcessEvent(event) )
+ mevent.Skip(false);
}
#endif // wxHAS_GENERIC_HEADERCTRL
#endif // WX_PRECOMP
#include "wx/headerctrl.h"
+
+#ifndef wxHAS_GENERIC_HEADERCTRL
+
#include "wx/imaglist.h"
#include "wx/msw/wrapcctl.h"
// wxHeaderCtrl events
// ----------------------------------------------------------------------------
-bool wxHeaderCtrl::SendClickEvent(bool dblclk, unsigned int idx, int button)
+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 evtType;
switch ( button )
return false;
}
- wxHeaderCtrlEvent event(evtType, GetId());
- event.SetEventObject(this);
- event.SetColumn(idx);
-
- return GetEventHandler()->ProcessEvent(event);
+ return SendEvent(evtType, idx);
}
bool wxHeaderCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
{
NMHEADER * const nmhdr = (NMHEADER *)lParam;
- switch ( nmhdr->hdr.code )
+ const int idx = nmhdr->iItem;
+ switch ( const UINT code = nmhdr->hdr.code )
{
case HDN_ITEMCLICK:
case HDN_ITEMDBLCLICK:
- if ( SendClickEvent(nmhdr->hdr.code == HDN_ITEMDBLCLICK,
- nmhdr->iItem,
- nmhdr->iButton) )
+ if ( SendClickEvent(code == HDN_ITEMDBLCLICK, nmhdr->iButton, idx) )
return true;
break;
const int col = wxMSWGetColumnClicked(&nmhdr->hdr, &pt);
if ( col != wxNOT_FOUND )
{
- if ( SendClickEvent(nmhdr->hdr.code == NM_RDBLCLK, col, 1) )
+ if ( SendClickEvent(code == NM_RDBLCLK, 1, col) )
return true;
}
//else: ignore clicks outside any column
}
break;
+
+ case HDN_DIVIDERDBLCLICK:
+ if ( SendEvent(wxEVT_COMMAND_HEADER_SEPARATOR_DCLICK, idx) )
+ return true;
+ break;
}
return wxHeaderCtrlBase::MSWOnNotify(idCtrl, lParam, result);
}
+
+#endif // wxHAS_GENERIC_HEADERCTRL