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