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