]> git.saurik.com Git - wxWidgets.git/blob - src/mac/frame.cpp
mac adaptions
[wxWidgets.git] / src / mac / frame.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: frame.cpp
3 // Purpose: wxFrame
4 // Author: AUTHOR
5 // Modified by:
6 // Created: ??/??/98
7 // RCS-ID: $Id$
8 // Copyright: (c) AUTHOR
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "frame.h"
14 #endif
15
16 #include "wx/frame.h"
17 #include "wx/statusbr.h"
18 #include "wx/toolbar.h"
19 #include "wx/menuitem.h"
20 #include "wx/menu.h"
21 #include "wx/dcclient.h"
22 #include "wx/dialog.h"
23 #include "wx/settings.h"
24 #include "wx/app.h"
25
26 #include <wx/mac/uma.h>
27
28 extern wxList wxModelessWindows;
29 extern wxList wxPendingDelete;
30
31 #if !USE_SHARED_LIBRARY
32 BEGIN_EVENT_TABLE(wxFrame, wxWindow)
33 EVT_SIZE(wxFrame::OnSize)
34 EVT_ACTIVATE(wxFrame::OnActivate)
35 EVT_MENU_HIGHLIGHT_ALL(wxFrame::OnMenuHighlight)
36 EVT_SYS_COLOUR_CHANGED(wxFrame::OnSysColourChanged)
37 EVT_IDLE(wxFrame::OnIdle)
38 EVT_CLOSE(wxFrame::OnCloseWindow)
39 END_EVENT_TABLE()
40
41 IMPLEMENT_DYNAMIC_CLASS(wxFrame, wxWindow)
42 #endif
43
44 #if wxUSE_NATIVE_STATUSBAR
45 bool wxFrame::m_useNativeStatusBar = TRUE;
46 #else
47 bool wxFrame::m_useNativeStatusBar = FALSE;
48 #endif
49
50 wxFrame::wxFrame()
51 {
52 #if wxUSE_TOOLBAR
53 m_frameToolBar = NULL ;
54 #endif
55
56 // in order to be able to give size events on show
57 m_frameMenuBar = NULL;
58 m_frameStatusBar = NULL;
59 m_iconized = FALSE;
60 }
61
62 bool wxFrame::Create(wxWindow *parent,
63 wxWindowID id,
64 const wxString& title,
65 const wxPoint& pos,
66 const wxSize& size,
67 long style,
68 const wxString& name)
69 {
70 if (!parent)
71 wxTopLevelWindows.Append(this);
72
73 SetName(name);
74 m_windowStyle = style;
75 m_frameMenuBar = NULL;
76
77 #if wxUSE_TOOLBAR
78 m_frameToolBar = NULL ;
79 #endif
80 m_frameStatusBar = NULL;
81
82 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE));
83
84 if ( id > -1 )
85 m_windowId = id;
86 else
87 m_windowId = (int)NewControlId();
88
89 if (parent) parent->AddChild(this);
90
91 wxModelessWindows.Append(this);
92
93 // create frame.
94
95 Rect theBoundsRect;
96
97 m_x = (int)pos.x;
98 m_y = (int)pos.y;
99 if ( m_y < 50 )
100 m_y = 50 ;
101 if ( m_x < 20 )
102 m_x = 20 ;
103
104 m_width = size.x;
105 if (m_width == -1)
106 m_width = 20;
107 m_height = size.y;
108 if (m_height == -1)
109 m_height = 20;
110
111 m_macWindowData = new MacWindowData() ;
112
113 ::SetRect(&theBoundsRect, m_x, m_y, m_x + m_width, m_y + m_height);
114
115 WindowClass wclass = kDocumentWindowClass ;
116 WindowAttributes attr = kWindowNoAttributes ;
117
118 if ( ( m_windowStyle & wxMINIMIZE_BOX ) || ( m_windowStyle & wxMAXIMIZE_BOX ) )
119 {
120 attr |= kWindowFullZoomAttribute ;
121 attr |= kWindowResizableAttribute ;
122 }
123 if ( m_windowStyle & wxSTAY_ON_TOP )
124 {
125 wclass = kFloatingWindowClass ;
126
127 // if ( m_windowStyle & wxCAPTION )
128 // attr |= kHasPaletteTitlebarMask ;
129 }
130 else
131 {
132 }
133 if ( m_windowStyle & wxSYSTEM_MENU )
134 {
135 attr |= kWindowCloseBoxAttribute ;
136 }
137 UMACreateNewWindow( wclass , attr , &theBoundsRect , &m_macWindowData->m_macWindow ) ;
138 wxAssociateWinWithMacWindow( m_macWindowData->m_macWindow , this ) ;
139 wxString label ;
140 if( wxApp::s_macDefaultEncodingIsPC )
141 label = wxMacMakeMacStringFromPC( title ) ;
142 else
143 label = title ;
144 UMASetWTitleC( m_macWindowData->m_macWindow , label ) ;
145 UMACreateRootControl( m_macWindowData->m_macWindow , &m_macWindowData->m_macRootControl ) ;
146 m_macWindowData->m_macWindowBackgroundTheme = kThemeBrushDocumentWindowBackground ;
147 m_macWindowData->m_macFocus = NULL ;
148 return TRUE;
149 }
150
151 wxFrame::~wxFrame()
152 {
153 wxTopLevelWindows.DeleteObject(this);
154
155 if (m_frameStatusBar)
156 delete m_frameStatusBar;
157 if (m_frameMenuBar)
158 delete m_frameMenuBar;
159
160 /* Check if it's the last top-level window */
161
162 if (wxTheApp && (wxTopLevelWindows.Number() == 0))
163 {
164 wxTheApp->SetTopWindow(NULL);
165
166 if (wxTheApp->GetExitOnFrameDelete())
167 {
168 wxTheApp->ExitMainLoop() ;
169 }
170 }
171
172 wxModelessWindows.DeleteObject(this);
173 }
174
175
176 void wxFrame::Iconize(bool iconize)
177 {
178 // TODO
179 }
180
181 // Equivalent to maximize/restore in Windows
182 void wxFrame::Maximize(bool maximize)
183 {
184 // TODO
185 }
186
187 bool wxFrame::IsIconized() const
188 {
189 // TODO
190 return FALSE;
191 }
192
193 // Is the frame maximized?
194 bool wxFrame::IsMaximized(void) const
195 {
196 // TODO
197 return FALSE;
198 }
199
200 void wxFrame::SetIcon(const wxIcon& icon)
201 {
202 m_icon = icon;
203 // TODO
204 }
205
206 wxStatusBar *wxFrame::OnCreateStatusBar(int number, long style, wxWindowID id,
207 const wxString& name)
208 {
209 wxStatusBar *statusBar = NULL;
210
211 statusBar = new wxStatusBar(this, id, wxPoint(0, 0), wxSize(100, 17),
212 style, name);
213
214 // Set the height according to the font and the border size
215 // we shouldn't do this on the mac, because we have to fit the grow box
216 /*
217 wxClientDC dc(statusBar);
218 dc.SetFont(statusBar->GetFont());
219
220 long x, y;
221 dc.GetTextExtent("X", &x, &y);
222
223 int height = (int)( (y * 1.1) + 2* statusBar->GetBorderY());
224
225 statusBar->SetSize(-1, -1, 100, height);
226
227 */
228
229 statusBar->SetFieldsCount(number);
230 return statusBar;
231 }
232
233 wxStatusBar* wxFrame::CreateStatusBar(int number, long style, wxWindowID id,
234 const wxString& name)
235 {
236 // Calling CreateStatusBar twice is an error.
237 wxCHECK_MSG( m_frameStatusBar == NULL, FALSE,
238 "recreating status bar in wxFrame" );
239
240 m_frameStatusBar = OnCreateStatusBar(number, style, id,
241 name);
242 if ( m_frameStatusBar )
243 {
244 PositionStatusBar();
245 return m_frameStatusBar;
246 }
247 else
248 return NULL;
249 }
250
251 void wxFrame::SetStatusText(const wxString& text, int number)
252 {
253 wxCHECK_RET( m_frameStatusBar != NULL, "no statusbar to set text for" );
254
255 m_frameStatusBar->SetStatusText(text, number);
256 }
257
258 void wxFrame::SetStatusWidths(int n, const int widths_field[])
259 {
260 wxCHECK_RET( m_frameStatusBar != NULL, "no statusbar to set widths for" );
261
262 m_frameStatusBar->SetStatusWidths(n, widths_field);
263 PositionStatusBar();
264 }
265
266 void wxFrame::PositionStatusBar()
267 {
268 if (m_frameStatusBar )
269 {
270 int w, h;
271 GetClientSize(&w, &h);
272 int sw, sh;
273 m_frameStatusBar->GetSize(&sw, &sh);
274
275 // Since we wish the status bar to be directly under the client area,
276 // we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS.
277 m_frameStatusBar->SetSize(0, h, w, sh);
278 }
279 }
280
281 void wxFrame::SetMenuBar(wxMenuBar *menuBar)
282 {
283 if (!menuBar)
284 {
285 m_frameMenuBar = NULL;
286 return;
287 }
288
289 m_frameMenuBar = menuBar;
290 // TODO : we move this into the app code
291 m_frameMenuBar->MacInstallMenuBar() ;
292 }
293
294 void wxFrame::Fit()
295 {
296 // Work out max. size
297 wxNode *node = GetChildren().First();
298 int max_width = 0;
299 int max_height = 0;
300 while (node)
301 {
302 // Find a child that's a subwindow, but not a dialog box.
303 wxWindow *win = (wxWindow *)node->Data();
304
305 if (!win->IsKindOf(CLASSINFO(wxFrame)) &&
306 !win->IsKindOf(CLASSINFO(wxDialog)))
307 {
308 int width, height;
309 int x, y;
310 win->GetSize(&width, &height);
311 win->GetPosition(&x, &y);
312
313 if ((x + width) > max_width)
314 max_width = x + width;
315 if ((y + height) > max_height)
316 max_height = y + height;
317 }
318 node = node->Next();
319 }
320 SetClientSize(max_width, max_height);
321 }
322
323 // Responds to colour changes, and passes event on to children.
324 void wxFrame::OnSysColourChanged(wxSysColourChangedEvent& event)
325 {
326 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE));
327 Refresh();
328
329 if ( m_frameStatusBar )
330 {
331 wxSysColourChangedEvent event2;
332 event2.SetEventObject( m_frameStatusBar );
333 m_frameStatusBar->ProcessEvent(event2);
334 }
335
336 // Propagate the event to the non-top-level children
337 wxWindow::OnSysColourChanged(event);
338 }
339
340 // Default resizing behaviour - if only ONE subwindow,
341 // resize to client rectangle size
342 void wxFrame::OnSize(wxSizeEvent& event)
343 {
344 // if we're using constraints - do use them
345 #if wxUSE_CONSTRAINTS
346 if ( GetAutoLayout() ) {
347 Layout();
348 return;
349 }
350 #endif
351
352 // do we have _exactly_ one child?
353 wxWindow *child = NULL;
354 for ( wxNode *node = GetChildren().First(); node; node = node->Next() )
355 {
356 wxWindow *win = (wxWindow *)node->Data();
357 if ( !win->IsKindOf(CLASSINFO(wxFrame)) &&
358 !win->IsKindOf(CLASSINFO(wxDialog)) &&
359 (win != GetStatusBar())
360 #if wxUSE_TOOLBAR
361 &&
362 (win != GetToolBar())
363 #endif
364 )
365 {
366 if ( child )
367 return; // it's our second subwindow - nothing to do
368 child = win;
369 }
370 }
371
372 if ( child ) {
373 // we have exactly one child - set it's size to fill the whole frame
374 int clientW, clientH;
375 GetClientSize(&clientW, &clientH);
376
377 int x = 0;
378 int y = 0;
379
380 child->SetSize(x, y, clientW, clientH);
381 }
382 }
383
384 // Default activation behaviour - set the focus for the first child
385 // subwindow found.
386 void wxFrame::OnActivate(wxActivateEvent& event)
387 {
388 for(wxNode *node = GetChildren().First(); node; node = node->Next())
389 {
390 // Find a child that's a subwindow, but not a dialog box.
391 wxWindow *child = (wxWindow *)node->Data();
392 if (!child->IsKindOf(CLASSINFO(wxFrame)) &&
393 !child->IsKindOf(CLASSINFO(wxDialog)))
394 {
395 child->SetFocus();
396 return;
397 }
398 }
399 }
400
401 // The default implementation for the close window event.
402 void wxFrame::OnCloseWindow(wxCloseEvent& event)
403 {
404 this->Destroy();
405 }
406
407 // Destroy the window (delayed, if a managed window)
408 bool wxFrame::Destroy()
409 {
410 if (!wxPendingDelete.Member(this))
411 wxPendingDelete.Append(this);
412 return TRUE;
413 }
414
415 // Default menu selection behaviour - display a help string
416 void wxFrame::OnMenuHighlight(wxMenuEvent& event)
417 {
418 if (GetStatusBar())
419 {
420 if (event.GetMenuId() == -1)
421 SetStatusText("");
422 else
423 {
424 wxMenuBar *menuBar = GetMenuBar();
425 if (menuBar)
426 {
427 wxString helpString(menuBar->GetHelpString(event.GetMenuId()));
428 if (helpString != "")
429 SetStatusText(helpString);
430 }
431 }
432 }
433 }
434
435 wxMenuBar *wxFrame::GetMenuBar() const
436 {
437 return m_frameMenuBar;
438 }
439
440
441 // Call this to simulate a menu command
442 void wxFrame::Command(int id)
443 {
444 ProcessCommand(id);
445 }
446
447 void wxFrame::ProcessCommand(int id)
448 {
449 wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, id);
450 commandEvent.SetInt( id );
451 commandEvent.SetEventObject( this );
452
453 wxMenuBar *bar = GetMenuBar() ;
454 if (!bar)
455 return;
456
457 /* TODO: check the menu item if required
458 wxMenuItem *item = bar->FindItemForId(id) ;
459 if (item && item->IsCheckable())
460 {
461 bar->Check(id,!bar->Checked(id)) ;
462 }
463 */
464
465 GetEventHandler()->ProcessEvent(commandEvent);
466 }
467
468 // Checks if there is a toolbar, and returns the first free client position
469 wxPoint wxFrame::GetClientAreaOrigin() const
470 {
471 wxPoint pt(0, 0);
472 #if wxUSE_TOOLBAR
473 if (GetToolBar())
474 {
475 int w, h;
476 GetToolBar()->GetSize(& w, & h);
477
478 if (GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL)
479 {
480 pt.x += w;
481 }
482 else
483 {
484 pt.y += h;
485 }
486 }
487 #endif
488 return pt;
489 }
490
491 void wxFrame::GetClientSize(int *x, int *y) const
492 {
493 wxWindow::GetClientSize( x , y ) ;
494
495 if ( GetStatusBar() )
496 {
497 int statusX, statusY;
498 GetStatusBar()->GetClientSize(&statusX, &statusY);
499 *y -= statusY;
500 }
501
502 wxPoint pt(GetClientAreaOrigin());
503 *y -= pt.y;
504 *x -= pt.x;
505 }
506
507 void wxFrame::DoSetClientSize(int clientwidth, int clientheight)
508 {
509 int currentclientwidth , currentclientheight ;
510 int currentwidth , currentheight ;
511
512 GetClientSize( &currentclientwidth , &currentclientheight ) ;
513 GetSize( &currentwidth , &currentheight ) ;
514
515 // find the current client size
516
517 // Find the difference between the entire window (title bar and all)
518 // and the client area; add this to the new client size to move the
519 // window
520
521 DoSetSize( -1 , -1 , currentwidth + clientwidth - currentclientwidth ,
522 currentheight + clientheight - currentclientheight , wxSIZE_USE_EXISTING ) ;
523 }
524
525
526 #if wxUSE_TOOLBAR
527 wxToolBar* wxFrame::CreateToolBar(long style, wxWindowID id, const wxString& name)
528 {
529 wxCHECK_MSG( m_frameToolBar == NULL, FALSE,
530 "recreating toolbar in wxFrame" );
531
532 wxToolBar* toolBar = OnCreateToolBar(style, id, name);
533 if (toolBar)
534 {
535 SetToolBar(toolBar);
536 PositionToolBar();
537 return toolBar;
538 }
539 else
540 {
541 return NULL;
542 }
543 }
544
545 wxToolBar* wxFrame::OnCreateToolBar(long style, wxWindowID id, const wxString& name)
546 {
547 return new wxToolBar(this, id, wxDefaultPosition, wxDefaultSize, style, name);
548 }
549
550 void wxFrame::PositionToolBar()
551 {
552 int cw, ch;
553
554 // TODO: we actually need to use the low-level client size, before
555 // the toolbar/status bar were added.
556 // So DEFINITELY replace the line below with something appropriate.
557
558 // GetClientSize(& cw, &ch);
559
560 cw = m_width ;
561 ch = m_height ;
562
563 if ( GetStatusBar() )
564 {
565 int statusX, statusY;
566 GetStatusBar()->GetClientSize(&statusX, &statusY);
567 ch -= statusY;
568 }
569
570 if (GetToolBar())
571 {
572 int tw, th;
573 GetToolBar()->GetSize(& tw, & th);
574
575 if (GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL)
576 {
577 // Use the 'real' position. wxSIZE_NO_ADJUSTMENTS
578 // means, pretend we don't have toolbar/status bar, so we
579 // have the original client size.
580 GetToolBar()->SetSize(0, 0, tw, ch, wxSIZE_NO_ADJUSTMENTS);
581 }
582 else
583 {
584 // Use the 'real' position
585 GetToolBar()->SetSize(0, 0, cw, th, wxSIZE_NO_ADJUSTMENTS);
586 }
587 }
588 }
589 #endif