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