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