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