headerctrl.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Name: wx/headerctrl.h
  3. // Purpose: wxHeaderCtrlBase class: interface of wxHeaderCtrl
  4. // Author: Vadim Zeitlin
  5. // Created: 2008-12-01
  6. // Copyright: (c) 2008 Vadim Zeitlin <vadim@wxwidgets.org>
  7. // Licence: wxWindows licence
  8. ///////////////////////////////////////////////////////////////////////////////
  9. #ifndef _WX_HEADERCTRL_H_
  10. #define _WX_HEADERCTRL_H_
  11. #include "wx/control.h"
  12. #if wxUSE_HEADERCTRL
  13. #include "wx/dynarray.h"
  14. #include "wx/vector.h"
  15. #include "wx/headercol.h"
  16. // notice that the classes in this header are defined in the core library even
  17. // although currently they're only used by wxGrid which is in wxAdv because we
  18. // plan to use it in wxListCtrl which is in core too in the future
  19. class WXDLLIMPEXP_FWD_CORE wxHeaderCtrlEvent;
  20. // ----------------------------------------------------------------------------
  21. // constants
  22. // ----------------------------------------------------------------------------
  23. enum
  24. {
  25. // allow column drag and drop
  26. wxHD_ALLOW_REORDER = 0x0001,
  27. // allow hiding (and showing back) the columns using the menu shown by
  28. // right clicking the header
  29. wxHD_ALLOW_HIDE = 0x0002,
  30. // style used by default when creating the control
  31. wxHD_DEFAULT_STYLE = wxHD_ALLOW_REORDER
  32. };
  33. extern WXDLLIMPEXP_DATA_CORE(const char) wxHeaderCtrlNameStr[];
  34. // ----------------------------------------------------------------------------
  35. // wxHeaderCtrlBase defines the interface of a header control
  36. // ----------------------------------------------------------------------------
  37. class WXDLLIMPEXP_CORE wxHeaderCtrlBase : public wxControl
  38. {
  39. public:
  40. /*
  41. Derived classes must provide default ctor as well as a ctor and
  42. Create() function with the following signatures:
  43. wxHeaderCtrl(wxWindow *parent,
  44. wxWindowID winid = wxID_ANY,
  45. const wxPoint& pos = wxDefaultPosition,
  46. const wxSize& size = wxDefaultSize,
  47. long style = wxHD_DEFAULT_STYLE,
  48. const wxString& name = wxHeaderCtrlNameStr);
  49. bool Create(wxWindow *parent,
  50. wxWindowID winid = wxID_ANY,
  51. const wxPoint& pos = wxDefaultPosition,
  52. const wxSize& size = wxDefaultSize,
  53. long style = wxHD_DEFAULT_STYLE,
  54. const wxString& name = wxHeaderCtrlNameStr);
  55. */
  56. // column-related methods
  57. // ----------------------
  58. // set the number of columns in the control
  59. //
  60. // this also calls UpdateColumn() for all columns
  61. void SetColumnCount(unsigned int count);
  62. // return the number of columns in the control as set by SetColumnCount()
  63. unsigned int GetColumnCount() const { return DoGetCount(); }
  64. // return whether the control has any columns
  65. bool IsEmpty() const { return DoGetCount() == 0; }
  66. // update the column with the given index
  67. void UpdateColumn(unsigned int idx)
  68. {
  69. wxCHECK_RET( idx < GetColumnCount(), "invalid column index" );
  70. DoUpdate(idx);
  71. }
  72. // columns order
  73. // -------------
  74. // set the columns order: the array defines the column index which appears
  75. // the given position, it must have GetColumnCount() elements and contain
  76. // all indices exactly once
  77. void SetColumnsOrder(const wxArrayInt& order);
  78. wxArrayInt GetColumnsOrder() const;
  79. // get the index of the column at the given display position
  80. unsigned int GetColumnAt(unsigned int pos) const;
  81. // get the position at which this column is currently displayed
  82. unsigned int GetColumnPos(unsigned int idx) const;
  83. // reset the columns order to the natural one
  84. void ResetColumnsOrder();
  85. // helper function used by the generic version of this control and also
  86. // wxGrid: reshuffles the array of column indices indexed by positions
  87. // (i.e. using the same convention as for SetColumnsOrder()) so that the
  88. // column with the given index is found at the specified position
  89. static void MoveColumnInOrderArray(wxArrayInt& order,
  90. unsigned int idx,
  91. unsigned int pos);
  92. // UI helpers
  93. // ----------
  94. #if wxUSE_MENUS
  95. // show the popup menu containing all columns with check marks for the ones
  96. // which are currently shown and return true if something was done using it
  97. // (in this case UpdateColumnVisibility() will have been called) or false
  98. // if the menu was cancelled
  99. //
  100. // this is called from the default right click handler for the controls
  101. // with wxHD_ALLOW_HIDE style
  102. bool ShowColumnsMenu(const wxPoint& pt, const wxString& title = wxString());
  103. // append the entries for all our columns to the given menu, with the
  104. // currently visible columns being checked
  105. //
  106. // this is used by ShowColumnsMenu() but can also be used if you use your
  107. // own custom columns menu but nevertheless want to show all the columns in
  108. // it
  109. //
  110. // the ids of the items corresponding to the columns are consecutive and
  111. // start from idColumnsBase
  112. void AddColumnsItems(wxMenu& menu, int idColumnsBase = 0);
  113. #endif // wxUSE_MENUS
  114. // show the columns customization dialog and return true if something was
  115. // changed using it (in which case UpdateColumnVisibility() and/or
  116. // UpdateColumnsOrder() will have been called)
  117. //
  118. // this is called by the control itself from ShowColumnsMenu() (which in
  119. // turn is only called by the control if wxHD_ALLOW_HIDE style was
  120. // specified) and if the control has wxHD_ALLOW_REORDER style as well
  121. bool ShowCustomizeDialog();
  122. // compute column title width
  123. int GetColumnTitleWidth(const wxHeaderColumn& col);
  124. // implementation only from now on
  125. // -------------------------------
  126. // the user doesn't need to TAB to this control
  127. virtual bool AcceptsFocusFromKeyboard() const { return false; }
  128. // this method is only overridden in order to synchronize the control with
  129. // the main window when it is scrolled, the derived class must implement
  130. // DoScrollHorz()
  131. virtual void ScrollWindow(int dx, int dy, const wxRect *rect = NULL);
  132. protected:
  133. // this method must be implemented by the derived classes to return the
  134. // information for the given column
  135. virtual const wxHeaderColumn& GetColumn(unsigned int idx) const = 0;
  136. // this method is called from the default EVT_HEADER_SEPARATOR_DCLICK
  137. // handler to update the fitting column width of the given column, it
  138. // should return true if the width was really updated
  139. virtual bool UpdateColumnWidthToFit(unsigned int WXUNUSED(idx),
  140. int WXUNUSED(widthTitle))
  141. {
  142. return false;
  143. }
  144. // this method is called from ShowColumnsMenu() and must be overridden to
  145. // update the internal column visibility (there is no need to call
  146. // UpdateColumn() from here, this will be done internally)
  147. virtual void UpdateColumnVisibility(unsigned int WXUNUSED(idx),
  148. bool WXUNUSED(show))
  149. {
  150. wxFAIL_MSG( "must be overridden if called" );
  151. }
  152. // this method is called from ShowCustomizeDialog() to reorder all columns
  153. // at once and should be implemented for controls using wxHD_ALLOW_REORDER
  154. // style (there is no need to call SetColumnsOrder() from here, this is
  155. // done by the control itself)
  156. virtual void UpdateColumnsOrder(const wxArrayInt& WXUNUSED(order))
  157. {
  158. wxFAIL_MSG( "must be overridden if called" );
  159. }
  160. // this method can be overridden in the derived classes to do something
  161. // (e.g. update/resize some internal data structures) before the number of
  162. // columns in the control changes
  163. virtual void OnColumnCountChanging(unsigned int WXUNUSED(count)) { }
  164. // helper function for the derived classes: update the array of column
  165. // indices after the number of columns changed
  166. void DoResizeColumnIndices(wxArrayInt& colIndices, unsigned int count);
  167. protected:
  168. // this window doesn't look nice with the border so don't use it by default
  169. virtual wxBorder GetDefaultBorder() const { return wxBORDER_NONE; }
  170. private:
  171. // methods implementing our public API and defined in platform-specific
  172. // implementations
  173. virtual void DoSetCount(unsigned int count) = 0;
  174. virtual unsigned int DoGetCount() const = 0;
  175. virtual void DoUpdate(unsigned int idx) = 0;
  176. virtual void DoScrollHorz(int dx) = 0;
  177. virtual void DoSetColumnsOrder(const wxArrayInt& order) = 0;
  178. virtual wxArrayInt DoGetColumnsOrder() const = 0;
  179. // event handlers
  180. void OnSeparatorDClick(wxHeaderCtrlEvent& event);
  181. #if wxUSE_MENUS
  182. void OnRClick(wxHeaderCtrlEvent& event);
  183. #endif // wxUSE_MENUS
  184. DECLARE_EVENT_TABLE()
  185. };
  186. // ----------------------------------------------------------------------------
  187. // wxHeaderCtrl: port-specific header control implementation, notice that this
  188. // is still an ABC which is meant to be used as part of another
  189. // control, see wxHeaderCtrlSimple for a standalone version
  190. // ----------------------------------------------------------------------------
  191. #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
  192. #include "wx/msw/headerctrl.h"
  193. #else
  194. #define wxHAS_GENERIC_HEADERCTRL
  195. #include "wx/generic/headerctrlg.h"
  196. #endif // platform
  197. // ----------------------------------------------------------------------------
  198. // wxHeaderCtrlSimple: concrete header control which can be used standalone
  199. // ----------------------------------------------------------------------------
  200. class WXDLLIMPEXP_CORE wxHeaderCtrlSimple : public wxHeaderCtrl
  201. {
  202. public:
  203. // control creation
  204. // ----------------
  205. wxHeaderCtrlSimple() { Init(); }
  206. wxHeaderCtrlSimple(wxWindow *parent,
  207. wxWindowID winid = wxID_ANY,
  208. const wxPoint& pos = wxDefaultPosition,
  209. const wxSize& size = wxDefaultSize,
  210. long style = wxHD_DEFAULT_STYLE,
  211. const wxString& name = wxHeaderCtrlNameStr)
  212. {
  213. Init();
  214. Create(parent, winid, pos, size, style, name);
  215. }
  216. // managing the columns
  217. // --------------------
  218. // insert the column at the given position, using GetColumnCount() as
  219. // position appends it at the end
  220. void InsertColumn(const wxHeaderColumnSimple& col, unsigned int idx)
  221. {
  222. wxCHECK_RET( idx <= GetColumnCount(), "invalid column index" );
  223. DoInsert(col, idx);
  224. }
  225. // append the column to the end of the control
  226. void AppendColumn(const wxHeaderColumnSimple& col)
  227. {
  228. DoInsert(col, GetColumnCount());
  229. }
  230. // delete the column at the given index
  231. void DeleteColumn(unsigned int idx)
  232. {
  233. wxCHECK_RET( idx < GetColumnCount(), "invalid column index" );
  234. DoDelete(idx);
  235. }
  236. // delete all the existing columns
  237. void DeleteAllColumns();
  238. // modifying columns
  239. // -----------------
  240. // show or hide the column, notice that even when a column is hidden we
  241. // still account for it when using indices
  242. void ShowColumn(unsigned int idx, bool show = true)
  243. {
  244. wxCHECK_RET( idx < GetColumnCount(), "invalid column index" );
  245. DoShowColumn(idx, show);
  246. }
  247. void HideColumn(unsigned int idx)
  248. {
  249. ShowColumn(idx, false);
  250. }
  251. // indicate that the column is used for sorting
  252. void ShowSortIndicator(unsigned int idx, bool ascending = true)
  253. {
  254. wxCHECK_RET( idx < GetColumnCount(), "invalid column index" );
  255. DoShowSortIndicator(idx, ascending);
  256. }
  257. // remove the sort indicator completely
  258. void RemoveSortIndicator();
  259. protected:
  260. // implement/override base class methods
  261. virtual const wxHeaderColumn& GetColumn(unsigned int idx) const;
  262. virtual bool UpdateColumnWidthToFit(unsigned int idx, int widthTitle);
  263. // and define another one to be overridden in the derived classes: it
  264. // should return the best width for the given column contents or -1 if not
  265. // implemented, we use it to implement UpdateColumnWidthToFit()
  266. virtual int GetBestFittingWidth(unsigned int WXUNUSED(idx)) const
  267. {
  268. return -1;
  269. }
  270. private:
  271. // functions implementing our public API
  272. void DoInsert(const wxHeaderColumnSimple& col, unsigned int idx);
  273. void DoDelete(unsigned int idx);
  274. void DoShowColumn(unsigned int idx, bool show);
  275. void DoShowSortIndicator(unsigned int idx, bool ascending);
  276. // common part of all ctors
  277. void Init();
  278. // bring the column count in sync with the number of columns we store
  279. void UpdateColumnCount()
  280. {
  281. SetColumnCount(static_cast<int>(m_cols.size()));
  282. }
  283. // all our current columns
  284. typedef wxVector<wxHeaderColumnSimple> Columns;
  285. Columns m_cols;
  286. // the column currently used for sorting or -1 if none
  287. unsigned int m_sortKey;
  288. wxDECLARE_NO_COPY_CLASS(wxHeaderCtrlSimple);
  289. };
  290. // ----------------------------------------------------------------------------
  291. // wxHeaderCtrl events
  292. // ----------------------------------------------------------------------------
  293. class WXDLLIMPEXP_CORE wxHeaderCtrlEvent : public wxNotifyEvent
  294. {
  295. public:
  296. wxHeaderCtrlEvent(wxEventType commandType = wxEVT_NULL, int winid = 0)
  297. : wxNotifyEvent(commandType, winid),
  298. m_col(-1),
  299. m_width(0),
  300. m_order(static_cast<unsigned int>(-1))
  301. {
  302. }
  303. wxHeaderCtrlEvent(const wxHeaderCtrlEvent& event)
  304. : wxNotifyEvent(event),
  305. m_col(event.m_col),
  306. m_width(event.m_width),
  307. m_order(event.m_order)
  308. {
  309. }
  310. // the column which this event pertains to: valid for all header events
  311. int GetColumn() const { return m_col; }
  312. void SetColumn(int col) { m_col = col; }
  313. // the width of the column: valid for column resizing/dragging events only
  314. int GetWidth() const { return m_width; }
  315. void SetWidth(int width) { m_width = width; }
  316. // the new position of the column: for end reorder events only
  317. unsigned int GetNewOrder() const { return m_order; }
  318. void SetNewOrder(unsigned int order) { m_order = order; }
  319. virtual wxEvent *Clone() const { return new wxHeaderCtrlEvent(*this); }
  320. protected:
  321. // the column affected by the event
  322. int m_col;
  323. // the current width for the dragging events
  324. int m_width;
  325. // the new column position for end reorder event
  326. unsigned int m_order;
  327. private:
  328. DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxHeaderCtrlEvent)
  329. };
  330. wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_CORE, wxEVT_HEADER_CLICK, wxHeaderCtrlEvent );
  331. wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_CORE, wxEVT_HEADER_RIGHT_CLICK, wxHeaderCtrlEvent );
  332. wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_CORE, wxEVT_HEADER_MIDDLE_CLICK, wxHeaderCtrlEvent );
  333. wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_CORE, wxEVT_HEADER_DCLICK, wxHeaderCtrlEvent );
  334. wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_CORE, wxEVT_HEADER_RIGHT_DCLICK, wxHeaderCtrlEvent );
  335. wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_CORE, wxEVT_HEADER_MIDDLE_DCLICK, wxHeaderCtrlEvent );
  336. wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_CORE, wxEVT_HEADER_SEPARATOR_DCLICK, wxHeaderCtrlEvent );
  337. wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_CORE, wxEVT_HEADER_BEGIN_RESIZE, wxHeaderCtrlEvent );
  338. wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_CORE, wxEVT_HEADER_RESIZING, wxHeaderCtrlEvent );
  339. wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_CORE, wxEVT_HEADER_END_RESIZE, wxHeaderCtrlEvent );
  340. wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_CORE, wxEVT_HEADER_BEGIN_REORDER, wxHeaderCtrlEvent );
  341. wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_CORE, wxEVT_HEADER_END_REORDER, wxHeaderCtrlEvent );
  342. wxDECLARE_EXPORTED_EVENT( WXDLLIMPEXP_CORE, wxEVT_HEADER_DRAGGING_CANCELLED, wxHeaderCtrlEvent );
  343. typedef void (wxEvtHandler::*wxHeaderCtrlEventFunction)(wxHeaderCtrlEvent&);
  344. #define wxHeaderCtrlEventHandler(func) \
  345. wxEVENT_HANDLER_CAST(wxHeaderCtrlEventFunction, func)
  346. #define wx__DECLARE_HEADER_EVT(evt, id, fn) \
  347. wx__DECLARE_EVT1(wxEVT_HEADER_ ## evt, id, wxHeaderCtrlEventHandler(fn))
  348. #define EVT_HEADER_CLICK(id, fn) wx__DECLARE_HEADER_EVT(CLICK, id, fn)
  349. #define EVT_HEADER_RIGHT_CLICK(id, fn) wx__DECLARE_HEADER_EVT(RIGHT_CLICK, id, fn)
  350. #define EVT_HEADER_MIDDLE_CLICK(id, fn) wx__DECLARE_HEADER_EVT(MIDDLE_CLICK, id, fn)
  351. #define EVT_HEADER_DCLICK(id, fn) wx__DECLARE_HEADER_EVT(DCLICK, id, fn)
  352. #define EVT_HEADER_RIGHT_DCLICK(id, fn) wx__DECLARE_HEADER_EVT(RIGHT_DCLICK, id, fn)
  353. #define EVT_HEADER_MIDDLE_DCLICK(id, fn) wx__DECLARE_HEADER_EVT(MIDDLE_DCLICK, id, fn)
  354. #define EVT_HEADER_SEPARATOR_DCLICK(id, fn) wx__DECLARE_HEADER_EVT(SEPARATOR_DCLICK, id, fn)
  355. #define EVT_HEADER_BEGIN_RESIZE(id, fn) wx__DECLARE_HEADER_EVT(BEGIN_RESIZE, id, fn)
  356. #define EVT_HEADER_RESIZING(id, fn) wx__DECLARE_HEADER_EVT(RESIZING, id, fn)
  357. #define EVT_HEADER_END_RESIZE(id, fn) wx__DECLARE_HEADER_EVT(END_RESIZE, id, fn)
  358. #define EVT_HEADER_BEGIN_REORDER(id, fn) wx__DECLARE_HEADER_EVT(BEGIN_REORDER, id, fn)
  359. #define EVT_HEADER_END_REORDER(id, fn) wx__DECLARE_HEADER_EVT(END_REORDER, id, fn)
  360. #define EVT_HEADER_DRAGGING_CANCELLED(id, fn) wx__DECLARE_HEADER_EVT(DRAGGING_CANCELLED, id, fn)
  361. // old wxEVT_COMMAND_* constants
  362. #define wxEVT_COMMAND_HEADER_CLICK wxEVT_HEADER_CLICK
  363. #define wxEVT_COMMAND_HEADER_RIGHT_CLICK wxEVT_HEADER_RIGHT_CLICK
  364. #define wxEVT_COMMAND_HEADER_MIDDLE_CLICK wxEVT_HEADER_MIDDLE_CLICK
  365. #define wxEVT_COMMAND_HEADER_DCLICK wxEVT_HEADER_DCLICK
  366. #define wxEVT_COMMAND_HEADER_RIGHT_DCLICK wxEVT_HEADER_RIGHT_DCLICK
  367. #define wxEVT_COMMAND_HEADER_MIDDLE_DCLICK wxEVT_HEADER_MIDDLE_DCLICK
  368. #define wxEVT_COMMAND_HEADER_SEPARATOR_DCLICK wxEVT_HEADER_SEPARATOR_DCLICK
  369. #define wxEVT_COMMAND_HEADER_BEGIN_RESIZE wxEVT_HEADER_BEGIN_RESIZE
  370. #define wxEVT_COMMAND_HEADER_RESIZING wxEVT_HEADER_RESIZING
  371. #define wxEVT_COMMAND_HEADER_END_RESIZE wxEVT_HEADER_END_RESIZE
  372. #define wxEVT_COMMAND_HEADER_BEGIN_REORDER wxEVT_HEADER_BEGIN_REORDER
  373. #define wxEVT_COMMAND_HEADER_END_REORDER wxEVT_HEADER_END_REORDER
  374. #define wxEVT_COMMAND_HEADER_DRAGGING_CANCELLED wxEVT_HEADER_DRAGGING_CANCELLED
  375. #endif // wxUSE_HEADERCTRL
  376. #endif // _WX_HEADERCTRL_H_