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