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