]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/frame.cpp
wxMSW update for CW, wxMac updated
[wxWidgets.git] / src / mac / carbon / frame.cpp
CommitLineData
e9576ca5
SC
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
519cb848
SC
26#include <wx/mac/uma.h>
27
e9576ca5
SC
28extern wxList wxModelessWindows;
29extern wxList wxPendingDelete;
30
31#if !USE_SHARED_LIBRARY
32BEGIN_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)
39END_EVENT_TABLE()
40
41IMPLEMENT_DYNAMIC_CLASS(wxFrame, wxWindow)
42#endif
43
44#if wxUSE_NATIVE_STATUSBAR
45bool wxFrame::m_useNativeStatusBar = TRUE;
46#else
47bool wxFrame::m_useNativeStatusBar = FALSE;
48#endif
49
50wxFrame::wxFrame()
51{
519cb848 52#if wxUSE_TOOLBAR
e9576ca5 53 m_frameToolBar = NULL ;
519cb848 54#endif
e7549107 55
519cb848 56 // in order to be able to give size events on show
e9576ca5
SC
57 m_frameMenuBar = NULL;
58 m_frameStatusBar = NULL;
e9576ca5 59 m_iconized = FALSE;
51abe921 60 m_isShown = FALSE;
e9576ca5
SC
61}
62
63bool 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;
51abe921 77 m_isShown = FALSE;
519cb848
SC
78
79#if wxUSE_TOOLBAR
e9576ca5 80 m_frameToolBar = NULL ;
519cb848 81#endif
e9576ca5
SC
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
519cb848
SC
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 ;
519cb848 150 return TRUE;
e9576ca5
SC
151}
152
153wxFrame::~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 {
519cb848 170 wxTheApp->ExitMainLoop() ;
e9576ca5
SC
171 }
172 }
173
174 wxModelessWindows.DeleteObject(this);
175}
176
e9576ca5
SC
177
178void wxFrame::Iconize(bool iconize)
179{
180 // TODO
181}
182
183// Equivalent to maximize/restore in Windows
184void wxFrame::Maximize(bool maximize)
185{
186 // TODO
187}
188
189bool wxFrame::IsIconized() const
190{
191 // TODO
192 return FALSE;
193}
194
195// Is the frame maximized?
196bool wxFrame::IsMaximized(void) const
197{
198 // TODO
199 return FALSE;
200}
201
e9576ca5
SC
202void wxFrame::SetIcon(const wxIcon& icon)
203{
204 m_icon = icon;
205 // TODO
206}
207
208wxStatusBar *wxFrame::OnCreateStatusBar(int number, long style, wxWindowID id,
209 const wxString& name)
210{
211 wxStatusBar *statusBar = NULL;
212
519cb848 213 statusBar = new wxStatusBar(this, id, wxPoint(0, 0), wxSize(100, 17),
e9576ca5
SC
214 style, name);
215
216 // Set the height according to the font and the border size
519cb848
SC
217 // we shouldn't do this on the mac, because we have to fit the grow box
218 /*
e9576ca5
SC
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
519cb848
SC
229 */
230
e9576ca5
SC
231 statusBar->SetFieldsCount(number);
232 return statusBar;
233}
234
235wxStatusBar* 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
253void 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
260void 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
268void wxFrame::PositionStatusBar()
269{
519cb848
SC
270 if (m_frameStatusBar )
271 {
e9576ca5
SC
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);
519cb848 280 }
e9576ca5
SC
281}
282
283void wxFrame::SetMenuBar(wxMenuBar *menuBar)
284{
285 if (!menuBar)
286 {
287 m_frameMenuBar = NULL;
288 return;
289 }
290
291 m_frameMenuBar = menuBar;
519cb848
SC
292 // TODO : we move this into the app code
293 m_frameMenuBar->MacInstallMenuBar() ;
e9576ca5
SC
294}
295
296void 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.
326void 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
6418cb93
SC
344void wxFrame::OnIdle(wxIdleEvent& WXUNUSED(event) )
345{
346 DoMenuUpdates();
347}
348
349
350// update all menus
351void wxFrame::DoMenuUpdates()
352{
353 wxMenuBar* bar = GetMenuBar();
354
355 if ( bar != NULL )
356 {
357 int nCount = bar->GetMenuCount();
358 for (int n = 0; n < nCount; n++)
359 DoMenuUpdates(bar->GetMenu(n), (wxWindow*) NULL);
360 }
361}
362
363// update a menu and all submenus recursively
364void wxFrame::DoMenuUpdates(wxMenu* menu, wxWindow* WXUNUSED(focusWin))
365{
366 wxEvtHandler* evtHandler = GetEventHandler();
367 wxMenuItemList::Node* node = menu->GetMenuItems().GetFirst();
368 while (node)
369 {
370 wxMenuItem* item = node->GetData();
371 if ( !item->IsSeparator() )
372 {
373 wxWindowID id = item->GetId();
374 wxUpdateUIEvent event(id);
375 event.SetEventObject( this );
376
377 if (evtHandler->ProcessEvent(event))
378 {
379 if (event.GetSetText())
380 menu->SetLabel(id, event.GetText());
381 if (event.GetSetChecked())
382 menu->Check(id, event.GetChecked());
383 if (event.GetSetEnabled())
384 menu->Enable(id, event.GetEnabled());
385 }
386
387 if (item->GetSubMenu())
388 DoMenuUpdates(item->GetSubMenu(), (wxWindow*) NULL);
389 }
390 node = node->GetNext();
391 }
392}
393
e9576ca5
SC
394void wxFrame::OnSize(wxSizeEvent& event)
395{
396 // if we're using constraints - do use them
397 #if wxUSE_CONSTRAINTS
398 if ( GetAutoLayout() ) {
399 Layout();
400 return;
401 }
402 #endif
403
404 // do we have _exactly_ one child?
405 wxWindow *child = NULL;
406 for ( wxNode *node = GetChildren().First(); node; node = node->Next() )
407 {
408 wxWindow *win = (wxWindow *)node->Data();
409 if ( !win->IsKindOf(CLASSINFO(wxFrame)) &&
410 !win->IsKindOf(CLASSINFO(wxDialog)) &&
519cb848
SC
411 (win != GetStatusBar())
412#if wxUSE_TOOLBAR
413 &&
414 (win != GetToolBar())
415#endif
416 )
e9576ca5
SC
417 {
418 if ( child )
419 return; // it's our second subwindow - nothing to do
420 child = win;
421 }
422 }
423
424 if ( child ) {
425 // we have exactly one child - set it's size to fill the whole frame
426 int clientW, clientH;
427 GetClientSize(&clientW, &clientH);
428
429 int x = 0;
430 int y = 0;
431
432 child->SetSize(x, y, clientW, clientH);
433 }
434}
435
436// Default activation behaviour - set the focus for the first child
437// subwindow found.
438void wxFrame::OnActivate(wxActivateEvent& event)
439{
440 for(wxNode *node = GetChildren().First(); node; node = node->Next())
441 {
442 // Find a child that's a subwindow, but not a dialog box.
443 wxWindow *child = (wxWindow *)node->Data();
444 if (!child->IsKindOf(CLASSINFO(wxFrame)) &&
445 !child->IsKindOf(CLASSINFO(wxDialog)))
446 {
447 child->SetFocus();
448 return;
449 }
450 }
451}
452
e3065973 453// The default implementation for the close window event.
e9576ca5
SC
454void wxFrame::OnCloseWindow(wxCloseEvent& event)
455{
e3065973 456 this->Destroy();
e9576ca5
SC
457}
458
459// Destroy the window (delayed, if a managed window)
460bool wxFrame::Destroy()
461{
462 if (!wxPendingDelete.Member(this))
463 wxPendingDelete.Append(this);
464 return TRUE;
465}
466
467// Default menu selection behaviour - display a help string
468void wxFrame::OnMenuHighlight(wxMenuEvent& event)
469{
470 if (GetStatusBar())
471 {
472 if (event.GetMenuId() == -1)
473 SetStatusText("");
474 else
475 {
476 wxMenuBar *menuBar = GetMenuBar();
477 if (menuBar)
478 {
479 wxString helpString(menuBar->GetHelpString(event.GetMenuId()));
480 if (helpString != "")
481 SetStatusText(helpString);
482 }
483 }
484 }
485}
486
487wxMenuBar *wxFrame::GetMenuBar() const
488{
489 return m_frameMenuBar;
490}
491
e9576ca5
SC
492
493// Call this to simulate a menu command
494void wxFrame::Command(int id)
495{
496 ProcessCommand(id);
497}
498
499void wxFrame::ProcessCommand(int id)
500{
519cb848 501 wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, id);
e9576ca5
SC
502 commandEvent.SetInt( id );
503 commandEvent.SetEventObject( this );
504
505 wxMenuBar *bar = GetMenuBar() ;
506 if (!bar)
507 return;
508
509/* TODO: check the menu item if required
510 wxMenuItem *item = bar->FindItemForId(id) ;
511 if (item && item->IsCheckable())
512 {
513 bar->Check(id,!bar->Checked(id)) ;
514 }
515*/
516
519cb848 517 GetEventHandler()->ProcessEvent(commandEvent);
e9576ca5
SC
518}
519
520// Checks if there is a toolbar, and returns the first free client position
521wxPoint wxFrame::GetClientAreaOrigin() const
522{
523 wxPoint pt(0, 0);
519cb848 524#if wxUSE_TOOLBAR
e9576ca5
SC
525 if (GetToolBar())
526 {
527 int w, h;
528 GetToolBar()->GetSize(& w, & h);
529
530 if (GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL)
531 {
532 pt.x += w;
533 }
534 else
535 {
536 pt.y += h;
537 }
538 }
519cb848 539#endif
e9576ca5
SC
540 return pt;
541}
542
7c74e7fe 543void wxFrame::DoGetClientSize(int *x, int *y) const
e9576ca5 544{
7c74e7fe 545 wxWindow::DoGetClientSize( x , y ) ;
519cb848
SC
546
547 if ( GetStatusBar() )
548 {
549 int statusX, statusY;
550 GetStatusBar()->GetClientSize(&statusX, &statusY);
551 *y -= statusY;
552 }
553
554 wxPoint pt(GetClientAreaOrigin());
555 *y -= pt.y;
556 *x -= pt.x;
e9576ca5
SC
557}
558
519cb848 559void wxFrame::DoSetClientSize(int clientwidth, int clientheight)
e9576ca5 560{
519cb848
SC
561 int currentclientwidth , currentclientheight ;
562 int currentwidth , currentheight ;
563
564 GetClientSize( &currentclientwidth , &currentclientheight ) ;
565 GetSize( &currentwidth , &currentheight ) ;
566
567 // find the current client size
568
569 // Find the difference between the entire window (title bar and all)
570 // and the client area; add this to the new client size to move the
571 // window
572
573 DoSetSize( -1 , -1 , currentwidth + clientwidth - currentclientwidth ,
574 currentheight + clientheight - currentclientheight , wxSIZE_USE_EXISTING ) ;
e9576ca5
SC
575}
576
519cb848
SC
577
578#if wxUSE_TOOLBAR
e9576ca5
SC
579wxToolBar* wxFrame::CreateToolBar(long style, wxWindowID id, const wxString& name)
580{
581 wxCHECK_MSG( m_frameToolBar == NULL, FALSE,
582 "recreating toolbar in wxFrame" );
583
584 wxToolBar* toolBar = OnCreateToolBar(style, id, name);
585 if (toolBar)
586 {
587 SetToolBar(toolBar);
588 PositionToolBar();
589 return toolBar;
590 }
591 else
592 {
593 return NULL;
594 }
595}
596
597wxToolBar* wxFrame::OnCreateToolBar(long style, wxWindowID id, const wxString& name)
598{
599 return new wxToolBar(this, id, wxDefaultPosition, wxDefaultSize, style, name);
600}
601
602void wxFrame::PositionToolBar()
603{
604 int cw, ch;
605
606 // TODO: we actually need to use the low-level client size, before
607 // the toolbar/status bar were added.
608 // So DEFINITELY replace the line below with something appropriate.
609
519cb848
SC
610 // GetClientSize(& cw, &ch);
611
612 cw = m_width ;
613 ch = m_height ;
e9576ca5
SC
614
615 if ( GetStatusBar() )
616 {
617 int statusX, statusY;
618 GetStatusBar()->GetClientSize(&statusX, &statusY);
619 ch -= statusY;
620 }
621
622 if (GetToolBar())
623 {
624 int tw, th;
625 GetToolBar()->GetSize(& tw, & th);
626
627 if (GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL)
628 {
629 // Use the 'real' position. wxSIZE_NO_ADJUSTMENTS
630 // means, pretend we don't have toolbar/status bar, so we
631 // have the original client size.
632 GetToolBar()->SetSize(0, 0, tw, ch, wxSIZE_NO_ADJUSTMENTS);
633 }
634 else
635 {
636 // Use the 'real' position
637 GetToolBar()->SetSize(0, 0, cw, th, wxSIZE_NO_ADJUSTMENTS);
638 }
639 }
640}
519cb848 641#endif