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