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