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