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