]> git.saurik.com Git - wxWidgets.git/blob - src/gtk1/frame.cpp
mini frame rewrite (titlebar still missing)
[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 /*
237 if ((m_windowStyle & wxMINIMIZE) == 0)
238 func |= GDK_FUNC_MINIMIZE;
239 if ((m_windowStyle & wxMAXIMIZE) == 0)
240 func |= GDK_FUNC_MAXIMIZE;
241 */
242 if ((m_windowStyle & wxSYSTEM_MENU) == 0)
243 decor |= GDK_DECOR_MENU;
244 if ((m_windowStyle & wxMINIMIZE_BOX) == 0)
245 decor |= GDK_DECOR_MINIMIZE;
246 if ((m_windowStyle & wxMAXIMIZE_BOX) == 0)
247 decor |= GDK_DECOR_MAXIMIZE;
248 if ((m_windowStyle & wxRESIZE_BORDER) == 0)
249 func |= GDK_FUNC_RESIZE;
250 gdk_window_set_decorations(m_widget->window, (GdkWMDecoration)decor);
251 gdk_window_set_functions(m_widget->window, (GdkWMFunction)func);
252
253 /* the user resized the frame by dragging etc. */
254 gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
255 GTK_SIGNAL_FUNC(gtk_frame_size_callback), (gpointer)this );
256
257 /* the only way to get the window size is to connect to this event */
258 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
259 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
260
261 return TRUE;
262 }
263
264 wxFrame::~wxFrame()
265 {
266 if (m_frameMenuBar) delete m_frameMenuBar;
267 m_frameMenuBar = (wxMenuBar *) NULL;
268
269 if (m_frameStatusBar) delete m_frameStatusBar;
270 m_frameStatusBar = (wxStatusBar *) NULL;
271
272 if (m_frameToolBar) delete m_frameToolBar;
273 m_frameToolBar = (wxToolBar *) NULL;
274
275 wxTopLevelWindows.DeleteObject( this );
276
277 if (wxTheApp->GetTopWindow() == this)
278 {
279 wxTheApp->SetTopWindow( (wxWindow*) NULL );
280 }
281
282 if (wxTopLevelWindows.Number() == 0)
283 {
284 wxTheApp->ExitMainLoop();
285 }
286 }
287
288 bool wxFrame::Show( bool show )
289 {
290 wxASSERT_MSG( (m_widget != NULL), "invalid frame" );
291
292 if (show && !m_sizeSet)
293 {
294 /* by calling GtkOnSize here, we don't have to call
295 either after showing the frame, which would entail
296 much ugly flicker or from within the size_allocate
297 handler, because GTK 1.1.X forbids that. */
298
299 GtkOnSize( m_x, m_y, m_width, m_height );
300 }
301
302 return wxWindow::Show( show );
303 }
304
305 bool wxFrame::Destroy()
306 {
307 wxASSERT_MSG( (m_widget != NULL), "invalid frame" );
308
309 if (!wxPendingDelete.Member(this)) wxPendingDelete.Append(this);
310
311 return TRUE;
312 }
313
314 void wxFrame::DoSetSize( int x, int y, int width, int height, int sizeFlags )
315 {
316 wxASSERT_MSG( (m_widget != NULL), "invalid frame" );
317
318 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
319 wxASSERT_MSG( (m_wxwindow != NULL), "invalid frame" );
320
321 /* avoid recursions */
322 if (m_resizing) return;
323 m_resizing = TRUE;
324
325 int old_x = m_x;
326 int old_y = m_y;
327 int old_width = m_width;
328 int old_height = m_height;
329
330 if ((sizeFlags & wxSIZE_USE_EXISTING) == wxSIZE_USE_EXISTING)
331 {
332 if (x != -1) m_x = x;
333 if (y != -1) m_y = y;
334 if (width != -1) m_width = width;
335 if (height != -1) m_height = height;
336 }
337 else
338 {
339 m_x = x;
340 m_y = y;
341 m_width = width;
342 m_height = height;
343 }
344
345 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
346 {
347 if (width == -1) m_width = 80;
348 }
349
350 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
351 {
352 if (height == -1) m_height = 26;
353 }
354
355 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
356 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
357 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
358 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
359
360 if ((m_x != -1) || (m_y != -1))
361 {
362 if ((m_x != old_x) || (m_y != old_y))
363 {
364 /* m_sizeSet = FALSE; */
365 gtk_widget_set_uposition( m_widget, m_x, m_y );
366 }
367 }
368
369 if ((m_width != old_width) || (m_height != old_height))
370 {
371 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
372 done either directly before the frame is shown or in idle time
373 so that different calls to SetSize() don't lead to flicker. */
374 m_sizeSet = FALSE;
375 }
376
377 m_resizing = FALSE;
378 }
379
380 void wxFrame::Centre( int direction )
381 {
382 wxASSERT_MSG( (m_widget != NULL), "invalid frame" );
383
384 int x = 0;
385 int y = 0;
386
387 if ((direction & wxHORIZONTAL) == wxHORIZONTAL) x = (gdk_screen_width () - m_width) / 2;
388 if ((direction & wxVERTICAL) == wxVERTICAL) y = (gdk_screen_height () - m_height) / 2;
389
390 Move( x, y );
391 }
392
393 void wxFrame::GetClientSize( int *width, int *height ) const
394 {
395 wxASSERT_MSG( (m_widget != NULL), "invalid frame" );
396
397 wxWindow::GetClientSize( width, height );
398 if (height)
399 {
400 if (m_frameMenuBar) (*height) -= wxMENU_HEIGHT;
401 if (m_frameStatusBar) (*height) -= wxSTATUS_HEIGHT;
402 if (m_frameToolBar)
403 {
404 int y = 0;
405 m_frameToolBar->GetSize( (int *) NULL, &y );
406 (*height) -= y;
407 }
408 (*height) -= m_miniEdge*2 + m_miniTitle;
409 }
410 if (width)
411 {
412 (*width) -= m_miniEdge*2;
413 }
414 }
415
416 void wxFrame::DoSetClientSize( int width, int height )
417 {
418 wxASSERT_MSG( (m_widget != NULL), "invalid frame" );
419
420 int h = height;
421 if (m_frameMenuBar) h += wxMENU_HEIGHT;
422 if (m_frameStatusBar) h += wxSTATUS_HEIGHT;
423 if (m_frameToolBar)
424 {
425 int y = 0;
426 m_frameToolBar->GetSize( (int *) NULL, &y );
427 h += y;
428 }
429 wxWindow::DoSetClientSize( width + m_miniEdge*2, h + m_miniEdge*2 + m_miniTitle );
430 }
431
432 void wxFrame::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y), int width, int height )
433 {
434 // due to a bug in gtk, x,y are always 0
435 // m_x = x;
436 // m_y = y;
437
438 /* avoid recursions */
439 if (m_resizing) return;
440 m_resizing = TRUE;
441
442 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
443 wxASSERT_MSG( (m_wxwindow != NULL), "invalid frame" );
444
445 m_width = width;
446 m_height = height;
447
448 /* space occupied by m_frameToolBar and m_frameMenuBar */
449 int client_area_y_offset = 0;
450
451 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
452 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
453 set in wxFrame::Create so it is used to check what kind of frame we
454 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
455 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
456 importantly) m_mainWidget */
457
458 if (m_mainWidget)
459 {
460 /* check if size is in legal range */
461 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
462 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
463 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
464 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
465
466 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
467 * menubar, the toolbar and the client area, which is represented by
468 * m_wxwindow.
469 * this hurts in the eye, but I don't want to call SetSize()
470 * because I don't want to call any non-native functions here. */
471
472 if (m_frameMenuBar)
473 {
474 int xx = m_miniEdge;
475 int yy = m_miniEdge + m_miniTitle;
476 int ww = m_width - 2*m_miniEdge;
477 int hh = wxMENU_HEIGHT;
478 m_frameMenuBar->m_x = xx;
479 m_frameMenuBar->m_y = yy;
480 m_frameMenuBar->m_width = ww;
481 m_frameMenuBar->m_height = hh;
482
483 gtk_myfixed_move( GTK_MYFIXED(m_mainWidget), m_frameMenuBar->m_widget, xx, yy );
484 gtk_widget_set_usize( m_frameMenuBar->m_widget, ww, hh );
485
486 client_area_y_offset += hh;
487 }
488
489 if (m_frameToolBar)
490 {
491 int xx = m_miniEdge;
492 int yy = m_miniEdge + m_miniTitle;
493 if ((m_frameMenuBar) || (m_mdiMenuBar)) yy += wxMENU_HEIGHT;
494 int ww = m_width - 2*m_miniEdge;
495 int hh = m_frameToolBar->m_height;
496
497 m_frameToolBar->m_x = xx;
498 m_frameToolBar->m_y = yy;
499 m_frameToolBar->m_height = hh;
500 m_frameToolBar->m_width = ww;
501
502 gtk_myfixed_move( GTK_MYFIXED(m_mainWidget), m_frameToolBar->m_widget, xx, yy );
503 gtk_widget_set_usize( m_frameToolBar->m_widget, ww, hh );
504
505 client_area_y_offset += hh;
506 }
507
508 int client_x = m_miniEdge;
509 int client_y = client_area_y_offset + m_miniEdge + m_miniTitle;
510 gtk_myfixed_move( GTK_MYFIXED(m_mainWidget), m_wxwindow, client_x, client_y );
511
512 int client_w = m_width - 2*m_miniEdge;
513 int client_h = m_height - client_area_y_offset- 2*m_miniEdge - m_miniTitle;
514 gtk_widget_set_usize( m_wxwindow, client_w, client_h );
515 }
516 else
517 {
518 /* if there is no m_mainWidget between m_widget and m_wxwindow there
519 is no need to set the size or position of m_wxwindow. */
520 }
521
522 if (m_frameStatusBar)
523 {
524 int xx = 0 + m_miniEdge;
525 int yy = m_height - wxSTATUS_HEIGHT - m_miniEdge - client_area_y_offset;
526 int ww = m_width - 2*m_miniEdge;
527 int hh = wxSTATUS_HEIGHT;
528
529 m_frameStatusBar->m_x = xx;
530 m_frameStatusBar->m_y = yy;
531 m_frameStatusBar->m_width = ww;
532 m_frameStatusBar->m_height = hh;
533
534 gtk_myfixed_move( GTK_MYFIXED(m_wxwindow), m_frameStatusBar->m_widget, xx, yy );
535 gtk_widget_set_usize( m_frameStatusBar->m_widget, ww, hh );
536 }
537
538 /* we actually set the size of a frame here and no-where else */
539 gtk_widget_set_usize( m_widget, m_width, m_height );
540
541 m_sizeSet = TRUE;
542
543 /* send size event to frame */
544 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
545 event.SetEventObject( this );
546 GetEventHandler()->ProcessEvent( event );
547
548 /* send size event to status bar */
549 if (m_frameStatusBar)
550 {
551 wxSizeEvent event2( wxSize(m_frameStatusBar->m_width,m_frameStatusBar->m_height), m_frameStatusBar->GetId() );
552 event2.SetEventObject( m_frameStatusBar );
553 m_frameStatusBar->GetEventHandler()->ProcessEvent( event2 );
554 }
555
556 m_resizing = FALSE;
557 }
558
559 void wxFrame::OnInternalIdle()
560 {
561 if (!m_sizeSet)
562 GtkOnSize( m_x, m_y, m_width, m_height );
563
564 DoMenuUpdates();
565 }
566
567 void wxFrame::OnCloseWindow( wxCloseEvent& event )
568 {
569 Destroy();
570 }
571
572 void wxFrame::OnSize( wxSizeEvent &WXUNUSED(event) )
573 {
574 wxASSERT_MSG( (m_widget != NULL), "invalid frame" );
575
576 if (GetAutoLayout())
577 {
578 Layout();
579 }
580 else
581 {
582 // do we have exactly one child?
583 wxWindow *child = (wxWindow *)NULL;
584 for ( wxNode *node = GetChildren().First(); node; node = node->Next() )
585 {
586 wxWindow *win = (wxWindow *)node->Data();
587 if ( !wxIS_KIND_OF(win,wxFrame) && !wxIS_KIND_OF(win,wxDialog) )
588 {
589 if ( child )
590 {
591 // it's the second one: do nothing
592 return;
593 }
594
595 child = win;
596 }
597 }
598
599 // no children at all?
600 if ( child )
601 {
602 // yes: set it's size to fill all the frame
603 int client_x, client_y;
604 GetClientSize( &client_x, &client_y );
605 child->SetSize( 1, 1, client_x-2, client_y-2 );
606 }
607 }
608 }
609
610 static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
611 {
612 menu->SetInvokingWindow( win );
613 wxNode *node = menu->GetItems().First();
614 while (node)
615 {
616 wxMenuItem *menuitem = (wxMenuItem*)node->Data();
617 if (menuitem->IsSubMenu())
618 SetInvokingWindow( menuitem->GetSubMenu(), win );
619 node = node->Next();
620 }
621 }
622
623 void wxFrame::SetMenuBar( wxMenuBar *menuBar )
624 {
625 wxASSERT_MSG( (m_widget != NULL), "invalid frame" );
626 wxASSERT_MSG( (m_wxwindow != NULL), "invalid frame" );
627
628 m_frameMenuBar = menuBar;
629
630 if (m_frameMenuBar)
631 {
632 wxNode *node = m_frameMenuBar->GetMenus().First();
633 while (node)
634 {
635 wxMenu *menu = (wxMenu*)node->Data();
636 SetInvokingWindow( menu, this );
637 node = node->Next();
638 }
639
640 if (m_frameMenuBar->m_parent != this)
641 {
642 m_frameMenuBar->m_parent = this;
643 gtk_myfixed_put( GTK_MYFIXED(m_mainWidget),
644 m_frameMenuBar->m_widget, m_frameMenuBar->m_x, m_frameMenuBar->m_y );
645
646 /* an mdi child menu bar might be underneath */
647 if (m_mdiMenuBar)
648 m_frameMenuBar->Show( FALSE );
649 }
650 }
651
652 m_sizeSet = FALSE;
653 }
654
655 wxMenuBar *wxFrame::GetMenuBar() const
656 {
657 return m_frameMenuBar;
658 }
659
660 void wxFrame::OnMenuHighlight(wxMenuEvent& event)
661 {
662 if (GetStatusBar())
663 {
664 // if no help string found, we will clear the status bar text
665 wxString helpString;
666
667 int menuId = event.GetMenuId();
668 if ( menuId != -1 )
669 {
670 wxMenuBar *menuBar = GetMenuBar();
671 if (menuBar)
672 {
673 helpString = menuBar->GetHelpString(menuId);
674 }
675 }
676
677 SetStatusText(helpString);
678 }
679 }
680
681 wxToolBar* wxFrame::CreateToolBar(long style, wxWindowID id, const wxString& name)
682 {
683 wxASSERT_MSG( (m_widget != NULL), "invalid frame" );
684
685 wxCHECK_MSG( m_frameToolBar == NULL, FALSE, "recreating toolbar in wxFrame" );
686
687 m_frameToolBar = OnCreateToolBar( style, id, name );
688
689 GetChildren().DeleteObject( m_frameToolBar );
690
691 m_sizeSet = FALSE;
692
693 return m_frameToolBar;
694 }
695
696 wxToolBar* wxFrame::OnCreateToolBar( long style, wxWindowID id, const wxString& name )
697 {
698 return new wxToolBar( this, id, wxDefaultPosition, wxDefaultSize, style, name );
699 }
700
701 wxToolBar *wxFrame::GetToolBar() const
702 {
703 return m_frameToolBar;
704 }
705
706 wxStatusBar* wxFrame::CreateStatusBar( int number, long style, wxWindowID id, const wxString& name )
707 {
708 wxASSERT_MSG( (m_widget != NULL), "invalid frame" );
709
710 wxCHECK_MSG( m_frameStatusBar == NULL, FALSE, "recreating status bar in wxFrame" );
711
712 m_frameStatusBar = OnCreateStatusBar( number, style, id, name );
713
714 m_sizeSet = FALSE;
715
716 return m_frameStatusBar;
717 }
718
719 wxStatusBar *wxFrame::OnCreateStatusBar( int number, long style, wxWindowID id, const wxString& name )
720 {
721 wxStatusBar *statusBar = (wxStatusBar *) NULL;
722
723 statusBar = new wxStatusBar(this, id, wxPoint(0, 0), wxSize(100, 20), style, name);
724
725 // Set the height according to the font and the border size
726 wxClientDC dc(statusBar);
727 dc.SetFont( statusBar->GetFont() );
728
729 long x, y;
730 dc.GetTextExtent( "X", &x, &y );
731
732 int height = (int)( (y * 1.1) + 2* statusBar->GetBorderY());
733
734 statusBar->SetSize( -1, -1, 100, height );
735
736 statusBar->SetFieldsCount( number );
737 return statusBar;
738 }
739
740 void wxFrame::Command( int id )
741 {
742 wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, id);
743 commandEvent.SetInt( id );
744 commandEvent.SetEventObject( this );
745
746 wxMenuBar *bar = GetMenuBar();
747 if (!bar) return;
748
749 wxMenuItem *item = bar->FindItemForId(id) ;
750 if (item && item->IsCheckable())
751 {
752 bar->Check(id,!bar->Checked(id)) ;
753 }
754
755 wxEvtHandler* evtHandler = GetEventHandler();
756
757 evtHandler->ProcessEvent(commandEvent);
758 }
759
760 void wxFrame::SetStatusText(const wxString& text, int number)
761 {
762 wxASSERT_MSG( (m_widget != NULL), "invalid frame" );
763
764 wxCHECK_RET( m_frameStatusBar != NULL, "no statusbar to set text for" );
765
766 m_frameStatusBar->SetStatusText(text, number);
767 }
768
769 void wxFrame::SetStatusWidths(int n, const int widths_field[] )
770 {
771 wxASSERT_MSG( (m_widget != NULL), "invalid frame" );
772
773 wxCHECK_RET( m_frameStatusBar != NULL, "no statusbar to set widths for" );
774
775 m_frameStatusBar->SetStatusWidths(n, widths_field);
776 }
777
778 wxStatusBar *wxFrame::GetStatusBar() const
779 {
780 return m_frameStatusBar;
781 }
782
783 void wxFrame::SetTitle( const wxString &title )
784 {
785 wxASSERT_MSG( (m_widget != NULL), "invalid frame" );
786
787 m_title = title;
788 if (m_title.IsNull()) m_title = "";
789 gtk_window_set_title( GTK_WINDOW(m_widget), title );
790 }
791
792 void wxFrame::SetIcon( const wxIcon &icon )
793 {
794 wxASSERT_MSG( (m_widget != NULL), "invalid frame" );
795
796 m_icon = icon;
797 if (!icon.Ok()) return;
798
799 wxMask *mask = icon.GetMask();
800 GdkBitmap *bm = (GdkBitmap *) NULL;
801 if (mask) bm = mask->GetBitmap();
802
803 gdk_window_set_icon( m_widget->window, (GdkWindow *) NULL, icon.GetPixmap(), bm );
804 }
805