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