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