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