]> git.saurik.com Git - wxWidgets.git/blob - src/common/wincmn.cpp
even more fixes to last-minute wxFileSystem mods
[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 #if defined(__WXPM__)
75 int wxWindowBase::ms_lastControlId = 2000;
76 #else
77 int wxWindowBase::ms_lastControlId = -200;
78 #endif
79
80 IMPLEMENT_ABSTRACT_CLASS(wxWindowBase, wxEvtHandler)
81
82 // ----------------------------------------------------------------------------
83 // event table
84 // ----------------------------------------------------------------------------
85
86 BEGIN_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
95 END_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
106 void 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
193 bool 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
233 wxWindowBase::~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
299 bool wxWindowBase::Destroy()
300 {
301 delete this;
302
303 return TRUE;
304 }
305
306 bool 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
320 bool 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
349 void 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
464 void 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
474 void 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
483 wxSize 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
582 wxPoint wxWindowBase::GetClientAreaOrigin() const
583 {
584 return wxPoint(0, 0);
585 }
586
587 // set the min/max size of the window
588 void 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
598 void 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
607 void 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
621 wxSize 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
637 bool 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
651 bool 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
668 bool wxWindowBase::IsTopLevel() const
669 {
670 return FALSE;
671 }
672
673 // ----------------------------------------------------------------------------
674 // reparenting the window
675 // ----------------------------------------------------------------------------
676
677 void 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
690 void 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
698 bool 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
734 void 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
746 wxEvtHandler *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
768 bool 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
811 bool 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
823 bool 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
835 bool 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
850 bool 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
870 void 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
880 wxWindow *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
894 void 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
916 void 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
932 wxRect 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
944 bool wxWindowBase::IsExposed(int x, int y) const
945 {
946 return m_updateRegion.Contains(x, y) != wxOutRegion;
947 }
948
949 bool 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
958 wxWindow *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
974 wxWindow *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
998 typedef bool (*wxFindWindowCmp)(const wxWindow *win,
999 const wxString& label, long id);
1000
1001 static
1002 bool wxFindWindowCmpLabels(const wxWindow *win, const wxString& label,
1003 long WXUNUSED(id))
1004 {
1005 return win->GetLabel() == label;
1006 }
1007
1008 static
1009 bool wxFindWindowCmpNames(const wxWindow *win, const wxString& label,
1010 long WXUNUSED(id))
1011 {
1012 return win->GetName() == label;
1013 }
1014
1015 static
1016 bool 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
1023 static
1024 wxWindow *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()
1053 static
1054 wxWindow *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 */
1081 wxWindow *
1082 wxWindowBase::FindWindowByLabel(const wxString& title, const wxWindow *parent)
1083 {
1084 return wxFindWindowHelper(parent, title, 0, wxFindWindowCmpLabels);
1085 }
1086
1087 /* static */
1088 wxWindow *
1089 wxWindowBase::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 */
1103 wxWindow *
1104 wxWindowBase::FindWindowById( long id, const wxWindow* parent )
1105 {
1106 return wxFindWindowHelper(parent, _T(""), id, wxFindWindowCmpIds);
1107 }
1108
1109 // ----------------------------------------------------------------------------
1110 // dialog oriented functions
1111 // ----------------------------------------------------------------------------
1112
1113 void 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
1130 bool 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
1155 bool 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
1187 bool 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
1219 void 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
1233 void 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
1244 void 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)
1254 wxString 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
1267 void 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
1290 void 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
1306 void 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
1322 void 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.
1354 void 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.
1379 void 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.
1388 void wxWindowBase::RemoveConstraintReference(wxWindowBase *otherWin)
1389 {
1390 if ( m_constraintsInvolvedIn )
1391 m_constraintsInvolvedIn->DeleteObject(otherWin);
1392 }
1393
1394 // Reset any constraints that mention this window
1395 void 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
1430 void 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
1440 void wxWindowBase::SetSizerAndFit(wxSizer *sizer, bool deleteOld)
1441 {
1442 SetSizer( sizer, deleteOld );
1443 sizer->SetSizeHints( (wxWindow*) this );
1444 }
1445
1446 #if wxUSE_CONSTRAINTS
1447
1448 void 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
1473 bool 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
1496 bool 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
1504 bool 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
1518 bool 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
1571 void 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.
1598 void 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)
1640 void 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
1668 void 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
1686 void 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
1698 void 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
1710 void 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
1724 void 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.
1748 void 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
1805 wxPoint 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
1818 wxPoint 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
1836 void 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
1855 void wxWindowBase::OnInitDialog( wxInitDialogEvent &WXUNUSED(event) )
1856 {
1857 TransferDataToWindow();
1858 }
1859
1860 // process Ctrl-Alt-mclick
1861 void 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
1929 void wxWindowListNode::DeleteData()
1930 {
1931 delete (wxWindow *)GetData();
1932 }
1933
1934 // ----------------------------------------------------------------------------
1935 // borders
1936 // ----------------------------------------------------------------------------
1937
1938 wxBorder 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
1949 wxBorder wxWindowBase::GetDefaultBorder() const
1950 {
1951 return wxBORDER_NONE;
1952 }
1953
1954 // ----------------------------------------------------------------------------
1955 // hit testing
1956 // ----------------------------------------------------------------------------
1957
1958 wxHitTest 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
1978 struct WXDLLEXPORT wxWindowNext
1979 {
1980 wxWindow *win;
1981 wxWindowNext *next;
1982 } *wxWindowBase::ms_winCaptureNext = NULL;
1983
1984 void 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
2004 void 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
2031 wxWindow* 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