]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/wincmn.cpp
use MoreFiles under Mac OS X
[wxWidgets.git] / src / common / wincmn.cpp
... / ...
CommitLineData
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$
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 #include "wx/sizer.h"
51#endif // wxUSE_CONSTRAINTS
52
53#if wxUSE_DRAG_AND_DROP
54 #include "wx/dnd.h"
55#endif // wxUSE_DRAG_AND_DROP
56
57#if wxUSE_HELP
58 #include "wx/cshelp.h"
59#endif // wxUSE_HELP
60
61#if wxUSE_TOOLTIPS
62 #include "wx/tooltip.h"
63#endif // wxUSE_TOOLTIPS
64
65#if wxUSE_CARET
66 #include "wx/caret.h"
67#endif // wxUSE_CARET
68
69// ----------------------------------------------------------------------------
70// static data
71// ----------------------------------------------------------------------------
72
73int wxWindowBase::ms_lastControlId = -200;
74
75IMPLEMENT_ABSTRACT_CLASS(wxWindowBase, wxEvtHandler)
76
77// ----------------------------------------------------------------------------
78// event table
79// ----------------------------------------------------------------------------
80
81BEGIN_EVENT_TABLE(wxWindowBase, wxEvtHandler)
82 EVT_SYS_COLOUR_CHANGED(wxWindowBase::OnSysColourChanged)
83 EVT_INIT_DIALOG(wxWindowBase::OnInitDialog)
84 EVT_MIDDLE_DOWN(wxWindowBase::OnMiddleClick)
85
86#if wxUSE_HELP
87 EVT_HELP(-1, wxWindowBase::OnHelp)
88#endif // wxUSE_HELP
89
90END_EVENT_TABLE()
91
92// ============================================================================
93// implementation of the common functionality of the wxWindow class
94// ============================================================================
95
96// ----------------------------------------------------------------------------
97// initialization
98// ----------------------------------------------------------------------------
99
100// the default initialization
101void wxWindowBase::InitBase()
102{
103 // no window yet, no parent nor children
104 m_parent = (wxWindow *)NULL;
105 m_windowId = -1;
106 m_children.DeleteContents( FALSE ); // don't auto delete node data
107
108 // no constraints on the minimal window size
109 m_minWidth =
110 m_minHeight =
111 m_maxWidth =
112 m_maxHeight = -1;
113
114 // window is created enabled but it's not visible yet
115 m_isShown = FALSE;
116 m_isEnabled = TRUE;
117
118 // the default event handler is just this window
119 m_eventHandler = this;
120
121#if wxUSE_VALIDATORS
122 // no validator
123 m_windowValidator = (wxValidator *) NULL;
124#endif // wxUSE_VALIDATORS
125
126 // use the system default colours
127 m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE);
128 m_foregroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOWTEXT);
129
130 // don't set the font here for wxMSW as we don't call WM_SETFONT here and
131 // so the font is *not* really set - but calls to SetFont() later won't do
132 // anything because m_font appears to be already set!
133#ifndef __WXMSW__
134 m_font = wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT);
135#endif // __WXMSW__
136
137 // no style bits
138 m_exStyle =
139 m_windowStyle = 0;
140
141 // an optimization for the event processing: checking this flag is much
142 // faster than using IsKindOf(CLASSINFO(wxWindow))
143 m_isWindow = TRUE;
144
145#if wxUSE_CONSTRAINTS
146 // no constraints whatsoever
147 m_constraints = (wxLayoutConstraints *) NULL;
148 m_constraintsInvolvedIn = (wxWindowList *) NULL;
149 m_windowSizer = (wxSizer *) NULL;
150 m_autoLayout = FALSE;
151#endif // wxUSE_CONSTRAINTS
152
153#if wxUSE_DRAG_AND_DROP
154 m_dropTarget = (wxDropTarget *)NULL;
155#endif // wxUSE_DRAG_AND_DROP
156
157#if wxUSE_TOOLTIPS
158 m_tooltip = (wxToolTip *)NULL;
159#endif // wxUSE_TOOLTIPS
160
161#if wxUSE_CARET
162 m_caret = (wxCaret *)NULL;
163#endif // wxUSE_CARET
164
165 // Whether we're using the current theme for this window (wxGTK only for now)
166 m_themeEnabled = FALSE;
167}
168
169// common part of window creation process
170bool wxWindowBase::CreateBase(wxWindowBase *parent,
171 wxWindowID id,
172 const wxPoint& WXUNUSED(pos),
173 const wxSize& WXUNUSED(size),
174 long style,
175 const wxValidator& validator,
176 const wxString& name)
177{
178 // m_isWindow is set to TRUE in wxWindowBase::Init() as well as many other
179 // member variables - check that it has been called (will catch the case
180 // when a new ctor is added which doesn't call InitWindow)
181 wxASSERT_MSG( m_isWindow, wxT("Init() must have been called before!") );
182
183 // generate a new id if the user doesn't care about it
184 m_windowId = id == -1 ? NewControlId() : id;
185
186 SetName(name);
187 SetWindowStyleFlag(style);
188 SetParent(parent);
189
190#if wxUSE_VALIDATORS
191 SetValidator(validator);
192#endif // wxUSE_VALIDATORS
193
194 // if the parent window has wxWS_EX_VALIDATE_RECURSIVELY set, we want to
195 // have it too - like this it's possible to set it only in the top level
196 // dialog/frame and all children will inherit it by defult
197 if ( parent && (parent->GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) )
198 {
199 SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY);
200 }
201
202 return TRUE;
203}
204
205// ----------------------------------------------------------------------------
206// destruction
207// ----------------------------------------------------------------------------
208
209// common clean up
210wxWindowBase::~wxWindowBase()
211{
212 // FIXME if these 2 cases result from programming errors in the user code
213 // we should probably assert here instead of silently fixing them
214
215 // Just in case the window has been Closed, but we're then deleting
216 // immediately: don't leave dangling pointers.
217 wxPendingDelete.DeleteObject(this);
218
219 // Just in case we've loaded a top-level window via LoadNativeDialog but
220 // we weren't a dialog class
221 wxTopLevelWindows.DeleteObject(this);
222
223 wxASSERT_MSG( GetChildren().GetCount() == 0, wxT("children not destroyed") );
224
225#if wxUSE_CARET
226 if ( m_caret )
227 delete m_caret;
228#endif // wxUSE_CARET
229
230#if wxUSE_VALIDATORS
231 if ( m_windowValidator )
232 delete m_windowValidator;
233#endif // wxUSE_VALIDATORS
234
235#if wxUSE_CONSTRAINTS
236 // Have to delete constraints/sizer FIRST otherwise sizers may try to look
237 // at deleted windows as they delete themselves.
238 DeleteRelatedConstraints();
239
240 if ( m_constraints )
241 {
242 // This removes any dangling pointers to this window in other windows'
243 // constraintsInvolvedIn lists.
244 UnsetConstraints(m_constraints);
245 delete m_constraints;
246 m_constraints = NULL;
247 }
248
249 if ( m_windowSizer )
250 delete m_windowSizer;
251
252#endif // wxUSE_CONSTRAINTS
253
254#if wxUSE_DRAG_AND_DROP
255 if ( m_dropTarget )
256 delete m_dropTarget;
257#endif // wxUSE_DRAG_AND_DROP
258
259#if wxUSE_TOOLTIPS
260 if ( m_tooltip )
261 delete m_tooltip;
262#endif // wxUSE_TOOLTIPS
263
264 // reset the dangling pointer our parent window may keep to us
265 if ( m_parent && m_parent->GetDefaultItem() == this )
266 {
267 m_parent->SetDefaultItem(NULL);
268 }
269}
270
271bool wxWindowBase::Destroy()
272{
273 delete this;
274
275 return TRUE;
276}
277
278bool wxWindowBase::Close(bool force)
279{
280 wxCloseEvent event(wxEVT_CLOSE_WINDOW, m_windowId);
281 event.SetEventObject(this);
282#if WXWIN_COMPATIBILITY
283 event.SetForce(force);
284#endif // WXWIN_COMPATIBILITY
285 event.SetCanVeto(!force);
286
287 // return FALSE if window wasn't closed because the application vetoed the
288 // close event
289 return GetEventHandler()->ProcessEvent(event) && !event.GetVeto();
290}
291
292bool wxWindowBase::DestroyChildren()
293{
294 wxWindowList::Node *node;
295 for ( ;; )
296 {
297 // we iterate until the list becomes empty
298 node = GetChildren().GetFirst();
299 if ( !node )
300 break;
301
302 wxWindow *child = node->GetData();
303
304 wxASSERT_MSG( child, wxT("children list contains empty nodes") );
305
306 child->Show(FALSE);
307 delete child;
308
309 wxASSERT_MSG( !GetChildren().Find(child),
310 wxT("child didn't remove itself using RemoveChild()") );
311 }
312
313 return TRUE;
314}
315
316// ----------------------------------------------------------------------------
317// size/position related methods
318// ----------------------------------------------------------------------------
319
320// centre the window with respect to its parent in either (or both) directions
321void wxWindowBase::Centre(int direction)
322{
323 // the position/size of the parent window or of the entire screen
324 wxPoint posParent;
325 int widthParent, heightParent;
326
327 wxWindow *parent = NULL;
328
329 if ( !(direction & wxCENTRE_ON_SCREEN) )
330 {
331 // find the parent to centre this window on: it should be the
332 // immediate parent for the controls but the top level parent for the
333 // top level windows (like dialogs)
334 parent = GetParent();
335 if ( IsTopLevel() )
336 {
337 while ( parent && !parent->IsTopLevel() )
338 {
339 parent = parent->GetParent();
340 }
341 }
342
343 // did we find the parent?
344 if ( !parent )
345 {
346 // no other choice
347 direction |= wxCENTRE_ON_SCREEN;
348 }
349 }
350
351 if ( direction & wxCENTRE_ON_SCREEN )
352 {
353 // centre with respect to the whole screen
354 wxDisplaySize(&widthParent, &heightParent);
355 }
356 else
357 {
358 if ( IsTopLevel() )
359 {
360 // centre on the parent
361 parent->GetSize(&widthParent, &heightParent);
362
363 // adjust to the parents position
364 posParent = parent->GetPosition();
365 }
366 else
367 {
368 // centre inside the parents client rectangle
369 parent->GetClientSize(&widthParent, &heightParent);
370 }
371 }
372
373 int width, height;
374 GetSize(&width, &height);
375
376 int xNew = -1,
377 yNew = -1;
378
379 if ( direction & wxHORIZONTAL )
380 xNew = (widthParent - width)/2;
381
382 if ( direction & wxVERTICAL )
383 yNew = (heightParent - height)/2;
384
385 xNew += posParent.x;
386 yNew += posParent.y;
387
388 // Base size of the visible dimensions of the display
389 // to take into account the taskbar
390 wxRect rect = wxGetClientDisplayRect();
391 wxSize size (rect.width,rect.height);
392
393 if (posParent.x >= 0) // if parent is on the main display
394 {
395 if (xNew < 0)
396 xNew = 0;
397 else if (xNew+width > size.x)
398 xNew = size.x-width-1;
399 }
400 if (posParent.y >= 0) // if parent is on the main display
401 {
402 if (yNew+height > size.y)
403 yNew = size.y-height-1;
404
405 // Make certain that the title bar is initially visible
406 // always, even if this would push the bottom of the
407 // dialog of the visible area of the display
408 if (yNew < 0)
409 yNew = 0;
410 }
411
412 // move the window to this position (keeping the old size but using
413 // SetSize() and not Move() to allow xNew and/or yNew to be -1)
414 SetSize(xNew, yNew, width, height, wxSIZE_ALLOW_MINUS_ONE);
415}
416
417// fits the window around the children
418void wxWindowBase::Fit()
419{
420 if ( GetChildren().GetCount() > 0 )
421 {
422 wxSize size = DoGetBestSize();
423
424 // for compatibility with the old versions and because it really looks
425 // slightly more pretty like this, add a pad
426 size.x += 7;
427 size.y += 14;
428
429 SetClientSize(size);
430 }
431 //else: do nothing if we have no children
432}
433
434// return the size best suited for the current window
435wxSize wxWindowBase::DoGetBestSize() const
436{
437 if ( GetChildren().GetCount() > 0 )
438 {
439 // our minimal acceptable size is such that all our windows fit inside
440 int maxX = 0,
441 maxY = 0;
442
443 for ( wxWindowList::Node *node = GetChildren().GetFirst();
444 node;
445 node = node->GetNext() )
446 {
447 wxWindow *win = node->GetData();
448 if ( win->IsTopLevel()
449#if wxUSE_STATUSBAR
450 || wxDynamicCast(win, wxStatusBar)
451#endif // wxUSE_STATUSBAR
452 )
453 {
454 // dialogs and frames lie in different top level windows -
455 // don't deal with them here; as for the status bars, they
456 // don't lie in the client area at all
457 continue;
458 }
459
460 int wx, wy, ww, wh;
461 win->GetPosition(&wx, &wy);
462
463 // if the window hadn't been positioned yet, assume that it is in
464 // the origin
465 if ( wx == -1 )
466 wx = 0;
467 if ( wy == -1 )
468 wy = 0;
469
470 win->GetSize(&ww, &wh);
471 if ( wx + ww > maxX )
472 maxX = wx + ww;
473 if ( wy + wh > maxY )
474 maxY = wy + wh;
475 }
476
477 return wxSize(maxX, maxY);
478 }
479 else
480 {
481 // for a generic window there is no natural best size - just use the
482 // current one
483 return GetSize();
484 }
485}
486
487// by default the origin is not shifted
488wxPoint wxWindowBase::GetClientAreaOrigin() const
489{
490 return wxPoint(0, 0);
491}
492
493// set the min/max size of the window
494void wxWindowBase::SetSizeHints(int minW, int minH,
495 int maxW, int maxH,
496 int WXUNUSED(incW), int WXUNUSED(incH))
497{
498 m_minWidth = minW;
499 m_maxWidth = maxW;
500 m_minHeight = minH;
501 m_maxHeight = maxH;
502}
503
504// ----------------------------------------------------------------------------
505// show/hide/enable/disable the window
506// ----------------------------------------------------------------------------
507
508bool wxWindowBase::Show(bool show)
509{
510 if ( show != m_isShown )
511 {
512 m_isShown = show;
513
514 return TRUE;
515 }
516 else
517 {
518 return FALSE;
519 }
520}
521
522bool wxWindowBase::Enable(bool enable)
523{
524 if ( enable != m_isEnabled )
525 {
526 m_isEnabled = enable;
527
528 return TRUE;
529 }
530 else
531 {
532 return FALSE;
533 }
534}
535// ----------------------------------------------------------------------------
536// RTTI
537// ----------------------------------------------------------------------------
538
539bool wxWindowBase::IsTopLevel() const
540{
541 return FALSE;
542}
543
544// ----------------------------------------------------------------------------
545// reparenting the window
546// ----------------------------------------------------------------------------
547
548void wxWindowBase::AddChild(wxWindowBase *child)
549{
550 wxCHECK_RET( child, wxT("can't add a NULL child") );
551
552 // this should never happen and it will lead to a crash later if it does
553 // because RemoveChild() will remove only one node from the children list
554 // and the other(s) one(s) will be left with dangling pointers in them
555 wxASSERT_MSG( !GetChildren().Find(child), _T("AddChild() called twice") );
556
557 GetChildren().Append(child);
558 child->SetParent(this);
559}
560
561void wxWindowBase::RemoveChild(wxWindowBase *child)
562{
563 wxCHECK_RET( child, wxT("can't remove a NULL child") );
564
565 GetChildren().DeleteObject(child);
566 child->SetParent((wxWindow *)NULL);
567}
568
569bool wxWindowBase::Reparent(wxWindowBase *newParent)
570{
571 wxWindow *oldParent = GetParent();
572 if ( newParent == oldParent )
573 {
574 // nothing done
575 return FALSE;
576 }
577
578 // unlink this window from the existing parent.
579 if ( oldParent )
580 {
581 oldParent->RemoveChild(this);
582 }
583 else
584 {
585 wxTopLevelWindows.DeleteObject(this);
586 }
587
588 // add it to the new one
589 if ( newParent )
590 {
591 newParent->AddChild(this);
592 }
593 else
594 {
595 wxTopLevelWindows.Append(this);
596 }
597
598 return TRUE;
599}
600
601// ----------------------------------------------------------------------------
602// event handler stuff
603// ----------------------------------------------------------------------------
604
605void wxWindowBase::PushEventHandler(wxEvtHandler *handler)
606{
607 handler->SetNextHandler(GetEventHandler());
608 SetEventHandler(handler);
609}
610
611wxEvtHandler *wxWindowBase::PopEventHandler(bool deleteHandler)
612{
613 wxEvtHandler *handlerA = GetEventHandler();
614 if ( handlerA )
615 {
616 wxEvtHandler *handlerB = handlerA->GetNextHandler();
617 handlerA->SetNextHandler((wxEvtHandler *)NULL);
618 SetEventHandler(handlerB);
619 if ( deleteHandler )
620 {
621 delete handlerA;
622 handlerA = (wxEvtHandler *)NULL;
623 }
624 }
625
626 return handlerA;
627}
628
629// ----------------------------------------------------------------------------
630// cursors, fonts &c
631// ----------------------------------------------------------------------------
632
633bool wxWindowBase::SetBackgroundColour( const wxColour &colour )
634{
635 if ( !colour.Ok() || (colour == m_backgroundColour) )
636 return FALSE;
637
638 m_backgroundColour = colour;
639
640 return TRUE;
641}
642
643bool wxWindowBase::SetForegroundColour( const wxColour &colour )
644{
645 if ( !colour.Ok() || (colour == m_foregroundColour) )
646 return FALSE;
647
648 m_foregroundColour = colour;
649
650 return TRUE;
651}
652
653bool wxWindowBase::SetCursor(const wxCursor& cursor)
654{
655 // setting an invalid cursor is ok, it means that we don't have any special
656 // cursor
657 if ( m_cursor == cursor )
658 {
659 // no change
660 return FALSE;
661 }
662
663 m_cursor = cursor;
664
665 return TRUE;
666}
667
668bool wxWindowBase::SetFont(const wxFont& font)
669{
670 // don't try to set invalid font, always fall back to the default
671 const wxFont& fontOk = font.Ok() ? font : *wxSWISS_FONT;
672
673 if ( fontOk == m_font )
674 {
675 // no change
676 return FALSE;
677 }
678
679 m_font = fontOk;
680
681 return TRUE;
682}
683
684#if wxUSE_CARET
685void wxWindowBase::SetCaret(wxCaret *caret)
686{
687 if ( m_caret )
688 {
689 delete m_caret;
690 }
691
692 m_caret = caret;
693
694 if ( m_caret )
695 {
696 wxASSERT_MSG( m_caret->GetWindow() == this,
697 wxT("caret should be created associated to this window") );
698 }
699}
700#endif // wxUSE_CARET
701
702#if wxUSE_VALIDATORS
703// ----------------------------------------------------------------------------
704// validators
705// ----------------------------------------------------------------------------
706
707void wxWindowBase::SetValidator(const wxValidator& validator)
708{
709 if ( m_windowValidator )
710 delete m_windowValidator;
711
712 m_windowValidator = (wxValidator *)validator.Clone();
713
714 if ( m_windowValidator )
715 m_windowValidator->SetWindow(this) ;
716}
717#endif // wxUSE_VALIDATORS
718
719// ----------------------------------------------------------------------------
720// update region stuff
721// ----------------------------------------------------------------------------
722
723wxRect wxWindowBase::GetUpdateClientRect() const
724{
725 wxRegion rgnUpdate = GetUpdateRegion();
726 rgnUpdate.Intersect(GetClientRect());
727 wxRect rectUpdate = rgnUpdate.GetBox();
728 wxPoint ptOrigin = GetClientAreaOrigin();
729 rectUpdate.x -= ptOrigin.x;
730 rectUpdate.y -= ptOrigin.y;
731
732 return rectUpdate;
733}
734
735bool wxWindowBase::IsExposed(int x, int y) const
736{
737 return m_updateRegion.Contains(x, y) != wxOutRegion;
738}
739
740bool wxWindowBase::IsExposed(int x, int y, int w, int h) const
741{
742 return m_updateRegion.Contains(x, y, w, h) != wxOutRegion;
743}
744
745// ----------------------------------------------------------------------------
746// find window by id or name
747// ----------------------------------------------------------------------------
748
749wxWindow *wxWindowBase::FindWindow( long id )
750{
751 if ( id == m_windowId )
752 return (wxWindow *)this;
753
754 wxWindowBase *res = (wxWindow *)NULL;
755 wxWindowList::Node *node;
756 for ( node = m_children.GetFirst(); node && !res; node = node->GetNext() )
757 {
758 wxWindowBase *child = node->GetData();
759 res = child->FindWindow( id );
760 }
761
762 return (wxWindow *)res;
763}
764
765wxWindow *wxWindowBase::FindWindow( const wxString& name )
766{
767 if ( name == m_windowName )
768 return (wxWindow *)this;
769
770 wxWindowBase *res = (wxWindow *)NULL;
771 wxWindowList::Node *node;
772 for ( node = m_children.GetFirst(); node && !res; node = node->GetNext() )
773 {
774 wxWindow *child = node->GetData();
775 res = child->FindWindow(name);
776 }
777
778 return (wxWindow *)res;
779}
780
781// ----------------------------------------------------------------------------
782// dialog oriented functions
783// ----------------------------------------------------------------------------
784
785void wxWindowBase::MakeModal(bool modal)
786{
787 // Disable all other windows
788 if ( IsTopLevel() )
789 {
790 wxWindowList::Node *node = wxTopLevelWindows.GetFirst();
791 while (node)
792 {
793 wxWindow *win = node->GetData();
794 if (win != this)
795 win->Enable(!modal);
796
797 node = node->GetNext();
798 }
799 }
800}
801
802bool wxWindowBase::Validate()
803{
804#if wxUSE_VALIDATORS
805 bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0;
806
807 wxWindowList::Node *node;
808 for ( node = m_children.GetFirst(); node; node = node->GetNext() )
809 {
810 wxWindowBase *child = node->GetData();
811 wxValidator *validator = child->GetValidator();
812 if ( validator && !validator->Validate((wxWindow *)this) )
813 {
814 return FALSE;
815 }
816
817 if ( recurse && !child->Validate() )
818 {
819 return FALSE;
820 }
821 }
822#endif // wxUSE_VALIDATORS
823
824 return TRUE;
825}
826
827bool wxWindowBase::TransferDataToWindow()
828{
829#if wxUSE_VALIDATORS
830 bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0;
831
832 wxWindowList::Node *node;
833 for ( node = m_children.GetFirst(); node; node = node->GetNext() )
834 {
835 wxWindowBase *child = node->GetData();
836 wxValidator *validator = child->GetValidator();
837 if ( validator && !validator->TransferToWindow() )
838 {
839 wxLogWarning(_("Could not transfer data to window"));
840 wxLog::FlushActive();
841
842 return FALSE;
843 }
844
845 if ( recurse )
846 {
847 if ( !child->TransferDataToWindow() )
848 {
849 // warning already given
850 return FALSE;
851 }
852 }
853 }
854#endif // wxUSE_VALIDATORS
855
856 return TRUE;
857}
858
859bool wxWindowBase::TransferDataFromWindow()
860{
861#if wxUSE_VALIDATORS
862 bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0;
863
864 wxWindowList::Node *node;
865 for ( node = m_children.GetFirst(); node; node = node->GetNext() )
866 {
867 wxWindow *child = node->GetData();
868 wxValidator *validator = child->GetValidator();
869 if ( validator && !validator->TransferFromWindow() )
870 {
871 // nop warning here because the application is supposed to give
872 // one itself - we don't know here what might have gone wrongly
873
874 return FALSE;
875 }
876
877 if ( recurse )
878 {
879 if ( !child->TransferDataFromWindow() )
880 {
881 // warning already given
882 return FALSE;
883 }
884 }
885 }
886#endif // wxUSE_VALIDATORS
887
888 return TRUE;
889}
890
891void wxWindowBase::InitDialog()
892{
893 wxInitDialogEvent event(GetId());
894 event.SetEventObject( this );
895 GetEventHandler()->ProcessEvent(event);
896}
897
898// ----------------------------------------------------------------------------
899// context-sensitive help support
900// ----------------------------------------------------------------------------
901
902#if wxUSE_HELP
903
904// associate this help text with this window
905void wxWindowBase::SetHelpText(const wxString& text)
906{
907 wxHelpProvider *helpProvider = wxHelpProvider::Get();
908 if ( helpProvider )
909 {
910 helpProvider->AddHelp(this, text);
911 }
912}
913
914// associate this help text with all windows with the same id as this
915// one
916void wxWindowBase::SetHelpTextForId(const wxString& text)
917{
918 wxHelpProvider *helpProvider = wxHelpProvider::Get();
919 if ( helpProvider )
920 {
921 helpProvider->AddHelp(GetId(), text);
922 }
923}
924
925// get the help string associated with this window (may be empty)
926wxString wxWindowBase::GetHelpText() const
927{
928 wxString text;
929 wxHelpProvider *helpProvider = wxHelpProvider::Get();
930 if ( helpProvider )
931 {
932 text = helpProvider->GetHelp(this);
933 }
934
935 return text;
936}
937
938// show help for this window
939void wxWindowBase::OnHelp(wxHelpEvent& event)
940{
941 wxHelpProvider *helpProvider = wxHelpProvider::Get();
942 if ( helpProvider )
943 {
944 if ( helpProvider->ShowHelp(this) )
945 {
946 // skip the event.Skip() below
947 return;
948 }
949 }
950
951 event.Skip();
952}
953
954#endif // wxUSE_HELP
955
956// ----------------------------------------------------------------------------
957// tooltips
958// ----------------------------------------------------------------------------
959
960#if wxUSE_TOOLTIPS
961
962void wxWindowBase::SetToolTip( const wxString &tip )
963{
964 // don't create the new tooltip if we already have one
965 if ( m_tooltip )
966 {
967 m_tooltip->SetTip( tip );
968 }
969 else
970 {
971 SetToolTip( new wxToolTip( tip ) );
972 }
973
974 // setting empty tooltip text does not remove the tooltip any more - use
975 // SetToolTip((wxToolTip *)NULL) for this
976}
977
978void wxWindowBase::DoSetToolTip(wxToolTip *tooltip)
979{
980 if ( m_tooltip )
981 delete m_tooltip;
982
983 m_tooltip = tooltip;
984}
985
986#endif // wxUSE_TOOLTIPS
987
988// ----------------------------------------------------------------------------
989// constraints and sizers
990// ----------------------------------------------------------------------------
991
992#if wxUSE_CONSTRAINTS
993
994void wxWindowBase::SetConstraints( wxLayoutConstraints *constraints )
995{
996 if ( m_constraints )
997 {
998 UnsetConstraints(m_constraints);
999 delete m_constraints;
1000 }
1001 m_constraints = constraints;
1002 if ( m_constraints )
1003 {
1004 // Make sure other windows know they're part of a 'meaningful relationship'
1005 if ( m_constraints->left.GetOtherWindow() && (m_constraints->left.GetOtherWindow() != this) )
1006 m_constraints->left.GetOtherWindow()->AddConstraintReference(this);
1007 if ( m_constraints->top.GetOtherWindow() && (m_constraints->top.GetOtherWindow() != this) )
1008 m_constraints->top.GetOtherWindow()->AddConstraintReference(this);
1009 if ( m_constraints->right.GetOtherWindow() && (m_constraints->right.GetOtherWindow() != this) )
1010 m_constraints->right.GetOtherWindow()->AddConstraintReference(this);
1011 if ( m_constraints->bottom.GetOtherWindow() && (m_constraints->bottom.GetOtherWindow() != this) )
1012 m_constraints->bottom.GetOtherWindow()->AddConstraintReference(this);
1013 if ( m_constraints->width.GetOtherWindow() && (m_constraints->width.GetOtherWindow() != this) )
1014 m_constraints->width.GetOtherWindow()->AddConstraintReference(this);
1015 if ( m_constraints->height.GetOtherWindow() && (m_constraints->height.GetOtherWindow() != this) )
1016 m_constraints->height.GetOtherWindow()->AddConstraintReference(this);
1017 if ( m_constraints->centreX.GetOtherWindow() && (m_constraints->centreX.GetOtherWindow() != this) )
1018 m_constraints->centreX.GetOtherWindow()->AddConstraintReference(this);
1019 if ( m_constraints->centreY.GetOtherWindow() && (m_constraints->centreY.GetOtherWindow() != this) )
1020 m_constraints->centreY.GetOtherWindow()->AddConstraintReference(this);
1021 }
1022}
1023
1024// This removes any dangling pointers to this window in other windows'
1025// constraintsInvolvedIn lists.
1026void wxWindowBase::UnsetConstraints(wxLayoutConstraints *c)
1027{
1028 if ( c )
1029 {
1030 if ( c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this) )
1031 c->left.GetOtherWindow()->RemoveConstraintReference(this);
1032 if ( c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this) )
1033 c->top.GetOtherWindow()->RemoveConstraintReference(this);
1034 if ( c->right.GetOtherWindow() && (c->right.GetOtherWindow() != this) )
1035 c->right.GetOtherWindow()->RemoveConstraintReference(this);
1036 if ( c->bottom.GetOtherWindow() && (c->bottom.GetOtherWindow() != this) )
1037 c->bottom.GetOtherWindow()->RemoveConstraintReference(this);
1038 if ( c->width.GetOtherWindow() && (c->width.GetOtherWindow() != this) )
1039 c->width.GetOtherWindow()->RemoveConstraintReference(this);
1040 if ( c->height.GetOtherWindow() && (c->height.GetOtherWindow() != this) )
1041 c->height.GetOtherWindow()->RemoveConstraintReference(this);
1042 if ( c->centreX.GetOtherWindow() && (c->centreX.GetOtherWindow() != this) )
1043 c->centreX.GetOtherWindow()->RemoveConstraintReference(this);
1044 if ( c->centreY.GetOtherWindow() && (c->centreY.GetOtherWindow() != this) )
1045 c->centreY.GetOtherWindow()->RemoveConstraintReference(this);
1046 }
1047}
1048
1049// Back-pointer to other windows we're involved with, so if we delete this
1050// window, we must delete any constraints we're involved with.
1051void wxWindowBase::AddConstraintReference(wxWindowBase *otherWin)
1052{
1053 if ( !m_constraintsInvolvedIn )
1054 m_constraintsInvolvedIn = new wxWindowList;
1055 if ( !m_constraintsInvolvedIn->Find(otherWin) )
1056 m_constraintsInvolvedIn->Append(otherWin);
1057}
1058
1059// REMOVE back-pointer to other windows we're involved with.
1060void wxWindowBase::RemoveConstraintReference(wxWindowBase *otherWin)
1061{
1062 if ( m_constraintsInvolvedIn )
1063 m_constraintsInvolvedIn->DeleteObject(otherWin);
1064}
1065
1066// Reset any constraints that mention this window
1067void wxWindowBase::DeleteRelatedConstraints()
1068{
1069 if ( m_constraintsInvolvedIn )
1070 {
1071 wxWindowList::Node *node = m_constraintsInvolvedIn->GetFirst();
1072 while (node)
1073 {
1074 wxWindow *win = node->GetData();
1075 wxLayoutConstraints *constr = win->GetConstraints();
1076
1077 // Reset any constraints involving this window
1078 if ( constr )
1079 {
1080 constr->left.ResetIfWin(this);
1081 constr->top.ResetIfWin(this);
1082 constr->right.ResetIfWin(this);
1083 constr->bottom.ResetIfWin(this);
1084 constr->width.ResetIfWin(this);
1085 constr->height.ResetIfWin(this);
1086 constr->centreX.ResetIfWin(this);
1087 constr->centreY.ResetIfWin(this);
1088 }
1089
1090 wxWindowList::Node *next = node->GetNext();
1091 delete node;
1092 node = next;
1093 }
1094
1095 delete m_constraintsInvolvedIn;
1096 m_constraintsInvolvedIn = (wxWindowList *) NULL;
1097 }
1098}
1099
1100void wxWindowBase::SetSizer(wxSizer *sizer)
1101{
1102 if (m_windowSizer) delete m_windowSizer;
1103
1104 m_windowSizer = sizer;
1105}
1106
1107bool wxWindowBase::Layout()
1108{
1109 // If there is a sizer, use it instead of the constraints
1110 if ( GetSizer() )
1111 {
1112 int w, h;
1113 GetClientSize(&w, &h);
1114
1115 GetSizer()->SetDimension( 0, 0, w, h );
1116 }
1117 else
1118 {
1119 wxLayoutConstraints *constr = GetConstraints();
1120 bool wasOk = constr && constr->AreSatisfied();
1121
1122 ResetConstraints(); // Mark all constraints as unevaluated
1123
1124 // if we're a top level panel (i.e. our parent is frame/dialog), our
1125 // own constraints will never be satisfied any more unless we do it
1126 // here
1127 if ( wasOk )
1128 {
1129 int noChanges = 1;
1130 while ( noChanges > 0 )
1131 {
1132 constr->SatisfyConstraints(this, &noChanges);
1133 }
1134 }
1135
1136 DoPhase(1); // Layout children
1137 DoPhase(2); // Layout grand children
1138 SetConstraintSizes(); // Recursively set the real window sizes
1139 }
1140
1141 return TRUE;
1142}
1143
1144
1145// Do a phase of evaluating constraints: the default behaviour. wxSizers may
1146// do a similar thing, but also impose their own 'constraints' and order the
1147// evaluation differently.
1148bool wxWindowBase::LayoutPhase1(int *noChanges)
1149{
1150 wxLayoutConstraints *constr = GetConstraints();
1151 if ( constr )
1152 {
1153 return constr->SatisfyConstraints(this, noChanges);
1154 }
1155 else
1156 return TRUE;
1157}
1158
1159bool wxWindowBase::LayoutPhase2(int *noChanges)
1160{
1161 *noChanges = 0;
1162
1163 // Layout children
1164 DoPhase(1);
1165 DoPhase(2);
1166 return TRUE;
1167}
1168
1169// Do a phase of evaluating child constraints
1170bool wxWindowBase::DoPhase(int phase)
1171{
1172 int noIterations = 0;
1173 int maxIterations = 500;
1174 int noChanges = 1;
1175 int noFailures = 0;
1176 wxWindowList succeeded;
1177 while ((noChanges > 0) && (noIterations < maxIterations))
1178 {
1179 noChanges = 0;
1180 noFailures = 0;
1181 wxWindowList::Node *node = GetChildren().GetFirst();
1182 while (node)
1183 {
1184 wxWindow *child = node->GetData();
1185 if ( !child->IsTopLevel() )
1186 {
1187 wxLayoutConstraints *constr = child->GetConstraints();
1188 if ( constr )
1189 {
1190 if ( !succeeded.Find(child) )
1191 {
1192 int tempNoChanges = 0;
1193 bool success = ( (phase == 1) ? child->LayoutPhase1(&tempNoChanges) : child->LayoutPhase2(&tempNoChanges) ) ;
1194 noChanges += tempNoChanges;
1195 if ( success )
1196 {
1197 succeeded.Append(child);
1198 }
1199 }
1200 }
1201 }
1202 node = node->GetNext();
1203 }
1204
1205 noIterations++;
1206 }
1207
1208 return TRUE;
1209}
1210
1211void wxWindowBase::ResetConstraints()
1212{
1213 wxLayoutConstraints *constr = GetConstraints();
1214 if ( constr )
1215 {
1216 constr->left.SetDone(FALSE);
1217 constr->top.SetDone(FALSE);
1218 constr->right.SetDone(FALSE);
1219 constr->bottom.SetDone(FALSE);
1220 constr->width.SetDone(FALSE);
1221 constr->height.SetDone(FALSE);
1222 constr->centreX.SetDone(FALSE);
1223 constr->centreY.SetDone(FALSE);
1224 }
1225
1226 wxWindowList::Node *node = GetChildren().GetFirst();
1227 while (node)
1228 {
1229 wxWindow *win = node->GetData();
1230 if ( !win->IsTopLevel() )
1231 win->ResetConstraints();
1232 node = node->GetNext();
1233 }
1234}
1235
1236// Need to distinguish between setting the 'fake' size for windows and sizers,
1237// and setting the real values.
1238void wxWindowBase::SetConstraintSizes(bool recurse)
1239{
1240 wxLayoutConstraints *constr = GetConstraints();
1241 if ( constr && constr->AreSatisfied() )
1242 {
1243 int x = constr->left.GetValue();
1244 int y = constr->top.GetValue();
1245 int w = constr->width.GetValue();
1246 int h = constr->height.GetValue();
1247
1248 if ( (constr->width.GetRelationship() != wxAsIs ) ||
1249 (constr->height.GetRelationship() != wxAsIs) )
1250 {
1251 SetSize(x, y, w, h);
1252 }
1253 else
1254 {
1255 // If we don't want to resize this window, just move it...
1256 Move(x, y);
1257 }
1258 }
1259 else if ( constr )
1260 {
1261 wxLogDebug(wxT("Constraints not satisfied for %s named '%s'."),
1262 GetClassInfo()->GetClassName(),
1263 GetName().c_str());
1264 }
1265
1266 if ( recurse )
1267 {
1268 wxWindowList::Node *node = GetChildren().GetFirst();
1269 while (node)
1270 {
1271 wxWindow *win = node->GetData();
1272 if ( !win->IsTopLevel() && win->GetConstraints() )
1273 win->SetConstraintSizes();
1274 node = node->GetNext();
1275 }
1276 }
1277}
1278
1279// Only set the size/position of the constraint (if any)
1280void wxWindowBase::SetSizeConstraint(int x, int y, int w, int h)
1281{
1282 wxLayoutConstraints *constr = GetConstraints();
1283 if ( constr )
1284 {
1285 if ( x != -1 )
1286 {
1287 constr->left.SetValue(x);
1288 constr->left.SetDone(TRUE);
1289 }
1290 if ( y != -1 )
1291 {
1292 constr->top.SetValue(y);
1293 constr->top.SetDone(TRUE);
1294 }
1295 if ( w != -1 )
1296 {
1297 constr->width.SetValue(w);
1298 constr->width.SetDone(TRUE);
1299 }
1300 if ( h != -1 )
1301 {
1302 constr->height.SetValue(h);
1303 constr->height.SetDone(TRUE);
1304 }
1305 }
1306}
1307
1308void wxWindowBase::MoveConstraint(int x, int y)
1309{
1310 wxLayoutConstraints *constr = GetConstraints();
1311 if ( constr )
1312 {
1313 if ( x != -1 )
1314 {
1315 constr->left.SetValue(x);
1316 constr->left.SetDone(TRUE);
1317 }
1318 if ( y != -1 )
1319 {
1320 constr->top.SetValue(y);
1321 constr->top.SetDone(TRUE);
1322 }
1323 }
1324}
1325
1326void wxWindowBase::GetSizeConstraint(int *w, int *h) const
1327{
1328 wxLayoutConstraints *constr = GetConstraints();
1329 if ( constr )
1330 {
1331 *w = constr->width.GetValue();
1332 *h = constr->height.GetValue();
1333 }
1334 else
1335 GetSize(w, h);
1336}
1337
1338void wxWindowBase::GetClientSizeConstraint(int *w, int *h) const
1339{
1340 wxLayoutConstraints *constr = GetConstraints();
1341 if ( constr )
1342 {
1343 *w = constr->width.GetValue();
1344 *h = constr->height.GetValue();
1345 }
1346 else
1347 GetClientSize(w, h);
1348}
1349
1350void wxWindowBase::AdjustForParentClientOrigin(int& x, int& y, int sizeFlags)
1351{
1352 // don't do it for the dialogs/frames - they float independently of their
1353 // parent
1354 if ( !IsTopLevel() )
1355 {
1356 wxWindow *parent = GetParent();
1357 if ( !(sizeFlags & wxSIZE_NO_ADJUSTMENTS) && parent )
1358 {
1359 wxPoint pt(parent->GetClientAreaOrigin());
1360 x += pt.x;
1361 y += pt.y;
1362 }
1363 }
1364}
1365
1366
1367void wxWindowBase::GetPositionConstraint(int *x, int *y) const
1368{
1369 wxLayoutConstraints *constr = GetConstraints();
1370 if ( constr )
1371 {
1372 *x = constr->left.GetValue();
1373 *y = constr->top.GetValue();
1374 }
1375 else
1376 GetPosition(x, y);
1377}
1378
1379#endif // wxUSE_CONSTRAINTS
1380
1381// ----------------------------------------------------------------------------
1382// do Update UI processing for child controls
1383// ----------------------------------------------------------------------------
1384
1385// TODO: should this be implemented for the child window rather
1386// than the parent? Then you can override it e.g. for wxCheckBox
1387// to do the Right Thing rather than having to assume a fixed number
1388// of control classes.
1389void wxWindowBase::UpdateWindowUI()
1390{
1391#if wxUSE_CONTROLS
1392 wxUpdateUIEvent event(GetId());
1393 event.m_eventObject = this;
1394
1395 if ( GetEventHandler()->ProcessEvent(event) )
1396 {
1397 if ( event.GetSetEnabled() )
1398 Enable(event.GetEnabled());
1399
1400 if ( event.GetSetText() )
1401 {
1402 wxControl *control = wxDynamicCastThis(wxControl);
1403 if ( control )
1404 {
1405#if wxUSE_TEXTCTRL
1406 wxTextCtrl *text = wxDynamicCast(control, wxTextCtrl);
1407 if ( text )
1408 text->SetValue(event.GetText());
1409 else
1410#endif // wxUSE_TEXTCTRL
1411 control->SetLabel(event.GetText());
1412 }
1413 }
1414
1415#if wxUSE_CHECKBOX
1416 wxCheckBox *checkbox = wxDynamicCastThis(wxCheckBox);
1417 if ( checkbox )
1418 {
1419 if ( event.GetSetChecked() )
1420 checkbox->SetValue(event.GetChecked());
1421 }
1422#endif // wxUSE_CHECKBOX
1423
1424#if wxUSE_RADIOBTN
1425 wxRadioButton *radiobtn = wxDynamicCastThis(wxRadioButton);
1426 if ( radiobtn )
1427 {
1428 if ( event.GetSetChecked() )
1429 radiobtn->SetValue(event.GetChecked());
1430 }
1431#endif // wxUSE_RADIOBTN
1432 }
1433#endif // wxUSE_CONTROLS
1434}
1435
1436// ----------------------------------------------------------------------------
1437// dialog units translations
1438// ----------------------------------------------------------------------------
1439
1440wxPoint wxWindowBase::ConvertPixelsToDialog(const wxPoint& pt)
1441{
1442 int charWidth = GetCharWidth();
1443 int charHeight = GetCharHeight();
1444 wxPoint pt2(-1, -1);
1445 if (pt.x != -1)
1446 pt2.x = (int) ((pt.x * 4) / charWidth) ;
1447 if (pt.y != -1)
1448 pt2.y = (int) ((pt.y * 8) / charHeight) ;
1449
1450 return pt2;
1451}
1452
1453wxPoint wxWindowBase::ConvertDialogToPixels(const wxPoint& pt)
1454{
1455 int charWidth = GetCharWidth();
1456 int charHeight = GetCharHeight();
1457 wxPoint pt2(-1, -1);
1458 if (pt.x != -1)
1459 pt2.x = (int) ((pt.x * charWidth) / 4) ;
1460 if (pt.y != -1)
1461 pt2.y = (int) ((pt.y * charHeight) / 8) ;
1462
1463 return pt2;
1464}
1465
1466// ----------------------------------------------------------------------------
1467// event handlers
1468// ----------------------------------------------------------------------------
1469
1470// propagate the colour change event to the subwindows
1471void wxWindowBase::OnSysColourChanged(wxSysColourChangedEvent& event)
1472{
1473 wxWindowList::Node *node = GetChildren().GetFirst();
1474 while ( node )
1475 {
1476 // Only propagate to non-top-level windows
1477 wxWindow *win = node->GetData();
1478 if ( !win->IsTopLevel() )
1479 {
1480 wxSysColourChangedEvent event2;
1481 event.m_eventObject = win;
1482 win->GetEventHandler()->ProcessEvent(event2);
1483 }
1484
1485 node = node->GetNext();
1486 }
1487}
1488
1489// the default action is to populate dialog with data when it's created
1490void wxWindowBase::OnInitDialog( wxInitDialogEvent &WXUNUSED(event) )
1491{
1492 TransferDataToWindow();
1493}
1494
1495// process Ctrl-Alt-mclick
1496void wxWindowBase::OnMiddleClick( wxMouseEvent& event )
1497{
1498#if wxUSE_MSGDLG
1499 if ( event.ControlDown() && event.AltDown() )
1500 {
1501 // don't translate these strings
1502 wxString port;
1503 switch ( wxGetOsVersion() )
1504 {
1505 case wxMOTIF_X: port = _T("Motif"); break;
1506 case wxMACINTOSH: port = _T("Mac"); break;
1507 case wxBEOS: port = _T("BeOS"); break;
1508 case wxGTK:
1509 case wxGTK_WIN32:
1510 case wxGTK_OS2:
1511 case wxGTK_BEOS: port = _T("GTK"); break;
1512 case wxWINDOWS:
1513 case wxPENWINDOWS:
1514 case wxWINDOWS_NT:
1515 case wxWIN32S:
1516 case wxWIN95:
1517 case wxWIN386: port = _T("MS Windows"); break;
1518 case wxMGL_UNIX:
1519 case wxMGL_X:
1520 case wxMGL_WIN32:
1521 case wxMGL_OS2: port = _T("MGL"); break;
1522 case wxWINDOWS_OS2:
1523 case wxOS2_PM: port = _T("OS/2"); break;
1524 default: port = _T("unknown"); break;
1525 }
1526
1527 wxMessageBox(wxString::Format(
1528 _T(
1529 " wxWindows Library (%s port)\nVersion %u.%u.%u, compiled at %s %s\n Copyright (c) 1995-2001 wxWindows team"
1530 ),
1531 port.c_str(),
1532 wxMAJOR_VERSION,
1533 wxMINOR_VERSION,
1534 wxRELEASE_NUMBER,
1535 __DATE__,
1536 __TIME__
1537 ),
1538 _T("wxWindows information"),
1539 wxICON_INFORMATION | wxOK,
1540 (wxWindow *)this);
1541 }
1542 else
1543#endif // wxUSE_MSGDLG
1544 {
1545 event.Skip();
1546 }
1547}
1548
1549// ----------------------------------------------------------------------------
1550// list classes implementation
1551// ----------------------------------------------------------------------------
1552
1553void wxWindowListNode::DeleteData()
1554{
1555 delete (wxWindow *)GetData();
1556}
1557
1558// ----------------------------------------------------------------------------
1559// borders
1560// ----------------------------------------------------------------------------
1561
1562wxBorder wxWindowBase::GetBorder() const
1563{
1564 wxBorder border = (wxBorder)(m_windowStyle & wxBORDER_MASK);
1565 if ( border == wxBORDER_DEFAULT )
1566 {
1567 border = GetDefaultBorder();
1568 }
1569
1570 return border;
1571}
1572
1573wxBorder wxWindowBase::GetDefaultBorder() const
1574{
1575 return wxBORDER_NONE;
1576}
1577
1578// ----------------------------------------------------------------------------
1579// hit testing
1580// ----------------------------------------------------------------------------
1581
1582wxHitTest wxWindowBase::DoHitTest(wxCoord x, wxCoord y) const
1583{
1584 // here we just check if the point is inside the window or not
1585
1586 // check the top and left border first
1587 bool outside = x < 0 || y < 0;
1588 if ( !outside )
1589 {
1590 // check the right and bottom borders too
1591 wxSize size = GetSize();
1592 outside = x >= size.x || y >= size.y;
1593 }
1594
1595 return outside ? wxHT_WINDOW_OUTSIDE : wxHT_WINDOW_INSIDE;
1596}
1597