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