wxFrame's m_mainWidget didn't have themes.
[wxWidgets.git] / src / gtk / frame.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: frame.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 // ============================================================================
11 // declarations
12 // ============================================================================
13
14 // ----------------------------------------------------------------------------
15 // headers
16 // ----------------------------------------------------------------------------
17
18 #ifdef __GNUG__
19 #pragma implementation "frame.h"
20 #endif
21
22 #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 void
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)) || (win->HasFlag(wxNO_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
326 //-----------------------------------------------------------------------------
327 // "map_event" from m_widget
328 //-----------------------------------------------------------------------------
329
330 static void
331 gtk_frame_map_callback( GtkWidget * WXUNUSED(widget),
332 GdkEvent * WXUNUSED(event),
333 wxFrame *win )
334 {
335 win->m_isIconized = FALSE;
336 }
337
338 //-----------------------------------------------------------------------------
339 // "unmap_event" from m_widget
340 //-----------------------------------------------------------------------------
341
342 static void
343 gtk_frame_unmap_callback( GtkWidget * WXUNUSED(widget),
344 GdkEvent * WXUNUSED(event),
345 wxFrame *win )
346 {
347 win->m_isIconized = TRUE;
348 }
349
350 //-----------------------------------------------------------------------------
351 // "expose_event" of m_client
352 //-----------------------------------------------------------------------------
353
354 static int gtk_window_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxWindow *win )
355 {
356 GtkPizza *pizza = GTK_PIZZA(widget);
357
358 gtk_paint_flat_box (win->m_widget->style, pizza->bin_window, GTK_STATE_NORMAL,
359 GTK_SHADOW_NONE, &gdk_event->area, win->m_widget, "base", 0, 0, -1, -1);
360
361 return TRUE;
362 }
363
364 //-----------------------------------------------------------------------------
365 // "draw" of m_client
366 //-----------------------------------------------------------------------------
367
368
369 static void gtk_window_draw_callback( GtkWidget *widget, GdkRectangle *rect, wxWindow *win )
370 {
371 GtkPizza *pizza = GTK_PIZZA(widget);
372
373 gtk_paint_flat_box (win->m_widget->style, pizza->bin_window, GTK_STATE_NORMAL,
374 GTK_SHADOW_NONE, rect, win->m_widget, "base", 0, 0, -1, -1);
375 }
376
377 // ----------------------------------------------------------------------------
378 // wxFrame itself
379 // ----------------------------------------------------------------------------
380
381 //-----------------------------------------------------------------------------
382 // InsertChild for wxFrame
383 //-----------------------------------------------------------------------------
384
385 /* Callback for wxFrame. This very strange beast has to be used because
386 * C++ has no virtual methods in a constructor. We have to emulate a
387 * virtual function here as wxWindows requires different ways to insert
388 * a child in container classes. */
389
390 static void wxInsertChildInFrame( wxFrame* parent, wxWindow* child )
391 {
392 wxASSERT( GTK_IS_WIDGET(child->m_widget) );
393
394 if (!parent->m_insertInClientArea)
395 {
396 /* these are outside the client area */
397 wxFrame* frame = (wxFrame*) parent;
398 gtk_pizza_put( GTK_PIZZA(frame->m_mainWidget),
399 GTK_WIDGET(child->m_widget),
400 child->m_x,
401 child->m_y,
402 child->m_width,
403 child->m_height );
404
405 #if wxUSE_TOOLBAR_NATIVE
406 /* we connect to these events for recalculating the client area
407 space when the toolbar is floating */
408 if (wxIS_KIND_OF(child,wxToolBar))
409 {
410 wxToolBar *toolBar = (wxToolBar*) child;
411 if (toolBar->GetWindowStyle() & wxTB_DOCKABLE)
412 {
413 gtk_signal_connect( GTK_OBJECT(toolBar->m_widget), "child_attached",
414 GTK_SIGNAL_FUNC(gtk_toolbar_attached_callback), (gpointer)parent );
415
416 gtk_signal_connect( GTK_OBJECT(toolBar->m_widget), "child_detached",
417 GTK_SIGNAL_FUNC(gtk_toolbar_detached_callback), (gpointer)parent );
418 }
419 }
420 #endif // wxUSE_TOOLBAR
421 }
422 else
423 {
424 /* these are inside the client area */
425 gtk_pizza_put( GTK_PIZZA(parent->m_wxwindow),
426 GTK_WIDGET(child->m_widget),
427 child->m_x,
428 child->m_y,
429 child->m_width,
430 child->m_height );
431 }
432
433 /* resize on OnInternalIdle */
434 parent->GtkUpdateSize();
435 }
436
437 // ----------------------------------------------------------------------------
438 // wxFrame creation
439 // ----------------------------------------------------------------------------
440
441 void wxFrame::Init()
442 {
443 m_sizeSet = FALSE;
444 m_miniEdge = 0;
445 m_miniTitle = 0;
446 m_mainWidget = (GtkWidget*) NULL;
447 m_menuBarDetached = FALSE;
448 m_toolBarDetached = FALSE;
449 m_insertInClientArea = TRUE;
450 m_isIconized = FALSE;
451 m_fsIsShowing = FALSE;
452 }
453
454 bool wxFrame::Create( wxWindow *parent,
455 wxWindowID id,
456 const wxString &title,
457 const wxPoint &pos,
458 const wxSize &size,
459 long style,
460 const wxString &name )
461 {
462 wxTopLevelWindows.Append( this );
463
464 m_needParent = FALSE;
465
466 if (!PreCreation( parent, pos, size ) ||
467 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
468 {
469 wxFAIL_MSG( wxT("wxFrame creation failed") );
470 return FALSE;
471 }
472
473 m_title = title;
474
475 m_insertCallback = (wxInsertChildFunction) wxInsertChildInFrame;
476
477 GtkWindowType win_type = GTK_WINDOW_TOPLEVEL;
478
479 if (style & wxFRAME_TOOL_WINDOW)
480 win_type = GTK_WINDOW_POPUP;
481
482 m_widget = gtk_window_new( win_type );
483
484 if ((m_parent) && (HasFlag(wxFRAME_FLOAT_ON_PARENT)) && (GTK_IS_WINDOW(m_parent->m_widget)))
485 gtk_window_set_transient_for( GTK_WINDOW(m_widget), GTK_WINDOW(m_parent->m_widget) );
486
487 if (!name.IsEmpty())
488 gtk_window_set_wmclass( GTK_WINDOW(m_widget), name.mb_str(), name.mb_str() );
489
490 #ifdef __WXDEBUG__
491 debug_focus_in( m_widget, wxT("wxFrame::m_widget"), name );
492 #endif
493
494 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
495 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
496
497 gtk_signal_connect( GTK_OBJECT(m_widget), "delete_event",
498 GTK_SIGNAL_FUNC(gtk_frame_delete_callback), (gpointer)this );
499
500 /* m_mainWidget holds the toolbar, the menubar and the client area */
501 m_mainWidget = gtk_pizza_new();
502 gtk_widget_show( m_mainWidget );
503 GTK_WIDGET_UNSET_FLAGS( m_mainWidget, GTK_CAN_FOCUS );
504 gtk_container_add( GTK_CONTAINER(m_widget), m_mainWidget );
505
506 /* for m_mainWidget themes */
507 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "expose_event",
508 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
509 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "draw",
510 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
511
512 #ifdef __WXDEBUG__
513 debug_focus_in( m_mainWidget, wxT("wxFrame::m_mainWidget"), name );
514 #endif
515
516 /* m_wxwindow only represents the client area without toolbar and menubar */
517 m_wxwindow = gtk_pizza_new();
518 gtk_widget_show( m_wxwindow );
519 gtk_container_add( GTK_CONTAINER(m_mainWidget), m_wxwindow );
520
521 #ifdef __WXDEBUG__
522 debug_focus_in( m_wxwindow, wxT("wxFrame::m_wxwindow"), name );
523 #endif
524
525 /* we donm't allow the frame to get the focus as otherwise
526 the frame will grabit at arbitrary fcous changes. */
527 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
528
529 if (m_parent) m_parent->AddChild( this );
530
531 /* the user resized the frame by dragging etc. */
532 gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
533 GTK_SIGNAL_FUNC(gtk_frame_size_callback), (gpointer)this );
534
535 PostCreation();
536
537 if ((m_x != -1) || (m_y != -1))
538 gtk_widget_set_uposition( m_widget, m_x, m_y );
539 gtk_widget_set_usize( m_widget, m_width, m_height );
540
541 /* we cannot set MWM hints and icons before the widget has
542 been realized, so we do this directly after realization */
543 gtk_signal_connect( GTK_OBJECT(m_widget), "realize",
544 GTK_SIGNAL_FUNC(gtk_frame_realized_callback), (gpointer) this );
545
546 /* the only way to get the window size is to connect to this event */
547 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
548 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
549
550 /* map and unmap for iconized state */
551 gtk_signal_connect( GTK_OBJECT(m_widget), "map_event",
552 GTK_SIGNAL_FUNC(gtk_frame_map_callback), (gpointer)this );
553 gtk_signal_connect( GTK_OBJECT(m_widget), "unmap_event",
554 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback), (gpointer)this );
555
556 /* the only way to get the window size is to connect to this event */
557 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
558 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
559
560 /* disable native tab traversal */
561 gtk_signal_connect( GTK_OBJECT(m_widget), "focus",
562 GTK_SIGNAL_FUNC(gtk_frame_focus_callback), (gpointer)this );
563
564 return TRUE;
565 }
566
567 wxFrame::~wxFrame()
568 {
569 m_isBeingDeleted = TRUE;
570
571 DeleteAllBars();
572
573 wxTopLevelWindows.DeleteObject( this );
574
575 if (wxTheApp->GetTopWindow() == this)
576 wxTheApp->SetTopWindow( (wxWindow*) NULL );
577
578 if ((wxTopLevelWindows.Number() == 0) &&
579 (wxTheApp->GetExitOnFrameDelete()))
580 {
581 wxTheApp->ExitMainLoop();
582 }
583 }
584
585 bool wxFrame::ShowFullScreen(bool show, long style )
586 {
587 if (show == m_fsIsShowing) return FALSE; // return what?
588
589 m_fsIsShowing = show;
590
591 if (show)
592 {
593 m_fsSaveStyle = m_windowStyle;
594 m_fsSaveFlag = style;
595 GetPosition( &m_fsSaveFrame.x, &m_fsSaveFrame.y );
596 GetSize( &m_fsSaveFrame.width, &m_fsSaveFrame.height );
597
598 gtk_widget_hide( m_widget );
599 gtk_widget_unrealize( m_widget );
600
601 m_windowStyle = wxSIMPLE_BORDER;
602
603 int x;
604 int y;
605 wxDisplaySize( &x, &y );
606 SetSize( 0, 0, x, y );
607
608 gtk_widget_realize( m_widget );
609 gtk_widget_show( m_widget );
610 }
611 else
612 {
613 gtk_widget_hide( m_widget );
614 gtk_widget_unrealize( m_widget );
615
616 m_windowStyle = m_fsSaveStyle;
617
618 SetSize( m_fsSaveFrame.x, m_fsSaveFrame.y, m_fsSaveFrame.width, m_fsSaveFrame.height );
619
620 gtk_widget_realize( m_widget );
621 gtk_widget_show( m_widget );
622 }
623
624 return TRUE;
625 }
626
627 // ----------------------------------------------------------------------------
628 // overridden wxWindow methods
629 // ----------------------------------------------------------------------------
630
631 bool wxFrame::Show( bool show )
632 {
633 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
634
635 if (show && !m_sizeSet)
636 {
637 /* by calling GtkOnSize here, we don't have to call
638 either after showing the frame, which would entail
639 much ugly flicker or from within the size_allocate
640 handler, because GTK 1.1.X forbids that. */
641
642 GtkOnSize( m_x, m_y, m_width, m_height );
643 }
644
645 return wxWindow::Show( show );
646 }
647
648 void wxFrame::DoMoveWindow(int WXUNUSED(x), int WXUNUSED(y), int WXUNUSED(width), int WXUNUSED(height) )
649 {
650 wxFAIL_MSG( wxT("DoMoveWindow called for wxFrame") );
651 }
652
653 void wxFrame::DoSetSize( int x, int y, int width, int height, int sizeFlags )
654 {
655 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
656
657 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
658 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
659
660 /* avoid recursions */
661 if (m_resizing)
662 return;
663 m_resizing = TRUE;
664
665 int old_x = m_x;
666 int old_y = m_y;
667
668 int old_width = m_width;
669 int old_height = m_height;
670
671 if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
672 {
673 if (x != -1) m_x = x;
674 if (y != -1) m_y = y;
675 if (width != -1) m_width = width;
676 if (height != -1) m_height = height;
677 }
678 else
679 {
680 m_x = x;
681 m_y = y;
682 m_width = width;
683 m_height = height;
684 }
685
686 /*
687 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
688 {
689 if (width == -1) m_width = 80;
690 }
691
692 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
693 {
694 if (height == -1) m_height = 26;
695 }
696 */
697
698 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
699 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
700 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
701 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
702
703 if ((m_x != -1) || (m_y != -1))
704 {
705 if ((m_x != old_x) || (m_y != old_y))
706 {
707 gtk_widget_set_uposition( m_widget, m_x, m_y );
708 }
709 }
710
711 if ((m_width != old_width) || (m_height != old_height))
712 {
713 gtk_widget_set_usize( m_widget, m_width, m_height );
714
715 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
716 done either directly before the frame is shown or in idle time
717 so that different calls to SetSize() don't lead to flicker. */
718 m_sizeSet = FALSE;
719 }
720
721 m_resizing = FALSE;
722 }
723
724 void wxFrame::DoGetClientSize( int *width, int *height ) const
725 {
726 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
727
728 wxWindow::DoGetClientSize( width, height );
729 if (height)
730 {
731 /* menu bar */
732 if (m_frameMenuBar)
733 {
734 if (!m_menuBarDetached)
735 (*height) -= wxMENU_HEIGHT;
736 else
737 (*height) -= wxPLACE_HOLDER;
738 }
739
740 #if wxUSE_STATUSBAR
741 /* status bar */
742 if (m_frameStatusBar && m_frameStatusBar->IsShown()) (*height) -= wxSTATUS_HEIGHT;
743 #endif // wxUSE_STATUSBAR
744
745 #if wxUSE_TOOLBAR
746 /* tool bar */
747 if (m_frameToolBar && m_frameToolBar->IsShown())
748 {
749 if (m_toolBarDetached)
750 {
751 *height -= wxPLACE_HOLDER;
752 }
753 else
754 {
755 int x, y;
756 m_frameToolBar->GetSize( &x, &y );
757 if ( m_frameToolBar->GetWindowStyle() & wxTB_VERTICAL )
758 {
759 *width -= x;
760 }
761 else
762 {
763 *height -= y;
764 }
765 }
766 }
767 #endif // wxUSE_TOOLBAR
768
769 /* mini edge */
770 *height -= m_miniEdge*2 + m_miniTitle;
771 }
772 if (width)
773 {
774 *width -= m_miniEdge*2;
775 }
776 }
777
778 void wxFrame::DoSetClientSize( int width, int height )
779 {
780 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
781
782 /* menu bar */
783 if (m_frameMenuBar)
784 {
785 if (!m_menuBarDetached)
786 height += wxMENU_HEIGHT;
787 else
788 height += wxPLACE_HOLDER;
789 }
790
791 #if wxUSE_STATUSBAR
792 /* status bar */
793 if (m_frameStatusBar && m_frameStatusBar->IsShown()) height += wxSTATUS_HEIGHT;
794 #endif
795
796 #if wxUSE_TOOLBAR
797 /* tool bar */
798 if (m_frameToolBar && m_frameToolBar->IsShown())
799 {
800 if (m_toolBarDetached)
801 {
802 height += wxPLACE_HOLDER;
803 }
804 else
805 {
806 int x, y;
807 m_frameToolBar->GetSize( &x, &y );
808 if ( m_frameToolBar->GetWindowStyle() & wxTB_VERTICAL )
809 {
810 width += x;
811 }
812 else
813 {
814 height += y;
815 }
816 }
817 }
818 #endif
819
820 DoSetSize( -1, -1, width + m_miniEdge*2, height + m_miniEdge*2 + m_miniTitle, 0 );
821 }
822
823 void wxFrame::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y),
824 int width, int height )
825 {
826 // due to a bug in gtk, x,y are always 0
827 // m_x = x;
828 // m_y = y;
829
830 /* avoid recursions */
831 if (m_resizing) return;
832 m_resizing = TRUE;
833
834 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
835 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
836
837 m_width = width;
838 m_height = height;
839
840 /* space occupied by m_frameToolBar and m_frameMenuBar */
841 int client_area_x_offset = 0,
842 client_area_y_offset = 0;
843
844 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
845 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
846 set in wxFrame::Create so it is used to check what kind of frame we
847 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
848 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
849 importantly) m_mainWidget */
850
851 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
852 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
853 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
854 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
855
856 if (m_mainWidget)
857 {
858 /* set size hints */
859 gint flag = 0; // GDK_HINT_POS;
860 if ((m_minWidth != -1) || (m_minHeight != -1)) flag |= GDK_HINT_MIN_SIZE;
861 if ((m_maxWidth != -1) || (m_maxHeight != -1)) flag |= GDK_HINT_MAX_SIZE;
862 GdkGeometry geom;
863 geom.min_width = m_minWidth;
864 geom.min_height = m_minHeight;
865 geom.max_width = m_maxWidth;
866 geom.max_height = m_maxHeight;
867 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget),
868 (GtkWidget*) NULL,
869 &geom,
870 (GdkWindowHints) flag );
871
872 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
873 * menubar, the toolbar and the client area, which is represented by
874 * m_wxwindow.
875 * this hurts in the eye, but I don't want to call SetSize()
876 * because I don't want to call any non-native functions here. */
877
878 if (m_frameMenuBar)
879 {
880 int xx = m_miniEdge;
881 int yy = m_miniEdge + m_miniTitle;
882 int ww = m_width - 2*m_miniEdge;
883 int hh = wxMENU_HEIGHT;
884 if (m_menuBarDetached) hh = wxPLACE_HOLDER;
885 m_frameMenuBar->m_x = xx;
886 m_frameMenuBar->m_y = yy;
887 m_frameMenuBar->m_width = ww;
888 m_frameMenuBar->m_height = hh;
889 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
890 m_frameMenuBar->m_widget,
891 xx, yy, ww, hh );
892 client_area_y_offset += hh;
893 }
894
895 #if wxUSE_TOOLBAR
896 if ((m_frameToolBar) && m_frameToolBar->IsShown() &&
897 (m_frameToolBar->m_widget->parent == m_mainWidget))
898 {
899 int xx = m_miniEdge;
900 int yy = m_miniEdge + m_miniTitle;
901 if (m_frameMenuBar)
902 {
903 if (!m_menuBarDetached)
904 yy += wxMENU_HEIGHT;
905 else
906 yy += wxPLACE_HOLDER;
907 }
908
909 m_frameToolBar->m_x = xx;
910 m_frameToolBar->m_y = yy;
911
912 /* don't change the toolbar's reported height/width */
913 int ww, hh;
914 if ( m_frameToolBar->GetWindowStyle() & wxTB_VERTICAL )
915 {
916 ww = m_toolBarDetached ? wxPLACE_HOLDER
917 : m_frameToolBar->m_width;
918 hh = m_height - 2*m_miniEdge;
919
920 client_area_x_offset += ww;
921 }
922 else
923 {
924 ww = m_width - 2*m_miniEdge;
925 hh = m_toolBarDetached ? wxPLACE_HOLDER
926 : m_frameToolBar->m_height;
927
928 client_area_y_offset += hh;
929 }
930
931 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
932 m_frameToolBar->m_widget,
933 xx, yy, ww, hh );
934 }
935 #endif // wxUSE_TOOLBAR
936
937 int client_x = client_area_x_offset + m_miniEdge;
938 int client_y = client_area_y_offset + m_miniEdge + m_miniTitle;
939 int client_w = m_width - client_area_x_offset - 2*m_miniEdge;
940 int client_h = m_height - client_area_y_offset- 2*m_miniEdge - m_miniTitle;
941 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
942 m_wxwindow,
943 client_x, client_y, client_w, client_h );
944 }
945 else
946 {
947 /* if there is no m_mainWidget between m_widget and m_wxwindow there
948 is no need to set the size or position of m_wxwindow. */
949 }
950
951 #if wxUSE_STATUSBAR
952 if (m_frameStatusBar && m_frameStatusBar->IsShown())
953 {
954 int xx = 0 + m_miniEdge;
955 int yy = m_height - wxSTATUS_HEIGHT - m_miniEdge - client_area_y_offset;
956 int ww = m_width - 2*m_miniEdge;
957 int hh = wxSTATUS_HEIGHT;
958 m_frameStatusBar->m_x = xx;
959 m_frameStatusBar->m_y = yy;
960 m_frameStatusBar->m_width = ww;
961 m_frameStatusBar->m_height = hh;
962 gtk_pizza_set_size( GTK_PIZZA(m_wxwindow),
963 m_frameStatusBar->m_widget,
964 xx, yy, ww, hh );
965 gtk_widget_draw( m_frameStatusBar->m_widget, (GdkRectangle*) NULL );
966 }
967 #endif
968
969 m_sizeSet = TRUE;
970
971 // send size event to frame
972 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
973 event.SetEventObject( this );
974 GetEventHandler()->ProcessEvent( event );
975
976 // send size event to status bar
977 if (m_frameStatusBar)
978 {
979 wxSizeEvent event2( wxSize(m_frameStatusBar->m_width,m_frameStatusBar->m_height), m_frameStatusBar->GetId() );
980 event2.SetEventObject( m_frameStatusBar );
981 m_frameStatusBar->GetEventHandler()->ProcessEvent( event2 );
982 }
983
984 m_resizing = FALSE;
985 }
986
987 void wxFrame::MakeModal( bool modal )
988 {
989 if (modal)
990 gtk_grab_add( m_widget );
991 else
992 gtk_grab_remove( m_widget );
993 }
994
995 void wxFrame::OnInternalIdle()
996 {
997 if (!m_sizeSet && GTK_WIDGET_REALIZED(m_wxwindow))
998 {
999 GtkOnSize( m_x, m_y, m_width, m_height );
1000
1001 // we'll come back later
1002 if (g_isIdle)
1003 wxapp_install_idle_handler();
1004 return;
1005 }
1006
1007 if (m_frameMenuBar) m_frameMenuBar->OnInternalIdle();
1008 #if wxUSE_TOOLBAR
1009 if (m_frameToolBar) m_frameToolBar->OnInternalIdle();
1010 #endif
1011 #if wxUSE_STATUSBAR
1012 if (m_frameStatusBar) m_frameStatusBar->OnInternalIdle();
1013 #endif
1014
1015 wxWindow::OnInternalIdle();
1016 }
1017
1018 // ----------------------------------------------------------------------------
1019 // menu/tool/status bar stuff
1020 // ----------------------------------------------------------------------------
1021
1022 void wxFrame::SetMenuBar( wxMenuBar *menuBar )
1023 {
1024 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
1025 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
1026
1027 if (menuBar == m_frameMenuBar)
1028 return;
1029
1030 if (m_frameMenuBar)
1031 {
1032 m_frameMenuBar->UnsetInvokingWindow( this );
1033
1034 if (m_frameMenuBar->GetWindowStyle() & wxMB_DOCKABLE)
1035 {
1036 gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar->m_widget),
1037 GTK_SIGNAL_FUNC(gtk_menu_attached_callback), (gpointer)this );
1038
1039 gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar->m_widget),
1040 GTK_SIGNAL_FUNC(gtk_menu_detached_callback), (gpointer)this );
1041 }
1042
1043 gtk_container_remove( GTK_CONTAINER(m_mainWidget), m_frameMenuBar->m_widget );
1044 gtk_widget_ref( m_frameMenuBar->m_widget );
1045 gtk_widget_unparent( m_frameMenuBar->m_widget );
1046 }
1047
1048 m_frameMenuBar = menuBar;
1049
1050 if (m_frameMenuBar)
1051 {
1052 m_frameMenuBar->SetInvokingWindow( this );
1053
1054 m_frameMenuBar->SetParent(this);
1055 gtk_pizza_put( GTK_PIZZA(m_mainWidget),
1056 m_frameMenuBar->m_widget,
1057 m_frameMenuBar->m_x,
1058 m_frameMenuBar->m_y,
1059 m_frameMenuBar->m_width,
1060 m_frameMenuBar->m_height );
1061
1062 if (menuBar->GetWindowStyle() & wxMB_DOCKABLE)
1063 {
1064 gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_attached",
1065 GTK_SIGNAL_FUNC(gtk_menu_attached_callback), (gpointer)this );
1066
1067 gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_detached",
1068 GTK_SIGNAL_FUNC(gtk_menu_detached_callback), (gpointer)this );
1069 }
1070
1071 m_frameMenuBar->Show( TRUE );
1072 }
1073
1074 /* resize window in OnInternalIdle */
1075 m_sizeSet = FALSE;
1076 }
1077
1078 #if wxUSE_TOOLBAR
1079 wxToolBar* wxFrame::CreateToolBar( long style, wxWindowID id, const wxString& name )
1080 {
1081 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
1082
1083 m_insertInClientArea = FALSE;
1084
1085 m_frameToolBar = wxFrameBase::CreateToolBar( style, id, name );
1086
1087 m_insertInClientArea = TRUE;
1088
1089 m_sizeSet = FALSE;
1090
1091 return m_frameToolBar;
1092 }
1093
1094 void wxFrame::SetToolBar(wxToolBar *toolbar)
1095 {
1096 wxFrameBase::SetToolBar(toolbar);
1097
1098 if (m_frameToolBar)
1099 {
1100 /* insert into toolbar area if not already there */
1101 if ((m_frameToolBar->m_widget->parent) &&
1102 (m_frameToolBar->m_widget->parent != m_mainWidget))
1103 {
1104 GetChildren().DeleteObject( m_frameToolBar );
1105
1106 gtk_widget_reparent( m_frameToolBar->m_widget, m_mainWidget );
1107 GtkUpdateSize();
1108 }
1109 }
1110 }
1111
1112 #endif // wxUSE_TOOLBAR
1113
1114 #if wxUSE_STATUSBAR
1115
1116 wxStatusBar* wxFrame::CreateStatusBar(int number,
1117 long style,
1118 wxWindowID id,
1119 const wxString& name)
1120 {
1121 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
1122
1123 // because it will change when toolbar is added
1124 m_sizeSet = FALSE;
1125
1126 return wxFrameBase::CreateStatusBar( number, style, id, name );
1127 }
1128
1129 void wxFrame::PositionStatusBar()
1130 {
1131 if ( !m_frameStatusBar )
1132 return;
1133
1134 m_sizeSet = FALSE;
1135 }
1136 #endif // wxUSE_STATUSBAR
1137
1138 // ----------------------------------------------------------------------------
1139 // frame title/icon
1140 // ----------------------------------------------------------------------------
1141
1142 void wxFrame::SetTitle( const wxString &title )
1143 {
1144 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
1145
1146 m_title = title;
1147 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
1148 }
1149
1150 void wxFrame::SetIcon( const wxIcon &icon )
1151 {
1152 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
1153
1154 wxFrameBase::SetIcon(icon);
1155
1156 if ( !m_icon.Ok() )
1157 return;
1158
1159 if (!m_widget->window)
1160 return;
1161
1162 wxMask *mask = icon.GetMask();
1163 GdkBitmap *bm = (GdkBitmap *) NULL;
1164 if (mask) bm = mask->GetBitmap();
1165
1166 gdk_window_set_icon( m_widget->window, (GdkWindow *) NULL, icon.GetPixmap(), bm );
1167 }
1168
1169 // ----------------------------------------------------------------------------
1170 // frame state: maximized/iconized/normal
1171 // ----------------------------------------------------------------------------
1172
1173 void wxFrame::Maximize(bool WXUNUSED(maximize))
1174 {
1175 wxFAIL_MSG( _T("not implemented") );
1176 }
1177
1178 bool wxFrame::IsMaximized() const
1179 {
1180 wxFAIL_MSG( _T("not implemented") );
1181
1182 return FALSE;
1183 }
1184
1185 void wxFrame::Restore()
1186 {
1187 wxFAIL_MSG( _T("not implemented") );
1188 }
1189
1190 void wxFrame::Iconize( bool iconize )
1191 {
1192 if (iconize)
1193 {
1194 XIconifyWindow( GDK_WINDOW_XDISPLAY( m_widget->window ),
1195 GDK_WINDOW_XWINDOW( m_widget->window ),
1196 DefaultScreen( GDK_DISPLAY() ) );
1197 }
1198 }
1199
1200 bool wxFrame::IsIconized() const
1201 {
1202 return m_isIconized;
1203 }