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