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