]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/frame.cpp
*** empty log message ***
[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
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;
5b8a521e 129 win->GtkUpdateSize();
121a3581 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
a56fcaaf 142 if ((g_openDialogs == 0) && (win->IsEnabled()))
2d68e1b4 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;
5b8a521e 157 win->GtkUpdateSize();
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;
5b8a521e 169 win->GtkUpdateSize();
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
5b8a521e 183 win->GtkUpdateSize();
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;
5b8a521e 198 win->GtkUpdateSize();
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 359
caf51f95 360#if wxUSE_TOOLBAR_NATIVE
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 */
5b8a521e 389 parent->GtkUpdateSize();
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
f59d80ca
RR
507 if ((wxTopLevelWindows.Number() == 0) &&
508 (wxTheApp->GetExitOnFrameDelete()))
509 {
0d2a2b60 510 wxTheApp->ExitMainLoop();
f59d80ca 511 }
362c6693 512}
ed7a557b 513
7c0ea335
VZ
514// ----------------------------------------------------------------------------
515// overridden wxWindow methods
516// ----------------------------------------------------------------------------
517
debe6624 518bool wxFrame::Show( bool show )
c801d85f 519{
223d09f6 520 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
8bbe427f 521
35178437 522 if (show && !m_sizeSet)
fb1585ae 523 {
e27ce4e9
RR
524 /* by calling GtkOnSize here, we don't have to call
525 either after showing the frame, which would entail
f362b96d 526 much ugly flicker or from within the size_allocate
e27ce4e9 527 handler, because GTK 1.1.X forbids that. */
8bbe427f 528
35178437 529 GtkOnSize( m_x, m_y, m_width, m_height );
fb1585ae 530 }
8bbe427f 531
fb1585ae 532 return wxWindow::Show( show );
362c6693 533}
c801d85f 534
23efdd02
RR
535void wxFrame::DoMoveWindow(int WXUNUSED(x), int WXUNUSED(y), int WXUNUSED(width), int WXUNUSED(height) )
536{
537 wxFAIL_MSG( wxT("DoMoveWindow called for wxFrame") );
538}
539
bfc6fde4 540void wxFrame::DoSetSize( int x, int y, int width, int height, int sizeFlags )
903f689b 541{
223d09f6 542 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
8bbe427f 543
ab2b3dd4 544 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
223d09f6 545 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
88ac883a 546
ab2b3dd4 547 /* avoid recursions */
7c0ea335
VZ
548 if (m_resizing)
549 return;
fb1585ae
RR
550 m_resizing = TRUE;
551
552 int old_x = m_x;
553 int old_y = m_y;
7beba2fc 554
fb1585ae
RR
555 int old_width = m_width;
556 int old_height = m_height;
8bbe427f 557
85ad5eb5 558 if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
fb1585ae
RR
559 {
560 if (x != -1) m_x = x;
561 if (y != -1) m_y = y;
562 if (width != -1) m_width = width;
563 if (height != -1) m_height = height;
564 }
565 else
566 {
567 m_x = x;
568 m_y = y;
569 m_width = width;
570 m_height = height;
571 }
572
11e1c70d 573/*
fb1585ae
RR
574 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
575 {
576 if (width == -1) m_width = 80;
577 }
578
579 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
580 {
581 if (height == -1) m_height = 26;
582 }
11e1c70d 583*/
8bbe427f 584
fb1585ae
RR
585 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
586 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
0c77152e
RR
587 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
588 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
fb1585ae
RR
589
590 if ((m_x != -1) || (m_y != -1))
591 {
8bbe427f 592 if ((m_x != old_x) || (m_y != old_y))
0138c2de 593 {
8487f887 594 gtk_widget_set_uposition( m_widget, m_x, m_y );
0138c2de 595 }
fb1585ae 596 }
8bbe427f 597
fb1585ae
RR
598 if ((m_width != old_width) || (m_height != old_height))
599 {
ab2b3dd4 600 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
f03fc89f
VZ
601 done either directly before the frame is shown or in idle time
602 so that different calls to SetSize() don't lead to flicker. */
de8113d9 603 m_sizeSet = FALSE;
fb1585ae 604 }
8bbe427f 605
fb1585ae 606 m_resizing = FALSE;
903f689b
RR
607}
608
f9241296 609void wxFrame::DoGetClientSize( int *width, int *height ) const
c801d85f 610{
223d09f6 611 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
8bbe427f 612
f9241296 613 wxWindow::DoGetClientSize( width, height );
fb1585ae 614 if (height)
46dc76ba 615 {
41ca191f
RR
616 /* menu bar */
617 if (m_frameMenuBar)
f03fc89f 618 {
88ac883a 619 if (!m_menuBarDetached)
f03fc89f
VZ
620 (*height) -= wxMENU_HEIGHT;
621 else
622 (*height) -= wxPLACE_HOLDER;
623 }
88ac883a 624
dcf924a3 625#if wxUSE_STATUSBAR
f03fc89f 626 /* status bar */
fb1585ae 627 if (m_frameStatusBar) (*height) -= wxSTATUS_HEIGHT;
93fa69f8 628#endif // wxUSE_STATUSBAR
88ac883a 629
dcf924a3 630#if wxUSE_TOOLBAR
f03fc89f 631 /* tool bar */
fb1585ae
RR
632 if (m_frameToolBar)
633 {
93fa69f8 634 if (m_toolBarDetached)
f03fc89f 635 {
93fa69f8 636 *height -= wxPLACE_HOLDER;
f03fc89f
VZ
637 }
638 else
93fa69f8
VZ
639 {
640 int x, y;
641 m_frameToolBar->GetSize( &x, &y );
642 if ( m_frameToolBar->GetWindowStyle() & wxTB_VERTICAL )
643 {
644 *width -= x;
645 }
646 else
647 {
648 *height -= y;
649 }
650 }
fb1585ae 651 }
93fa69f8 652#endif // wxUSE_TOOLBAR
88ac883a 653
f03fc89f 654 /* mini edge */
93fa69f8 655 *height -= m_miniEdge*2 + m_miniTitle;
b2b3ccc5
RR
656 }
657 if (width)
658 {
93fa69f8 659 *width -= m_miniEdge*2;
46dc76ba 660 }
362c6693 661}
c801d85f 662
bfc6fde4 663void wxFrame::DoSetClientSize( int width, int height )
b593568e 664{
223d09f6 665 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
8bbe427f 666
41ca191f
RR
667 /* menu bar */
668 if (m_frameMenuBar)
f03fc89f 669 {
88ac883a 670 if (!m_menuBarDetached)
f03fc89f
VZ
671 height += wxMENU_HEIGHT;
672 else
673 height += wxPLACE_HOLDER;
674 }
88ac883a 675
dcf924a3 676#if wxUSE_STATUSBAR
f03fc89f 677 /* status bar */
41ca191f 678 if (m_frameStatusBar) height += wxSTATUS_HEIGHT;
dcf924a3 679#endif
88ac883a 680
dcf924a3 681#if wxUSE_TOOLBAR
f03fc89f 682 /* tool bar */
41ca191f
RR
683 if (m_frameToolBar)
684 {
93fa69f8 685 if (m_toolBarDetached)
f03fc89f 686 {
93fa69f8 687 height += wxPLACE_HOLDER;
f03fc89f
VZ
688 }
689 else
93fa69f8
VZ
690 {
691 int x, y;
692 m_frameToolBar->GetSize( &x, &y );
693 if ( m_frameToolBar->GetWindowStyle() & wxTB_VERTICAL )
694 {
695 width += x;
696 }
697 else
698 {
699 height += y;
700 }
701 }
41ca191f 702 }
dcf924a3 703#endif
88ac883a 704
3017f78d 705 DoSetSize( -1, -1, width + m_miniEdge*2, height + m_miniEdge*2 + m_miniTitle, 0 );
362c6693 706}
b593568e 707
7c0ea335
VZ
708void wxFrame::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y),
709 int width, int height )
c801d85f 710{
f5368809
RR
711 // due to a bug in gtk, x,y are always 0
712 // m_x = x;
713 // m_y = y;
714
ab2b3dd4 715 /* avoid recursions */
e52f60e6
RR
716 if (m_resizing) return;
717 m_resizing = TRUE;
8bbe427f 718
ab2b3dd4 719 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
223d09f6 720 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
88ac883a 721
f5368809
RR
722 m_width = width;
723 m_height = height;
7beba2fc 724
ab2b3dd4 725 /* space occupied by m_frameToolBar and m_frameMenuBar */
93fa69f8
VZ
726 int client_area_x_offset = 0,
727 client_area_y_offset = 0;
8bbe427f 728
ab2b3dd4
RR
729 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
730 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
731 set in wxFrame::Create so it is used to check what kind of frame we
732 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
733 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
734 importantly) m_mainWidget */
88ac883a 735
ab2b3dd4 736 if (m_mainWidget)
f5368809 737 {
ab2b3dd4
RR
738 /* check if size is in legal range */
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;
743
744 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
745 * menubar, the toolbar and the client area, which is represented by
746 * m_wxwindow.
747 * this hurts in the eye, but I don't want to call SetSize()
748 * because I don't want to call any non-native functions here. */
88ac883a 749
ab2b3dd4
RR
750 if (m_frameMenuBar)
751 {
752 int xx = m_miniEdge;
753 int yy = m_miniEdge + m_miniTitle;
754 int ww = m_width - 2*m_miniEdge;
41ca191f 755 int hh = wxMENU_HEIGHT;
f03fc89f 756 if (m_menuBarDetached) hh = wxPLACE_HOLDER;
121a3581
RR
757 m_frameMenuBar->m_x = xx;
758 m_frameMenuBar->m_y = yy;
759 m_frameMenuBar->m_width = ww;
760 m_frameMenuBar->m_height = hh;
da048e3d 761 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
88ac883a 762 m_frameMenuBar->m_widget,
f03fc89f
VZ
763 xx, yy, ww, hh );
764 client_area_y_offset += hh;
ab2b3dd4 765 }
88ac883a 766
dcf924a3 767#if wxUSE_TOOLBAR
11e1c70d 768 if ((m_frameToolBar) &&
7beba2fc 769 (m_frameToolBar->m_widget->parent == m_mainWidget))
ab2b3dd4
RR
770 {
771 int xx = m_miniEdge;
772 int yy = m_miniEdge + m_miniTitle;
41ca191f 773 if (m_frameMenuBar)
f03fc89f 774 {
88ac883a
VZ
775 if (!m_menuBarDetached)
776 yy += wxMENU_HEIGHT;
777 else
f03fc89f
VZ
778 yy += wxPLACE_HOLDER;
779 }
93fa69f8 780
121a3581
RR
781 m_frameToolBar->m_x = xx;
782 m_frameToolBar->m_y = yy;
93fa69f8
VZ
783
784 /* don't change the toolbar's reported height/width */
785 int ww, hh;
786 if ( m_frameToolBar->GetWindowStyle() & wxTB_VERTICAL )
787 {
788 ww = m_toolBarDetached ? wxPLACE_HOLDER
789 : m_frameToolBar->m_width;
790 hh = m_height - 2*m_miniEdge;
791
792 client_area_x_offset += ww;
793 }
794 else
795 {
796 ww = m_width - 2*m_miniEdge;
797 hh = m_toolBarDetached ? wxPLACE_HOLDER
798 : m_frameToolBar->m_height;
799
800 client_area_y_offset += hh;
801 }
802
da048e3d 803 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
88ac883a 804 m_frameToolBar->m_widget,
f03fc89f 805 xx, yy, ww, hh );
ab2b3dd4 806 }
93fa69f8 807#endif // wxUSE_TOOLBAR
88ac883a 808
93fa69f8 809 int client_x = client_area_x_offset + m_miniEdge;
f03fc89f 810 int client_y = client_area_y_offset + m_miniEdge + m_miniTitle;
93fa69f8 811 int client_w = m_width - client_area_x_offset - 2*m_miniEdge;
f03fc89f 812 int client_h = m_height - client_area_y_offset- 2*m_miniEdge - m_miniTitle;
da048e3d 813 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
88ac883a 814 m_wxwindow,
f03fc89f 815 client_x, client_y, client_w, client_h );
32a95f9f
RR
816 }
817 else
818 {
819 /* if there is no m_mainWidget between m_widget and m_wxwindow there
f03fc89f 820 is no need to set the size or position of m_wxwindow. */
f5368809 821 }
88ac883a 822
dcf924a3 823#if wxUSE_STATUSBAR
f5368809
RR
824 if (m_frameStatusBar)
825 {
b2b3ccc5 826 int xx = 0 + m_miniEdge;
f362b96d 827 int yy = m_height - wxSTATUS_HEIGHT - m_miniEdge - client_area_y_offset;
ac57418f
RR
828 int ww = m_width - 2*m_miniEdge;
829 int hh = wxSTATUS_HEIGHT;
121a3581
RR
830 m_frameStatusBar->m_x = xx;
831 m_frameStatusBar->m_y = yy;
832 m_frameStatusBar->m_width = ww;
833 m_frameStatusBar->m_height = hh;
da048e3d 834 gtk_pizza_set_size( GTK_PIZZA(m_wxwindow),
7c0ea335
VZ
835 m_frameStatusBar->m_widget,
836 xx, yy, ww, hh );
b6fa52db 837 gtk_widget_draw( m_frameStatusBar->m_widget, (GdkRectangle*) NULL );
f5368809 838 }
dcf924a3 839#endif
8bbe427f 840
de8113d9
RR
841 /* we actually set the size of a frame here and no-where else */
842 gtk_widget_set_usize( m_widget, m_width, m_height );
88ac883a 843
54517652 844 m_sizeSet = TRUE;
7beba2fc 845
54517652 846 // send size event to frame
43a18898
RR
847 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
848 event.SetEventObject( this );
e52f60e6 849 GetEventHandler()->ProcessEvent( event );
8bbe427f 850
54517652 851 // send size event to status bar
5aa5e35a
RR
852 if (m_frameStatusBar)
853 {
a2053b27 854 wxSizeEvent event2( wxSize(m_frameStatusBar->m_width,m_frameStatusBar->m_height), m_frameStatusBar->GetId() );
5aa5e35a
RR
855 event2.SetEventObject( m_frameStatusBar );
856 m_frameStatusBar->GetEventHandler()->ProcessEvent( event2 );
857 }
884470b1 858
e52f60e6
RR
859 m_resizing = FALSE;
860}
861
ca26177c
RR
862void wxFrame::MakeModal( bool modal )
863{
864 if (modal)
ca26177c 865 gtk_grab_add( m_widget );
ca26177c 866 else
c25ccf85 867 gtk_grab_remove( m_widget );
ca26177c
RR
868}
869
9390a202 870void wxFrame::OnInternalIdle()
e52f60e6 871{
1b3667ab 872 if (!m_sizeSet && GTK_WIDGET_REALIZED(m_wxwindow))
54517652 873 {
e52f60e6 874 GtkOnSize( m_x, m_y, m_width, m_height );
7beba2fc
VZ
875
876 // we'll come back later
54517652
RR
877 if (g_isIdle)
878 wxapp_install_idle_handler();
7beba2fc 879 return;
54517652 880 }
88ac883a 881
082b2798 882 if (m_frameMenuBar) m_frameMenuBar->OnInternalIdle();
dcf924a3 883#if wxUSE_TOOLBAR
082b2798 884 if (m_frameToolBar) m_frameToolBar->OnInternalIdle();
dcf924a3
RR
885#endif
886#if wxUSE_STATUSBAR
082b2798 887 if (m_frameStatusBar) m_frameStatusBar->OnInternalIdle();
dcf924a3 888#endif
5e014a0c
RR
889
890 wxWindow::OnInternalIdle();
362c6693 891}
c801d85f 892
7c0ea335
VZ
893// ----------------------------------------------------------------------------
894// menu/tool/status bar stuff
895// ----------------------------------------------------------------------------
c801d85f 896
c801d85f
KB
897void wxFrame::SetMenuBar( wxMenuBar *menuBar )
898{
223d09f6
KB
899 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
900 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
8bbe427f 901
186baeb2
RR
902 if (menuBar == m_frameMenuBar)
903 return;
904
905 if (m_frameMenuBar)
906 {
907 m_frameMenuBar->UnsetInvokingWindow( this );
908
909 if (m_frameMenuBar->GetWindowStyle() & wxMB_DOCKABLE)
910 {
911 gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar->m_widget),
912 GTK_SIGNAL_FUNC(gtk_menu_attached_callback), (gpointer)this );
913
914 gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar->m_widget),
915 GTK_SIGNAL_FUNC(gtk_menu_detached_callback), (gpointer)this );
916 }
917
918 gtk_container_remove( GTK_CONTAINER(m_mainWidget), m_frameMenuBar->m_widget );
919 gtk_widget_ref( m_frameMenuBar->m_widget );
920 gtk_widget_unparent( m_frameMenuBar->m_widget );
921 }
922
f5368809 923 m_frameMenuBar = menuBar;
8bbe427f 924
f5368809 925 if (m_frameMenuBar)
30dea054 926 {
5bd9e519 927 m_frameMenuBar->SetInvokingWindow( this );
8bbe427f 928
186baeb2
RR
929 m_frameMenuBar->SetParent(this);
930 gtk_pizza_put( GTK_PIZZA(m_mainWidget),
88ac883a
VZ
931 m_frameMenuBar->m_widget,
932 m_frameMenuBar->m_x,
a2053b27
RR
933 m_frameMenuBar->m_y,
934 m_frameMenuBar->m_width,
935 m_frameMenuBar->m_height );
88ac883a 936
186baeb2
RR
937 if (menuBar->GetWindowStyle() & wxMB_DOCKABLE)
938 {
939 gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_attached",
940 GTK_SIGNAL_FUNC(gtk_menu_attached_callback), (gpointer)this );
7beba2fc 941
186baeb2
RR
942 gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_detached",
943 GTK_SIGNAL_FUNC(gtk_menu_detached_callback), (gpointer)this );
f5368809 944 }
186baeb2
RR
945
946 m_frameMenuBar->Show( TRUE );
716b7364 947 }
8bbe427f 948
1e133b7d 949 /* resize window in OnInternalIdle */
5b077d48 950 m_sizeSet = FALSE;
362c6693 951}
c801d85f 952
88ac883a 953#if wxUSE_TOOLBAR
6bc8a1c8 954wxToolBar* wxFrame::CreateToolBar( long style, wxWindowID id, const wxString& name )
46dc76ba 955{
223d09f6 956 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
8bbe427f 957
6bc8a1c8 958 m_insertInClientArea = FALSE;
88ac883a 959
7c0ea335 960 m_frameToolBar = wxFrameBase::CreateToolBar( style, id, name );
8bbe427f 961
7c0ea335
VZ
962 if (m_frameToolBar)
963 GetChildren().DeleteObject( m_frameToolBar );
88ac883a 964
6bc8a1c8 965 m_insertInClientArea = TRUE;
8bbe427f 966
5b077d48 967 m_sizeSet = FALSE;
8bbe427f 968
f5368809 969 return m_frameToolBar;
362c6693 970}
46dc76ba 971
7beba2fc
VZ
972void wxFrame::SetToolBar(wxToolBar *toolbar)
973{
7c0ea335
VZ
974 wxFrameBase::SetToolBar(toolbar);
975
307f16e8
RR
976 if (m_frameToolBar)
977 {
978 /* insert into toolbar area if not already there */
3017f78d
RR
979 if ((m_frameToolBar->m_widget->parent) &&
980 (m_frameToolBar->m_widget->parent != m_mainWidget))
307f16e8 981 {
3017f78d 982 GetChildren().DeleteObject( m_frameToolBar );
7beba2fc
VZ
983
984 gtk_widget_reparent( m_frameToolBar->m_widget, m_mainWidget );
5b8a521e 985 GtkUpdateSize();
7beba2fc 986 }
307f16e8
RR
987 }
988}
989
88ac883a 990#endif // wxUSE_TOOLBAR
46dc76ba 991
88ac883a 992#if wxUSE_STATUSBAR
8bbe427f 993
7c0ea335
VZ
994wxStatusBar* wxFrame::CreateStatusBar(int number,
995 long style,
996 wxWindowID id,
997 const wxString& name)
c801d85f 998{
223d09f6 999 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
8bbe427f 1000
7c0ea335
VZ
1001 // because it will change when toolbar is added
1002 m_sizeSet = FALSE;
c801d85f 1003
7c0ea335 1004 return wxFrameBase::CreateStatusBar( number, style, id, name );
362c6693
RR
1005}
1006
8febdd39
RR
1007void wxFrame::PositionStatusBar()
1008{
1009 if ( !m_frameStatusBar )
1010 return;
1011
1012 m_sizeSet = FALSE;
1013}
88ac883a 1014#endif // wxUSE_STATUSBAR
c801d85f 1015
7c0ea335
VZ
1016// ----------------------------------------------------------------------------
1017// frame title/icon
1018// ----------------------------------------------------------------------------
c801d85f 1019
c801d85f
KB
1020void wxFrame::SetTitle( const wxString &title )
1021{
223d09f6 1022 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
8bbe427f 1023
f5368809 1024 m_title = title;
ed9b9841 1025 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
362c6693 1026}
c801d85f 1027
d355d3fe
RR
1028void wxFrame::SetIcon( const wxIcon &icon )
1029{
223d09f6 1030 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
8bbe427f 1031
7c0ea335 1032 wxFrameBase::SetIcon(icon);
8bbe427f 1033
7c0ea335
VZ
1034 if ( !m_icon.Ok() )
1035 return;
1036
1037 if (!m_widget->window)
1038 return;
58dea4b0 1039
f5368809
RR
1040 wxMask *mask = icon.GetMask();
1041 GdkBitmap *bm = (GdkBitmap *) NULL;
1042 if (mask) bm = mask->GetBitmap();
8bbe427f 1043
f5368809 1044 gdk_window_set_icon( m_widget->window, (GdkWindow *) NULL, icon.GetPixmap(), bm );
d355d3fe 1045}
b2b3ccc5 1046
7c0ea335
VZ
1047// ----------------------------------------------------------------------------
1048// frame state: maximized/iconized/normal (TODO)
1049// ----------------------------------------------------------------------------
1050
7beba2fc 1051void wxFrame::Maximize(bool WXUNUSED(maximize))
cd25b18c
RR
1052{
1053}
1054
7c0ea335
VZ
1055bool wxFrame::IsMaximized() const
1056{
1057 return FALSE;
1058}
1059
7beba2fc 1060void wxFrame::Restore()
cd25b18c
RR
1061{
1062}
1063
7beba2fc
VZ
1064void wxFrame::Iconize( bool iconize )
1065{
cd25b18c
RR
1066 if (iconize)
1067 {
1068 XIconifyWindow( GDK_WINDOW_XDISPLAY( m_widget->window ),
7beba2fc
VZ
1069 GDK_WINDOW_XWINDOW( m_widget->window ),
1070 DefaultScreen( GDK_DISPLAY() ) );
cd25b18c
RR
1071 }
1072}
1073
7beba2fc
VZ
1074bool wxFrame::IsIconized() const
1075{
1076 return FALSE;
cd25b18c 1077}