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