?lk
[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 <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->UpdateSize();
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)
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->UpdateSize();
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->UpdateSize();
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->UpdateSize();
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->UpdateSize();
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
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->UpdateSize();
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->ExitMainLoop();
509 }
510
511 // ----------------------------------------------------------------------------
512 // overridden wxWindow methods
513 // ----------------------------------------------------------------------------
514
515 bool wxFrame::Show( bool show )
516 {
517 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
518
519 if (show && !m_sizeSet)
520 {
521 /* by calling GtkOnSize here, we don't have to call
522 either after showing the frame, which would entail
523 much ugly flicker or from within the size_allocate
524 handler, because GTK 1.1.X forbids that. */
525
526 GtkOnSize( m_x, m_y, m_width, m_height );
527 }
528
529 return wxWindow::Show( show );
530 }
531
532 void wxFrame::DoSetSize( int x, int y, int width, int height, int sizeFlags )
533 {
534 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
535
536 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
537 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
538
539 /* avoid recursions */
540 if (m_resizing)
541 return;
542 m_resizing = TRUE;
543
544 int old_x = m_x;
545 int old_y = m_y;
546
547 int old_width = m_width;
548 int old_height = m_height;
549
550 if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
551 {
552 if (x != -1) m_x = x;
553 if (y != -1) m_y = y;
554 if (width != -1) m_width = width;
555 if (height != -1) m_height = height;
556 }
557 else
558 {
559 m_x = x;
560 m_y = y;
561 m_width = width;
562 m_height = height;
563 }
564
565 /*
566 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
567 {
568 if (width == -1) m_width = 80;
569 }
570
571 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
572 {
573 if (height == -1) m_height = 26;
574 }
575 */
576
577 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
578 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
579 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
580 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
581
582 if ((m_x != -1) || (m_y != -1))
583 {
584 if ((m_x != old_x) || (m_y != old_y))
585 {
586 gtk_widget_set_uposition( m_widget, m_x, m_y );
587 }
588 }
589
590 if ((m_width != old_width) || (m_height != old_height))
591 {
592 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
593 done either directly before the frame is shown or in idle time
594 so that different calls to SetSize() don't lead to flicker. */
595 m_sizeSet = FALSE;
596 }
597
598 m_resizing = FALSE;
599 }
600
601 void wxFrame::DoGetClientSize( int *width, int *height ) const
602 {
603 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
604
605 wxWindow::DoGetClientSize( width, height );
606 if (height)
607 {
608 /* menu bar */
609 if (m_frameMenuBar)
610 {
611 if (!m_menuBarDetached)
612 (*height) -= wxMENU_HEIGHT;
613 else
614 (*height) -= wxPLACE_HOLDER;
615 }
616
617 #if wxUSE_STATUSBAR
618 /* status bar */
619 if (m_frameStatusBar) (*height) -= wxSTATUS_HEIGHT;
620 #endif
621
622 #if wxUSE_TOOLBAR
623 /* tool bar */
624 if (m_frameToolBar)
625 {
626 if (!m_toolBarDetached)
627 {
628 int y = 0;
629 m_frameToolBar->GetSize( (int *) NULL, &y );
630 (*height) -= y;
631 }
632 else
633 (*height) -= wxPLACE_HOLDER;
634 }
635 #endif
636
637 /* mini edge */
638 (*height) -= m_miniEdge*2 + m_miniTitle;
639 }
640 if (width)
641 {
642 (*width) -= m_miniEdge*2;
643 }
644 }
645
646 void wxFrame::DoSetClientSize( int width, int height )
647 {
648 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
649
650 /* menu bar */
651 if (m_frameMenuBar)
652 {
653 if (!m_menuBarDetached)
654 height += wxMENU_HEIGHT;
655 else
656 height += wxPLACE_HOLDER;
657 }
658
659 #if wxUSE_STATUSBAR
660 /* status bar */
661 if (m_frameStatusBar) height += wxSTATUS_HEIGHT;
662 #endif
663
664 #if wxUSE_TOOLBAR
665 /* tool bar */
666 if (m_frameToolBar)
667 {
668 if (!m_toolBarDetached)
669 {
670 int y = 0;
671 m_frameToolBar->GetSize( (int *) NULL, &y );
672 height += y;
673 }
674 else
675 height += wxPLACE_HOLDER;
676 }
677 #endif
678
679 DoSetSize( -1, -1, width + m_miniEdge*2, height + m_miniEdge*2 + m_miniTitle, 0 );
680 }
681
682 void wxFrame::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y),
683 int width, int height )
684 {
685 // due to a bug in gtk, x,y are always 0
686 // m_x = x;
687 // m_y = y;
688
689 /* avoid recursions */
690 if (m_resizing) return;
691 m_resizing = TRUE;
692
693 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
694 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
695
696 m_width = width;
697 m_height = height;
698
699 /* space occupied by m_frameToolBar and m_frameMenuBar */
700 int client_area_y_offset = 0;
701
702 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
703 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
704 set in wxFrame::Create so it is used to check what kind of frame we
705 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
706 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
707 importantly) m_mainWidget */
708
709 if (m_mainWidget)
710 {
711 /* check if size is in legal range */
712 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
713 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
714 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
715 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
716
717 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
718 * menubar, the toolbar and the client area, which is represented by
719 * m_wxwindow.
720 * this hurts in the eye, but I don't want to call SetSize()
721 * because I don't want to call any non-native functions here. */
722
723 if (m_frameMenuBar)
724 {
725 int xx = m_miniEdge;
726 int yy = m_miniEdge + m_miniTitle;
727 int ww = m_width - 2*m_miniEdge;
728 int hh = wxMENU_HEIGHT;
729 if (m_menuBarDetached) hh = wxPLACE_HOLDER;
730 m_frameMenuBar->m_x = xx;
731 m_frameMenuBar->m_y = yy;
732 m_frameMenuBar->m_width = ww;
733 m_frameMenuBar->m_height = hh;
734 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
735 m_frameMenuBar->m_widget,
736 xx, yy, ww, hh );
737 client_area_y_offset += hh;
738 }
739
740 #if wxUSE_TOOLBAR
741 if ((m_frameToolBar) &&
742 (m_frameToolBar->m_widget->parent == m_mainWidget))
743 {
744 int xx = m_miniEdge;
745 int yy = m_miniEdge + m_miniTitle;
746 if (m_frameMenuBar)
747 {
748 if (!m_menuBarDetached)
749 yy += wxMENU_HEIGHT;
750 else
751 yy += wxPLACE_HOLDER;
752 }
753 int ww = m_width - 2*m_miniEdge;
754 int hh = m_frameToolBar->m_height;
755 if (m_toolBarDetached) hh = wxPLACE_HOLDER;
756 m_frameToolBar->m_x = xx;
757 m_frameToolBar->m_y = yy;
758 /* m_frameToolBar->m_height = hh; don't change the toolbar's reported size
759 m_frameToolBar->m_width = ww; */
760 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
761 m_frameToolBar->m_widget,
762 xx, yy, ww, hh );
763 client_area_y_offset += hh;
764 }
765 #endif
766
767 int client_x = m_miniEdge;
768 int client_y = client_area_y_offset + m_miniEdge + m_miniTitle;
769 int client_w = m_width - 2*m_miniEdge;
770 int client_h = m_height - client_area_y_offset- 2*m_miniEdge - m_miniTitle;
771 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
772 m_wxwindow,
773 client_x, client_y, client_w, client_h );
774 }
775 else
776 {
777 /* if there is no m_mainWidget between m_widget and m_wxwindow there
778 is no need to set the size or position of m_wxwindow. */
779 }
780
781 #if wxUSE_STATUSBAR
782 if (m_frameStatusBar)
783 {
784 int xx = 0 + m_miniEdge;
785 int yy = m_height - wxSTATUS_HEIGHT - m_miniEdge - client_area_y_offset;
786 int ww = m_width - 2*m_miniEdge;
787 int hh = wxSTATUS_HEIGHT;
788 m_frameStatusBar->m_x = xx;
789 m_frameStatusBar->m_y = yy;
790 m_frameStatusBar->m_width = ww;
791 m_frameStatusBar->m_height = hh;
792 gtk_pizza_set_size( GTK_PIZZA(m_wxwindow),
793 m_frameStatusBar->m_widget,
794 xx, yy, ww, hh );
795 }
796 #endif
797
798 /* we actually set the size of a frame here and no-where else */
799 gtk_widget_set_usize( m_widget, m_width, m_height );
800
801 m_sizeSet = TRUE;
802
803 // send size event to frame
804 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
805 event.SetEventObject( this );
806 GetEventHandler()->ProcessEvent( event );
807
808 // send size event to status bar
809 if (m_frameStatusBar)
810 {
811 wxSizeEvent event2( wxSize(m_frameStatusBar->m_width,m_frameStatusBar->m_height), m_frameStatusBar->GetId() );
812 event2.SetEventObject( m_frameStatusBar );
813 m_frameStatusBar->GetEventHandler()->ProcessEvent( event2 );
814 }
815
816 m_resizing = FALSE;
817 }
818
819 void wxFrame::MakeModal( bool modal )
820 {
821 if (modal)
822 gtk_grab_add( m_widget );
823 else
824 gtk_grab_remove( m_widget );
825 }
826
827 void wxFrame::OnInternalIdle()
828 {
829 if (!m_sizeSet && GTK_WIDGET_REALIZED(m_wxwindow))
830 {
831 GtkOnSize( m_x, m_y, m_width, m_height );
832
833 // we'll come back later
834 if (g_isIdle)
835 wxapp_install_idle_handler();
836 return;
837 }
838
839 if (m_frameMenuBar) m_frameMenuBar->OnInternalIdle();
840 #if wxUSE_TOOLBAR
841 if (m_frameToolBar) m_frameToolBar->OnInternalIdle();
842 #endif
843 #if wxUSE_STATUSBAR
844 if (m_frameStatusBar) m_frameStatusBar->OnInternalIdle();
845 #endif
846
847 wxWindow::OnInternalIdle();
848 }
849
850 // ----------------------------------------------------------------------------
851 // menu/tool/status bar stuff
852 // ----------------------------------------------------------------------------
853
854 void wxFrame::SetMenuBar( wxMenuBar *menuBar )
855 {
856 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
857 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
858
859 m_frameMenuBar = menuBar;
860
861 if (m_frameMenuBar)
862 {
863 m_frameMenuBar->SetInvokingWindow( this );
864
865 if (m_frameMenuBar->GetParent() != this)
866 {
867 m_frameMenuBar->SetParent(this);
868 gtk_pizza_put( GTK_PIZZA(m_mainWidget),
869 m_frameMenuBar->m_widget,
870 m_frameMenuBar->m_x,
871 m_frameMenuBar->m_y,
872 m_frameMenuBar->m_width,
873 m_frameMenuBar->m_height );
874
875 if (menuBar->GetWindowStyle() & wxMB_DOCKABLE)
876 {
877 gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_attached",
878 GTK_SIGNAL_FUNC(gtk_menu_attached_callback), (gpointer)this );
879
880 gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_detached",
881 GTK_SIGNAL_FUNC(gtk_menu_detached_callback), (gpointer)this );
882 }
883
884 m_frameMenuBar->Show( TRUE );
885 }
886 }
887
888 /* resize window in OnInternalIdle */
889 m_sizeSet = FALSE;
890 }
891
892 #if wxUSE_TOOLBAR
893 wxToolBar* wxFrame::CreateToolBar( long style, wxWindowID id, const wxString& name )
894 {
895 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
896
897 m_insertInClientArea = FALSE;
898
899 m_frameToolBar = wxFrameBase::CreateToolBar( style, id, name );
900
901 if (m_frameToolBar)
902 GetChildren().DeleteObject( m_frameToolBar );
903
904 m_insertInClientArea = TRUE;
905
906 m_sizeSet = FALSE;
907
908 return m_frameToolBar;
909 }
910
911 void wxFrame::SetToolBar(wxToolBar *toolbar)
912 {
913 wxFrameBase::SetToolBar(toolbar);
914
915 if (m_frameToolBar)
916 {
917 /* insert into toolbar area if not already there */
918 if ((m_frameToolBar->m_widget->parent) &&
919 (m_frameToolBar->m_widget->parent != m_mainWidget))
920 {
921 GetChildren().DeleteObject( m_frameToolBar );
922
923 gtk_widget_reparent( m_frameToolBar->m_widget, m_mainWidget );
924 UpdateSize();
925 }
926 }
927 }
928
929 #endif // wxUSE_TOOLBAR
930
931 #if wxUSE_STATUSBAR
932
933 wxStatusBar* wxFrame::CreateStatusBar(int number,
934 long style,
935 wxWindowID id,
936 const wxString& name)
937 {
938 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
939
940 // because it will change when toolbar is added
941 m_sizeSet = FALSE;
942
943 return wxFrameBase::CreateStatusBar( number, style, id, name );
944 }
945
946 #endif // wxUSE_STATUSBAR
947
948 // ----------------------------------------------------------------------------
949 // frame title/icon
950 // ----------------------------------------------------------------------------
951
952 void wxFrame::SetTitle( const wxString &title )
953 {
954 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
955
956 m_title = title;
957 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
958 }
959
960 void wxFrame::SetIcon( const wxIcon &icon )
961 {
962 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
963
964 wxFrameBase::SetIcon(icon);
965
966 if ( !m_icon.Ok() )
967 return;
968
969 if (!m_widget->window)
970 return;
971
972 wxMask *mask = icon.GetMask();
973 GdkBitmap *bm = (GdkBitmap *) NULL;
974 if (mask) bm = mask->GetBitmap();
975
976 gdk_window_set_icon( m_widget->window, (GdkWindow *) NULL, icon.GetPixmap(), bm );
977 }
978
979 // ----------------------------------------------------------------------------
980 // frame state: maximized/iconized/normal (TODO)
981 // ----------------------------------------------------------------------------
982
983 void wxFrame::Maximize(bool WXUNUSED(maximize))
984 {
985 }
986
987 bool wxFrame::IsMaximized() const
988 {
989 return FALSE;
990 }
991
992 void wxFrame::Restore()
993 {
994 }
995
996 void wxFrame::Iconize( bool iconize )
997 {
998 if (iconize)
999 {
1000 XIconifyWindow( GDK_WINDOW_XDISPLAY( m_widget->window ),
1001 GDK_WINDOW_XWINDOW( m_widget->window ),
1002 DefaultScreen( GDK_DISPLAY() ) );
1003 }
1004 }
1005
1006 bool wxFrame::IsIconized() const
1007 {
1008 return FALSE;
1009 }