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