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