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