]> git.saurik.com Git - wxWidgets.git/blame - src/common/wincmn.cpp
Add ability to have a wxMenuBar as a common menu
[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
55d99c7a 9// Licence: wxWindows licence
7ec1983b
VZ
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"
1e6feb95 38 #include "wx/control.h"
f03fc89f
VZ
39 #include "wx/checkbox.h"
40 #include "wx/radiobut.h"
106844da 41 #include "wx/statbox.h"
26bf1ce0 42 #include "wx/textctrl.h"
f03fc89f
VZ
43 #include "wx/settings.h"
44 #include "wx/dialog.h"
a02dc3e3 45 #include "wx/msgdlg.h"
a37a5a73 46 #include "wx/statusbr.h"
ed39ff57 47 #include "wx/dcclient.h"
f03fc89f
VZ
48#endif //WX_PRECOMP
49
50#if wxUSE_CONSTRAINTS
51 #include "wx/layout.h"
52#endif // wxUSE_CONSTRAINTS
53
461e93f9
JS
54#include "wx/sizer.h"
55
f03fc89f
VZ
56#if wxUSE_DRAG_AND_DROP
57 #include "wx/dnd.h"
58#endif // wxUSE_DRAG_AND_DROP
59
ed5317e5 60#if wxUSE_ACCESSIBILITY
7de59551 61 #include "wx/access.h"
ed5317e5
JS
62#endif
63
bd83cb56
VZ
64#if wxUSE_HELP
65 #include "wx/cshelp.h"
66#endif // wxUSE_HELP
67
f03fc89f
VZ
68#if wxUSE_TOOLTIPS
69 #include "wx/tooltip.h"
70#endif // wxUSE_TOOLTIPS
71
789295bf
VZ
72#if wxUSE_CARET
73 #include "wx/caret.h"
74#endif // wxUSE_CARET
75
f03fc89f
VZ
76// ----------------------------------------------------------------------------
77// static data
78// ----------------------------------------------------------------------------
79
edd802c6
DW
80#if defined(__WXPM__)
81int wxWindowBase::ms_lastControlId = 2000;
82#else
42e69d6b 83int wxWindowBase::ms_lastControlId = -200;
edd802c6 84#endif
f03fc89f
VZ
85
86IMPLEMENT_ABSTRACT_CLASS(wxWindowBase, wxEvtHandler)
87
88// ----------------------------------------------------------------------------
89// event table
90// ----------------------------------------------------------------------------
91
92BEGIN_EVENT_TABLE(wxWindowBase, wxEvtHandler)
93 EVT_SYS_COLOUR_CHANGED(wxWindowBase::OnSysColourChanged)
94 EVT_INIT_DIALOG(wxWindowBase::OnInitDialog)
a02dc3e3 95 EVT_MIDDLE_DOWN(wxWindowBase::OnMiddleClick)
bd83cb56
VZ
96
97#if wxUSE_HELP
98 EVT_HELP(-1, wxWindowBase::OnHelp)
99#endif // wxUSE_HELP
100
f03fc89f
VZ
101END_EVENT_TABLE()
102
103// ============================================================================
104// implementation of the common functionality of the wxWindow class
105// ============================================================================
106
107// ----------------------------------------------------------------------------
108// initialization
109// ----------------------------------------------------------------------------
110
111// the default initialization
112void wxWindowBase::InitBase()
113{
114 // no window yet, no parent nor children
f03fc89f
VZ
115 m_parent = (wxWindow *)NULL;
116 m_windowId = -1;
117 m_children.DeleteContents( FALSE ); // don't auto delete node data
118
119 // no constraints on the minimal window size
120 m_minWidth =
121 m_minHeight =
122 m_maxWidth =
123 m_maxHeight = -1;
124
125 // window is created enabled but it's not visible yet
126 m_isShown = FALSE;
127 m_isEnabled = TRUE;
128
f03fc89f
VZ
129 // the default event handler is just this window
130 m_eventHandler = this;
131
88ac883a 132#if wxUSE_VALIDATORS
f03fc89f
VZ
133 // no validator
134 m_windowValidator = (wxValidator *) NULL;
88ac883a 135#endif // wxUSE_VALIDATORS
f03fc89f
VZ
136
137 // use the system default colours
a756f210
VS
138 m_backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE);
139 m_foregroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
f6e4e9ea 140
8bf30fe9
VZ
141 // don't set the font here for wxMSW as we don't call WM_SETFONT here and
142 // so the font is *not* really set - but calls to SetFont() later won't do
143 // anything because m_font appears to be already set!
144#ifndef __WXMSW__
a756f210 145 m_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
8bf30fe9 146#endif // __WXMSW__
807a903e 147
08df3e44
VZ
148 // the colours/fonts are default for now
149 m_hasBgCol =
150 m_hasFgCol =
151 m_hasFont = FALSE;
d6091355
JS
152
153 m_isBeingDeleted = FALSE;
08df3e44 154
f03fc89f 155 // no style bits
d80cd92a 156 m_exStyle =
f03fc89f
VZ
157 m_windowStyle = 0;
158
159 // an optimization for the event processing: checking this flag is much
160 // faster than using IsKindOf(CLASSINFO(wxWindow))
161 m_isWindow = TRUE;
162
163#if wxUSE_CONSTRAINTS
164 // no constraints whatsoever
165 m_constraints = (wxLayoutConstraints *) NULL;
166 m_constraintsInvolvedIn = (wxWindowList *) NULL;
461e93f9
JS
167#endif // wxUSE_CONSTRAINTS
168
f03fc89f 169 m_windowSizer = (wxSizer *) NULL;
be90c029 170 m_containingSizer = (wxSizer *) NULL;
f03fc89f 171 m_autoLayout = FALSE;
f03fc89f
VZ
172
173#if wxUSE_DRAG_AND_DROP
174 m_dropTarget = (wxDropTarget *)NULL;
175#endif // wxUSE_DRAG_AND_DROP
176
177#if wxUSE_TOOLTIPS
178 m_tooltip = (wxToolTip *)NULL;
179#endif // wxUSE_TOOLTIPS
789295bf
VZ
180
181#if wxUSE_CARET
182 m_caret = (wxCaret *)NULL;
183#endif // wxUSE_CARET
a2d93e73 184
574c939e 185#if wxUSE_PALETTE
b95edd47 186 m_hasCustomPalette = FALSE;
574c939e
KB
187#endif // wxUSE_PALETTE
188
ed5317e5
JS
189#if wxUSE_ACCESSIBILITY
190 m_accessible = NULL;
191#endif
192
566d84a7 193 m_virtualSize = wxDefaultSize;
1e2a653b
VZ
194
195 m_minVirtualWidth =
196 m_minVirtualHeight =
197 m_maxVirtualWidth =
566d84a7
RL
198 m_maxVirtualHeight = -1;
199
a2d93e73
JS
200 // Whether we're using the current theme for this window (wxGTK only for now)
201 m_themeEnabled = FALSE;
f03fc89f
VZ
202}
203
204// common part of window creation process
205bool wxWindowBase::CreateBase(wxWindowBase *parent,
206 wxWindowID id,
74e3313b
VZ
207 const wxPoint& WXUNUSED(pos),
208 const wxSize& WXUNUSED(size),
f03fc89f 209 long style,
8d99be5f 210 const wxValidator& validator,
f03fc89f
VZ
211 const wxString& name)
212{
213 // m_isWindow is set to TRUE in wxWindowBase::Init() as well as many other
214 // member variables - check that it has been called (will catch the case
215 // when a new ctor is added which doesn't call InitWindow)
223d09f6 216 wxASSERT_MSG( m_isWindow, wxT("Init() must have been called before!") );
f03fc89f 217
106844da
VZ
218#if wxUSE_STATBOX
219 // wxGTK doesn't allow to create controls with static box as the parent so
220 // this will result in a crash when the program is ported to wxGTK so warn
221 // the user about it
222
223 // if you get this assert, the correct solution is to create the controls
224 // as siblings of the static box
225 wxASSERT_MSG( !parent || !wxDynamicCast(parent, wxStaticBox),
226 _T("wxStaticBox can't be used as a window parent!") );
227#endif // wxUSE_STATBOX
228
925f154d
VZ
229 // ids are limited to 16 bits under MSW so if you care about portability,
230 // it's not a good idea to use ids out of this range (and negative ids are
231 // reserved for wxWindows own usage)
232 wxASSERT_MSG( id == wxID_ANY || (id >= 0 && id < 32767),
233 _T("invalid id value") );
234
f03fc89f 235 // generate a new id if the user doesn't care about it
925f154d 236 m_windowId = id == wxID_ANY ? NewControlId() : id;
f03fc89f
VZ
237
238 SetName(name);
239 SetWindowStyleFlag(style);
240 SetParent(parent);
674ac8b9
VZ
241
242#if wxUSE_VALIDATORS
8d99be5f 243 SetValidator(validator);
674ac8b9 244#endif // wxUSE_VALIDATORS
f03fc89f 245
8ae6ce07
VZ
246 // if the parent window has wxWS_EX_VALIDATE_RECURSIVELY set, we want to
247 // have it too - like this it's possible to set it only in the top level
248 // dialog/frame and all children will inherit it by defult
249 if ( parent && (parent->GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) )
250 {
9cb98d89 251 SetExtraStyle(GetExtraStyle() | wxWS_EX_VALIDATE_RECURSIVELY);
8ae6ce07
VZ
252 }
253
f03fc89f
VZ
254 return TRUE;
255}
256
257// ----------------------------------------------------------------------------
258// destruction
259// ----------------------------------------------------------------------------
260
261// common clean up
262wxWindowBase::~wxWindowBase()
263{
349d1942
VS
264 wxASSERT_MSG( GetCapture() != this, wxT("attempt to destroy window with mouse capture") );
265
f03fc89f
VZ
266 // FIXME if these 2 cases result from programming errors in the user code
267 // we should probably assert here instead of silently fixing them
268
269 // Just in case the window has been Closed, but we're then deleting
270 // immediately: don't leave dangling pointers.
271 wxPendingDelete.DeleteObject(this);
272
273 // Just in case we've loaded a top-level window via LoadNativeDialog but
274 // we weren't a dialog class
275 wxTopLevelWindows.DeleteObject(this);
a23fd0e1 276
223d09f6 277 wxASSERT_MSG( GetChildren().GetCount() == 0, wxT("children not destroyed") );
f03fc89f 278
789295bf
VZ
279#if wxUSE_CARET
280 if ( m_caret )
281 delete m_caret;
282#endif // wxUSE_CARET
283
88ac883a 284#if wxUSE_VALIDATORS
f03fc89f
VZ
285 if ( m_windowValidator )
286 delete m_windowValidator;
88ac883a 287#endif // wxUSE_VALIDATORS
f03fc89f 288
f03fc89f
VZ
289#if wxUSE_CONSTRAINTS
290 // Have to delete constraints/sizer FIRST otherwise sizers may try to look
291 // at deleted windows as they delete themselves.
292 DeleteRelatedConstraints();
293
294 if ( m_constraints )
295 {
296 // This removes any dangling pointers to this window in other windows'
297 // constraintsInvolvedIn lists.
298 UnsetConstraints(m_constraints);
299 delete m_constraints;
300 m_constraints = NULL;
301 }
302
461e93f9
JS
303#endif // wxUSE_CONSTRAINTS
304
be90c029 305 if ( m_containingSizer )
12a3f227 306 m_containingSizer->Detach( (wxWindow*)this );
be90c029 307
f03fc89f
VZ
308 if ( m_windowSizer )
309 delete m_windowSizer;
310
f03fc89f
VZ
311#if wxUSE_DRAG_AND_DROP
312 if ( m_dropTarget )
313 delete m_dropTarget;
314#endif // wxUSE_DRAG_AND_DROP
315
316#if wxUSE_TOOLTIPS
317 if ( m_tooltip )
318 delete m_tooltip;
319#endif // wxUSE_TOOLTIPS
b0ee47ff 320
ed5317e5
JS
321#if wxUSE_ACCESSIBILITY
322 if ( m_accessible )
323 delete m_accessible;
324#endif
325
b0ee47ff
VZ
326 // reset the dangling pointer our parent window may keep to us
327 if ( m_parent && m_parent->GetDefaultItem() == this )
328 {
329 m_parent->SetDefaultItem(NULL);
330 }
f03fc89f
VZ
331}
332
333bool wxWindowBase::Destroy()
334{
335 delete this;
336
337 return TRUE;
338}
339
340bool wxWindowBase::Close(bool force)
341{
342 wxCloseEvent event(wxEVT_CLOSE_WINDOW, m_windowId);
343 event.SetEventObject(this);
344#if WXWIN_COMPATIBILITY
345 event.SetForce(force);
346#endif // WXWIN_COMPATIBILITY
347 event.SetCanVeto(!force);
348
349 // return FALSE if window wasn't closed because the application vetoed the
350 // close event
351 return GetEventHandler()->ProcessEvent(event) && !event.GetVeto();
352}
353
354bool wxWindowBase::DestroyChildren()
355{
356 wxWindowList::Node *node;
a23fd0e1 357 for ( ;; )
f03fc89f 358 {
a23fd0e1
VZ
359 // we iterate until the list becomes empty
360 node = GetChildren().GetFirst();
361 if ( !node )
362 break;
363
f03fc89f 364 wxWindow *child = node->GetData();
a23fd0e1 365
223d09f6 366 wxASSERT_MSG( child, wxT("children list contains empty nodes") );
a23fd0e1 367
1a77875b 368 child->Show(FALSE);
eb082a08 369 delete child;
a23fd0e1
VZ
370
371 wxASSERT_MSG( !GetChildren().Find(child),
223d09f6 372 wxT("child didn't remove itself using RemoveChild()") );
f03fc89f
VZ
373 }
374
375 return TRUE;
376}
377
378// ----------------------------------------------------------------------------
f68586e5 379// size/position related methods
f03fc89f
VZ
380// ----------------------------------------------------------------------------
381
382// centre the window with respect to its parent in either (or both) directions
383void wxWindowBase::Centre(int direction)
384{
f6bcfd97
BP
385 // the position/size of the parent window or of the entire screen
386 wxPoint posParent;
f03fc89f
VZ
387 int widthParent, heightParent;
388
f6bcfd97
BP
389 wxWindow *parent = NULL;
390
391 if ( !(direction & wxCENTRE_ON_SCREEN) )
f03fc89f 392 {
f6bcfd97
BP
393 // find the parent to centre this window on: it should be the
394 // immediate parent for the controls but the top level parent for the
395 // top level windows (like dialogs)
396 parent = GetParent();
397 if ( IsTopLevel() )
398 {
399 while ( parent && !parent->IsTopLevel() )
400 {
401 parent = parent->GetParent();
402 }
403 }
404
e28b0102
VZ
405 // there is no wxTopLevelWindow under wxMotif yet
406#ifndef __WXMOTIF__
085ad686
VZ
407 // we shouldn't center the dialog on the iconized window: under
408 // Windows, for example, this places it completely off the screen
409 if ( parent )
410 {
411 wxTopLevelWindow *winTop = wxDynamicCast(parent, wxTopLevelWindow);
412 if ( winTop && winTop->IsIconized() )
413 {
414 parent = NULL;
415 }
416 }
e28b0102 417#endif // __WXMOTIF__
085ad686 418
f6bcfd97
BP
419 // did we find the parent?
420 if ( !parent )
421 {
422 // no other choice
423 direction |= wxCENTRE_ON_SCREEN;
424 }
f03fc89f 425 }
10fcf31a
VZ
426
427 if ( direction & wxCENTRE_ON_SCREEN )
f03fc89f
VZ
428 {
429 // centre with respect to the whole screen
430 wxDisplaySize(&widthParent, &heightParent);
431 }
10fcf31a
VZ
432 else
433 {
f6bcfd97
BP
434 if ( IsTopLevel() )
435 {
436 // centre on the parent
437 parent->GetSize(&widthParent, &heightParent);
438
439 // adjust to the parents position
440 posParent = parent->GetPosition();
441 }
442 else
443 {
444 // centre inside the parents client rectangle
445 parent->GetClientSize(&widthParent, &heightParent);
446 }
10fcf31a 447 }
f03fc89f
VZ
448
449 int width, height;
450 GetSize(&width, &height);
451
c39eda94
VZ
452 int xNew = -1,
453 yNew = -1;
f03fc89f
VZ
454
455 if ( direction & wxHORIZONTAL )
c39eda94 456 xNew = (widthParent - width)/2;
f03fc89f
VZ
457
458 if ( direction & wxVERTICAL )
c39eda94 459 yNew = (heightParent - height)/2;
f03fc89f 460
f6bcfd97
BP
461 xNew += posParent.x;
462 yNew += posParent.y;
7631a292 463
ef397583
GT
464 // Base size of the visible dimensions of the display
465 // to take into account the taskbar
466 wxRect rect = wxGetClientDisplayRect();
467 wxSize size (rect.width,rect.height);
468
ede7020a
VS
469 // NB: in wxMSW, negative position may not neccessary mean "out of screen",
470 // but it may mean that the window is placed on other than the main
471 // display. Therefore we only make sure centered window is on the main display
472 // if the parent is at least partially present here.
473 if (posParent.x + widthParent >= 0) // if parent is (partially) on the main display
ef397583
GT
474 {
475 if (xNew < 0)
476 xNew = 0;
477 else if (xNew+width > size.x)
478 xNew = size.x-width-1;
479 }
ede7020a 480 if (posParent.y + heightParent >= 0) // if parent is (partially) on the main display
ef397583
GT
481 {
482 if (yNew+height > size.y)
483 yNew = size.y-height-1;
484
485 // Make certain that the title bar is initially visible
486 // always, even if this would push the bottom of the
487 // dialog of the visible area of the display
488 if (yNew < 0)
489 yNew = 0;
490 }
491
0fff366e
VZ
492 // move the window to this position (keeping the old size but using
493 // SetSize() and not Move() to allow xNew and/or yNew to be -1)
db89aa76 494 SetSize(xNew, yNew, width, height, wxSIZE_ALLOW_MINUS_ONE);
7631a292
RD
495}
496
f03fc89f
VZ
497// fits the window around the children
498void wxWindowBase::Fit()
499{
f68586e5
VZ
500 if ( GetChildren().GetCount() > 0 )
501 {
ec5bb70d 502 SetClientSize(DoGetBestSize());
f68586e5
VZ
503 }
504 //else: do nothing if we have no children
505}
f03fc89f 506
2b5f62a0
VZ
507// fits virtual size (ie. scrolled area etc.) around children
508void wxWindowBase::FitInside()
509{
510 if ( GetChildren().GetCount() > 0 )
511 {
512 SetVirtualSize( GetBestVirtualSize() );
513 }
514}
515
f68586e5
VZ
516// return the size best suited for the current window
517wxSize wxWindowBase::DoGetBestSize() const
518{
ec5bb70d
VZ
519 if ( m_windowSizer )
520 {
521 return m_windowSizer->GetMinSize();
522 }
523#if wxUSE_CONSTRAINTS
524 else if ( m_constraints )
525 {
526 wxConstCast(this, wxWindowBase)->SatisfyConstraints();
527
528 // our minimal acceptable size is such that all our windows fit inside
529 int maxX = 0,
530 maxY = 0;
531
532 for ( wxWindowList::Node *node = GetChildren().GetFirst();
533 node;
534 node = node->GetNext() )
535 {
536 wxLayoutConstraints *c = node->GetData()->GetConstraints();
537 if ( !c )
538 {
539 // it's not normal that we have an unconstrained child, but
540 // what can we do about it?
541 continue;
542 }
543
544 int x = c->right.GetValue(),
545 y = c->bottom.GetValue();
546
547 if ( x > maxX )
548 maxX = x;
549
550 if ( y > maxY )
551 maxY = y;
552
553 // TODO: we must calculate the overlaps somehow, otherwise we
554 // will never return a size bigger than the current one :-(
555 }
556
557 return wxSize(maxX, maxY);
558 }
559#endif // wxUSE_CONSTRAINTS
560 else if ( GetChildren().GetCount() > 0 )
f03fc89f 561 {
f68586e5
VZ
562 // our minimal acceptable size is such that all our windows fit inside
563 int maxX = 0,
564 maxY = 0;
565
566 for ( wxWindowList::Node *node = GetChildren().GetFirst();
567 node;
568 node = node->GetNext() )
42e69d6b 569 {
f68586e5 570 wxWindow *win = node->GetData();
1e6feb95
VZ
571 if ( win->IsTopLevel()
572#if wxUSE_STATUSBAR
573 || wxDynamicCast(win, wxStatusBar)
574#endif // wxUSE_STATUSBAR
575 )
f68586e5
VZ
576 {
577 // dialogs and frames lie in different top level windows -
7d9fd004
VZ
578 // don't deal with them here; as for the status bars, they
579 // don't lie in the client area at all
f68586e5
VZ
580 continue;
581 }
582
583 int wx, wy, ww, wh;
584 win->GetPosition(&wx, &wy);
3f5513f5
VZ
585
586 // if the window hadn't been positioned yet, assume that it is in
587 // the origin
588 if ( wx == -1 )
589 wx = 0;
590 if ( wy == -1 )
591 wy = 0;
592
f68586e5
VZ
593 win->GetSize(&ww, &wh);
594 if ( wx + ww > maxX )
595 maxX = wx + ww;
596 if ( wy + wh > maxY )
597 maxY = wy + wh;
42e69d6b
VZ
598 }
599
ec5bb70d
VZ
600 // for compatibility with the old versions and because it really looks
601 // slightly more pretty like this, add a pad
602 maxX += 7;
603 maxY += 14;
604
ba81034d 605 return wxSize(maxX, maxY);
f68586e5
VZ
606 }
607 else
608 {
609 // for a generic window there is no natural best size - just use the
610 // current one
611 return GetSize();
f03fc89f 612 }
f03fc89f
VZ
613}
614
1e6feb95
VZ
615// by default the origin is not shifted
616wxPoint wxWindowBase::GetClientAreaOrigin() const
617{
618 return wxPoint(0, 0);
619}
620
f03fc89f 621// set the min/max size of the window
f03fc89f
VZ
622void wxWindowBase::SetSizeHints(int minW, int minH,
623 int maxW, int maxH,
624 int WXUNUSED(incW), int WXUNUSED(incH))
625{
e587e144
VZ
626 // setting min width greater than max width leads to infinite loops under
627 // X11 and generally doesn't make any sense, so don't allow it
628 wxCHECK_RET( (minW == -1 || maxW == -1 || minW <= maxW) &&
77b0d411 629 (minH == -1 || maxH == -1 || minH <= maxH),
e587e144
VZ
630 _T("min width/height must be less than max width/height!") );
631
f03fc89f
VZ
632 m_minWidth = minW;
633 m_maxWidth = maxW;
634 m_minHeight = minH;
635 m_maxHeight = maxH;
636}
637
566d84a7
RL
638void wxWindowBase::SetVirtualSizeHints( int minW, int minH,
639 int maxW, int maxH )
640{
641 m_minVirtualWidth = minW;
642 m_maxVirtualWidth = maxW;
643 m_minVirtualHeight = minH;
644 m_maxVirtualHeight = maxH;
566d84a7
RL
645}
646
647void wxWindowBase::DoSetVirtualSize( int x, int y )
648{
1e2a653b
VZ
649 if ( m_minVirtualWidth != -1 && m_minVirtualWidth > x )
650 x = m_minVirtualWidth;
651 if ( m_maxVirtualWidth != -1 && m_maxVirtualWidth < x )
652 x = m_maxVirtualWidth;
653 if ( m_minVirtualHeight != -1 && m_minVirtualHeight > y )
654 y = m_minVirtualHeight;
655 if ( m_maxVirtualHeight != -1 && m_maxVirtualHeight < y )
656 y = m_maxVirtualHeight;
657
658 m_virtualSize = wxSize(x, y);
566d84a7
RL
659}
660
661wxSize wxWindowBase::DoGetVirtualSize() const
662{
663 wxSize s( GetClientSize() );
664
150c8d89
RL
665 return wxSize( wxMax( m_virtualSize.GetWidth(), s.GetWidth() ),
666 wxMax( m_virtualSize.GetHeight(), s.GetHeight() ) );
566d84a7
RL
667}
668
f03fc89f
VZ
669// ----------------------------------------------------------------------------
670// show/hide/enable/disable the window
671// ----------------------------------------------------------------------------
672
673bool wxWindowBase::Show(bool show)
674{
675 if ( show != m_isShown )
676 {
677 m_isShown = show;
678
679 return TRUE;
680 }
681 else
682 {
683 return FALSE;
684 }
685}
686
687bool wxWindowBase::Enable(bool enable)
688{
689 if ( enable != m_isEnabled )
690 {
691 m_isEnabled = enable;
692
693 return TRUE;
694 }
695 else
696 {
697 return FALSE;
698 }
699}
34636400
VZ
700// ----------------------------------------------------------------------------
701// RTTI
702// ----------------------------------------------------------------------------
703
704bool wxWindowBase::IsTopLevel() const
705{
8487f887 706 return FALSE;
34636400 707}
f03fc89f
VZ
708
709// ----------------------------------------------------------------------------
710// reparenting the window
711// ----------------------------------------------------------------------------
712
713void wxWindowBase::AddChild(wxWindowBase *child)
714{
223d09f6 715 wxCHECK_RET( child, wxT("can't add a NULL child") );
f03fc89f 716
f6bcfd97
BP
717 // this should never happen and it will lead to a crash later if it does
718 // because RemoveChild() will remove only one node from the children list
719 // and the other(s) one(s) will be left with dangling pointers in them
720 wxASSERT_MSG( !GetChildren().Find(child), _T("AddChild() called twice") );
721
f03fc89f
VZ
722 GetChildren().Append(child);
723 child->SetParent(this);
724}
725
726void wxWindowBase::RemoveChild(wxWindowBase *child)
727{
223d09f6 728 wxCHECK_RET( child, wxT("can't remove a NULL child") );
f03fc89f
VZ
729
730 GetChildren().DeleteObject(child);
731 child->SetParent((wxWindow *)NULL);
732}
439b3bf1 733
f03fc89f
VZ
734bool wxWindowBase::Reparent(wxWindowBase *newParent)
735{
736 wxWindow *oldParent = GetParent();
737 if ( newParent == oldParent )
738 {
739 // nothing done
740 return FALSE;
741 }
742
743 // unlink this window from the existing parent.
744 if ( oldParent )
745 {
746 oldParent->RemoveChild(this);
747 }
748 else
749 {
750 wxTopLevelWindows.DeleteObject(this);
751 }
752
753 // add it to the new one
754 if ( newParent )
755 {
756 newParent->AddChild(this);
757 }
758 else
759 {
760 wxTopLevelWindows.Append(this);
761 }
762
763 return TRUE;
764}
765
766// ----------------------------------------------------------------------------
767// event handler stuff
768// ----------------------------------------------------------------------------
769
770void wxWindowBase::PushEventHandler(wxEvtHandler *handler)
771{
3a074ba8
VZ
772 wxEvtHandler *handlerOld = GetEventHandler();
773
774 handler->SetNextHandler(handlerOld);
775
776 if ( handlerOld )
777 GetEventHandler()->SetPreviousHandler(handler);
778
f03fc89f
VZ
779 SetEventHandler(handler);
780}
781
782wxEvtHandler *wxWindowBase::PopEventHandler(bool deleteHandler)
783{
784 wxEvtHandler *handlerA = GetEventHandler();
785 if ( handlerA )
786 {
787 wxEvtHandler *handlerB = handlerA->GetNextHandler();
788 handlerA->SetNextHandler((wxEvtHandler *)NULL);
3a074ba8
VZ
789
790 if ( handlerB )
791 handlerB->SetPreviousHandler((wxEvtHandler *)NULL);
f03fc89f 792 SetEventHandler(handlerB);
3a074ba8 793
f03fc89f
VZ
794 if ( deleteHandler )
795 {
796 delete handlerA;
797 handlerA = (wxEvtHandler *)NULL;
798 }
799 }
800
801 return handlerA;
802}
803
2e36d5cf
VZ
804bool wxWindowBase::RemoveEventHandler(wxEvtHandler *handler)
805{
806 wxCHECK_MSG( handler, FALSE, _T("RemoveEventHandler(NULL) called") );
807
808 wxEvtHandler *handlerPrev = NULL,
809 *handlerCur = GetEventHandler();
810 while ( handlerCur )
811 {
812 wxEvtHandler *handlerNext = handlerCur->GetNextHandler();
813
814 if ( handlerCur == handler )
815 {
816 if ( handlerPrev )
817 {
818 handlerPrev->SetNextHandler(handlerNext);
819 }
820 else
821 {
822 SetEventHandler(handlerNext);
823 }
824
7a9c8d74
JS
825 if ( handlerNext )
826 {
827 handlerNext->SetPreviousHandler ( handlerPrev );
828 }
2e36d5cf
VZ
829 handler->SetNextHandler(NULL);
830
831 return TRUE;
832 }
833
834 handlerPrev = handlerCur;
835 handlerCur = handlerNext;
836 }
837
838 wxFAIL_MSG( _T("where has the event handler gone?") );
839
840 return FALSE;
841}
842
f03fc89f
VZ
843// ----------------------------------------------------------------------------
844// cursors, fonts &c
845// ----------------------------------------------------------------------------
846
847bool wxWindowBase::SetBackgroundColour( const wxColour &colour )
848{
849 if ( !colour.Ok() || (colour == m_backgroundColour) )
850 return FALSE;
851
852 m_backgroundColour = colour;
853
23895080
VZ
854 m_hasBgCol = TRUE;
855
f03fc89f
VZ
856 return TRUE;
857}
858
859bool wxWindowBase::SetForegroundColour( const wxColour &colour )
860{
861 if ( !colour.Ok() || (colour == m_foregroundColour) )
862 return FALSE;
863
864 m_foregroundColour = colour;
865
23895080
VZ
866 m_hasFgCol = TRUE;
867
f03fc89f
VZ
868 return TRUE;
869}
870
871bool wxWindowBase::SetCursor(const wxCursor& cursor)
872{
8a9c2246
VZ
873 // setting an invalid cursor is ok, it means that we don't have any special
874 // cursor
13588544 875 if ( m_cursor == cursor )
f03fc89f
VZ
876 {
877 // no change
878 return FALSE;
879 }
880
8a9c2246 881 m_cursor = cursor;
f03fc89f
VZ
882
883 return TRUE;
884}
885
886bool wxWindowBase::SetFont(const wxFont& font)
887{
888 // don't try to set invalid font, always fall back to the default
889 const wxFont& fontOk = font.Ok() ? font : *wxSWISS_FONT;
890
8bf30fe9 891 if ( fontOk == m_font )
f03fc89f
VZ
892 {
893 // no change
894 return FALSE;
895 }
896
897 m_font = fontOk;
898
23895080
VZ
899 m_hasFont = TRUE;
900
f03fc89f
VZ
901 return TRUE;
902}
903
b95edd47
VZ
904#if wxUSE_PALETTE
905
906void wxWindowBase::SetPalette(const wxPalette& pal)
907{
908 m_hasCustomPalette = TRUE;
909 m_palette = pal;
910
911 // VZ: can anyone explain me what do we do here?
912 wxWindowDC d((wxWindow *) this);
913 d.SetPalette(pal);
914}
915
916wxWindow *wxWindowBase::GetAncestorWithCustomPalette() const
917{
918 wxWindow *win = (wxWindow *)this;
919 while ( win && !win->HasCustomPalette() )
920 {
921 win = win->GetParent();
922 }
923
924 return win;
925}
926
927#endif // wxUSE_PALETTE
928
789295bf
VZ
929#if wxUSE_CARET
930void wxWindowBase::SetCaret(wxCaret *caret)
931{
932 if ( m_caret )
933 {
934 delete m_caret;
935 }
936
937 m_caret = caret;
938
939 if ( m_caret )
940 {
941 wxASSERT_MSG( m_caret->GetWindow() == this,
223d09f6 942 wxT("caret should be created associated to this window") );
789295bf
VZ
943 }
944}
945#endif // wxUSE_CARET
946
88ac883a 947#if wxUSE_VALIDATORS
f03fc89f
VZ
948// ----------------------------------------------------------------------------
949// validators
950// ----------------------------------------------------------------------------
951
952void wxWindowBase::SetValidator(const wxValidator& validator)
953{
954 if ( m_windowValidator )
955 delete m_windowValidator;
956
957 m_windowValidator = (wxValidator *)validator.Clone();
958
959 if ( m_windowValidator )
960 m_windowValidator->SetWindow(this) ;
961}
88ac883a 962#endif // wxUSE_VALIDATORS
f03fc89f
VZ
963
964// ----------------------------------------------------------------------------
1e6feb95 965// update region stuff
f03fc89f
VZ
966// ----------------------------------------------------------------------------
967
1e6feb95
VZ
968wxRect wxWindowBase::GetUpdateClientRect() const
969{
970 wxRegion rgnUpdate = GetUpdateRegion();
971 rgnUpdate.Intersect(GetClientRect());
972 wxRect rectUpdate = rgnUpdate.GetBox();
973 wxPoint ptOrigin = GetClientAreaOrigin();
974 rectUpdate.x -= ptOrigin.x;
975 rectUpdate.y -= ptOrigin.y;
976
977 return rectUpdate;
978}
979
f03fc89f
VZ
980bool wxWindowBase::IsExposed(int x, int y) const
981{
982 return m_updateRegion.Contains(x, y) != wxOutRegion;
983}
984
985bool wxWindowBase::IsExposed(int x, int y, int w, int h) const
986{
987 return m_updateRegion.Contains(x, y, w, h) != wxOutRegion;
988}
989
990// ----------------------------------------------------------------------------
146ba0fe 991// find child window by id or name
f03fc89f
VZ
992// ----------------------------------------------------------------------------
993
994wxWindow *wxWindowBase::FindWindow( long id )
995{
996 if ( id == m_windowId )
997 return (wxWindow *)this;
998
999 wxWindowBase *res = (wxWindow *)NULL;
1000 wxWindowList::Node *node;
1001 for ( node = m_children.GetFirst(); node && !res; node = node->GetNext() )
1002 {
1003 wxWindowBase *child = node->GetData();
1004 res = child->FindWindow( id );
1005 }
1006
1007 return (wxWindow *)res;
1008}
1009
1010wxWindow *wxWindowBase::FindWindow( const wxString& name )
1011{
1012 if ( name == m_windowName )
1013 return (wxWindow *)this;
1014
1015 wxWindowBase *res = (wxWindow *)NULL;
1016 wxWindowList::Node *node;
1017 for ( node = m_children.GetFirst(); node && !res; node = node->GetNext() )
1018 {
1019 wxWindow *child = node->GetData();
1020 res = child->FindWindow(name);
1021 }
1022
1023 return (wxWindow *)res;
1024}
1025
146ba0fe
VZ
1026
1027// find any window by id or name or label: If parent is non-NULL, look through
1028// children for a label or title matching the specified string. If NULL, look
1029// through all top-level windows.
1030//
1031// to avoid duplicating code we reuse the same helper function but with
1032// different comparators
1033
1034typedef bool (*wxFindWindowCmp)(const wxWindow *win,
1035 const wxString& label, long id);
1036
1037static
1038bool wxFindWindowCmpLabels(const wxWindow *win, const wxString& label,
1039 long WXUNUSED(id))
1040{
1041 return win->GetLabel() == label;
1042}
1043
1044static
1045bool wxFindWindowCmpNames(const wxWindow *win, const wxString& label,
1046 long WXUNUSED(id))
1047{
1048 return win->GetName() == label;
1049}
1050
1051static
1052bool wxFindWindowCmpIds(const wxWindow *win, const wxString& WXUNUSED(label),
1053 long id)
1054{
1055 return win->GetId() == id;
1056}
1057
1058// recursive helper for the FindWindowByXXX() functions
1059static
1060wxWindow *wxFindWindowRecursively(const wxWindow *parent,
1061 const wxString& label,
1062 long id,
1063 wxFindWindowCmp cmp)
1064{
1065 if ( parent )
1066 {
1067 // see if this is the one we're looking for
1068 if ( (*cmp)(parent, label, id) )
1069 return (wxWindow *)parent;
1070
1071 // It wasn't, so check all its children
1072 for ( wxWindowList::Node * node = parent->GetChildren().GetFirst();
1073 node;
1074 node = node->GetNext() )
1075 {
1076 // recursively check each child
1077 wxWindow *win = (wxWindow *)node->GetData();
1078 wxWindow *retwin = wxFindWindowRecursively(win, label, id, cmp);
1079 if (retwin)
1080 return retwin;
1081 }
1082 }
1083
1084 // Not found
1085 return NULL;
1086}
1087
1088// helper for FindWindowByXXX()
1089static
1090wxWindow *wxFindWindowHelper(const wxWindow *parent,
1091 const wxString& label,
1092 long id,
1093 wxFindWindowCmp cmp)
1094{
1095 if ( parent )
1096 {
1097 // just check parent and all its children
1098 return wxFindWindowRecursively(parent, label, id, cmp);
1099 }
1100
1101 // start at very top of wx's windows
1102 for ( wxWindowList::Node * node = wxTopLevelWindows.GetFirst();
1103 node;
1104 node = node->GetNext() )
1105 {
1106 // recursively check each window & its children
1107 wxWindow *win = node->GetData();
1108 wxWindow *retwin = wxFindWindowRecursively(win, label, id, cmp);
1109 if (retwin)
1110 return retwin;
1111 }
1112
1113 return NULL;
1114}
1115
1116/* static */
1117wxWindow *
1118wxWindowBase::FindWindowByLabel(const wxString& title, const wxWindow *parent)
1119{
1120 return wxFindWindowHelper(parent, title, 0, wxFindWindowCmpLabels);
1121}
1122
1123/* static */
1124wxWindow *
1125wxWindowBase::FindWindowByName(const wxString& title, const wxWindow *parent)
1126{
1127 wxWindow *win = wxFindWindowHelper(parent, title, 0, wxFindWindowCmpNames);
1128
1129 if ( !win )
1130 {
1131 // fall back to the label
1132 win = FindWindowByLabel(title, parent);
1133 }
1134
1135 return win;
1136}
1137
1138/* static */
1139wxWindow *
1140wxWindowBase::FindWindowById( long id, const wxWindow* parent )
1141{
1142 return wxFindWindowHelper(parent, _T(""), id, wxFindWindowCmpIds);
1143}
1144
f03fc89f
VZ
1145// ----------------------------------------------------------------------------
1146// dialog oriented functions
1147// ----------------------------------------------------------------------------
1148
34636400 1149void wxWindowBase::MakeModal(bool modal)
f03fc89f 1150{
34636400
VZ
1151 // Disable all other windows
1152 if ( IsTopLevel() )
1153 {
1154 wxWindowList::Node *node = wxTopLevelWindows.GetFirst();
1155 while (node)
1156 {
1157 wxWindow *win = node->GetData();
1158 if (win != this)
1159 win->Enable(!modal);
1160
1161 node = node->GetNext();
1162 }
1163 }
f03fc89f
VZ
1164}
1165
1166bool wxWindowBase::Validate()
1167{
88ac883a 1168#if wxUSE_VALIDATORS
d80cd92a
VZ
1169 bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0;
1170
f03fc89f
VZ
1171 wxWindowList::Node *node;
1172 for ( node = m_children.GetFirst(); node; node = node->GetNext() )
1173 {
1174 wxWindowBase *child = node->GetData();
1175 wxValidator *validator = child->GetValidator();
dcd6b914 1176 if ( validator && !validator->Validate((wxWindow *)this) )
f03fc89f
VZ
1177 {
1178 return FALSE;
1179 }
d80cd92a
VZ
1180
1181 if ( recurse && !child->Validate() )
1182 {
1183 return FALSE;
1184 }
f03fc89f 1185 }
88ac883a 1186#endif // wxUSE_VALIDATORS
f03fc89f
VZ
1187
1188 return TRUE;
1189}
1190
1191bool wxWindowBase::TransferDataToWindow()
1192{
88ac883a 1193#if wxUSE_VALIDATORS
d80cd92a
VZ
1194 bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0;
1195
f03fc89f
VZ
1196 wxWindowList::Node *node;
1197 for ( node = m_children.GetFirst(); node; node = node->GetNext() )
1198 {
1199 wxWindowBase *child = node->GetData();
1200 wxValidator *validator = child->GetValidator();
1201 if ( validator && !validator->TransferToWindow() )
1202 {
d80cd92a 1203 wxLogWarning(_("Could not transfer data to window"));
e30285ab 1204#if wxUSE_LOG
d80cd92a 1205 wxLog::FlushActive();
e30285ab 1206#endif // wxUSE_LOG
f03fc89f
VZ
1207
1208 return FALSE;
1209 }
d80cd92a
VZ
1210
1211 if ( recurse )
1212 {
a58a12e9 1213 if ( !child->TransferDataToWindow() )
d80cd92a
VZ
1214 {
1215 // warning already given
1216 return FALSE;
1217 }
1218 }
f03fc89f 1219 }
88ac883a 1220#endif // wxUSE_VALIDATORS
f03fc89f
VZ
1221
1222 return TRUE;
1223}
1224
1225bool wxWindowBase::TransferDataFromWindow()
1226{
88ac883a 1227#if wxUSE_VALIDATORS
d80cd92a
VZ
1228 bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0;
1229
f03fc89f
VZ
1230 wxWindowList::Node *node;
1231 for ( node = m_children.GetFirst(); node; node = node->GetNext() )
1232 {
1233 wxWindow *child = node->GetData();
d80cd92a
VZ
1234 wxValidator *validator = child->GetValidator();
1235 if ( validator && !validator->TransferFromWindow() )
f03fc89f 1236 {
d80cd92a
VZ
1237 // nop warning here because the application is supposed to give
1238 // one itself - we don't know here what might have gone wrongly
1239
f03fc89f
VZ
1240 return FALSE;
1241 }
d80cd92a
VZ
1242
1243 if ( recurse )
1244 {
a58a12e9 1245 if ( !child->TransferDataFromWindow() )
d80cd92a
VZ
1246 {
1247 // warning already given
1248 return FALSE;
1249 }
1250 }
f03fc89f 1251 }
88ac883a 1252#endif // wxUSE_VALIDATORS
f03fc89f
VZ
1253
1254 return TRUE;
1255}
1256
1257void wxWindowBase::InitDialog()
1258{
1259 wxInitDialogEvent event(GetId());
1260 event.SetEventObject( this );
1261 GetEventHandler()->ProcessEvent(event);
1262}
1263
1264// ----------------------------------------------------------------------------
bd83cb56
VZ
1265// context-sensitive help support
1266// ----------------------------------------------------------------------------
1267
1268#if wxUSE_HELP
1269
1270// associate this help text with this window
1271void wxWindowBase::SetHelpText(const wxString& text)
1272{
1273 wxHelpProvider *helpProvider = wxHelpProvider::Get();
1274 if ( helpProvider )
1275 {
1276 helpProvider->AddHelp(this, text);
1277 }
1278}
1279
1280// associate this help text with all windows with the same id as this
1281// one
1282void wxWindowBase::SetHelpTextForId(const wxString& text)
1283{
1284 wxHelpProvider *helpProvider = wxHelpProvider::Get();
1285 if ( helpProvider )
1286 {
1287 helpProvider->AddHelp(GetId(), text);
1288 }
1289}
1290
1291// get the help string associated with this window (may be empty)
1292wxString wxWindowBase::GetHelpText() const
1293{
1294 wxString text;
1295 wxHelpProvider *helpProvider = wxHelpProvider::Get();
1296 if ( helpProvider )
1297 {
1298 text = helpProvider->GetHelp(this);
1299 }
1300
1301 return text;
1302}
1303
1304// show help for this window
1305void wxWindowBase::OnHelp(wxHelpEvent& event)
1306{
1307 wxHelpProvider *helpProvider = wxHelpProvider::Get();
1308 if ( helpProvider )
1309 {
1310 if ( helpProvider->ShowHelp(this) )
1311 {
1312 // skip the event.Skip() below
1313 return;
1314 }
1315 }
1316
1317 event.Skip();
1318}
1319
1320#endif // wxUSE_HELP
1321
1322// ----------------------------------------------------------------------------
574c939e 1323// tooltipsroot.Replace("\\", "/");
f03fc89f
VZ
1324// ----------------------------------------------------------------------------
1325
1326#if wxUSE_TOOLTIPS
1327
1328void wxWindowBase::SetToolTip( const wxString &tip )
1329{
1330 // don't create the new tooltip if we already have one
1331 if ( m_tooltip )
1332 {
1333 m_tooltip->SetTip( tip );
1334 }
1335 else
1336 {
1337 SetToolTip( new wxToolTip( tip ) );
1338 }
1339
1340 // setting empty tooltip text does not remove the tooltip any more - use
1341 // SetToolTip((wxToolTip *)NULL) for this
1342}
1343
1344void wxWindowBase::DoSetToolTip(wxToolTip *tooltip)
1345{
1346 if ( m_tooltip )
1347 delete m_tooltip;
1348
1349 m_tooltip = tooltip;
1350}
1351
1352#endif // wxUSE_TOOLTIPS
1353
1354// ----------------------------------------------------------------------------
1355// constraints and sizers
1356// ----------------------------------------------------------------------------
1357
1358#if wxUSE_CONSTRAINTS
1359
1360void wxWindowBase::SetConstraints( wxLayoutConstraints *constraints )
1361{
1362 if ( m_constraints )
1363 {
1364 UnsetConstraints(m_constraints);
1365 delete m_constraints;
1366 }
1367 m_constraints = constraints;
1368 if ( m_constraints )
1369 {
1370 // Make sure other windows know they're part of a 'meaningful relationship'
1371 if ( m_constraints->left.GetOtherWindow() && (m_constraints->left.GetOtherWindow() != this) )
1372 m_constraints->left.GetOtherWindow()->AddConstraintReference(this);
1373 if ( m_constraints->top.GetOtherWindow() && (m_constraints->top.GetOtherWindow() != this) )
1374 m_constraints->top.GetOtherWindow()->AddConstraintReference(this);
1375 if ( m_constraints->right.GetOtherWindow() && (m_constraints->right.GetOtherWindow() != this) )
1376 m_constraints->right.GetOtherWindow()->AddConstraintReference(this);
1377 if ( m_constraints->bottom.GetOtherWindow() && (m_constraints->bottom.GetOtherWindow() != this) )
1378 m_constraints->bottom.GetOtherWindow()->AddConstraintReference(this);
1379 if ( m_constraints->width.GetOtherWindow() && (m_constraints->width.GetOtherWindow() != this) )
1380 m_constraints->width.GetOtherWindow()->AddConstraintReference(this);
1381 if ( m_constraints->height.GetOtherWindow() && (m_constraints->height.GetOtherWindow() != this) )
1382 m_constraints->height.GetOtherWindow()->AddConstraintReference(this);
1383 if ( m_constraints->centreX.GetOtherWindow() && (m_constraints->centreX.GetOtherWindow() != this) )
1384 m_constraints->centreX.GetOtherWindow()->AddConstraintReference(this);
1385 if ( m_constraints->centreY.GetOtherWindow() && (m_constraints->centreY.GetOtherWindow() != this) )
1386 m_constraints->centreY.GetOtherWindow()->AddConstraintReference(this);
1387 }
1388}
1389
1390// This removes any dangling pointers to this window in other windows'
1391// constraintsInvolvedIn lists.
1392void wxWindowBase::UnsetConstraints(wxLayoutConstraints *c)
1393{
1394 if ( c )
1395 {
1396 if ( c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this) )
1397 c->left.GetOtherWindow()->RemoveConstraintReference(this);
1398 if ( c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this) )
1399 c->top.GetOtherWindow()->RemoveConstraintReference(this);
1400 if ( c->right.GetOtherWindow() && (c->right.GetOtherWindow() != this) )
1401 c->right.GetOtherWindow()->RemoveConstraintReference(this);
1402 if ( c->bottom.GetOtherWindow() && (c->bottom.GetOtherWindow() != this) )
1403 c->bottom.GetOtherWindow()->RemoveConstraintReference(this);
1404 if ( c->width.GetOtherWindow() && (c->width.GetOtherWindow() != this) )
1405 c->width.GetOtherWindow()->RemoveConstraintReference(this);
1406 if ( c->height.GetOtherWindow() && (c->height.GetOtherWindow() != this) )
1407 c->height.GetOtherWindow()->RemoveConstraintReference(this);
1408 if ( c->centreX.GetOtherWindow() && (c->centreX.GetOtherWindow() != this) )
1409 c->centreX.GetOtherWindow()->RemoveConstraintReference(this);
1410 if ( c->centreY.GetOtherWindow() && (c->centreY.GetOtherWindow() != this) )
1411 c->centreY.GetOtherWindow()->RemoveConstraintReference(this);
1412 }
1413}
1414
1415// Back-pointer to other windows we're involved with, so if we delete this
1416// window, we must delete any constraints we're involved with.
1417void wxWindowBase::AddConstraintReference(wxWindowBase *otherWin)
1418{
1419 if ( !m_constraintsInvolvedIn )
1420 m_constraintsInvolvedIn = new wxWindowList;
1421 if ( !m_constraintsInvolvedIn->Find(otherWin) )
1422 m_constraintsInvolvedIn->Append(otherWin);
1423}
1424
1425// REMOVE back-pointer to other windows we're involved with.
1426void wxWindowBase::RemoveConstraintReference(wxWindowBase *otherWin)
1427{
1428 if ( m_constraintsInvolvedIn )
1429 m_constraintsInvolvedIn->DeleteObject(otherWin);
1430}
1431
1432// Reset any constraints that mention this window
1433void wxWindowBase::DeleteRelatedConstraints()
1434{
1435 if ( m_constraintsInvolvedIn )
1436 {
1437 wxWindowList::Node *node = m_constraintsInvolvedIn->GetFirst();
1438 while (node)
1439 {
1440 wxWindow *win = node->GetData();
1441 wxLayoutConstraints *constr = win->GetConstraints();
1442
1443 // Reset any constraints involving this window
1444 if ( constr )
1445 {
1446 constr->left.ResetIfWin(this);
1447 constr->top.ResetIfWin(this);
1448 constr->right.ResetIfWin(this);
1449 constr->bottom.ResetIfWin(this);
1450 constr->width.ResetIfWin(this);
1451 constr->height.ResetIfWin(this);
1452 constr->centreX.ResetIfWin(this);
1453 constr->centreY.ResetIfWin(this);
1454 }
1455
1456 wxWindowList::Node *next = node->GetNext();
1457 delete node;
1458 node = next;
1459 }
1460
1461 delete m_constraintsInvolvedIn;
1462 m_constraintsInvolvedIn = (wxWindowList *) NULL;
1463 }
1464}
ec5bb70d
VZ
1465
1466#endif // wxUSE_CONSTRAINTS
f03fc89f 1467
3aa5d532 1468void wxWindowBase::SetSizer(wxSizer *sizer, bool deleteOld)
f03fc89f 1469{
ec5bb70d
VZ
1470 if ( deleteOld )
1471 delete m_windowSizer;
3417c2cd 1472
f03fc89f 1473 m_windowSizer = sizer;
566d84a7 1474
ec5bb70d 1475 SetAutoLayout( sizer != NULL );
566d84a7
RL
1476}
1477
1478void wxWindowBase::SetSizerAndFit(wxSizer *sizer, bool deleteOld)
1479{
1480 SetSizer( sizer, deleteOld );
1481 sizer->SetSizeHints( (wxWindow*) this );
f03fc89f
VZ
1482}
1483
ec5bb70d
VZ
1484#if wxUSE_CONSTRAINTS
1485
1486void wxWindowBase::SatisfyConstraints()
1487{
1488 wxLayoutConstraints *constr = GetConstraints();
1489 bool wasOk = constr && constr->AreSatisfied();
1490
1491 ResetConstraints(); // Mark all constraints as unevaluated
1492
1493 int noChanges = 1;
1494
1495 // if we're a top level panel (i.e. our parent is frame/dialog), our
1496 // own constraints will never be satisfied any more unless we do it
1497 // here
1498 if ( wasOk )
1499 {
1500 while ( noChanges > 0 )
1501 {
1502 LayoutPhase1(&noChanges);
1503 }
1504 }
1505
1506 LayoutPhase2(&noChanges);
1507}
1508
1509#endif // wxUSE_CONSTRAINTS
1510
f03fc89f
VZ
1511bool wxWindowBase::Layout()
1512{
3417c2cd 1513 // If there is a sizer, use it instead of the constraints
f03fc89f
VZ
1514 if ( GetSizer() )
1515 {
f1df0927 1516 int w, h;
566d84a7 1517 GetVirtualSize(&w, &h);
3417c2cd 1518 GetSizer()->SetDimension( 0, 0, w, h );
f03fc89f 1519 }
461e93f9 1520#if wxUSE_CONSTRAINTS
f1df0927 1521 else
f03fc89f 1522 {
ec5bb70d 1523 SatisfyConstraints(); // Find the right constraints values
f1df0927 1524 SetConstraintSizes(); // Recursively set the real window sizes
f03fc89f 1525 }
461e93f9 1526#endif
5d4b632b 1527
f03fc89f
VZ
1528 return TRUE;
1529}
1530
461e93f9 1531#if wxUSE_CONSTRAINTS
ec5bb70d
VZ
1532
1533// first phase of the constraints evaluation: set our own constraints
f03fc89f
VZ
1534bool wxWindowBase::LayoutPhase1(int *noChanges)
1535{
1536 wxLayoutConstraints *constr = GetConstraints();
ec5bb70d
VZ
1537
1538 return !constr || constr->SatisfyConstraints(this, noChanges);
f03fc89f
VZ
1539}
1540
ec5bb70d 1541// second phase: set the constraints for our children
f03fc89f
VZ
1542bool wxWindowBase::LayoutPhase2(int *noChanges)
1543{
1544 *noChanges = 0;
1545
1546 // Layout children
1547 DoPhase(1);
ec5bb70d
VZ
1548
1549 // Layout grand children
f03fc89f 1550 DoPhase(2);
ec5bb70d 1551
f03fc89f
VZ
1552 return TRUE;
1553}
1554
1555// Do a phase of evaluating child constraints
1556bool wxWindowBase::DoPhase(int phase)
1557{
ec5bb70d
VZ
1558 // the list containing the children for which the constraints are already
1559 // set correctly
f03fc89f 1560 wxWindowList succeeded;
ec5bb70d
VZ
1561
1562 // the max number of iterations we loop before concluding that we can't set
1563 // the constraints
1564 static const int maxIterations = 500;
1565
1566 for ( int noIterations = 0; noIterations < maxIterations; noIterations++ )
f03fc89f 1567 {
ec5bb70d
VZ
1568 int noChanges = 0;
1569
1570 // loop over all children setting their constraints
1571 for ( wxWindowList::Node *node = GetChildren().GetFirst();
1572 node;
1573 node = node->GetNext() )
f03fc89f
VZ
1574 {
1575 wxWindow *child = node->GetData();
ec5bb70d 1576 if ( child->IsTopLevel() )
f03fc89f 1577 {
ec5bb70d
VZ
1578 // top level children are not inside our client area
1579 continue;
1580 }
1581
1582 if ( !child->GetConstraints() || succeeded.Find(child) )
1583 {
1584 // this one is either already ok or nothing we can do about it
1585 continue;
1586 }
1587
1588 int tempNoChanges = 0;
1589 bool success = phase == 1 ? child->LayoutPhase1(&tempNoChanges)
1590 : child->LayoutPhase2(&tempNoChanges);
1591 noChanges += tempNoChanges;
1592
1593 if ( success )
1594 {
1595 succeeded.Append(child);
f03fc89f 1596 }
f03fc89f
VZ
1597 }
1598
ec5bb70d
VZ
1599 if ( !noChanges )
1600 {
1601 // constraints are set
1602 break;
1603 }
f03fc89f
VZ
1604 }
1605
1606 return TRUE;
1607}
1608
1609void wxWindowBase::ResetConstraints()
1610{
1611 wxLayoutConstraints *constr = GetConstraints();
1612 if ( constr )
1613 {
1614 constr->left.SetDone(FALSE);
1615 constr->top.SetDone(FALSE);
1616 constr->right.SetDone(FALSE);
1617 constr->bottom.SetDone(FALSE);
1618 constr->width.SetDone(FALSE);
1619 constr->height.SetDone(FALSE);
1620 constr->centreX.SetDone(FALSE);
1621 constr->centreY.SetDone(FALSE);
1622 }
f1df0927 1623
f03fc89f
VZ
1624 wxWindowList::Node *node = GetChildren().GetFirst();
1625 while (node)
1626 {
1627 wxWindow *win = node->GetData();
34636400 1628 if ( !win->IsTopLevel() )
f03fc89f
VZ
1629 win->ResetConstraints();
1630 node = node->GetNext();
1631 }
1632}
1633
1634// Need to distinguish between setting the 'fake' size for windows and sizers,
1635// and setting the real values.
1636void wxWindowBase::SetConstraintSizes(bool recurse)
1637{
1638 wxLayoutConstraints *constr = GetConstraints();
4b7f2165 1639 if ( constr && constr->AreSatisfied() )
f03fc89f
VZ
1640 {
1641 int x = constr->left.GetValue();
1642 int y = constr->top.GetValue();
1643 int w = constr->width.GetValue();
1644 int h = constr->height.GetValue();
1645
f03fc89f 1646 if ( (constr->width.GetRelationship() != wxAsIs ) ||
3417c2cd 1647 (constr->height.GetRelationship() != wxAsIs) )
f03fc89f 1648 {
3417c2cd 1649 SetSize(x, y, w, h);
f03fc89f
VZ
1650 }
1651 else
1652 {
3417c2cd
RR
1653 // If we don't want to resize this window, just move it...
1654 Move(x, y);
f03fc89f
VZ
1655 }
1656 }
1657 else if ( constr )
1658 {
4b7f2165 1659 wxLogDebug(wxT("Constraints not satisfied for %s named '%s'."),
f1df0927 1660 GetClassInfo()->GetClassName(),
4b7f2165 1661 GetName().c_str());
f03fc89f
VZ
1662 }
1663
1664 if ( recurse )
1665 {
1666 wxWindowList::Node *node = GetChildren().GetFirst();
1667 while (node)
1668 {
1669 wxWindow *win = node->GetData();
e2f9212c 1670 if ( !win->IsTopLevel() && win->GetConstraints() )
f03fc89f
VZ
1671 win->SetConstraintSizes();
1672 node = node->GetNext();
1673 }
1674 }
1675}
1676
f03fc89f
VZ
1677// Only set the size/position of the constraint (if any)
1678void wxWindowBase::SetSizeConstraint(int x, int y, int w, int h)
1679{
1680 wxLayoutConstraints *constr = GetConstraints();
1681 if ( constr )
1682 {
1683 if ( x != -1 )
1684 {
1685 constr->left.SetValue(x);
1686 constr->left.SetDone(TRUE);
1687 }
1688 if ( y != -1 )
1689 {
1690 constr->top.SetValue(y);
1691 constr->top.SetDone(TRUE);
1692 }
1693 if ( w != -1 )
1694 {
1695 constr->width.SetValue(w);
1696 constr->width.SetDone(TRUE);
1697 }
1698 if ( h != -1 )
1699 {
1700 constr->height.SetValue(h);
1701 constr->height.SetDone(TRUE);
1702 }
1703 }
1704}
1705
1706void wxWindowBase::MoveConstraint(int x, int y)
1707{
1708 wxLayoutConstraints *constr = GetConstraints();
1709 if ( constr )
1710 {
1711 if ( x != -1 )
1712 {
1713 constr->left.SetValue(x);
1714 constr->left.SetDone(TRUE);
1715 }
1716 if ( y != -1 )
1717 {
1718 constr->top.SetValue(y);
1719 constr->top.SetDone(TRUE);
1720 }
1721 }
1722}
1723
1724void wxWindowBase::GetSizeConstraint(int *w, int *h) const
1725{
1726 wxLayoutConstraints *constr = GetConstraints();
1727 if ( constr )
1728 {
1729 *w = constr->width.GetValue();
1730 *h = constr->height.GetValue();
1731 }
1732 else
1733 GetSize(w, h);
1734}
1735
1736void wxWindowBase::GetClientSizeConstraint(int *w, int *h) const
1737{
1738 wxLayoutConstraints *constr = GetConstraints();
1739 if ( constr )
1740 {
1741 *w = constr->width.GetValue();
1742 *h = constr->height.GetValue();
1743 }
1744 else
1745 GetClientSize(w, h);
1746}
1747
461e93f9
JS
1748void wxWindowBase::GetPositionConstraint(int *x, int *y) const
1749{
1750 wxLayoutConstraints *constr = GetConstraints();
1751 if ( constr )
1752 {
1753 *x = constr->left.GetValue();
1754 *y = constr->top.GetValue();
1755 }
1756 else
1757 GetPosition(x, y);
1758}
1759
1760#endif // wxUSE_CONSTRAINTS
1761
20a1eea1 1762void wxWindowBase::AdjustForParentClientOrigin(int& x, int& y, int sizeFlags) const
a200c35e
VS
1763{
1764 // don't do it for the dialogs/frames - they float independently of their
1765 // parent
1766 if ( !IsTopLevel() )
1767 {
1768 wxWindow *parent = GetParent();
1769 if ( !(sizeFlags & wxSIZE_NO_ADJUSTMENTS) && parent )
1770 {
1771 wxPoint pt(parent->GetClientAreaOrigin());
1772 x += pt.x;
1773 y += pt.y;
1774 }
1775 }
1776}
1777
f03fc89f
VZ
1778// ----------------------------------------------------------------------------
1779// do Update UI processing for child controls
1780// ----------------------------------------------------------------------------
7ec1983b
VZ
1781
1782// TODO: should this be implemented for the child window rather
1783// than the parent? Then you can override it e.g. for wxCheckBox
1784// to do the Right Thing rather than having to assume a fixed number
1785// of control classes.
f03fc89f 1786void wxWindowBase::UpdateWindowUI()
7ec1983b 1787{
1e6feb95 1788#if wxUSE_CONTROLS
26bf1ce0
VZ
1789 wxUpdateUIEvent event(GetId());
1790 event.m_eventObject = this;
1791
1792 if ( GetEventHandler()->ProcessEvent(event) )
7ec1983b 1793 {
26bf1ce0
VZ
1794 if ( event.GetSetEnabled() )
1795 Enable(event.GetEnabled());
7ec1983b 1796
26bf1ce0 1797 if ( event.GetSetText() )
f03fc89f 1798 {
f7637829 1799 wxControl *control = wxDynamicCastThis(wxControl);
26bf1ce0 1800 if ( control )
34636400 1801 {
1e6feb95 1802#if wxUSE_TEXTCTRL
26bf1ce0
VZ
1803 wxTextCtrl *text = wxDynamicCast(control, wxTextCtrl);
1804 if ( text )
2b5f62a0
VZ
1805 {
1806 if ( event.GetText() != text->GetValue() )
1807 text->SetValue(event.GetText());
1808 }
26bf1ce0 1809 else
1e6feb95 1810#endif // wxUSE_TEXTCTRL
2b5f62a0
VZ
1811 {
1812 if ( event.GetText() != control->GetLabel() )
1813 control->SetLabel(event.GetText());
1814 }
34636400 1815 }
26bf1ce0 1816 }
f03fc89f 1817
88ac883a 1818#if wxUSE_CHECKBOX
f7637829 1819 wxCheckBox *checkbox = wxDynamicCastThis(wxCheckBox);
26bf1ce0
VZ
1820 if ( checkbox )
1821 {
1822 if ( event.GetSetChecked() )
1823 checkbox->SetValue(event.GetChecked());
1824 }
88ac883a
VZ
1825#endif // wxUSE_CHECKBOX
1826
b3402d0d 1827#if wxUSE_RADIOBTN
f7637829 1828 wxRadioButton *radiobtn = wxDynamicCastThis(wxRadioButton);
26bf1ce0
VZ
1829 if ( radiobtn )
1830 {
1831 if ( event.GetSetChecked() )
1832 radiobtn->SetValue(event.GetChecked());
f03fc89f 1833 }
b3402d0d 1834#endif // wxUSE_RADIOBTN
7ec1983b 1835 }
1e6feb95 1836#endif // wxUSE_CONTROLS
7ec1983b 1837}
fd71308f 1838
f03fc89f
VZ
1839// ----------------------------------------------------------------------------
1840// dialog units translations
1841// ----------------------------------------------------------------------------
1842
1843wxPoint wxWindowBase::ConvertPixelsToDialog(const wxPoint& pt)
fd71308f
JS
1844{
1845 int charWidth = GetCharWidth();
1846 int charHeight = GetCharHeight();
5d9c2818
RD
1847 wxPoint pt2(-1, -1);
1848 if (pt.x != -1)
1849 pt2.x = (int) ((pt.x * 4) / charWidth) ;
1850 if (pt.y != -1)
1851 pt2.y = (int) ((pt.y * 8) / charHeight) ;
fd71308f
JS
1852
1853 return pt2;
1854}
1855
f03fc89f 1856wxPoint wxWindowBase::ConvertDialogToPixels(const wxPoint& pt)
fd71308f
JS
1857{
1858 int charWidth = GetCharWidth();
1859 int charHeight = GetCharHeight();
5d9c2818
RD
1860 wxPoint pt2(-1, -1);
1861 if (pt.x != -1)
1862 pt2.x = (int) ((pt.x * charWidth) / 4) ;
1863 if (pt.y != -1)
1864 pt2.y = (int) ((pt.y * charHeight) / 8) ;
fd71308f
JS
1865
1866 return pt2;
1867}
1868
f03fc89f
VZ
1869// ----------------------------------------------------------------------------
1870// event handlers
1871// ----------------------------------------------------------------------------
1872
1873// propagate the colour change event to the subwindows
1874void wxWindowBase::OnSysColourChanged(wxSysColourChangedEvent& event)
1875{
1876 wxWindowList::Node *node = GetChildren().GetFirst();
1877 while ( node )
1878 {
1879 // Only propagate to non-top-level windows
1880 wxWindow *win = node->GetData();
1881 if ( !win->IsTopLevel() )
1882 {
1883 wxSysColourChangedEvent event2;
1884 event.m_eventObject = win;
1885 win->GetEventHandler()->ProcessEvent(event2);
1886 }
1887
1888 node = node->GetNext();
1889 }
1890}
1891
1892// the default action is to populate dialog with data when it's created
1893void wxWindowBase::OnInitDialog( wxInitDialogEvent &WXUNUSED(event) )
1894{
1895 TransferDataToWindow();
1896}
1897
a02dc3e3
VZ
1898// process Ctrl-Alt-mclick
1899void wxWindowBase::OnMiddleClick( wxMouseEvent& event )
1900{
1e6feb95 1901#if wxUSE_MSGDLG
a02dc3e3
VZ
1902 if ( event.ControlDown() && event.AltDown() )
1903 {
1904 // don't translate these strings
1905 wxString port;
af3062a8
VZ
1906
1907#ifdef __WXUNIVERSAL__
1908 port = _T("Univ/");
1909#endif // __WXUNIVERSAL__
1910
a02dc3e3
VZ
1911 switch ( wxGetOsVersion() )
1912 {
ea8e90b7 1913 case wxMOTIF_X: port += _T("Motif"); break;
ff8fda36 1914 case wxMAC:
ea8e90b7
VZ
1915 case wxMAC_DARWIN: port += _T("Mac"); break;
1916 case wxBEOS: port += _T("BeOS"); break;
a02dc3e3
VZ
1917 case wxGTK:
1918 case wxGTK_WIN32:
1919 case wxGTK_OS2:
ea8e90b7 1920 case wxGTK_BEOS: port += _T("GTK"); break;
a02dc3e3
VZ
1921 case wxWINDOWS:
1922 case wxPENWINDOWS:
1923 case wxWINDOWS_NT:
1924 case wxWIN32S:
1925 case wxWIN95:
ea8e90b7 1926 case wxWIN386: port += _T("MS Windows"); break;
a02dc3e3
VZ
1927 case wxMGL_UNIX:
1928 case wxMGL_X:
1929 case wxMGL_WIN32:
ea8e90b7 1930 case wxMGL_OS2: port += _T("MGL"); break;
a02dc3e3 1931 case wxWINDOWS_OS2:
ea8e90b7
VZ
1932 case wxOS2_PM: port += _T("OS/2"); break;
1933 default: port += _T("unknown"); break;
a02dc3e3
VZ
1934 }
1935
1936 wxMessageBox(wxString::Format(
1937 _T(
af3062a8 1938 " wxWindows Library (%s port)\nVersion %u.%u.%u%s, compiled at %s %s\n Copyright (c) 1995-2002 wxWindows team"
a02dc3e3
VZ
1939 ),
1940 port.c_str(),
1941 wxMAJOR_VERSION,
1942 wxMINOR_VERSION,
1943 wxRELEASE_NUMBER,
3f562374
VZ
1944#if wxUSE_UNICODE
1945 L" (Unicode)",
1946#else
1947 "",
1948#endif
1949 __TDATE__,
1950 __TTIME__
a02dc3e3
VZ
1951 ),
1952 _T("wxWindows information"),
1953 wxICON_INFORMATION | wxOK,
1954 (wxWindow *)this);
1955 }
1956 else
1e6feb95 1957#endif // wxUSE_MSGDLG
a02dc3e3
VZ
1958 {
1959 event.Skip();
1960 }
1961}
1962
ed5317e5
JS
1963// ----------------------------------------------------------------------------
1964// accessibility
1965// ----------------------------------------------------------------------------
1966
1967#if wxUSE_ACCESSIBILITY
1968void wxWindowBase::SetAccessible(wxAccessible* accessible)
1969{
2aefc528 1970 if (m_accessible && (accessible != m_accessible))
ed5317e5
JS
1971 delete m_accessible;
1972 m_accessible = accessible;
1973 if (m_accessible)
1974 m_accessible->SetWindow((wxWindow*) this);
1975}
1976
1977// Returns the accessible object, creating if necessary.
1978wxAccessible* wxWindowBase::GetOrCreateAccessible()
1979{
1980 if (!m_accessible)
1981 m_accessible = CreateAccessible();
1982 return m_accessible;
1983}
1984
1985// Override to create a specific accessible object.
1986wxAccessible* wxWindowBase::CreateAccessible()
1987{
1988 return new wxWindowAccessible((wxWindow*) this);
1989}
1990
1991#endif
1992
f03fc89f
VZ
1993// ----------------------------------------------------------------------------
1994// list classes implementation
1995// ----------------------------------------------------------------------------
1996
1997void wxWindowListNode::DeleteData()
1998{
1999 delete (wxWindow *)GetData();
2000}
2001
1e6feb95
VZ
2002// ----------------------------------------------------------------------------
2003// borders
2004// ----------------------------------------------------------------------------
2005
2006wxBorder wxWindowBase::GetBorder() const
2007{
2008 wxBorder border = (wxBorder)(m_windowStyle & wxBORDER_MASK);
2009 if ( border == wxBORDER_DEFAULT )
2010 {
2011 border = GetDefaultBorder();
2012 }
2013
2014 return border;
2015}
2016
2017wxBorder wxWindowBase::GetDefaultBorder() const
2018{
2019 return wxBORDER_NONE;
2020}
2021
2022// ----------------------------------------------------------------------------
2023// hit testing
2024// ----------------------------------------------------------------------------
2025
2026wxHitTest wxWindowBase::DoHitTest(wxCoord x, wxCoord y) const
2027{
2028 // here we just check if the point is inside the window or not
2029
2030 // check the top and left border first
2031 bool outside = x < 0 || y < 0;
2032 if ( !outside )
2033 {
2034 // check the right and bottom borders too
2035 wxSize size = GetSize();
2036 outside = x >= size.x || y >= size.y;
2037 }
2038
2039 return outside ? wxHT_WINDOW_OUTSIDE : wxHT_WINDOW_INSIDE;
2040}
2041
94633ad9
VZ
2042// ----------------------------------------------------------------------------
2043// mouse capture
2044// ----------------------------------------------------------------------------
2045
2046struct WXDLLEXPORT wxWindowNext
2047{
2048 wxWindow *win;
2049 wxWindowNext *next;
786646f3 2050} *wxWindowBase::ms_winCaptureNext = NULL;
94633ad9 2051
a83e1475 2052void wxWindowBase::CaptureMouse()
94633ad9 2053{
7e555446 2054 wxLogTrace(_T("mousecapture"), _T("CaptureMouse(%p)"), this);
45e0dc94 2055
94633ad9
VZ
2056 wxWindow *winOld = GetCapture();
2057 if ( winOld )
2058 {
df2f507b 2059 ((wxWindowBase*) winOld)->DoReleaseMouse();
edd802c6 2060
94633ad9
VZ
2061 // save it on stack
2062 wxWindowNext *item = new wxWindowNext;
2063 item->win = winOld;
2064 item->next = ms_winCaptureNext;
2065 ms_winCaptureNext = item;
2066 }
2067 //else: no mouse capture to save
2068
2069 DoCaptureMouse();
2070}
2071
a83e1475 2072void wxWindowBase::ReleaseMouse()
94633ad9 2073{
7e555446 2074 wxLogTrace(_T("mousecapture"), _T("ReleaseMouse(%p)"), this);
349d1942 2075
63fd5f0b 2076 wxASSERT_MSG( GetCapture() == this, wxT("attempt to release mouse, but this window hasn't captured it") );
a7b09001 2077
94633ad9
VZ
2078 DoReleaseMouse();
2079
2080 if ( ms_winCaptureNext )
2081 {
44f8caa7 2082 ((wxWindowBase*)ms_winCaptureNext->win)->DoCaptureMouse();
edd802c6 2083
94633ad9
VZ
2084 wxWindowNext *item = ms_winCaptureNext;
2085 ms_winCaptureNext = item->next;
2086 delete item;
2087 }
2088 //else: stack is empty, no previous capture
2089
2090 wxLogTrace(_T("mousecapture"),
7e555446 2091 _T("After ReleaseMouse() mouse is captured by %p"),
94633ad9
VZ
2092 GetCapture());
2093}
2094
7de59551
RD
2095
2096void wxWindowBase::SendDestroyEvent()
2097{
2098 wxWindowDestroyEvent event;
2099 event.SetEventObject(this);
2100 event.SetId(GetId());
2101 GetEventHandler()->ProcessEvent(event);
2102}
2103
33b494d6
VZ
2104// ----------------------------------------------------------------------------
2105// global functions
2106// ----------------------------------------------------------------------------
2107
2108wxWindow* wxGetTopLevelParent(wxWindow *win)
2109{
2110 while ( win && !win->IsTopLevel() )
2111 win = win->GetParent();
2112
2113 return win;
2114}
2115
ed5317e5
JS
2116#if wxUSE_ACCESSIBILITY
2117// ----------------------------------------------------------------------------
2118// accessible object for windows
2119// ----------------------------------------------------------------------------
2120
2121// Can return either a child object, or an integer
2122// representing the child element, starting from 1.
2123wxAccStatus wxWindowAccessible::HitTest(const wxPoint& pt, int* childId, wxAccessible** childObject)
2124{
2125 wxASSERT( GetWindow() != NULL );
2126 if (!GetWindow())
2127 return wxACC_FAIL;
2128
2129 return wxACC_NOT_IMPLEMENTED;
2130}
2131
2132// Returns the rectangle for this object (id = 0) or a child element (id > 0).
2133wxAccStatus wxWindowAccessible::GetLocation(wxRect& rect, int elementId)
2134{
2135 wxASSERT( GetWindow() != NULL );
2136 if (!GetWindow())
2137 return wxACC_FAIL;
2138
c6e2af45
JS
2139 wxWindow* win = NULL;
2140 if (elementId == 0)
2141 {
2142 win = GetWindow();
2143 }
2144 else
2145 {
2146 if (elementId <= (int) GetWindow()->GetChildren().GetCount())
2147 {
2148 win = (wxWindow*) GetWindow()->GetChildren().Nth(elementId-1)->GetData();
2149 }
2150 else
2151 return wxACC_FAIL;
2152 }
2153 if (win)
2154 {
2155 rect = win->GetRect();
2156 if (win->GetParent() && !win->IsKindOf(CLASSINFO(wxTopLevelWindow)))
2157 rect.SetPosition(win->GetParent()->ClientToScreen(rect.GetPosition()));
2158 return wxACC_OK;
2159 }
2160
ed5317e5
JS
2161 return wxACC_NOT_IMPLEMENTED;
2162}
2163
2164// Navigates from fromId to toId/toObject.
2165wxAccStatus wxWindowAccessible::Navigate(wxNavDir navDir, int fromId,
2166 int* toId, wxAccessible** toObject)
2167{
2168 wxASSERT( GetWindow() != NULL );
2169 if (!GetWindow())
2170 return wxACC_FAIL;
2171
c6e2af45
JS
2172 switch (navDir)
2173 {
2174 case wxNAVDIR_FIRSTCHILD:
2175 {
2176 if (GetWindow()->GetChildren().GetCount() == 0)
2177 return wxACC_FALSE;
2178 wxWindow* childWindow = (wxWindow*) GetWindow()->GetChildren().GetFirst()->GetData();
2179 *toObject = childWindow->GetOrCreateAccessible();
2180
2181 return wxACC_OK;
2182 }
2183 case wxNAVDIR_LASTCHILD:
2184 {
2185 if (GetWindow()->GetChildren().GetCount() == 0)
2186 return wxACC_FALSE;
2187 wxWindow* childWindow = (wxWindow*) GetWindow()->GetChildren().GetLast()->GetData();
2188 *toObject = childWindow->GetOrCreateAccessible();
2189
2190 return wxACC_OK;
2191 }
2192 case wxNAVDIR_RIGHT:
2193 case wxNAVDIR_DOWN:
2194 case wxNAVDIR_NEXT:
2195 {
2196 wxWindowList::Node *node = NULL;
2197 if (fromId == 0)
2198 {
2199 // Can't navigate to sibling of this window
2200 // if we're a top-level window.
2201 if (!GetWindow()->GetParent())
2202 return wxACC_NOT_IMPLEMENTED;
2203
2204 node = GetWindow()->GetParent()->GetChildren().Find(GetWindow());
2205 }
2206 else
2207 {
2208 if (fromId <= (int) GetWindow()->GetChildren().GetCount())
2209 node = (wxWindowList::Node*) GetWindow()->GetChildren().Nth(fromId-1);
2210 }
2211
2212 if (node && node->GetNext())
2213 {
2214 wxWindow* nextWindow = (wxWindow*) node->GetNext()->Data();
2215 *toObject = nextWindow->GetOrCreateAccessible();
2216 return wxACC_OK;
2217 }
2218 else
2219 return wxACC_FALSE;
2220 }
2221 case wxNAVDIR_LEFT:
2222 case wxNAVDIR_UP:
2223 case wxNAVDIR_PREVIOUS:
2224 {
2225 wxWindowList::Node *node = NULL;
2226 if (fromId == 0)
2227 {
2228 // Can't navigate to sibling of this window
2229 // if we're a top-level window.
2230 if (!GetWindow()->GetParent())
2231 return wxACC_NOT_IMPLEMENTED;
2232
2233 node = GetWindow()->GetParent()->GetChildren().Find(GetWindow());
2234 }
2235 else
2236 {
2237 if (fromId <= (int) GetWindow()->GetChildren().GetCount())
2238 node = (wxWindowList::Node*) GetWindow()->GetChildren().Nth(fromId-1);
2239 }
2240
2241 if (node && node->GetPrevious())
2242 {
2243 wxWindow* previousWindow = (wxWindow*) node->GetPrevious()->Data();
2244 *toObject = previousWindow->GetOrCreateAccessible();
2245 return wxACC_OK;
2246 }
2247 else
2248 return wxACC_FALSE;
2249 }
2250 }
2251
ed5317e5
JS
2252 return wxACC_NOT_IMPLEMENTED;
2253}
2254
2255// Gets the name of the specified object.
2256wxAccStatus wxWindowAccessible::GetName(int childId, wxString* name)
2257{
2258 wxASSERT( GetWindow() != NULL );
2259 if (!GetWindow())
2260 return wxACC_FAIL;
2261
2aefc528
JS
2262 wxString title;
2263
2264 // If a child, leave wxWindows to call the function on the actual
2265 // child object.
2266 if (childId > 0)
2267 return wxACC_NOT_IMPLEMENTED;
2268
2269 // This will eventually be replaced by specialised
2270 // accessible classes, one for each kind of wxWindows
2271 // control or window.
2272 if (GetWindow()->IsKindOf(CLASSINFO(wxButton)))
2273 title = ((wxButton*) GetWindow())->GetLabel();
2274 else
2275 title = GetWindow()->GetName();
2276
ed5317e5
JS
2277 if (!title.IsEmpty())
2278 {
2279 *name = title;
2280 return wxACC_OK;
2281 }
2282 else
2283 return wxACC_NOT_IMPLEMENTED;
2284}
2285
2286// Gets the number of children.
2287wxAccStatus wxWindowAccessible::GetChildCount(int* childId)
2288{
2289 wxASSERT( GetWindow() != NULL );
2290 if (!GetWindow())
2291 return wxACC_FAIL;
2292
2293 *childId = (int) GetWindow()->GetChildren().GetCount();
2294 return wxACC_OK;
2295}
2296
2297// Gets the specified child (starting from 1).
2298// If *child is NULL and return value is wxACC_OK,
2299// this means that the child is a simple element and
2300// not an accessible object.
2301wxAccStatus wxWindowAccessible::GetChild(int childId, wxAccessible** child)
2302{
2303 wxASSERT( GetWindow() != NULL );
2304 if (!GetWindow())
2305 return wxACC_FAIL;
2306
2307 if (childId == 0)
2308 {
2309 *child = this;
2310 return wxACC_OK;
2311 }
2312
2313 if (childId > (int) GetWindow()->GetChildren().GetCount())
2314 return wxACC_FAIL;
2315
2316 wxWindow* childWindow = (wxWindow*) GetWindow()->GetChildren().Nth(childId-1)->GetData();
2317 *child = childWindow->GetOrCreateAccessible();
2318 if (*child)
2319 return wxACC_OK;
2320 else
2321 return wxACC_FAIL;
2322}
2323
2324// Gets the parent, or NULL.
2325wxAccStatus wxWindowAccessible::GetParent(wxAccessible** parent)
2326{
2327 wxASSERT( GetWindow() != NULL );
2328 if (!GetWindow())
2329 return wxACC_FAIL;
2330
2331 wxWindow* parentWindow = GetWindow()->GetParent();
c6e2af45 2332 if (!parentWindow)
ed5317e5
JS
2333 {
2334 *parent = NULL;
2335 return wxACC_OK;
2336 }
2337 else
2338 {
2339 *parent = parentWindow->GetOrCreateAccessible();
2340 if (*parent)
2341 return wxACC_OK;
2342 else
2343 return wxACC_FAIL;
2344 }
2345}
2346
2347// Performs the default action. childId is 0 (the action for this object)
2348// or > 0 (the action for a child).
2349// Return wxACC_NOT_SUPPORTED if there is no default action for this
2350// window (e.g. an edit control).
2351wxAccStatus wxWindowAccessible::DoDefaultAction(int childId)
2352{
2353 wxASSERT( GetWindow() != NULL );
2354 if (!GetWindow())
2355 return wxACC_FAIL;
2356
2357 return wxACC_NOT_IMPLEMENTED;
2358}
2359
2360// Gets the default action for this object (0) or > 0 (the action for a child).
2361// Return wxACC_OK even if there is no action. actionName is the action, or the empty
2362// string if there is no action.
2363// The retrieved string describes the action that is performed on an object,
2364// not what the object does as a result. For example, a toolbar button that prints
2365// a document has a default action of "Press" rather than "Prints the current document."
2366wxAccStatus wxWindowAccessible::GetDefaultAction(int childId, wxString* actionName)
2367{
2368 wxASSERT( GetWindow() != NULL );
2369 if (!GetWindow())
2370 return wxACC_FAIL;
2371
2372 return wxACC_NOT_IMPLEMENTED;
2373}
2374
2375// Returns the description for this object or a child.
2376wxAccStatus wxWindowAccessible::GetDescription(int childId, wxString* description)
2377{
2378 wxASSERT( GetWindow() != NULL );
2379 if (!GetWindow())
2380 return wxACC_FAIL;
2381
2aefc528
JS
2382 wxString ht(GetWindow()->GetHelpText());
2383 if (!ht.IsEmpty())
2384 {
2385 *description = ht;
2386 return wxACC_OK;
2387 }
ed5317e5
JS
2388 return wxACC_NOT_IMPLEMENTED;
2389}
2390
2391// Returns help text for this object or a child, similar to tooltip text.
2392wxAccStatus wxWindowAccessible::GetHelpText(int childId, wxString* helpText)
2393{
2394 wxASSERT( GetWindow() != NULL );
2395 if (!GetWindow())
2396 return wxACC_FAIL;
2397
2398 wxString ht(GetWindow()->GetHelpText());
2399 if (!ht.IsEmpty())
2400 {
2401 *helpText = ht;
2402 return wxACC_OK;
2403 }
2404 return wxACC_NOT_IMPLEMENTED;
2405}
2406
2407// Returns the keyboard shortcut for this object or child.
2408// Return e.g. ALT+K
2409wxAccStatus wxWindowAccessible::GetKeyboardShortcut(int childId, wxString* shortcut)
2410{
2411 wxASSERT( GetWindow() != NULL );
2412 if (!GetWindow())
2413 return wxACC_FAIL;
2414
2415 return wxACC_NOT_IMPLEMENTED;
2416}
2417
2418// Returns a role constant.
2419wxAccStatus wxWindowAccessible::GetRole(int childId, wxAccRole* role)
2420{
2421 wxASSERT( GetWindow() != NULL );
2422 if (!GetWindow())
2423 return wxACC_FAIL;
2424
2aefc528
JS
2425 // If a child, leave wxWindows to call the function on the actual
2426 // child object.
2427 if (childId > 0)
2428 return wxACC_NOT_IMPLEMENTED;
2429
2430 if (GetWindow()->IsKindOf(CLASSINFO(wxControl)))
2431 return wxACC_NOT_IMPLEMENTED;
2432#if wxUSE_STATUSBAR
2433 if (GetWindow()->IsKindOf(CLASSINFO(wxStatusBar)))
2434 return wxACC_NOT_IMPLEMENTED;
2435#endif
2436#if wxUSE_TOOLBAR
2437 if (GetWindow()->IsKindOf(CLASSINFO(wxToolBar)))
2438 return wxACC_NOT_IMPLEMENTED;
2439#endif
2440
2441 //*role = wxROLE_SYSTEM_CLIENT;
2442 *role = wxROLE_SYSTEM_CLIENT;
2443 return wxACC_OK;
2444
ed5317e5
JS
2445 return wxACC_NOT_IMPLEMENTED;
2446}
2447
2448// Returns a state constant.
2449wxAccStatus wxWindowAccessible::GetState(int childId, long* state)
2450{
2451 wxASSERT( GetWindow() != NULL );
2452 if (!GetWindow())
2453 return wxACC_FAIL;
2454
2aefc528
JS
2455 // If a child, leave wxWindows to call the function on the actual
2456 // child object.
2457 if (childId > 0)
2458 return wxACC_NOT_IMPLEMENTED;
2459
2460 if (GetWindow()->IsKindOf(CLASSINFO(wxControl)))
2461 return wxACC_NOT_IMPLEMENTED;
2462
2463#if wxUSE_STATUSBAR
2464 if (GetWindow()->IsKindOf(CLASSINFO(wxStatusBar)))
2465 return wxACC_NOT_IMPLEMENTED;
2466#endif
2467#if wxUSE_TOOLBAR
2468 if (GetWindow()->IsKindOf(CLASSINFO(wxToolBar)))
2469 return wxACC_NOT_IMPLEMENTED;
2470#endif
2471
2472 *state = 0;
2473 return wxACC_OK;
2474
ed5317e5
JS
2475 return wxACC_NOT_IMPLEMENTED;
2476}
2477
2478// Returns a localized string representing the value for the object
2479// or child.
2480wxAccStatus wxWindowAccessible::GetValue(int childId, wxString* strValue)
2481{
2482 wxASSERT( GetWindow() != NULL );
2483 if (!GetWindow())
2484 return wxACC_FAIL;
2485
2486 return wxACC_NOT_IMPLEMENTED;
2487}
2488
2489// Selects the object or child.
2490wxAccStatus wxWindowAccessible::Select(int childId, wxAccSelectionFlags selectFlags)
2491{
2492 wxASSERT( GetWindow() != NULL );
2493 if (!GetWindow())
2494 return wxACC_FAIL;
2495
2496 return wxACC_NOT_IMPLEMENTED;
2497}
2498
2499// Gets the window with the keyboard focus.
2500// If childId is 0 and child is NULL, no object in
2501// this subhierarchy has the focus.
2502// If this object has the focus, child should be 'this'.
2503wxAccStatus wxWindowAccessible::GetFocus(int* childId, wxAccessible** child)
2504{
2505 wxASSERT( GetWindow() != NULL );
2506 if (!GetWindow())
2507 return wxACC_FAIL;
2508
2509 return wxACC_NOT_IMPLEMENTED;
2510}
2511
2512// Gets a variant representing the selected children
2513// of this object.
2514// Acceptable values:
2515// - a null variant (IsNull() returns TRUE)
2516// - a list variant (GetType() == wxT("list")
2517// - an integer representing the selected child element,
2518// or 0 if this object is selected (GetType() == wxT("long")
2519// - a "void*" pointer to a wxAccessible child object
2520wxAccStatus wxWindowAccessible::GetSelections(wxVariant* selections)
2521{
2522 wxASSERT( GetWindow() != NULL );
2523 if (!GetWindow())
2524 return wxACC_FAIL;
2525
2526 return wxACC_NOT_IMPLEMENTED;
2527}
2528
2529#endif // wxUSE_ACCESSIBILITY