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