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