home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2233.zip / wxOS2-2_3_3.zip / wxWindows-2.3.3 / src / common / wincmn.cpp < prev    next >
C/C++ Source or Header  |  2002-08-30  |  58KB  |  2,027 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        common/window.cpp
  3. // Purpose:     common (to all ports) wxWindow functions
  4. // Author:      Julian Smart, Vadim Zeitlin
  5. // Modified by:
  6. // Created:     13/07/98
  7. // RCS-ID:      $Id: wincmn.cpp,v 1.123 2002/08/30 13:44:03 DW Exp $
  8. // Copyright:   (c) wxWindows team
  9. // Licence:     wxWindows license
  10. /////////////////////////////////////////////////////////////////////////////
  11.  
  12. // ============================================================================
  13. // declarations
  14. // ============================================================================
  15.  
  16. // ----------------------------------------------------------------------------
  17. // headers
  18. // ----------------------------------------------------------------------------
  19.  
  20. #ifdef __GNUG__
  21.     #pragma implementation "windowbase.h"
  22. #endif
  23.  
  24. // For compilers that support precompilation, includes "wx.h".
  25. #include "wx/wxprec.h"
  26.  
  27. #ifdef __BORLANDC__
  28.     #pragma hdrstop
  29. #endif
  30.  
  31. #ifndef WX_PRECOMP
  32.     #include "wx/string.h"
  33.     #include "wx/log.h"
  34.     #include "wx/intl.h"
  35.     #include "wx/frame.h"
  36.     #include "wx/defs.h"
  37.     #include "wx/window.h"
  38.     #include "wx/control.h"
  39.     #include "wx/checkbox.h"
  40.     #include "wx/radiobut.h"
  41.     #include "wx/textctrl.h"
  42.     #include "wx/settings.h"
  43.     #include "wx/dialog.h"
  44.     #include "wx/msgdlg.h"
  45.     #include "wx/statusbr.h"
  46. #endif //WX_PRECOMP
  47.  
  48. #if wxUSE_CONSTRAINTS
  49.     #include "wx/layout.h"
  50. #endif // wxUSE_CONSTRAINTS
  51.  
  52. #include "wx/sizer.h"
  53.  
  54. #if wxUSE_DRAG_AND_DROP
  55.     #include "wx/dnd.h"
  56. #endif // wxUSE_DRAG_AND_DROP
  57.  
  58. #if wxUSE_HELP
  59.     #include "wx/cshelp.h"
  60. #endif // wxUSE_HELP
  61.  
  62. #if wxUSE_TOOLTIPS
  63.     #include "wx/tooltip.h"
  64. #endif // wxUSE_TOOLTIPS
  65.  
  66. #if wxUSE_CARET
  67.     #include "wx/caret.h"
  68. #endif // wxUSE_CARET
  69.  
  70. // ----------------------------------------------------------------------------
  71. // static data
  72. // ----------------------------------------------------------------------------
  73.  
  74. #if defined(__WXPM__)
  75. int wxWindowBase::ms_lastControlId = 2000;
  76. #else
  77. int wxWindowBase::ms_lastControlId = -200;
  78. #endif
  79.  
  80. IMPLEMENT_ABSTRACT_CLASS(wxWindowBase, wxEvtHandler)
  81.  
  82. // ----------------------------------------------------------------------------
  83. // event table
  84. // ----------------------------------------------------------------------------
  85.  
  86. BEGIN_EVENT_TABLE(wxWindowBase, wxEvtHandler)
  87.     EVT_SYS_COLOUR_CHANGED(wxWindowBase::OnSysColourChanged)
  88.     EVT_INIT_DIALOG(wxWindowBase::OnInitDialog)
  89.     EVT_MIDDLE_DOWN(wxWindowBase::OnMiddleClick)
  90.  
  91. #if wxUSE_HELP
  92.     EVT_HELP(-1, wxWindowBase::OnHelp)
  93. #endif // wxUSE_HELP
  94.  
  95. END_EVENT_TABLE()
  96.  
  97. // ============================================================================
  98. // implementation of the common functionality of the wxWindow class
  99. // ============================================================================
  100.  
  101. // ----------------------------------------------------------------------------
  102. // initialization
  103. // ----------------------------------------------------------------------------
  104.  
  105. // the default initialization
  106. void wxWindowBase::InitBase()
  107. {
  108.     // no window yet, no parent nor children
  109.     m_parent = (wxWindow *)NULL;
  110.     m_windowId = -1;
  111.     m_children.DeleteContents( FALSE ); // don't auto delete node data
  112.  
  113.     // no constraints on the minimal window size
  114.     m_minWidth =
  115.     m_minHeight =
  116.     m_maxWidth =
  117.     m_maxHeight = -1;
  118.  
  119.     // window is created enabled but it's not visible yet
  120.     m_isShown = FALSE;
  121.     m_isEnabled = TRUE;
  122.  
  123.     // the default event handler is just this window
  124.     m_eventHandler = this;
  125.  
  126. #if wxUSE_VALIDATORS
  127.     // no validator
  128.     m_windowValidator = (wxValidator *) NULL;
  129. #endif // wxUSE_VALIDATORS
  130.  
  131.     // use the system default colours
  132.     m_backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE);
  133.     m_foregroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
  134.  
  135.     // don't set the font here for wxMSW as we don't call WM_SETFONT here and
  136.     // so the font is *not* really set - but calls to SetFont() later won't do
  137.     // anything because m_font appears to be already set!
  138. #ifndef __WXMSW__
  139.     m_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
  140. #endif // __WXMSW__
  141.  
  142.     // the colours/fonts are default for now
  143.     m_hasBgCol =
  144.     m_hasFgCol =
  145.     m_hasFont = FALSE;
  146.  
  147.     // no style bits
  148.     m_exStyle =
  149.     m_windowStyle = 0;
  150.  
  151.     // an optimization for the event processing: checking this flag is much
  152.     // faster than using IsKindOf(CLASSINFO(wxWindow))
  153.     m_isWindow = TRUE;
  154.  
  155. #if wxUSE_CONSTRAINTS
  156.     // no constraints whatsoever
  157.     m_constraints = (wxLayoutConstraints *) NULL;
  158.     m_constraintsInvolvedIn = (wxWindowList *) NULL;
  159. #endif // wxUSE_CONSTRAINTS
  160.  
  161.     m_windowSizer = (wxSizer *) NULL;
  162.     m_containingSizer = (wxSizer *) NULL;
  163.     m_autoLayout = FALSE;
  164.  
  165. #if wxUSE_DRAG_AND_DROP
  166.     m_dropTarget = (wxDropTarget *)NULL;
  167. #endif // wxUSE_DRAG_AND_DROP
  168.  
  169. #if wxUSE_TOOLTIPS
  170.     m_tooltip = (wxToolTip *)NULL;
  171. #endif // wxUSE_TOOLTIPS
  172.  
  173. #if wxUSE_CARET
  174.     m_caret = (wxCaret *)NULL;
  175. #endif // wxUSE_CARET
  176.  
  177. #if wxUSE_PALETTE
  178.     m_hasCustomPalette = FALSE;
  179. #endif // wxUSE_PALETTE
  180.  
  181.     m_virtualSize = wxDefaultSize;
  182.  
  183.     m_minVirtualWidth =
  184.     m_minVirtualHeight =
  185.     m_maxVirtualWidth =
  186.     m_maxVirtualHeight = -1;
  187.  
  188.     // Whether we're using the current theme for this window (wxGTK only for now)
  189.     m_themeEnabled = FALSE;
  190. }
  191.  
  192. // common part of window creation process
  193. bool wxWindowBase::CreateBase(wxWindowBase *parent,
  194.                               wxWindowID id,
  195.                               const wxPoint& WXUNUSED(pos),
  196.                               const wxSize& WXUNUSED(size),
  197.                               long style,
  198.                               const wxValidator& validator,
  199.                               const wxString& name)
  200. {
  201.     // m_isWindow is set to TRUE in wxWindowBase::Init() as well as many other
  202.     // member variables - check that it has been called (will catch the case
  203.     // when a new ctor is added which doesn't call InitWindow)
  204.     wxASSERT_MSG( m_isWindow, wxT("Init() must have been called before!") );
  205.  
  206.     // generate a new id if the user doesn't care about it
  207.     m_windowId = id == -1 ? NewControlId() : id;
  208.  
  209.     SetName(name);
  210.     SetWindowStyleFlag(style);
  211.     SetParent(parent);
  212.  
  213. #if wxUSE_VALIDATORS
  214.     SetValidator(validator);
  215. #endif // wxUSE_VALIDATORS
  216.  
  217.     // if the parent window has wxWS_EX_VALIDATE_RECURSIVELY set, we want to
  218.     // have it too - like this it's possible to set it only in the top level
  219.     // dialog/frame and all children will inherit it by defult
  220.     if ( parent && (parent->GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) )
  221.     {
  222.         SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY);
  223.     }
  224.  
  225.     return TRUE;
  226. }
  227.  
  228. // ----------------------------------------------------------------------------
  229. // destruction
  230. // ----------------------------------------------------------------------------
  231.  
  232. // common clean up
  233. wxWindowBase::~wxWindowBase()
  234. {
  235.     wxASSERT_MSG( GetCapture() != this, wxT("attempt to destroy window with mouse capture") );
  236.  
  237.     // FIXME if these 2 cases result from programming errors in the user code
  238.     //       we should probably assert here instead of silently fixing them
  239.  
  240.     // Just in case the window has been Closed, but we're then deleting
  241.     // immediately: don't leave dangling pointers.
  242.     wxPendingDelete.DeleteObject(this);
  243.  
  244.     // Just in case we've loaded a top-level window via LoadNativeDialog but
  245.     // we weren't a dialog class
  246.     wxTopLevelWindows.DeleteObject(this);
  247.  
  248.     wxASSERT_MSG( GetChildren().GetCount() == 0, wxT("children not destroyed") );
  249.  
  250. #if wxUSE_CARET
  251.     if ( m_caret )
  252.         delete m_caret;
  253. #endif // wxUSE_CARET
  254.  
  255. #if wxUSE_VALIDATORS
  256.     if ( m_windowValidator )
  257.         delete m_windowValidator;
  258. #endif // wxUSE_VALIDATORS
  259.  
  260. #if wxUSE_CONSTRAINTS
  261.     // Have to delete constraints/sizer FIRST otherwise sizers may try to look
  262.     // at deleted windows as they delete themselves.
  263.     DeleteRelatedConstraints();
  264.  
  265.     if ( m_constraints )
  266.     {
  267.         // This removes any dangling pointers to this window in other windows'
  268.         // constraintsInvolvedIn lists.
  269.         UnsetConstraints(m_constraints);
  270.         delete m_constraints;
  271.         m_constraints = NULL;
  272.     }
  273.  
  274. #endif // wxUSE_CONSTRAINTS
  275.  
  276.     if ( m_containingSizer )
  277.         m_containingSizer->Remove((wxWindow*)this);
  278.  
  279.     if ( m_windowSizer )
  280.         delete m_windowSizer;
  281.  
  282. #if wxUSE_DRAG_AND_DROP
  283.     if ( m_dropTarget )
  284.         delete m_dropTarget;
  285. #endif // wxUSE_DRAG_AND_DROP
  286.  
  287. #if wxUSE_TOOLTIPS
  288.     if ( m_tooltip )
  289.         delete m_tooltip;
  290. #endif // wxUSE_TOOLTIPS
  291.  
  292.     // reset the dangling pointer our parent window may keep to us
  293.     if ( m_parent && m_parent->GetDefaultItem() == this )
  294.     {
  295.         m_parent->SetDefaultItem(NULL);
  296.     }
  297. }
  298.  
  299. bool wxWindowBase::Destroy()
  300. {
  301.     delete this;
  302.  
  303.     return TRUE;
  304. }
  305.  
  306. bool wxWindowBase::Close(bool force)
  307. {
  308.     wxCloseEvent event(wxEVT_CLOSE_WINDOW, m_windowId);
  309.     event.SetEventObject(this);
  310. #if WXWIN_COMPATIBILITY
  311.     event.SetForce(force);
  312. #endif // WXWIN_COMPATIBILITY
  313.     event.SetCanVeto(!force);
  314.  
  315.     // return FALSE if window wasn't closed because the application vetoed the
  316.     // close event
  317.     return GetEventHandler()->ProcessEvent(event) && !event.GetVeto();
  318. }
  319.  
  320. bool wxWindowBase::DestroyChildren()
  321. {
  322.     wxWindowList::Node *node;
  323.     for ( ;; )
  324.     {
  325.         // we iterate until the list becomes empty
  326.         node = GetChildren().GetFirst();
  327.         if ( !node )
  328.             break;
  329.  
  330.         wxWindow *child = node->GetData();
  331.  
  332.         wxASSERT_MSG( child, wxT("children list contains empty nodes") );
  333.  
  334.         child->Show(FALSE);
  335.         delete child;
  336.  
  337.         wxASSERT_MSG( !GetChildren().Find(child),
  338.                       wxT("child didn't remove itself using RemoveChild()") );
  339.     }
  340.  
  341.     return TRUE;
  342. }
  343.  
  344. // ----------------------------------------------------------------------------
  345. // size/position related methods
  346. // ----------------------------------------------------------------------------
  347.  
  348. // centre the window with respect to its parent in either (or both) directions
  349. void wxWindowBase::Centre(int direction)
  350. {
  351.     // the position/size of the parent window or of the entire screen
  352.     wxPoint posParent;
  353.     int widthParent, heightParent;
  354.  
  355.     wxWindow *parent = NULL;
  356.  
  357.     if ( !(direction & wxCENTRE_ON_SCREEN) )
  358.     {
  359.         // find the parent to centre this window on: it should be the
  360.         // immediate parent for the controls but the top level parent for the
  361.         // top level windows (like dialogs)
  362.         parent = GetParent();
  363.         if ( IsTopLevel() )
  364.         {
  365.             while ( parent && !parent->IsTopLevel() )
  366.             {
  367.                 parent = parent->GetParent();
  368.             }
  369.         }
  370.  
  371.         // there is no wxTopLevelWindow under wxMotif yet
  372. #ifndef __WXMOTIF__
  373.         // we shouldn't center the dialog on the iconized window: under
  374.         // Windows, for example, this places it completely off the screen
  375.         if ( parent )
  376.         {
  377.             wxTopLevelWindow *winTop = wxDynamicCast(parent, wxTopLevelWindow);
  378.             if ( winTop && winTop->IsIconized() )
  379.             {
  380.                 parent = NULL;
  381.             }
  382.         }
  383. #endif // __WXMOTIF__
  384.  
  385.         // did we find the parent?
  386.         if ( !parent )
  387.         {
  388.             // no other choice
  389.             direction |= wxCENTRE_ON_SCREEN;
  390.         }
  391.     }
  392.  
  393.     if ( direction & wxCENTRE_ON_SCREEN )
  394.     {
  395.         // centre with respect to the whole screen
  396.         wxDisplaySize(&widthParent, &heightParent);
  397.     }
  398.     else
  399.     {
  400.         if ( IsTopLevel() )
  401.         {
  402.             // centre on the parent
  403.             parent->GetSize(&widthParent, &heightParent);
  404.  
  405.             // adjust to the parents position
  406.             posParent = parent->GetPosition();
  407.         }
  408.         else
  409.         {
  410.             // centre inside the parents client rectangle
  411.             parent->GetClientSize(&widthParent, &heightParent);
  412.         }
  413.     }
  414.  
  415.     int width, height;
  416.     GetSize(&width, &height);
  417.  
  418.     int xNew = -1,
  419.         yNew = -1;
  420.  
  421.     if ( direction & wxHORIZONTAL )
  422.         xNew = (widthParent - width)/2;
  423.  
  424.     if ( direction & wxVERTICAL )
  425.         yNew = (heightParent - height)/2;
  426.  
  427.     xNew += posParent.x;
  428.     yNew += posParent.y;
  429.  
  430.     // Base size of the visible dimensions of the display
  431.     // to take into account the taskbar
  432.     wxRect rect = wxGetClientDisplayRect();
  433.     wxSize size (rect.width,rect.height);
  434.  
  435.     // NB: in wxMSW, negative position may not neccessary mean "out of screen",
  436.     //     but it may mean that the window is placed on other than the main
  437.     //     display. Therefore we only make sure centered window is on the main display
  438.     //     if the parent is at least partially present here.
  439.     if (posParent.x + widthParent >= 0)  // if parent is (partially) on the main display
  440.     {
  441.         if (xNew < 0)
  442.             xNew = 0;
  443.         else if (xNew+width > size.x)
  444.             xNew = size.x-width-1;
  445.     }
  446.     if (posParent.y + heightParent >= 0)  // if parent is (partially) on the main display
  447.     {
  448.         if (yNew+height > size.y)
  449.             yNew = size.y-height-1;
  450.  
  451.         // Make certain that the title bar is initially visible
  452.         // always, even if this would push the bottom of the
  453.         // dialog of the visible area of the display
  454.         if (yNew < 0)
  455.             yNew = 0;
  456.     }
  457.  
  458.     // move the window to this position (keeping the old size but using
  459.     // SetSize() and not Move() to allow xNew and/or yNew to be -1)
  460.     SetSize(xNew, yNew, width, height, wxSIZE_ALLOW_MINUS_ONE);
  461. }
  462.  
  463. // fits the window around the children
  464. void wxWindowBase::Fit()
  465. {
  466.     if ( GetChildren().GetCount() > 0 )
  467.     {
  468.         SetClientSize(DoGetBestSize());
  469.     }
  470.     //else: do nothing if we have no children
  471. }
  472.  
  473. // return the size best suited for the current window
  474. wxSize wxWindowBase::DoGetBestSize() const
  475. {
  476.     if ( m_windowSizer )
  477.     {
  478.         return m_windowSizer->GetMinSize();
  479.     }
  480. #if wxUSE_CONSTRAINTS
  481.     else if ( m_constraints )
  482.     {
  483.         wxConstCast(this, wxWindowBase)->SatisfyConstraints();
  484.  
  485.         // our minimal acceptable size is such that all our windows fit inside
  486.         int maxX = 0,
  487.             maxY = 0;
  488.  
  489.         for ( wxWindowList::Node *node = GetChildren().GetFirst();
  490.               node;
  491.               node = node->GetNext() )
  492.         {
  493.             wxLayoutConstraints *c = node->GetData()->GetConstraints();
  494.             if ( !c )
  495.             {
  496.                 // it's not normal that we have an unconstrained child, but
  497.                 // what can we do about it?
  498.                 continue;
  499.             }
  500.  
  501.             int x = c->right.GetValue(),
  502.                 y = c->bottom.GetValue();
  503.  
  504.             if ( x > maxX )
  505.                 maxX = x;
  506.  
  507.             if ( y > maxY )
  508.                 maxY = y;
  509.  
  510.             // TODO: we must calculate the overlaps somehow, otherwise we
  511.             //       will never return a size bigger than the current one :-(
  512.         }
  513.  
  514.         return wxSize(maxX, maxY);
  515.     }
  516. #endif // wxUSE_CONSTRAINTS
  517.     else if ( GetChildren().GetCount() > 0 )
  518.     {
  519.         // our minimal acceptable size is such that all our windows fit inside
  520.         int maxX = 0,
  521.             maxY = 0;
  522.  
  523.         for ( wxWindowList::Node *node = GetChildren().GetFirst();
  524.               node;
  525.               node = node->GetNext() )
  526.         {
  527.             wxWindow *win = node->GetData();
  528.             if ( win->IsTopLevel()
  529. #if wxUSE_STATUSBAR
  530.                     || wxDynamicCast(win, wxStatusBar)
  531. #endif // wxUSE_STATUSBAR
  532.                )
  533.             {
  534.                 // dialogs and frames lie in different top level windows -
  535.                 // don't deal with them here; as for the status bars, they
  536.                 // don't lie in the client area at all
  537.                 continue;
  538.             }
  539.  
  540.             int wx, wy, ww, wh;
  541.             win->GetPosition(&wx, &wy);
  542.  
  543.             // if the window hadn't been positioned yet, assume that it is in
  544.             // the origin
  545.             if ( wx == -1 )
  546.                 wx = 0;
  547.             if ( wy == -1 )
  548.                 wy = 0;
  549.  
  550.             win->GetSize(&ww, &wh);
  551.             if ( wx + ww > maxX )
  552.                 maxX = wx + ww;
  553.             if ( wy + wh > maxY )
  554.                 maxY = wy + wh;
  555.         }
  556.  
  557.         // for compatibility with the old versions and because it really looks
  558.         // slightly more pretty like this, add a pad
  559.         maxX += 7;
  560.         maxY += 14;
  561.  
  562.         return wxSize(maxX, maxY);
  563.     }
  564.     else
  565.     {
  566.         // for a generic window there is no natural best size - just use the
  567.         // current one
  568.         return GetSize();
  569.     }
  570. }
  571.  
  572. // by default the origin is not shifted
  573. wxPoint wxWindowBase::GetClientAreaOrigin() const
  574. {
  575.     return wxPoint(0, 0);
  576. }
  577.  
  578. // set the min/max size of the window
  579. void wxWindowBase::SetSizeHints(int minW, int minH,
  580.                                 int maxW, int maxH,
  581.                                 int WXUNUSED(incW), int WXUNUSED(incH))
  582. {
  583.     m_minWidth = minW;
  584.     m_maxWidth = maxW;
  585.     m_minHeight = minH;
  586.     m_maxHeight = maxH;
  587. }
  588.  
  589. void wxWindowBase::SetVirtualSizeHints( int minW, int minH,
  590.                                         int maxW, int maxH )
  591. {
  592.     m_minVirtualWidth = minW;
  593.     m_maxVirtualWidth = maxW;
  594.     m_minVirtualHeight = minH;
  595.     m_maxVirtualHeight = maxH;
  596.  
  597.     SetVirtualSize( GetClientSize() );
  598. }
  599.  
  600. void wxWindowBase::DoSetVirtualSize( int x, int y )
  601. {
  602.     if ( m_minVirtualWidth != -1 && m_minVirtualWidth > x )
  603.         x = m_minVirtualWidth;
  604.     if ( m_maxVirtualWidth != -1 && m_maxVirtualWidth < x )
  605.         x = m_maxVirtualWidth;
  606.     if ( m_minVirtualHeight != -1 && m_minVirtualHeight > y )
  607.         y = m_minVirtualHeight;
  608.     if ( m_maxVirtualHeight != -1 && m_maxVirtualHeight < y )
  609.         y = m_maxVirtualHeight;
  610.  
  611.     m_virtualSize = wxSize(x, y);
  612. }
  613.  
  614. wxSize wxWindowBase::DoGetVirtualSize() const
  615. {
  616.     wxSize  s( GetClientSize() );
  617.  
  618.     if( m_virtualSize.GetWidth() != -1 )
  619.         s.SetWidth( m_virtualSize.GetWidth() );
  620.     if( m_virtualSize.GetHeight() != -1 )
  621.         s.SetHeight( m_virtualSize.GetHeight() );
  622.  
  623.     return s;
  624. }
  625.  
  626. // ----------------------------------------------------------------------------
  627. // show/hide/enable/disable the window
  628. // ----------------------------------------------------------------------------
  629.  
  630. bool wxWindowBase::Show(bool show)
  631. {
  632.     if ( show != m_isShown )
  633.     {
  634.         m_isShown = show;
  635.  
  636.         return TRUE;
  637.     }
  638.     else
  639.     {
  640.         return FALSE;
  641.     }
  642. }
  643.  
  644. bool wxWindowBase::Enable(bool enable)
  645. {
  646.     if ( enable != m_isEnabled )
  647.     {
  648.         m_isEnabled = enable;
  649.  
  650.         return TRUE;
  651.     }
  652.     else
  653.     {
  654.         return FALSE;
  655.     }
  656. }
  657. // ----------------------------------------------------------------------------
  658. // RTTI
  659. // ----------------------------------------------------------------------------
  660.  
  661. bool wxWindowBase::IsTopLevel() const
  662. {
  663.     return FALSE;
  664. }
  665.  
  666. // ----------------------------------------------------------------------------
  667. // reparenting the window
  668. // ----------------------------------------------------------------------------
  669.  
  670. void wxWindowBase::AddChild(wxWindowBase *child)
  671. {
  672.     wxCHECK_RET( child, wxT("can't add a NULL child") );
  673.  
  674.     // this should never happen and it will lead to a crash later if it does
  675.     // because RemoveChild() will remove only one node from the children list
  676.     // and the other(s) one(s) will be left with dangling pointers in them
  677.     wxASSERT_MSG( !GetChildren().Find(child), _T("AddChild() called twice") );
  678.  
  679.     GetChildren().Append(child);
  680.     child->SetParent(this);
  681. }
  682.  
  683. void wxWindowBase::RemoveChild(wxWindowBase *child)
  684. {
  685.     wxCHECK_RET( child, wxT("can't remove a NULL child") );
  686.  
  687.     GetChildren().DeleteObject(child);
  688.     child->SetParent((wxWindow *)NULL);
  689. }
  690.  
  691. bool wxWindowBase::Reparent(wxWindowBase *newParent)
  692. {
  693.     wxWindow *oldParent = GetParent();
  694.     if ( newParent == oldParent )
  695.     {
  696.         // nothing done
  697.         return FALSE;
  698.     }
  699.  
  700.     // unlink this window from the existing parent.
  701.     if ( oldParent )
  702.     {
  703.         oldParent->RemoveChild(this);
  704.     }
  705.     else
  706.     {
  707.         wxTopLevelWindows.DeleteObject(this);
  708.     }
  709.  
  710.     // add it to the new one
  711.     if ( newParent )
  712.     {
  713.         newParent->AddChild(this);
  714.     }
  715.     else
  716.     {
  717.         wxTopLevelWindows.Append(this);
  718.     }
  719.  
  720.     return TRUE;
  721. }
  722.  
  723. // ----------------------------------------------------------------------------
  724. // event handler stuff
  725. // ----------------------------------------------------------------------------
  726.  
  727. void wxWindowBase::PushEventHandler(wxEvtHandler *handler)
  728. {
  729.     wxEvtHandler *handlerOld = GetEventHandler();
  730.  
  731.     handler->SetNextHandler(handlerOld);
  732.  
  733.     if ( handlerOld )
  734.         GetEventHandler()->SetPreviousHandler(handler);
  735.  
  736.     SetEventHandler(handler);
  737. }
  738.  
  739. wxEvtHandler *wxWindowBase::PopEventHandler(bool deleteHandler)
  740. {
  741.     wxEvtHandler *handlerA = GetEventHandler();
  742.     if ( handlerA )
  743.     {
  744.         wxEvtHandler *handlerB = handlerA->GetNextHandler();
  745.         handlerA->SetNextHandler((wxEvtHandler *)NULL);
  746.  
  747.         if ( handlerB )
  748.             handlerB->SetPreviousHandler((wxEvtHandler *)NULL);
  749.         SetEventHandler(handlerB);
  750.  
  751.         if ( deleteHandler )
  752.         {
  753.             delete handlerA;
  754.             handlerA = (wxEvtHandler *)NULL;
  755.         }
  756.     }
  757.  
  758.     return handlerA;
  759. }
  760.  
  761. bool wxWindowBase::RemoveEventHandler(wxEvtHandler *handler)
  762. {
  763.     wxCHECK_MSG( handler, FALSE, _T("RemoveEventHandler(NULL) called") );
  764.  
  765.     wxEvtHandler *handlerPrev = NULL,
  766.                  *handlerCur = GetEventHandler();
  767.     while ( handlerCur )
  768.     {
  769.         wxEvtHandler *handlerNext = handlerCur->GetNextHandler();
  770.  
  771.         if ( handlerCur == handler )
  772.         {
  773.             if ( handlerPrev )
  774.             {
  775.                 handlerPrev->SetNextHandler(handlerNext);
  776.             }
  777.             else
  778.             {
  779.                 SetEventHandler(handlerNext);
  780.             }
  781.  
  782.             if ( handlerNext )
  783.             {
  784.                 handlerNext->SetPreviousHandler ( handlerPrev );
  785.             }
  786.             handler->SetNextHandler(NULL);
  787.  
  788.             return TRUE;
  789.         }
  790.  
  791.         handlerPrev = handlerCur;
  792.         handlerCur = handlerNext;
  793.     }
  794.  
  795.     wxFAIL_MSG( _T("where has the event handler gone?") );
  796.  
  797.     return FALSE;
  798. }
  799.  
  800. // ----------------------------------------------------------------------------
  801. // cursors, fonts &c
  802. // ----------------------------------------------------------------------------
  803.  
  804. bool wxWindowBase::SetBackgroundColour( const wxColour &colour )
  805. {
  806.     if ( !colour.Ok() || (colour == m_backgroundColour) )
  807.         return FALSE;
  808.  
  809.     m_backgroundColour = colour;
  810.  
  811.     m_hasBgCol = TRUE;
  812.  
  813.     return TRUE;
  814. }
  815.  
  816. bool wxWindowBase::SetForegroundColour( const wxColour &colour )
  817. {
  818.     if ( !colour.Ok() || (colour == m_foregroundColour) )
  819.         return FALSE;
  820.  
  821.     m_foregroundColour = colour;
  822.  
  823.     m_hasFgCol = TRUE;
  824.  
  825.     return TRUE;
  826. }
  827.  
  828. bool wxWindowBase::SetCursor(const wxCursor& cursor)
  829. {
  830.     // setting an invalid cursor is ok, it means that we don't have any special
  831.     // cursor
  832.     if ( m_cursor == cursor )
  833.     {
  834.         // no change
  835.         return FALSE;
  836.     }
  837.  
  838.     m_cursor = cursor;
  839.  
  840.     return TRUE;
  841. }
  842.  
  843. bool wxWindowBase::SetFont(const wxFont& font)
  844. {
  845.     // don't try to set invalid font, always fall back to the default
  846.     const wxFont& fontOk = font.Ok() ? font : *wxSWISS_FONT;
  847.  
  848.     if ( fontOk == m_font )
  849.     {
  850.         // no change
  851.         return FALSE;
  852.     }
  853.  
  854.     m_font = fontOk;
  855.  
  856.     m_hasFont = TRUE;
  857.  
  858.     return TRUE;
  859. }
  860.  
  861. #if wxUSE_PALETTE
  862.  
  863. void wxWindowBase::SetPalette(const wxPalette& pal)
  864. {
  865.     m_hasCustomPalette = TRUE;
  866.     m_palette = pal;
  867.  
  868.     // VZ: can anyone explain me what do we do here?
  869.     wxWindowDC d((wxWindow *) this);
  870.     d.SetPalette(pal);
  871. }
  872.  
  873. wxWindow *wxWindowBase::GetAncestorWithCustomPalette() const
  874. {
  875.     wxWindow *win = (wxWindow *)this;
  876.     while ( win && !win->HasCustomPalette() )
  877.     {
  878.         win = win->GetParent();
  879.     }
  880.  
  881.     return win;
  882. }
  883.  
  884. #endif // wxUSE_PALETTE
  885.  
  886. #if wxUSE_CARET
  887. void wxWindowBase::SetCaret(wxCaret *caret)
  888. {
  889.     if ( m_caret )
  890.     {
  891.         delete m_caret;
  892.     }
  893.  
  894.     m_caret = caret;
  895.  
  896.     if ( m_caret )
  897.     {
  898.         wxASSERT_MSG( m_caret->GetWindow() == this,
  899.                       wxT("caret should be created associated to this window") );
  900.     }
  901. }
  902. #endif // wxUSE_CARET
  903.  
  904. #if wxUSE_VALIDATORS
  905. // ----------------------------------------------------------------------------
  906. // validators
  907. // ----------------------------------------------------------------------------
  908.  
  909. void wxWindowBase::SetValidator(const wxValidator& validator)
  910. {
  911.     if ( m_windowValidator )
  912.         delete m_windowValidator;
  913.  
  914.     m_windowValidator = (wxValidator *)validator.Clone();
  915.  
  916.     if ( m_windowValidator )
  917.         m_windowValidator->SetWindow(this) ;
  918. }
  919. #endif // wxUSE_VALIDATORS
  920.  
  921. // ----------------------------------------------------------------------------
  922. // update region stuff
  923. // ----------------------------------------------------------------------------
  924.  
  925. wxRect wxWindowBase::GetUpdateClientRect() const
  926. {
  927.     wxRegion rgnUpdate = GetUpdateRegion();
  928.     rgnUpdate.Intersect(GetClientRect());
  929.     wxRect rectUpdate = rgnUpdate.GetBox();
  930.     wxPoint ptOrigin = GetClientAreaOrigin();
  931.     rectUpdate.x -= ptOrigin.x;
  932.     rectUpdate.y -= ptOrigin.y;
  933.  
  934.     return rectUpdate;
  935. }
  936.  
  937. bool wxWindowBase::IsExposed(int x, int y) const
  938. {
  939.     return m_updateRegion.Contains(x, y) != wxOutRegion;
  940. }
  941.  
  942. bool wxWindowBase::IsExposed(int x, int y, int w, int h) const
  943. {
  944.     return m_updateRegion.Contains(x, y, w, h) != wxOutRegion;
  945. }
  946.  
  947. // ----------------------------------------------------------------------------
  948. // find child window by id or name
  949. // ----------------------------------------------------------------------------
  950.  
  951. wxWindow *wxWindowBase::FindWindow( long id )
  952. {
  953.     if ( id == m_windowId )
  954.         return (wxWindow *)this;
  955.  
  956.     wxWindowBase *res = (wxWindow *)NULL;
  957.     wxWindowList::Node *node;
  958.     for ( node = m_children.GetFirst(); node && !res; node = node->GetNext() )
  959.     {
  960.         wxWindowBase *child = node->GetData();
  961.         res = child->FindWindow( id );
  962.     }
  963.  
  964.     return (wxWindow *)res;
  965. }
  966.  
  967. wxWindow *wxWindowBase::FindWindow( const wxString& name )
  968. {
  969.     if ( name == m_windowName )
  970.         return (wxWindow *)this;
  971.  
  972.     wxWindowBase *res = (wxWindow *)NULL;
  973.     wxWindowList::Node *node;
  974.     for ( node = m_children.GetFirst(); node && !res; node = node->GetNext() )
  975.     {
  976.         wxWindow *child = node->GetData();
  977.         res = child->FindWindow(name);
  978.     }
  979.  
  980.     return (wxWindow *)res;
  981. }
  982.  
  983.  
  984. // find any window by id or name or label: If parent is non-NULL, look through
  985. // children for a label or title matching the specified string. If NULL, look
  986. // through all top-level windows.
  987. //
  988. // to avoid duplicating code we reuse the same helper function but with
  989. // different comparators
  990.  
  991. typedef bool (*wxFindWindowCmp)(const wxWindow *win,
  992.                                 const wxString& label, long id);
  993.  
  994. static
  995. bool wxFindWindowCmpLabels(const wxWindow *win, const wxString& label,
  996.                            long WXUNUSED(id))
  997. {
  998.     return win->GetLabel() == label;
  999. }
  1000.  
  1001. static
  1002. bool wxFindWindowCmpNames(const wxWindow *win, const wxString& label,
  1003.                           long WXUNUSED(id))
  1004. {
  1005.     return win->GetName() == label;
  1006. }
  1007.  
  1008. static
  1009. bool wxFindWindowCmpIds(const wxWindow *win, const wxString& WXUNUSED(label),
  1010.                         long id)
  1011. {
  1012.     return win->GetId() == id;
  1013. }
  1014.  
  1015. // recursive helper for the FindWindowByXXX() functions
  1016. static
  1017. wxWindow *wxFindWindowRecursively(const wxWindow *parent,
  1018.                                   const wxString& label,
  1019.                                   long id,
  1020.                                   wxFindWindowCmp cmp)
  1021. {
  1022.     if ( parent )
  1023.     {
  1024.         // see if this is the one we're looking for
  1025.         if ( (*cmp)(parent, label, id) )
  1026.             return (wxWindow *)parent;
  1027.  
  1028.         // It wasn't, so check all its children
  1029.         for ( wxWindowList::Node * node = parent->GetChildren().GetFirst();
  1030.               node;
  1031.               node = node->GetNext() )
  1032.         {
  1033.             // recursively check each child
  1034.             wxWindow *win = (wxWindow *)node->GetData();
  1035.             wxWindow *retwin = wxFindWindowRecursively(win, label, id, cmp);
  1036.             if (retwin)
  1037.                 return retwin;
  1038.         }
  1039.     }
  1040.  
  1041.     // Not found
  1042.     return NULL;
  1043. }
  1044.  
  1045. // helper for FindWindowByXXX()
  1046. static
  1047. wxWindow *wxFindWindowHelper(const wxWindow *parent,
  1048.                              const wxString& label,
  1049.                              long id,
  1050.                              wxFindWindowCmp cmp)
  1051. {
  1052.     if ( parent )
  1053.     {
  1054.         // just check parent and all its children
  1055.         return wxFindWindowRecursively(parent, label, id, cmp);
  1056.     }
  1057.  
  1058.     // start at very top of wx's windows
  1059.     for ( wxWindowList::Node * node = wxTopLevelWindows.GetFirst();
  1060.           node;
  1061.           node = node->GetNext() )
  1062.     {
  1063.         // recursively check each window & its children
  1064.         wxWindow *win = node->GetData();
  1065.         wxWindow *retwin = wxFindWindowRecursively(win, label, id, cmp);
  1066.         if (retwin)
  1067.             return retwin;
  1068.     }
  1069.  
  1070.     return NULL;
  1071. }
  1072.  
  1073. /* static */
  1074. wxWindow *
  1075. wxWindowBase::FindWindowByLabel(const wxString& title, const wxWindow *parent)
  1076. {
  1077.     return wxFindWindowHelper(parent, title, 0, wxFindWindowCmpLabels);
  1078. }
  1079.  
  1080. /* static */
  1081. wxWindow *
  1082. wxWindowBase::FindWindowByName(const wxString& title, const wxWindow *parent)
  1083. {
  1084.     wxWindow *win = wxFindWindowHelper(parent, title, 0, wxFindWindowCmpNames);
  1085.  
  1086.     if ( !win )
  1087.     {
  1088.         // fall back to the label
  1089.         win = FindWindowByLabel(title, parent);
  1090.     }
  1091.  
  1092.     return win;
  1093. }
  1094.  
  1095. /* static */
  1096. wxWindow *
  1097. wxWindowBase::FindWindowById( long id, const wxWindow* parent )
  1098. {
  1099.     return wxFindWindowHelper(parent, _T(""), id, wxFindWindowCmpIds);
  1100. }
  1101.  
  1102. // ----------------------------------------------------------------------------
  1103. // dialog oriented functions
  1104. // ----------------------------------------------------------------------------
  1105.  
  1106. void wxWindowBase::MakeModal(bool modal)
  1107. {
  1108.     // Disable all other windows
  1109.     if ( IsTopLevel() )
  1110.     {
  1111.         wxWindowList::Node *node = wxTopLevelWindows.GetFirst();
  1112.         while (node)
  1113.         {
  1114.             wxWindow *win = node->GetData();
  1115.             if (win != this)
  1116.                 win->Enable(!modal);
  1117.  
  1118.             node = node->GetNext();
  1119.         }
  1120.     }
  1121. }
  1122.  
  1123. bool wxWindowBase::Validate()
  1124. {
  1125. #if wxUSE_VALIDATORS
  1126.     bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0;
  1127.  
  1128.     wxWindowList::Node *node;
  1129.     for ( node = m_children.GetFirst(); node; node = node->GetNext() )
  1130.     {
  1131.         wxWindowBase *child = node->GetData();
  1132.         wxValidator *validator = child->GetValidator();
  1133.         if ( validator && !validator->Validate((wxWindow *)this) )
  1134.         {
  1135.             return FALSE;
  1136.         }
  1137.  
  1138.         if ( recurse && !child->Validate() )
  1139.         {
  1140.             return FALSE;
  1141.         }
  1142.     }
  1143. #endif // wxUSE_VALIDATORS
  1144.  
  1145.     return TRUE;
  1146. }
  1147.  
  1148. bool wxWindowBase::TransferDataToWindow()
  1149. {
  1150. #if wxUSE_VALIDATORS
  1151.     bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0;
  1152.  
  1153.     wxWindowList::Node *node;
  1154.     for ( node = m_children.GetFirst(); node; node = node->GetNext() )
  1155.     {
  1156.         wxWindowBase *child = node->GetData();
  1157.         wxValidator *validator = child->GetValidator();
  1158.         if ( validator && !validator->TransferToWindow() )
  1159.         {
  1160.             wxLogWarning(_("Could not transfer data to window"));
  1161.             wxLog::FlushActive();
  1162.  
  1163.             return FALSE;
  1164.         }
  1165.  
  1166.         if ( recurse )
  1167.         {
  1168.             if ( !child->TransferDataToWindow() )
  1169.             {
  1170.                 // warning already given
  1171.                 return FALSE;
  1172.             }
  1173.         }
  1174.     }
  1175. #endif // wxUSE_VALIDATORS
  1176.  
  1177.     return TRUE;
  1178. }
  1179.  
  1180. bool wxWindowBase::TransferDataFromWindow()
  1181. {
  1182. #if wxUSE_VALIDATORS
  1183.     bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0;
  1184.  
  1185.     wxWindowList::Node *node;
  1186.     for ( node = m_children.GetFirst(); node; node = node->GetNext() )
  1187.     {
  1188.         wxWindow *child = node->GetData();
  1189.         wxValidator *validator = child->GetValidator();
  1190.         if ( validator && !validator->TransferFromWindow() )
  1191.         {
  1192.             // nop warning here because the application is supposed to give
  1193.             // one itself - we don't know here what might have gone wrongly
  1194.  
  1195.             return FALSE;
  1196.         }
  1197.  
  1198.         if ( recurse )
  1199.         {
  1200.             if ( !child->TransferDataFromWindow() )
  1201.             {
  1202.                 // warning already given
  1203.                 return FALSE;
  1204.             }
  1205.         }
  1206.     }
  1207. #endif // wxUSE_VALIDATORS
  1208.  
  1209.     return TRUE;
  1210. }
  1211.  
  1212. void wxWindowBase::InitDialog()
  1213. {
  1214.     wxInitDialogEvent event(GetId());
  1215.     event.SetEventObject( this );
  1216.     GetEventHandler()->ProcessEvent(event);
  1217. }
  1218.  
  1219. // ----------------------------------------------------------------------------
  1220. // context-sensitive help support
  1221. // ----------------------------------------------------------------------------
  1222.  
  1223. #if wxUSE_HELP
  1224.  
  1225. // associate this help text with this window
  1226. void wxWindowBase::SetHelpText(const wxString& text)
  1227. {
  1228.     wxHelpProvider *helpProvider = wxHelpProvider::Get();
  1229.     if ( helpProvider )
  1230.     {
  1231.         helpProvider->AddHelp(this, text);
  1232.     }
  1233. }
  1234.  
  1235. // associate this help text with all windows with the same id as this
  1236. // one
  1237. void wxWindowBase::SetHelpTextForId(const wxString& text)
  1238. {
  1239.     wxHelpProvider *helpProvider = wxHelpProvider::Get();
  1240.     if ( helpProvider )
  1241.     {
  1242.         helpProvider->AddHelp(GetId(), text);
  1243.     }
  1244. }
  1245.  
  1246. // get the help string associated with this window (may be empty)
  1247. wxString wxWindowBase::GetHelpText() const
  1248. {
  1249.     wxString text;
  1250.     wxHelpProvider *helpProvider = wxHelpProvider::Get();
  1251.     if ( helpProvider )
  1252.     {
  1253.         text = helpProvider->GetHelp(this);
  1254.     }
  1255.  
  1256.     return text;
  1257. }
  1258.  
  1259. // show help for this window
  1260. void wxWindowBase::OnHelp(wxHelpEvent& event)
  1261. {
  1262.     wxHelpProvider *helpProvider = wxHelpProvider::Get();
  1263.     if ( helpProvider )
  1264.     {
  1265.         if ( helpProvider->ShowHelp(this) )
  1266.         {
  1267.             // skip the event.Skip() below
  1268.             return;
  1269.         }
  1270.     }
  1271.  
  1272.     event.Skip();
  1273. }
  1274.  
  1275. #endif // wxUSE_HELP
  1276.  
  1277. // ----------------------------------------------------------------------------
  1278. // tooltipsroot.Replace("\\", "/");
  1279. // ----------------------------------------------------------------------------
  1280.  
  1281. #if wxUSE_TOOLTIPS
  1282.  
  1283. void wxWindowBase::SetToolTip( const wxString &tip )
  1284. {
  1285.     // don't create the new tooltip if we already have one
  1286.     if ( m_tooltip )
  1287.     {
  1288.         m_tooltip->SetTip( tip );
  1289.     }
  1290.     else
  1291.     {
  1292.         SetToolTip( new wxToolTip( tip ) );
  1293.     }
  1294.  
  1295.     // setting empty tooltip text does not remove the tooltip any more - use
  1296.     // SetToolTip((wxToolTip *)NULL) for this
  1297. }
  1298.  
  1299. void wxWindowBase::DoSetToolTip(wxToolTip *tooltip)
  1300. {
  1301.     if ( m_tooltip )
  1302.         delete m_tooltip;
  1303.  
  1304.     m_tooltip = tooltip;
  1305. }
  1306.  
  1307. #endif // wxUSE_TOOLTIPS
  1308.  
  1309. // ----------------------------------------------------------------------------
  1310. // constraints and sizers
  1311. // ----------------------------------------------------------------------------
  1312.  
  1313. #if wxUSE_CONSTRAINTS
  1314.  
  1315. void wxWindowBase::SetConstraints( wxLayoutConstraints *constraints )
  1316. {
  1317.     if ( m_constraints )
  1318.     {
  1319.         UnsetConstraints(m_constraints);
  1320.         delete m_constraints;
  1321.     }
  1322.     m_constraints = constraints;
  1323.     if ( m_constraints )
  1324.     {
  1325.         // Make sure other windows know they're part of a 'meaningful relationship'
  1326.         if ( m_constraints->left.GetOtherWindow() && (m_constraints->left.GetOtherWindow() != this) )
  1327.             m_constraints->left.GetOtherWindow()->AddConstraintReference(this);
  1328.         if ( m_constraints->top.GetOtherWindow() && (m_constraints->top.GetOtherWindow() != this) )
  1329.             m_constraints->top.GetOtherWindow()->AddConstraintReference(this);
  1330.         if ( m_constraints->right.GetOtherWindow() && (m_constraints->right.GetOtherWindow() != this) )
  1331.             m_constraints->right.GetOtherWindow()->AddConstraintReference(this);
  1332.         if ( m_constraints->bottom.GetOtherWindow() && (m_constraints->bottom.GetOtherWindow() != this) )
  1333.             m_constraints->bottom.GetOtherWindow()->AddConstraintReference(this);
  1334.         if ( m_constraints->width.GetOtherWindow() && (m_constraints->width.GetOtherWindow() != this) )
  1335.             m_constraints->width.GetOtherWindow()->AddConstraintReference(this);
  1336.         if ( m_constraints->height.GetOtherWindow() && (m_constraints->height.GetOtherWindow() != this) )
  1337.             m_constraints->height.GetOtherWindow()->AddConstraintReference(this);
  1338.         if ( m_constraints->centreX.GetOtherWindow() && (m_constraints->centreX.GetOtherWindow() != this) )
  1339.             m_constraints->centreX.GetOtherWindow()->AddConstraintReference(this);
  1340.         if ( m_constraints->centreY.GetOtherWindow() && (m_constraints->centreY.GetOtherWindow() != this) )
  1341.             m_constraints->centreY.GetOtherWindow()->AddConstraintReference(this);
  1342.     }
  1343. }
  1344.  
  1345. // This removes any dangling pointers to this window in other windows'
  1346. // constraintsInvolvedIn lists.
  1347. void wxWindowBase::UnsetConstraints(wxLayoutConstraints *c)
  1348. {
  1349.     if ( c )
  1350.     {
  1351.         if ( c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this) )
  1352.             c->left.GetOtherWindow()->RemoveConstraintReference(this);
  1353.         if ( c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this) )
  1354.             c->top.GetOtherWindow()->RemoveConstraintReference(this);
  1355.         if ( c->right.GetOtherWindow() && (c->right.GetOtherWindow() != this) )
  1356.             c->right.GetOtherWindow()->RemoveConstraintReference(this);
  1357.         if ( c->bottom.GetOtherWindow() && (c->bottom.GetOtherWindow() != this) )
  1358.             c->bottom.GetOtherWindow()->RemoveConstraintReference(this);
  1359.         if ( c->width.GetOtherWindow() && (c->width.GetOtherWindow() != this) )
  1360.             c->width.GetOtherWindow()->RemoveConstraintReference(this);
  1361.         if ( c->height.GetOtherWindow() && (c->height.GetOtherWindow() != this) )
  1362.             c->height.GetOtherWindow()->RemoveConstraintReference(this);
  1363.         if ( c->centreX.GetOtherWindow() && (c->centreX.GetOtherWindow() != this) )
  1364.             c->centreX.GetOtherWindow()->RemoveConstraintReference(this);
  1365.         if ( c->centreY.GetOtherWindow() && (c->centreY.GetOtherWindow() != this) )
  1366.             c->centreY.GetOtherWindow()->RemoveConstraintReference(this);
  1367.     }
  1368. }
  1369.  
  1370. // Back-pointer to other windows we're involved with, so if we delete this
  1371. // window, we must delete any constraints we're involved with.
  1372. void wxWindowBase::AddConstraintReference(wxWindowBase *otherWin)
  1373. {
  1374.     if ( !m_constraintsInvolvedIn )
  1375.         m_constraintsInvolvedIn = new wxWindowList;
  1376.     if ( !m_constraintsInvolvedIn->Find(otherWin) )
  1377.         m_constraintsInvolvedIn->Append(otherWin);
  1378. }
  1379.  
  1380. // REMOVE back-pointer to other windows we're involved with.
  1381. void wxWindowBase::RemoveConstraintReference(wxWindowBase *otherWin)
  1382. {
  1383.     if ( m_constraintsInvolvedIn )
  1384.         m_constraintsInvolvedIn->DeleteObject(otherWin);
  1385. }
  1386.  
  1387. // Reset any constraints that mention this window
  1388. void wxWindowBase::DeleteRelatedConstraints()
  1389. {
  1390.     if ( m_constraintsInvolvedIn )
  1391.     {
  1392.         wxWindowList::Node *node = m_constraintsInvolvedIn->GetFirst();
  1393.         while (node)
  1394.         {
  1395.             wxWindow *win = node->GetData();
  1396.             wxLayoutConstraints *constr = win->GetConstraints();
  1397.  
  1398.             // Reset any constraints involving this window
  1399.             if ( constr )
  1400.             {
  1401.                 constr->left.ResetIfWin(this);
  1402.                 constr->top.ResetIfWin(this);
  1403.                 constr->right.ResetIfWin(this);
  1404.                 constr->bottom.ResetIfWin(this);
  1405.                 constr->width.ResetIfWin(this);
  1406.                 constr->height.ResetIfWin(this);
  1407.                 constr->centreX.ResetIfWin(this);
  1408.                 constr->centreY.ResetIfWin(this);
  1409.             }
  1410.  
  1411.             wxWindowList::Node *next = node->GetNext();
  1412.             delete node;
  1413.             node = next;
  1414.         }
  1415.  
  1416.         delete m_constraintsInvolvedIn;
  1417.         m_constraintsInvolvedIn = (wxWindowList *) NULL;
  1418.     }
  1419. }
  1420.  
  1421. #endif // wxUSE_CONSTRAINTS
  1422.  
  1423. void wxWindowBase::SetSizer(wxSizer *sizer, bool deleteOld)
  1424. {
  1425.     if ( deleteOld )
  1426.         delete m_windowSizer;
  1427.  
  1428.     m_windowSizer = sizer;
  1429.  
  1430.     SetAutoLayout( sizer != NULL );
  1431. }
  1432.  
  1433. void wxWindowBase::SetSizerAndFit(wxSizer *sizer, bool deleteOld)
  1434. {
  1435.     SetSizer( sizer, deleteOld );
  1436.     sizer->SetSizeHints( (wxWindow*) this );
  1437. }
  1438.  
  1439. #if wxUSE_CONSTRAINTS
  1440.  
  1441. void wxWindowBase::SatisfyConstraints()
  1442. {
  1443.     wxLayoutConstraints *constr = GetConstraints();
  1444.     bool wasOk = constr && constr->AreSatisfied();
  1445.  
  1446.     ResetConstraints();   // Mark all constraints as unevaluated
  1447.  
  1448.     int noChanges = 1;
  1449.  
  1450.     // if we're a top level panel (i.e. our parent is frame/dialog), our
  1451.     // own constraints will never be satisfied any more unless we do it
  1452.     // here
  1453.     if ( wasOk )
  1454.     {
  1455.         while ( noChanges > 0 )
  1456.         {
  1457.             LayoutPhase1(&noChanges);
  1458.         }
  1459.     }
  1460.  
  1461.     LayoutPhase2(&noChanges);
  1462. }
  1463.  
  1464. #endif // wxUSE_CONSTRAINTS
  1465.  
  1466. bool wxWindowBase::Layout()
  1467. {
  1468.     // If there is a sizer, use it instead of the constraints
  1469.     if ( GetSizer() )
  1470.     {
  1471.         int w, h;
  1472.         GetVirtualSize(&w, &h);
  1473.         GetSizer()->SetDimension( 0, 0, w, h );
  1474.     }
  1475. #if wxUSE_CONSTRAINTS
  1476.     else
  1477.     {
  1478.         SatisfyConstraints(); // Find the right constraints values
  1479.         SetConstraintSizes(); // Recursively set the real window sizes
  1480.     }
  1481. #endif
  1482.  
  1483.     return TRUE;
  1484. }
  1485.  
  1486. #if wxUSE_CONSTRAINTS
  1487.  
  1488. // first phase of the constraints evaluation: set our own constraints
  1489. bool wxWindowBase::LayoutPhase1(int *noChanges)
  1490. {
  1491.     wxLayoutConstraints *constr = GetConstraints();
  1492.  
  1493.     return !constr || constr->SatisfyConstraints(this, noChanges);
  1494. }
  1495.  
  1496. // second phase: set the constraints for our children
  1497. bool wxWindowBase::LayoutPhase2(int *noChanges)
  1498. {
  1499.     *noChanges = 0;
  1500.  
  1501.     // Layout children
  1502.     DoPhase(1);
  1503.  
  1504.     // Layout grand children
  1505.     DoPhase(2);
  1506.  
  1507.     return TRUE;
  1508. }
  1509.  
  1510. // Do a phase of evaluating child constraints
  1511. bool wxWindowBase::DoPhase(int phase)
  1512. {
  1513.     // the list containing the children for which the constraints are already
  1514.     // set correctly
  1515.     wxWindowList succeeded;
  1516.  
  1517.     // the max number of iterations we loop before concluding that we can't set
  1518.     // the constraints
  1519.     static const int maxIterations = 500;
  1520.  
  1521.     for ( int noIterations = 0; noIterations < maxIterations; noIterations++ )
  1522.     {
  1523.         int noChanges = 0;
  1524.  
  1525.         // loop over all children setting their constraints
  1526.         for ( wxWindowList::Node *node = GetChildren().GetFirst();
  1527.               node;
  1528.               node = node->GetNext() )
  1529.         {
  1530.             wxWindow *child = node->GetData();
  1531.             if ( child->IsTopLevel() )
  1532.             {
  1533.                 // top level children are not inside our client area
  1534.                 continue;
  1535.             }
  1536.  
  1537.             if ( !child->GetConstraints() || succeeded.Find(child) )
  1538.             {
  1539.                 // this one is either already ok or nothing we can do about it
  1540.                 continue;
  1541.             }
  1542.  
  1543.             int tempNoChanges = 0;
  1544.             bool success = phase == 1 ? child->LayoutPhase1(&tempNoChanges)
  1545.                                       : child->LayoutPhase2(&tempNoChanges);
  1546.             noChanges += tempNoChanges;
  1547.  
  1548.             if ( success )
  1549.             {
  1550.                 succeeded.Append(child);
  1551.             }
  1552.         }
  1553.  
  1554.         if ( !noChanges )
  1555.         {
  1556.             // constraints are set
  1557.             break;
  1558.         }
  1559.     }
  1560.  
  1561.     return TRUE;
  1562. }
  1563.  
  1564. void wxWindowBase::ResetConstraints()
  1565. {
  1566.     wxLayoutConstraints *constr = GetConstraints();
  1567.     if ( constr )
  1568.     {
  1569.         constr->left.SetDone(FALSE);
  1570.         constr->top.SetDone(FALSE);
  1571.         constr->right.SetDone(FALSE);
  1572.         constr->bottom.SetDone(FALSE);
  1573.         constr->width.SetDone(FALSE);
  1574.         constr->height.SetDone(FALSE);
  1575.         constr->centreX.SetDone(FALSE);
  1576.         constr->centreY.SetDone(FALSE);
  1577.     }
  1578.  
  1579.     wxWindowList::Node *node = GetChildren().GetFirst();
  1580.     while (node)
  1581.     {
  1582.         wxWindow *win = node->GetData();
  1583.         if ( !win->IsTopLevel() )
  1584.             win->ResetConstraints();
  1585.         node = node->GetNext();
  1586.     }
  1587. }
  1588.  
  1589. // Need to distinguish between setting the 'fake' size for windows and sizers,
  1590. // and setting the real values.
  1591. void wxWindowBase::SetConstraintSizes(bool recurse)
  1592. {
  1593.     wxLayoutConstraints *constr = GetConstraints();
  1594.     if ( constr && constr->AreSatisfied() )
  1595.     {
  1596.         int x = constr->left.GetValue();
  1597.         int y = constr->top.GetValue();
  1598.         int w = constr->width.GetValue();
  1599.         int h = constr->height.GetValue();
  1600.  
  1601.         if ( (constr->width.GetRelationship() != wxAsIs ) ||
  1602.              (constr->height.GetRelationship() != wxAsIs) )
  1603.         {
  1604.             SetSize(x, y, w, h);
  1605.         }
  1606.         else
  1607.         {
  1608.             // If we don't want to resize this window, just move it...
  1609.             Move(x, y);
  1610.         }
  1611.     }
  1612.     else if ( constr )
  1613.     {
  1614.         wxLogDebug(wxT("Constraints not satisfied for %s named '%s'."),
  1615.                    GetClassInfo()->GetClassName(),
  1616.                    GetName().c_str());
  1617.     }
  1618.  
  1619.     if ( recurse )
  1620.     {
  1621.         wxWindowList::Node *node = GetChildren().GetFirst();
  1622.         while (node)
  1623.         {
  1624.             wxWindow *win = node->GetData();
  1625.             if ( !win->IsTopLevel() && win->GetConstraints() )
  1626.                 win->SetConstraintSizes();
  1627.             node = node->GetNext();
  1628.         }
  1629.     }
  1630. }
  1631.  
  1632. // Only set the size/position of the constraint (if any)
  1633. void wxWindowBase::SetSizeConstraint(int x, int y, int w, int h)
  1634. {
  1635.     wxLayoutConstraints *constr = GetConstraints();
  1636.     if ( constr )
  1637.     {
  1638.         if ( x != -1 )
  1639.         {
  1640.             constr->left.SetValue(x);
  1641.             constr->left.SetDone(TRUE);
  1642.         }
  1643.         if ( y != -1 )
  1644.         {
  1645.             constr->top.SetValue(y);
  1646.             constr->top.SetDone(TRUE);
  1647.         }
  1648.         if ( w != -1 )
  1649.         {
  1650.             constr->width.SetValue(w);
  1651.             constr->width.SetDone(TRUE);
  1652.         }
  1653.         if ( h != -1 )
  1654.         {
  1655.             constr->height.SetValue(h);
  1656.             constr->height.SetDone(TRUE);
  1657.         }
  1658.     }
  1659. }
  1660.  
  1661. void wxWindowBase::MoveConstraint(int x, int y)
  1662. {
  1663.     wxLayoutConstraints *constr = GetConstraints();
  1664.     if ( constr )
  1665.     {
  1666.         if ( x != -1 )
  1667.         {
  1668.             constr->left.SetValue(x);
  1669.             constr->left.SetDone(TRUE);
  1670.         }
  1671.         if ( y != -1 )
  1672.         {
  1673.             constr->top.SetValue(y);
  1674.             constr->top.SetDone(TRUE);
  1675.         }
  1676.     }
  1677. }
  1678.  
  1679. void wxWindowBase::GetSizeConstraint(int *w, int *h) const
  1680. {
  1681.     wxLayoutConstraints *constr = GetConstraints();
  1682.     if ( constr )
  1683.     {
  1684.         *w = constr->width.GetValue();
  1685.         *h = constr->height.GetValue();
  1686.     }
  1687.     else
  1688.         GetSize(w, h);
  1689. }
  1690.  
  1691. void wxWindowBase::GetClientSizeConstraint(int *w, int *h) const
  1692. {
  1693.     wxLayoutConstraints *constr = GetConstraints();
  1694.     if ( constr )
  1695.     {
  1696.         *w = constr->width.GetValue();
  1697.         *h = constr->height.GetValue();
  1698.     }
  1699.     else
  1700.         GetClientSize(w, h);
  1701. }
  1702.  
  1703. void wxWindowBase::GetPositionConstraint(int *x, int *y) const
  1704. {
  1705.     wxLayoutConstraints *constr = GetConstraints();
  1706.     if ( constr )
  1707.     {
  1708.         *x = constr->left.GetValue();
  1709.         *y = constr->top.GetValue();
  1710.     }
  1711.     else
  1712.         GetPosition(x, y);
  1713. }
  1714.  
  1715. #endif // wxUSE_CONSTRAINTS
  1716.  
  1717. void wxWindowBase::AdjustForParentClientOrigin(int& x, int& y, int sizeFlags) const
  1718. {
  1719.     // don't do it for the dialogs/frames - they float independently of their
  1720.     // parent
  1721.     if ( !IsTopLevel() )
  1722.     {
  1723.         wxWindow *parent = GetParent();
  1724.         if ( !(sizeFlags & wxSIZE_NO_ADJUSTMENTS) && parent )
  1725.         {
  1726.             wxPoint pt(parent->GetClientAreaOrigin());
  1727.             x += pt.x;
  1728.             y += pt.y;
  1729.         }
  1730.     }
  1731. }
  1732.  
  1733. // ----------------------------------------------------------------------------
  1734. // do Update UI processing for child controls
  1735. // ----------------------------------------------------------------------------
  1736.  
  1737. // TODO: should this be implemented for the child window rather
  1738. // than the parent? Then you can override it e.g. for wxCheckBox
  1739. // to do the Right Thing rather than having to assume a fixed number
  1740. // of control classes.
  1741. void wxWindowBase::UpdateWindowUI()
  1742. {
  1743. #if wxUSE_CONTROLS
  1744.     wxUpdateUIEvent event(GetId());
  1745.     event.m_eventObject = this;
  1746.  
  1747.     if ( GetEventHandler()->ProcessEvent(event) )
  1748.     {
  1749.         if ( event.GetSetEnabled() )
  1750.             Enable(event.GetEnabled());
  1751.  
  1752.         if ( event.GetSetText() )
  1753.         {
  1754.             wxControl *control = wxDynamicCastThis(wxControl);
  1755.             if ( control )
  1756.             {
  1757. #if wxUSE_TEXTCTRL
  1758.                 wxTextCtrl *text = wxDynamicCast(control, wxTextCtrl);
  1759.                 if ( text )
  1760.                     text->SetValue(event.GetText());
  1761.                 else
  1762. #endif // wxUSE_TEXTCTRL
  1763.                     control->SetLabel(event.GetText());
  1764.             }
  1765.         }
  1766.  
  1767. #if wxUSE_CHECKBOX
  1768.         wxCheckBox *checkbox = wxDynamicCastThis(wxCheckBox);
  1769.         if ( checkbox )
  1770.         {
  1771.             if ( event.GetSetChecked() )
  1772.                 checkbox->SetValue(event.GetChecked());
  1773.         }
  1774. #endif // wxUSE_CHECKBOX
  1775.  
  1776. #if wxUSE_RADIOBTN
  1777.         wxRadioButton *radiobtn = wxDynamicCastThis(wxRadioButton);
  1778.         if ( radiobtn )
  1779.         {
  1780.             if ( event.GetSetChecked() )
  1781.                 radiobtn->SetValue(event.GetChecked());
  1782.         }
  1783. #endif // wxUSE_RADIOBTN
  1784.     }
  1785. #endif // wxUSE_CONTROLS
  1786. }
  1787.  
  1788. // ----------------------------------------------------------------------------
  1789. // dialog units translations
  1790. // ----------------------------------------------------------------------------
  1791.  
  1792. wxPoint wxWindowBase::ConvertPixelsToDialog(const wxPoint& pt)
  1793. {
  1794.     int charWidth = GetCharWidth();
  1795.     int charHeight = GetCharHeight();
  1796.     wxPoint pt2(-1, -1);
  1797.     if (pt.x != -1)
  1798.         pt2.x = (int) ((pt.x * 4) / charWidth) ;
  1799.     if (pt.y != -1)
  1800.         pt2.y = (int) ((pt.y * 8) / charHeight) ;
  1801.  
  1802.     return pt2;
  1803. }
  1804.  
  1805. wxPoint wxWindowBase::ConvertDialogToPixels(const wxPoint& pt)
  1806. {
  1807.     int charWidth = GetCharWidth();
  1808.     int charHeight = GetCharHeight();
  1809.     wxPoint pt2(-1, -1);
  1810.     if (pt.x != -1)
  1811.         pt2.x = (int) ((pt.x * charWidth) / 4) ;
  1812.     if (pt.y != -1)
  1813.         pt2.y = (int) ((pt.y * charHeight) / 8) ;
  1814.  
  1815.     return pt2;
  1816. }
  1817.  
  1818. // ----------------------------------------------------------------------------
  1819. // event handlers
  1820. // ----------------------------------------------------------------------------
  1821.  
  1822. // propagate the colour change event to the subwindows
  1823. void wxWindowBase::OnSysColourChanged(wxSysColourChangedEvent& event)
  1824. {
  1825.     wxWindowList::Node *node = GetChildren().GetFirst();
  1826.     while ( node )
  1827.     {
  1828.         // Only propagate to non-top-level windows
  1829.         wxWindow *win = node->GetData();
  1830.         if ( !win->IsTopLevel() )
  1831.         {
  1832.             wxSysColourChangedEvent event2;
  1833.             event.m_eventObject = win;
  1834.             win->GetEventHandler()->ProcessEvent(event2);
  1835.         }
  1836.  
  1837.         node = node->GetNext();
  1838.     }
  1839. }
  1840.  
  1841. // the default action is to populate dialog with data when it's created
  1842. void wxWindowBase::OnInitDialog( wxInitDialogEvent &WXUNUSED(event) )
  1843. {
  1844.     TransferDataToWindow();
  1845. }
  1846.  
  1847. // process Ctrl-Alt-mclick
  1848. void wxWindowBase::OnMiddleClick( wxMouseEvent& event )
  1849. {
  1850. #if wxUSE_MSGDLG
  1851.     if ( event.ControlDown() && event.AltDown() )
  1852.     {
  1853.         // don't translate these strings
  1854.         wxString port;
  1855.  
  1856. #ifdef __WXUNIVERSAL__
  1857.         port = _T("Univ/");
  1858. #endif // __WXUNIVERSAL__
  1859.  
  1860.         switch ( wxGetOsVersion() )
  1861.         {
  1862.             case wxMOTIF_X:     port = _T("Motif"); break;
  1863.             case wxMAC:
  1864.             case wxMAC_DARWIN:  port = _T("Mac"); break;
  1865.             case wxBEOS:        port = _T("BeOS"); break;
  1866.             case wxGTK:
  1867.             case wxGTK_WIN32:
  1868.             case wxGTK_OS2:
  1869.             case wxGTK_BEOS:    port = _T("GTK"); break;
  1870.             case wxWINDOWS:
  1871.             case wxPENWINDOWS:
  1872.             case wxWINDOWS_NT:
  1873.             case wxWIN32S:
  1874.             case wxWIN95:
  1875.             case wxWIN386:      port = _T("MS Windows"); break;
  1876.             case wxMGL_UNIX:
  1877.             case wxMGL_X:
  1878.             case wxMGL_WIN32:
  1879.             case wxMGL_OS2:     port = _T("MGL"); break;
  1880.             case wxWINDOWS_OS2:
  1881.             case wxOS2_PM:      port = _T("OS/2"); break;
  1882.             default:            port = _T("unknown"); break;
  1883.         }
  1884.  
  1885.         wxMessageBox(wxString::Format(
  1886.                                       _T(
  1887.                                         "       wxWindows Library (%s port)\nVersion %u.%u.%u%s, compiled at %s %s\n   Copyright (c) 1995-2002 wxWindows team"
  1888.                                         ),
  1889.                                       port.c_str(),
  1890.                                       wxMAJOR_VERSION,
  1891.                                       wxMINOR_VERSION,
  1892.                                       wxRELEASE_NUMBER,
  1893. #if wxUSE_UNICODE
  1894.                                       L" (Unicode)",
  1895. #else
  1896.                                       "",
  1897. #endif
  1898.                                       __TDATE__,
  1899.                                       __TTIME__
  1900.                                      ),
  1901.                      _T("wxWindows information"),
  1902.                      wxICON_INFORMATION | wxOK,
  1903.                      (wxWindow *)this);
  1904.     }
  1905.     else
  1906. #endif // wxUSE_MSGDLG
  1907.     {
  1908.         event.Skip();
  1909.     }
  1910. }
  1911.  
  1912. // ----------------------------------------------------------------------------
  1913. // list classes implementation
  1914. // ----------------------------------------------------------------------------
  1915.  
  1916. void wxWindowListNode::DeleteData()
  1917. {
  1918.     delete (wxWindow *)GetData();
  1919. }
  1920.  
  1921. // ----------------------------------------------------------------------------
  1922. // borders
  1923. // ----------------------------------------------------------------------------
  1924.  
  1925. wxBorder wxWindowBase::GetBorder() const
  1926. {
  1927.     wxBorder border = (wxBorder)(m_windowStyle & wxBORDER_MASK);
  1928.     if ( border == wxBORDER_DEFAULT )
  1929.     {
  1930.         border = GetDefaultBorder();
  1931.     }
  1932.  
  1933.     return border;
  1934. }
  1935.  
  1936. wxBorder wxWindowBase::GetDefaultBorder() const
  1937. {
  1938.     return wxBORDER_NONE;
  1939. }
  1940.  
  1941. // ----------------------------------------------------------------------------
  1942. // hit testing
  1943. // ----------------------------------------------------------------------------
  1944.  
  1945. wxHitTest wxWindowBase::DoHitTest(wxCoord x, wxCoord y) const
  1946. {
  1947.     // here we just check if the point is inside the window or not
  1948.  
  1949.     // check the top and left border first
  1950.     bool outside = x < 0 || y < 0;
  1951.     if ( !outside )
  1952.     {
  1953.         // check the right and bottom borders too
  1954.         wxSize size = GetSize();
  1955.         outside = x >= size.x || y >= size.y;
  1956.     }
  1957.  
  1958.     return outside ? wxHT_WINDOW_OUTSIDE : wxHT_WINDOW_INSIDE;
  1959. }
  1960.  
  1961. // ----------------------------------------------------------------------------
  1962. // mouse capture
  1963. // ----------------------------------------------------------------------------
  1964.  
  1965. struct WXDLLEXPORT wxWindowNext
  1966. {
  1967.     wxWindow *win;
  1968.     wxWindowNext *next;
  1969. } *wxWindowBase::ms_winCaptureNext = NULL;
  1970.  
  1971. void wxWindowBase::CaptureMouse()
  1972. {
  1973.     wxLogTrace(_T("mousecapture"), _T("CaptureMouse(%p)"), this);
  1974.  
  1975.     wxWindow *winOld = GetCapture();
  1976.     if ( winOld )
  1977.     {
  1978.         ((wxWindowBase*) winOld)->DoReleaseMouse();
  1979.  
  1980.         // save it on stack
  1981.         wxWindowNext *item = new wxWindowNext;
  1982.         item->win = winOld;
  1983.         item->next = ms_winCaptureNext;
  1984.         ms_winCaptureNext = item;
  1985.     }
  1986.     //else: no mouse capture to save
  1987.  
  1988.     DoCaptureMouse();
  1989. }
  1990.  
  1991. void wxWindowBase::ReleaseMouse()
  1992. {
  1993.     wxLogTrace(_T("mousecapture"), _T("ReleaseMouse(%p)"), this);
  1994.  
  1995.     wxASSERT_MSG( GetCapture() == this, wxT("attempt to release mouse, but this window hasn't captured it") );
  1996.  
  1997.     DoReleaseMouse();
  1998.  
  1999.     if ( ms_winCaptureNext )
  2000.     {
  2001.         ((wxWindowBase*)ms_winCaptureNext->win)->DoCaptureMouse();
  2002.  
  2003.         wxWindowNext *item = ms_winCaptureNext;
  2004.         ms_winCaptureNext = item->next;
  2005.         delete item;
  2006.     }
  2007.     //else: stack is empty, no previous capture
  2008.  
  2009.     wxLogTrace(_T("mousecapture"),
  2010.                _T("After ReleaseMouse() mouse is captured by %p"),
  2011.                GetCapture());
  2012. }
  2013.  
  2014. // ----------------------------------------------------------------------------
  2015. // global functions
  2016. // ----------------------------------------------------------------------------
  2017.  
  2018. wxWindow* wxGetTopLevelParent(wxWindow *win)
  2019. {
  2020.     while ( win && !win->IsTopLevel() )
  2021.          win = win->GetParent();
  2022.  
  2023.     return win;
  2024. }
  2025.  
  2026. // vi:sts=4:sw=4:et
  2027.