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