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