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