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