compositewin.h 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Name: wx/compositewin.h
  3. // Purpose: wxCompositeWindow<> declaration
  4. // Author: Vadim Zeitlin
  5. // Created: 2011-01-02
  6. // Copyright: (c) 2011 Vadim Zeitlin <vadim@wxwidgets.org>
  7. // Licence: wxWindows licence
  8. ///////////////////////////////////////////////////////////////////////////////
  9. #ifndef _WX_COMPOSITEWIN_H_
  10. #define _WX_COMPOSITEWIN_H_
  11. #include "wx/window.h"
  12. #include "wx/containr.h"
  13. class WXDLLIMPEXP_FWD_CORE wxToolTip;
  14. // NB: This is an experimental and, as for now, undocumented class used only by
  15. // wxWidgets itself internally. Don't use it in your code until its API is
  16. // officially stabilized unless you are ready to change it with the next
  17. // wxWidgets release.
  18. // ----------------------------------------------------------------------------
  19. // wxCompositeWindow is a helper for implementing composite windows: to define
  20. // a class using subwindows, simply inherit from it specialized with the real
  21. // base class name and implement GetCompositeWindowParts() pure virtual method.
  22. // ----------------------------------------------------------------------------
  23. // The template parameter W must be a wxWindow-derived class.
  24. template <class W>
  25. class wxCompositeWindow : public W
  26. {
  27. public:
  28. typedef W BaseWindowClass;
  29. // Default ctor doesn't do anything.
  30. wxCompositeWindow()
  31. {
  32. this->Connect
  33. (
  34. wxEVT_CREATE,
  35. wxWindowCreateEventHandler(wxCompositeWindow::OnWindowCreate)
  36. );
  37. }
  38. #ifndef __VISUALC6__
  39. // FIXME-VC6: This compiler can't compile DoSetForAllParts() template function,
  40. // it can't determine whether the deduced type should be "T" or "const T&". And
  41. // without this function wxCompositeWindow is pretty useless so simply disable
  42. // this code for it, this does mean that setting colours/fonts/... for
  43. // composite controls won't work in the library compiled with it but so far
  44. // this only affects the generic wxDatePickerCtrl which is not used by default
  45. // under MSW anyhow so it doesn't seem to be worth it to spend time and uglify
  46. // the code to fix it.
  47. // Override all wxWindow methods which must be forwarded to the composite
  48. // window parts.
  49. // Attribute setters group.
  50. //
  51. // NB: Unfortunately we can't factor out the call for the setter itself
  52. // into DoSetForAllParts() because we can't call the function passed to
  53. // it non-virtually and we need to do this to avoid infinite recursion,
  54. // so we work around this by calling the method of this object itself
  55. // manually in each function.
  56. virtual bool SetForegroundColour(const wxColour& colour)
  57. {
  58. if ( !BaseWindowClass::SetForegroundColour(colour) )
  59. return false;
  60. SetForAllParts(&wxWindowBase::SetForegroundColour, colour);
  61. return true;
  62. }
  63. virtual bool SetBackgroundColour(const wxColour& colour)
  64. {
  65. if ( !BaseWindowClass::SetBackgroundColour(colour) )
  66. return false;
  67. SetForAllParts(&wxWindowBase::SetBackgroundColour, colour);
  68. return true;
  69. }
  70. virtual bool SetFont(const wxFont& font)
  71. {
  72. if ( !BaseWindowClass::SetFont(font) )
  73. return false;
  74. SetForAllParts(&wxWindowBase::SetFont, font);
  75. return true;
  76. }
  77. virtual bool SetCursor(const wxCursor& cursor)
  78. {
  79. if ( !BaseWindowClass::SetCursor(cursor) )
  80. return false;
  81. SetForAllParts(&wxWindowBase::SetCursor, cursor);
  82. return true;
  83. }
  84. #if wxUSE_TOOLTIPS
  85. virtual void DoSetToolTip(wxToolTip *tip)
  86. {
  87. BaseWindowClass::DoSetToolTip(tip);
  88. SetForAllParts(&wxWindowBase::CopyToolTip, tip);
  89. }
  90. #endif // wxUSE_TOOLTIPS
  91. #endif // !__VISUALC6__
  92. virtual void SetFocus()
  93. {
  94. wxSetFocusToChild(this, NULL);
  95. }
  96. private:
  97. // Must be implemented by the derived class to return all children to which
  98. // the public methods we override should forward to.
  99. virtual wxWindowList GetCompositeWindowParts() const = 0;
  100. void OnWindowCreate(wxWindowCreateEvent& event)
  101. {
  102. event.Skip();
  103. // Attach a few event handlers to all parts of the composite window.
  104. // This makes the composite window behave more like a simple control
  105. // and allows other code (such as wxDataViewCtrl's inline editing
  106. // support) to hook into its event processing.
  107. wxWindow *child = event.GetWindow();
  108. if ( child == this )
  109. return; // not a child, we don't want to Connect() to ourselves
  110. // Always capture wxEVT_KILL_FOCUS:
  111. child->Connect(wxEVT_KILL_FOCUS,
  112. wxFocusEventHandler(wxCompositeWindow::OnKillFocus),
  113. NULL, this);
  114. // Some events should be only handled for non-toplevel children. For
  115. // example, we want to close the control in wxDataViewCtrl when Enter
  116. // is pressed in the inline editor, but not when it's pressed in a
  117. // popup dialog it opens.
  118. wxWindow *win = child;
  119. while ( win && win != this )
  120. {
  121. if ( win->IsTopLevel() )
  122. return;
  123. win = win->GetParent();
  124. }
  125. child->Connect(wxEVT_CHAR,
  126. wxKeyEventHandler(wxCompositeWindow::OnChar),
  127. NULL, this);
  128. }
  129. void OnChar(wxKeyEvent& event)
  130. {
  131. if ( !this->ProcessWindowEvent(event) )
  132. event.Skip();
  133. }
  134. void OnKillFocus(wxFocusEvent& event)
  135. {
  136. // Ignore focus changes within the composite control:
  137. wxWindow *win = event.GetWindow();
  138. while ( win )
  139. {
  140. if ( win == this )
  141. {
  142. event.Skip();
  143. return;
  144. }
  145. // Note that we don't use IsTopLevel() check here, because we do
  146. // want to ignore focus changes going to toplevel window that have
  147. // the composite control as its parent; these would typically be
  148. // some kind of control's popup window.
  149. win = win->GetParent();
  150. }
  151. // The event shouldn't be ignored, forward it to the main control:
  152. if ( !this->ProcessWindowEvent(event) )
  153. event.Skip();
  154. }
  155. #ifndef __VISUALC6__
  156. template <class T>
  157. void SetForAllParts(bool (wxWindowBase::*func)(const T&), const T& arg)
  158. {
  159. DoSetForAllParts<const T&>(func, arg);
  160. }
  161. template <class T>
  162. void SetForAllParts(bool (wxWindowBase::*func)(T*), T* arg)
  163. {
  164. DoSetForAllParts<T*>(func, arg);
  165. }
  166. template <class T>
  167. void DoSetForAllParts(bool (wxWindowBase::*func)(T), T arg)
  168. {
  169. // Simply call the setters for all parts of this composite window.
  170. const wxWindowList parts = GetCompositeWindowParts();
  171. for ( wxWindowList::const_iterator i = parts.begin();
  172. i != parts.end();
  173. ++i )
  174. {
  175. wxWindow * const child = *i;
  176. // Allow NULL elements in the list, this makes the code of derived
  177. // composite controls which may have optionally shown children
  178. // simpler and it doesn't cost us much here.
  179. if ( child )
  180. (child->*func)(arg);
  181. }
  182. }
  183. #endif // !__VISUALC6__
  184. wxDECLARE_NO_COPY_TEMPLATE_CLASS(wxCompositeWindow, W);
  185. };
  186. #endif // _WX_COMPOSITEWIN_H_