]> git.saurik.com Git - wxWidgets.git/blame - src/common/wincmn.cpp
untested changes...
[wxWidgets.git] / src / common / wincmn.cpp
CommitLineData
7ec1983b 1/////////////////////////////////////////////////////////////////////////////
f03fc89f 2// Name: common/window.cpp
7ec1983b
VZ
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$
f03fc89f 8// Copyright: (c) wxWindows team
7ec1983b
VZ
9// Licence: wxWindows license
10/////////////////////////////////////////////////////////////////////////////
11
f03fc89f
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
f701d7ab 19
58654ed0
VZ
20#ifdef __GNUG__
21 #pragma implementation "windowbase.h"
22#endif
23
341287bf
JS
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
f701d7ab 27#ifdef __BORLANDC__
f03fc89f 28 #pragma hdrstop
f701d7ab
JS
29#endif
30
f03fc89f
VZ
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/checkbox.h"
39 #include "wx/radiobut.h"
40 #include "wx/settings.h"
41 #include "wx/dialog.h"
42#endif //WX_PRECOMP
43
44#if wxUSE_CONSTRAINTS
45 #include "wx/layout.h"
46#endif // wxUSE_CONSTRAINTS
47
48#if wxUSE_DRAG_AND_DROP
49 #include "wx/dnd.h"
50#endif // wxUSE_DRAG_AND_DROP
51
52#if wxUSE_TOOLTIPS
53 #include "wx/tooltip.h"
54#endif // wxUSE_TOOLTIPS
55
56// ----------------------------------------------------------------------------
57// static data
58// ----------------------------------------------------------------------------
59
69418a8e 60int wxWindowBase::ms_lastControlId = -2;
f03fc89f
VZ
61
62IMPLEMENT_ABSTRACT_CLASS(wxWindowBase, wxEvtHandler)
63
64// ----------------------------------------------------------------------------
65// event table
66// ----------------------------------------------------------------------------
67
68BEGIN_EVENT_TABLE(wxWindowBase, wxEvtHandler)
69 EVT_SYS_COLOUR_CHANGED(wxWindowBase::OnSysColourChanged)
70 EVT_INIT_DIALOG(wxWindowBase::OnInitDialog)
71END_EVENT_TABLE()
72
73// ============================================================================
74// implementation of the common functionality of the wxWindow class
75// ============================================================================
76
77// ----------------------------------------------------------------------------
78// initialization
79// ----------------------------------------------------------------------------
80
81// the default initialization
82void wxWindowBase::InitBase()
83{
84 // no window yet, no parent nor children
f03fc89f
VZ
85 m_parent = (wxWindow *)NULL;
86 m_windowId = -1;
87 m_children.DeleteContents( FALSE ); // don't auto delete node data
88
89 // no constraints on the minimal window size
90 m_minWidth =
91 m_minHeight =
92 m_maxWidth =
93 m_maxHeight = -1;
94
95 // window is created enabled but it's not visible yet
96 m_isShown = FALSE;
97 m_isEnabled = TRUE;
98
99 // no client data
100 m_clientObject = (wxClientData *)NULL;
101 m_clientData = NULL;
102
103 // the default event handler is just this window
104 m_eventHandler = this;
105
106 // no validator
107 m_windowValidator = (wxValidator *) NULL;
108
109 // use the system default colours
110 wxSystemSettings settings;
111
112 m_backgroundColour = settings.GetSystemColour(wxSYS_COLOUR_BTNFACE);
113 m_foregroundColour = *wxBLACK; // TODO take this from sys settings too?
114 m_font = *wxSWISS_FONT; // and this?
115
116 // no style bits
117 m_windowStyle = 0;
118
119 // an optimization for the event processing: checking this flag is much
120 // faster than using IsKindOf(CLASSINFO(wxWindow))
121 m_isWindow = TRUE;
122
123#if wxUSE_CONSTRAINTS
124 // no constraints whatsoever
125 m_constraints = (wxLayoutConstraints *) NULL;
126 m_constraintsInvolvedIn = (wxWindowList *) NULL;
127 m_windowSizer = (wxSizer *) NULL;
128 m_sizerParent = (wxWindowBase *) NULL;
129 m_autoLayout = FALSE;
130#endif // wxUSE_CONSTRAINTS
131
132#if wxUSE_DRAG_AND_DROP
133 m_dropTarget = (wxDropTarget *)NULL;
134#endif // wxUSE_DRAG_AND_DROP
135
136#if wxUSE_TOOLTIPS
137 m_tooltip = (wxToolTip *)NULL;
138#endif // wxUSE_TOOLTIPS
139}
140
141// common part of window creation process
142bool wxWindowBase::CreateBase(wxWindowBase *parent,
143 wxWindowID id,
74e3313b
VZ
144 const wxPoint& WXUNUSED(pos),
145 const wxSize& WXUNUSED(size),
f03fc89f
VZ
146 long style,
147 const wxString& name)
148{
149 // m_isWindow is set to TRUE in wxWindowBase::Init() as well as many other
150 // member variables - check that it has been called (will catch the case
151 // when a new ctor is added which doesn't call InitWindow)
152 wxASSERT_MSG( m_isWindow, _T("Init() must have been called before!") );
153
154 // generate a new id if the user doesn't care about it
69418a8e 155 m_windowId = id == -1 ? NewControlId() : id;
f03fc89f
VZ
156
157 SetName(name);
158 SetWindowStyleFlag(style);
159 SetParent(parent);
160
161 return TRUE;
162}
163
164// ----------------------------------------------------------------------------
165// destruction
166// ----------------------------------------------------------------------------
167
168// common clean up
169wxWindowBase::~wxWindowBase()
170{
171 // FIXME if these 2 cases result from programming errors in the user code
172 // we should probably assert here instead of silently fixing them
173
174 // Just in case the window has been Closed, but we're then deleting
175 // immediately: don't leave dangling pointers.
176 wxPendingDelete.DeleteObject(this);
177
178 // Just in case we've loaded a top-level window via LoadNativeDialog but
179 // we weren't a dialog class
180 wxTopLevelWindows.DeleteObject(this);
eb082a08
RR
181
182 wxASSERT_MSG( GetChildren().GetCount() == 0, "children not destroyed" );
f03fc89f
VZ
183
184 if ( m_windowValidator )
185 delete m_windowValidator;
186
187 if ( m_clientObject )
188 delete m_clientObject;
189
190#if wxUSE_CONSTRAINTS
191 // Have to delete constraints/sizer FIRST otherwise sizers may try to look
192 // at deleted windows as they delete themselves.
193 DeleteRelatedConstraints();
194
195 if ( m_constraints )
196 {
197 // This removes any dangling pointers to this window in other windows'
198 // constraintsInvolvedIn lists.
199 UnsetConstraints(m_constraints);
200 delete m_constraints;
201 m_constraints = NULL;
202 }
203
204 if ( m_windowSizer )
205 delete m_windowSizer;
206
207 // If this is a child of a sizer, remove self from parent
208 if ( m_sizerParent )
209 m_sizerParent->RemoveChild(this);
210#endif // wxUSE_CONSTRAINTS
211
212#if wxUSE_DRAG_AND_DROP
213 if ( m_dropTarget )
214 delete m_dropTarget;
215#endif // wxUSE_DRAG_AND_DROP
216
217#if wxUSE_TOOLTIPS
218 if ( m_tooltip )
219 delete m_tooltip;
220#endif // wxUSE_TOOLTIPS
221}
222
223bool wxWindowBase::Destroy()
224{
225 delete this;
226
227 return TRUE;
228}
229
230bool wxWindowBase::Close(bool force)
231{
232 wxCloseEvent event(wxEVT_CLOSE_WINDOW, m_windowId);
233 event.SetEventObject(this);
234#if WXWIN_COMPATIBILITY
235 event.SetForce(force);
236#endif // WXWIN_COMPATIBILITY
237 event.SetCanVeto(!force);
238
239 // return FALSE if window wasn't closed because the application vetoed the
240 // close event
241 return GetEventHandler()->ProcessEvent(event) && !event.GetVeto();
242}
243
244bool wxWindowBase::DestroyChildren()
245{
246 wxWindowList::Node *node;
eb082a08 247 while ( (node = GetChildren().GetFirst()) )
f03fc89f
VZ
248 {
249 wxWindow *child = node->GetData();
eb082a08
RR
250
251 wxASSERT_MSG( child, "m_children contains empty nodes" );
252
253 delete child;
254
255 wxASSERT_MSG( !GetChildren().Find(child), "child didn't remove itself using RemoveChild()" );
f03fc89f
VZ
256 }
257
258 return TRUE;
259}
260
261// ----------------------------------------------------------------------------
262// centre/fit the window
263// ----------------------------------------------------------------------------
264
265// centre the window with respect to its parent in either (or both) directions
266void wxWindowBase::Centre(int direction)
267{
268 int widthParent, heightParent;
269
270 wxWindow *parent = GetParent();
271 if ( parent )
272 {
273 parent->GetClientSize(&widthParent, &heightParent);
274 }
275 else
276 {
277 // centre with respect to the whole screen
278 wxDisplaySize(&widthParent, &heightParent);
279 }
280
281 int width, height;
282 GetSize(&width, &height);
283
284 int new_x = -1,
285 new_y = -1;
286
287 if ( direction & wxHORIZONTAL )
288 new_x = (widthParent - width)/2;
289
290 if ( direction & wxVERTICAL )
291 new_y = (heightParent - height)/2;
292
293 Move(new_x, new_y);
294}
295
296// fits the window around the children
297void wxWindowBase::Fit()
298{
299 int maxX = 0,
300 maxY = 0;
301
302 wxWindowList::Node *node = GetChildren().GetFirst();
303 while ( node )
304 {
305 wxWindow *win = node->GetData();
306 int wx, wy, ww, wh;
307 win->GetPosition(&wx, &wy);
308 win->GetSize(&ww, &wh);
309 if ( wx + ww > maxX )
310 maxX = wx + ww;
311 if ( wy + wh > maxY )
312 maxY = wy + wh;
313
314 node = node->GetNext();
315 }
316
317 // leave a margin
318 SetClientSize(maxX + 7, maxY + 14);
319}
320
321// set the min/max size of the window
322
323void wxWindowBase::SetSizeHints(int minW, int minH,
324 int maxW, int maxH,
325 int WXUNUSED(incW), int WXUNUSED(incH))
326{
327 m_minWidth = minW;
328 m_maxWidth = maxW;
329 m_minHeight = minH;
330 m_maxHeight = maxH;
331}
332
333// ----------------------------------------------------------------------------
334// show/hide/enable/disable the window
335// ----------------------------------------------------------------------------
336
337bool wxWindowBase::Show(bool show)
338{
339 if ( show != m_isShown )
340 {
341 m_isShown = show;
342
343 return TRUE;
344 }
345 else
346 {
347 return FALSE;
348 }
349}
350
351bool wxWindowBase::Enable(bool enable)
352{
353 if ( enable != m_isEnabled )
354 {
355 m_isEnabled = enable;
356
357 return TRUE;
358 }
359 else
360 {
361 return FALSE;
362 }
363}
364
365// ----------------------------------------------------------------------------
366// reparenting the window
367// ----------------------------------------------------------------------------
368
369void wxWindowBase::AddChild(wxWindowBase *child)
370{
371 wxCHECK_RET( child, _T("can't add a NULL child") );
372
373 GetChildren().Append(child);
374 child->SetParent(this);
375}
376
377void wxWindowBase::RemoveChild(wxWindowBase *child)
378{
379 wxCHECK_RET( child, _T("can't remove a NULL child") );
380
381 GetChildren().DeleteObject(child);
382 child->SetParent((wxWindow *)NULL);
383}
439b3bf1 384
f03fc89f
VZ
385bool wxWindowBase::Reparent(wxWindowBase *newParent)
386{
387 wxWindow *oldParent = GetParent();
388 if ( newParent == oldParent )
389 {
390 // nothing done
391 return FALSE;
392 }
393
394 // unlink this window from the existing parent.
395 if ( oldParent )
396 {
397 oldParent->RemoveChild(this);
398 }
399 else
400 {
401 wxTopLevelWindows.DeleteObject(this);
402 }
403
404 // add it to the new one
405 if ( newParent )
406 {
407 newParent->AddChild(this);
408 }
409 else
410 {
411 wxTopLevelWindows.Append(this);
412 }
413
414 return TRUE;
415}
416
417// ----------------------------------------------------------------------------
418// event handler stuff
419// ----------------------------------------------------------------------------
420
421void wxWindowBase::PushEventHandler(wxEvtHandler *handler)
422{
423 handler->SetNextHandler(GetEventHandler());
424 SetEventHandler(handler);
425}
426
427wxEvtHandler *wxWindowBase::PopEventHandler(bool deleteHandler)
428{
429 wxEvtHandler *handlerA = GetEventHandler();
430 if ( handlerA )
431 {
432 wxEvtHandler *handlerB = handlerA->GetNextHandler();
433 handlerA->SetNextHandler((wxEvtHandler *)NULL);
434 SetEventHandler(handlerB);
435 if ( deleteHandler )
436 {
437 delete handlerA;
438 handlerA = (wxEvtHandler *)NULL;
439 }
440 }
441
442 return handlerA;
443}
444
445// ----------------------------------------------------------------------------
446// cursors, fonts &c
447// ----------------------------------------------------------------------------
448
449bool wxWindowBase::SetBackgroundColour( const wxColour &colour )
450{
451 if ( !colour.Ok() || (colour == m_backgroundColour) )
452 return FALSE;
453
454 m_backgroundColour = colour;
455
456 return TRUE;
457}
458
459bool wxWindowBase::SetForegroundColour( const wxColour &colour )
460{
461 if ( !colour.Ok() || (colour == m_foregroundColour) )
462 return FALSE;
463
464 m_foregroundColour = colour;
465
466 return TRUE;
467}
468
469bool wxWindowBase::SetCursor(const wxCursor& cursor)
470{
471 // don't try to set invalid cursor, always fall back to the default
472 const wxCursor& cursorOk = cursor.Ok() ? cursor : *wxSTANDARD_CURSOR;
473
474 if ( cursorOk == m_cursor )
475 {
476 // no change
477 return FALSE;
478 }
479
480 m_cursor = cursorOk;
481
482 return TRUE;
483}
484
485bool wxWindowBase::SetFont(const wxFont& font)
486{
487 // don't try to set invalid font, always fall back to the default
488 const wxFont& fontOk = font.Ok() ? font : *wxSWISS_FONT;
489
490 if ( fontOk == m_font )
491 {
492 // no change
493 return FALSE;
494 }
495
496 m_font = fontOk;
497
498 return TRUE;
499}
500
501// ----------------------------------------------------------------------------
502// validators
503// ----------------------------------------------------------------------------
504
505void wxWindowBase::SetValidator(const wxValidator& validator)
506{
507 if ( m_windowValidator )
508 delete m_windowValidator;
509
510 m_windowValidator = (wxValidator *)validator.Clone();
511
512 if ( m_windowValidator )
513 m_windowValidator->SetWindow(this) ;
514}
515
516// ----------------------------------------------------------------------------
517// update region testing
518// ----------------------------------------------------------------------------
519
520bool wxWindowBase::IsExposed(int x, int y) const
521{
522 return m_updateRegion.Contains(x, y) != wxOutRegion;
523}
524
525bool wxWindowBase::IsExposed(int x, int y, int w, int h) const
526{
527 return m_updateRegion.Contains(x, y, w, h) != wxOutRegion;
528}
529
530// ----------------------------------------------------------------------------
531// find window by id or name
532// ----------------------------------------------------------------------------
533
534wxWindow *wxWindowBase::FindWindow( long id )
535{
536 if ( id == m_windowId )
537 return (wxWindow *)this;
538
539 wxWindowBase *res = (wxWindow *)NULL;
540 wxWindowList::Node *node;
541 for ( node = m_children.GetFirst(); node && !res; node = node->GetNext() )
542 {
543 wxWindowBase *child = node->GetData();
544 res = child->FindWindow( id );
545 }
546
547 return (wxWindow *)res;
548}
549
550wxWindow *wxWindowBase::FindWindow( const wxString& name )
551{
552 if ( name == m_windowName )
553 return (wxWindow *)this;
554
555 wxWindowBase *res = (wxWindow *)NULL;
556 wxWindowList::Node *node;
557 for ( node = m_children.GetFirst(); node && !res; node = node->GetNext() )
558 {
559 wxWindow *child = node->GetData();
560 res = child->FindWindow(name);
561 }
562
563 return (wxWindow *)res;
564}
565
566// ----------------------------------------------------------------------------
567// dialog oriented functions
568// ----------------------------------------------------------------------------
569
74e3313b 570void wxWindowBase::MakeModal(bool WXUNUSED(modal))
f03fc89f
VZ
571{
572 wxFAIL_MSG("TODO");
573}
574
575bool wxWindowBase::Validate()
576{
577 wxWindowList::Node *node;
578 for ( node = m_children.GetFirst(); node; node = node->GetNext() )
579 {
580 wxWindowBase *child = node->GetData();
581 wxValidator *validator = child->GetValidator();
582 if ( validator && validator->Validate(this) )
583 {
584 return FALSE;
585 }
586 }
587
588 return TRUE;
589}
590
591bool wxWindowBase::TransferDataToWindow()
592{
593 wxWindowList::Node *node;
594 for ( node = m_children.GetFirst(); node; node = node->GetNext() )
595 {
596 wxWindowBase *child = node->GetData();
597 wxValidator *validator = child->GetValidator();
598 if ( validator && !validator->TransferToWindow() )
599 {
600 wxLog *log = wxLog::GetActiveTarget();
601 if ( log )
602 {
603 wxLogWarning(_("Could not transfer data to window"));
604 log->Flush();
605 }
606
607 return FALSE;
608 }
609 }
610
611 return TRUE;
612}
613
614bool wxWindowBase::TransferDataFromWindow()
615{
616 wxWindowList::Node *node;
617 for ( node = m_children.GetFirst(); node; node = node->GetNext() )
618 {
619 wxWindow *child = node->GetData();
620 if ( child->GetValidator() &&
621 !child->GetValidator()->TransferFromWindow() )
622 {
623 return FALSE;
624 }
625 }
626
627 return TRUE;
628}
629
630void wxWindowBase::InitDialog()
631{
632 wxInitDialogEvent event(GetId());
633 event.SetEventObject( this );
634 GetEventHandler()->ProcessEvent(event);
635}
636
637// ----------------------------------------------------------------------------
638// tooltips
639// ----------------------------------------------------------------------------
640
641#if wxUSE_TOOLTIPS
642
643void wxWindowBase::SetToolTip( const wxString &tip )
644{
645 // don't create the new tooltip if we already have one
646 if ( m_tooltip )
647 {
648 m_tooltip->SetTip( tip );
649 }
650 else
651 {
652 SetToolTip( new wxToolTip( tip ) );
653 }
654
655 // setting empty tooltip text does not remove the tooltip any more - use
656 // SetToolTip((wxToolTip *)NULL) for this
657}
658
659void wxWindowBase::DoSetToolTip(wxToolTip *tooltip)
660{
661 if ( m_tooltip )
662 delete m_tooltip;
663
664 m_tooltip = tooltip;
665}
666
667#endif // wxUSE_TOOLTIPS
668
669// ----------------------------------------------------------------------------
670// constraints and sizers
671// ----------------------------------------------------------------------------
672
673#if wxUSE_CONSTRAINTS
674
675void wxWindowBase::SetConstraints( wxLayoutConstraints *constraints )
676{
677 if ( m_constraints )
678 {
679 UnsetConstraints(m_constraints);
680 delete m_constraints;
681 }
682 m_constraints = constraints;
683 if ( m_constraints )
684 {
685 // Make sure other windows know they're part of a 'meaningful relationship'
686 if ( m_constraints->left.GetOtherWindow() && (m_constraints->left.GetOtherWindow() != this) )
687 m_constraints->left.GetOtherWindow()->AddConstraintReference(this);
688 if ( m_constraints->top.GetOtherWindow() && (m_constraints->top.GetOtherWindow() != this) )
689 m_constraints->top.GetOtherWindow()->AddConstraintReference(this);
690 if ( m_constraints->right.GetOtherWindow() && (m_constraints->right.GetOtherWindow() != this) )
691 m_constraints->right.GetOtherWindow()->AddConstraintReference(this);
692 if ( m_constraints->bottom.GetOtherWindow() && (m_constraints->bottom.GetOtherWindow() != this) )
693 m_constraints->bottom.GetOtherWindow()->AddConstraintReference(this);
694 if ( m_constraints->width.GetOtherWindow() && (m_constraints->width.GetOtherWindow() != this) )
695 m_constraints->width.GetOtherWindow()->AddConstraintReference(this);
696 if ( m_constraints->height.GetOtherWindow() && (m_constraints->height.GetOtherWindow() != this) )
697 m_constraints->height.GetOtherWindow()->AddConstraintReference(this);
698 if ( m_constraints->centreX.GetOtherWindow() && (m_constraints->centreX.GetOtherWindow() != this) )
699 m_constraints->centreX.GetOtherWindow()->AddConstraintReference(this);
700 if ( m_constraints->centreY.GetOtherWindow() && (m_constraints->centreY.GetOtherWindow() != this) )
701 m_constraints->centreY.GetOtherWindow()->AddConstraintReference(this);
702 }
703}
704
705// This removes any dangling pointers to this window in other windows'
706// constraintsInvolvedIn lists.
707void wxWindowBase::UnsetConstraints(wxLayoutConstraints *c)
708{
709 if ( c )
710 {
711 if ( c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this) )
712 c->left.GetOtherWindow()->RemoveConstraintReference(this);
713 if ( c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this) )
714 c->top.GetOtherWindow()->RemoveConstraintReference(this);
715 if ( c->right.GetOtherWindow() && (c->right.GetOtherWindow() != this) )
716 c->right.GetOtherWindow()->RemoveConstraintReference(this);
717 if ( c->bottom.GetOtherWindow() && (c->bottom.GetOtherWindow() != this) )
718 c->bottom.GetOtherWindow()->RemoveConstraintReference(this);
719 if ( c->width.GetOtherWindow() && (c->width.GetOtherWindow() != this) )
720 c->width.GetOtherWindow()->RemoveConstraintReference(this);
721 if ( c->height.GetOtherWindow() && (c->height.GetOtherWindow() != this) )
722 c->height.GetOtherWindow()->RemoveConstraintReference(this);
723 if ( c->centreX.GetOtherWindow() && (c->centreX.GetOtherWindow() != this) )
724 c->centreX.GetOtherWindow()->RemoveConstraintReference(this);
725 if ( c->centreY.GetOtherWindow() && (c->centreY.GetOtherWindow() != this) )
726 c->centreY.GetOtherWindow()->RemoveConstraintReference(this);
727 }
728}
729
730// Back-pointer to other windows we're involved with, so if we delete this
731// window, we must delete any constraints we're involved with.
732void wxWindowBase::AddConstraintReference(wxWindowBase *otherWin)
733{
734 if ( !m_constraintsInvolvedIn )
735 m_constraintsInvolvedIn = new wxWindowList;
736 if ( !m_constraintsInvolvedIn->Find(otherWin) )
737 m_constraintsInvolvedIn->Append(otherWin);
738}
739
740// REMOVE back-pointer to other windows we're involved with.
741void wxWindowBase::RemoveConstraintReference(wxWindowBase *otherWin)
742{
743 if ( m_constraintsInvolvedIn )
744 m_constraintsInvolvedIn->DeleteObject(otherWin);
745}
746
747// Reset any constraints that mention this window
748void wxWindowBase::DeleteRelatedConstraints()
749{
750 if ( m_constraintsInvolvedIn )
751 {
752 wxWindowList::Node *node = m_constraintsInvolvedIn->GetFirst();
753 while (node)
754 {
755 wxWindow *win = node->GetData();
756 wxLayoutConstraints *constr = win->GetConstraints();
757
758 // Reset any constraints involving this window
759 if ( constr )
760 {
761 constr->left.ResetIfWin(this);
762 constr->top.ResetIfWin(this);
763 constr->right.ResetIfWin(this);
764 constr->bottom.ResetIfWin(this);
765 constr->width.ResetIfWin(this);
766 constr->height.ResetIfWin(this);
767 constr->centreX.ResetIfWin(this);
768 constr->centreY.ResetIfWin(this);
769 }
770
771 wxWindowList::Node *next = node->GetNext();
772 delete node;
773 node = next;
774 }
775
776 delete m_constraintsInvolvedIn;
777 m_constraintsInvolvedIn = (wxWindowList *) NULL;
778 }
779}
780
781void wxWindowBase::SetSizer(wxSizer *sizer)
782{
783 m_windowSizer = sizer;
784 if ( sizer )
785 sizer->SetSizerParent(this);
786}
787
788bool wxWindowBase::Layout()
789{
790 if ( GetConstraints() )
791 {
792 int w, h;
793 GetClientSize(&w, &h);
794 GetConstraints()->width.SetValue(w);
795 GetConstraints()->height.SetValue(h);
796 }
797
798 // If top level (one sizer), evaluate the sizer's constraints.
799 if ( GetSizer() )
800 {
801 int noChanges;
802 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
803 GetSizer()->LayoutPhase1(&noChanges);
804 GetSizer()->LayoutPhase2(&noChanges);
805 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
806 return TRUE;
807 }
808 else
809 {
810 // Otherwise, evaluate child constraints
811 ResetConstraints(); // Mark all constraints as unevaluated
812 DoPhase(1); // Just one phase need if no sizers involved
813 DoPhase(2);
814 SetConstraintSizes(); // Recursively set the real window sizes
815 }
816 return TRUE;
817}
818
819
820// Do a phase of evaluating constraints: the default behaviour. wxSizers may
821// do a similar thing, but also impose their own 'constraints' and order the
822// evaluation differently.
823bool wxWindowBase::LayoutPhase1(int *noChanges)
824{
825 wxLayoutConstraints *constr = GetConstraints();
826 if ( constr )
827 {
828 return constr->SatisfyConstraints(this, noChanges);
829 }
830 else
831 return TRUE;
832}
833
834bool wxWindowBase::LayoutPhase2(int *noChanges)
835{
836 *noChanges = 0;
837
838 // Layout children
839 DoPhase(1);
840 DoPhase(2);
841 return TRUE;
842}
843
844// Do a phase of evaluating child constraints
845bool wxWindowBase::DoPhase(int phase)
846{
847 int noIterations = 0;
848 int maxIterations = 500;
849 int noChanges = 1;
850 int noFailures = 0;
851 wxWindowList succeeded;
852 while ((noChanges > 0) && (noIterations < maxIterations))
853 {
854 noChanges = 0;
855 noFailures = 0;
856 wxWindowList::Node *node = GetChildren().GetFirst();
857 while (node)
858 {
859 wxWindow *child = node->GetData();
860 if ( !child->IsKindOf(CLASSINFO(wxFrame)) && !child->IsKindOf(CLASSINFO(wxDialog)) )
861 {
862 wxLayoutConstraints *constr = child->GetConstraints();
863 if ( constr )
864 {
865 if ( !succeeded.Find(child) )
866 {
867 int tempNoChanges = 0;
868 bool success = ( (phase == 1) ? child->LayoutPhase1(&tempNoChanges) : child->LayoutPhase2(&tempNoChanges) ) ;
869 noChanges += tempNoChanges;
870 if ( success )
871 {
872 succeeded.Append(child);
873 }
874 }
875 }
876 }
877 node = node->GetNext();
878 }
879
880 noIterations++;
881 }
882
883 return TRUE;
884}
885
886void wxWindowBase::ResetConstraints()
887{
888 wxLayoutConstraints *constr = GetConstraints();
889 if ( constr )
890 {
891 constr->left.SetDone(FALSE);
892 constr->top.SetDone(FALSE);
893 constr->right.SetDone(FALSE);
894 constr->bottom.SetDone(FALSE);
895 constr->width.SetDone(FALSE);
896 constr->height.SetDone(FALSE);
897 constr->centreX.SetDone(FALSE);
898 constr->centreY.SetDone(FALSE);
899 }
900 wxWindowList::Node *node = GetChildren().GetFirst();
901 while (node)
902 {
903 wxWindow *win = node->GetData();
904 if ( !win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)) )
905 win->ResetConstraints();
906 node = node->GetNext();
907 }
908}
909
910// Need to distinguish between setting the 'fake' size for windows and sizers,
911// and setting the real values.
912void wxWindowBase::SetConstraintSizes(bool recurse)
913{
914 wxLayoutConstraints *constr = GetConstraints();
915 if ( constr && constr->left.GetDone() && constr->right.GetDone( ) &&
916 constr->width.GetDone() && constr->height.GetDone())
917 {
918 int x = constr->left.GetValue();
919 int y = constr->top.GetValue();
920 int w = constr->width.GetValue();
921 int h = constr->height.GetValue();
922
923 // If we don't want to resize this window, just move it...
924 if ( (constr->width.GetRelationship() != wxAsIs ) ||
925 (constr->height.GetRelationship() != wxAsIs))
926 {
927 // Calls Layout() recursively. AAAGH. How can we stop that.
928 // Simply take Layout() out of non-top level OnSizes.
929 SizerSetSize(x, y, w, h);
930 }
931 else
932 {
933 SizerMove(x, y);
934 }
935 }
936 else if ( constr )
937 {
938 wxChar *windowClass = GetClassInfo()->GetClassName();
939
940 wxString winName;
941 if ( GetName() == _T("") )
942 winName = _T("unnamed");
943 else
944 winName = GetName();
945 wxLogDebug( _T("Constraint(s) not satisfied for window of type %s, name %s:\n"),
946 (const wxChar *)windowClass,
947 (const wxChar *)winName);
948 if ( !constr->left.GetDone()) wxLogDebug( _T(" unsatisfied 'left' constraint.\n") );
949 if ( !constr->right.GetDone()) wxLogDebug( _T(" unsatisfied 'right' constraint.\n") );
950 if ( !constr->width.GetDone()) wxLogDebug( _T(" unsatisfied 'width' constraint.\n") );
951 if ( !constr->height.GetDone()) wxLogDebug( _T(" unsatisfied 'height' constraint.\n") );
952 wxLogDebug( _T("Please check constraints: try adding AsIs() constraints.\n") );
953 }
954
955 if ( recurse )
956 {
957 wxWindowList::Node *node = GetChildren().GetFirst();
958 while (node)
959 {
960 wxWindow *win = node->GetData();
961 if ( !win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)) )
962 win->SetConstraintSizes();
963 node = node->GetNext();
964 }
965 }
966}
967
968// This assumes that all sizers are 'on' the same window, i.e. the parent of
969// this window.
970void wxWindowBase::TransformSizerToActual(int *x, int *y) const
971{
972 if ( !m_sizerParent || m_sizerParent->IsKindOf(CLASSINFO(wxDialog) ) ||
973 m_sizerParent->IsKindOf(CLASSINFO(wxFrame)) )
974 return;
975
976 int xp, yp;
977 m_sizerParent->GetPosition(&xp, &yp);
978 m_sizerParent->TransformSizerToActual(&xp, &yp);
979 *x += xp;
980 *y += yp;
981}
982
983void wxWindowBase::SizerSetSize(int x, int y, int w, int h)
984{
985 int xx = x;
986 int yy = y;
987 TransformSizerToActual(&xx, &yy);
988 SetSize(xx, yy, w, h);
989}
990
991void wxWindowBase::SizerMove(int x, int y)
992{
993 int xx = x;
994 int yy = y;
995 TransformSizerToActual(&xx, &yy);
996 Move(xx, yy);
997}
998
999// Only set the size/position of the constraint (if any)
1000void wxWindowBase::SetSizeConstraint(int x, int y, int w, int h)
1001{
1002 wxLayoutConstraints *constr = GetConstraints();
1003 if ( constr )
1004 {
1005 if ( x != -1 )
1006 {
1007 constr->left.SetValue(x);
1008 constr->left.SetDone(TRUE);
1009 }
1010 if ( y != -1 )
1011 {
1012 constr->top.SetValue(y);
1013 constr->top.SetDone(TRUE);
1014 }
1015 if ( w != -1 )
1016 {
1017 constr->width.SetValue(w);
1018 constr->width.SetDone(TRUE);
1019 }
1020 if ( h != -1 )
1021 {
1022 constr->height.SetValue(h);
1023 constr->height.SetDone(TRUE);
1024 }
1025 }
1026}
1027
1028void wxWindowBase::MoveConstraint(int x, int y)
1029{
1030 wxLayoutConstraints *constr = GetConstraints();
1031 if ( constr )
1032 {
1033 if ( x != -1 )
1034 {
1035 constr->left.SetValue(x);
1036 constr->left.SetDone(TRUE);
1037 }
1038 if ( y != -1 )
1039 {
1040 constr->top.SetValue(y);
1041 constr->top.SetDone(TRUE);
1042 }
1043 }
1044}
1045
1046void wxWindowBase::GetSizeConstraint(int *w, int *h) const
1047{
1048 wxLayoutConstraints *constr = GetConstraints();
1049 if ( constr )
1050 {
1051 *w = constr->width.GetValue();
1052 *h = constr->height.GetValue();
1053 }
1054 else
1055 GetSize(w, h);
1056}
1057
1058void wxWindowBase::GetClientSizeConstraint(int *w, int *h) const
1059{
1060 wxLayoutConstraints *constr = GetConstraints();
1061 if ( constr )
1062 {
1063 *w = constr->width.GetValue();
1064 *h = constr->height.GetValue();
1065 }
1066 else
1067 GetClientSize(w, h);
1068}
1069
1070void wxWindowBase::GetPositionConstraint(int *x, int *y) const
1071{
1072 wxLayoutConstraints *constr = GetConstraints();
1073 if ( constr )
1074 {
1075 *x = constr->left.GetValue();
1076 *y = constr->top.GetValue();
1077 }
1078 else
1079 GetPosition(x, y);
1080}
1081
1082#endif // wxUSE_CONSTRAINTS
1083
1084// ----------------------------------------------------------------------------
1085// do Update UI processing for child controls
1086// ----------------------------------------------------------------------------
7ec1983b
VZ
1087
1088// TODO: should this be implemented for the child window rather
1089// than the parent? Then you can override it e.g. for wxCheckBox
1090// to do the Right Thing rather than having to assume a fixed number
1091// of control classes.
f03fc89f 1092void wxWindowBase::UpdateWindowUI()
7ec1983b 1093{
f03fc89f
VZ
1094 wxWindowID id = GetId();
1095 if ( id > 0 )
7ec1983b 1096 {
f03fc89f
VZ
1097 wxUpdateUIEvent event(id);
1098 event.m_eventObject = this;
7ec1983b 1099
f03fc89f
VZ
1100 if ( GetEventHandler()->ProcessEvent(event) )
1101 {
1102 if ( event.GetSetEnabled() )
1103 Enable(event.GetEnabled());
7ec1983b 1104
f03fc89f
VZ
1105 if ( event.GetSetText() && IsKindOf(CLASSINFO(wxControl)) )
1106 ((wxControl*)this)->SetLabel(event.GetText());
1107
1108 if ( IsKindOf(CLASSINFO(wxCheckBox)) )
1109 {
1110 if ( event.GetSetChecked() )
1111 ((wxCheckBox *)this)->SetValue(event.GetChecked());
1112 }
1113 // TODO No radio buttons in wxGTK yet
7ec1983b 1114#ifndef __WXGTK__
f03fc89f
VZ
1115 else if ( IsKindOf(CLASSINFO(wxRadioButton)) )
1116 {
1117 if ( event.GetSetChecked() )
1118 ((wxRadioButton *) this)->SetValue(event.GetChecked());
1119 }
1120#endif // !wxGTK
1121 }
7ec1983b 1122 }
7ec1983b 1123}
fd71308f 1124
f03fc89f
VZ
1125// ----------------------------------------------------------------------------
1126// dialog units translations
1127// ----------------------------------------------------------------------------
1128
1129wxPoint wxWindowBase::ConvertPixelsToDialog(const wxPoint& pt)
fd71308f
JS
1130{
1131 int charWidth = GetCharWidth();
1132 int charHeight = GetCharHeight();
1133 wxPoint pt2;
1134 pt2.x = (int) ((pt.x * 4) / charWidth) ;
1135 pt2.y = (int) ((pt.y * 8) / charHeight) ;
1136
1137 return pt2;
1138}
1139
f03fc89f 1140wxPoint wxWindowBase::ConvertDialogToPixels(const wxPoint& pt)
fd71308f
JS
1141{
1142 int charWidth = GetCharWidth();
1143 int charHeight = GetCharHeight();
1144 wxPoint pt2;
1145 pt2.x = (int) ((pt.x * charWidth) / 4) ;
1146 pt2.y = (int) ((pt.y * charHeight) / 8) ;
1147
1148 return pt2;
1149}
1150
f03fc89f
VZ
1151// ----------------------------------------------------------------------------
1152// event handlers
1153// ----------------------------------------------------------------------------
1154
1155// propagate the colour change event to the subwindows
1156void wxWindowBase::OnSysColourChanged(wxSysColourChangedEvent& event)
1157{
1158 wxWindowList::Node *node = GetChildren().GetFirst();
1159 while ( node )
1160 {
1161 // Only propagate to non-top-level windows
1162 wxWindow *win = node->GetData();
1163 if ( !win->IsTopLevel() )
1164 {
1165 wxSysColourChangedEvent event2;
1166 event.m_eventObject = win;
1167 win->GetEventHandler()->ProcessEvent(event2);
1168 }
1169
1170 node = node->GetNext();
1171 }
1172}
1173
1174// the default action is to populate dialog with data when it's created
1175void wxWindowBase::OnInitDialog( wxInitDialogEvent &WXUNUSED(event) )
1176{
1177 TransferDataToWindow();
1178}
1179
1180// ----------------------------------------------------------------------------
1181// list classes implementation
1182// ----------------------------------------------------------------------------
1183
1184void wxWindowListNode::DeleteData()
1185{
1186 delete (wxWindow *)GetData();
1187}
1188