]> git.saurik.com Git - wxWidgets.git/blob - src/osx/window_osx.cpp
Fix using weak references to incomplete classes.
[wxWidgets.git] / src / osx / window_osx.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/carbon/window.cpp
3 // Purpose: wxWindowMac
4 // Author: Stefan Csomor
5 // Modified by:
6 // Created: 1998-01-01
7 // RCS-ID: $Id: window.cpp 54981 2008-08-05 17:52:02Z SC $
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #include "wx/wxprec.h"
13
14 #include "wx/window.h"
15
16 #ifndef WX_PRECOMP
17 #include "wx/log.h"
18 #include "wx/app.h"
19 #include "wx/utils.h"
20 #include "wx/panel.h"
21 #include "wx/frame.h"
22 #include "wx/dc.h"
23 #include "wx/dcclient.h"
24 #include "wx/button.h"
25 #include "wx/menu.h"
26 #include "wx/dialog.h"
27 #include "wx/settings.h"
28 #include "wx/msgdlg.h"
29 #include "wx/scrolbar.h"
30 #include "wx/statbox.h"
31 #include "wx/textctrl.h"
32 #include "wx/toolbar.h"
33 #include "wx/layout.h"
34 #include "wx/statusbr.h"
35 #include "wx/menuitem.h"
36 #include "wx/treectrl.h"
37 #include "wx/listctrl.h"
38 #endif
39
40 #include "wx/tooltip.h"
41 #include "wx/spinctrl.h"
42 #include "wx/geometry.h"
43
44 #if wxUSE_LISTCTRL
45 #include "wx/listctrl.h"
46 #endif
47
48 #if wxUSE_TREECTRL
49 #include "wx/treectrl.h"
50 #endif
51
52 #if wxUSE_CARET
53 #include "wx/caret.h"
54 #endif
55
56 #if wxUSE_POPUPWIN
57 #include "wx/popupwin.h"
58 #endif
59
60 #if wxUSE_DRAG_AND_DROP
61 #include "wx/dnd.h"
62 #endif
63
64 #include "wx/graphics.h"
65
66 #if wxOSX_USE_CARBON
67 #include "wx/osx/uma.h"
68 #else
69 #include "wx/osx/private.h"
70 #endif
71
72 #define MAC_SCROLLBAR_SIZE 15
73 #define MAC_SMALL_SCROLLBAR_SIZE 11
74
75 #include <string.h>
76
77 #ifdef __WXUNIVERSAL__
78 IMPLEMENT_ABSTRACT_CLASS(wxWindowMac, wxWindowBase)
79 #else
80 IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
81 #endif
82
83 BEGIN_EVENT_TABLE(wxWindowMac, wxWindowBase)
84 EVT_MOUSE_EVENTS(wxWindowMac::OnMouseEvent)
85 END_EVENT_TABLE()
86
87 #define wxMAC_DEBUG_REDRAW 0
88 #ifndef wxMAC_DEBUG_REDRAW
89 #define wxMAC_DEBUG_REDRAW 0
90 #endif
91
92 // ===========================================================================
93 // implementation
94 // ===========================================================================
95
96 // the grow box has to be implemented as an inactive window, so that nothing can direct
97 // the focus to it
98
99 class WXDLLIMPEXP_CORE wxBlindPlateWindow : public wxWindow
100 {
101 public:
102 wxBlindPlateWindow() { Init(); }
103
104 // Old-style constructor (no default values for coordinates to avoid
105 // ambiguity with the new one)
106 wxBlindPlateWindow(wxWindow *parent,
107 int x, int y, int width, int height,
108 long style = wxTAB_TRAVERSAL | wxNO_BORDER,
109 const wxString& name = wxPanelNameStr)
110 {
111 Init();
112
113 Create(parent, wxID_ANY, wxPoint(x, y), wxSize(width, height), style, name);
114 }
115
116 // Constructor
117 wxBlindPlateWindow(wxWindow *parent,
118 wxWindowID winid = wxID_ANY,
119 const wxPoint& pos = wxDefaultPosition,
120 const wxSize& size = wxDefaultSize,
121 long style = wxTAB_TRAVERSAL | wxNO_BORDER,
122 const wxString& name = wxPanelNameStr)
123 {
124 Init();
125
126 Create(parent, winid, pos, size, style, name);
127 }
128
129 // Pseudo ctor
130 bool Create(wxWindow *parent,
131 wxWindowID winid = wxID_ANY,
132 const wxPoint& pos = wxDefaultPosition,
133 const wxSize& size = wxDefaultSize,
134 long style = wxTAB_TRAVERSAL | wxNO_BORDER,
135 const wxString& name = wxPanelNameStr)
136 {
137 if ( !wxWindow::Create(parent, winid, pos, size, style, name) )
138 return false;
139
140 // so that non-solid background renders correctly under GTK+:
141 SetThemeEnabled(true);
142 }
143
144 virtual ~wxBlindPlateWindow();
145
146 virtual bool AcceptsFocus() const
147 {
148 return false;
149 }
150
151 protected:
152 // common part of all ctors
153 void Init()
154 {
155 }
156
157 DECLARE_DYNAMIC_CLASS_NO_COPY(wxBlindPlateWindow)
158 DECLARE_EVENT_TABLE()
159 };
160
161 wxBlindPlateWindow::~wxBlindPlateWindow()
162 {
163 }
164
165 IMPLEMENT_DYNAMIC_CLASS(wxBlindPlateWindow, wxWindow)
166
167 BEGIN_EVENT_TABLE(wxBlindPlateWindow, wxWindow)
168 END_EVENT_TABLE()
169
170
171 // ----------------------------------------------------------------------------
172 // constructors and such
173 // ----------------------------------------------------------------------------
174
175 wxWindowMac::wxWindowMac()
176 {
177 Init();
178 }
179
180 wxWindowMac::wxWindowMac(wxWindowMac *parent,
181 wxWindowID id,
182 const wxPoint& pos ,
183 const wxSize& size ,
184 long style ,
185 const wxString& name )
186 {
187 Init();
188 Create(parent, id, pos, size, style, name);
189 }
190
191 void wxWindowMac::Init()
192 {
193 m_peer = NULL ;
194 m_macAlpha = 255 ;
195 m_cgContextRef = NULL ;
196
197 // as all windows are created with WS_VISIBLE style...
198 m_isShown = true;
199
200 m_hScrollBar = NULL ;
201 m_vScrollBar = NULL ;
202 m_hScrollBarAlwaysShown = false;
203 m_vScrollBarAlwaysShown = false;
204 m_growBox = NULL ;
205
206 m_macIsUserPane = true;
207 m_clipChildren = false ;
208 m_cachedClippedRectValid = false ;
209 m_isNativeWindowWrapper = false;
210 }
211
212 wxWindowMac::~wxWindowMac()
213 {
214 SendDestroyEvent();
215
216 MacInvalidateBorders() ;
217
218 #ifndef __WXUNIVERSAL__
219 // VS: make sure there's no wxFrame with last focus set to us:
220 for ( wxWindow *win = GetParent(); win; win = win->GetParent() )
221 {
222 wxFrame *frame = wxDynamicCast(win, wxFrame);
223 if ( frame )
224 {
225 if ( frame->GetLastFocus() == this )
226 frame->SetLastFocus(NULL);
227 break;
228 }
229 }
230 #endif
231
232 // destroy children before destroying this window itself
233 DestroyChildren();
234
235 // wxRemoveMacControlAssociation( this ) ;
236 // If we delete an item, we should initialize the parent panel,
237 // because it could now be invalid.
238 wxTopLevelWindow *tlw = wxDynamicCast(wxGetTopLevelParent((wxWindow*)this), wxTopLevelWindow);
239 if ( tlw )
240 {
241 if ( tlw->GetDefaultItem() == (wxButton*) this)
242 tlw->SetDefaultItem(NULL);
243 }
244
245 if ( g_MacLastWindow == this )
246 g_MacLastWindow = NULL ;
247
248 #ifndef __WXUNIVERSAL__
249 wxFrame* frame = wxDynamicCast( wxGetTopLevelParent( (wxWindow*)this ) , wxFrame ) ;
250 if ( frame )
251 {
252 if ( frame->GetLastFocus() == this )
253 frame->SetLastFocus( NULL ) ;
254 }
255 #endif
256
257 // delete our drop target if we've got one
258 #if wxUSE_DRAG_AND_DROP
259 if ( m_dropTarget != NULL )
260 {
261 delete m_dropTarget;
262 m_dropTarget = NULL;
263 }
264 #endif
265
266 delete m_peer ;
267 }
268
269 WXWidget wxWindowMac::GetHandle() const
270 {
271 if ( m_peer )
272 return (WXWidget) m_peer->GetWXWidget() ;
273 return NULL;
274 }
275
276 // ---------------------------------------------------------------------------
277 // Utility Routines to move between different coordinate systems
278 // ---------------------------------------------------------------------------
279
280 /*
281 * Right now we have the following setup :
282 * a border that is not part of the native control is always outside the
283 * control's border (otherwise we loose all native intelligence, future ways
284 * may be to have a second embedding control responsible for drawing borders
285 * and backgrounds eventually)
286 * so all this border calculations have to be taken into account when calling
287 * native methods or getting native oriented data
288 * so we have three coordinate systems here
289 * wx client coordinates
290 * wx window coordinates (including window frames)
291 * native coordinates
292 */
293
294 //
295 //
296
297 // Constructor
298 bool wxWindowMac::Create(wxWindowMac *parent,
299 wxWindowID id,
300 const wxPoint& pos,
301 const wxSize& size,
302 long style,
303 const wxString& name)
304 {
305 wxCHECK_MSG( parent, false, wxT("can't create wxWindowMac without parent") );
306
307 if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) )
308 return false;
309
310 m_windowVariant = parent->GetWindowVariant() ;
311
312 if ( m_macIsUserPane )
313 {
314 m_peer = wxWidgetImpl::CreateUserPane( this, parent, id, pos, size , style, GetExtraStyle() );
315 MacPostControlCreate(pos, size) ;
316 }
317
318 #ifndef __WXUNIVERSAL__
319 // Don't give scrollbars to wxControls unless they ask for them
320 if ( (! IsKindOf(CLASSINFO(wxControl))
321 #if wxUSE_STATUSBAR
322 && ! IsKindOf(CLASSINFO(wxStatusBar))
323 #endif
324 )
325 || (IsKindOf(CLASSINFO(wxControl)) && ((style & wxHSCROLL) || (style & wxVSCROLL))))
326 {
327 MacCreateScrollBars( style ) ;
328 }
329 #endif
330
331 wxWindowCreateEvent event((wxWindow*)this);
332 GetEventHandler()->AddPendingEvent(event);
333
334 return true;
335 }
336
337 void wxWindowMac::MacChildAdded()
338 {
339 #if wxUSE_SCROLLBAR
340 if ( m_vScrollBar )
341 m_vScrollBar->Raise() ;
342 if ( m_hScrollBar )
343 m_hScrollBar->Raise() ;
344 if ( m_growBox )
345 m_growBox->Raise() ;
346 #endif
347 }
348
349 void wxWindowMac::MacPostControlCreate(const wxPoint& WXUNUSED(pos), const wxSize& size)
350 {
351 wxASSERT_MSG( m_peer != NULL && m_peer->IsOk() , wxT("No valid mac control") ) ;
352
353 GetParent()->AddChild( this );
354
355 m_peer->InstallEventHandler();
356 m_peer->Embed(GetParent()->GetPeer());
357
358 GetParent()->MacChildAdded() ;
359
360 // adjust font, controlsize etc
361 DoSetWindowVariant( m_windowVariant ) ;
362
363 m_peer->SetLabel( wxStripMenuCodes(m_label, wxStrip_Mnemonics), GetFont().GetEncoding() ) ;
364
365 // for controls we want to use best size for wxDefaultSize params )
366 if ( !m_macIsUserPane )
367 SetInitialSize(size);
368
369 SetCursor( *wxSTANDARD_CURSOR ) ;
370 }
371
372 void wxWindowMac::DoSetWindowVariant( wxWindowVariant variant )
373 {
374 // Don't assert, in case we set the window variant before
375 // the window is created
376 // wxASSERT( m_peer->Ok() ) ;
377
378 m_windowVariant = variant ;
379
380 if (m_peer == NULL || !m_peer->IsOk())
381 return;
382
383 m_peer->SetControlSize( variant );
384 #if wxOSX_USE_CARBON
385 ControlSize size ;
386
387 // we will get that from the settings later
388 // and make this NORMAL later, but first
389 // we have a few calculations that we must fix
390
391 switch ( variant )
392 {
393 case wxWINDOW_VARIANT_NORMAL :
394 size = kControlSizeNormal;
395 break ;
396
397 case wxWINDOW_VARIANT_SMALL :
398 size = kControlSizeSmall;
399 break ;
400
401 case wxWINDOW_VARIANT_MINI :
402 // not always defined in the headers
403 size = 3 ;
404 break ;
405
406 case wxWINDOW_VARIANT_LARGE :
407 size = kControlSizeLarge;
408 break ;
409
410 default:
411 wxFAIL_MSG(wxT("unexpected window variant"));
412 break ;
413 }
414 m_peer->SetData<ControlSize>(kControlEntireControl, kControlSizeTag, &size ) ;
415 #endif
416
417
418 switch ( variant )
419 {
420 case wxWINDOW_VARIANT_NORMAL :
421 static wxFont sysNormal(wxOSX_SYSTEM_FONT_NORMAL);
422 SetFont(sysNormal) ;
423 break ;
424
425 case wxWINDOW_VARIANT_SMALL :
426 static wxFont sysSmall(wxOSX_SYSTEM_FONT_SMALL);
427 SetFont(sysSmall) ;
428 break ;
429
430 case wxWINDOW_VARIANT_MINI :
431 static wxFont sysMini(wxOSX_SYSTEM_FONT_MINI);
432 SetFont(sysMini) ;
433 break ;
434
435 case wxWINDOW_VARIANT_LARGE :
436 static wxFont sysLarge(wxOSX_SYSTEM_FONT_NORMAL);
437 SetFont(sysLarge) ;
438 break ;
439
440 default:
441 wxFAIL_MSG(wxT("unexpected window variant"));
442 break ;
443 }
444 }
445
446 void wxWindowMac::MacUpdateControlFont()
447 {
448 if ( m_peer )
449 m_peer->SetFont( GetFont() , GetForegroundColour() , GetWindowStyle() ) ;
450
451 // do not trigger refreshes upon invisible and possible partly created objects
452 if ( IsShownOnScreen() )
453 Refresh() ;
454 }
455
456 bool wxWindowMac::SetFont(const wxFont& font)
457 {
458 bool retval = wxWindowBase::SetFont( font );
459
460 MacUpdateControlFont() ;
461
462 return retval;
463 }
464
465 bool wxWindowMac::SetForegroundColour(const wxColour& col )
466 {
467 bool retval = wxWindowBase::SetForegroundColour( col );
468
469 if (retval)
470 MacUpdateControlFont();
471
472 return retval;
473 }
474
475 bool wxWindowMac::SetBackgroundColour(const wxColour& col )
476 {
477 if (m_growBox)
478 {
479 if ( m_backgroundColour.Ok() )
480 m_growBox->SetBackgroundColour(m_backgroundColour);
481 else
482 m_growBox->SetBackgroundColour(*wxWHITE);
483 }
484
485 if ( !wxWindowBase::SetBackgroundColour(col) && m_hasBgCol )
486 return false ;
487
488 if ( m_peer )
489 m_peer->SetBackgroundColour( col ) ;
490
491 return true ;
492 }
493
494 static bool wxIsWindowOrParentDisabled(wxWindow* w)
495 {
496 while (w && !w->IsTopLevel())
497 {
498 if (!w->IsEnabled())
499 return true;
500 w = w->GetParent();
501 }
502 return false;
503 }
504
505 void wxWindowMac::SetFocus()
506 {
507 if ( !AcceptsFocus() )
508 return ;
509
510 if (wxIsWindowOrParentDisabled((wxWindow*) this))
511 return;
512
513 wxWindow* former = FindFocus() ;
514 if ( former == this )
515 return ;
516
517 m_peer->SetFocus() ;
518 }
519
520 void wxWindowMac::DoCaptureMouse()
521 {
522 wxApp::s_captureWindow = (wxWindow*) this ;
523 m_peer->CaptureMouse() ;
524 }
525
526 wxWindow * wxWindowBase::GetCapture()
527 {
528 return wxApp::s_captureWindow ;
529 }
530
531 void wxWindowMac::DoReleaseMouse()
532 {
533 wxApp::s_captureWindow = NULL ;
534
535 m_peer->ReleaseMouse() ;
536 }
537
538 #if wxUSE_DRAG_AND_DROP
539
540 void wxWindowMac::SetDropTarget(wxDropTarget *pDropTarget)
541 {
542 delete m_dropTarget;
543
544 m_dropTarget = pDropTarget;
545 if ( m_dropTarget != NULL )
546 {
547 // TODO:
548 }
549 }
550
551 #endif
552
553 // Old-style File Manager Drag & Drop
554 void wxWindowMac::DragAcceptFiles(bool WXUNUSED(accept))
555 {
556 // TODO:
557 }
558
559 // From a wx position / size calculate the appropriate size of the native control
560
561 bool wxWindowMac::MacGetBoundsForControl(
562 const wxPoint& pos,
563 const wxSize& size,
564 int& x, int& y,
565 int& w, int& h , bool adjustOrigin ) const
566 {
567 // the desired size, minus the border pixels gives the correct size of the control
568 x = (int)pos.x;
569 y = (int)pos.y;
570
571 w = WidthDefault( size.x );
572 h = HeightDefault( size.y );
573
574 x += MacGetLeftBorderSize() ;
575 y += MacGetTopBorderSize() ;
576 w -= MacGetLeftBorderSize() + MacGetRightBorderSize() ;
577 h -= MacGetTopBorderSize() + MacGetBottomBorderSize() ;
578
579 if ( adjustOrigin )
580 AdjustForParentClientOrigin( x , y ) ;
581
582 // this is in window relative coordinate, as this parent may have a border, its physical position is offset by this border
583 if ( GetParent() && !GetParent()->IsTopLevel() )
584 {
585 x -= GetParent()->MacGetLeftBorderSize() ;
586 y -= GetParent()->MacGetTopBorderSize() ;
587 }
588
589 return true ;
590 }
591
592 // Get window size (not client size)
593 void wxWindowMac::DoGetSize(int *x, int *y) const
594 {
595 int width, height;
596 m_peer->GetSize( width, height );
597
598 if (x)
599 *x = width + MacGetLeftBorderSize() + MacGetRightBorderSize() ;
600 if (y)
601 *y = height + MacGetTopBorderSize() + MacGetBottomBorderSize() ;
602 }
603
604 // get the position of the bounds of this window in client coordinates of its parent
605 void wxWindowMac::DoGetPosition(int *x, int *y) const
606 {
607 int x1, y1;
608
609 m_peer->GetPosition( x1, y1 ) ;
610
611 // get the wx window position from the native one
612 x1 -= MacGetLeftBorderSize() ;
613 y1 -= MacGetTopBorderSize() ;
614
615 if ( !IsTopLevel() )
616 {
617 wxWindow *parent = GetParent();
618 if ( parent )
619 {
620 // we must first adjust it to be in window coordinates of the parent,
621 // as otherwise it gets lost by the ClientAreaOrigin fix
622 x1 += parent->MacGetLeftBorderSize() ;
623 y1 += parent->MacGetTopBorderSize() ;
624
625 // and now to client coordinates
626 wxPoint pt(parent->GetClientAreaOrigin());
627 x1 -= pt.x ;
628 y1 -= pt.y ;
629 }
630 }
631
632 if (x)
633 *x = x1 ;
634 if (y)
635 *y = y1 ;
636 }
637
638 void wxWindowMac::DoScreenToClient(int *x, int *y) const
639 {
640 wxNonOwnedWindow* tlw = MacGetTopLevelWindow() ;
641 wxCHECK_RET( tlw , wxT("TopLevel Window missing") ) ;
642 tlw->GetNonOwnedPeer()->ScreenToWindow( x, y);
643 MacRootWindowToWindow( x , y ) ;
644
645 wxPoint origin = GetClientAreaOrigin() ;
646 if (x)
647 *x -= origin.x ;
648 if (y)
649 *y -= origin.y ;
650 }
651
652 void wxWindowMac::DoClientToScreen(int *x, int *y) const
653 {
654 wxNonOwnedWindow* tlw = MacGetTopLevelWindow() ;
655 wxCHECK_RET( tlw , wxT("TopLevel window missing") ) ;
656
657 wxPoint origin = GetClientAreaOrigin() ;
658 if (x)
659 *x += origin.x ;
660 if (y)
661 *y += origin.y ;
662
663 MacWindowToRootWindow( x , y ) ;
664 tlw->GetNonOwnedPeer()->WindowToScreen( x , y );
665 }
666
667 void wxWindowMac::MacClientToRootWindow( int *x , int *y ) const
668 {
669 wxPoint origin = GetClientAreaOrigin() ;
670 if (x)
671 *x += origin.x ;
672 if (y)
673 *y += origin.y ;
674
675 MacWindowToRootWindow( x , y ) ;
676 }
677
678 void wxWindowMac::MacWindowToRootWindow( int *x , int *y ) const
679 {
680 wxPoint pt ;
681
682 if (x)
683 pt.x = *x ;
684 if (y)
685 pt.y = *y ;
686
687 if ( !IsTopLevel() )
688 {
689 wxNonOwnedWindow* top = MacGetTopLevelWindow();
690 if (top)
691 {
692 pt.x -= MacGetLeftBorderSize() ;
693 pt.y -= MacGetTopBorderSize() ;
694 wxWidgetImpl::Convert( &pt , m_peer , top->m_peer ) ;
695 }
696 }
697
698 if (x)
699 *x = (int) pt.x ;
700 if (y)
701 *y = (int) pt.y ;
702 }
703
704 void wxWindowMac::MacRootWindowToWindow( int *x , int *y ) const
705 {
706 wxPoint pt ;
707
708 if (x)
709 pt.x = *x ;
710 if (y)
711 pt.y = *y ;
712
713 if ( !IsTopLevel() )
714 {
715 wxNonOwnedWindow* top = MacGetTopLevelWindow();
716 if (top)
717 {
718 wxWidgetImpl::Convert( &pt , top->m_peer , m_peer ) ;
719 pt.x += MacGetLeftBorderSize() ;
720 pt.y += MacGetTopBorderSize() ;
721 }
722 }
723
724 if (x)
725 *x = (int) pt.x ;
726 if (y)
727 *y = (int) pt.y ;
728 }
729
730 wxSize wxWindowMac::DoGetSizeFromClientSize( const wxSize & size ) const
731 {
732 wxSize sizeTotal = size;
733
734 int innerwidth, innerheight;
735 int left, top;
736 int outerwidth, outerheight;
737
738 m_peer->GetContentArea( left, top, innerwidth, innerheight );
739 m_peer->GetSize( outerwidth, outerheight );
740
741 sizeTotal.x += outerwidth-innerwidth;
742 sizeTotal.y += outerheight-innerheight;
743
744 sizeTotal.x += MacGetLeftBorderSize() + MacGetRightBorderSize() ;
745 sizeTotal.y += MacGetTopBorderSize() + MacGetBottomBorderSize() ;
746
747 return sizeTotal;
748 }
749
750 // Get size *available for subwindows* i.e. excluding menu bar etc.
751 void wxWindowMac::DoGetClientSize( int *x, int *y ) const
752 {
753 int ww, hh;
754
755 int left, top;
756
757 m_peer->GetContentArea( left, top, ww, hh );
758 #if wxUSE_SCROLLBAR
759 if (m_hScrollBar && m_hScrollBar->IsShown() )
760 hh -= m_hScrollBar->GetSize().y ;
761
762 if (m_vScrollBar && m_vScrollBar->IsShown() )
763 ww -= m_vScrollBar->GetSize().x ;
764
765 #endif
766 if (x)
767 *x = ww;
768 if (y)
769 *y = hh;
770 }
771
772 bool wxWindowMac::SetCursor(const wxCursor& cursor)
773 {
774 if (m_cursor.IsSameAs(cursor))
775 return false;
776
777 if (!cursor.IsOk())
778 {
779 if ( ! wxWindowBase::SetCursor( *wxSTANDARD_CURSOR ) )
780 return false ;
781 }
782 else
783 {
784 if ( ! wxWindowBase::SetCursor( cursor ) )
785 return false ;
786 }
787
788 wxASSERT_MSG( m_cursor.Ok(),
789 wxT("cursor must be valid after call to the base version"));
790
791 if ( GetPeer() != NULL )
792 GetPeer()->SetCursor( m_cursor );
793
794 return true ;
795 }
796
797 #if wxUSE_MENUS
798 bool wxWindowMac::DoPopupMenu(wxMenu *menu, int x, int y)
799 {
800 #ifndef __WXUNIVERSAL__
801 menu->SetInvokingWindow((wxWindow*)this);
802 menu->UpdateUI();
803
804 if ( x == wxDefaultCoord && y == wxDefaultCoord )
805 {
806 wxPoint mouse = wxGetMousePosition();
807 x = mouse.x;
808 y = mouse.y;
809 }
810 else
811 {
812 ClientToScreen( &x , &y ) ;
813 }
814 menu->GetPeer()->PopUp(this, x, y);
815 menu->SetInvokingWindow( NULL );
816 return true;
817 #else
818 // actually this shouldn't be called, because universal is having its own implementation
819 return false;
820 #endif
821 }
822 #endif
823
824 // ----------------------------------------------------------------------------
825 // tooltips
826 // ----------------------------------------------------------------------------
827
828 #if wxUSE_TOOLTIPS
829
830 void wxWindowMac::DoSetToolTip(wxToolTip *tooltip)
831 {
832 wxWindowBase::DoSetToolTip(tooltip);
833
834 if ( m_tooltip )
835 m_tooltip->SetWindow(this);
836
837 if (m_peer)
838 m_peer->SetToolTip(tooltip);
839 }
840
841 #endif
842
843 void wxWindowMac::MacInvalidateBorders()
844 {
845 if ( m_peer == NULL )
846 return ;
847
848 bool vis = IsShownOnScreen() ;
849 if ( !vis )
850 return ;
851
852 int outerBorder = MacGetLeftBorderSize() ;
853
854 if ( m_peer->NeedsFocusRect() )
855 outerBorder += 4 ;
856
857 if ( outerBorder == 0 )
858 return ;
859
860 // now we know that we have something to do at all
861
862 int tx,ty,tw,th;
863
864 m_peer->GetSize( tw, th );
865 m_peer->GetPosition( tx, ty );
866
867 wxRect leftupdate( tx-outerBorder,ty,outerBorder,th );
868 wxRect rightupdate( tx+tw, ty, outerBorder, th );
869 wxRect topupdate( tx-outerBorder, ty-outerBorder, tw + 2 * outerBorder, outerBorder );
870 wxRect bottomupdate( tx-outerBorder, ty + th, tw + 2 * outerBorder, outerBorder );
871
872 if (GetParent()) {
873 GetParent()->m_peer->SetNeedsDisplay(&leftupdate);
874 GetParent()->m_peer->SetNeedsDisplay(&rightupdate);
875 GetParent()->m_peer->SetNeedsDisplay(&topupdate);
876 GetParent()->m_peer->SetNeedsDisplay(&bottomupdate);
877 }
878 }
879
880 void wxWindowMac::DoMoveWindow(int x, int y, int width, int height)
881 {
882 // this is never called for a toplevel window, so we know we have a parent
883 int former_x , former_y , former_w, former_h ;
884
885 // Get true coordinates of former position
886 DoGetPosition( &former_x , &former_y ) ;
887 DoGetSize( &former_w , &former_h ) ;
888
889 wxWindow *parent = GetParent();
890 if ( parent )
891 {
892 wxPoint pt(parent->GetClientAreaOrigin());
893 former_x += pt.x ;
894 former_y += pt.y ;
895 }
896
897 int actualWidth = width ;
898 int actualHeight = height ;
899 int actualX = x;
900 int actualY = y;
901
902 #if 0
903 // min and max sizes are only for sizers, not for explicit size setting
904 if ((m_minWidth != -1) && (actualWidth < m_minWidth))
905 actualWidth = m_minWidth;
906 if ((m_minHeight != -1) && (actualHeight < m_minHeight))
907 actualHeight = m_minHeight;
908 if ((m_maxWidth != -1) && (actualWidth > m_maxWidth))
909 actualWidth = m_maxWidth;
910 if ((m_maxHeight != -1) && (actualHeight > m_maxHeight))
911 actualHeight = m_maxHeight;
912 #endif
913
914 bool doMove = false, doResize = false ;
915
916 if ( actualX != former_x || actualY != former_y )
917 doMove = true ;
918
919 if ( actualWidth != former_w || actualHeight != former_h )
920 doResize = true ;
921
922 if ( doMove || doResize )
923 {
924 // as the borders are drawn outside the native control, we adjust now
925
926 wxRect bounds( wxPoint( actualX + MacGetLeftBorderSize() ,actualY + MacGetTopBorderSize() ),
927 wxSize( actualWidth - (MacGetLeftBorderSize() + MacGetRightBorderSize()) ,
928 actualHeight - (MacGetTopBorderSize() + MacGetBottomBorderSize()) ) ) ;
929
930 if ( parent && !parent->IsTopLevel() )
931 {
932 bounds.Offset( -parent->MacGetLeftBorderSize(), -parent->MacGetTopBorderSize() );
933 }
934
935 MacInvalidateBorders() ;
936
937 m_cachedClippedRectValid = false ;
938
939 m_peer->Move( bounds.x, bounds.y, bounds.width, bounds.height);
940
941 wxWindowMac::MacSuperChangedPosition() ; // like this only children will be notified
942
943 MacInvalidateBorders() ;
944
945 MacRepositionScrollBars() ;
946 if ( doMove )
947 {
948 wxPoint point(actualX, actualY);
949 wxMoveEvent event(point, m_windowId);
950 event.SetEventObject(this);
951 HandleWindowEvent(event) ;
952 }
953
954 if ( doResize )
955 {
956 MacRepositionScrollBars() ;
957 wxSize size(actualWidth, actualHeight);
958 wxSizeEvent event(size, m_windowId);
959 event.SetEventObject(this);
960 HandleWindowEvent(event);
961 }
962 }
963 }
964
965 wxSize wxWindowMac::DoGetBestSize() const
966 {
967 if ( m_macIsUserPane || IsTopLevel() )
968 {
969 return wxWindowBase::DoGetBestSize() ;
970 }
971 else
972 {
973 wxRect r ;
974
975 m_peer->GetBestRect(&r);
976
977 if ( r.GetWidth() == 0 && r.GetHeight() == 0 )
978 {
979 r.x =
980 r.y = 0 ;
981 r.width =
982 r.height = 16 ;
983
984 #if wxUSE_SCROLLBAR
985 if ( IsKindOf( CLASSINFO( wxScrollBar ) ) )
986 {
987 r.height = 16 ;
988 }
989 else
990 #endif
991 #if wxUSE_SPINBTN
992 if ( IsKindOf( CLASSINFO( wxSpinButton ) ) )
993 {
994 r.height = 24 ;
995 }
996 else
997 #endif
998 {
999 // return wxWindowBase::DoGetBestSize() ;
1000 }
1001 }
1002
1003 int bestWidth = r.width + MacGetLeftBorderSize() +
1004 MacGetRightBorderSize();
1005 int bestHeight = r.height + MacGetTopBorderSize() +
1006 MacGetBottomBorderSize();
1007 if ( bestHeight < 10 )
1008 bestHeight = 13 ;
1009
1010 return wxSize(bestWidth, bestHeight);
1011 }
1012 }
1013
1014 // set the size of the window: if the dimensions are positive, just use them,
1015 // but if any of them is equal to -1, it means that we must find the value for
1016 // it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
1017 // which case -1 is a valid value for x and y)
1018 //
1019 // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
1020 // the width/height to best suit our contents, otherwise we reuse the current
1021 // width/height
1022 void wxWindowMac::DoSetSize(int x, int y, int width, int height, int sizeFlags)
1023 {
1024 // get the current size and position...
1025 int currentX, currentY;
1026 int currentW, currentH;
1027
1028 GetPosition(&currentX, &currentY);
1029 GetSize(&currentW, &currentH);
1030
1031 // ... and don't do anything (avoiding flicker) if it's already ok
1032 if ( x == currentX && y == currentY &&
1033 width == currentW && height == currentH && ( height != -1 && width != -1 ) )
1034 {
1035 // TODO: REMOVE
1036 MacRepositionScrollBars() ; // we might have a real position shift
1037
1038 if (sizeFlags & wxSIZE_FORCE_EVENT)
1039 {
1040 wxSizeEvent event( wxSize(width,height), GetId() );
1041 event.SetEventObject( this );
1042 HandleWindowEvent( event );
1043 }
1044
1045 return;
1046 }
1047
1048 if ( !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
1049 {
1050 if ( x == wxDefaultCoord )
1051 x = currentX;
1052 if ( y == wxDefaultCoord )
1053 y = currentY;
1054 }
1055
1056 AdjustForParentClientOrigin( x, y, sizeFlags );
1057
1058 wxSize size = wxDefaultSize;
1059 if ( width == wxDefaultCoord )
1060 {
1061 if ( sizeFlags & wxSIZE_AUTO_WIDTH )
1062 {
1063 size = DoGetBestSize();
1064 width = size.x;
1065 }
1066 else
1067 {
1068 // just take the current one
1069 width = currentW;
1070 }
1071 }
1072
1073 if ( height == wxDefaultCoord )
1074 {
1075 if ( sizeFlags & wxSIZE_AUTO_HEIGHT )
1076 {
1077 if ( size.x == wxDefaultCoord )
1078 size = DoGetBestSize();
1079 // else: already called DoGetBestSize() above
1080
1081 height = size.y;
1082 }
1083 else
1084 {
1085 // just take the current one
1086 height = currentH;
1087 }
1088 }
1089
1090 DoMoveWindow( x, y, width, height );
1091 }
1092
1093 wxPoint wxWindowMac::GetClientAreaOrigin() const
1094 {
1095 int left,top,width,height;
1096 m_peer->GetContentArea( left , top , width , height);
1097 return wxPoint( left + MacGetLeftBorderSize() , top + MacGetTopBorderSize() );
1098 }
1099
1100 void wxWindowMac::DoSetClientSize(int clientwidth, int clientheight)
1101 {
1102 if ( clientwidth != wxDefaultCoord || clientheight != wxDefaultCoord )
1103 {
1104 int currentclientwidth , currentclientheight ;
1105 int currentwidth , currentheight ;
1106
1107 GetClientSize( &currentclientwidth , &currentclientheight ) ;
1108 GetSize( &currentwidth , &currentheight ) ;
1109
1110 DoSetSize( wxDefaultCoord , wxDefaultCoord , currentwidth + clientwidth - currentclientwidth ,
1111 currentheight + clientheight - currentclientheight , wxSIZE_USE_EXISTING ) ;
1112 }
1113 }
1114
1115 void wxWindowMac::SetLabel(const wxString& title)
1116 {
1117 if ( title == m_label )
1118 return;
1119
1120 m_label = title ;
1121
1122 InvalidateBestSize();
1123
1124 if ( m_peer && m_peer->IsOk() )
1125 m_peer->SetLabel( wxStripMenuCodes(m_label, wxStrip_Mnemonics), GetFont().GetEncoding() ) ;
1126
1127 // do not trigger refreshes upon invisible and possible partly created objects
1128 if ( IsShownOnScreen() )
1129 Refresh() ;
1130 }
1131
1132 wxString wxWindowMac::GetLabel() const
1133 {
1134 return m_label ;
1135 }
1136
1137 bool wxWindowMac::Show(bool show)
1138 {
1139 if ( !wxWindowBase::Show(show) )
1140 return false;
1141
1142 if ( m_peer )
1143 m_peer->SetVisibility( show ) ;
1144
1145 #ifdef __WXOSX_IPHONE__
1146 // only when there's no native event support
1147 if ( !IsTopLevel() )
1148 #endif
1149 {
1150 wxShowEvent eventShow(GetId(), show);
1151 eventShow.SetEventObject(this);
1152
1153 HandleWindowEvent(eventShow);
1154 }
1155
1156 return true;
1157 }
1158
1159 bool wxWindowMac::OSXShowWithEffect(bool show,
1160 wxShowEffect effect,
1161 unsigned timeout)
1162 {
1163 if ( effect == wxSHOW_EFFECT_NONE ||
1164 !m_peer || !m_peer->ShowWithEffect(show, effect, timeout) )
1165 return Show(show);
1166
1167 return true;
1168 }
1169
1170 void wxWindowMac::DoEnable(bool enable)
1171 {
1172 m_peer->Enable( enable ) ;
1173 MacInvalidateBorders();
1174 }
1175
1176 //
1177 // status change notifications
1178 //
1179
1180 void wxWindowMac::MacVisibilityChanged()
1181 {
1182 }
1183
1184 void wxWindowMac::MacHiliteChanged()
1185 {
1186 }
1187
1188 void wxWindowMac::MacEnabledStateChanged()
1189 {
1190 OnEnabled( m_peer->IsEnabled() );
1191 }
1192
1193 //
1194 // status queries on the inherited window's state
1195 //
1196
1197 bool wxWindowMac::MacIsReallyEnabled()
1198 {
1199 return m_peer->IsEnabled() ;
1200 }
1201
1202 bool wxWindowMac::MacIsReallyHilited()
1203 {
1204 #if wxOSX_USE_CARBON
1205 return m_peer->IsActive();
1206 #else
1207 return true; // TODO
1208 #endif
1209 }
1210
1211 int wxWindowMac::GetCharHeight() const
1212 {
1213 wxCoord height;
1214 GetTextExtent( wxT("g") , NULL , &height , NULL , NULL , NULL );
1215
1216 return height;
1217 }
1218
1219 int wxWindowMac::GetCharWidth() const
1220 {
1221 wxCoord width;
1222 GetTextExtent( wxT("g") , &width , NULL , NULL , NULL , NULL );
1223
1224 return width;
1225 }
1226
1227 void wxWindowMac::DoGetTextExtent(const wxString& str,
1228 int *x, int *y,
1229 int *descent,
1230 int *externalLeading,
1231 const wxFont *theFont) const
1232 {
1233 const wxFont *fontToUse = theFont;
1234 wxFont tempFont;
1235 if ( !fontToUse )
1236 {
1237 tempFont = GetFont();
1238 fontToUse = &tempFont;
1239 }
1240
1241 wxGraphicsContext* ctx = wxGraphicsContext::Create();
1242 ctx->SetFont( *fontToUse, *wxBLACK );
1243
1244 wxDouble h , d , e , w;
1245 ctx->GetTextExtent( str, &w, &h, &d, &e );
1246
1247 delete ctx;
1248
1249 if ( externalLeading )
1250 *externalLeading = (wxCoord)(e+0.5);
1251 if ( descent )
1252 *descent = (wxCoord)(d+0.5);
1253 if ( x )
1254 *x = (wxCoord)(w+0.5);
1255 if ( y )
1256 *y = (wxCoord)(h+0.5);
1257 }
1258
1259 /*
1260 * Rect is given in client coordinates, for further reading, read wxTopLevelWindowMac::InvalidateRect
1261 * we always intersect with the entire window, not only with the client area
1262 */
1263
1264 void wxWindowMac::Refresh(bool WXUNUSED(eraseBack), const wxRect *rect)
1265 {
1266 if ( m_peer == NULL )
1267 return ;
1268
1269 if ( !IsShownOnScreen() )
1270 return ;
1271
1272 m_peer->SetNeedsDisplay( rect ) ;
1273 }
1274
1275 void wxWindowMac::DoFreeze()
1276 {
1277 #if wxOSX_USE_CARBON
1278 if ( m_peer && m_peer->IsOk() )
1279 m_peer->SetDrawingEnabled( false ) ;
1280 #endif
1281 }
1282
1283 void wxWindowMac::DoThaw()
1284 {
1285 #if wxOSX_USE_CARBON
1286 if ( m_peer && m_peer->IsOk() )
1287 {
1288 m_peer->SetDrawingEnabled( true ) ;
1289 m_peer->InvalidateWithChildren() ;
1290 }
1291 #endif
1292 }
1293
1294 wxWindow *wxGetActiveWindow()
1295 {
1296 // actually this is a windows-only concept
1297 return NULL;
1298 }
1299
1300 // Coordinates relative to the window
1301 void wxWindowMac::WarpPointer(int x_pos, int y_pos)
1302 {
1303 #if wxOSX_USE_COCOA_OR_CARBON
1304 int x = x_pos;
1305 int y = y_pos;
1306 DoClientToScreen(&x, &y);
1307 CGPoint cgpoint = CGPointMake( x, y );
1308 CGWarpMouseCursorPosition( cgpoint );
1309
1310 // At least GTK sends a mouse moved event after WarpMouse
1311 wxMouseEvent event(wxEVT_MOTION);
1312 event.m_x = x_pos;
1313 event.m_y = y_pos;
1314 wxMouseState mState = ::wxGetMouseState();
1315
1316 event.m_altDown = mState.AltDown();
1317 event.m_controlDown = mState.ControlDown();
1318 event.m_leftDown = mState.LeftIsDown();
1319 event.m_middleDown = mState.MiddleIsDown();
1320 event.m_rightDown = mState.RightIsDown();
1321 event.m_metaDown = mState.MetaDown();
1322 event.m_shiftDown = mState.ShiftDown();
1323 event.SetId(GetId());
1324 event.SetEventObject(this);
1325 GetEventHandler()->ProcessEvent(event);
1326 #endif
1327 }
1328
1329 int wxWindowMac::GetScrollPos(int orient) const
1330 {
1331 #if wxUSE_SCROLLBAR
1332 if ( orient == wxHORIZONTAL )
1333 {
1334 if ( m_hScrollBar )
1335 return m_hScrollBar->GetThumbPosition() ;
1336 }
1337 else
1338 {
1339 if ( m_vScrollBar )
1340 return m_vScrollBar->GetThumbPosition() ;
1341 }
1342 #endif
1343 return 0;
1344 }
1345
1346 // This now returns the whole range, not just the number
1347 // of positions that we can scroll.
1348 int wxWindowMac::GetScrollRange(int orient) const
1349 {
1350 #if wxUSE_SCROLLBAR
1351 if ( orient == wxHORIZONTAL )
1352 {
1353 if ( m_hScrollBar )
1354 return m_hScrollBar->GetRange() ;
1355 }
1356 else
1357 {
1358 if ( m_vScrollBar )
1359 return m_vScrollBar->GetRange() ;
1360 }
1361 #endif
1362 return 0;
1363 }
1364
1365 int wxWindowMac::GetScrollThumb(int orient) const
1366 {
1367 #if wxUSE_SCROLLBAR
1368 if ( orient == wxHORIZONTAL )
1369 {
1370 if ( m_hScrollBar )
1371 return m_hScrollBar->GetThumbSize() ;
1372 }
1373 else
1374 {
1375 if ( m_vScrollBar )
1376 return m_vScrollBar->GetThumbSize() ;
1377 }
1378 #endif
1379 return 0;
1380 }
1381
1382 void wxWindowMac::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh))
1383 {
1384 #if wxUSE_SCROLLBAR
1385 if ( orient == wxHORIZONTAL )
1386 {
1387 if ( m_hScrollBar )
1388 m_hScrollBar->SetThumbPosition( pos ) ;
1389 }
1390 else
1391 {
1392 if ( m_vScrollBar )
1393 m_vScrollBar->SetThumbPosition( pos ) ;
1394 }
1395 #endif
1396 }
1397
1398 void
1399 wxWindowMac::AlwaysShowScrollbars(bool hflag, bool vflag)
1400 {
1401 bool needVisibilityUpdate = false;
1402
1403 if ( m_hScrollBarAlwaysShown != hflag )
1404 {
1405 m_hScrollBarAlwaysShown = hflag;
1406 needVisibilityUpdate = true;
1407 }
1408
1409 if ( m_vScrollBarAlwaysShown != vflag )
1410 {
1411 m_vScrollBarAlwaysShown = vflag;
1412 needVisibilityUpdate = true;
1413 }
1414
1415 if ( needVisibilityUpdate )
1416 DoUpdateScrollbarVisibility();
1417 }
1418
1419 //
1420 // we draw borders and grow boxes, are already set up and clipped in the current port / cgContextRef
1421 // our own window origin is at leftOrigin/rightOrigin
1422 //
1423
1424 void wxWindowMac::MacPaintGrowBox()
1425 {
1426 if ( IsTopLevel() )
1427 return ;
1428
1429 #if wxUSE_SCROLLBAR
1430 if ( MacHasScrollBarCorner() )
1431 {
1432 #if 0
1433 CGContextRef cgContext = (CGContextRef) MacGetCGContextRef() ;
1434 wxASSERT( cgContext ) ;
1435
1436 int tx,ty,tw,th;
1437
1438 m_peer->GetSize( tw, th );
1439 m_peer->GetPosition( tx, ty );
1440
1441 Rect rect = { ty,tx, ty+th, tx+tw };
1442
1443
1444 int size = m_hScrollBar ? m_hScrollBar->GetSize().y : ( m_vScrollBar ? m_vScrollBar->GetSize().x : MAC_SCROLLBAR_SIZE ) ;
1445 CGRect cgrect = CGRectMake( rect.right - size , rect.bottom - size , size , size ) ;
1446 CGContextSaveGState( cgContext );
1447
1448 if ( m_backgroundColour.Ok() )
1449 {
1450 CGContextSetFillColorWithColor( cgContext, m_backgroundColour.GetCGColor() );
1451 }
1452 else
1453 {
1454 CGContextSetRGBFillColor( cgContext, (CGFloat) 1.0, (CGFloat)1.0 ,(CGFloat) 1.0 , (CGFloat)1.0 );
1455 }
1456 CGContextFillRect( cgContext, cgrect );
1457 CGContextRestoreGState( cgContext );
1458 #else
1459 if (m_growBox)
1460 {
1461 if ( m_backgroundColour.Ok() )
1462 m_growBox->SetBackgroundColour(m_backgroundColour);
1463 else
1464 m_growBox->SetBackgroundColour(*wxWHITE);
1465 }
1466 #endif
1467 }
1468
1469 #endif
1470 }
1471
1472 void wxWindowMac::MacPaintBorders( int WXUNUSED(leftOrigin) , int WXUNUSED(rightOrigin) )
1473 {
1474 if ( IsTopLevel() )
1475 return ;
1476
1477 bool hasFocus = m_peer->NeedsFocusRect() && m_peer->HasFocus() ;
1478
1479 // back to the surrounding frame rectangle
1480 int tx,ty,tw,th;
1481
1482 m_peer->GetSize( tw, th );
1483 m_peer->GetPosition( tx, ty );
1484
1485 Rect rect = { ty,tx, ty+th, tx+tw };
1486
1487 #if wxOSX_USE_COCOA_OR_CARBON
1488
1489 InsetRect( &rect, -1 , -1 ) ;
1490
1491 {
1492 CGRect cgrect = CGRectMake( rect.left , rect.top , rect.right - rect.left ,
1493 rect.bottom - rect.top ) ;
1494
1495 CGContextRef cgContext = (CGContextRef) GetParent()->MacGetCGContextRef() ;
1496 wxASSERT( cgContext ) ;
1497
1498 if ( m_peer->NeedsFrame() )
1499 {
1500 HIThemeFrameDrawInfo info ;
1501 memset( &info, 0 , sizeof(info) ) ;
1502
1503 info.version = 0 ;
1504 info.kind = 0 ;
1505 info.state = IsEnabled() ? kThemeStateActive : kThemeStateInactive ;
1506 info.isFocused = hasFocus ;
1507
1508 if ( HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER) || HasFlag(wxDOUBLE_BORDER) )
1509 {
1510 info.kind = kHIThemeFrameTextFieldSquare ;
1511 HIThemeDrawFrame( &cgrect , &info , cgContext , kHIThemeOrientationNormal ) ;
1512 }
1513 else if ( HasFlag(wxSIMPLE_BORDER) )
1514 {
1515 info.kind = kHIThemeFrameListBox ;
1516 HIThemeDrawFrame( &cgrect , &info , cgContext , kHIThemeOrientationNormal ) ;
1517 }
1518 }
1519
1520 if ( hasFocus )
1521 {
1522 HIThemeDrawFocusRect( &cgrect , true , cgContext , kHIThemeOrientationNormal ) ;
1523 }
1524 }
1525 #endif // wxOSX_USE_COCOA_OR_CARBON
1526 }
1527
1528 void wxWindowMac::RemoveChild( wxWindowBase *child )
1529 {
1530 #if wxUSE_SCROLLBAR
1531 if ( child == m_hScrollBar )
1532 m_hScrollBar = NULL ;
1533 if ( child == m_vScrollBar )
1534 m_vScrollBar = NULL ;
1535 if ( child == m_growBox )
1536 m_growBox = NULL ;
1537 #endif
1538 wxWindowBase::RemoveChild( child ) ;
1539 }
1540
1541 void wxWindowMac::DoUpdateScrollbarVisibility()
1542 {
1543 #if wxUSE_SCROLLBAR
1544 bool triggerSizeEvent = false;
1545
1546 if ( m_hScrollBar )
1547 {
1548 bool showHScrollBar = m_hScrollBarAlwaysShown || m_hScrollBar->IsNeeded();
1549
1550 if ( m_hScrollBar->IsShown() != showHScrollBar )
1551 {
1552 m_hScrollBar->Show( showHScrollBar );
1553 triggerSizeEvent = true;
1554 }
1555 }
1556
1557 if ( m_vScrollBar)
1558 {
1559 bool showVScrollBar = m_vScrollBarAlwaysShown || m_vScrollBar->IsNeeded();
1560
1561 if ( m_vScrollBar->IsShown() != showVScrollBar )
1562 {
1563 m_vScrollBar->Show( showVScrollBar ) ;
1564 triggerSizeEvent = true;
1565 }
1566 }
1567
1568 MacRepositionScrollBars() ;
1569 if ( triggerSizeEvent )
1570 {
1571 wxSizeEvent event(GetSize(), m_windowId);
1572 event.SetEventObject(this);
1573 HandleWindowEvent(event);
1574 }
1575 #endif
1576 }
1577
1578 // New function that will replace some of the above.
1579 void wxWindowMac::SetScrollbar(int orient, int pos, int thumb,
1580 int range, bool refresh)
1581 {
1582 #if wxUSE_SCROLLBAR
1583 if ( orient == wxHORIZONTAL && m_hScrollBar )
1584 m_hScrollBar->SetScrollbar(pos, thumb, range, thumb, refresh);
1585 else if ( orient == wxVERTICAL && m_vScrollBar )
1586 m_vScrollBar->SetScrollbar(pos, thumb, range, thumb, refresh);
1587
1588 DoUpdateScrollbarVisibility();
1589 #endif
1590 }
1591
1592 // Does a physical scroll
1593 void wxWindowMac::ScrollWindow(int dx, int dy, const wxRect *rect)
1594 {
1595 if ( dx == 0 && dy == 0 )
1596 return ;
1597
1598 int width , height ;
1599 GetClientSize( &width , &height ) ;
1600
1601 {
1602 wxRect scrollrect( MacGetLeftBorderSize() , MacGetTopBorderSize() , width , height ) ;
1603 if ( rect )
1604 scrollrect.Intersect( *rect ) ;
1605 // as the native control might be not a 0/0 wx window coordinates, we have to offset
1606 scrollrect.Offset( -MacGetLeftBorderSize() , -MacGetTopBorderSize() ) ;
1607
1608 m_peer->ScrollRect( &scrollrect, dx, dy );
1609 }
1610
1611 wxWindowMac *child;
1612 int x, y, w, h;
1613 for (wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); node; node = node->GetNext())
1614 {
1615 child = node->GetData();
1616 if (child == NULL)
1617 continue;
1618
1619 if (child->IsTopLevel())
1620 continue;
1621
1622 if ( !IsClientAreaChild(child) )
1623 continue;
1624
1625 child->GetPosition( &x, &y );
1626 child->GetSize( &w, &h );
1627 if (rect)
1628 {
1629 wxRect rc( x, y, w, h );
1630 if (rect->Intersects( rc ))
1631 child->SetSize( x + dx, y + dy, w, h, wxSIZE_AUTO|wxSIZE_ALLOW_MINUS_ONE );
1632 }
1633 else
1634 {
1635 child->SetSize( x + dx, y + dy, w, h, wxSIZE_AUTO|wxSIZE_ALLOW_MINUS_ONE );
1636 }
1637 }
1638 }
1639
1640 void wxWindowMac::MacOnScroll( wxScrollEvent &event )
1641 {
1642 #if wxUSE_SCROLLBAR
1643 if ( event.GetEventObject() == m_vScrollBar || event.GetEventObject() == m_hScrollBar )
1644 {
1645 wxScrollWinEvent wevent;
1646 wevent.SetPosition(event.GetPosition());
1647 wevent.SetOrientation(event.GetOrientation());
1648 wevent.SetEventObject(this);
1649
1650 if (event.GetEventType() == wxEVT_SCROLL_TOP)
1651 wevent.SetEventType( wxEVT_SCROLLWIN_TOP );
1652 else if (event.GetEventType() == wxEVT_SCROLL_BOTTOM)
1653 wevent.SetEventType( wxEVT_SCROLLWIN_BOTTOM );
1654 else if (event.GetEventType() == wxEVT_SCROLL_LINEUP)
1655 wevent.SetEventType( wxEVT_SCROLLWIN_LINEUP );
1656 else if (event.GetEventType() == wxEVT_SCROLL_LINEDOWN)
1657 wevent.SetEventType( wxEVT_SCROLLWIN_LINEDOWN );
1658 else if (event.GetEventType() == wxEVT_SCROLL_PAGEUP)
1659 wevent.SetEventType( wxEVT_SCROLLWIN_PAGEUP );
1660 else if (event.GetEventType() == wxEVT_SCROLL_PAGEDOWN)
1661 wevent.SetEventType( wxEVT_SCROLLWIN_PAGEDOWN );
1662 else if (event.GetEventType() == wxEVT_SCROLL_THUMBTRACK)
1663 wevent.SetEventType( wxEVT_SCROLLWIN_THUMBTRACK );
1664 else if (event.GetEventType() == wxEVT_SCROLL_THUMBRELEASE)
1665 wevent.SetEventType( wxEVT_SCROLLWIN_THUMBRELEASE );
1666
1667 HandleWindowEvent(wevent);
1668 }
1669 #endif
1670 }
1671
1672 wxWindow *wxWindowBase::DoFindFocus()
1673 {
1674 return wxFindWindowFromWXWidget(wxWidgetImpl::FindFocus());
1675 }
1676
1677 void wxWindowMac::OnInternalIdle()
1678 {
1679 // This calls the UI-update mechanism (querying windows for
1680 // menu/toolbar/control state information)
1681 if (wxUpdateUIEvent::CanUpdate(this) && IsShownOnScreen())
1682 UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
1683 }
1684
1685 // Raise the window to the top of the Z order
1686 void wxWindowMac::Raise()
1687 {
1688 m_peer->Raise();
1689 }
1690
1691 // Lower the window to the bottom of the Z order
1692 void wxWindowMac::Lower()
1693 {
1694 m_peer->Lower();
1695 }
1696
1697 // static wxWindow *gs_lastWhich = NULL;
1698
1699 bool wxWindowMac::MacSetupCursor( const wxPoint& pt )
1700 {
1701 // first trigger a set cursor event
1702
1703 wxPoint clientorigin = GetClientAreaOrigin() ;
1704 wxSize clientsize = GetClientSize() ;
1705 wxCursor cursor ;
1706 if ( wxRect2DInt( clientorigin.x , clientorigin.y , clientsize.x , clientsize.y ).Contains( wxPoint2DInt( pt ) ) )
1707 {
1708 wxSetCursorEvent event( pt.x , pt.y );
1709
1710 bool processedEvtSetCursor = HandleWindowEvent(event);
1711 if ( processedEvtSetCursor && event.HasCursor() )
1712 {
1713 cursor = event.GetCursor() ;
1714 }
1715 else
1716 {
1717 // the test for processedEvtSetCursor is here to prevent using m_cursor
1718 // if the user code caught EVT_SET_CURSOR() and returned nothing from
1719 // it - this is a way to say that our cursor shouldn't be used for this
1720 // point
1721 if ( !processedEvtSetCursor && m_cursor.Ok() )
1722 cursor = m_cursor ;
1723
1724 if ( !wxIsBusy() && !GetParent() )
1725 cursor = *wxSTANDARD_CURSOR ;
1726 }
1727
1728 if ( cursor.Ok() )
1729 cursor.MacInstall() ;
1730 }
1731
1732 return cursor.Ok() ;
1733 }
1734
1735 wxString wxWindowMac::MacGetToolTipString( wxPoint &WXUNUSED(pt) )
1736 {
1737 #if wxUSE_TOOLTIPS
1738 if ( m_tooltip )
1739 return m_tooltip->GetTip() ;
1740 #endif
1741
1742 return wxEmptyString ;
1743 }
1744
1745 void wxWindowMac::ClearBackground()
1746 {
1747 Refresh() ;
1748 Update() ;
1749 }
1750
1751 void wxWindowMac::Update()
1752 {
1753 wxNonOwnedWindow* top = MacGetTopLevelWindow();
1754 if (top)
1755 top->Update() ;
1756 }
1757
1758 wxNonOwnedWindow* wxWindowMac::MacGetTopLevelWindow() const
1759 {
1760 wxWindowMac *iter = (wxWindowMac*)this ;
1761
1762 while ( iter )
1763 {
1764 if ( iter->IsTopLevel() )
1765 {
1766 wxTopLevelWindow* toplevel = wxDynamicCast(iter,wxTopLevelWindow);
1767 if ( toplevel )
1768 return toplevel;
1769 #if wxUSE_POPUPWIN
1770 wxPopupWindow* popupwin = wxDynamicCast(iter,wxPopupWindow);
1771 if ( popupwin )
1772 return popupwin;
1773 #endif
1774 }
1775 iter = iter->GetParent() ;
1776 }
1777
1778 return NULL ;
1779 }
1780
1781 const wxRect& wxWindowMac::MacGetClippedClientRect() const
1782 {
1783 MacUpdateClippedRects() ;
1784
1785 return m_cachedClippedClientRect ;
1786 }
1787
1788 const wxRect& wxWindowMac::MacGetClippedRect() const
1789 {
1790 MacUpdateClippedRects() ;
1791
1792 return m_cachedClippedRect ;
1793 }
1794
1795 const wxRect&wxWindowMac:: MacGetClippedRectWithOuterStructure() const
1796 {
1797 MacUpdateClippedRects() ;
1798
1799 return m_cachedClippedRectWithOuterStructure ;
1800 }
1801
1802 const wxRegion& wxWindowMac::MacGetVisibleRegion( bool includeOuterStructures )
1803 {
1804 static wxRegion emptyrgn ;
1805
1806 if ( !m_isBeingDeleted && IsShownOnScreen() )
1807 {
1808 MacUpdateClippedRects() ;
1809 if ( includeOuterStructures )
1810 return m_cachedClippedRegionWithOuterStructure ;
1811 else
1812 return m_cachedClippedRegion ;
1813 }
1814 else
1815 {
1816 return emptyrgn ;
1817 }
1818 }
1819
1820 void wxWindowMac::MacUpdateClippedRects() const
1821 {
1822 #if wxOSX_USE_CARBON
1823 if ( m_cachedClippedRectValid )
1824 return ;
1825
1826 // includeOuterStructures is true if we try to draw somthing like a focus ring etc.
1827 // also a window dc uses this, in this case we only clip in the hierarchy for hard
1828 // borders like a scrollwindow, splitter etc otherwise we end up in a paranoia having
1829 // to add focus borders everywhere
1830
1831 Rect rIncludingOuterStructures ;
1832
1833 int tx,ty,tw,th;
1834
1835 m_peer->GetSize( tw, th );
1836 m_peer->GetPosition( tx, ty );
1837
1838 Rect r = { ty,tx, ty+th, tx+tw };
1839
1840 r.left -= MacGetLeftBorderSize() ;
1841 r.top -= MacGetTopBorderSize() ;
1842 r.bottom += MacGetBottomBorderSize() ;
1843 r.right += MacGetRightBorderSize() ;
1844
1845 r.right -= r.left ;
1846 r.bottom -= r.top ;
1847 r.left = 0 ;
1848 r.top = 0 ;
1849
1850 rIncludingOuterStructures = r ;
1851 InsetRect( &rIncludingOuterStructures , -4 , -4 ) ;
1852
1853 wxRect cl = GetClientRect() ;
1854 Rect rClient = { cl.y , cl.x , cl.y + cl.height , cl.x + cl.width } ;
1855
1856 int x , y ;
1857 wxSize size ;
1858 const wxWindow* child = (wxWindow*) this ;
1859 const wxWindow* parent = NULL ;
1860
1861 while ( !child->IsTopLevel() && ( parent = child->GetParent() ) != NULL )
1862 {
1863 if ( parent->MacIsChildOfClientArea(child) )
1864 {
1865 size = parent->GetClientSize() ;
1866 wxPoint origin = parent->GetClientAreaOrigin() ;
1867 x = origin.x ;
1868 y = origin.y ;
1869 }
1870 else
1871 {
1872 // this will be true for scrollbars, toolbars etc.
1873 size = parent->GetSize() ;
1874 y = parent->MacGetTopBorderSize() ;
1875 x = parent->MacGetLeftBorderSize() ;
1876 size.x -= parent->MacGetLeftBorderSize() + parent->MacGetRightBorderSize() ;
1877 size.y -= parent->MacGetTopBorderSize() + parent->MacGetBottomBorderSize() ;
1878 }
1879
1880 parent->MacWindowToRootWindow( &x, &y ) ;
1881 MacRootWindowToWindow( &x , &y ) ;
1882
1883 Rect rparent = { y , x , y + size.y , x + size.x } ;
1884
1885 // the wxwindow and client rects will always be clipped
1886 SectRect( &r , &rparent , &r ) ;
1887 SectRect( &rClient , &rparent , &rClient ) ;
1888
1889 // the structure only at 'hard' borders
1890 if ( parent->MacClipChildren() ||
1891 ( parent->GetParent() && parent->GetParent()->MacClipGrandChildren() ) )
1892 {
1893 SectRect( &rIncludingOuterStructures , &rparent , &rIncludingOuterStructures ) ;
1894 }
1895
1896 child = parent ;
1897 }
1898
1899 m_cachedClippedRect = wxRect( r.left , r.top , r.right - r.left , r.bottom - r.top ) ;
1900 m_cachedClippedClientRect = wxRect( rClient.left , rClient.top ,
1901 rClient.right - rClient.left , rClient.bottom - rClient.top ) ;
1902 m_cachedClippedRectWithOuterStructure = wxRect(
1903 rIncludingOuterStructures.left , rIncludingOuterStructures.top ,
1904 rIncludingOuterStructures.right - rIncludingOuterStructures.left ,
1905 rIncludingOuterStructures.bottom - rIncludingOuterStructures.top ) ;
1906
1907 m_cachedClippedRegionWithOuterStructure = wxRegion( m_cachedClippedRectWithOuterStructure ) ;
1908 m_cachedClippedRegion = wxRegion( m_cachedClippedRect ) ;
1909 m_cachedClippedClientRegion = wxRegion( m_cachedClippedClientRect ) ;
1910
1911 m_cachedClippedRectValid = true ;
1912 #endif
1913 }
1914
1915 /*
1916 This function must not change the updatergn !
1917 */
1918 bool wxWindowMac::MacDoRedraw( long time )
1919 {
1920 bool handled = false ;
1921
1922 wxRegion formerUpdateRgn = m_updateRegion;
1923 wxRegion clientUpdateRgn = formerUpdateRgn;
1924
1925 const wxRect clientRect = GetClientRect();
1926
1927 clientUpdateRgn.Intersect(clientRect);
1928
1929 // first send an erase event to the entire update area
1930 const wxBackgroundStyle bgStyle = GetBackgroundStyle();
1931 switch ( bgStyle )
1932 {
1933 case wxBG_STYLE_ERASE:
1934 case wxBG_STYLE_SYSTEM:
1935 case wxBG_STYLE_COLOUR:
1936 {
1937 // for the toplevel window this really is the entire area for
1938 // all the others only their client area, otherwise they might
1939 // be drawing with full alpha and eg put blue into the grow-box
1940 // area of a scrolled window (scroll sample)
1941 wxWindowDC dc(this);
1942 if ( IsTopLevel() )
1943 dc.SetDeviceClippingRegion(formerUpdateRgn);
1944 else
1945 dc.SetDeviceClippingRegion(clientUpdateRgn);
1946
1947 if ( bgStyle == wxBG_STYLE_ERASE )
1948 {
1949 wxEraseEvent eevent( GetId(), &dc );
1950 eevent.SetEventObject( this );
1951 if ( ProcessWindowEvent( eevent ) )
1952 break;
1953 }
1954
1955 if ( UseBgCol() )
1956 {
1957 dc.SetBackground(GetBackgroundColour());
1958 dc.Clear();
1959 }
1960 }
1961 break;
1962
1963 case wxBG_STYLE_PAINT:
1964 case wxBG_STYLE_TRANSPARENT:
1965 // nothing to do, user-defined EVT_PAINT handler will overwrite the
1966 // entire window client area
1967 break;
1968
1969 default:
1970 wxFAIL_MSG( "unsupported background style" );
1971 }
1972
1973 // as this is a full window, shouldn't be necessary anymore
1974 // MacPaintGrowBox();
1975
1976 // calculate a client-origin version of the update rgn and set
1977 // m_updateRegion to that
1978 clientUpdateRgn.Offset(-clientRect.GetPosition());
1979 m_updateRegion = clientUpdateRgn ;
1980
1981 if ( !m_updateRegion.Empty() )
1982 {
1983 // paint the window itself
1984
1985 wxPaintEvent event(GetId());
1986 event.SetTimestamp(time);
1987 event.SetEventObject(this);
1988 handled = HandleWindowEvent(event);
1989 }
1990
1991 m_updateRegion = formerUpdateRgn;
1992 return handled;
1993 }
1994
1995 void wxWindowMac::MacPaintChildrenBorders()
1996 {
1997 // now we cannot rely on having its borders drawn by a window itself, as it does not
1998 // get the updateRgn wide enough to always do so, so we do it from the parent
1999 // this would also be the place to draw any custom backgrounds for native controls
2000 // in Composited windowing
2001 wxPoint clientOrigin = GetClientAreaOrigin() ;
2002
2003 wxWindowMac *child;
2004 int x, y, w, h;
2005 for (wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); node; node = node->GetNext())
2006 {
2007 child = node->GetData();
2008 if (child == NULL)
2009 continue;
2010 #if wxUSE_SCROLLBAR
2011 if (child == m_vScrollBar)
2012 continue;
2013 if (child == m_hScrollBar)
2014 continue;
2015 if (child == m_growBox)
2016 continue;
2017 #endif
2018 if (child->IsTopLevel())
2019 continue;
2020 if (!child->IsShown())
2021 continue;
2022
2023 // only draw those in the update region (add a safety margin of 10 pixels for shadow effects
2024
2025 child->GetPosition( &x, &y );
2026 child->GetSize( &w, &h );
2027
2028 if ( m_updateRegion.Contains(clientOrigin.x+x-10, clientOrigin.y+y-10, w+20, h+20) )
2029 {
2030 // paint custom borders
2031 wxNcPaintEvent eventNc( child->GetId() );
2032 eventNc.SetEventObject( child );
2033 if ( !child->HandleWindowEvent( eventNc ) )
2034 {
2035 child->MacPaintBorders(0, 0) ;
2036 }
2037 }
2038 }
2039 }
2040
2041
2042 WXWindow wxWindowMac::MacGetTopLevelWindowRef() const
2043 {
2044 wxNonOwnedWindow* tlw = MacGetTopLevelWindow();
2045 return tlw ? tlw->GetWXWindow() : NULL ;
2046 }
2047
2048 bool wxWindowMac::MacHasScrollBarCorner() const
2049 {
2050 #if wxUSE_SCROLLBAR
2051 /* Returns whether the scroll bars in a wxScrolledWindow should be
2052 * shortened. Scroll bars should be shortened if either:
2053 *
2054 * - both scroll bars are visible, or
2055 *
2056 * - there is a resize box in the parent frame's corner and this
2057 * window shares the bottom and right edge with the parent
2058 * frame.
2059 */
2060
2061 if ( m_hScrollBar == NULL && m_vScrollBar == NULL )
2062 return false;
2063
2064 if ( ( m_hScrollBar && m_hScrollBar->IsShown() )
2065 && ( m_vScrollBar && m_vScrollBar->IsShown() ) )
2066 {
2067 // Both scroll bars visible
2068 return true;
2069 }
2070 else
2071 {
2072 wxPoint thisWindowBottomRight = GetScreenRect().GetBottomRight();
2073
2074 for ( const wxWindow *win = (wxWindow*)this; win; win = win->GetParent() )
2075 {
2076 const wxFrame *frame = wxDynamicCast( win, wxFrame ) ;
2077 if ( frame )
2078 {
2079 if ( frame->GetWindowStyleFlag() & wxRESIZE_BORDER )
2080 {
2081 // Parent frame has resize handle
2082 wxPoint frameBottomRight = frame->GetScreenRect().GetBottomRight();
2083
2084 // Note: allow for some wiggle room here as wxMac's
2085 // window rect calculations seem to be imprecise
2086 if ( abs( thisWindowBottomRight.x - frameBottomRight.x ) <= 2
2087 && abs( thisWindowBottomRight.y - frameBottomRight.y ) <= 2 )
2088 {
2089 // Parent frame has resize handle and shares
2090 // right bottom corner
2091 return true ;
2092 }
2093 else
2094 {
2095 // Parent frame has resize handle but doesn't
2096 // share right bottom corner
2097 return false ;
2098 }
2099 }
2100 else
2101 {
2102 // Parent frame doesn't have resize handle
2103 return false ;
2104 }
2105 }
2106 }
2107
2108 // No parent frame found
2109 return false ;
2110 }
2111 #else
2112 return false;
2113 #endif
2114 }
2115
2116 void wxWindowMac::MacCreateScrollBars( long style )
2117 {
2118 #if wxUSE_SCROLLBAR
2119 wxASSERT_MSG( m_vScrollBar == NULL && m_hScrollBar == NULL , wxT("attempt to create window twice") ) ;
2120
2121 if ( style & ( wxVSCROLL | wxHSCROLL ) )
2122 {
2123 int scrlsize = MAC_SCROLLBAR_SIZE ;
2124 if ( GetWindowVariant() == wxWINDOW_VARIANT_SMALL || GetWindowVariant() == wxWINDOW_VARIANT_MINI )
2125 {
2126 scrlsize = MAC_SMALL_SCROLLBAR_SIZE ;
2127 }
2128
2129 int adjust = MacHasScrollBarCorner() ? scrlsize - 1: 0 ;
2130 int width, height ;
2131 GetClientSize( &width , &height ) ;
2132
2133 wxPoint vPoint(width - scrlsize, 0) ;
2134 wxSize vSize(scrlsize, height - adjust) ;
2135 wxPoint hPoint(0, height - scrlsize) ;
2136 wxSize hSize(width - adjust, scrlsize) ;
2137
2138 // we have to set the min size to a smaller value, otherwise they cannot get smaller (InitialSize sets MinSize)
2139 if ( style & wxVSCROLL )
2140 {
2141 m_vScrollBar = new wxScrollBar((wxWindow*)this, wxID_ANY, vPoint, vSize , wxVERTICAL);
2142 m_vScrollBar->SetMinSize( wxDefaultSize );
2143 }
2144
2145 if ( style & wxHSCROLL )
2146 {
2147 m_hScrollBar = new wxScrollBar((wxWindow*)this, wxID_ANY, hPoint, hSize , wxHORIZONTAL);
2148 m_hScrollBar->SetMinSize( wxDefaultSize );
2149 }
2150
2151 wxPoint gPoint(width - scrlsize, height - scrlsize);
2152 wxSize gSize(scrlsize, scrlsize);
2153 m_growBox = new wxBlindPlateWindow((wxWindow *)this, wxID_ANY, gPoint, gSize, 0);
2154 }
2155
2156 // because the create does not take into account the client area origin
2157 // we might have a real position shift
2158 MacRepositionScrollBars() ;
2159 #endif
2160 }
2161
2162 bool wxWindowMac::MacIsChildOfClientArea( const wxWindow* child ) const
2163 {
2164 bool result = ((child == NULL)
2165 #if wxUSE_SCROLLBAR
2166 || ((child != m_hScrollBar) && (child != m_vScrollBar) && (child != m_growBox))
2167 #endif
2168 );
2169
2170 return result ;
2171 }
2172
2173 void wxWindowMac::MacRepositionScrollBars()
2174 {
2175 #if wxUSE_SCROLLBAR
2176 if ( !m_hScrollBar && !m_vScrollBar )
2177 return ;
2178
2179 int scrlsize = m_hScrollBar ? m_hScrollBar->GetSize().y : ( m_vScrollBar ? m_vScrollBar->GetSize().x : MAC_SCROLLBAR_SIZE ) ;
2180 int adjust = MacHasScrollBarCorner() ? scrlsize - 1 : 0 ;
2181
2182 // get real client area
2183 int width, height ;
2184 GetSize( &width , &height );
2185
2186 width -= MacGetLeftBorderSize() + MacGetRightBorderSize();
2187 height -= MacGetTopBorderSize() + MacGetBottomBorderSize();
2188
2189 wxPoint vPoint( width - scrlsize, 0 ) ;
2190 wxSize vSize( scrlsize, height - adjust ) ;
2191 wxPoint hPoint( 0 , height - scrlsize ) ;
2192 wxSize hSize( width - adjust, scrlsize ) ;
2193
2194 if ( m_vScrollBar )
2195 m_vScrollBar->SetSize( vPoint.x , vPoint.y, vSize.x, vSize.y , wxSIZE_ALLOW_MINUS_ONE );
2196 if ( m_hScrollBar )
2197 m_hScrollBar->SetSize( hPoint.x , hPoint.y, hSize.x, hSize.y, wxSIZE_ALLOW_MINUS_ONE );
2198 if ( m_growBox )
2199 {
2200 if ( MacHasScrollBarCorner() )
2201 {
2202 m_growBox->SetSize( width - scrlsize, height - scrlsize, wxDefaultCoord, wxDefaultCoord, wxSIZE_USE_EXISTING );
2203 if ( !m_growBox->IsShown() )
2204 m_growBox->Show();
2205 }
2206 else
2207 {
2208 if ( m_growBox->IsShown() )
2209 m_growBox->Hide();
2210 }
2211 }
2212 #endif
2213 }
2214
2215 bool wxWindowMac::AcceptsFocus() const
2216 {
2217 if ( MacIsUserPane() )
2218 return wxWindowBase::AcceptsFocus();
2219 else
2220 return m_peer->CanFocus();
2221 }
2222
2223 void wxWindowMac::MacSuperChangedPosition()
2224 {
2225 // only window-absolute structures have to be moved i.e. controls
2226
2227 m_cachedClippedRectValid = false ;
2228
2229 wxWindowMac *child;
2230 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
2231 while ( node )
2232 {
2233 child = node->GetData();
2234 child->MacSuperChangedPosition() ;
2235
2236 node = node->GetNext();
2237 }
2238 }
2239
2240 void wxWindowMac::MacTopLevelWindowChangedPosition()
2241 {
2242 // only screen-absolute structures have to be moved i.e. glcanvas
2243
2244 wxWindowMac *child;
2245 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
2246 while ( node )
2247 {
2248 child = node->GetData();
2249 child->MacTopLevelWindowChangedPosition() ;
2250
2251 node = node->GetNext();
2252 }
2253 }
2254
2255 long wxWindowMac::MacGetLeftBorderSize() const
2256 {
2257 if ( IsTopLevel() )
2258 return 0 ;
2259
2260 SInt32 border = 0 ;
2261
2262 if ( m_peer && m_peer->NeedsFrame() )
2263 {
2264 if (HasFlag(wxRAISED_BORDER) || HasFlag( wxSUNKEN_BORDER) || HasFlag(wxDOUBLE_BORDER))
2265 {
2266 #if wxOSX_USE_COCOA_OR_CARBON
2267 // this metric is only the 'outset' outside the simple frame rect
2268 GetThemeMetric( kThemeMetricEditTextFrameOutset , &border ) ;
2269 border += 1;
2270 #else
2271 border += 2;
2272 #endif
2273 }
2274 else if (HasFlag(wxSIMPLE_BORDER))
2275 {
2276 #if wxOSX_USE_COCOA_OR_CARBON
2277 // this metric is only the 'outset' outside the simple frame rect
2278 GetThemeMetric( kThemeMetricListBoxFrameOutset , &border ) ;
2279 border += 1;
2280 #else
2281 border += 1;
2282 #endif
2283 }
2284 }
2285
2286 return border ;
2287 }
2288
2289 long wxWindowMac::MacGetRightBorderSize() const
2290 {
2291 // they are all symmetric in mac themes
2292 return MacGetLeftBorderSize() ;
2293 }
2294
2295 long wxWindowMac::MacGetTopBorderSize() const
2296 {
2297 // they are all symmetric in mac themes
2298 return MacGetLeftBorderSize() ;
2299 }
2300
2301 long wxWindowMac::MacGetBottomBorderSize() const
2302 {
2303 // they are all symmetric in mac themes
2304 return MacGetLeftBorderSize() ;
2305 }
2306
2307 long wxWindowMac::MacRemoveBordersFromStyle( long style )
2308 {
2309 return style & ~wxBORDER_MASK ;
2310 }
2311
2312 // Find the wxWindowMac at the current mouse position, returning the mouse
2313 // position.
2314 wxWindow * wxFindWindowAtPointer( wxPoint& pt )
2315 {
2316 pt = wxGetMousePosition();
2317 wxWindowMac* found = wxFindWindowAtPoint(pt);
2318
2319 return (wxWindow*) found;
2320 }
2321
2322 // Get the current mouse position.
2323 wxPoint wxGetMousePosition()
2324 {
2325 int x, y;
2326
2327 wxGetMousePosition( &x, &y );
2328
2329 return wxPoint(x, y);
2330 }
2331
2332 void wxWindowMac::OnMouseEvent( wxMouseEvent &event )
2333 {
2334 if ( event.GetEventType() == wxEVT_RIGHT_DOWN )
2335 {
2336 // copied from wxGTK : CS
2337 // VZ: shouldn't we move this to base class then?
2338
2339 // generate a "context menu" event: this is similar to wxEVT_RIGHT_DOWN
2340 // except that:
2341 //
2342 // (a) it's a command event and so is propagated to the parent
2343 // (b) under MSW it can be generated from kbd too
2344 // (c) it uses screen coords (because of (a))
2345 wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU,
2346 this->GetId(),
2347 this->ClientToScreen(event.GetPosition()));
2348 evtCtx.SetEventObject(this);
2349 if ( ! HandleWindowEvent(evtCtx) )
2350 event.Skip() ;
2351 }
2352 else
2353 {
2354 event.Skip() ;
2355 }
2356 }
2357
2358 void wxWindowMac::TriggerScrollEvent( wxEventType WXUNUSED(scrollEvent) )
2359 {
2360 }
2361
2362 Rect wxMacGetBoundsForControl( wxWindowMac* window , const wxPoint& pos , const wxSize &size , bool adjustForOrigin )
2363 {
2364 int x, y, w, h ;
2365
2366 window->MacGetBoundsForControl( pos , size , x , y, w, h , adjustForOrigin ) ;
2367 Rect bounds = { y, x, y + h, x + w };
2368
2369 return bounds ;
2370 }
2371
2372 bool wxWindowMac::OSXHandleClicked( double WXUNUSED(timestampsec) )
2373 {
2374 return false;
2375 }
2376
2377 wxInt32 wxWindowMac::MacControlHit(WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF event )
2378 {
2379 #if wxOSX_USE_COCOA_OR_CARBON
2380 if ( OSXHandleClicked( GetEventTime((EventRef)event) ) )
2381 return noErr;
2382
2383 return eventNotHandledErr ;
2384 #else
2385 return 0;
2386 #endif
2387 }
2388
2389 bool wxWindowMac::Reparent(wxWindowBase *newParentBase)
2390 {
2391 wxWindowMac *newParent = (wxWindowMac *)newParentBase;
2392 if ( !wxWindowBase::Reparent(newParent) )
2393 return false;
2394
2395 m_peer->RemoveFromParent();
2396 m_peer->Embed( GetParent()->GetPeer() );
2397
2398 MacChildAdded();
2399 return true;
2400 }
2401
2402 bool wxWindowMac::SetTransparent(wxByte alpha)
2403 {
2404 SetBackgroundStyle(wxBG_STYLE_TRANSPARENT);
2405
2406 if ( alpha != m_macAlpha )
2407 {
2408 m_macAlpha = alpha ;
2409 Refresh() ;
2410 }
2411 return true ;
2412 }
2413
2414
2415 bool wxWindowMac::CanSetTransparent()
2416 {
2417 return true ;
2418 }
2419
2420 wxByte wxWindowMac::GetTransparent() const
2421 {
2422 return m_macAlpha ;
2423 }
2424
2425 bool wxWindowMac::IsShownOnScreen() const
2426 {
2427 if ( m_peer && m_peer->IsOk() )
2428 {
2429 bool peerVis = m_peer->IsVisible();
2430 bool wxVis = wxWindowBase::IsShownOnScreen();
2431 if( peerVis != wxVis )
2432 {
2433 // CS : put a breakpoint here to investigate differences
2434 // between native an wx visibilities
2435 // the only place where I've encountered them until now
2436 // are the hiding/showing sequences where the vis-changed event is
2437 // first sent to the innermost control, while wx does things
2438 // from the outmost control
2439 wxVis = wxWindowBase::IsShownOnScreen();
2440 return wxVis;
2441 }
2442
2443 return m_peer->IsVisible();
2444 }
2445 return wxWindowBase::IsShownOnScreen();
2446 }
2447
2448 bool wxWindowMac::OSXHandleKeyEvent( wxKeyEvent& event )
2449 {
2450 bool handled = HandleWindowEvent( event ) ;
2451 if ( handled && event.GetSkipped() )
2452 handled = false ;
2453
2454 #if wxUSE_ACCEL
2455 if ( !handled && event.GetEventType() == wxEVT_KEY_DOWN)
2456 {
2457 wxWindow *ancestor = this;
2458 while (ancestor)
2459 {
2460 int command = ancestor->GetAcceleratorTable()->GetCommand( event );
2461 if (command != -1)
2462 {
2463 wxEvtHandler * const handler = ancestor->GetEventHandler();
2464
2465 wxCommandEvent command_event( wxEVT_COMMAND_MENU_SELECTED, command );
2466 handled = handler->ProcessEvent( command_event );
2467
2468 if ( !handled )
2469 {
2470 // accelerators can also be used with buttons, try them too
2471 command_event.SetEventType(wxEVT_COMMAND_BUTTON_CLICKED);
2472 handled = handler->ProcessEvent( command_event );
2473 }
2474
2475 break;
2476 }
2477
2478 if (ancestor->IsTopLevel())
2479 break;
2480
2481 ancestor = ancestor->GetParent();
2482 }
2483 }
2484 #endif // wxUSE_ACCEL
2485
2486 return handled ;
2487 }
2488
2489 //
2490 // wxWidgetImpl
2491 //
2492
2493 WX_DECLARE_HASH_MAP(WXWidget, wxWidgetImpl*, wxPointerHash, wxPointerEqual, MacControlMap);
2494
2495 static MacControlMap wxWinMacControlList;
2496
2497 wxWindowMac *wxFindWindowFromWXWidget(WXWidget inControl )
2498 {
2499 wxWidgetImpl* impl = wxWidgetImpl::FindFromWXWidget( inControl );
2500 if ( impl )
2501 return impl->GetWXPeer();
2502
2503 return NULL;
2504 }
2505
2506 wxWidgetImpl *wxWidgetImpl::FindFromWXWidget(WXWidget inControl )
2507 {
2508 MacControlMap::iterator node = wxWinMacControlList.find(inControl);
2509
2510 return (node == wxWinMacControlList.end()) ? NULL : node->second;
2511 }
2512
2513 void wxWidgetImpl::Associate(WXWidget inControl, wxWidgetImpl *impl)
2514 {
2515 // adding NULL ControlRef is (first) surely a result of an error and
2516 // (secondly) breaks native event processing
2517 wxCHECK_RET( inControl != (WXWidget) NULL, wxT("attempt to add a NULL WXWidget to control map") );
2518
2519 wxWinMacControlList[inControl] = impl;
2520 }
2521
2522 void wxWidgetImpl::RemoveAssociations(wxWidgetImpl* impl)
2523 {
2524 // iterate over all the elements in the class
2525 // is the iterator stable ? as we might have two associations pointing to the same wxWindow
2526 // we should go on...
2527
2528 bool found = true ;
2529 while ( found )
2530 {
2531 found = false ;
2532 MacControlMap::iterator it;
2533 for ( it = wxWinMacControlList.begin(); it != wxWinMacControlList.end(); ++it )
2534 {
2535 if ( it->second == impl )
2536 {
2537 wxWinMacControlList.erase(it);
2538 found = true ;
2539 break;
2540 }
2541 }
2542 }
2543 }
2544
2545 IMPLEMENT_ABSTRACT_CLASS( wxWidgetImpl , wxObject )
2546
2547 wxWidgetImpl::wxWidgetImpl( wxWindowMac* peer , bool isRootControl )
2548 {
2549 Init();
2550 m_isRootControl = isRootControl;
2551 m_wxPeer = peer;
2552 m_shouldSendEvents = true;
2553 }
2554
2555 wxWidgetImpl::wxWidgetImpl()
2556 {
2557 Init();
2558 }
2559
2560 wxWidgetImpl::~wxWidgetImpl()
2561 {
2562 }
2563
2564 void wxWidgetImpl::Init()
2565 {
2566 m_isRootControl = false;
2567 m_wxPeer = NULL;
2568 m_needsFocusRect = false;
2569 m_needsFrame = true;
2570 }
2571
2572 void wxWidgetImpl::SetNeedsFocusRect( bool needs )
2573 {
2574 m_needsFocusRect = needs;
2575 }
2576
2577 bool wxWidgetImpl::NeedsFocusRect() const
2578 {
2579 return m_needsFocusRect;
2580 }
2581
2582 void wxWidgetImpl::SetNeedsFrame( bool needs )
2583 {
2584 m_needsFrame = needs;
2585 }
2586
2587 bool wxWidgetImpl::NeedsFrame() const
2588 {
2589 return m_needsFrame;
2590 }