]> git.saurik.com Git - wxWidgets.git/blob - src/common/wincmn.cpp
check for wxOnAssert reentrancy
[wxWidgets.git] / src / common / wincmn.cpp
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
73 int wxWindowBase::ms_lastControlId = -200;
74
75 IMPLEMENT_ABSTRACT_CLASS(wxWindowBase, wxEvtHandler)
76
77 // ----------------------------------------------------------------------------
78 // event table
79 // ----------------------------------------------------------------------------
80
81 BEGIN_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
90 END_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
101 void 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
170 bool 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
210 wxWindowBase::~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
271 bool wxWindowBase::Destroy()
272 {
273 delete this;
274
275 return TRUE;
276 }
277
278 bool 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
292 bool 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
321 void 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
418 void 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
435 wxSize 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
488 wxPoint wxWindowBase::GetClientAreaOrigin() const
489 {
490 return wxPoint(0, 0);
491 }
492
493 // set the min/max size of the window
494 void 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
508 bool 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
522 bool 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
539 bool wxWindowBase::IsTopLevel() const
540 {
541 return FALSE;
542 }
543
544 // ----------------------------------------------------------------------------
545 // reparenting the window
546 // ----------------------------------------------------------------------------
547
548 void 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
561 void 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
569 bool 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
605 void wxWindowBase::PushEventHandler(wxEvtHandler *handler)
606 {
607 handler->SetNextHandler(GetEventHandler());
608 SetEventHandler(handler);
609 }
610
611 wxEvtHandler *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
633 bool 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
643 bool 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
653 bool 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
668 bool 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
685 void 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
707 void 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
723 wxRect 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
735 bool wxWindowBase::IsExposed(int x, int y) const
736 {
737 return m_updateRegion.Contains(x, y) != wxOutRegion;
738 }
739
740 bool 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
749 wxWindow *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
765 wxWindow *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
785 void 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
802 bool 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
827 bool 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
859 bool 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
891 void 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
905 void 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
916 void 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)
926 wxString 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
939 void 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
962 void 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
978 void 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
994 void 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.
1026 void 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.
1051 void 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.
1060 void wxWindowBase::RemoveConstraintReference(wxWindowBase *otherWin)
1061 {
1062 if ( m_constraintsInvolvedIn )
1063 m_constraintsInvolvedIn->DeleteObject(otherWin);
1064 }
1065
1066 // Reset any constraints that mention this window
1067 void 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
1100 void wxWindowBase::SetSizer(wxSizer *sizer)
1101 {
1102 if (m_windowSizer) delete m_windowSizer;
1103
1104 m_windowSizer = sizer;
1105 }
1106
1107 bool 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.
1148 bool 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
1159 bool 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
1170 bool 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
1211 void 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.
1238 void 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)
1280 void 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
1308 void 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
1326 void 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
1338 void 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
1350 void 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
1367 void 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.
1389 void 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
1440 wxPoint 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
1453 wxPoint 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
1471 void 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
1490 void wxWindowBase::OnInitDialog( wxInitDialogEvent &WXUNUSED(event) )
1491 {
1492 TransferDataToWindow();
1493 }
1494
1495 // process Ctrl-Alt-mclick
1496 void 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 wxMAC:
1507 case wxMAC_DARWIN: port = _T("Mac"); break;
1508 case wxBEOS: port = _T("BeOS"); break;
1509 case wxGTK:
1510 case wxGTK_WIN32:
1511 case wxGTK_OS2:
1512 case wxGTK_BEOS: port = _T("GTK"); break;
1513 case wxWINDOWS:
1514 case wxPENWINDOWS:
1515 case wxWINDOWS_NT:
1516 case wxWIN32S:
1517 case wxWIN95:
1518 case wxWIN386: port = _T("MS Windows"); break;
1519 case wxMGL_UNIX:
1520 case wxMGL_X:
1521 case wxMGL_WIN32:
1522 case wxMGL_OS2: port = _T("MGL"); break;
1523 case wxWINDOWS_OS2:
1524 case wxOS2_PM: port = _T("OS/2"); break;
1525 default: port = _T("unknown"); break;
1526 }
1527
1528 wxMessageBox(wxString::Format(
1529 _T(
1530 " wxWindows Library (%s port)\nVersion %u.%u.%u, compiled at %s %s\n Copyright (c) 1995-2001 wxWindows team"
1531 ),
1532 port.c_str(),
1533 wxMAJOR_VERSION,
1534 wxMINOR_VERSION,
1535 wxRELEASE_NUMBER,
1536 __DATE__,
1537 __TIME__
1538 ),
1539 _T("wxWindows information"),
1540 wxICON_INFORMATION | wxOK,
1541 (wxWindow *)this);
1542 }
1543 else
1544 #endif // wxUSE_MSGDLG
1545 {
1546 event.Skip();
1547 }
1548 }
1549
1550 // ----------------------------------------------------------------------------
1551 // list classes implementation
1552 // ----------------------------------------------------------------------------
1553
1554 void wxWindowListNode::DeleteData()
1555 {
1556 delete (wxWindow *)GetData();
1557 }
1558
1559 // ----------------------------------------------------------------------------
1560 // borders
1561 // ----------------------------------------------------------------------------
1562
1563 wxBorder wxWindowBase::GetBorder() const
1564 {
1565 wxBorder border = (wxBorder)(m_windowStyle & wxBORDER_MASK);
1566 if ( border == wxBORDER_DEFAULT )
1567 {
1568 border = GetDefaultBorder();
1569 }
1570
1571 return border;
1572 }
1573
1574 wxBorder wxWindowBase::GetDefaultBorder() const
1575 {
1576 return wxBORDER_NONE;
1577 }
1578
1579 // ----------------------------------------------------------------------------
1580 // hit testing
1581 // ----------------------------------------------------------------------------
1582
1583 wxHitTest wxWindowBase::DoHitTest(wxCoord x, wxCoord y) const
1584 {
1585 // here we just check if the point is inside the window or not
1586
1587 // check the top and left border first
1588 bool outside = x < 0 || y < 0;
1589 if ( !outside )
1590 {
1591 // check the right and bottom borders too
1592 wxSize size = GetSize();
1593 outside = x >= size.x || y >= size.y;
1594 }
1595
1596 return outside ? wxHT_WINDOW_OUTSIDE : wxHT_WINDOW_INSIDE;
1597 }
1598