home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / common / wincmn.cpp < prev    next >
C/C++ Source or Header  |  2003-01-03  |  59KB  |  2,040 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.2.4 2003/01/03 12:56:31 JS 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. // fits virtual size (ie. scrolled area etc.) around children
  474. void wxWindowBase::FitInside()
  475. {
  476.     if ( GetChildren().GetCount() > 0 )
  477.     {
  478.         SetVirtualSize( GetBestVirtualSize() );
  479.     }
  480. }
  481.  
  482. // return the size best suited for the current window
  483. wxSize wxWindowBase::DoGetBestSize() const
  484. {
  485.     if ( m_windowSizer )
  486.     {
  487.         return m_windowSizer->GetMinSize();
  488.     }
  489. #if wxUSE_CONSTRAINTS
  490.     else if ( m_constraints )
  491.     {
  492.         wxConstCast(this, wxWindowBase)->SatisfyConstraints();
  493.  
  494.         // our minimal acceptable size is such that all our windows fit inside
  495.         int maxX = 0,
  496.             maxY = 0;
  497.  
  498.         for ( wxWindowList::Node *node = GetChildren().GetFirst();
  499.               node;
  500.               node = node->GetNext() )
  501.         {
  502.             wxLayoutConstraints *c = node->GetData()->GetConstraints();
  503.             if ( !c )
  504.             {
  505.                 // it's not normal that we have an unconstrained child, but
  506.                 // what can we do about it?
  507.                 continue;
  508.             }
  509.  
  510.             int x = c->right.GetValue(),
  511.                 y = c->bottom.GetValue();
  512.  
  513.             if ( x > maxX )
  514.                 maxX = x;
  515.  
  516.             if ( y > maxY )
  517.                 maxY = y;
  518.  
  519.             // TODO: we must calculate the overlaps somehow, otherwise we
  520.             //       will never return a size bigger than the current one :-(
  521.         }
  522.  
  523.         return wxSize(maxX, maxY);
  524.     }
  525. #endif // wxUSE_CONSTRAINTS
  526.     else if ( GetChildren().GetCount() > 0 )
  527.     {
  528.         // our minimal acceptable size is such that all our windows fit inside
  529.         int maxX = 0,
  530.             maxY = 0;
  531.  
  532.         for ( wxWindowList::Node *node = GetChildren().GetFirst();
  533.               node;
  534.               node = node->GetNext() )
  535.         {
  536.             wxWindow *win = node->GetData();
  537.             if ( win->IsTopLevel()
  538. #if wxUSE_STATUSBAR
  539.                     || wxDynamicCast(win, wxStatusBar)
  540. #endif // wxUSE_STATUSBAR
  541.                )
  542.             {
  543.                 // dialogs and frames lie in different top level windows -
  544.                 // don't deal with them here; as for the status bars, they
  545.                 // don't lie in the client area at all
  546.                 continue;
  547.             }
  548.  
  549.             int wx, wy, ww, wh;
  550.             win->GetPosition(&wx, &wy);
  551.  
  552.             // if the window hadn't been positioned yet, assume that it is in
  553.             // the origin
  554.             if ( wx == -1 )
  555.                 wx = 0;
  556.             if ( wy == -1 )
  557.                 wy = 0;
  558.  
  559.             win->GetSize(&ww, &wh);
  560.             if ( wx + ww > maxX )
  561.                 maxX = wx + ww;
  562.             if ( wy + wh > maxY )
  563.                 maxY = wy + wh;
  564.         }
  565.  
  566.         // for compatibility with the old versions and because it really looks
  567.         // slightly more pretty like this, add a pad
  568.         maxX += 7;
  569.         maxY += 14;
  570.  
  571.         return wxSize(maxX, maxY);
  572.     }
  573.     else
  574.     {
  575.         // for a generic window there is no natural best size - just use the
  576.         // current one
  577.         return GetSize();
  578.     }
  579. }
  580.  
  581. // by default the origin is not shifted
  582. wxPoint wxWindowBase::GetClientAreaOrigin() const
  583. {
  584.     return wxPoint(0, 0);
  585. }
  586.  
  587. // set the min/max size of the window
  588. void wxWindowBase::SetSizeHints(int minW, int minH,
  589.                                 int maxW, int maxH,
  590.                                 int WXUNUSED(incW), int WXUNUSED(incH))
  591. {
  592.     m_minWidth = minW;
  593.     m_maxWidth = maxW;
  594.     m_minHeight = minH;
  595.     m_maxHeight = maxH;
  596. }
  597.  
  598. void wxWindowBase::SetVirtualSizeHints( int minW, int minH,
  599.                                         int maxW, int maxH )
  600. {
  601.     m_minVirtualWidth = minW;
  602.     m_maxVirtualWidth = maxW;
  603.     m_minVirtualHeight = minH;
  604.     m_maxVirtualHeight = maxH;
  605. }
  606.  
  607. void wxWindowBase::DoSetVirtualSize( int x, int y )
  608. {
  609.     if ( m_minVirtualWidth != -1 && m_minVirtualWidth > x )
  610.         x = m_minVirtualWidth;
  611.     if ( m_maxVirtualWidth != -1 && m_maxVirtualWidth < x )
  612.         x = m_maxVirtualWidth;
  613.     if ( m_minVirtualHeight != -1 && m_minVirtualHeight > y )
  614.         y = m_minVirtualHeight;
  615.     if ( m_maxVirtualHeight != -1 && m_maxVirtualHeight < y )
  616.         y = m_maxVirtualHeight;
  617.  
  618.     m_virtualSize = wxSize(x, y);
  619. }
  620.  
  621. wxSize wxWindowBase::DoGetVirtualSize() const
  622. {
  623.     wxSize  s( GetClientSize() );
  624.  
  625.     if( m_virtualSize.GetWidth() != -1 )
  626.         s.SetWidth( m_virtualSize.GetWidth() );
  627.     if( m_virtualSize.GetHeight() != -1 )
  628.         s.SetHeight( m_virtualSize.GetHeight() );
  629.  
  630.     return s;
  631. }
  632.  
  633. // ----------------------------------------------------------------------------
  634. // show/hide/enable/disable the window
  635. // ----------------------------------------------------------------------------
  636.  
  637. bool wxWindowBase::Show(bool show)
  638. {
  639.     if ( show != m_isShown )
  640.     {
  641.         m_isShown = show;
  642.  
  643.         return TRUE;
  644.     }
  645.     else
  646.     {
  647.         return FALSE;
  648.     }
  649. }
  650.  
  651. bool wxWindowBase::Enable(bool enable)
  652. {
  653.     if ( enable != m_isEnabled )
  654.     {
  655.         m_isEnabled = enable;
  656.  
  657.         return TRUE;
  658.     }
  659.     else
  660.     {
  661.         return FALSE;
  662.     }
  663. }
  664. // ----------------------------------------------------------------------------
  665. // RTTI
  666. // ----------------------------------------------------------------------------
  667.  
  668. bool wxWindowBase::IsTopLevel() const
  669. {
  670.     return FALSE;
  671. }
  672.  
  673. // ----------------------------------------------------------------------------
  674. // reparenting the window
  675. // ----------------------------------------------------------------------------
  676.  
  677. void wxWindowBase::AddChild(wxWindowBase *child)
  678. {
  679.     wxCHECK_RET( child, wxT("can't add a NULL child") );
  680.  
  681.     // this should never happen and it will lead to a crash later if it does
  682.     // because RemoveChild() will remove only one node from the children list
  683.     // and the other(s) one(s) will be left with dangling pointers in them
  684.     wxASSERT_MSG( !GetChildren().Find(child), _T("AddChild() called twice") );
  685.  
  686.     GetChildren().Append(child);
  687.     child->SetParent(this);
  688. }
  689.  
  690. void wxWindowBase::RemoveChild(wxWindowBase *child)
  691. {
  692.     wxCHECK_RET( child, wxT("can't remove a NULL child") );
  693.  
  694.     GetChildren().DeleteObject(child);
  695.     child->SetParent((wxWindow *)NULL);
  696. }
  697.  
  698. bool wxWindowBase::Reparent(wxWindowBase *newParent)
  699. {
  700.     wxWindow *oldParent = GetParent();
  701.     if ( newParent == oldParent )
  702.     {
  703.         // nothing done
  704.         return FALSE;
  705.     }
  706.  
  707.     // unlink this window from the existing parent.
  708.     if ( oldParent )
  709.     {
  710.         oldParent->RemoveChild(this);
  711.     }
  712.     else
  713.     {
  714.         wxTopLevelWindows.DeleteObject(this);
  715.     }
  716.  
  717.     // add it to the new one
  718.     if ( newParent )
  719.     {
  720.         newParent->AddChild(this);
  721.     }
  722.     else
  723.     {
  724.         wxTopLevelWindows.Append(this);
  725.     }
  726.  
  727.     return TRUE;
  728. }
  729.  
  730. // ----------------------------------------------------------------------------
  731. // event handler stuff
  732. // ----------------------------------------------------------------------------
  733.  
  734. void wxWindowBase::PushEventHandler(wxEvtHandler *handler)
  735. {
  736.     wxEvtHandler *handlerOld = GetEventHandler();
  737.  
  738.     handler->SetNextHandler(handlerOld);
  739.  
  740.     if ( handlerOld )
  741.         GetEventHandler()->SetPreviousHandler(handler);
  742.  
  743.     SetEventHandler(handler);
  744. }
  745.  
  746. wxEvtHandler *wxWindowBase::PopEventHandler(bool deleteHandler)
  747. {
  748.     wxEvtHandler *handlerA = GetEventHandler();
  749.     if ( handlerA )
  750.     {
  751.         wxEvtHandler *handlerB = handlerA->GetNextHandler();
  752.         handlerA->SetNextHandler((wxEvtHandler *)NULL);
  753.  
  754.         if ( handlerB )
  755.             handlerB->SetPreviousHandler((wxEvtHandler *)NULL);
  756.         SetEventHandler(handlerB);
  757.  
  758.         if ( deleteHandler )
  759.         {
  760.             delete handlerA;
  761.             handlerA = (wxEvtHandler *)NULL;
  762.         }
  763.     }
  764.  
  765.     return handlerA;
  766. }
  767.  
  768. bool wxWindowBase::RemoveEventHandler(wxEvtHandler *handler)
  769. {
  770.     wxCHECK_MSG( handler, FALSE, _T("RemoveEventHandler(NULL) called") );
  771.  
  772.     wxEvtHandler *handlerPrev = NULL,
  773.                  *handlerCur = GetEventHandler();
  774.     while ( handlerCur )
  775.     {
  776.         wxEvtHandler *handlerNext = handlerCur->GetNextHandler();
  777.  
  778.         if ( handlerCur == handler )
  779.         {
  780.             if ( handlerPrev )
  781.             {
  782.                 handlerPrev->SetNextHandler(handlerNext);
  783.             }
  784.             else
  785.             {
  786.                 SetEventHandler(handlerNext);
  787.             }
  788.  
  789.             if ( handlerNext )
  790.             {
  791.                 handlerNext->SetPreviousHandler ( handlerPrev );
  792.             }
  793.             handler->SetNextHandler(NULL);
  794.  
  795.             return TRUE;
  796.         }
  797.  
  798.         handlerPrev = handlerCur;
  799.         handlerCur = handlerNext;
  800.     }
  801.  
  802.     wxFAIL_MSG( _T("where has the event handler gone?") );
  803.  
  804.     return FALSE;
  805. }
  806.  
  807. // ----------------------------------------------------------------------------
  808. // cursors, fonts &c
  809. // ----------------------------------------------------------------------------
  810.  
  811. bool wxWindowBase::SetBackgroundColour( const wxColour &colour )
  812. {
  813.     if ( !colour.Ok() || (colour == m_backgroundColour) )
  814.         return FALSE;
  815.  
  816.     m_backgroundColour = colour;
  817.  
  818.     m_hasBgCol = TRUE;
  819.  
  820.     return TRUE;
  821. }
  822.  
  823. bool wxWindowBase::SetForegroundColour( const wxColour &colour )
  824. {
  825.     if ( !colour.Ok() || (colour == m_foregroundColour) )
  826.         return FALSE;
  827.  
  828.     m_foregroundColour = colour;
  829.  
  830.     m_hasFgCol = TRUE;
  831.  
  832.     return TRUE;
  833. }
  834.  
  835. bool wxWindowBase::SetCursor(const wxCursor& cursor)
  836. {
  837.     // setting an invalid cursor is ok, it means that we don't have any special
  838.     // cursor
  839.     if ( m_cursor == cursor )
  840.     {
  841.         // no change
  842.         return FALSE;
  843.     }
  844.  
  845.     m_cursor = cursor;
  846.  
  847.     return TRUE;
  848. }
  849.  
  850. bool wxWindowBase::SetFont(const wxFont& font)
  851. {
  852.     // don't try to set invalid font, always fall back to the default
  853.     const wxFont& fontOk = font.Ok() ? font : *wxSWISS_FONT;
  854.  
  855.     if ( fontOk == m_font )
  856.     {
  857.         // no change
  858.         return FALSE;
  859.     }
  860.  
  861.     m_font = fontOk;
  862.  
  863.     m_hasFont = TRUE;
  864.  
  865.     return TRUE;
  866. }
  867.  
  868. #if wxUSE_PALETTE
  869.  
  870. void wxWindowBase::SetPalette(const wxPalette& pal)
  871. {
  872.     m_hasCustomPalette = TRUE;
  873.     m_palette = pal;
  874.  
  875.     // VZ: can anyone explain me what do we do here?
  876.     wxWindowDC d((wxWindow *) this);
  877.     d.SetPalette(pal);
  878. }
  879.  
  880. wxWindow *wxWindowBase::GetAncestorWithCustomPalette() const
  881. {
  882.     wxWindow *win = (wxWindow *)this;
  883.     while ( win && !win->HasCustomPalette() )
  884.     {
  885.         win = win->GetParent();
  886.     }
  887.  
  888.     return win;
  889. }
  890.  
  891. #endif // wxUSE_PALETTE
  892.  
  893. #if wxUSE_CARET
  894. void wxWindowBase::SetCaret(wxCaret *caret)
  895. {
  896.     if ( m_caret )
  897.     {
  898.         delete m_caret;
  899.     }
  900.  
  901.     m_caret = caret;
  902.  
  903.     if ( m_caret )
  904.     {
  905.         wxASSERT_MSG( m_caret->GetWindow() == this,
  906.                       wxT("caret should be created associated to this window") );
  907.     }
  908. }
  909. #endif // wxUSE_CARET
  910.  
  911. #if wxUSE_VALIDATORS
  912. // ----------------------------------------------------------------------------
  913. // validators
  914. // ----------------------------------------------------------------------------
  915.  
  916. void wxWindowBase::SetValidator(const wxValidator& validator)
  917. {
  918.     if ( m_windowValidator )
  919.         delete m_windowValidator;
  920.  
  921.     m_windowValidator = (wxValidator *)validator.Clone();
  922.  
  923.     if ( m_windowValidator )
  924.         m_windowValidator->SetWindow(this) ;
  925. }
  926. #endif // wxUSE_VALIDATORS
  927.  
  928. // ----------------------------------------------------------------------------
  929. // update region stuff
  930. // ----------------------------------------------------------------------------
  931.  
  932. wxRect wxWindowBase::GetUpdateClientRect() const
  933. {
  934.     wxRegion rgnUpdate = GetUpdateRegion();
  935.     rgnUpdate.Intersect(GetClientRect());
  936.     wxRect rectUpdate = rgnUpdate.GetBox();
  937.     wxPoint ptOrigin = GetClientAreaOrigin();
  938.     rectUpdate.x -= ptOrigin.x;
  939.     rectUpdate.y -= ptOrigin.y;
  940.  
  941.     return rectUpdate;
  942. }
  943.  
  944. bool wxWindowBase::IsExposed(int x, int y) const
  945. {
  946.     return m_updateRegion.Contains(x, y) != wxOutRegion;
  947. }
  948.  
  949. bool wxWindowBase::IsExposed(int x, int y, int w, int h) const
  950. {
  951.     return m_updateRegion.Contains(x, y, w, h) != wxOutRegion;
  952. }
  953.  
  954. // ----------------------------------------------------------------------------
  955. // find child window by id or name
  956. // ----------------------------------------------------------------------------
  957.  
  958. wxWindow *wxWindowBase::FindWindow( long id )
  959. {
  960.     if ( id == m_windowId )
  961.         return (wxWindow *)this;
  962.  
  963.     wxWindowBase *res = (wxWindow *)NULL;
  964.     wxWindowList::Node *node;
  965.     for ( node = m_children.GetFirst(); node && !res; node = node->GetNext() )
  966.     {
  967.         wxWindowBase *child = node->GetData();
  968.         res = child->FindWindow( id );
  969.     }
  970.  
  971.     return (wxWindow *)res;
  972. }
  973.  
  974. wxWindow *wxWindowBase::FindWindow( const wxString& name )
  975. {
  976.     if ( name == m_windowName )
  977.         return (wxWindow *)this;
  978.  
  979.     wxWindowBase *res = (wxWindow *)NULL;
  980.     wxWindowList::Node *node;
  981.     for ( node = m_children.GetFirst(); node && !res; node = node->GetNext() )
  982.     {
  983.         wxWindow *child = node->GetData();
  984.         res = child->FindWindow(name);
  985.     }
  986.  
  987.     return (wxWindow *)res;
  988. }
  989.  
  990.  
  991. // find any window by id or name or label: If parent is non-NULL, look through
  992. // children for a label or title matching the specified string. If NULL, look
  993. // through all top-level windows.
  994. //
  995. // to avoid duplicating code we reuse the same helper function but with
  996. // different comparators
  997.  
  998. typedef bool (*wxFindWindowCmp)(const wxWindow *win,
  999.                                 const wxString& label, long id);
  1000.  
  1001. static
  1002. bool wxFindWindowCmpLabels(const wxWindow *win, const wxString& label,
  1003.                            long WXUNUSED(id))
  1004. {
  1005.     return win->GetLabel() == label;
  1006. }
  1007.  
  1008. static
  1009. bool wxFindWindowCmpNames(const wxWindow *win, const wxString& label,
  1010.                           long WXUNUSED(id))
  1011. {
  1012.     return win->GetName() == label;
  1013. }
  1014.  
  1015. static
  1016. bool wxFindWindowCmpIds(const wxWindow *win, const wxString& WXUNUSED(label),
  1017.                         long id)
  1018. {
  1019.     return win->GetId() == id;
  1020. }
  1021.  
  1022. // recursive helper for the FindWindowByXXX() functions
  1023. static
  1024. wxWindow *wxFindWindowRecursively(const wxWindow *parent,
  1025.                                   const wxString& label,
  1026.                                   long id,
  1027.                                   wxFindWindowCmp cmp)
  1028. {
  1029.     if ( parent )
  1030.     {
  1031.         // see if this is the one we're looking for
  1032.         if ( (*cmp)(parent, label, id) )
  1033.             return (wxWindow *)parent;
  1034.  
  1035.         // It wasn't, so check all its children
  1036.         for ( wxWindowList::Node * node = parent->GetChildren().GetFirst();
  1037.               node;
  1038.               node = node->GetNext() )
  1039.         {
  1040.             // recursively check each child
  1041.             wxWindow *win = (wxWindow *)node->GetData();
  1042.             wxWindow *retwin = wxFindWindowRecursively(win, label, id, cmp);
  1043.             if (retwin)
  1044.                 return retwin;
  1045.         }
  1046.     }
  1047.  
  1048.     // Not found
  1049.     return NULL;
  1050. }
  1051.  
  1052. // helper for FindWindowByXXX()
  1053. static
  1054. wxWindow *wxFindWindowHelper(const wxWindow *parent,
  1055.                              const wxString& label,
  1056.                              long id,
  1057.                              wxFindWindowCmp cmp)
  1058. {
  1059.     if ( parent )
  1060.     {
  1061.         // just check parent and all its children
  1062.         return wxFindWindowRecursively(parent, label, id, cmp);
  1063.     }
  1064.  
  1065.     // start at very top of wx's windows
  1066.     for ( wxWindowList::Node * node = wxTopLevelWindows.GetFirst();
  1067.           node;
  1068.           node = node->GetNext() )
  1069.     {
  1070.         // recursively check each window & its children
  1071.         wxWindow *win = node->GetData();
  1072.         wxWindow *retwin = wxFindWindowRecursively(win, label, id, cmp);
  1073.         if (retwin)
  1074.             return retwin;
  1075.     }
  1076.  
  1077.     return NULL;
  1078. }
  1079.  
  1080. /* static */
  1081. wxWindow *
  1082. wxWindowBase::FindWindowByLabel(const wxString& title, const wxWindow *parent)
  1083. {
  1084.     return wxFindWindowHelper(parent, title, 0, wxFindWindowCmpLabels);
  1085. }
  1086.  
  1087. /* static */
  1088. wxWindow *
  1089. wxWindowBase::FindWindowByName(const wxString& title, const wxWindow *parent)
  1090. {
  1091.     wxWindow *win = wxFindWindowHelper(parent, title, 0, wxFindWindowCmpNames);
  1092.  
  1093.     if ( !win )
  1094.     {
  1095.         // fall back to the label
  1096.         win = FindWindowByLabel(title, parent);
  1097.     }
  1098.  
  1099.     return win;
  1100. }
  1101.  
  1102. /* static */
  1103. wxWindow *
  1104. wxWindowBase::FindWindowById( long id, const wxWindow* parent )
  1105. {
  1106.     return wxFindWindowHelper(parent, _T(""), id, wxFindWindowCmpIds);
  1107. }
  1108.  
  1109. // ----------------------------------------------------------------------------
  1110. // dialog oriented functions
  1111. // ----------------------------------------------------------------------------
  1112.  
  1113. void wxWindowBase::MakeModal(bool modal)
  1114. {
  1115.     // Disable all other windows
  1116.     if ( IsTopLevel() )
  1117.     {
  1118.         wxWindowList::Node *node = wxTopLevelWindows.GetFirst();
  1119.         while (node)
  1120.         {
  1121.             wxWindow *win = node->GetData();
  1122.             if (win != this)
  1123.                 win->Enable(!modal);
  1124.  
  1125.             node = node->GetNext();
  1126.         }
  1127.     }
  1128. }
  1129.  
  1130. bool wxWindowBase::Validate()
  1131. {
  1132. #if wxUSE_VALIDATORS
  1133.     bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0;
  1134.  
  1135.     wxWindowList::Node *node;
  1136.     for ( node = m_children.GetFirst(); node; node = node->GetNext() )
  1137.     {
  1138.         wxWindowBase *child = node->GetData();
  1139.         wxValidator *validator = child->GetValidator();
  1140.         if ( validator && !validator->Validate((wxWindow *)this) )
  1141.         {
  1142.             return FALSE;
  1143.         }
  1144.  
  1145.         if ( recurse && !child->Validate() )
  1146.         {
  1147.             return FALSE;
  1148.         }
  1149.     }
  1150. #endif // wxUSE_VALIDATORS
  1151.  
  1152.     return TRUE;
  1153. }
  1154.  
  1155. bool wxWindowBase::TransferDataToWindow()
  1156. {
  1157. #if wxUSE_VALIDATORS
  1158.     bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0;
  1159.  
  1160.     wxWindowList::Node *node;
  1161.     for ( node = m_children.GetFirst(); node; node = node->GetNext() )
  1162.     {
  1163.         wxWindowBase *child = node->GetData();
  1164.         wxValidator *validator = child->GetValidator();
  1165.         if ( validator && !validator->TransferToWindow() )
  1166.         {
  1167.             wxLogWarning(_("Could not transfer data to window"));
  1168.             wxLog::FlushActive();
  1169.  
  1170.             return FALSE;
  1171.         }
  1172.  
  1173.         if ( recurse )
  1174.         {
  1175.             if ( !child->TransferDataToWindow() )
  1176.             {
  1177.                 // warning already given
  1178.                 return FALSE;
  1179.             }
  1180.         }
  1181.     }
  1182. #endif // wxUSE_VALIDATORS
  1183.  
  1184.     return TRUE;
  1185. }
  1186.  
  1187. bool wxWindowBase::TransferDataFromWindow()
  1188. {
  1189. #if wxUSE_VALIDATORS
  1190.     bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0;
  1191.  
  1192.     wxWindowList::Node *node;
  1193.     for ( node = m_children.GetFirst(); node; node = node->GetNext() )
  1194.     {
  1195.         wxWindow *child = node->GetData();
  1196.         wxValidator *validator = child->GetValidator();
  1197.         if ( validator && !validator->TransferFromWindow() )
  1198.         {
  1199.             // nop warning here because the application is supposed to give
  1200.             // one itself - we don't know here what might have gone wrongly
  1201.  
  1202.             return FALSE;
  1203.         }
  1204.  
  1205.         if ( recurse )
  1206.         {
  1207.             if ( !child->TransferDataFromWindow() )
  1208.             {
  1209.                 // warning already given
  1210.                 return FALSE;
  1211.             }
  1212.         }
  1213.     }
  1214. #endif // wxUSE_VALIDATORS
  1215.  
  1216.     return TRUE;
  1217. }
  1218.  
  1219. void wxWindowBase::InitDialog()
  1220. {
  1221.     wxInitDialogEvent event(GetId());
  1222.     event.SetEventObject( this );
  1223.     GetEventHandler()->ProcessEvent(event);
  1224. }
  1225.  
  1226. // ----------------------------------------------------------------------------
  1227. // context-sensitive help support
  1228. // ----------------------------------------------------------------------------
  1229.  
  1230. #if wxUSE_HELP
  1231.  
  1232. // associate this help text with this window
  1233. void wxWindowBase::SetHelpText(const wxString& text)
  1234. {
  1235.     wxHelpProvider *helpProvider = wxHelpProvider::Get();
  1236.     if ( helpProvider )
  1237.     {
  1238.         helpProvider->AddHelp(this, text);
  1239.     }
  1240. }
  1241.  
  1242. // associate this help text with all windows with the same id as this
  1243. // one
  1244. void wxWindowBase::SetHelpTextForId(const wxString& text)
  1245. {
  1246.     wxHelpProvider *helpProvider = wxHelpProvider::Get();
  1247.     if ( helpProvider )
  1248.     {
  1249.         helpProvider->AddHelp(GetId(), text);
  1250.     }
  1251. }
  1252.  
  1253. // get the help string associated with this window (may be empty)
  1254. wxString wxWindowBase::GetHelpText() const
  1255. {
  1256.     wxString text;
  1257.     wxHelpProvider *helpProvider = wxHelpProvider::Get();
  1258.     if ( helpProvider )
  1259.     {
  1260.         text = helpProvider->GetHelp(this);
  1261.     }
  1262.  
  1263.     return text;
  1264. }
  1265.  
  1266. // show help for this window
  1267. void wxWindowBase::OnHelp(wxHelpEvent& event)
  1268. {
  1269.     wxHelpProvider *helpProvider = wxHelpProvider::Get();
  1270.     if ( helpProvider )
  1271.     {
  1272.         if ( helpProvider->ShowHelp(this) )
  1273.         {
  1274.             // skip the event.Skip() below
  1275.             return;
  1276.         }
  1277.     }
  1278.  
  1279.     event.Skip();
  1280. }
  1281.  
  1282. #endif // wxUSE_HELP
  1283.  
  1284. // ----------------------------------------------------------------------------
  1285. // tooltipsroot.Replace("\\", "/");
  1286. // ----------------------------------------------------------------------------
  1287.  
  1288. #if wxUSE_TOOLTIPS
  1289.  
  1290. void wxWindowBase::SetToolTip( const wxString &tip )
  1291. {
  1292.     // don't create the new tooltip if we already have one
  1293.     if ( m_tooltip )
  1294.     {
  1295.         m_tooltip->SetTip( tip );
  1296.     }
  1297.     else
  1298.     {
  1299.         SetToolTip( new wxToolTip( tip ) );
  1300.     }
  1301.  
  1302.     // setting empty tooltip text does not remove the tooltip any more - use
  1303.     // SetToolTip((wxToolTip *)NULL) for this
  1304. }
  1305.  
  1306. void wxWindowBase::DoSetToolTip(wxToolTip *tooltip)
  1307. {
  1308.     if ( m_tooltip )
  1309.         delete m_tooltip;
  1310.  
  1311.     m_tooltip = tooltip;
  1312. }
  1313.  
  1314. #endif // wxUSE_TOOLTIPS
  1315.  
  1316. // ----------------------------------------------------------------------------
  1317. // constraints and sizers
  1318. // ----------------------------------------------------------------------------
  1319.  
  1320. #if wxUSE_CONSTRAINTS
  1321.  
  1322. void wxWindowBase::SetConstraints( wxLayoutConstraints *constraints )
  1323. {
  1324.     if ( m_constraints )
  1325.     {
  1326.         UnsetConstraints(m_constraints);
  1327.         delete m_constraints;
  1328.     }
  1329.     m_constraints = constraints;
  1330.     if ( m_constraints )
  1331.     {
  1332.         // Make sure other windows know they're part of a 'meaningful relationship'
  1333.         if ( m_constraints->left.GetOtherWindow() && (m_constraints->left.GetOtherWindow() != this) )
  1334.             m_constraints->left.GetOtherWindow()->AddConstraintReference(this);
  1335.         if ( m_constraints->top.GetOtherWindow() && (m_constraints->top.GetOtherWindow() != this) )
  1336.             m_constraints->top.GetOtherWindow()->AddConstraintReference(this);
  1337.         if ( m_constraints->right.GetOtherWindow() && (m_constraints->right.GetOtherWindow() != this) )
  1338.             m_constraints->right.GetOtherWindow()->AddConstraintReference(this);
  1339.         if ( m_constraints->bottom.GetOtherWindow() && (m_constraints->bottom.GetOtherWindow() != this) )
  1340.             m_constraints->bottom.GetOtherWindow()->AddConstraintReference(this);
  1341.         if ( m_constraints->width.GetOtherWindow() && (m_constraints->width.GetOtherWindow() != this) )
  1342.             m_constraints->width.GetOtherWindow()->AddConstraintReference(this);
  1343.         if ( m_constraints->height.GetOtherWindow() && (m_constraints->height.GetOtherWindow() != this) )
  1344.             m_constraints->height.GetOtherWindow()->AddConstraintReference(this);
  1345.         if ( m_constraints->centreX.GetOtherWindow() && (m_constraints->centreX.GetOtherWindow() != this) )
  1346.             m_constraints->centreX.GetOtherWindow()->AddConstraintReference(this);
  1347.         if ( m_constraints->centreY.GetOtherWindow() && (m_constraints->centreY.GetOtherWindow() != this) )
  1348.             m_constraints->centreY.GetOtherWindow()->AddConstraintReference(this);
  1349.     }
  1350. }
  1351.  
  1352. // This removes any dangling pointers to this window in other windows'
  1353. // constraintsInvolvedIn lists.
  1354. void wxWindowBase::UnsetConstraints(wxLayoutConstraints *c)
  1355. {
  1356.     if ( c )
  1357.     {
  1358.         if ( c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this) )
  1359.             c->left.GetOtherWindow()->RemoveConstraintReference(this);
  1360.         if ( c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this) )
  1361.             c->top.GetOtherWindow()->RemoveConstraintReference(this);
  1362.         if ( c->right.GetOtherWindow() && (c->right.GetOtherWindow() != this) )
  1363.             c->right.GetOtherWindow()->RemoveConstraintReference(this);
  1364.         if ( c->bottom.GetOtherWindow() && (c->bottom.GetOtherWindow() != this) )
  1365.             c->bottom.GetOtherWindow()->RemoveConstraintReference(this);
  1366.         if ( c->width.GetOtherWindow() && (c->width.GetOtherWindow() != this) )
  1367.             c->width.GetOtherWindow()->RemoveConstraintReference(this);
  1368.         if ( c->height.GetOtherWindow() && (c->height.GetOtherWindow() != this) )
  1369.             c->height.GetOtherWindow()->RemoveConstraintReference(this);
  1370.         if ( c->centreX.GetOtherWindow() && (c->centreX.GetOtherWindow() != this) )
  1371.             c->centreX.GetOtherWindow()->RemoveConstraintReference(this);
  1372.         if ( c->centreY.GetOtherWindow() && (c->centreY.GetOtherWindow() != this) )
  1373.             c->centreY.GetOtherWindow()->RemoveConstraintReference(this);
  1374.     }
  1375. }
  1376.  
  1377. // Back-pointer to other windows we're involved with, so if we delete this
  1378. // window, we must delete any constraints we're involved with.
  1379. void wxWindowBase::AddConstraintReference(wxWindowBase *otherWin)
  1380. {
  1381.     if ( !m_constraintsInvolvedIn )
  1382.         m_constraintsInvolvedIn = new wxWindowList;
  1383.     if ( !m_constraintsInvolvedIn->Find(otherWin) )
  1384.         m_constraintsInvolvedIn->Append(otherWin);
  1385. }
  1386.  
  1387. // REMOVE back-pointer to other windows we're involved with.
  1388. void wxWindowBase::RemoveConstraintReference(wxWindowBase *otherWin)
  1389. {
  1390.     if ( m_constraintsInvolvedIn )
  1391.         m_constraintsInvolvedIn->DeleteObject(otherWin);
  1392. }
  1393.  
  1394. // Reset any constraints that mention this window
  1395. void wxWindowBase::DeleteRelatedConstraints()
  1396. {
  1397.     if ( m_constraintsInvolvedIn )
  1398.     {
  1399.         wxWindowList::Node *node = m_constraintsInvolvedIn->GetFirst();
  1400.         while (node)
  1401.         {
  1402.             wxWindow *win = node->GetData();
  1403.             wxLayoutConstraints *constr = win->GetConstraints();
  1404.  
  1405.             // Reset any constraints involving this window
  1406.             if ( constr )
  1407.             {
  1408.                 constr->left.ResetIfWin(this);
  1409.                 constr->top.ResetIfWin(this);
  1410.                 constr->right.ResetIfWin(this);
  1411.                 constr->bottom.ResetIfWin(this);
  1412.                 constr->width.ResetIfWin(this);
  1413.                 constr->height.ResetIfWin(this);
  1414.                 constr->centreX.ResetIfWin(this);
  1415.                 constr->centreY.ResetIfWin(this);
  1416.             }
  1417.  
  1418.             wxWindowList::Node *next = node->GetNext();
  1419.             delete node;
  1420.             node = next;
  1421.         }
  1422.  
  1423.         delete m_constraintsInvolvedIn;
  1424.         m_constraintsInvolvedIn = (wxWindowList *) NULL;
  1425.     }
  1426. }
  1427.  
  1428. #endif // wxUSE_CONSTRAINTS
  1429.  
  1430. void wxWindowBase::SetSizer(wxSizer *sizer, bool deleteOld)
  1431. {
  1432.     if ( deleteOld )
  1433.         delete m_windowSizer;
  1434.  
  1435.     m_windowSizer = sizer;
  1436.  
  1437.     SetAutoLayout( sizer != NULL );
  1438. }
  1439.  
  1440. void wxWindowBase::SetSizerAndFit(wxSizer *sizer, bool deleteOld)
  1441. {
  1442.     SetSizer( sizer, deleteOld );
  1443.     sizer->SetSizeHints( (wxWindow*) this );
  1444. }
  1445.  
  1446. #if wxUSE_CONSTRAINTS
  1447.  
  1448. void wxWindowBase::SatisfyConstraints()
  1449. {
  1450.     wxLayoutConstraints *constr = GetConstraints();
  1451.     bool wasOk = constr && constr->AreSatisfied();
  1452.  
  1453.     ResetConstraints();   // Mark all constraints as unevaluated
  1454.  
  1455.     int noChanges = 1;
  1456.  
  1457.     // if we're a top level panel (i.e. our parent is frame/dialog), our
  1458.     // own constraints will never be satisfied any more unless we do it
  1459.     // here
  1460.     if ( wasOk )
  1461.     {
  1462.         while ( noChanges > 0 )
  1463.         {
  1464.             LayoutPhase1(&noChanges);
  1465.         }
  1466.     }
  1467.  
  1468.     LayoutPhase2(&noChanges);
  1469. }
  1470.  
  1471. #endif // wxUSE_CONSTRAINTS
  1472.  
  1473. bool wxWindowBase::Layout()
  1474. {
  1475.     // If there is a sizer, use it instead of the constraints
  1476.     if ( GetSizer() )
  1477.     {
  1478.         int w, h;
  1479.         GetVirtualSize(&w, &h);
  1480.         GetSizer()->SetDimension( 0, 0, w, h );
  1481.     }
  1482. #if wxUSE_CONSTRAINTS
  1483.     else
  1484.     {
  1485.         SatisfyConstraints(); // Find the right constraints values
  1486.         SetConstraintSizes(); // Recursively set the real window sizes
  1487.     }
  1488. #endif
  1489.  
  1490.     return TRUE;
  1491. }
  1492.  
  1493. #if wxUSE_CONSTRAINTS
  1494.  
  1495. // first phase of the constraints evaluation: set our own constraints
  1496. bool wxWindowBase::LayoutPhase1(int *noChanges)
  1497. {
  1498.     wxLayoutConstraints *constr = GetConstraints();
  1499.  
  1500.     return !constr || constr->SatisfyConstraints(this, noChanges);
  1501. }
  1502.  
  1503. // second phase: set the constraints for our children
  1504. bool wxWindowBase::LayoutPhase2(int *noChanges)
  1505. {
  1506.     *noChanges = 0;
  1507.  
  1508.     // Layout children
  1509.     DoPhase(1);
  1510.  
  1511.     // Layout grand children
  1512.     DoPhase(2);
  1513.  
  1514.     return TRUE;
  1515. }
  1516.  
  1517. // Do a phase of evaluating child constraints
  1518. bool wxWindowBase::DoPhase(int phase)
  1519. {
  1520.     // the list containing the children for which the constraints are already
  1521.     // set correctly
  1522.     wxWindowList succeeded;
  1523.  
  1524.     // the max number of iterations we loop before concluding that we can't set
  1525.     // the constraints
  1526.     static const int maxIterations = 500;
  1527.  
  1528.     for ( int noIterations = 0; noIterations < maxIterations; noIterations++ )
  1529.     {
  1530.         int noChanges = 0;
  1531.  
  1532.         // loop over all children setting their constraints
  1533.         for ( wxWindowList::Node *node = GetChildren().GetFirst();
  1534.               node;
  1535.               node = node->GetNext() )
  1536.         {
  1537.             wxWindow *child = node->GetData();
  1538.             if ( child->IsTopLevel() )
  1539.             {
  1540.                 // top level children are not inside our client area
  1541.                 continue;
  1542.             }
  1543.  
  1544.             if ( !child->GetConstraints() || succeeded.Find(child) )
  1545.             {
  1546.                 // this one is either already ok or nothing we can do about it
  1547.                 continue;
  1548.             }
  1549.  
  1550.             int tempNoChanges = 0;
  1551.             bool success = phase == 1 ? child->LayoutPhase1(&tempNoChanges)
  1552.                                       : child->LayoutPhase2(&tempNoChanges);
  1553.             noChanges += tempNoChanges;
  1554.  
  1555.             if ( success )
  1556.             {
  1557.                 succeeded.Append(child);
  1558.             }
  1559.         }
  1560.  
  1561.         if ( !noChanges )
  1562.         {
  1563.             // constraints are set
  1564.             break;
  1565.         }
  1566.     }
  1567.  
  1568.     return TRUE;
  1569. }
  1570.  
  1571. void wxWindowBase::ResetConstraints()
  1572. {
  1573.     wxLayoutConstraints *constr = GetConstraints();
  1574.     if ( constr )
  1575.     {
  1576.         constr->left.SetDone(FALSE);
  1577.         constr->top.SetDone(FALSE);
  1578.         constr->right.SetDone(FALSE);
  1579.         constr->bottom.SetDone(FALSE);
  1580.         constr->width.SetDone(FALSE);
  1581.         constr->height.SetDone(FALSE);
  1582.         constr->centreX.SetDone(FALSE);
  1583.         constr->centreY.SetDone(FALSE);
  1584.     }
  1585.  
  1586.     wxWindowList::Node *node = GetChildren().GetFirst();
  1587.     while (node)
  1588.     {
  1589.         wxWindow *win = node->GetData();
  1590.         if ( !win->IsTopLevel() )
  1591.             win->ResetConstraints();
  1592.         node = node->GetNext();
  1593.     }
  1594. }
  1595.  
  1596. // Need to distinguish between setting the 'fake' size for windows and sizers,
  1597. // and setting the real values.
  1598. void wxWindowBase::SetConstraintSizes(bool recurse)
  1599. {
  1600.     wxLayoutConstraints *constr = GetConstraints();
  1601.     if ( constr && constr->AreSatisfied() )
  1602.     {
  1603.         int x = constr->left.GetValue();
  1604.         int y = constr->top.GetValue();
  1605.         int w = constr->width.GetValue();
  1606.         int h = constr->height.GetValue();
  1607.  
  1608.         if ( (constr->width.GetRelationship() != wxAsIs ) ||
  1609.              (constr->height.GetRelationship() != wxAsIs) )
  1610.         {
  1611.             SetSize(x, y, w, h);
  1612.         }
  1613.         else
  1614.         {
  1615.             // If we don't want to resize this window, just move it...
  1616.             Move(x, y);
  1617.         }
  1618.     }
  1619.     else if ( constr )
  1620.     {
  1621.         wxLogDebug(wxT("Constraints not satisfied for %s named '%s'."),
  1622.                    GetClassInfo()->GetClassName(),
  1623.                    GetName().c_str());
  1624.     }
  1625.  
  1626.     if ( recurse )
  1627.     {
  1628.         wxWindowList::Node *node = GetChildren().GetFirst();
  1629.         while (node)
  1630.         {
  1631.             wxWindow *win = node->GetData();
  1632.             if ( !win->IsTopLevel() && win->GetConstraints() )
  1633.                 win->SetConstraintSizes();
  1634.             node = node->GetNext();
  1635.         }
  1636.     }
  1637. }
  1638.  
  1639. // Only set the size/position of the constraint (if any)
  1640. void wxWindowBase::SetSizeConstraint(int x, int y, int w, int h)
  1641. {
  1642.     wxLayoutConstraints *constr = GetConstraints();
  1643.     if ( constr )
  1644.     {
  1645.         if ( x != -1 )
  1646.         {
  1647.             constr->left.SetValue(x);
  1648.             constr->left.SetDone(TRUE);
  1649.         }
  1650.         if ( y != -1 )
  1651.         {
  1652.             constr->top.SetValue(y);
  1653.             constr->top.SetDone(TRUE);
  1654.         }
  1655.         if ( w != -1 )
  1656.         {
  1657.             constr->width.SetValue(w);
  1658.             constr->width.SetDone(TRUE);
  1659.         }
  1660.         if ( h != -1 )
  1661.         {
  1662.             constr->height.SetValue(h);
  1663.             constr->height.SetDone(TRUE);
  1664.         }
  1665.     }
  1666. }
  1667.  
  1668. void wxWindowBase::MoveConstraint(int x, int y)
  1669. {
  1670.     wxLayoutConstraints *constr = GetConstraints();
  1671.     if ( constr )
  1672.     {
  1673.         if ( x != -1 )
  1674.         {
  1675.             constr->left.SetValue(x);
  1676.             constr->left.SetDone(TRUE);
  1677.         }
  1678.         if ( y != -1 )
  1679.         {
  1680.             constr->top.SetValue(y);
  1681.             constr->top.SetDone(TRUE);
  1682.         }
  1683.     }
  1684. }
  1685.  
  1686. void wxWindowBase::GetSizeConstraint(int *w, int *h) const
  1687. {
  1688.     wxLayoutConstraints *constr = GetConstraints();
  1689.     if ( constr )
  1690.     {
  1691.         *w = constr->width.GetValue();
  1692.         *h = constr->height.GetValue();
  1693.     }
  1694.     else
  1695.         GetSize(w, h);
  1696. }
  1697.  
  1698. void wxWindowBase::GetClientSizeConstraint(int *w, int *h) const
  1699. {
  1700.     wxLayoutConstraints *constr = GetConstraints();
  1701.     if ( constr )
  1702.     {
  1703.         *w = constr->width.GetValue();
  1704.         *h = constr->height.GetValue();
  1705.     }
  1706.     else
  1707.         GetClientSize(w, h);
  1708. }
  1709.  
  1710. void wxWindowBase::GetPositionConstraint(int *x, int *y) const
  1711. {
  1712.     wxLayoutConstraints *constr = GetConstraints();
  1713.     if ( constr )
  1714.     {
  1715.         *x = constr->left.GetValue();
  1716.         *y = constr->top.GetValue();
  1717.     }
  1718.     else
  1719.         GetPosition(x, y);
  1720. }
  1721.  
  1722. #endif // wxUSE_CONSTRAINTS
  1723.  
  1724. void wxWindowBase::AdjustForParentClientOrigin(int& x, int& y, int sizeFlags) const
  1725. {
  1726.     // don't do it for the dialogs/frames - they float independently of their
  1727.     // parent
  1728.     if ( !IsTopLevel() )
  1729.     {
  1730.         wxWindow *parent = GetParent();
  1731.         if ( !(sizeFlags & wxSIZE_NO_ADJUSTMENTS) && parent )
  1732.         {
  1733.             wxPoint pt(parent->GetClientAreaOrigin());
  1734.             x += pt.x;
  1735.             y += pt.y;
  1736.         }
  1737.     }
  1738. }
  1739.  
  1740. // ----------------------------------------------------------------------------
  1741. // do Update UI processing for child controls
  1742. // ----------------------------------------------------------------------------
  1743.  
  1744. // TODO: should this be implemented for the child window rather
  1745. // than the parent? Then you can override it e.g. for wxCheckBox
  1746. // to do the Right Thing rather than having to assume a fixed number
  1747. // of control classes.
  1748. void wxWindowBase::UpdateWindowUI()
  1749. {
  1750. #if wxUSE_CONTROLS
  1751.     wxUpdateUIEvent event(GetId());
  1752.     event.m_eventObject = this;
  1753.  
  1754.     if ( GetEventHandler()->ProcessEvent(event) )
  1755.     {
  1756.         if ( event.GetSetEnabled() )
  1757.             Enable(event.GetEnabled());
  1758.  
  1759.         if ( event.GetSetText() )
  1760.         {
  1761.             wxControl *control = wxDynamicCastThis(wxControl);
  1762.             if ( control )
  1763.             {
  1764. #if wxUSE_TEXTCTRL
  1765.                 wxTextCtrl *text = wxDynamicCast(control, wxTextCtrl);
  1766.                 if ( text )
  1767.                 {
  1768.                     if ( event.GetText() != text->GetValue() )
  1769.                         text->SetValue(event.GetText());
  1770.                 }
  1771.                 else
  1772. #endif // wxUSE_TEXTCTRL
  1773.                 {
  1774.                     if ( event.GetText() != control->GetLabel() )
  1775.                         control->SetLabel(event.GetText());
  1776.                 }
  1777.             }
  1778.         }
  1779.  
  1780. #if wxUSE_CHECKBOX
  1781.         wxCheckBox *checkbox = wxDynamicCastThis(wxCheckBox);
  1782.         if ( checkbox )
  1783.         {
  1784.             if ( event.GetSetChecked() )
  1785.                 checkbox->SetValue(event.GetChecked());
  1786.         }
  1787. #endif // wxUSE_CHECKBOX
  1788.  
  1789. #if wxUSE_RADIOBTN
  1790.         wxRadioButton *radiobtn = wxDynamicCastThis(wxRadioButton);
  1791.         if ( radiobtn )
  1792.         {
  1793.             if ( event.GetSetChecked() )
  1794.                 radiobtn->SetValue(event.GetChecked());
  1795.         }
  1796. #endif // wxUSE_RADIOBTN
  1797.     }
  1798. #endif // wxUSE_CONTROLS
  1799. }
  1800.  
  1801. // ----------------------------------------------------------------------------
  1802. // dialog units translations
  1803. // ----------------------------------------------------------------------------
  1804.  
  1805. wxPoint wxWindowBase::ConvertPixelsToDialog(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 * 4) / charWidth) ;
  1812.     if (pt.y != -1)
  1813.         pt2.y = (int) ((pt.y * 8) / charHeight) ;
  1814.  
  1815.     return pt2;
  1816. }
  1817.  
  1818. wxPoint wxWindowBase::ConvertDialogToPixels(const wxPoint& pt)
  1819. {
  1820.     int charWidth = GetCharWidth();
  1821.     int charHeight = GetCharHeight();
  1822.     wxPoint pt2(-1, -1);
  1823.     if (pt.x != -1)
  1824.         pt2.x = (int) ((pt.x * charWidth) / 4) ;
  1825.     if (pt.y != -1)
  1826.         pt2.y = (int) ((pt.y * charHeight) / 8) ;
  1827.  
  1828.     return pt2;
  1829. }
  1830.  
  1831. // ----------------------------------------------------------------------------
  1832. // event handlers
  1833. // ----------------------------------------------------------------------------
  1834.  
  1835. // propagate the colour change event to the subwindows
  1836. void wxWindowBase::OnSysColourChanged(wxSysColourChangedEvent& event)
  1837. {
  1838.     wxWindowList::Node *node = GetChildren().GetFirst();
  1839.     while ( node )
  1840.     {
  1841.         // Only propagate to non-top-level windows
  1842.         wxWindow *win = node->GetData();
  1843.         if ( !win->IsTopLevel() )
  1844.         {
  1845.             wxSysColourChangedEvent event2;
  1846.             event.m_eventObject = win;
  1847.             win->GetEventHandler()->ProcessEvent(event2);
  1848.         }
  1849.  
  1850.         node = node->GetNext();
  1851.     }
  1852. }
  1853.  
  1854. // the default action is to populate dialog with data when it's created
  1855. void wxWindowBase::OnInitDialog( wxInitDialogEvent &WXUNUSED(event) )
  1856. {
  1857.     TransferDataToWindow();
  1858. }
  1859.  
  1860. // process Ctrl-Alt-mclick
  1861. void wxWindowBase::OnMiddleClick( wxMouseEvent& event )
  1862. {
  1863. #if wxUSE_MSGDLG
  1864.     if ( event.ControlDown() && event.AltDown() )
  1865.     {
  1866.         // don't translate these strings
  1867.         wxString port;
  1868.  
  1869. #ifdef __WXUNIVERSAL__
  1870.         port = _T("Univ/");
  1871. #endif // __WXUNIVERSAL__
  1872.  
  1873.         switch ( wxGetOsVersion() )
  1874.         {
  1875.             case wxMOTIF_X:     port += _T("Motif"); break;
  1876.             case wxMAC:
  1877.             case wxMAC_DARWIN:  port += _T("Mac"); break;
  1878.             case wxBEOS:        port += _T("BeOS"); break;
  1879.             case wxGTK:
  1880.             case wxGTK_WIN32:
  1881.             case wxGTK_OS2:
  1882.             case wxGTK_BEOS:    port += _T("GTK"); break;
  1883.             case wxWINDOWS:
  1884.             case wxPENWINDOWS:
  1885.             case wxWINDOWS_NT:
  1886.             case wxWIN32S:
  1887.             case wxWIN95:
  1888.             case wxWIN386:      port += _T("MS Windows"); break;
  1889.             case wxMGL_UNIX:
  1890.             case wxMGL_X:
  1891.             case wxMGL_WIN32:
  1892.             case wxMGL_OS2:     port += _T("MGL"); break;
  1893.             case wxWINDOWS_OS2:
  1894.             case wxOS2_PM:      port += _T("OS/2"); break;
  1895.             default:            port += _T("unknown"); break;
  1896.         }
  1897.  
  1898.         wxMessageBox(wxString::Format(
  1899.                                       _T(
  1900.                                         "       wxWindows Library (%s port)\nVersion %u.%u.%u%s, compiled at %s %s\n   Copyright (c) 1995-2002 wxWindows team"
  1901.                                         ),
  1902.                                       port.c_str(),
  1903.                                       wxMAJOR_VERSION,
  1904.                                       wxMINOR_VERSION,
  1905.                                       wxRELEASE_NUMBER,
  1906. #if wxUSE_UNICODE
  1907.                                       L" (Unicode)",
  1908. #else
  1909.                                       "",
  1910. #endif
  1911.                                       __TDATE__,
  1912.                                       __TTIME__
  1913.                                      ),
  1914.                      _T("wxWindows information"),
  1915.                      wxICON_INFORMATION | wxOK,
  1916.                      (wxWindow *)this);
  1917.     }
  1918.     else
  1919. #endif // wxUSE_MSGDLG
  1920.     {
  1921.         event.Skip();
  1922.     }
  1923. }
  1924.  
  1925. // ----------------------------------------------------------------------------
  1926. // list classes implementation
  1927. // ----------------------------------------------------------------------------
  1928.  
  1929. void wxWindowListNode::DeleteData()
  1930. {
  1931.     delete (wxWindow *)GetData();
  1932. }
  1933.  
  1934. // ----------------------------------------------------------------------------
  1935. // borders
  1936. // ----------------------------------------------------------------------------
  1937.  
  1938. wxBorder wxWindowBase::GetBorder() const
  1939. {
  1940.     wxBorder border = (wxBorder)(m_windowStyle & wxBORDER_MASK);
  1941.     if ( border == wxBORDER_DEFAULT )
  1942.     {
  1943.         border = GetDefaultBorder();
  1944.     }
  1945.  
  1946.     return border;
  1947. }
  1948.  
  1949. wxBorder wxWindowBase::GetDefaultBorder() const
  1950. {
  1951.     return wxBORDER_NONE;
  1952. }
  1953.  
  1954. // ----------------------------------------------------------------------------
  1955. // hit testing
  1956. // ----------------------------------------------------------------------------
  1957.  
  1958. wxHitTest wxWindowBase::DoHitTest(wxCoord x, wxCoord y) const
  1959. {
  1960.     // here we just check if the point is inside the window or not
  1961.  
  1962.     // check the top and left border first
  1963.     bool outside = x < 0 || y < 0;
  1964.     if ( !outside )
  1965.     {
  1966.         // check the right and bottom borders too
  1967.         wxSize size = GetSize();
  1968.         outside = x >= size.x || y >= size.y;
  1969.     }
  1970.  
  1971.     return outside ? wxHT_WINDOW_OUTSIDE : wxHT_WINDOW_INSIDE;
  1972. }
  1973.  
  1974. // ----------------------------------------------------------------------------
  1975. // mouse capture
  1976. // ----------------------------------------------------------------------------
  1977.  
  1978. struct WXDLLEXPORT wxWindowNext
  1979. {
  1980.     wxWindow *win;
  1981.     wxWindowNext *next;
  1982. } *wxWindowBase::ms_winCaptureNext = NULL;
  1983.  
  1984. void wxWindowBase::CaptureMouse()
  1985. {
  1986.     wxLogTrace(_T("mousecapture"), _T("CaptureMouse(%p)"), this);
  1987.  
  1988.     wxWindow *winOld = GetCapture();
  1989.     if ( winOld )
  1990.     {
  1991.         ((wxWindowBase*) winOld)->DoReleaseMouse();
  1992.  
  1993.         // save it on stack
  1994.         wxWindowNext *item = new wxWindowNext;
  1995.         item->win = winOld;
  1996.         item->next = ms_winCaptureNext;
  1997.         ms_winCaptureNext = item;
  1998.     }
  1999.     //else: no mouse capture to save
  2000.  
  2001.     DoCaptureMouse();
  2002. }
  2003.  
  2004. void wxWindowBase::ReleaseMouse()
  2005. {
  2006.     wxLogTrace(_T("mousecapture"), _T("ReleaseMouse(%p)"), this);
  2007.  
  2008.     wxASSERT_MSG( GetCapture() == this, wxT("attempt to release mouse, but this window hasn't captured it") );
  2009.  
  2010.     DoReleaseMouse();
  2011.  
  2012.     if ( ms_winCaptureNext )
  2013.     {
  2014.         ((wxWindowBase*)ms_winCaptureNext->win)->DoCaptureMouse();
  2015.  
  2016.         wxWindowNext *item = ms_winCaptureNext;
  2017.         ms_winCaptureNext = item->next;
  2018.         delete item;
  2019.     }
  2020.     //else: stack is empty, no previous capture
  2021.  
  2022.     wxLogTrace(_T("mousecapture"),
  2023.                _T("After ReleaseMouse() mouse is captured by %p"),
  2024.                GetCapture());
  2025. }
  2026.  
  2027. // ----------------------------------------------------------------------------
  2028. // global functions
  2029. // ----------------------------------------------------------------------------
  2030.  
  2031. wxWindow* wxGetTopLevelParent(wxWindow *win)
  2032. {
  2033.     while ( win && !win->IsTopLevel() )
  2034.          win = win->GetParent();
  2035.  
  2036.     return win;
  2037. }
  2038.  
  2039. // vi:sts=4:sw=4:et
  2040.