]> git.saurik.com Git - wxWidgets.git/blob - interface/wx/headerctrl.h
Add wxEventLoop::ScheduleExit().
[wxWidgets.git] / interface / wx / headerctrl.h
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: wx/headerctrl.h
3 // Purpose: interface of wxHeaderCtrl
4 // Author: Vadim Zeitlin
5 // Created: 2008-12-01
6 // RCS-ID: $Id$
7 // Copyright: (c) 2008 Vadim Zeitlin <vadim@wxwidgets.org>
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11
12 enum
13 {
14 // allow column drag and drop
15 wxHD_ALLOW_REORDER = 0x0001,
16
17 // allow hiding (and showing back) the columns using the menu shown by
18 // right clicking the header
19 wxHD_ALLOW_HIDE = 0x0002,
20
21 // style used by default when creating the control
22 wxHD_DEFAULT_STYLE = wxHD_ALLOW_REORDER
23 };
24
25
26
27 /**
28 @class wxHeaderCtrl
29
30 wxHeaderCtrl is the control containing the column headings which is usually
31 used for display of tabular data.
32
33 It is used as part of wxGrid, in generic version wxDataViewCtrl and report
34 view of wxListCtrl but can be also used independently. In general this
35 class is meant to be used as part of another control which already stores
36 the column information somewhere as it can't be used directly: instead you
37 need to inherit from it and implement the GetColumn() method to provide
38 column information. See wxHeaderCtrlSimple for a concrete control class
39 which can be used directly.
40
41 In addition to labeling the columns, the control has the following
42 features:
43 - Column reordering support, either by explicitly configuring the
44 columns order and calling SetColumnsOrder() or by dragging the
45 columns interactively (if enabled).
46 - Display of the icons in the header: this is often used to display a
47 sort or reverse sort indicator when the column header is clicked.
48
49 Notice that this control itself doesn't do anything other than displaying
50 the column headers. In particular column reordering and sorting must still
51 be supported by the associated control displaying the real data under the
52 header. Also remember to call ScrollWindow() method of the control if the
53 associated data display window has a horizontal scrollbar, otherwise the
54 headers wouldn't align with the data when the window is scrolled.
55
56 This control is implemented using the native header control under MSW
57 systems and a generic implementation elsewhere.
58
59
60 @section headerctrl_improvements Future Improvements
61
62 Some features are supported by the native MSW control and so could be
63 easily implemented in this version of wxHeaderCtrl but need to be
64 implemented in the generic version as well to be really useful. Please let
65 us know if you need or, better, plan to work on implementing, any of them:
66 - Displaying bitmaps instead of or together with the text
67 - Custom drawn headers
68 - Filters associated with a column.
69
70
71 @beginStyleTable
72 @style{wxHD_ALLOW_REORDER}
73 If this style is specified (it is by default), the user can reorder
74 the control columns by dragging them.
75 @style{wxHD_ALLOW_HIDE}
76 If this style is specified, the control shows a popup menu allowing the
77 user to change the columns visibility on right mouse click. Notice that
78 the program can always hide or show the columns, this style only
79 affects the users capability to do it.
80 @style{wxHD_DEFAULT_STYLE}
81 Symbolic name for the default control style, currently equal to
82 @c wxHD_ALLOW_REORDER.
83 @endStyleTable
84
85 @beginEventEmissionTable{wxHeaderCtrlEvent}
86 @event{EVT_HEADER_CLICK(id, func)}
87 A column heading was clicked.
88 @event{EVT_HEADER_RIGHT_CLICK(id, func)}
89 A column heading was right clicked.
90 @event{EVT_HEADER_MIDDLE_CLICK(id, func)}
91 A column heading was clicked with the middle mouse button.
92 @event{EVT_HEADER_DCLICK(id, func)}
93 A column heading was double clicked.
94 @event{EVT_HEADER_RIGHT_DCLICK(id, func)}
95 A column heading was right double clicked.
96 @event{EVT_HEADER_MIDDLE_DCLICK(id, func)}
97 A column heading was double clicked with the middle mouse button.
98 @event{EVT_HEADER_SEPARATOR_DCLICK(id, func)}
99 Separator to the right of the specified column was double clicked
100 (this action is commonly used to resize the column to fit its
101 contents width and the control provides UpdateColumnWidthToFit() method
102 to make implementing this easier).
103 @event{EVT_HEADER_BEGIN_RESIZE(id, func)}
104 The user started to drag the separator to the right of the column
105 with the specified index (this can only happen for the columns for
106 which wxHeaderColumn::IsResizeable() returns true). The event can
107 be vetoed to prevent the column from being resized. If it isn't,
108 the resizing and end resize (or dragging cancelled) events will be
109 generated later.
110 @event{EVT_HEADER_RESIZING(id, func)}
111 The user is dragging the column with the specified index resizing
112 it and its current width is wxHeaderCtrlEvent::GetWidth().
113 The event can be vetoed to stop the dragging operation completely at
114 any time.
115 @event{EVT_HEADER_END_RESIZE(id, func)}
116 The user stopped dragging the column by releasing the mouse.
117 The column should normally be resized to the value of
118 wxHeaderCtrlEvent::GetWidth().
119 @event{EVT_HEADER_BEGIN_REORDER(id, func)}
120 The user started to drag the column with the specified index (this
121 can only happen for the controls with wxHD_ALLOW_REORDER style).
122 This event can be vetoed to prevent the column from being reordered,
123 otherwise the end reorder message will be generated later.
124 @event{EVT_HEADER_END_REORDER(id, func)}
125 The user dropped the column in its new location. The event can be
126 vetoed to prevent the column from being placed at the new position
127 or handled to update the display of the data in the associated
128 control to match the new column location (available from
129 wxHeaderCtrlEvent::GetNewOrder()).
130 @event{EVT_HEADER_DRAGGING_CANCELLED(id, func)}
131 The resizing or reordering operation currently in progress was
132 cancelled. This can happen if the user pressed Esc key while
133 dragging the mouse or the mouse capture was lost for some other
134 reason. You only need to handle this event if your application
135 entered into some modal mode when resizing or reordering began, in
136 which case it should handle this event in addition to the matching
137 end resizing or reordering ones.
138 @endEventTable
139
140 @library{wxcore}
141 @category{ctrl}
142
143 @see wxGrid, wxListCtrl, wxDataViewCtrl
144 */
145 class wxHeaderCtrl : public wxControl
146 {
147 public:
148 /**
149 Default constructor not creating the underlying window.
150
151 You must use Create() after creating the object using this constructor.
152 */
153 wxHeaderCtrl();
154
155 /**
156 Constructor creating the window.
157
158 Please see Create() for the parameters documentation.
159 */
160 wxHeaderCtrl(wxWindow *parent,
161 wxWindowID winid = wxID_ANY,
162 const wxPoint& pos = wxDefaultPosition,
163 const wxSize& size = wxDefaultSize,
164 long style = wxHD_DEFAULT_STYLE,
165 const wxString& name = wxHeaderCtrlNameStr);
166
167 /**
168 Create the header control window.
169
170 @param parent
171 The parent window. The header control should be typically
172 positioned along the top edge of this window.
173 @param winid
174 Id of the control or @c wxID_ANY if you don't care.
175 @param pos
176 The initial position of the control.
177 @param size
178 The initial size of the control (usually not very useful as this
179 control will typically be resized to have the same width as the
180 associated data display control).
181 @param style
182 The control style, @c wxHD_DEFAULT_STYLE by default. Notice that
183 the default style allows the user to reorder the columns by
184 dragging them and you need to explicitly turn this feature off by
185 using @code wxHD_DEFAULT_STYLE & ~wxHD_ALLOW_REORDER @endcode if
186 this is undesirable.
187 @param name
188 The name of the control.
189 */
190 bool Create(wxWindow *parent,
191 wxWindowID winid = wxID_ANY,
192 const wxPoint& pos = wxDefaultPosition,
193 const wxSize& size = wxDefaultSize,
194 long style = wxHD_DEFAULT_STYLE,
195 const wxString& name = wxHeaderCtrlNameStr);
196
197 /**
198 Set the number of columns in the control.
199
200 The control will use GetColumn() to get information about all the
201 new columns and refresh itself, i.e. this method also has the same
202 effect as calling UpdateColumn() for all columns but it should only be
203 used if the number of columns really changed.
204 */
205 void SetColumnCount(unsigned int count);
206
207 /**
208 Return the number of columns in the control.
209
210 @return
211 Number of columns as previously set by SetColumnCount().
212
213 @see IsEmpty()
214 */
215 unsigned int GetColumnCount() const;
216
217 /**
218 Return whether the control has any columns.
219
220 @see GetColumnCount()
221 */
222 bool IsEmpty() const;
223
224 /**
225 Update the column with the given index.
226
227 When the value returned by GetColumn() changes, this method must be
228 called to notify the control about the change and update the visual
229 display to match the new column data.
230
231 @param idx
232 The column index, must be less than GetColumnCount().
233 */
234 void UpdateColumn(unsigned int idx);
235
236 /**
237 Change the columns display order.
238
239 The display order defines the order in which the columns appear on the
240 screen and does @em not affect the interpretation of indices by all the
241 other class methods.
242
243 The @a order array specifies the column indices corresponding to the
244 display positions.
245
246 @param order
247 A permutation of all column indices, i.e. an array of size
248 GetColumnsOrder() containing all column indices exactly once. The
249 n-th element of this array defines the index of the column shown at
250 the n-th position from left (for the default left-to-right writing
251 direction).
252
253 @see wxListCtrl::SetColumnsOrder()
254 */
255 void SetColumnsOrder(const wxArrayInt& order);
256
257 /**
258 Return the array describing the columns display order.
259
260 For the controls without wxHD_ALLOW_REORDER style the returned array
261 will be the same as was passed to SetColumnsOrder() previously or
262 define the default order (with n-th element being n) if it hadn't been
263 called. But for the controls with wxHD_ALLOW_REORDER style, the columns
264 can be also reordered by user.
265 */
266 wxArrayInt GetColumnsOrder() const;
267
268 /**
269 Return the index of the column displayed at the given position.
270
271 @param pos
272 The display position, e.g. 0 for the left-most column, 1 for the
273 next one and so on until GetColumnCount() - 1.
274
275 @see GetColumnPos()
276 */
277 unsigned int GetColumnAt(unsigned int pos) const;
278
279 /**
280 Get the position at which this column is currently displayed.
281
282 Notice that a valid position is returned even for the hidden columns
283 currently.
284
285 @param idx
286 The column index, must be less than GetColumnCount().
287
288 @see GetColumnAt()
289 */
290 unsigned int GetColumnPos(unsigned int idx) const;
291
292 /**
293 Reset the columns order to the natural one.
294
295 After calling this function, the column with index @c idx appears at
296 position @c idx in the control.
297 */
298 void ResetColumnsOrder();
299
300 /**
301 Helper function to manipulate the array of column indices.
302
303 This function reshuffles the array of column indices indexed by
304 positions (i.e. using the same convention as for SetColumnsOrder()) so
305 that the column with the given index is found at the specified
306 position.
307
308 @param order
309 Array containing the indices of columns in order of their
310 positions.
311 @param idx
312 The index of the column to move.
313 @param pos
314 The new position for the column @a idx.
315 */
316 static void MoveColumnInOrderArray(wxArrayInt& order,
317 unsigned int idx,
318 unsigned int pos);
319
320 /**
321 Show the popup menu allowing the user to show or hide the columns.
322
323 This functions shows the popup menu containing all columns with check
324 marks for the ones which are currently shown and allows the user to
325 check or uncheck them to toggle their visibility. It is called from the
326 default EVT_HEADER_RIGHT_CLICK handler for the controls which have
327 wxHD_ALLOW_HIDE style. And if the column has wxHD_ALLOW_REORDER style
328 as well, the menu also contains an item to customize the columns shown
329 using which results in ShowCustomizeDialog() being called, please see
330 its description for more details.
331
332 If a column was toggled, UpdateColumnVisibility() virtual function is
333 called so it must be implemented for the controls with wxHD_ALLOW_HIDE
334 style or if you call this function explicitly.
335
336 @param pt
337 The position of the menu, in the header window coordinates.
338 @param title
339 The title for the menu if not empty.
340 @return
341 @true if a column was shown or hidden or @false if nothing was
342 done, e.g. because the menu was cancelled.
343 */
344 bool ShowColumnsMenu(const wxPoint& pt, const wxString& title = wxString());
345
346 /**
347 Helper function appending the checkable items corresponding to all the
348 columns to the given menu.
349
350 This function is used by ShowColumnsMenu() but can also be used if you
351 show your own custom columns menu and still want all the columns shown
352 in it. It appends menu items with column labels as their text and
353 consecutive ids starting from @a idColumnsBase to the menu and checks
354 the items corresponding to the currently visible columns.
355
356 Example of use:
357 @code
358 wxMenu menu;
359 menu.Append(100, "Some custom command");
360 menu.AppendSeparator();
361 AddColumnsItems(menu, 200);
362 const int rc = GetPopupMenuSelectionFromUser(menu, pt);
363 if ( rc >= 200 )
364 ... toggle visibility of the column rc-200 ...
365 @endcode
366
367 @param menu
368 The menu to append the items to. It may be currently empty or not.
369 @param idColumnsBase
370 The id for the menu item corresponding to the first column, the
371 other ones are consecutive starting from it. It should be positive.
372 */
373 void AddColumnsItems(wxMenu& menu, int idColumnsBase = 0);
374
375 /**
376 Show the column customization dialog.
377
378 This function displays a modal dialog containing the list of all
379 columns which the user can use to reorder them as well as show or hide
380 individual columns.
381
382 If the user accepts the changes done in the dialog, the virtual
383 methods UpdateColumnVisibility() and UpdateColumnsOrder() will be
384 called so they must be overridden in the derived class if this method
385 is ever called. Please notice that the user will be able to invoke it
386 interactively from the header popup menu if the control has both
387 wxHD_ALLOW_HIDE and wxHD_ALLOW_REORDER styles.
388
389 @see wxRearrangeDialog
390 */
391 bool ShowCustomizeDialog();
392
393 /**
394 Returns width needed for given column's title.
395
396 @since 2.9.4
397 */
398 int GetColumnTitleWidth(const wxHeaderColumn& col);
399
400 protected:
401 /**
402 Method to be implemented by the derived classes to return the
403 information for the given column.
404
405 @param idx
406 The column index, between 0 and the value last passed to
407 SetColumnCount().
408 */
409 virtual const wxHeaderColumn& GetColumn(unsigned int idx) const = 0;
410
411 /**
412 Method called when the column visibility is changed by the user.
413
414 This method is called from ShowColumnsMenu() or ShowCustomizeDialog()
415 when the user interactively hides or shows a column. A typical
416 implementation will simply update the internally stored column state.
417 Notice that there is no need to call UpdateColumn() from this method as
418 it is already done by wxHeaderCtrl itself.
419
420 The base class version doesn't do anything and must be overridden if
421 this method is called.
422
423 @param idx
424 The index of the column whose visibility was toggled.
425 @param show
426 The new visibility value, @true if the column is now shown or
427 @false if it is not hidden.
428 */
429 virtual void UpdateColumnVisibility(unsigned int idx, bool show);
430
431 /**
432 Method called when the columns order is changed in the customization
433 dialog.
434
435 This method is only called from ShowCustomizeDialog() when the user
436 changes the order of columns. In particular it is @em not called if a
437 single column changes place because the user dragged it to the new
438 location, the EVT_HEADER_END_REORDER event handler should be used to
439 react to this.
440
441 A typical implementation in a derived class will update the display
442 order of the columns in the associated control, if any. Notice that
443 there is no need to call SetColumnsOrder() from it as wxHeaderCtrl does
444 it itself.
445
446 The base class version doesn't do anything and must be overridden if
447 this method is called.
448
449 @param order
450 The new column order. This array uses the same convention as
451 SetColumnsOrder().
452 */
453 virtual void UpdateColumnsOrder(const wxArrayInt& order);
454
455 /**
456 Method which may be implemented by the derived classes to allow double
457 clicking the column separator to resize the column to fit its contents.
458
459 When a separator is double clicked, the default handler of
460 EVT_HEADER_SEPARATOR_DCLICK event calls this function and refreshes the
461 column if it returns @true so to implement the resizing of the column
462 to fit its width on header double click you need to implement this
463 method using logic similar to this example:
464 @code
465 class MyHeaderColumn : public wxHeaderColumn
466 {
467 public:
468 ...
469
470 void SetWidth(int width) { m_width = width; }
471 virtual int GetWidth() const { return m_width; }
472
473 private:
474 int m_width;
475 };
476
477 class MyHeaderCtrl : public wxHeaderCtrl
478 {
479 public:
480 protected:
481 virtual wxHeaderColumn& GetColumn(unsigned int idx) const
482 {
483 return m_cols[idx];
484 }
485
486 virtual bool UpdateColumnWidthToFit(unsigned int idx, int widthTitle)
487 {
488 int widthContents = ... compute minimal width for column idx ...
489 m_cols[idx].SetWidth(wxMax(widthContents, widthTitle));
490 return true;
491 }
492
493 wxVector<MyHeaderColumn> m_cols;
494 };
495 @endcode
496
497 Base class version simply returns @false.
498
499 @param idx
500 The zero-based index of the column to update.
501 @param widthTitle
502 Contains minimal width needed to display the column header itself
503 and will usually be used as a starting point for the fitting width
504 calculation.
505
506 @return
507 @true to indicate that the column was resized, i.e. GetColumn() now
508 returns the new width value, and so must be refreshed or @false
509 meaning that the control didn't reach to the separator double click.
510 */
511 virtual bool UpdateColumnWidthToFit(unsigned int idx, int widthTitle);
512
513 /**
514 Can be overridden in the derived class to update internal data
515 structures when the number of the columns in the control changes.
516
517 This method is called by SetColumnCount() before effectively changing
518 the number of columns.
519
520 The base class version does nothing but it is good practice to still
521 call it from the overridden version in the derived class.
522 */
523 virtual void OnColumnCountChanging(unsigned int count);
524 };
525
526
527 /**
528 @class wxHeaderCtrlSimple
529
530 wxHeaderCtrlSimple is a concrete header control which can be used directly,
531 without inheriting from it as you need to do when using wxHeaderCtrl
532 itself.
533
534 When using it, you need to use simple AppendColumn(), InsertColumn() and
535 DeleteColumn() methods instead of setting the number of columns with
536 SetColumnCount() and returning the information about them from the
537 overridden GetColumn().
538
539 @library{wxcore}
540 @category{ctrl}
541
542 @see wxHeaderCtrl
543 */
544 class wxHeaderCtrlSimple : public wxHeaderCtrl
545 {
546 public:
547 /**
548 Default constructor not creating the underlying window.
549
550 You must use Create() after creating the object using this constructor.
551 */
552 wxHeaderCtrlSimple();
553
554 /**
555 Constructor creating the window.
556
557 Please see the base class wxHeaderCtrl::Create() method for the
558 parameters description.
559 */
560 wxHeaderCtrlSimple(wxWindow *parent,
561 wxWindowID winid = wxID_ANY,
562 const wxPoint& pos = wxDefaultPosition,
563 const wxSize& size = wxDefaultSize,
564 long style = wxHD_DEFAULT_STYLE,
565 const wxString& name = wxHeaderCtrlNameStr);
566
567 /**
568 Insert the column at the given position.
569
570 @param col
571 The column to insert. Notice that because of the existence of
572 implicit conversion from wxString to wxHeaderColumn a string
573 can be passed directly here.
574 @param idx
575 The position of the new column, from 0 to GetColumnCount(). Using
576 GetColumnCount() means to append the column to the end.
577
578 @see AppendColumn()
579 */
580 void InsertColumn(const wxHeaderColumnSimple& col, unsigned int idx);
581
582 /**
583 Append the column to the end of the control.
584
585 @see InsertColumn()
586 */
587 void AppendColumn(const wxHeaderColumnSimple& col);
588
589 /**
590 Delete the column at the given position.
591
592 @see InsertColumn(), AppendColumn()
593 */
594 void DeleteColumn(unsigned int idx);
595
596 /**
597 Show or hide the column.
598
599 Initially the column is shown by default or hidden if it was added with
600 wxCOL_HIDDEN flag set.
601
602 When a column is hidden, it doesn't appear at all on the screen but its
603 index is still taken into account when working with other columns. E.g.
604 if there are three columns 0, 1 and 2 and the column 1 is hidden you
605 still need to use index 2 to refer to the last visible column.
606
607 @param idx
608 The index of the column to show or hide, from 0 to GetColumnCount().
609 @param show
610 Indicates whether the column should be shown (default) or hidden.
611 */
612 void ShowColumn(unsigned int idx, bool show = true);
613
614 /**
615 Hide the column with the given index.
616
617 This is the same as calling @code ShowColumn(idx, false) @endcode.
618
619 @param idx
620 The index of the column to show or hide, from 0 to GetColumnCount().
621 */
622 void HideColumn(unsigned int idx);
623
624 /**
625 Update the column sort indicator.
626
627 The sort indicator, if shown, is typically an arrow pointing upwards or
628 downwards depending on whether the control contents is sorted in
629 ascending or descending order.
630
631 @param idx
632 The column to set the sort indicator for.
633 If @c -1 is given, then the currently shown sort indicator
634 will be removed.
635 @param sortOrder
636 If @true or @false show the sort indicator corresponding to
637 ascending or descending sort order respectively.
638 */
639 void ShowSortIndicator(unsigned int idx, bool sortOrder = true);
640
641 /**
642 Remove the sort indicator from the column being used as sort key.
643
644 @see ShowSortIndicator
645 */
646 void RemoveSortIndicator();
647
648 protected:
649 /**
650 This function can be overridden in the classes deriving from this
651 control instead of overriding UpdateColumnWidthToFit().
652
653 To implement automatic column resizing to fit its contents width when
654 the column divider is double clicked, you need to simply return the
655 fitting width for the given column @a idx from this method, the control
656 will automatically use the biggest value between the one returned from
657 here and the one needed for the display of the column title itself.
658
659 The base class version returns -1 indicating that this function is not
660 implemented.
661 */
662 virtual int GetBestFittingWidth(unsigned int idx) const;
663 };
664
665 /**
666 @class wxHeaderCtrlEvent
667
668 Event class representing the events generated by wxHeaderCtrl.
669
670 @library{wxcore}
671 @category{events}
672
673 @see wxHeaderCtrl
674 */
675 class wxHeaderCtrlEvent : public wxNotifyEvent
676 {
677 public:
678 wxHeaderCtrlEvent(wxEventType commandType = wxEVT_NULL, int winid = 0);
679 wxHeaderCtrlEvent(const wxHeaderCtrlEvent& event);
680
681 /**
682 Return the index of the column affected by this event.
683
684 This method can be called for all header control events.
685 */
686 int GetColumn() const;
687 void SetColumn(int col);
688
689 /**
690 Return the current width of the column.
691
692 This method can only be called for the dragging events.
693 */
694 int GetWidth() const;
695 void SetWidth(int width);
696
697 /**
698 Return the new order of the column.
699
700 This method can only be called for a reorder event for which it
701 indicates the tentative new position for the column GetColumn()
702 selected by the user. If the event is not vetoed, this will become the
703 new column position in wxHeaderCtrl::GetColumnsOrder().
704 */
705 unsigned int GetNewOrder() const;
706 void SetNewOrder(unsigned int order);
707 };
708
709
710
711 wxEventType wxEVT_HEADER_CLICK;
712 wxEventType wxEVT_HEADER_RIGHT_CLICK;
713 wxEventType wxEVT_HEADER_MIDDLE_CLICK;
714 wxEventType wxEVT_HEADER_DCLICK;
715 wxEventType wxEVT_HEADER_RIGHT_DCLICK;
716 wxEventType wxEVT_HEADER_MIDDLE_DCLICK;
717 wxEventType wxEVT_HEADER_SEPARATOR_DCLICK;
718 wxEventType wxEVT_HEADER_BEGIN_RESIZE;
719 wxEventType wxEVT_HEADER_RESIZING;
720 wxEventType wxEVT_HEADER_END_RESIZE;
721 wxEventType wxEVT_HEADER_BEGIN_REORDER;
722 wxEventType wxEVT_HEADER_END_REORDER;
723 wxEventType wxEVT_HEADER_DRAGGING_CANCELLED;