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