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