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