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