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