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