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