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