232 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			232 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| ///////////////////////////////////////////////////////////////////////////////
 | |
| // Name:        wx/compositewin.h
 | |
| // Purpose:     wxCompositeWindow<> declaration
 | |
| // Author:      Vadim Zeitlin
 | |
| // Created:     2011-01-02
 | |
| // Copyright:   (c) 2011 Vadim Zeitlin <vadim@wxwidgets.org>
 | |
| // Licence:     wxWindows licence
 | |
| ///////////////////////////////////////////////////////////////////////////////
 | |
| 
 | |
| #ifndef _WX_COMPOSITEWIN_H_
 | |
| #define _WX_COMPOSITEWIN_H_
 | |
| 
 | |
| #include "wx/window.h"
 | |
| #include "wx/containr.h"
 | |
| 
 | |
| class WXDLLIMPEXP_FWD_CORE wxToolTip;
 | |
| 
 | |
| // NB: This is an experimental and, as for now, undocumented class used only by
 | |
| //     wxWidgets itself internally. Don't use it in your code until its API is
 | |
| //     officially stabilized unless you are ready to change it with the next
 | |
| //     wxWidgets release.
 | |
| 
 | |
| // ----------------------------------------------------------------------------
 | |
| // wxCompositeWindow is a helper for implementing composite windows: to define
 | |
| // a class using subwindows, simply inherit from it specialized with the real
 | |
| // base class name and implement GetCompositeWindowParts() pure virtual method.
 | |
| // ----------------------------------------------------------------------------
 | |
| 
 | |
| // The template parameter W must be a wxWindow-derived class.
 | |
| template <class W>
 | |
| class wxCompositeWindow : public W
 | |
| {
 | |
| public:
 | |
|     typedef W BaseWindowClass;
 | |
| 
 | |
|     // Default ctor doesn't do anything.
 | |
|     wxCompositeWindow()
 | |
|     {
 | |
|         this->Connect
 | |
|               (
 | |
|                   wxEVT_CREATE,
 | |
|                   wxWindowCreateEventHandler(wxCompositeWindow::OnWindowCreate)
 | |
|               );
 | |
| 
 | |
|     }
 | |
| 
 | |
|     // Override all wxWindow methods which must be forwarded to the composite
 | |
|     // window parts.
 | |
| 
 | |
|     // Attribute setters group.
 | |
|     //
 | |
|     // NB: Unfortunately we can't factor out the call for the setter itself
 | |
|     //     into DoSetForAllParts() because we can't call the function passed to
 | |
|     //     it non-virtually and we need to do this to avoid infinite recursion,
 | |
|     //     so we work around this by calling the method of this object itself
 | |
|     //     manually in each function.
 | |
|     virtual bool SetForegroundColour(const wxColour& colour) wxOVERRIDE
 | |
|     {
 | |
|         if ( !BaseWindowClass::SetForegroundColour(colour) )
 | |
|             return false;
 | |
| 
 | |
|         SetForAllParts(&wxWindowBase::SetForegroundColour, colour);
 | |
| 
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     virtual bool SetBackgroundColour(const wxColour& colour) wxOVERRIDE
 | |
|     {
 | |
|         if ( !BaseWindowClass::SetBackgroundColour(colour) )
 | |
|             return false;
 | |
| 
 | |
|         SetForAllParts(&wxWindowBase::SetBackgroundColour, colour);
 | |
| 
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     virtual bool SetFont(const wxFont& font) wxOVERRIDE
 | |
|     {
 | |
|         if ( !BaseWindowClass::SetFont(font) )
 | |
|             return false;
 | |
| 
 | |
|         SetForAllParts(&wxWindowBase::SetFont, font);
 | |
| 
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     virtual bool SetCursor(const wxCursor& cursor) wxOVERRIDE
 | |
|     {
 | |
|         if ( !BaseWindowClass::SetCursor(cursor) )
 | |
|             return false;
 | |
| 
 | |
|         SetForAllParts(&wxWindowBase::SetCursor, cursor);
 | |
| 
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     virtual void SetLayoutDirection(wxLayoutDirection dir) wxOVERRIDE
 | |
|     {
 | |
|         BaseWindowClass::SetLayoutDirection(dir);
 | |
| 
 | |
|         SetForAllParts(&wxWindowBase::SetLayoutDirection, dir);
 | |
| 
 | |
|         // The child layout almost invariably depends on the layout direction,
 | |
|         // so redo it when it changes.
 | |
|         //
 | |
|         // However avoid doing it when we're called from wxWindow::Create() in
 | |
|         // wxGTK as the derived window is not fully created yet and calling its
 | |
|         // SetSize() may be unexpected. This does mean that any future calls to
 | |
|         // SetLayoutDirection(wxLayout_Default) wouldn't result in a re-layout
 | |
|         // neither, but then we're not supposed to be called with it at all.
 | |
|         if ( dir != wxLayout_Default )
 | |
|             this->SetSize(-1, -1, -1, -1, wxSIZE_AUTO | wxSIZE_FORCE);
 | |
|     }
 | |
| 
 | |
| #if wxUSE_TOOLTIPS
 | |
|     virtual void DoSetToolTipText(const wxString &tip) wxOVERRIDE
 | |
|     {
 | |
|         BaseWindowClass::DoSetToolTipText(tip);
 | |
| 
 | |
|         // Use a variable to disambiguate between SetToolTip() overloads.
 | |
|         void (wxWindowBase::*func)(const wxString&) = &wxWindowBase::SetToolTip;
 | |
| 
 | |
|         SetForAllParts(func, tip);
 | |
|     }
 | |
| 
 | |
|     virtual void DoSetToolTip(wxToolTip *tip) wxOVERRIDE
 | |
|     {
 | |
|         BaseWindowClass::DoSetToolTip(tip);
 | |
| 
 | |
|         SetForAllParts(&wxWindowBase::CopyToolTip, tip);
 | |
|     }
 | |
| #endif // wxUSE_TOOLTIPS
 | |
| 
 | |
|     virtual void SetFocus() wxOVERRIDE
 | |
|     {
 | |
|         wxSetFocusToChild(this, NULL);
 | |
|     }
 | |
| 
 | |
| private:
 | |
|     // Must be implemented by the derived class to return all children to which
 | |
|     // the public methods we override should forward to.
 | |
|     virtual wxWindowList GetCompositeWindowParts() const = 0;
 | |
| 
 | |
|     void OnWindowCreate(wxWindowCreateEvent& event)
 | |
|     {
 | |
|         event.Skip();
 | |
| 
 | |
|         // Attach a few event handlers to all parts of the composite window.
 | |
|         // This makes the composite window behave more like a simple control
 | |
|         // and allows other code (such as wxDataViewCtrl's inline editing
 | |
|         // support) to hook into its event processing.
 | |
| 
 | |
|         wxWindow *child = event.GetWindow();
 | |
|         if ( child == this )
 | |
|             return; // not a child, we don't want to Connect() to ourselves
 | |
| 
 | |
|         // Always capture wxEVT_KILL_FOCUS:
 | |
|         child->Connect(wxEVT_KILL_FOCUS,
 | |
|                        wxFocusEventHandler(wxCompositeWindow::OnKillFocus),
 | |
|                        NULL, this);
 | |
| 
 | |
|         // Some events should be only handled for non-toplevel children. For
 | |
|         // example, we want to close the control in wxDataViewCtrl when Enter
 | |
|         // is pressed in the inline editor, but not when it's pressed in a
 | |
|         // popup dialog it opens.
 | |
|         wxWindow *win = child;
 | |
|         while ( win && win != this )
 | |
|         {
 | |
|             if ( win->IsTopLevel() )
 | |
|                 return;
 | |
|             win = win->GetParent();
 | |
|         }
 | |
| 
 | |
|         child->Connect(wxEVT_CHAR,
 | |
|                        wxKeyEventHandler(wxCompositeWindow::OnChar),
 | |
|                        NULL, this);
 | |
|     }
 | |
| 
 | |
|     void OnChar(wxKeyEvent& event)
 | |
|     {
 | |
|         if ( !this->ProcessWindowEvent(event) )
 | |
|             event.Skip();
 | |
|     }
 | |
| 
 | |
|     void OnKillFocus(wxFocusEvent& event)
 | |
|     {
 | |
|         // Ignore focus changes within the composite control:
 | |
|         wxWindow *win = event.GetWindow();
 | |
|         while ( win )
 | |
|         {
 | |
|             if ( win == this )
 | |
|             {
 | |
|                 event.Skip();
 | |
|                 return;
 | |
|             }
 | |
| 
 | |
|             // Note that we don't use IsTopLevel() check here, because we do
 | |
|             // want to ignore focus changes going to toplevel window that have
 | |
|             // the composite control as its parent; these would typically be
 | |
|             // some kind of control's popup window.
 | |
|             win = win->GetParent();
 | |
|         }
 | |
| 
 | |
|         // The event shouldn't be ignored, forward it to the main control:
 | |
|         if ( !this->ProcessWindowEvent(event) )
 | |
|             event.Skip();
 | |
|     }
 | |
| 
 | |
|     template <class T, class TArg, class R>
 | |
|     void SetForAllParts(R (wxWindowBase::*func)(TArg), T arg)
 | |
|     {
 | |
|         // Simply call the setters for all parts of this composite window.
 | |
|         const wxWindowList parts = GetCompositeWindowParts();
 | |
|         for ( wxWindowList::const_iterator i = parts.begin();
 | |
|               i != parts.end();
 | |
|               ++i )
 | |
|         {
 | |
|             wxWindow * const child = *i;
 | |
| 
 | |
|             // Allow NULL elements in the list, this makes the code of derived
 | |
|             // composite controls which may have optionally shown children
 | |
|             // simpler and it doesn't cost us much here.
 | |
|             if ( child )
 | |
|                 (child->*func)(arg);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     wxDECLARE_NO_COPY_TEMPLATE_CLASS(wxCompositeWindow, W);
 | |
| };
 | |
| 
 | |
| #endif // _WX_COMPOSITEWIN_H_
 |