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