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