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