]> git.saurik.com Git - wxWidgets.git/blob - src/gtk1/frame.cpp
Corrected hotkeys for MDI menus.
[wxWidgets.git] / src / gtk1 / frame.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: frame.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #ifdef __GNUG__
11 #pragma implementation "frame.h"
12 #endif
13
14 #include "wx/frame.h"
15 #include "wx/dialog.h"
16 #include "wx/control.h"
17 #include "wx/app.h"
18 #include "wx/menu.h"
19 #include "wx/toolbar.h"
20 #include "wx/statusbr.h"
21 #include "wx/dcclient.h"
22
23 #include "glib.h"
24 #include "gdk/gdk.h"
25 #include "gtk/gtk.h"
26 #include "wx/gtk/win_gtk.h"
27 #include "gdk/gdkkeysyms.h"
28
29 //-----------------------------------------------------------------------------
30 // constants
31 //-----------------------------------------------------------------------------
32
33 const int wxMENU_HEIGHT = 27;
34 const int wxSTATUS_HEIGHT = 25;
35 const int wxPLACE_HOLDER = 0;
36
37 //-----------------------------------------------------------------------------
38 // idle system
39 //-----------------------------------------------------------------------------
40
41 extern void wxapp_install_idle_handler();
42 extern bool g_isIdle;
43
44 //-----------------------------------------------------------------------------
45 // data
46 //-----------------------------------------------------------------------------
47
48 extern wxList wxPendingDelete;
49
50 //-----------------------------------------------------------------------------
51 // debug
52 //-----------------------------------------------------------------------------
53
54 #ifdef __WXDEBUG__
55
56 extern void debug_focus_in( GtkWidget* widget, const wxChar* name, const wxChar *window );
57
58 #endif
59
60 //-----------------------------------------------------------------------------
61 // "size_allocate"
62 //-----------------------------------------------------------------------------
63
64 static void gtk_frame_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation* alloc, wxFrame *win )
65 {
66 if (g_isIdle)
67 wxapp_install_idle_handler();
68
69 if (!win->m_hasVMT) return;
70
71 if ((win->m_width != alloc->width) || (win->m_height != alloc->height))
72 {
73 win->m_width = alloc->width;
74 win->m_height = alloc->height;
75 win->UpdateSize();
76 }
77 }
78
79 //-----------------------------------------------------------------------------
80 // "delete_event"
81 //-----------------------------------------------------------------------------
82
83 static gint gtk_frame_delete_callback( GtkWidget *WXUNUSED(widget), GdkEvent *WXUNUSED(event), wxFrame *win )
84 {
85 if (g_isIdle)
86 wxapp_install_idle_handler();
87
88 win->Close();
89
90 return TRUE;
91 }
92
93 //-----------------------------------------------------------------------------
94 // "child_attached" of menu bar
95 //-----------------------------------------------------------------------------
96
97 static void gtk_menu_attached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
98 {
99 if (!win->m_hasVMT) return;
100
101 win->m_menuBarDetached = FALSE;
102 win->UpdateSize();
103 }
104
105 //-----------------------------------------------------------------------------
106 // "child_detached" of menu bar
107 //-----------------------------------------------------------------------------
108
109 static void gtk_menu_detached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
110 {
111 if (!win->m_hasVMT) return;
112
113 win->m_menuBarDetached = TRUE;
114 win->UpdateSize();
115 }
116
117 #if wxUSE_TOOLBAR
118 //-----------------------------------------------------------------------------
119 // "child_attached" of tool bar
120 //-----------------------------------------------------------------------------
121
122 static void gtk_toolbar_attached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
123 {
124 if (!win->m_hasVMT) return;
125
126 win->m_toolBarDetached = FALSE;
127
128 win->UpdateSize();
129 }
130
131 //-----------------------------------------------------------------------------
132 // "child_detached" of tool bar
133 //-----------------------------------------------------------------------------
134
135 static void gtk_toolbar_detached_callback( GtkWidget *widget, GtkWidget *WXUNUSED(child), wxFrame *win )
136 {
137 if (g_isIdle)
138 wxapp_install_idle_handler();
139
140 if (!win->m_hasVMT) return;
141
142 win->m_toolBarDetached = TRUE;
143 win->UpdateSize();
144 }
145 #endif // wxUSE_TOOLBAR
146
147 //-----------------------------------------------------------------------------
148 // "configure_event"
149 //-----------------------------------------------------------------------------
150
151 static gint gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *WXUNUSED(event), wxFrame *win )
152 {
153 if (g_isIdle)
154 wxapp_install_idle_handler();
155
156 if (!win->m_hasVMT) return FALSE;
157
158 int x = 0;
159 int y = 0;
160 gdk_window_get_root_origin( win->m_widget->window, &x, &y );
161
162 win->m_x = x;
163 win->m_y = y;
164
165 wxMoveEvent mevent( wxPoint(win->m_x,win->m_y), win->GetId() );
166 mevent.SetEventObject( win );
167 win->GetEventHandler()->ProcessEvent( mevent );
168
169 return FALSE;
170 }
171
172 //-----------------------------------------------------------------------------
173 // "realize" from m_widget
174 //-----------------------------------------------------------------------------
175
176 /* we cannot MWM hints and icons before the widget has been realized,
177 so we do this directly after realization */
178
179 static gint
180 gtk_frame_realized_callback( GtkWidget *widget, wxFrame *win )
181 {
182 if (g_isIdle)
183 wxapp_install_idle_handler();
184
185 /* all this is for Motif Window Manager "hints" and is supposed to be
186 recognized by other WM as well. not tested. */
187 long decor = (long) GDK_DECOR_BORDER;
188 long func = (long) GDK_FUNC_MOVE;
189
190 if ((win->GetWindowStyle() & wxCAPTION) != 0)
191 decor |= GDK_DECOR_TITLE;
192 if ((win->GetWindowStyle() & wxSYSTEM_MENU) != 0)
193 {
194 decor |= GDK_DECOR_MENU;
195 func |= GDK_FUNC_CLOSE;
196 }
197 if ((win->GetWindowStyle() & wxMINIMIZE_BOX) != 0)
198 {
199 func |= GDK_FUNC_MINIMIZE;
200 decor |= GDK_DECOR_MINIMIZE;
201 }
202 if ((win->GetWindowStyle() & wxMAXIMIZE_BOX) != 0)
203 {
204 func |= GDK_FUNC_MAXIMIZE;
205 decor |= GDK_DECOR_MAXIMIZE;
206 }
207 if ((win->GetWindowStyle() & wxRESIZE_BORDER) != 0)
208 {
209 func |= GDK_FUNC_RESIZE;
210 decor |= GDK_DECOR_RESIZEH;
211 }
212
213
214 gdk_window_set_decorations( win->m_widget->window, (GdkWMDecoration)decor);
215 gdk_window_set_functions( win->m_widget->window, (GdkWMFunction)func);
216
217 /* GTK's shrinking/growing policy */
218 if ((win->GetWindowStyle() & wxRESIZE_BORDER) == 0)
219 gtk_window_set_policy(GTK_WINDOW(win->m_widget), 0, 0, 1);
220 else
221 gtk_window_set_policy(GTK_WINDOW(win->m_widget), 1, 1, 1);
222
223 /* reset the icon */
224 if (win->m_icon != wxNullIcon)
225 {
226 wxIcon icon( win->m_icon );
227 win->m_icon = wxNullIcon;
228 win->SetIcon( icon );
229 }
230
231 /* we set the focus to the child that accepts the focus. this
232 doesn't really have to be done in "realize" but why not? */
233 wxWindowList::Node *node = win->GetChildren().GetFirst();
234 while (node)
235 {
236 wxWindow *child = node->GetData();
237 if (child->AcceptsFocus())
238 {
239 child->SetFocus();
240 break;
241 }
242
243 node = node->GetNext();
244 }
245
246 return FALSE;
247 }
248
249 //-----------------------------------------------------------------------------
250 // InsertChild for wxFrame
251 //-----------------------------------------------------------------------------
252
253 /* Callback for wxFrame. This very strange beast has to be used because
254 * C++ has no virtual methods in a constructor. We have to emulate a
255 * virtual function here as wxWindows requires different ways to insert
256 * a child in container classes. */
257
258 static void wxInsertChildInFrame( wxFrame* parent, wxWindow* child )
259 {
260 if (!parent->m_insertInClientArea)
261 {
262 /* these are outside the client area */
263 wxFrame* frame = (wxFrame*) parent;
264 gtk_myfixed_put( GTK_MYFIXED(frame->m_mainWidget),
265 GTK_WIDGET(child->m_widget),
266 child->m_x,
267 child->m_y,
268 child->m_width,
269 child->m_height );
270
271 #if wxUSE_TOOLBAR
272 /* we connect to these events for recalculating the client area
273 space when the toolbar is floating */
274 if (wxIS_KIND_OF(child,wxToolBar))
275 {
276 wxToolBar *toolBar = (wxToolBar*) child;
277 if (toolBar->GetWindowStyle() & wxTB_DOCKABLE)
278 {
279 gtk_signal_connect( GTK_OBJECT(toolBar->m_widget), "child_attached",
280 GTK_SIGNAL_FUNC(gtk_toolbar_attached_callback), (gpointer)parent );
281
282 gtk_signal_connect( GTK_OBJECT(toolBar->m_widget), "child_detached",
283 GTK_SIGNAL_FUNC(gtk_toolbar_detached_callback), (gpointer)parent );
284 }
285 }
286 #endif // wxUSE_TOOLBAR
287 }
288 else
289 {
290 /* these are inside the client area */
291 gtk_myfixed_put( GTK_MYFIXED(parent->m_wxwindow),
292 GTK_WIDGET(child->m_widget),
293 child->m_x,
294 child->m_y,
295 child->m_width,
296 child->m_height );
297 }
298
299 /* resize on OnInternalIdle */
300 parent->UpdateSize();
301 }
302
303 //-----------------------------------------------------------------------------
304 // wxFrame
305 //-----------------------------------------------------------------------------
306
307 BEGIN_EVENT_TABLE(wxFrame, wxWindow)
308 EVT_SIZE(wxFrame::OnSize)
309 EVT_CLOSE(wxFrame::OnCloseWindow)
310 EVT_MENU_HIGHLIGHT_ALL(wxFrame::OnMenuHighlight)
311 END_EVENT_TABLE()
312
313 IMPLEMENT_DYNAMIC_CLASS(wxFrame,wxWindow)
314
315 void wxFrame::Init()
316 {
317 m_frameMenuBar = (wxMenuBar *) NULL;
318 #if wxUSE_STATUSBAR
319 m_frameStatusBar = (wxStatusBar *) NULL;
320 #endif // wxUSE_STATUSBAR
321 #if wxUSE_TOOLBAR
322 m_frameToolBar = (wxToolBar *) NULL;
323 #endif // wxUSE_TOOLBAR
324 m_sizeSet = FALSE;
325 m_miniEdge = 0;
326 m_miniTitle = 0;
327 m_mainWidget = (GtkWidget*) NULL;
328 m_menuBarDetached = FALSE;
329 m_toolBarDetached = FALSE;
330 m_insertInClientArea = TRUE;
331 }
332
333 wxFrame::wxFrame( wxWindow *parent, wxWindowID id, const wxString &title,
334 const wxPoint &pos, const wxSize &size,
335 long style, const wxString &name )
336 {
337 Init();
338
339 Create( parent, id, title, pos, size, style, name );
340 }
341
342 bool wxFrame::Create( wxWindow *parent, wxWindowID id, const wxString &title,
343 const wxPoint &pos, const wxSize &size,
344 long style, const wxString &name )
345 {
346 wxTopLevelWindows.Append( this );
347
348 m_needParent = FALSE;
349
350 PreCreation( parent, id, pos, size, style, name );
351
352 m_title = title;
353
354 m_insertCallback = (wxInsertChildFunction) wxInsertChildInFrame;
355
356 GtkWindowType win_type = GTK_WINDOW_TOPLEVEL;
357 if (style & wxSIMPLE_BORDER) win_type = GTK_WINDOW_POPUP;
358
359 m_widget = gtk_window_new( win_type );
360
361 if (!name.IsEmpty())
362 gtk_window_set_wmclass( GTK_WINDOW(m_widget), name.mb_str(), name.mb_str() );
363
364 #ifdef __WXDEBUG__
365 debug_focus_in( m_widget, _T("wxFrame::m_widget"), name );
366 #endif
367
368 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
369 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
370
371 gtk_signal_connect( GTK_OBJECT(m_widget), "delete_event",
372 GTK_SIGNAL_FUNC(gtk_frame_delete_callback), (gpointer)this );
373
374 /* m_mainWidget holds the toolbar, the menubar and the client area */
375 m_mainWidget = gtk_myfixed_new();
376 gtk_widget_show( m_mainWidget );
377 GTK_WIDGET_UNSET_FLAGS( m_mainWidget, GTK_CAN_FOCUS );
378 gtk_container_add( GTK_CONTAINER(m_widget), m_mainWidget );
379
380 #ifdef __WXDEBUG__
381 debug_focus_in( m_mainWidget, _T("wxFrame::m_mainWidget"), name );
382 #endif
383
384 /* m_wxwindow only represents the client area without toolbar and menubar */
385 m_wxwindow = gtk_myfixed_new();
386 gtk_widget_show( m_wxwindow );
387 gtk_container_add( GTK_CONTAINER(m_mainWidget), m_wxwindow );
388
389 #ifdef __WXDEBUG__
390 debug_focus_in( m_wxwindow, _T("wxFrame::m_wxwindow"), name );
391 #endif
392
393 /* we donm't allow the frame to get the focus as otherwise
394 the frame will grabit at arbitrary fcous changes. */
395 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
396
397 if (m_parent) m_parent->AddChild( this );
398
399 PostCreation();
400
401 /* we cannot set MWM hints and icons before the widget has
402 been realized, so we do this directly after realization */
403 gtk_signal_connect( GTK_OBJECT(m_widget), "realize",
404 GTK_SIGNAL_FUNC(gtk_frame_realized_callback), (gpointer) this );
405
406 /* the user resized the frame by dragging etc. */
407 gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
408 GTK_SIGNAL_FUNC(gtk_frame_size_callback), (gpointer)this );
409
410 /* the only way to get the window size is to connect to this event */
411 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
412 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
413
414 return TRUE;
415 }
416
417 wxFrame::~wxFrame()
418 {
419 m_isBeingDeleted = TRUE;
420
421 if (m_frameMenuBar) delete m_frameMenuBar;
422 m_frameMenuBar = (wxMenuBar *) NULL;
423
424 #if wxUSE_STATUSBAR
425 if (m_frameStatusBar) delete m_frameStatusBar;
426 m_frameStatusBar = (wxStatusBar *) NULL;
427 #endif // wxUSE_STATUSBAR
428
429 #if wxUSE_TOOLBAR
430 if (m_frameToolBar) delete m_frameToolBar;
431 m_frameToolBar = (wxToolBar *) NULL;
432 #endif // wxUSE_TOOLBAR
433
434 wxTopLevelWindows.DeleteObject( this );
435
436 if (wxTheApp->GetTopWindow() == this)
437 wxTheApp->SetTopWindow( (wxWindow*) NULL );
438
439 if (wxTopLevelWindows.Number() == 0)
440 wxTheApp->ExitMainLoop();
441 }
442
443 bool wxFrame::Show( bool show )
444 {
445 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
446
447 if (show && !m_sizeSet)
448 {
449 /* by calling GtkOnSize here, we don't have to call
450 either after showing the frame, which would entail
451 much ugly flicker or from within the size_allocate
452 handler, because GTK 1.1.X forbids that. */
453
454 GtkOnSize( m_x, m_y, m_width, m_height );
455 }
456
457 return wxWindow::Show( show );
458 }
459
460 bool wxFrame::Destroy()
461 {
462 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
463
464 if (!wxPendingDelete.Member(this)) wxPendingDelete.Append(this);
465
466 return TRUE;
467 }
468
469 void wxFrame::DoSetSize( int x, int y, int width, int height, int sizeFlags )
470 {
471 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
472
473 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
474 wxASSERT_MSG( (m_wxwindow != NULL), _T("invalid frame") );
475
476 /* avoid recursions */
477 if (m_resizing) return;
478 m_resizing = TRUE;
479
480 int old_x = m_x;
481 int old_y = m_y;
482 int old_width = m_width;
483 int old_height = m_height;
484
485 if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
486 {
487 if (x != -1) m_x = x;
488 if (y != -1) m_y = y;
489 if (width != -1) m_width = width;
490 if (height != -1) m_height = height;
491 }
492 else
493 {
494 m_x = x;
495 m_y = y;
496 m_width = width;
497 m_height = height;
498 }
499
500 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
501 {
502 if (width == -1) m_width = 80;
503 }
504
505 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
506 {
507 if (height == -1) m_height = 26;
508 }
509
510 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
511 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
512 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
513 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
514
515 if ((m_x != -1) || (m_y != -1))
516 {
517 if ((m_x != old_x) || (m_y != old_y))
518 {
519 gtk_widget_set_uposition( m_widget, m_x, m_y );
520 }
521 }
522
523 if ((m_width != old_width) || (m_height != old_height))
524 {
525 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
526 done either directly before the frame is shown or in idle time
527 so that different calls to SetSize() don't lead to flicker. */
528 m_sizeSet = FALSE;
529 }
530
531 m_resizing = FALSE;
532 }
533
534 void wxFrame::Centre( int direction )
535 {
536 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
537
538 int x = 0;
539 int y = 0;
540
541 if ((direction & wxHORIZONTAL) == wxHORIZONTAL) x = (gdk_screen_width () - m_width) / 2;
542 if ((direction & wxVERTICAL) == wxVERTICAL) y = (gdk_screen_height () - m_height) / 2;
543
544 Move( x, y );
545 }
546
547 void wxFrame::DoGetClientSize( int *width, int *height ) const
548 {
549 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
550
551 wxWindow::DoGetClientSize( width, height );
552 if (height)
553 {
554 /* menu bar */
555 if (m_frameMenuBar)
556 {
557 if (!m_menuBarDetached)
558 (*height) -= wxMENU_HEIGHT;
559 else
560 (*height) -= wxPLACE_HOLDER;
561 }
562
563 /* status bar */
564 if (m_frameStatusBar) (*height) -= wxSTATUS_HEIGHT;
565
566 /* tool bar */
567 if (m_frameToolBar)
568 {
569 if (!m_toolBarDetached)
570 {
571 int y = 0;
572 m_frameToolBar->GetSize( (int *) NULL, &y );
573 (*height) -= y;
574 }
575 else
576 (*height) -= wxPLACE_HOLDER;
577 }
578
579 /* mini edge */
580 (*height) -= m_miniEdge*2 + m_miniTitle;
581 }
582 if (width)
583 {
584 (*width) -= m_miniEdge*2;
585 }
586 }
587
588 void wxFrame::DoSetClientSize( int width, int height )
589 {
590 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
591
592 /* menu bar */
593 if (m_frameMenuBar)
594 {
595 if (!m_menuBarDetached)
596 height += wxMENU_HEIGHT;
597 else
598 height += wxPLACE_HOLDER;
599 }
600
601 /* status bar */
602 if (m_frameStatusBar) height += wxSTATUS_HEIGHT;
603
604 /* tool bar */
605 if (m_frameToolBar)
606 {
607 if (!m_toolBarDetached)
608 {
609 int y = 0;
610 m_frameToolBar->GetSize( (int *) NULL, &y );
611 height += y;
612 }
613 else
614 height += wxPLACE_HOLDER;
615 }
616
617 wxWindow::DoSetClientSize( width + m_miniEdge*2, height + m_miniEdge*2 + m_miniTitle );
618 }
619
620 void wxFrame::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y), int width, int height )
621 {
622 // due to a bug in gtk, x,y are always 0
623 // m_x = x;
624 // m_y = y;
625
626 /* avoid recursions */
627 if (m_resizing) return;
628 m_resizing = TRUE;
629
630 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
631 wxASSERT_MSG( (m_wxwindow != NULL), _T("invalid frame") );
632
633 m_width = width;
634 m_height = height;
635
636 /* space occupied by m_frameToolBar and m_frameMenuBar */
637 int client_area_y_offset = 0;
638
639 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
640 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
641 set in wxFrame::Create so it is used to check what kind of frame we
642 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
643 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
644 importantly) m_mainWidget */
645
646 if (m_mainWidget)
647 {
648 /* check if size is in legal range */
649 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
650 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
651 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
652 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
653
654 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
655 * menubar, the toolbar and the client area, which is represented by
656 * m_wxwindow.
657 * this hurts in the eye, but I don't want to call SetSize()
658 * because I don't want to call any non-native functions here. */
659
660 if (m_frameMenuBar)
661 {
662 int xx = m_miniEdge;
663 int yy = m_miniEdge + m_miniTitle;
664 int ww = m_width - 2*m_miniEdge;
665 int hh = wxMENU_HEIGHT;
666 if (m_menuBarDetached) hh = wxPLACE_HOLDER;
667 m_frameMenuBar->m_x = xx;
668 m_frameMenuBar->m_y = yy;
669 m_frameMenuBar->m_width = ww;
670 m_frameMenuBar->m_height = hh;
671 gtk_myfixed_set_size( GTK_MYFIXED(m_mainWidget),
672 m_frameMenuBar->m_widget,
673 xx, yy, ww, hh );
674 client_area_y_offset += hh;
675 }
676
677 if (m_frameToolBar)
678 {
679 int xx = m_miniEdge;
680 int yy = m_miniEdge + m_miniTitle;
681 if (m_frameMenuBar)
682 {
683 if (!m_menuBarDetached)
684 yy += wxMENU_HEIGHT;
685 else
686 yy += wxPLACE_HOLDER;
687 }
688 int ww = m_width - 2*m_miniEdge;
689 int hh = m_frameToolBar->m_height;
690 if (m_toolBarDetached) hh = wxPLACE_HOLDER;
691 m_frameToolBar->m_x = xx;
692 m_frameToolBar->m_y = yy;
693 /* m_frameToolBar->m_height = hh; don't change the toolbar's height */
694 m_frameToolBar->m_width = ww;
695 gtk_myfixed_set_size( GTK_MYFIXED(m_mainWidget),
696 m_frameToolBar->m_widget,
697 xx, yy, ww, hh );
698 client_area_y_offset += hh;
699 }
700
701 int client_x = m_miniEdge;
702 int client_y = client_area_y_offset + m_miniEdge + m_miniTitle;
703 int client_w = m_width - 2*m_miniEdge;
704 int client_h = m_height - client_area_y_offset- 2*m_miniEdge - m_miniTitle;
705 gtk_myfixed_set_size( GTK_MYFIXED(m_mainWidget),
706 m_wxwindow,
707 client_x, client_y, client_w, client_h );
708 }
709 else
710 {
711 /* if there is no m_mainWidget between m_widget and m_wxwindow there
712 is no need to set the size or position of m_wxwindow. */
713 }
714
715 if (m_frameStatusBar)
716 {
717 int xx = 0 + m_miniEdge;
718 int yy = m_height - wxSTATUS_HEIGHT - m_miniEdge - client_area_y_offset;
719 int ww = m_width - 2*m_miniEdge;
720 int hh = wxSTATUS_HEIGHT;
721 m_frameStatusBar->m_x = xx;
722 m_frameStatusBar->m_y = yy;
723 m_frameStatusBar->m_width = ww;
724 m_frameStatusBar->m_height = hh;
725 gtk_myfixed_set_size( GTK_MYFIXED(m_wxwindow),
726 m_frameStatusBar->m_widget,
727 xx, yy, ww, hh );
728 }
729
730 /* we actually set the size of a frame here and no-where else */
731 gtk_widget_set_usize( m_widget, m_width, m_height );
732
733 m_sizeSet = TRUE;
734
735 /* send size event to frame */
736 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
737 event.SetEventObject( this );
738 GetEventHandler()->ProcessEvent( event );
739
740 /* send size event to status bar */
741 if (m_frameStatusBar)
742 {
743 wxSizeEvent event2( wxSize(m_frameStatusBar->m_width,m_frameStatusBar->m_height), m_frameStatusBar->GetId() );
744 event2.SetEventObject( m_frameStatusBar );
745 m_frameStatusBar->GetEventHandler()->ProcessEvent( event2 );
746 }
747
748 m_resizing = FALSE;
749 }
750
751 void wxFrame::MakeModal( bool modal )
752 {
753 if (modal)
754 gtk_grab_add( m_widget );
755 else
756 gtk_grab_remove( m_widget );
757 }
758
759 void wxFrame::OnInternalIdle()
760 {
761 if (!m_sizeSet && GTK_WIDGET_REALIZED(m_wxwindow))
762 GtkOnSize( m_x, m_y, m_width, m_height );
763
764 DoMenuUpdates();
765
766 if (m_frameMenuBar) m_frameMenuBar->OnInternalIdle();
767 if (m_frameToolBar) m_frameToolBar->OnInternalIdle();
768 if (m_frameStatusBar) m_frameStatusBar->OnInternalIdle();
769 }
770
771 void wxFrame::OnCloseWindow( wxCloseEvent& WXUNUSED(event) )
772 {
773 Destroy();
774 }
775
776 void wxFrame::OnSize( wxSizeEvent &WXUNUSED(event) )
777 {
778 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
779
780 #if wxUSE_CONSTRAINTS
781 if (GetAutoLayout())
782 {
783 Layout();
784 }
785 else
786 #endif // wxUSE_CONSTRAINTS
787 {
788 /* do we have exactly one child? */
789 wxWindow *child = (wxWindow *)NULL;
790 for ( wxNode *node = GetChildren().First(); node; node = node->Next() )
791 {
792 wxWindow *win = (wxWindow *)node->Data();
793 if ( !wxIS_KIND_OF(win,wxFrame) && !wxIS_KIND_OF(win,wxDialog) )
794 {
795 if (child)
796 {
797 /* it's the second one: do nothing */
798 return;
799 }
800
801 child = win;
802 }
803 }
804
805 /* no children at all? */
806 if (child)
807 {
808 /* yes: set it's size to fill all the frame */
809 int client_x, client_y;
810 DoGetClientSize( &client_x, &client_y );
811 child->SetSize( 1, 1, client_x-2, client_y-2 );
812 }
813 }
814 }
815
816 void wxFrame::SetMenuBar( wxMenuBar *menuBar )
817 {
818 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
819 wxASSERT_MSG( (m_wxwindow != NULL), _T("invalid frame") );
820
821 m_frameMenuBar = menuBar;
822
823 if (m_frameMenuBar)
824 {
825 m_frameMenuBar->SetInvokingWindow( this );
826
827 if (m_frameMenuBar->GetParent() != this)
828 {
829 m_frameMenuBar->SetParent(this);
830 gtk_myfixed_put( GTK_MYFIXED(m_mainWidget),
831 m_frameMenuBar->m_widget,
832 m_frameMenuBar->m_x,
833 m_frameMenuBar->m_y,
834 m_frameMenuBar->m_width,
835 m_frameMenuBar->m_height );
836
837 if (menuBar->GetWindowStyle() & wxMB_DOCKABLE)
838 {
839 gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_attached",
840 GTK_SIGNAL_FUNC(gtk_menu_attached_callback), (gpointer)this );
841
842 gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_detached",
843 GTK_SIGNAL_FUNC(gtk_menu_detached_callback), (gpointer)this );
844 }
845
846 m_frameMenuBar->Show( TRUE );
847 }
848 }
849
850 /* resize window in OnInternalIdle */
851 m_sizeSet = FALSE;
852 }
853
854 wxMenuBar *wxFrame::GetMenuBar() const
855 {
856 return m_frameMenuBar;
857 }
858
859 void wxFrame::OnMenuHighlight(wxMenuEvent& event)
860 {
861 #if wxUSE_STATUSBAR
862 if (GetStatusBar())
863 {
864 // if no help string found, we will clear the status bar text
865 wxString helpString;
866
867 int menuId = event.GetMenuId();
868 if ( menuId != -1 )
869 {
870 wxMenuBar *menuBar = GetMenuBar();
871 if (menuBar)
872 {
873 helpString = menuBar->GetHelpString(menuId);
874 }
875 }
876
877 SetStatusText(helpString);
878 }
879 #endif // wxUSE_STATUSBAR
880 }
881
882 #if wxUSE_TOOLBAR
883 wxToolBar* wxFrame::CreateToolBar( long style, wxWindowID id, const wxString& name )
884 {
885 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
886
887 wxCHECK_MSG( m_frameToolBar == NULL, FALSE, _T("recreating toolbar in wxFrame") );
888
889 m_insertInClientArea = FALSE;
890
891 m_frameToolBar = OnCreateToolBar( style, id, name );
892
893 if (m_frameToolBar) GetChildren().DeleteObject( m_frameToolBar );
894
895 m_insertInClientArea = TRUE;
896
897 m_sizeSet = FALSE;
898
899 return m_frameToolBar;
900 }
901
902 wxToolBar* wxFrame::OnCreateToolBar( long style, wxWindowID id, const wxString& name )
903 {
904 return new wxToolBar( this, id, wxDefaultPosition, wxDefaultSize, style, name );
905 }
906
907 wxToolBar *wxFrame::GetToolBar() const
908 {
909 return m_frameToolBar;
910 }
911 #endif // wxUSE_TOOLBAR
912
913 #if wxUSE_STATUSBAR
914 wxStatusBar* wxFrame::CreateStatusBar( int number, long style, wxWindowID id, const wxString& name )
915 {
916 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
917
918 wxCHECK_MSG( m_frameStatusBar == NULL, FALSE, _T("recreating status bar in wxFrame") );
919
920 m_frameStatusBar = OnCreateStatusBar( number, style, id, name );
921
922 m_sizeSet = FALSE;
923
924 return m_frameStatusBar;
925 }
926
927 wxStatusBar *wxFrame::OnCreateStatusBar( int number, long style, wxWindowID id, const wxString& name )
928 {
929 wxStatusBar *statusBar = (wxStatusBar *) NULL;
930
931 statusBar = new wxStatusBar(this, id, wxPoint(0, 0), wxSize(100, 20), style, name);
932
933 // Set the height according to the font and the border size
934 wxClientDC dc(statusBar);
935 dc.SetFont( statusBar->GetFont() );
936
937 long x, y;
938 dc.GetTextExtent( "X", &x, &y );
939
940 int height = (int)( (y * 1.1) + 2* statusBar->GetBorderY());
941
942 statusBar->SetSize( -1, -1, 100, height );
943
944 statusBar->SetFieldsCount( number );
945 return statusBar;
946 }
947
948 wxStatusBar *wxFrame::GetStatusBar() const
949 {
950 return m_frameStatusBar;
951 }
952
953 void wxFrame::SetStatusText(const wxString& text, int number)
954 {
955 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
956
957 wxCHECK_RET( m_frameStatusBar != NULL, _T("no statusbar to set text for") );
958
959 m_frameStatusBar->SetStatusText(text, number);
960 }
961
962 void wxFrame::SetStatusWidths(int n, const int widths_field[] )
963 {
964 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
965
966 wxCHECK_RET( m_frameStatusBar != NULL, _T("no statusbar to set widths for") );
967
968 m_frameStatusBar->SetStatusWidths(n, widths_field);
969 }
970 #endif // wxUSE_STATUSBAR
971
972 void wxFrame::Command( int id )
973 {
974 wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, id);
975 commandEvent.SetInt( id );
976 commandEvent.SetEventObject( this );
977
978 wxMenuBar *bar = GetMenuBar();
979 if (!bar) return;
980
981 wxMenuItem *item = bar->FindItemForId(id) ;
982 if (item && item->IsCheckable())
983 {
984 bar->Check(id,!bar->Checked(id)) ;
985 }
986
987 wxEvtHandler* evtHandler = GetEventHandler();
988
989 evtHandler->ProcessEvent(commandEvent);
990 }
991
992 void wxFrame::SetTitle( const wxString &title )
993 {
994 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
995
996 m_title = title;
997 if (m_title.IsNull()) m_title = _T("");
998 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
999 }
1000
1001 void wxFrame::SetIcon( const wxIcon &icon )
1002 {
1003 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
1004
1005 m_icon = icon;
1006 if (!icon.Ok()) return;
1007
1008 if (!m_widget->window) return;
1009
1010 wxMask *mask = icon.GetMask();
1011 GdkBitmap *bm = (GdkBitmap *) NULL;
1012 if (mask) bm = mask->GetBitmap();
1013
1014 gdk_window_set_icon( m_widget->window, (GdkWindow *) NULL, icon.GetPixmap(), bm );
1015 }
1016