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