]> git.saurik.com Git - wxWidgets.git/blame - src/os2/window.cpp
1. minor headers rearrangement: wxprec.h doesn't include setup.h directly
[wxWidgets.git] / src / os2 / window.cpp
CommitLineData
0e320a79
DW
1/////////////////////////////////////////////////////////////////////////////
2// Name: windows.cpp
3// Purpose: wxWindow
4// Author: AUTHOR
5// Modified by:
6// Created: ??/??/98
7// RCS-ID: $Id$
8// Copyright: (c) AUTHOR
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "window.h"
14#endif
15
16#include "wx/setup.h"
17#include "wx/menu.h"
18#include "wx/dc.h"
19#include "wx/dcclient.h"
20#include "wx/utils.h"
21#include "wx/app.h"
22#include "wx/panel.h"
23#include "wx/layout.h"
24#include "wx/dialog.h"
25#include "wx/listbox.h"
26#include "wx/button.h"
27#include "wx/settings.h"
28#include "wx/msgdlg.h"
29#include "wx/frame.h"
30
31#include "wx/menuitem.h"
32#include "wx/log.h"
33
34#if wxUSE_DRAG_AND_DROP
35#include "wx/dnd.h"
36#endif
37
38#include <string.h>
39
40extern wxList wxPendingDelete;
41
42#if !USE_SHARED_LIBRARY
43IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxEvtHandler)
44
45BEGIN_EVENT_TABLE(wxWindow, wxEvtHandler)
46 EVT_CHAR(wxWindow::OnChar)
47 EVT_KEY_DOWN(wxWindow::OnKeyDown)
48 EVT_KEY_UP(wxWindow::OnKeyUp)
49 EVT_ERASE_BACKGROUND(wxWindow::OnEraseBackground)
50 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged)
51 EVT_INIT_DIALOG(wxWindow::OnInitDialog)
52 EVT_IDLE(wxWindow::OnIdle)
53END_EVENT_TABLE()
54
55#endif
56
57
58// Constructor
59wxWindow::wxWindow()
60{
61 // Generic
62 m_isWindow = TRUE; // An optimization
63 m_windowId = 0;
64 m_windowStyle = 0;
65 m_windowParent = NULL;
66 m_windowEventHandler = this;
67 m_windowName = "";
68 m_windowCursor = *wxSTANDARD_CURSOR;
69 m_children = new wxList;
70 m_constraints = NULL;
71 m_constraintsInvolvedIn = NULL;
72 m_windowSizer = NULL;
73 m_sizerParent = NULL;
74 m_autoLayout = FALSE;
75 m_windowValidator = NULL;
76 m_defaultItem = NULL;
77 m_returnCode = 0;
78 m_caretWidth = 0; m_caretHeight = 0;
79 m_caretEnabled = FALSE;
80 m_caretShown = FALSE;
81 m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE) ;
82 // m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW) ; ;
83 m_foregroundColour = *wxBLACK;
84
85#if wxUSE_DRAG_AND_DROP
86 m_pDropTarget = NULL;
87#endif
88}
89
90// Destructor
91wxWindow::~wxWindow()
92{
93 // Have to delete constraints/sizer FIRST otherwise
94 // sizers may try to look at deleted windows as they
95 // delete themselves.
96#if wxUSE_CONSTRAINTS
97 DeleteRelatedConstraints();
98 if (m_constraints)
99 {
100 // This removes any dangling pointers to this window
101 // in other windows' constraintsInvolvedIn lists.
102 UnsetConstraints(m_constraints);
103 delete m_constraints;
104 m_constraints = NULL;
105 }
106 if (m_windowSizer)
107 {
108 delete m_windowSizer;
109 m_windowSizer = NULL;
110 }
111 // If this is a child of a sizer, remove self from parent
112 if (m_sizerParent)
113 m_sizerParent->RemoveChild((wxWindow *)this);
114#endif
115
116 if (m_windowParent)
117 m_windowParent->RemoveChild(this);
118
119 DestroyChildren();
120
121 // TODO: destroy the window
122
123 delete m_children;
124 m_children = NULL;
125
126 // Just in case the window has been Closed, but
127 // we're then deleting immediately: don't leave
128 // dangling pointers.
129 wxPendingDelete.DeleteObject(this);
130
131 if ( m_windowValidator )
132 delete m_windowValidator;
133}
134
135// Destroy the window (delayed, if a managed window)
136bool wxWindow::Destroy()
137{
138 delete this;
139 return TRUE;
140}
141
142// Constructor
143bool wxWindow::Create(wxWindow *parent, wxWindowID id,
144 const wxPoint& pos,
145 const wxSize& size,
146 long style,
147 const wxString& name)
148{
149 // Generic
150 m_isWindow = TRUE; // An optimization
151 m_windowId = 0;
152 m_windowStyle = 0;
153 m_windowParent = NULL;
154 m_windowEventHandler = this;
155 m_windowName = "";
156 m_windowCursor = *wxSTANDARD_CURSOR;
157 m_constraints = NULL;
158 m_constraintsInvolvedIn = NULL;
159 m_windowSizer = NULL;
160 m_sizerParent = NULL;
161 m_autoLayout = FALSE;
162 m_windowValidator = NULL;
163
164#if wxUSE_DRAG_AND_DROP
165 m_pDropTarget = NULL;
166#endif
167
168 m_caretWidth = 0; m_caretHeight = 0;
169 m_caretEnabled = FALSE;
170 m_caretShown = FALSE;
171 m_minSizeX = -1;
172 m_minSizeY = -1;
173 m_maxSizeX = -1;
174 m_maxSizeY = -1;
175 m_defaultItem = NULL;
176 m_windowParent = NULL;
177 if (!parent)
178 return FALSE;
179
180 if (parent) parent->AddChild(this);
181
182 m_returnCode = 0;
183
184 SetName(name);
185
186 if ( id == -1 )
187 m_windowId = (int)NewControlId();
188 else
189 m_windowId = id;
190
191 // m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW) ; ;
192 m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE) ;
193 m_foregroundColour = *wxBLACK;
194
195 m_windowStyle = style;
196
197 if ( id == -1 )
198 m_windowId = (int)NewControlId();
199 else
200 m_windowId = id;
201
202 // TODO: create the window
203
204 return TRUE;
205}
206
207void wxWindow::SetFocus()
208{
209 // TODO
210}
211
212void wxWindow::Enable(bool enable)
213{
214 // TODO
215}
216
217void wxWindow::CaptureMouse()
218{
219 // TODO
220}
221
222void wxWindow::ReleaseMouse()
223{
224 // TODO
225}
226
227// Push/pop event handler (i.e. allow a chain of event handlers
228// be searched)
229void wxWindow::PushEventHandler(wxEvtHandler *handler)
230{
231 handler->SetNextHandler(GetEventHandler());
232 SetEventHandler(handler);
233}
234
235wxEvtHandler *wxWindow::PopEventHandler(bool deleteHandler)
236{
237 if ( GetEventHandler() )
238 {
239 wxEvtHandler *handlerA = GetEventHandler();
240 wxEvtHandler *handlerB = handlerA->GetNextHandler();
241 handlerA->SetNextHandler(NULL);
242 SetEventHandler(handlerB);
243 if ( deleteHandler )
244 {
245 delete handlerA;
246 return NULL;
247 }
248 else
249 return handlerA;
250 }
251 else
252 return NULL;
253}
254
255#if wxUSE_DRAG_AND_DROP
256
257void wxWindow::SetDropTarget(wxDropTarget *pDropTarget)
258{
259 if ( m_pDropTarget != 0 ) {
260 delete m_pDropTarget;
261 }
262
263 m_pDropTarget = pDropTarget;
264 if ( m_pDropTarget != 0 )
265 {
266 // TODO
267 }
268}
269
270#endif
271
272// Old style file-manager drag&drop
273void wxWindow::DragAcceptFiles(bool accept)
274{
275 // TODO
276}
277
278// Get total size
279void wxWindow::GetSize(int *x, int *y) const
280{
281 // TODO
282}
283
284void wxWindow::GetPosition(int *x, int *y) const
285{
286 // TODO
287}
288
289void wxWindow::ScreenToClient(int *x, int *y) const
290{
291 // TODO
292}
293
294void wxWindow::ClientToScreen(int *x, int *y) const
295{
296 // TODO
297}
298
299void wxWindow::SetCursor(const wxCursor& cursor)
300{
301 m_windowCursor = cursor;
302 if (m_windowCursor.Ok())
303 {
304 // TODO
305 }
306}
307
308
309// Get size *available for subwindows* i.e. excluding menu bar etc.
310void wxWindow::GetClientSize(int *x, int *y) const
311{
312 // TODO
313}
314
315void wxWindow::SetSize(int x, int y, int width, int height, int sizeFlags)
316{
317 // TODO
318}
319
320void wxWindow::SetClientSize(int width, int height)
321{
322 // TODO
323}
324
325// For implementation purposes - sometimes decorations make the client area
326// smaller
327wxPoint wxWindow::GetClientAreaOrigin() const
328{
329 return wxPoint(0, 0);
330}
331
332// Makes an adjustment to the window position (for example, a frame that has
333// a toolbar that it manages itself).
334void wxWindow::AdjustForParentClientOrigin(int& x, int& y, int sizeFlags)
335{
336 if (((sizeFlags & wxSIZE_NO_ADJUSTMENTS) == 0) && GetParent())
337 {
338 wxPoint pt(GetParent()->GetClientAreaOrigin());
339 x += pt.x; y += pt.y;
340 }
341}
342
343bool wxWindow::Show(bool show)
344{
345 // TODO
346 return FALSE;
347}
348
349bool wxWindow::IsShown() const
350{
351 // TODO
352 return FALSE;
353}
354
355int wxWindow::GetCharHeight() const
356{
357 // TODO
358 return 0;
359}
360
361int wxWindow::GetCharWidth() const
362{
363 // TODO
364 return 0;
365}
366
367void wxWindow::GetTextExtent(const wxString& string, int *x, int *y,
368 int *descent, int *externalLeading, const wxFont *theFont, bool) const
369{
370 wxFont *fontToUse = (wxFont *)theFont;
371 if (!fontToUse)
372 fontToUse = (wxFont *) & m_windowFont;
373
374 // TODO
375}
376
377void wxWindow::Refresh(bool eraseBack, const wxRect *rect)
378{
379 // TODO
380}
381
382// Responds to colour changes: passes event on to children.
383void wxWindow::OnSysColourChanged(wxSysColourChangedEvent& event)
384{
385 wxNode *node = GetChildren().First();
386 while ( node )
387 {
388 // Only propagate to non-top-level windows
389 wxWindow *win = (wxWindow *)node->Data();
390 if ( win->GetParent() )
391 {
392 wxSysColourChangedEvent event2;
393 event.m_eventObject = win;
394 win->GetEventHandler()->ProcessEvent(event2);
395 }
396
397 node = node->Next();
398 }
399}
400
401// This can be called by the app (or wxWindows) to do default processing for the current
402// event. Save message/event info in wxWindow so they can be used in this function.
403long wxWindow::Default()
404{
405 // TODO
406 return 0;
407}
408
409void wxWindow::InitDialog()
410{
411 wxInitDialogEvent event(GetId());
412 event.SetEventObject( this );
413 GetEventHandler()->ProcessEvent(event);
414}
415
416// Default init dialog behaviour is to transfer data to window
417void wxWindow::OnInitDialog(wxInitDialogEvent& event)
418{
419 TransferDataToWindow();
420}
421
422// Caret manipulation
423void wxWindow::CreateCaret(int w, int h)
424{
425 m_caretWidth = w;
426 m_caretHeight = h;
427 m_caretEnabled = TRUE;
428}
429
430void wxWindow::CreateCaret(const wxBitmap *WXUNUSED(bitmap))
431{
432 // TODO
433}
434
435void wxWindow::ShowCaret(bool show)
436{
437 // TODO
438}
439
440void wxWindow::DestroyCaret()
441{
442 // TODO
443 m_caretEnabled = FALSE;
444}
445
446void wxWindow::SetCaretPos(int x, int y)
447{
448 // TODO
449}
450
451void wxWindow::GetCaretPos(int *x, int *y) const
452{
453 // TODO
454}
455
456wxWindow *wxGetActiveWindow()
457{
458 // TODO
459 return NULL;
460}
461
462void wxWindow::SetSizeHints(int minW, int minH, int maxW, int maxH, int WXUNUSED(incW), int WXUNUSED(incH))
463{
464 m_minSizeX = minW;
465 m_minSizeY = minH;
466 m_maxSizeX = maxW;
467 m_maxSizeY = maxH;
468}
469
470void wxWindow::Centre(int direction)
471{
472 int x, y, width, height, panel_width, panel_height, new_x, new_y;
473
474 wxWindow *father = (wxWindow *)GetParent();
475 if (!father)
476 return;
477
478 father->GetClientSize(&panel_width, &panel_height);
479 GetSize(&width, &height);
480 GetPosition(&x, &y);
481
482 new_x = -1;
483 new_y = -1;
484
485 if (direction & wxHORIZONTAL)
486 new_x = (int)((panel_width - width)/2);
487
488 if (direction & wxVERTICAL)
489 new_y = (int)((panel_height - height)/2);
490
491 SetSize(new_x, new_y, -1, -1);
492
493}
494
495// Coordinates relative to the window
496void wxWindow::WarpPointer (int x_pos, int y_pos)
497{
498 // TODO
499}
500
501void wxWindow::OnEraseBackground(wxEraseEvent& event)
502{
503 // TODO
504 Default();
505}
506
507int wxWindow::GetScrollPos(int orient) const
508{
509 // TODO
510 return 0;
511}
512
513// This now returns the whole range, not just the number
514// of positions that we can scroll.
515int wxWindow::GetScrollRange(int orient) const
516{
517 // TODO
518 return 0;
519}
520
521int wxWindow::GetScrollThumb(int orient) const
522{
523 // TODO
524 return 0;
525}
526
527void wxWindow::SetScrollPos(int orient, int pos, bool refresh)
528{
529 // TODO
530 return;
531}
532
533// New function that will replace some of the above.
534void wxWindow::SetScrollbar(int orient, int pos, int thumbVisible,
535 int range, bool refresh)
536{
537 // TODO
538}
539
540// Does a physical scroll
541void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect)
542{
543 // TODO
544 return;
545}
546
547void wxWindow::SetFont(const wxFont& font)
548{
549 m_windowFont = font;
550
551 if (!m_windowFont.Ok())
552 return;
553 // TODO
554}
555
556void wxWindow::OnChar(wxKeyEvent& event)
557{
558/* ??
559 if ( event.KeyCode() == WXK_TAB ) {
560 // propagate the TABs to the parent - it's up to it to decide what
561 // to do with it
562 if ( GetParent() ) {
563 if ( GetParent()->ProcessEvent(event) )
564 return;
565 }
566 }
567*/
568 Default();
569}
570
571void wxWindow::OnKeyDown(wxKeyEvent& event)
572{
573 Default();
574}
575
576void wxWindow::OnKeyUp(wxKeyEvent& event)
577{
578 Default();
579}
580
581void wxWindow::OnPaint(wxPaintEvent& event)
582{
583 Default();
584}
585
586bool wxWindow::IsEnabled() const
587{
588 // TODO
589 return FALSE;
590}
591
592// Dialog support: override these and call
593// base class members to add functionality
594// that can't be done using validators.
595// NOTE: these functions assume that controls
596// are direct children of this window, not grandchildren
597// or other levels of descendant.
598
599// Transfer values to controls. If returns FALSE,
600// it's an application error (pops up a dialog)
601bool wxWindow::TransferDataToWindow()
602{
603 wxNode *node = GetChildren().First();
604 while ( node )
605 {
606 wxWindow *child = (wxWindow *)node->Data();
607 if ( child->GetValidator() &&
608 !child->GetValidator()->TransferToWindow() )
609 {
610 wxMessageBox("Application Error", "Could not transfer data to window", wxOK|wxICON_EXCLAMATION);
611 return FALSE;
612 }
613
614 node = node->Next();
615 }
616 return TRUE;
617}
618
619// Transfer values from controls. If returns FALSE,
620// validation failed: don't quit
621bool wxWindow::TransferDataFromWindow()
622{
623 wxNode *node = GetChildren().First();
624 while ( node )
625 {
626 wxWindow *child = (wxWindow *)node->Data();
627 if ( child->GetValidator() && !child->GetValidator()->TransferFromWindow() )
628 {
629 return FALSE;
630 }
631
632 node = node->Next();
633 }
634 return TRUE;
635}
636
637bool wxWindow::Validate()
638{
639 wxNode *node = GetChildren().First();
640 while ( node )
641 {
642 wxWindow *child = (wxWindow *)node->Data();
643 if ( child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->Validate(this) )
644 {
645 return FALSE;
646 }
647
648 node = node->Next();
649 }
650 return TRUE;
651}
652
653// Get the window with the focus
654wxWindow *wxWindow::FindFocus()
655{
656 // TODO
657 return NULL;
658}
659
660void wxWindow::AddChild(wxWindow *child)
661{
662 GetChildren().Append(child);
663 child->m_windowParent = this;
664}
665
666void wxWindow::RemoveChild(wxWindow *child)
667{
668 GetChildren().DeleteObject(child);
669 child->m_windowParent = NULL;
670}
671
672void wxWindow::DestroyChildren()
673{
674 wxNode *node;
675 while ((node = GetChildren().First()) != (wxNode *)NULL) {
676 wxWindow *child;
677 if ((child = (wxWindow *)node->Data()) != (wxWindow *)NULL) {
678 delete child;
679 if ( GetChildren().Member(child) )
680 delete node;
681 }
682 } /* while */
683}
684
685void wxWindow::MakeModal(bool modal)
686{
687 // Disable all other windows
688 if (this->IsKindOf(CLASSINFO(wxDialog)) || this->IsKindOf(CLASSINFO(wxFrame)))
689 {
690 wxNode *node = wxTopLevelWindows.First();
691 while (node)
692 {
693 wxWindow *win = (wxWindow *)node->Data();
694 if (win != this)
695 win->Enable(!modal);
696
697 node = node->Next();
698 }
699 }
700}
701
702// If nothing defined for this, try the parent.
703// E.g. we may be a button loaded from a resource, with no callback function
704// defined.
705void wxWindow::OnCommand(wxWindow& win, wxCommandEvent& event)
706{
707 if (GetEventHandler()->ProcessEvent(event) )
708 return;
709 if (m_windowParent)
710 m_windowParent->GetEventHandler()->OnCommand(win, event);
711}
712
713void wxWindow::SetConstraints(wxLayoutConstraints *c)
714{
715 if (m_constraints)
716 {
717 UnsetConstraints(m_constraints);
718 delete m_constraints;
719 }
720 m_constraints = c;
721 if (m_constraints)
722 {
723 // Make sure other windows know they're part of a 'meaningful relationship'
724 if (m_constraints->left.GetOtherWindow() && (m_constraints->left.GetOtherWindow() != this))
725 m_constraints->left.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
726 if (m_constraints->top.GetOtherWindow() && (m_constraints->top.GetOtherWindow() != this))
727 m_constraints->top.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
728 if (m_constraints->right.GetOtherWindow() && (m_constraints->right.GetOtherWindow() != this))
729 m_constraints->right.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
730 if (m_constraints->bottom.GetOtherWindow() && (m_constraints->bottom.GetOtherWindow() != this))
731 m_constraints->bottom.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
732 if (m_constraints->width.GetOtherWindow() && (m_constraints->width.GetOtherWindow() != this))
733 m_constraints->width.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
734 if (m_constraints->height.GetOtherWindow() && (m_constraints->height.GetOtherWindow() != this))
735 m_constraints->height.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
736 if (m_constraints->centreX.GetOtherWindow() && (m_constraints->centreX.GetOtherWindow() != this))
737 m_constraints->centreX.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
738 if (m_constraints->centreY.GetOtherWindow() && (m_constraints->centreY.GetOtherWindow() != this))
739 m_constraints->centreY.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
740 }
741}
742
743// This removes any dangling pointers to this window
744// in other windows' constraintsInvolvedIn lists.
745void wxWindow::UnsetConstraints(wxLayoutConstraints *c)
746{
747 if (c)
748 {
749 if (c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this))
750 c->left.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
751 if (c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this))
752 c->top.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
753 if (c->right.GetOtherWindow() && (c->right.GetOtherWindow() != this))
754 c->right.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
755 if (c->bottom.GetOtherWindow() && (c->bottom.GetOtherWindow() != this))
756 c->bottom.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
757 if (c->width.GetOtherWindow() && (c->width.GetOtherWindow() != this))
758 c->width.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
759 if (c->height.GetOtherWindow() && (c->height.GetOtherWindow() != this))
760 c->height.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
761 if (c->centreX.GetOtherWindow() && (c->centreX.GetOtherWindow() != this))
762 c->centreX.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
763 if (c->centreY.GetOtherWindow() && (c->centreY.GetOtherWindow() != this))
764 c->centreY.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
765 }
766}
767
768// Back-pointer to other windows we're involved with, so if we delete
769// this window, we must delete any constraints we're involved with.
770void wxWindow::AddConstraintReference(wxWindow *otherWin)
771{
772 if (!m_constraintsInvolvedIn)
773 m_constraintsInvolvedIn = new wxList;
774 if (!m_constraintsInvolvedIn->Member(otherWin))
775 m_constraintsInvolvedIn->Append(otherWin);
776}
777
778// REMOVE back-pointer to other windows we're involved with.
779void wxWindow::RemoveConstraintReference(wxWindow *otherWin)
780{
781 if (m_constraintsInvolvedIn)
782 m_constraintsInvolvedIn->DeleteObject(otherWin);
783}
784
785// Reset any constraints that mention this window
786void wxWindow::DeleteRelatedConstraints()
787{
788 if (m_constraintsInvolvedIn)
789 {
790 wxNode *node = m_constraintsInvolvedIn->First();
791 while (node)
792 {
793 wxWindow *win = (wxWindow *)node->Data();
794 wxNode *next = node->Next();
795 wxLayoutConstraints *constr = win->GetConstraints();
796
797 // Reset any constraints involving this window
798 if (constr)
799 {
800 constr->left.ResetIfWin((wxWindow *)this);
801 constr->top.ResetIfWin((wxWindow *)this);
802 constr->right.ResetIfWin((wxWindow *)this);
803 constr->bottom.ResetIfWin((wxWindow *)this);
804 constr->width.ResetIfWin((wxWindow *)this);
805 constr->height.ResetIfWin((wxWindow *)this);
806 constr->centreX.ResetIfWin((wxWindow *)this);
807 constr->centreY.ResetIfWin((wxWindow *)this);
808 }
809 delete node;
810 node = next;
811 }
812 delete m_constraintsInvolvedIn;
813 m_constraintsInvolvedIn = NULL;
814 }
815}
816
817void wxWindow::SetSizer(wxSizer *sizer)
818{
819 m_windowSizer = sizer;
820 if (sizer)
821 sizer->SetSizerParent((wxWindow *)this);
822}
823
824/*
825 * New version
826 */
827
828bool wxWindow::Layout()
829{
830 if (GetConstraints())
831 {
832 int w, h;
833 GetClientSize(&w, &h);
834 GetConstraints()->width.SetValue(w);
835 GetConstraints()->height.SetValue(h);
836 }
837
838 // If top level (one sizer), evaluate the sizer's constraints.
839 if (GetSizer())
840 {
841 int noChanges;
842 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
843 GetSizer()->LayoutPhase1(&noChanges);
844 GetSizer()->LayoutPhase2(&noChanges);
845 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
846 return TRUE;
847 }
848 else
849 {
850 // Otherwise, evaluate child constraints
851 ResetConstraints(); // Mark all constraints as unevaluated
852 DoPhase(1); // Just one phase need if no sizers involved
853 DoPhase(2);
854 SetConstraintSizes(); // Recursively set the real window sizes
855 }
856 return TRUE;
857}
858
859
860// Do a phase of evaluating constraints:
861// the default behaviour. wxSizers may do a similar
862// thing, but also impose their own 'constraints'
863// and order the evaluation differently.
864bool wxWindow::LayoutPhase1(int *noChanges)
865{
866 wxLayoutConstraints *constr = GetConstraints();
867 if (constr)
868 {
869 return constr->SatisfyConstraints((wxWindow *)this, noChanges);
870 }
871 else
872 return TRUE;
873}
874
875bool wxWindow::LayoutPhase2(int *noChanges)
876{
877 *noChanges = 0;
878
879 // Layout children
880 DoPhase(1);
881 DoPhase(2);
882 return TRUE;
883}
884
885// Do a phase of evaluating child constraints
886bool wxWindow::DoPhase(int phase)
887{
888 int noIterations = 0;
889 int maxIterations = 500;
890 int noChanges = 1;
891 int noFailures = 0;
892 wxList succeeded;
893 while ((noChanges > 0) && (noIterations < maxIterations))
894 {
895 noChanges = 0;
896 noFailures = 0;
897 wxNode *node = GetChildren().First();
898 while (node)
899 {
900 wxWindow *child = (wxWindow *)node->Data();
901 if (!child->IsKindOf(CLASSINFO(wxFrame)) && !child->IsKindOf(CLASSINFO(wxDialog)))
902 {
903 wxLayoutConstraints *constr = child->GetConstraints();
904 if (constr)
905 {
906 if (succeeded.Member(child))
907 {
908 }
909 else
910 {
911 int tempNoChanges = 0;
912 bool success = ( (phase == 1) ? child->LayoutPhase1(&tempNoChanges) : child->LayoutPhase2(&tempNoChanges) ) ;
913 noChanges += tempNoChanges;
914 if (success)
915 {
916 succeeded.Append(child);
917 }
918 }
919 }
920 }
921 node = node->Next();
922 }
923 noIterations ++;
924 }
925 return TRUE;
926}
927
928void wxWindow::ResetConstraints()
929{
930 wxLayoutConstraints *constr = GetConstraints();
931 if (constr)
932 {
933 constr->left.SetDone(FALSE);
934 constr->top.SetDone(FALSE);
935 constr->right.SetDone(FALSE);
936 constr->bottom.SetDone(FALSE);
937 constr->width.SetDone(FALSE);
938 constr->height.SetDone(FALSE);
939 constr->centreX.SetDone(FALSE);
940 constr->centreY.SetDone(FALSE);
941 }
942 wxNode *node = GetChildren().First();
943 while (node)
944 {
945 wxWindow *win = (wxWindow *)node->Data();
946 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
947 win->ResetConstraints();
948 node = node->Next();
949 }
950}
951
952// Need to distinguish between setting the 'fake' size for
953// windows and sizers, and setting the real values.
954void wxWindow::SetConstraintSizes(bool recurse)
955{
956 wxLayoutConstraints *constr = GetConstraints();
957 if (constr && constr->left.GetDone() && constr->right.GetDone() &&
958 constr->width.GetDone() && constr->height.GetDone())
959 {
960 int x = constr->left.GetValue();
961 int y = constr->top.GetValue();
962 int w = constr->width.GetValue();
963 int h = constr->height.GetValue();
964
965 // If we don't want to resize this window, just move it...
966 if ((constr->width.GetRelationship() != wxAsIs) ||
967 (constr->height.GetRelationship() != wxAsIs))
968 {
969 // Calls Layout() recursively. AAAGH. How can we stop that.
970 // Simply take Layout() out of non-top level OnSizes.
971 SizerSetSize(x, y, w, h);
972 }
973 else
974 {
975 SizerMove(x, y);
976 }
977 }
978 else if (constr)
979 {
980 char *windowClass = this->GetClassInfo()->GetClassName();
981
982 wxString winName;
983 if (GetName() == "")
984 winName = "unnamed";
985 else
986 winName = GetName();
987 wxDebugMsg("Constraint(s) not satisfied for window of type %s, name %s:\n", (const char *)windowClass, (const char *)winName);
988 if (!constr->left.GetDone())
989 wxDebugMsg(" unsatisfied 'left' constraint.\n");
990 if (!constr->right.GetDone())
991 wxDebugMsg(" unsatisfied 'right' constraint.\n");
992 if (!constr->width.GetDone())
993 wxDebugMsg(" unsatisfied 'width' constraint.\n");
994 if (!constr->height.GetDone())
995 wxDebugMsg(" unsatisfied 'height' constraint.\n");
996 wxDebugMsg("Please check constraints: try adding AsIs() constraints.\n");
997 }
998
999 if (recurse)
1000 {
1001 wxNode *node = GetChildren().First();
1002 while (node)
1003 {
1004 wxWindow *win = (wxWindow *)node->Data();
1005 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
1006 win->SetConstraintSizes();
1007 node = node->Next();
1008 }
1009 }
1010}
1011
1012// This assumes that all sizers are 'on' the same
1013// window, i.e. the parent of this window.
1014void wxWindow::TransformSizerToActual(int *x, int *y) const
1015{
1016 if (!m_sizerParent || m_sizerParent->IsKindOf(CLASSINFO(wxDialog)) ||
1017 m_sizerParent->IsKindOf(CLASSINFO(wxFrame)) )
1018 return;
1019
1020 int xp, yp;
1021 m_sizerParent->GetPosition(&xp, &yp);
1022 m_sizerParent->TransformSizerToActual(&xp, &yp);
1023 *x += xp;
1024 *y += yp;
1025}
1026
1027void wxWindow::SizerSetSize(int x, int y, int w, int h)
1028{
1029 int xx = x;
1030 int yy = y;
1031 TransformSizerToActual(&xx, &yy);
1032 SetSize(xx, yy, w, h);
1033}
1034
1035void wxWindow::SizerMove(int x, int y)
1036{
1037 int xx = x;
1038 int yy = y;
1039 TransformSizerToActual(&xx, &yy);
1040 Move(xx, yy);
1041}
1042
1043// Only set the size/position of the constraint (if any)
1044void wxWindow::SetSizeConstraint(int x, int y, int w, int h)
1045{
1046 wxLayoutConstraints *constr = GetConstraints();
1047 if (constr)
1048 {
1049 if (x != -1)
1050 {
1051 constr->left.SetValue(x);
1052 constr->left.SetDone(TRUE);
1053 }
1054 if (y != -1)
1055 {
1056 constr->top.SetValue(y);
1057 constr->top.SetDone(TRUE);
1058 }
1059 if (w != -1)
1060 {
1061 constr->width.SetValue(w);
1062 constr->width.SetDone(TRUE);
1063 }
1064 if (h != -1)
1065 {
1066 constr->height.SetValue(h);
1067 constr->height.SetDone(TRUE);
1068 }
1069 }
1070}
1071
1072void wxWindow::MoveConstraint(int x, int y)
1073{
1074 wxLayoutConstraints *constr = GetConstraints();
1075 if (constr)
1076 {
1077 if (x != -1)
1078 {
1079 constr->left.SetValue(x);
1080 constr->left.SetDone(TRUE);
1081 }
1082 if (y != -1)
1083 {
1084 constr->top.SetValue(y);
1085 constr->top.SetDone(TRUE);
1086 }
1087 }
1088}
1089
1090void wxWindow::GetSizeConstraint(int *w, int *h) const
1091{
1092 wxLayoutConstraints *constr = GetConstraints();
1093 if (constr)
1094 {
1095 *w = constr->width.GetValue();
1096 *h = constr->height.GetValue();
1097 }
1098 else
1099 GetSize(w, h);
1100}
1101
1102void wxWindow::GetClientSizeConstraint(int *w, int *h) const
1103{
1104 wxLayoutConstraints *constr = GetConstraints();
1105 if (constr)
1106 {
1107 *w = constr->width.GetValue();
1108 *h = constr->height.GetValue();
1109 }
1110 else
1111 GetClientSize(w, h);
1112}
1113
1114void wxWindow::GetPositionConstraint(int *x, int *y) const
1115{
1116 wxLayoutConstraints *constr = GetConstraints();
1117 if (constr)
1118 {
1119 *x = constr->left.GetValue();
1120 *y = constr->top.GetValue();
1121 }
1122 else
1123 GetPosition(x, y);
1124}
1125
1126bool wxWindow::Close(bool force)
1127{
1128 wxCloseEvent event(wxEVT_CLOSE_WINDOW, m_windowId);
1129 event.SetEventObject(this);
1130#if WXWIN_COMPATIBILITY
1131 event.SetForce(force);
1132#endif
1133 event.SetCanVeto(!force);
1134
1135 return GetEventHandler()->ProcessEvent(event);
1136}
1137
1138wxObject* wxWindow::GetChild(int number) const
1139{
1140 // Return a pointer to the Nth object in the window
1141 wxNode *node = GetChildren().First();
1142 int n = number;
1143 while (node && n--)
1144 node = node->Next() ;
1145 if (node)
1146 {
1147 wxObject *obj = (wxObject *)node->Data();
1148 return(obj) ;
1149 }
1150 else
1151 return NULL ;
1152}
1153
1154void wxWindow::OnDefaultAction(wxControl *initiatingItem)
1155{
1156 // Obsolete function
1157}
1158
1159void wxWindow::Clear()
1160{
1161 wxClientDC dc(this);
1162 wxBrush brush(GetBackgroundColour(), wxSOLID);
1163 dc.SetBackground(brush);
1164 dc.Clear();
1165}
1166
1167// Fits the panel around the items
1168void wxWindow::Fit()
1169{
1170 int maxX = 0;
1171 int maxY = 0;
1172 wxNode *node = GetChildren().First();
1173 while ( node )
1174 {
1175 wxWindow *win = (wxWindow *)node->Data();
1176 int wx, wy, ww, wh;
1177 win->GetPosition(&wx, &wy);
1178 win->GetSize(&ww, &wh);
1179 if ( wx + ww > maxX )
1180 maxX = wx + ww;
1181 if ( wy + wh > maxY )
1182 maxY = wy + wh;
1183
1184 node = node->Next();
1185 }
1186 SetClientSize(maxX + 5, maxY + 5);
1187}
1188
1189void wxWindow::SetValidator(const wxValidator& validator)
1190{
1191 if ( m_windowValidator )
1192 delete m_windowValidator;
1193 m_windowValidator = validator.Clone();
1194
1195 if ( m_windowValidator )
1196 m_windowValidator->SetWindow(this) ;
1197}
1198
1199void wxWindow::SetAcceleratorTable(const wxAcceleratorTable& accel)
1200{
1201 m_acceleratorTable = accel;
1202}
1203
1204// Find a window by id or name
1205wxWindow *wxWindow::FindWindow(long id)
1206{
1207 if ( GetId() == id)
1208 return this;
1209
1210 wxNode *node = GetChildren().First();
1211 while ( node )
1212 {
1213 wxWindow *child = (wxWindow *)node->Data();
1214 wxWindow *found = child->FindWindow(id);
1215 if ( found )
1216 return found;
1217 node = node->Next();
1218 }
1219 return NULL;
1220}
1221
1222wxWindow *wxWindow::FindWindow(const wxString& name)
1223{
1224 if ( GetName() == name)
1225 return this;
1226
1227 wxNode *node = GetChildren().First();
1228 while ( node )
1229 {
1230 wxWindow *child = (wxWindow *)node->Data();
1231 wxWindow *found = child->FindWindow(name);
1232 if ( found )
1233 return found;
1234 node = node->Next();
1235 }
1236 return NULL;
1237}
1238
1239void wxWindow::OnIdle(wxIdleEvent& event)
1240{
1241/* TODO: you may need to do something like this
1242 * if your GUI doesn't generate enter/leave events
1243
1244 // Check if we need to send a LEAVE event
1245 if (m_mouseInWindow)
1246 {
1247 POINT pt;
1248 ::GetCursorPos(&pt);
1249 if (::WindowFromPoint(pt) != (HWND) GetHWND())
1250 {
1251 // Generate a LEAVE event
1252 m_mouseInWindow = FALSE;
1253 MSWOnMouseLeave(pt.x, pt.y, 0);
1254 }
1255 }
1256*/
1257
1258 // This calls the UI-update mechanism (querying windows for
1259 // menu/toolbar/control state information)
1260 UpdateWindowUI();
1261}
1262
1263// Raise the window to the top of the Z order
1264void wxWindow::Raise()
1265{
1266 // TODO
1267}
1268
1269// Lower the window to the bottom of the Z order
1270void wxWindow::Lower()
1271{
1272 // TODO
1273}
1274
1275bool wxWindow::AcceptsFocus() const
1276{
1277 return IsShown() && IsEnabled();
1278}
1279
1280// Update region access
1281wxRegion wxWindow::GetUpdateRegion() const
1282{
1283 return m_updateRegion;
1284}
1285
1286bool wxWindow::IsExposed(int x, int y, int w, int h) const
1287{
1288 return (m_updateRegion.Contains(x, y, w, h) != wxOutRegion);
1289}
1290
1291bool wxWindow::IsExposed(const wxPoint& pt) const
1292{
1293 return (m_updateRegion.Contains(pt) != wxOutRegion);
1294}
1295
1296bool wxWindow::IsExposed(const wxRect& rect) const
1297{
1298 return (m_updateRegion.Contains(rect) != wxOutRegion);
1299}
1300
1301void wxWindow::SetToolTip(const wxString& tooltip)
1302{
1303 // TODO
1304}
1305
1306/*
1307 * Allocates control IDs
1308 */
1309
1310int wxWindow::NewControlId()
1311{
1312 static int s_controlId = 0;
1313 s_controlId ++;
1314 return s_controlId;
1315}
1316
1317