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