]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/frame.cpp
Added wxWindowBase::CentreOnParent to allow top level windows to be
[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
10#ifdef __GNUG__
fe4e9e6c 11 #pragma implementation "frame.h"
c801d85f
KB
12#endif
13
14#include "wx/frame.h"
15#include "wx/dialog.h"
16#include "wx/control.h"
17#include "wx/app.h"
cf4219e7
RR
18#include "wx/menu.h"
19#include "wx/toolbar.h"
20#include "wx/statusbr.h"
362c6693 21#include "wx/dcclient.h"
83624f79
RR
22
23#include "glib.h"
24#include "gdk/gdk.h"
25#include "gtk/gtk.h"
c801d85f 26#include "wx/gtk/win_gtk.h"
801aa178 27#include "gdk/gdkkeysyms.h"
c801d85f 28
2f2aa628
RR
29//-----------------------------------------------------------------------------
30// constants
31//-----------------------------------------------------------------------------
32
907789a0 33const int wxMENU_HEIGHT = 27;
c67daf87 34const int wxSTATUS_HEIGHT = 25;
41ca191f 35const int wxPLACE_HOLDER = 0;
c801d85f 36
acfd422a
RR
37//-----------------------------------------------------------------------------
38// idle system
39//-----------------------------------------------------------------------------
40
41extern void wxapp_install_idle_handler();
42extern bool g_isIdle;
43
2f2aa628
RR
44//-----------------------------------------------------------------------------
45// data
46//-----------------------------------------------------------------------------
47
c801d85f
KB
48extern wxList wxPendingDelete;
49
2e563988
RR
50//-----------------------------------------------------------------------------
51// debug
52//-----------------------------------------------------------------------------
53
54#ifdef __WXDEBUG__
55
56extern void debug_focus_in( GtkWidget* widget, const wxChar* name, const wxChar *window );
57
58#endif
59
c801d85f 60//-----------------------------------------------------------------------------
2f2aa628 61// "size_allocate"
c801d85f 62//-----------------------------------------------------------------------------
c801d85f 63
2f2aa628 64static void gtk_frame_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation* alloc, wxFrame *win )
ed7a557b 65{
88ac883a 66 if (g_isIdle)
121a3581 67 wxapp_install_idle_handler();
acfd422a 68
a2053b27 69 if (!win->m_hasVMT) return;
8bbe427f 70
121a3581
RR
71 if ((win->m_width != alloc->width) || (win->m_height != alloc->height))
72 {
73 win->m_width = alloc->width;
74 win->m_height = alloc->height;
75 win->UpdateSize();
76 }
362c6693 77}
c801d85f
KB
78
79//-----------------------------------------------------------------------------
2f2aa628
RR
80// "delete_event"
81//-----------------------------------------------------------------------------
c801d85f 82
2f2aa628 83static gint gtk_frame_delete_callback( GtkWidget *WXUNUSED(widget), GdkEvent *WXUNUSED(event), wxFrame *win )
ed7a557b 84{
88ac883a 85 if (g_isIdle)
121a3581 86 wxapp_install_idle_handler();
ed7a557b 87
fb1585ae 88 win->Close();
c801d85f 89
fb1585ae 90 return TRUE;
362c6693 91}
c801d85f 92
16bcc879
RR
93//-----------------------------------------------------------------------------
94// "child_attached" of menu bar
95//-----------------------------------------------------------------------------
96
97static void gtk_menu_attached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
98{
a2053b27 99 if (!win->m_hasVMT) return;
88ac883a 100
16bcc879 101 win->m_menuBarDetached = FALSE;
f03fc89f 102 win->UpdateSize();
16bcc879
RR
103}
104
105//-----------------------------------------------------------------------------
106// "child_detached" of menu bar
107//-----------------------------------------------------------------------------
108
109static void gtk_menu_detached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
110{
a2053b27 111 if (!win->m_hasVMT) return;
88ac883a 112
16bcc879 113 win->m_menuBarDetached = TRUE;
f03fc89f 114 win->UpdateSize();
16bcc879
RR
115}
116
88ac883a 117#if wxUSE_TOOLBAR
16bcc879
RR
118//-----------------------------------------------------------------------------
119// "child_attached" of tool bar
120//-----------------------------------------------------------------------------
121
122static void gtk_toolbar_attached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
123{
a2053b27 124 if (!win->m_hasVMT) return;
88ac883a 125
16bcc879 126 win->m_toolBarDetached = FALSE;
88ac883a 127
f03fc89f 128 win->UpdateSize();
16bcc879
RR
129}
130
131//-----------------------------------------------------------------------------
132// "child_detached" of tool bar
133//-----------------------------------------------------------------------------
134
8a126fcc 135static void gtk_toolbar_detached_callback( GtkWidget *widget, GtkWidget *WXUNUSED(child), wxFrame *win )
16bcc879 136{
88ac883a 137 if (g_isIdle)
801aa178 138 wxapp_install_idle_handler();
acfd422a 139
a2053b27 140 if (!win->m_hasVMT) return;
88ac883a 141
16bcc879 142 win->m_toolBarDetached = TRUE;
f03fc89f 143 win->UpdateSize();
16bcc879 144}
88ac883a 145#endif // wxUSE_TOOLBAR
16bcc879 146
47908e25 147//-----------------------------------------------------------------------------
2f2aa628
RR
148// "configure_event"
149//-----------------------------------------------------------------------------
47908e25 150
dfc3d7e0 151static gint gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *WXUNUSED(event), wxFrame *win )
47908e25 152{
88ac883a 153 if (g_isIdle)
121a3581 154 wxapp_install_idle_handler();
acfd422a 155
a2053b27 156 if (!win->m_hasVMT) return FALSE;
88ac883a 157
dfc3d7e0
RR
158 int x = 0;
159 int y = 0;
160 gdk_window_get_root_origin( win->m_widget->window, &x, &y );
88ac883a 161
dfc3d7e0
RR
162 win->m_x = x;
163 win->m_y = y;
8bbe427f 164
a2053b27 165 wxMoveEvent mevent( wxPoint(win->m_x,win->m_y), win->GetId() );
36b3b54a
RR
166 mevent.SetEventObject( win );
167 win->GetEventHandler()->ProcessEvent( mevent );
168
fb1585ae 169 return FALSE;
362c6693 170}
47908e25 171
2b07d713
RR
172//-----------------------------------------------------------------------------
173// "realize" from m_widget
174//-----------------------------------------------------------------------------
175
88ac883a 176/* we cannot MWM hints and icons before the widget has been realized,
2b07d713
RR
177 so we do this directly after realization */
178
88ac883a 179static gint
58dea4b0 180gtk_frame_realized_callback( GtkWidget *widget, wxFrame *win )
2b07d713 181{
88ac883a 182 if (g_isIdle)
121a3581 183 wxapp_install_idle_handler();
acfd422a 184
2b07d713
RR
185 /* all this is for Motif Window Manager "hints" and is supposed to be
186 recognized by other WM as well. not tested. */
051b55ad
KB
187 long decor = (long) GDK_DECOR_BORDER;
188 long func = (long) GDK_FUNC_MOVE;
88ac883a 189
f03fc89f
VZ
190 if ((win->GetWindowStyle() & wxCAPTION) != 0)
191 decor |= GDK_DECOR_TITLE;
192 if ((win->GetWindowStyle() & wxSYSTEM_MENU) != 0)
aa64626e
KB
193 {
194 decor |= GDK_DECOR_MENU;
195 func |= GDK_FUNC_CLOSE;
196 }
f03fc89f 197 if ((win->GetWindowStyle() & wxMINIMIZE_BOX) != 0)
15b24b14 198 {
f03fc89f
VZ
199 func |= GDK_FUNC_MINIMIZE;
200 decor |= GDK_DECOR_MINIMIZE;
15b24b14 201 }
f03fc89f 202 if ((win->GetWindowStyle() & wxMAXIMIZE_BOX) != 0)
15b24b14 203 {
f03fc89f
VZ
204 func |= GDK_FUNC_MAXIMIZE;
205 decor |= GDK_DECOR_MAXIMIZE;
15b24b14 206 }
f03fc89f 207 if ((win->GetWindowStyle() & wxRESIZE_BORDER) != 0)
aa64626e
KB
208 {
209 func |= GDK_FUNC_RESIZE;
210 decor |= GDK_DECOR_RESIZEH;
aa64626e
KB
211 }
212
88ac883a 213
a2053b27
RR
214 gdk_window_set_decorations( win->m_widget->window, (GdkWMDecoration)decor);
215 gdk_window_set_functions( win->m_widget->window, (GdkWMFunction)func);
88ac883a 216
2b07d713 217 /* GTK's shrinking/growing policy */
f03fc89f 218 if ((win->GetWindowStyle() & wxRESIZE_BORDER) == 0)
a2053b27 219 gtk_window_set_policy(GTK_WINDOW(win->m_widget), 0, 0, 1);
2b07d713 220 else
a2053b27 221 gtk_window_set_policy(GTK_WINDOW(win->m_widget), 1, 1, 1);
88ac883a 222
58dea4b0
RR
223 /* reset the icon */
224 if (win->m_icon != wxNullIcon)
225 {
226 wxIcon icon( win->m_icon );
227 win->m_icon = wxNullIcon;
f03fc89f 228 win->SetIcon( icon );
58dea4b0 229 }
88ac883a 230
2e563988
RR
231 /* we set the focus to the child that accepts the focus. this
232 doesn't really have to be done in "realize" but why not? */
f03fc89f 233 wxWindowList::Node *node = win->GetChildren().GetFirst();
2e563988
RR
234 while (node)
235 {
f03fc89f
VZ
236 wxWindow *child = node->GetData();
237 if (child->AcceptsFocus())
238 {
239 child->SetFocus();
240 break;
241 }
88ac883a 242
f03fc89f 243 node = node->GetNext();
2e563988 244 }
88ac883a 245
227e5e99
RR
246 return FALSE;
247}
88ac883a 248
f362b96d
RR
249//-----------------------------------------------------------------------------
250// InsertChild for wxFrame
251//-----------------------------------------------------------------------------
252
253/* Callback for wxFrame. This very strange beast has to be used because
254 * C++ has no virtual methods in a constructor. We have to emulate a
255 * virtual function here as wxWindows requires different ways to insert
256 * a child in container classes. */
257
6bc8a1c8 258static void wxInsertChildInFrame( wxFrame* parent, wxWindow* child )
f362b96d 259{
6bc8a1c8 260 if (!parent->m_insertInClientArea)
f362b96d
RR
261 {
262 /* these are outside the client area */
f03fc89f 263 wxFrame* frame = (wxFrame*) parent;
f362b96d 264 gtk_myfixed_put( GTK_MYFIXED(frame->m_mainWidget),
a2053b27
RR
265 GTK_WIDGET(child->m_widget),
266 child->m_x,
267 child->m_y,
268 child->m_width,
269 child->m_height );
88ac883a
VZ
270
271#if wxUSE_TOOLBAR
f03fc89f
VZ
272 /* we connect to these events for recalculating the client area
273 space when the toolbar is floating */
274 if (wxIS_KIND_OF(child,wxToolBar))
275 {
276 wxToolBar *toolBar = (wxToolBar*) child;
277 if (toolBar->GetWindowStyle() & wxTB_DOCKABLE)
278 {
a2053b27 279 gtk_signal_connect( GTK_OBJECT(toolBar->m_widget), "child_attached",
41ca191f 280 GTK_SIGNAL_FUNC(gtk_toolbar_attached_callback), (gpointer)parent );
88ac883a 281
a2053b27 282 gtk_signal_connect( GTK_OBJECT(toolBar->m_widget), "child_detached",
41ca191f 283 GTK_SIGNAL_FUNC(gtk_toolbar_detached_callback), (gpointer)parent );
f03fc89f
VZ
284 }
285 }
88ac883a 286#endif // wxUSE_TOOLBAR
f362b96d
RR
287 }
288 else
289 {
290 /* these are inside the client area */
a2053b27
RR
291 gtk_myfixed_put( GTK_MYFIXED(parent->m_wxwindow),
292 GTK_WIDGET(child->m_widget),
293 child->m_x,
294 child->m_y,
295 child->m_width,
296 child->m_height );
f362b96d
RR
297 }
298
f362b96d 299 /* resize on OnInternalIdle */
f03fc89f 300 parent->UpdateSize();
f362b96d
RR
301}
302
2f2aa628
RR
303//-----------------------------------------------------------------------------
304// wxFrame
c801d85f
KB
305//-----------------------------------------------------------------------------
306
307BEGIN_EVENT_TABLE(wxFrame, wxWindow)
fb1585ae 308 EVT_SIZE(wxFrame::OnSize)
fe4e9e6c 309 EVT_CLOSE(wxFrame::OnCloseWindow)
342b6a2f 310 EVT_MENU_HIGHLIGHT_ALL(wxFrame::OnMenuHighlight)
c801d85f
KB
311END_EVENT_TABLE()
312
313IMPLEMENT_DYNAMIC_CLASS(wxFrame,wxWindow)
314
ddb6bc71 315void wxFrame::Init()
c801d85f 316{
fb1585ae 317 m_frameMenuBar = (wxMenuBar *) NULL;
88ac883a 318#if wxUSE_STATUSBAR
fb1585ae 319 m_frameStatusBar = (wxStatusBar *) NULL;
88ac883a
VZ
320#endif // wxUSE_STATUSBAR
321#if wxUSE_TOOLBAR
fb1585ae 322 m_frameToolBar = (wxToolBar *) NULL;
88ac883a 323#endif // wxUSE_TOOLBAR
fb1585ae 324 m_sizeSet = FALSE;
b2b3ccc5
RR
325 m_miniEdge = 0;
326 m_miniTitle = 0;
ab2b3dd4 327 m_mainWidget = (GtkWidget*) NULL;
16bcc879
RR
328 m_menuBarDetached = FALSE;
329 m_toolBarDetached = FALSE;
6bc8a1c8 330 m_insertInClientArea = TRUE;
362c6693 331}
c801d85f 332
ed7a557b 333wxFrame::wxFrame( wxWindow *parent, wxWindowID id, const wxString &title,
debe6624
JS
334 const wxPoint &pos, const wxSize &size,
335 long style, const wxString &name )
c801d85f 336{
ddb6bc71 337 Init();
88ac883a 338
fb1585ae 339 Create( parent, id, title, pos, size, style, name );
362c6693 340}
c801d85f 341
debe6624 342bool wxFrame::Create( wxWindow *parent, wxWindowID id, const wxString &title,
c801d85f 343 const wxPoint &pos, const wxSize &size,
debe6624 344 long style, const wxString &name )
c801d85f 345{
a802c3a1 346 wxTopLevelWindows.Append( this );
8bbe427f 347
fb1585ae 348 m_needParent = FALSE;
ed7a557b 349
fb1585ae 350 PreCreation( parent, id, pos, size, style, name );
c801d85f 351
fb1585ae 352 m_title = title;
88ac883a 353
6bc8a1c8 354 m_insertCallback = (wxInsertChildFunction) wxInsertChildInFrame;
ed7a557b 355
fb1585ae
RR
356 GtkWindowType win_type = GTK_WINDOW_TOPLEVEL;
357 if (style & wxSIMPLE_BORDER) win_type = GTK_WINDOW_POPUP;
8bbe427f 358
fb1585ae 359 m_widget = gtk_window_new( win_type );
88ac883a 360
de1c750f
RR
361 if (!name.IsEmpty())
362 gtk_window_set_wmclass( GTK_WINDOW(m_widget), name.mb_str(), name.mb_str() );
8bbe427f 363
2e563988
RR
364#ifdef __WXDEBUG__
365 debug_focus_in( m_widget, _T("wxFrame::m_widget"), name );
366#endif
367
ed9b9841 368 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
fb1585ae 369 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
ed7a557b 370
fb1585ae
RR
371 gtk_signal_connect( GTK_OBJECT(m_widget), "delete_event",
372 GTK_SIGNAL_FUNC(gtk_frame_delete_callback), (gpointer)this );
ed7a557b 373
f362b96d
RR
374 /* m_mainWidget holds the toolbar, the menubar and the client area */
375 m_mainWidget = gtk_myfixed_new();
376 gtk_widget_show( m_mainWidget );
377 GTK_WIDGET_UNSET_FLAGS( m_mainWidget, GTK_CAN_FOCUS );
378 gtk_container_add( GTK_CONTAINER(m_widget), m_mainWidget );
88ac883a 379
2e563988
RR
380#ifdef __WXDEBUG__
381 debug_focus_in( m_mainWidget, _T("wxFrame::m_mainWidget"), name );
382#endif
383
f362b96d 384 /* m_wxwindow only represents the client area without toolbar and menubar */
fb1585ae
RR
385 m_wxwindow = gtk_myfixed_new();
386 gtk_widget_show( m_wxwindow );
f362b96d 387 gtk_container_add( GTK_CONTAINER(m_mainWidget), m_wxwindow );
88ac883a 388
2e563988
RR
389#ifdef __WXDEBUG__
390 debug_focus_in( m_wxwindow, _T("wxFrame::m_wxwindow"), name );
391#endif
392
393 /* we donm't allow the frame to get the focus as otherwise
394 the frame will grabit at arbitrary fcous changes. */
395 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
ed7a557b 396
de8113d9
RR
397 if (m_parent) m_parent->AddChild( this );
398
399 PostCreation();
400
58dea4b0 401 /* we cannot set MWM hints and icons before the widget has
2b07d713
RR
402 been realized, so we do this directly after realization */
403 gtk_signal_connect( GTK_OBJECT(m_widget), "realize",
f03fc89f 404 GTK_SIGNAL_FUNC(gtk_frame_realized_callback), (gpointer) this );
88ac883a 405
ab2b3dd4 406 /* the user resized the frame by dragging etc. */
fb1585ae
RR
407 gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
408 GTK_SIGNAL_FUNC(gtk_frame_size_callback), (gpointer)this );
ed7a557b 409
ab2b3dd4 410 /* the only way to get the window size is to connect to this event */
fb1585ae
RR
411 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
412 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
8bbe427f 413
fb1585ae 414 return TRUE;
362c6693 415}
c801d85f 416
19717c50 417wxFrame::~wxFrame()
c801d85f 418{
31c6b4fc 419 m_isBeingDeleted = TRUE;
88ac883a 420
fb1585ae 421 if (m_frameMenuBar) delete m_frameMenuBar;
e27ce4e9 422 m_frameMenuBar = (wxMenuBar *) NULL;
88ac883a
VZ
423
424#if wxUSE_STATUSBAR
fb1585ae 425 if (m_frameStatusBar) delete m_frameStatusBar;
e27ce4e9 426 m_frameStatusBar = (wxStatusBar *) NULL;
88ac883a
VZ
427#endif // wxUSE_STATUSBAR
428
429#if wxUSE_TOOLBAR
fb1585ae 430 if (m_frameToolBar) delete m_frameToolBar;
e27ce4e9 431 m_frameToolBar = (wxToolBar *) NULL;
88ac883a 432#endif // wxUSE_TOOLBAR
ed7a557b 433
fb1585ae 434 wxTopLevelWindows.DeleteObject( this );
2b854a32 435
0d2a2b60 436 if (wxTheApp->GetTopWindow() == this)
0d2a2b60 437 wxTheApp->SetTopWindow( (wxWindow*) NULL );
2b854a32 438
0d2a2b60 439 if (wxTopLevelWindows.Number() == 0)
0d2a2b60 440 wxTheApp->ExitMainLoop();
362c6693 441}
ed7a557b 442
debe6624 443bool wxFrame::Show( bool show )
c801d85f 444{
ed9b9841 445 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 446
35178437 447 if (show && !m_sizeSet)
fb1585ae 448 {
e27ce4e9
RR
449 /* by calling GtkOnSize here, we don't have to call
450 either after showing the frame, which would entail
f362b96d 451 much ugly flicker or from within the size_allocate
e27ce4e9 452 handler, because GTK 1.1.X forbids that. */
8bbe427f 453
35178437 454 GtkOnSize( m_x, m_y, m_width, m_height );
fb1585ae 455 }
8bbe427f 456
fb1585ae 457 return wxWindow::Show( show );
362c6693 458}
c801d85f 459
19717c50 460bool wxFrame::Destroy()
c801d85f 461{
ed9b9841 462 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 463
fb1585ae 464 if (!wxPendingDelete.Member(this)) wxPendingDelete.Append(this);
ed7a557b 465
fb1585ae 466 return TRUE;
c801d85f
KB
467}
468
bfc6fde4 469void wxFrame::DoSetSize( int x, int y, int width, int height, int sizeFlags )
903f689b 470{
ed9b9841 471 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 472
ab2b3dd4 473 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
ed9b9841 474 wxASSERT_MSG( (m_wxwindow != NULL), _T("invalid frame") );
88ac883a 475
ab2b3dd4 476 /* avoid recursions */
88ac883a 477 if (m_resizing) return;
fb1585ae
RR
478 m_resizing = TRUE;
479
480 int old_x = m_x;
481 int old_y = m_y;
482 int old_width = m_width;
483 int old_height = m_height;
8bbe427f 484
85ad5eb5 485 if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
fb1585ae
RR
486 {
487 if (x != -1) m_x = x;
488 if (y != -1) m_y = y;
489 if (width != -1) m_width = width;
490 if (height != -1) m_height = height;
491 }
492 else
493 {
494 m_x = x;
495 m_y = y;
496 m_width = width;
497 m_height = height;
498 }
499
500 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
501 {
502 if (width == -1) m_width = 80;
503 }
504
505 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
506 {
507 if (height == -1) m_height = 26;
508 }
8bbe427f 509
fb1585ae
RR
510 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
511 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
0c77152e
RR
512 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
513 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
fb1585ae
RR
514
515 if ((m_x != -1) || (m_y != -1))
516 {
8bbe427f 517 if ((m_x != old_x) || (m_y != old_y))
0138c2de 518 {
f03fc89f 519 gtk_widget_set_uposition( m_widget, m_x, m_y );
0138c2de 520 }
fb1585ae 521 }
8bbe427f 522
fb1585ae
RR
523 if ((m_width != old_width) || (m_height != old_height))
524 {
ab2b3dd4 525 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
f03fc89f
VZ
526 done either directly before the frame is shown or in idle time
527 so that different calls to SetSize() don't lead to flicker. */
de8113d9 528 m_sizeSet = FALSE;
fb1585ae 529 }
8bbe427f 530
fb1585ae 531 m_resizing = FALSE;
903f689b
RR
532}
533
534void wxFrame::Centre( int direction )
535{
ed9b9841 536 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 537
43a18898
RR
538 int x = 0;
539 int y = 0;
8bbe427f 540
f5eafd0e
RR
541 if ((direction & wxHORIZONTAL) == wxHORIZONTAL) x = (gdk_screen_width () - m_width) / 2;
542 if ((direction & wxVERTICAL) == wxVERTICAL) y = (gdk_screen_height () - m_height) / 2;
8bbe427f 543
fb1585ae 544 Move( x, y );
903f689b
RR
545}
546
f9241296 547void wxFrame::DoGetClientSize( int *width, int *height ) const
c801d85f 548{
ed9b9841 549 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 550
f9241296 551 wxWindow::DoGetClientSize( width, height );
fb1585ae 552 if (height)
46dc76ba 553 {
41ca191f
RR
554 /* menu bar */
555 if (m_frameMenuBar)
f03fc89f 556 {
88ac883a 557 if (!m_menuBarDetached)
f03fc89f
VZ
558 (*height) -= wxMENU_HEIGHT;
559 else
560 (*height) -= wxPLACE_HOLDER;
561 }
88ac883a 562
f03fc89f 563 /* status bar */
fb1585ae 564 if (m_frameStatusBar) (*height) -= wxSTATUS_HEIGHT;
88ac883a 565
f03fc89f 566 /* tool bar */
fb1585ae
RR
567 if (m_frameToolBar)
568 {
f03fc89f
VZ
569 if (!m_toolBarDetached)
570 {
41ca191f
RR
571 int y = 0;
572 m_frameToolBar->GetSize( (int *) NULL, &y );
573 (*height) -= y;
f03fc89f
VZ
574 }
575 else
41ca191f 576 (*height) -= wxPLACE_HOLDER;
fb1585ae 577 }
88ac883a 578
f03fc89f 579 /* mini edge */
b2b3ccc5
RR
580 (*height) -= m_miniEdge*2 + m_miniTitle;
581 }
582 if (width)
583 {
584 (*width) -= m_miniEdge*2;
46dc76ba 585 }
362c6693 586}
c801d85f 587
bfc6fde4 588void wxFrame::DoSetClientSize( int width, int height )
b593568e 589{
ed9b9841 590 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 591
41ca191f
RR
592 /* menu bar */
593 if (m_frameMenuBar)
f03fc89f 594 {
88ac883a 595 if (!m_menuBarDetached)
f03fc89f
VZ
596 height += wxMENU_HEIGHT;
597 else
598 height += wxPLACE_HOLDER;
599 }
88ac883a 600
f03fc89f 601 /* status bar */
41ca191f 602 if (m_frameStatusBar) height += wxSTATUS_HEIGHT;
88ac883a 603
f03fc89f 604 /* tool bar */
41ca191f
RR
605 if (m_frameToolBar)
606 {
f03fc89f
VZ
607 if (!m_toolBarDetached)
608 {
41ca191f
RR
609 int y = 0;
610 m_frameToolBar->GetSize( (int *) NULL, &y );
611 height += y;
f03fc89f
VZ
612 }
613 else
41ca191f
RR
614 height += wxPLACE_HOLDER;
615 }
88ac883a 616
41ca191f 617 wxWindow::DoSetClientSize( width + m_miniEdge*2, height + m_miniEdge*2 + m_miniTitle );
362c6693 618}
b593568e 619
47908e25 620void wxFrame::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y), int width, int height )
c801d85f 621{
f5368809
RR
622 // due to a bug in gtk, x,y are always 0
623 // m_x = x;
624 // m_y = y;
625
ab2b3dd4 626 /* avoid recursions */
e52f60e6
RR
627 if (m_resizing) return;
628 m_resizing = TRUE;
8bbe427f 629
ab2b3dd4 630 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
ed9b9841 631 wxASSERT_MSG( (m_wxwindow != NULL), _T("invalid frame") );
88ac883a 632
f5368809
RR
633 m_width = width;
634 m_height = height;
8bbe427f 635
ab2b3dd4 636 /* space occupied by m_frameToolBar and m_frameMenuBar */
88ac883a 637 int client_area_y_offset = 0;
8bbe427f 638
ab2b3dd4
RR
639 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
640 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
641 set in wxFrame::Create so it is used to check what kind of frame we
642 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
643 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
644 importantly) m_mainWidget */
88ac883a 645
ab2b3dd4 646 if (m_mainWidget)
f5368809 647 {
ab2b3dd4
RR
648 /* check if size is in legal range */
649 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
650 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
651 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
652 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
653
654 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
655 * menubar, the toolbar and the client area, which is represented by
656 * m_wxwindow.
657 * this hurts in the eye, but I don't want to call SetSize()
658 * because I don't want to call any non-native functions here. */
88ac883a 659
ab2b3dd4
RR
660 if (m_frameMenuBar)
661 {
662 int xx = m_miniEdge;
663 int yy = m_miniEdge + m_miniTitle;
664 int ww = m_width - 2*m_miniEdge;
41ca191f 665 int hh = wxMENU_HEIGHT;
f03fc89f 666 if (m_menuBarDetached) hh = wxPLACE_HOLDER;
121a3581
RR
667 m_frameMenuBar->m_x = xx;
668 m_frameMenuBar->m_y = yy;
669 m_frameMenuBar->m_width = ww;
670 m_frameMenuBar->m_height = hh;
88ac883a
VZ
671 gtk_myfixed_set_size( GTK_MYFIXED(m_mainWidget),
672 m_frameMenuBar->m_widget,
f03fc89f
VZ
673 xx, yy, ww, hh );
674 client_area_y_offset += hh;
ab2b3dd4 675 }
88ac883a 676
ab2b3dd4
RR
677 if (m_frameToolBar)
678 {
679 int xx = m_miniEdge;
680 int yy = m_miniEdge + m_miniTitle;
41ca191f 681 if (m_frameMenuBar)
f03fc89f 682 {
88ac883a
VZ
683 if (!m_menuBarDetached)
684 yy += wxMENU_HEIGHT;
685 else
f03fc89f
VZ
686 yy += wxPLACE_HOLDER;
687 }
ab2b3dd4 688 int ww = m_width - 2*m_miniEdge;
a2053b27 689 int hh = m_frameToolBar->m_height;
88ac883a 690 if (m_toolBarDetached) hh = wxPLACE_HOLDER;
121a3581
RR
691 m_frameToolBar->m_x = xx;
692 m_frameToolBar->m_y = yy;
693 /* m_frameToolBar->m_height = hh; don't change the toolbar's height */
694 m_frameToolBar->m_width = ww;
88ac883a
VZ
695 gtk_myfixed_set_size( GTK_MYFIXED(m_mainWidget),
696 m_frameToolBar->m_widget,
f03fc89f
VZ
697 xx, yy, ww, hh );
698 client_area_y_offset += hh;
ab2b3dd4 699 }
88ac883a 700
32a95f9f 701 int client_x = m_miniEdge;
f03fc89f 702 int client_y = client_area_y_offset + m_miniEdge + m_miniTitle;
32a95f9f 703 int client_w = m_width - 2*m_miniEdge;
f03fc89f 704 int client_h = m_height - client_area_y_offset- 2*m_miniEdge - m_miniTitle;
88ac883a
VZ
705 gtk_myfixed_set_size( GTK_MYFIXED(m_mainWidget),
706 m_wxwindow,
f03fc89f 707 client_x, client_y, client_w, client_h );
32a95f9f
RR
708 }
709 else
710 {
711 /* if there is no m_mainWidget between m_widget and m_wxwindow there
f03fc89f 712 is no need to set the size or position of m_wxwindow. */
f5368809 713 }
88ac883a 714
f5368809
RR
715 if (m_frameStatusBar)
716 {
b2b3ccc5 717 int xx = 0 + m_miniEdge;
f362b96d 718 int yy = m_height - wxSTATUS_HEIGHT - m_miniEdge - client_area_y_offset;
ac57418f
RR
719 int ww = m_width - 2*m_miniEdge;
720 int hh = wxSTATUS_HEIGHT;
121a3581
RR
721 m_frameStatusBar->m_x = xx;
722 m_frameStatusBar->m_y = yy;
723 m_frameStatusBar->m_width = ww;
724 m_frameStatusBar->m_height = hh;
88ac883a
VZ
725 gtk_myfixed_set_size( GTK_MYFIXED(m_wxwindow),
726 m_frameStatusBar->m_widget,
f03fc89f 727 xx, yy, ww, hh );
f5368809 728 }
8bbe427f 729
de8113d9
RR
730 /* we actually set the size of a frame here and no-where else */
731 gtk_widget_set_usize( m_widget, m_width, m_height );
88ac883a 732
f5368809 733 m_sizeSet = TRUE;
8bbe427f 734
884470b1 735 /* send size event to frame */
43a18898
RR
736 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
737 event.SetEventObject( this );
e52f60e6 738 GetEventHandler()->ProcessEvent( event );
8bbe427f 739
884470b1 740 /* send size event to status bar */
5aa5e35a
RR
741 if (m_frameStatusBar)
742 {
a2053b27 743 wxSizeEvent event2( wxSize(m_frameStatusBar->m_width,m_frameStatusBar->m_height), m_frameStatusBar->GetId() );
5aa5e35a
RR
744 event2.SetEventObject( m_frameStatusBar );
745 m_frameStatusBar->GetEventHandler()->ProcessEvent( event2 );
746 }
884470b1 747
e52f60e6
RR
748 m_resizing = FALSE;
749}
750
ca26177c
RR
751void wxFrame::MakeModal( bool modal )
752{
753 if (modal)
ca26177c 754 gtk_grab_add( m_widget );
ca26177c 755 else
c25ccf85 756 gtk_grab_remove( m_widget );
ca26177c
RR
757}
758
9390a202 759void wxFrame::OnInternalIdle()
e52f60e6 760{
1b3667ab 761 if (!m_sizeSet && GTK_WIDGET_REALIZED(m_wxwindow))
e52f60e6 762 GtkOnSize( m_x, m_y, m_width, m_height );
8bbe427f 763
e52f60e6 764 DoMenuUpdates();
88ac883a 765
082b2798
RR
766 if (m_frameMenuBar) m_frameMenuBar->OnInternalIdle();
767 if (m_frameToolBar) m_frameToolBar->OnInternalIdle();
768 if (m_frameStatusBar) m_frameStatusBar->OnInternalIdle();
362c6693 769}
c801d85f 770
6bc8a1c8 771void wxFrame::OnCloseWindow( wxCloseEvent& WXUNUSED(event) )
fe4e9e6c 772{
e3065973 773 Destroy();
fe4e9e6c
VZ
774}
775
c801d85f
KB
776void wxFrame::OnSize( wxSizeEvent &WXUNUSED(event) )
777{
ed9b9841 778 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 779
88ac883a 780#if wxUSE_CONSTRAINTS
f5368809
RR
781 if (GetAutoLayout())
782 {
783 Layout();
784 }
8bbe427f 785 else
88ac883a 786#endif // wxUSE_CONSTRAINTS
c801d85f 787 {
ab46dc18 788 /* do we have exactly one child? */
0138c2de
VZ
789 wxWindow *child = (wxWindow *)NULL;
790 for ( wxNode *node = GetChildren().First(); node; node = node->Next() )
f5368809
RR
791 {
792 wxWindow *win = (wxWindow *)node->Data();
0138c2de 793 if ( !wxIS_KIND_OF(win,wxFrame) && !wxIS_KIND_OF(win,wxDialog) )
f5368809 794 {
ab46dc18 795 if (child)
0138c2de 796 {
ab46dc18 797 /* it's the second one: do nothing */
0138c2de
VZ
798 return;
799 }
800
f5368809
RR
801 child = win;
802 }
803 }
ed7a557b 804
ab46dc18
RR
805 /* no children at all? */
806 if (child)
0138c2de 807 {
ab46dc18 808 /* yes: set it's size to fill all the frame */
0138c2de 809 int client_x, client_y;
326f9654 810 DoGetClientSize( &client_x, &client_y );
0138c2de
VZ
811 child->SetSize( 1, 1, client_x-2, client_y-2 );
812 }
362c6693 813 }
362c6693 814}
c801d85f 815
c801d85f
KB
816void wxFrame::SetMenuBar( wxMenuBar *menuBar )
817{
ed9b9841
OK
818 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
819 wxASSERT_MSG( (m_wxwindow != NULL), _T("invalid frame") );
8bbe427f 820
f5368809 821 m_frameMenuBar = menuBar;
8bbe427f 822
f5368809 823 if (m_frameMenuBar)
30dea054 824 {
5bd9e519 825 m_frameMenuBar->SetInvokingWindow( this );
8bbe427f 826
f03fc89f 827 if (m_frameMenuBar->GetParent() != this)
f5368809 828 {
f03fc89f 829 m_frameMenuBar->SetParent(this);
f362b96d 830 gtk_myfixed_put( GTK_MYFIXED(m_mainWidget),
88ac883a
VZ
831 m_frameMenuBar->m_widget,
832 m_frameMenuBar->m_x,
a2053b27
RR
833 m_frameMenuBar->m_y,
834 m_frameMenuBar->m_width,
835 m_frameMenuBar->m_height );
88ac883a 836
f03fc89f
VZ
837 if (menuBar->GetWindowStyle() & wxMB_DOCKABLE)
838 {
a2053b27 839 gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_attached",
16bcc879 840 GTK_SIGNAL_FUNC(gtk_menu_attached_callback), (gpointer)this );
88ac883a 841
a2053b27 842 gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_detached",
16bcc879 843 GTK_SIGNAL_FUNC(gtk_menu_detached_callback), (gpointer)this );
f03fc89f 844 }
5bd9e519
RR
845
846 m_frameMenuBar->Show( TRUE );
f5368809 847 }
716b7364 848 }
8bbe427f 849
1e133b7d 850 /* resize window in OnInternalIdle */
5b077d48 851 m_sizeSet = FALSE;
362c6693 852}
c801d85f 853
8bbe427f 854wxMenuBar *wxFrame::GetMenuBar() const
46dc76ba 855{
f5368809 856 return m_frameMenuBar;
362c6693 857}
46dc76ba 858
342b6a2f
RR
859void wxFrame::OnMenuHighlight(wxMenuEvent& event)
860{
88ac883a 861#if wxUSE_STATUSBAR
342b6a2f
RR
862 if (GetStatusBar())
863 {
0138c2de
VZ
864 // if no help string found, we will clear the status bar text
865 wxString helpString;
866
867 int menuId = event.GetMenuId();
868 if ( menuId != -1 )
342b6a2f
RR
869 {
870 wxMenuBar *menuBar = GetMenuBar();
871 if (menuBar)
872 {
342b6a2f 873 helpString = menuBar->GetHelpString(menuId);
342b6a2f
RR
874 }
875 }
0138c2de
VZ
876
877 SetStatusText(helpString);
342b6a2f 878 }
88ac883a 879#endif // wxUSE_STATUSBAR
342b6a2f
RR
880}
881
88ac883a 882#if wxUSE_TOOLBAR
6bc8a1c8 883wxToolBar* wxFrame::CreateToolBar( long style, wxWindowID id, const wxString& name )
46dc76ba 884{
ed9b9841 885 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 886
ed9b9841 887 wxCHECK_MSG( m_frameToolBar == NULL, FALSE, _T("recreating toolbar in wxFrame") );
362c6693 888
6bc8a1c8 889 m_insertInClientArea = FALSE;
88ac883a 890
f5368809 891 m_frameToolBar = OnCreateToolBar( style, id, name );
8bbe427f 892
6bc8a1c8 893 if (m_frameToolBar) GetChildren().DeleteObject( m_frameToolBar );
88ac883a 894
6bc8a1c8 895 m_insertInClientArea = TRUE;
8bbe427f 896
5b077d48 897 m_sizeSet = FALSE;
8bbe427f 898
f5368809 899 return m_frameToolBar;
362c6693 900}
46dc76ba 901
362c6693 902wxToolBar* wxFrame::OnCreateToolBar( long style, wxWindowID id, const wxString& name )
46dc76ba 903{
f5368809 904 return new wxToolBar( this, id, wxDefaultPosition, wxDefaultSize, style, name );
362c6693
RR
905}
906
8bbe427f
VZ
907wxToolBar *wxFrame::GetToolBar() const
908{
909 return m_frameToolBar;
362c6693 910}
88ac883a 911#endif // wxUSE_TOOLBAR
46dc76ba 912
88ac883a 913#if wxUSE_STATUSBAR
e3e65dac 914wxStatusBar* wxFrame::CreateStatusBar( int number, long style, wxWindowID id, const wxString& name )
c801d85f 915{
ed9b9841 916 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 917
ed9b9841 918 wxCHECK_MSG( m_frameStatusBar == NULL, FALSE, _T("recreating status bar in wxFrame") );
c801d85f 919
f5368809 920 m_frameStatusBar = OnCreateStatusBar( number, style, id, name );
8bbe427f 921
5b077d48 922 m_sizeSet = FALSE;
8bbe427f 923
f5368809 924 return m_frameStatusBar;
362c6693
RR
925}
926
927wxStatusBar *wxFrame::OnCreateStatusBar( int number, long style, wxWindowID id, const wxString& name )
928{
f5368809 929 wxStatusBar *statusBar = (wxStatusBar *) NULL;
8bbe427f 930
f5368809 931 statusBar = new wxStatusBar(this, id, wxPoint(0, 0), wxSize(100, 20), style, name);
8bbe427f 932
f5368809
RR
933 // Set the height according to the font and the border size
934 wxClientDC dc(statusBar);
8bbe427f 935 dc.SetFont( statusBar->GetFont() );
362c6693 936
f5368809
RR
937 long x, y;
938 dc.GetTextExtent( "X", &x, &y );
362c6693 939
f5368809 940 int height = (int)( (y * 1.1) + 2* statusBar->GetBorderY());
362c6693 941
f5368809 942 statusBar->SetSize( -1, -1, 100, height );
362c6693 943
f5368809
RR
944 statusBar->SetFieldsCount( number );
945 return statusBar;
362c6693 946}
c801d85f 947
88ac883a 948wxStatusBar *wxFrame::GetStatusBar() const
30f1b5f3 949{
88ac883a 950 return m_frameStatusBar;
30f1b5f3
RR
951}
952
362c6693 953void wxFrame::SetStatusText(const wxString& text, int number)
c801d85f 954{
ed9b9841 955 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 956
ed9b9841 957 wxCHECK_RET( m_frameStatusBar != NULL, _T("no statusbar to set text for") );
c801d85f 958
f5368809 959 m_frameStatusBar->SetStatusText(text, number);
362c6693
RR
960}
961
962void wxFrame::SetStatusWidths(int n, const int widths_field[] )
c801d85f 963{
ed9b9841 964 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 965
ed9b9841 966 wxCHECK_RET( m_frameStatusBar != NULL, _T("no statusbar to set widths for") );
362c6693 967
f5368809 968 m_frameStatusBar->SetStatusWidths(n, widths_field);
362c6693 969}
88ac883a 970#endif // wxUSE_STATUSBAR
c801d85f 971
88ac883a 972void wxFrame::Command( int id )
c801d85f 973{
88ac883a
VZ
974 wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, id);
975 commandEvent.SetInt( id );
976 commandEvent.SetEventObject( this );
977
978 wxMenuBar *bar = GetMenuBar();
979 if (!bar) return;
980
981 wxMenuItem *item = bar->FindItemForId(id) ;
982 if (item && item->IsCheckable())
983 {
984 bar->Check(id,!bar->Checked(id)) ;
985 }
986
987 wxEvtHandler* evtHandler = GetEventHandler();
988
989 evtHandler->ProcessEvent(commandEvent);
362c6693 990}
c801d85f 991
c801d85f
KB
992void wxFrame::SetTitle( const wxString &title )
993{
ed9b9841 994 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 995
f5368809 996 m_title = title;
ed9b9841
OK
997 if (m_title.IsNull()) m_title = _T("");
998 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
362c6693 999}
c801d85f 1000
d355d3fe
RR
1001void wxFrame::SetIcon( const wxIcon &icon )
1002{
ed9b9841 1003 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 1004
f5368809
RR
1005 m_icon = icon;
1006 if (!icon.Ok()) return;
8bbe427f 1007
58dea4b0
RR
1008 if (!m_widget->window) return;
1009
f5368809
RR
1010 wxMask *mask = icon.GetMask();
1011 GdkBitmap *bm = (GdkBitmap *) NULL;
1012 if (mask) bm = mask->GetBitmap();
8bbe427f 1013
f5368809 1014 gdk_window_set_icon( m_widget->window, (GdkWindow *) NULL, icon.GetPixmap(), bm );
d355d3fe 1015}
b2b3ccc5 1016