]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/frame.cpp
Yet another one.
[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
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
8a126fcc 123static void gtk_toolbar_detached_callback( GtkWidget *widget, GtkWidget *WXUNUSED(child), wxFrame *win )
16bcc879
RR
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
fb1585ae
RR
274 gtk_signal_connect( GTK_OBJECT(m_widget), "delete_event",
275 GTK_SIGNAL_FUNC(gtk_frame_delete_callback), (gpointer)this );
ed7a557b 276
f362b96d
RR
277 /* m_mainWidget holds the toolbar, the menubar and the client area */
278 m_mainWidget = gtk_myfixed_new();
279 gtk_widget_show( m_mainWidget );
280 GTK_WIDGET_UNSET_FLAGS( m_mainWidget, GTK_CAN_FOCUS );
281 gtk_container_add( GTK_CONTAINER(m_widget), m_mainWidget );
282 gtk_widget_realize( m_mainWidget );
283
284 /* m_wxwindow only represents the client area without toolbar and menubar */
fb1585ae
RR
285 m_wxwindow = gtk_myfixed_new();
286 gtk_widget_show( m_wxwindow );
287 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
f362b96d 288 gtk_container_add( GTK_CONTAINER(m_mainWidget), m_wxwindow );
ed7a557b 289
de8113d9
RR
290 if (m_parent) m_parent->AddChild( this );
291
292 PostCreation();
293
294 gtk_widget_realize( m_widget );
295
ab2b3dd4
RR
296 /* all this is for Motif Window Manager "hints" and is supposed to be
297 recognized by other WM as well. not tested. */
298 long decor = (long) GDK_DECOR_ALL;
299 long func = (long) GDK_FUNC_ALL;
16bcc879 300
ab2b3dd4 301 if ((m_windowStyle & wxCAPTION) == 0)
034be888 302 decor |= GDK_DECOR_TITLE;
16bcc879 303/* if ((m_windowStyle & wxMINIMIZE) == 0)
034be888 304 func |= GDK_FUNC_MINIMIZE;
ab2b3dd4 305 if ((m_windowStyle & wxMAXIMIZE) == 0)
16bcc879 306 func |= GDK_FUNC_MAXIMIZE; */
ab2b3dd4 307 if ((m_windowStyle & wxSYSTEM_MENU) == 0)
034be888 308 decor |= GDK_DECOR_MENU;
ab2b3dd4 309 if ((m_windowStyle & wxMINIMIZE_BOX) == 0)
034be888 310 decor |= GDK_DECOR_MINIMIZE;
ab2b3dd4 311 if ((m_windowStyle & wxMAXIMIZE_BOX) == 0)
034be888 312 decor |= GDK_DECOR_MAXIMIZE;
ab2b3dd4 313 if ((m_windowStyle & wxRESIZE_BORDER) == 0)
034be888 314 func |= GDK_FUNC_RESIZE;
16bcc879 315
ab2b3dd4
RR
316 gdk_window_set_decorations(m_widget->window, (GdkWMDecoration)decor);
317 gdk_window_set_functions(m_widget->window, (GdkWMFunction)func);
034be888 318
8a126fcc
RR
319 /* GTK's shrinking/growing policy */
320 if ((m_windowStyle & wxRESIZE_BORDER) == 0)
321 gtk_window_set_policy(GTK_WINDOW(m_widget), 0, 0, 1);
322 else
323 gtk_window_set_policy(GTK_WINDOW(m_widget), 1, 1, 1);
324
ab2b3dd4 325 /* the user resized the frame by dragging etc. */
fb1585ae
RR
326 gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
327 GTK_SIGNAL_FUNC(gtk_frame_size_callback), (gpointer)this );
ed7a557b 328
ab2b3dd4 329 /* the only way to get the window size is to connect to this event */
fb1585ae
RR
330 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
331 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
8bbe427f 332
fb1585ae 333 return TRUE;
362c6693 334}
c801d85f 335
19717c50 336wxFrame::~wxFrame()
c801d85f 337{
fb1585ae 338 if (m_frameMenuBar) delete m_frameMenuBar;
e27ce4e9
RR
339 m_frameMenuBar = (wxMenuBar *) NULL;
340
fb1585ae 341 if (m_frameStatusBar) delete m_frameStatusBar;
e27ce4e9
RR
342 m_frameStatusBar = (wxStatusBar *) NULL;
343
fb1585ae 344 if (m_frameToolBar) delete m_frameToolBar;
e27ce4e9 345 m_frameToolBar = (wxToolBar *) NULL;
ed7a557b 346
fb1585ae 347 wxTopLevelWindows.DeleteObject( this );
2b854a32 348
0d2a2b60 349 if (wxTheApp->GetTopWindow() == this)
0d2a2b60 350 wxTheApp->SetTopWindow( (wxWindow*) NULL );
2b854a32 351
0d2a2b60 352 if (wxTopLevelWindows.Number() == 0)
0d2a2b60 353 wxTheApp->ExitMainLoop();
362c6693 354}
ed7a557b 355
debe6624 356bool wxFrame::Show( bool show )
c801d85f 357{
ed9b9841 358 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 359
35178437 360 if (show && !m_sizeSet)
fb1585ae 361 {
e27ce4e9
RR
362 /* by calling GtkOnSize here, we don't have to call
363 either after showing the frame, which would entail
f362b96d 364 much ugly flicker or from within the size_allocate
e27ce4e9 365 handler, because GTK 1.1.X forbids that. */
8bbe427f 366
35178437 367 GtkOnSize( m_x, m_y, m_width, m_height );
fb1585ae 368 }
8bbe427f 369
fb1585ae 370 return wxWindow::Show( show );
362c6693 371}
c801d85f 372
19717c50 373bool wxFrame::Destroy()
c801d85f 374{
ed9b9841 375 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 376
fb1585ae 377 if (!wxPendingDelete.Member(this)) wxPendingDelete.Append(this);
ed7a557b 378
fb1585ae 379 return TRUE;
c801d85f
KB
380}
381
bfc6fde4 382void wxFrame::DoSetSize( int x, int y, int width, int height, int sizeFlags )
903f689b 383{
ed9b9841 384 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 385
ab2b3dd4 386 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
ed9b9841 387 wxASSERT_MSG( (m_wxwindow != NULL), _T("invalid frame") );
ab2b3dd4
RR
388
389 /* avoid recursions */
390 if (m_resizing) return;
fb1585ae
RR
391 m_resizing = TRUE;
392
393 int old_x = m_x;
394 int old_y = m_y;
395 int old_width = m_width;
396 int old_height = m_height;
8bbe427f 397
fb1585ae
RR
398 if ((sizeFlags & wxSIZE_USE_EXISTING) == wxSIZE_USE_EXISTING)
399 {
400 if (x != -1) m_x = x;
401 if (y != -1) m_y = y;
402 if (width != -1) m_width = width;
403 if (height != -1) m_height = height;
404 }
405 else
406 {
407 m_x = x;
408 m_y = y;
409 m_width = width;
410 m_height = height;
411 }
412
413 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
414 {
415 if (width == -1) m_width = 80;
416 }
417
418 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
419 {
420 if (height == -1) m_height = 26;
421 }
8bbe427f 422
fb1585ae
RR
423 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
424 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
0c77152e
RR
425 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
426 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
fb1585ae
RR
427
428 if ((m_x != -1) || (m_y != -1))
429 {
8bbe427f 430 if ((m_x != old_x) || (m_y != old_y))
0138c2de 431 {
de8113d9 432 /* m_sizeSet = FALSE; */
0138c2de
VZ
433 gtk_widget_set_uposition( m_widget, m_x, m_y );
434 }
fb1585ae 435 }
8bbe427f 436
fb1585ae
RR
437 if ((m_width != old_width) || (m_height != old_height))
438 {
ab2b3dd4
RR
439 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
440 done either directly before the frame is shown or in idle time
441 so that different calls to SetSize() don't lead to flicker. */
de8113d9 442 m_sizeSet = FALSE;
fb1585ae 443 }
8bbe427f 444
fb1585ae 445 m_resizing = FALSE;
903f689b
RR
446}
447
448void wxFrame::Centre( int direction )
449{
ed9b9841 450 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 451
43a18898
RR
452 int x = 0;
453 int y = 0;
8bbe427f 454
f5eafd0e
RR
455 if ((direction & wxHORIZONTAL) == wxHORIZONTAL) x = (gdk_screen_width () - m_width) / 2;
456 if ((direction & wxVERTICAL) == wxVERTICAL) y = (gdk_screen_height () - m_height) / 2;
8bbe427f 457
fb1585ae 458 Move( x, y );
903f689b
RR
459}
460
c801d85f
KB
461void wxFrame::GetClientSize( int *width, int *height ) const
462{
ed9b9841 463 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 464
fb1585ae
RR
465 wxWindow::GetClientSize( width, height );
466 if (height)
46dc76ba 467 {
41ca191f
RR
468 /* menu bar */
469 if (m_frameMenuBar)
470 {
471 if (!m_menuBarDetached)
472 (*height) -= wxMENU_HEIGHT;
473 else
474 (*height) -= wxPLACE_HOLDER;
475 }
476
477 /* status bar */
fb1585ae 478 if (m_frameStatusBar) (*height) -= wxSTATUS_HEIGHT;
41ca191f
RR
479
480 /* tool bar */
fb1585ae
RR
481 if (m_frameToolBar)
482 {
41ca191f
RR
483 if (!m_toolBarDetached)
484 {
485 int y = 0;
486 m_frameToolBar->GetSize( (int *) NULL, &y );
487 (*height) -= y;
488 }
489 else
490 (*height) -= wxPLACE_HOLDER;
fb1585ae 491 }
41ca191f
RR
492
493 /* mini edge */
b2b3ccc5
RR
494 (*height) -= m_miniEdge*2 + m_miniTitle;
495 }
496 if (width)
497 {
498 (*width) -= m_miniEdge*2;
46dc76ba 499 }
362c6693 500}
c801d85f 501
bfc6fde4 502void wxFrame::DoSetClientSize( int width, int height )
b593568e 503{
ed9b9841 504 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 505
41ca191f
RR
506 /* menu bar */
507 if (m_frameMenuBar)
508 {
509 if (!m_menuBarDetached)
510 height += wxMENU_HEIGHT;
511 else
512 height += wxPLACE_HOLDER;
513 }
514
515 /* status bar */
516 if (m_frameStatusBar) height += wxSTATUS_HEIGHT;
517
518 /* tool bar */
519 if (m_frameToolBar)
520 {
521 if (!m_toolBarDetached)
522 {
523 int y = 0;
524 m_frameToolBar->GetSize( (int *) NULL, &y );
525 height += y;
526 }
527 else
528 height += wxPLACE_HOLDER;
529 }
530
531 wxWindow::DoSetClientSize( width + m_miniEdge*2, height + m_miniEdge*2 + m_miniTitle );
362c6693 532}
b593568e 533
47908e25 534void wxFrame::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y), int width, int height )
c801d85f 535{
f5368809
RR
536 // due to a bug in gtk, x,y are always 0
537 // m_x = x;
538 // m_y = y;
539
ab2b3dd4 540 /* avoid recursions */
e52f60e6
RR
541 if (m_resizing) return;
542 m_resizing = TRUE;
8bbe427f 543
ab2b3dd4 544 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
ed9b9841 545 wxASSERT_MSG( (m_wxwindow != NULL), _T("invalid frame") );
ab2b3dd4 546
f5368809
RR
547 m_width = width;
548 m_height = height;
8bbe427f 549
ab2b3dd4 550 /* space occupied by m_frameToolBar and m_frameMenuBar */
f362b96d 551 int client_area_y_offset = 0;
8bbe427f 552
ab2b3dd4
RR
553 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
554 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
555 set in wxFrame::Create so it is used to check what kind of frame we
556 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
557 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
558 importantly) m_mainWidget */
559
560 if (m_mainWidget)
f5368809 561 {
ab2b3dd4
RR
562 /* check if size is in legal range */
563 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
564 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
565 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
566 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
567
568 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
569 * menubar, the toolbar and the client area, which is represented by
570 * m_wxwindow.
571 * this hurts in the eye, but I don't want to call SetSize()
572 * because I don't want to call any non-native functions here. */
573
574 if (m_frameMenuBar)
575 {
576 int xx = m_miniEdge;
577 int yy = m_miniEdge + m_miniTitle;
578 int ww = m_width - 2*m_miniEdge;
41ca191f
RR
579 int hh = wxMENU_HEIGHT;
580 if (m_menuBarDetached) hh = wxPLACE_HOLDER;
ab2b3dd4
RR
581 m_frameMenuBar->m_x = xx;
582 m_frameMenuBar->m_y = yy;
583 m_frameMenuBar->m_width = ww;
584 m_frameMenuBar->m_height = hh;
585
586 gtk_myfixed_move( GTK_MYFIXED(m_mainWidget), m_frameMenuBar->m_widget, xx, yy );
587 gtk_widget_set_usize( m_frameMenuBar->m_widget, ww, hh );
f362b96d 588
ab2b3dd4
RR
589 client_area_y_offset += hh;
590 }
e27ce4e9 591
ab2b3dd4
RR
592 if (m_frameToolBar)
593 {
594 int xx = m_miniEdge;
595 int yy = m_miniEdge + m_miniTitle;
41ca191f
RR
596 if (m_frameMenuBar)
597 {
598 if (!m_menuBarDetached)
599 yy += wxMENU_HEIGHT;
600 else
601 yy += wxPLACE_HOLDER;
602 }
ab2b3dd4
RR
603 int ww = m_width - 2*m_miniEdge;
604 int hh = m_frameToolBar->m_height;
41ca191f 605 if (m_toolBarDetached) hh = wxPLACE_HOLDER;
ab2b3dd4
RR
606 m_frameToolBar->m_x = xx;
607 m_frameToolBar->m_y = yy;
41ca191f 608 /* m_frameToolBar->m_height = hh; don't change the toolbar's height */
ab2b3dd4
RR
609 m_frameToolBar->m_width = ww;
610
611 gtk_myfixed_move( GTK_MYFIXED(m_mainWidget), m_frameToolBar->m_widget, xx, yy );
612 gtk_widget_set_usize( m_frameToolBar->m_widget, ww, hh );
f362b96d 613
ab2b3dd4
RR
614 client_area_y_offset += hh;
615 }
616
32a95f9f
RR
617 int client_x = m_miniEdge;
618 int client_y = client_area_y_offset + m_miniEdge + m_miniTitle;
619 gtk_myfixed_move( GTK_MYFIXED(m_mainWidget), m_wxwindow, client_x, client_y );
620
621 int client_w = m_width - 2*m_miniEdge;
622 int client_h = m_height - client_area_y_offset- 2*m_miniEdge - m_miniTitle;
623 gtk_widget_set_usize( m_wxwindow, client_w, client_h );
624 }
625 else
626 {
627 /* if there is no m_mainWidget between m_widget and m_wxwindow there
628 is no need to set the size or position of m_wxwindow. */
f5368809 629 }
f362b96d 630
f5368809
RR
631 if (m_frameStatusBar)
632 {
b2b3ccc5 633 int xx = 0 + m_miniEdge;
f362b96d 634 int yy = m_height - wxSTATUS_HEIGHT - m_miniEdge - client_area_y_offset;
ac57418f
RR
635 int ww = m_width - 2*m_miniEdge;
636 int hh = wxSTATUS_HEIGHT;
8bbe427f 637
b2b3ccc5
RR
638 m_frameStatusBar->m_x = xx;
639 m_frameStatusBar->m_y = yy;
640 m_frameStatusBar->m_width = ww;
641 m_frameStatusBar->m_height = hh;
8bbe427f 642
b2b3ccc5
RR
643 gtk_myfixed_move( GTK_MYFIXED(m_wxwindow), m_frameStatusBar->m_widget, xx, yy );
644 gtk_widget_set_usize( m_frameStatusBar->m_widget, ww, hh );
f5368809 645 }
8bbe427f 646
de8113d9
RR
647 /* we actually set the size of a frame here and no-where else */
648 gtk_widget_set_usize( m_widget, m_width, m_height );
649
f5368809 650 m_sizeSet = TRUE;
8bbe427f 651
884470b1 652 /* send size event to frame */
43a18898
RR
653 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
654 event.SetEventObject( this );
e52f60e6 655 GetEventHandler()->ProcessEvent( event );
8bbe427f 656
884470b1 657 /* send size event to status bar */
5aa5e35a
RR
658 if (m_frameStatusBar)
659 {
660 wxSizeEvent event2( wxSize(m_frameStatusBar->m_width,m_frameStatusBar->m_height), m_frameStatusBar->GetId() );
661 event2.SetEventObject( m_frameStatusBar );
662 m_frameStatusBar->GetEventHandler()->ProcessEvent( event2 );
663 }
884470b1 664
e52f60e6
RR
665 m_resizing = FALSE;
666}
667
9390a202 668void wxFrame::OnInternalIdle()
e52f60e6
RR
669{
670 if (!m_sizeSet)
671 GtkOnSize( m_x, m_y, m_width, m_height );
8bbe427f 672
e52f60e6 673 DoMenuUpdates();
362c6693 674}
c801d85f 675
fe4e9e6c
VZ
676void wxFrame::OnCloseWindow( wxCloseEvent& event )
677{
e3065973 678 Destroy();
fe4e9e6c
VZ
679}
680
c801d85f
KB
681void wxFrame::OnSize( wxSizeEvent &WXUNUSED(event) )
682{
ed9b9841 683 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 684
f5368809
RR
685 if (GetAutoLayout())
686 {
687 Layout();
688 }
8bbe427f 689 else
c801d85f 690 {
0138c2de
VZ
691 // do we have exactly one child?
692 wxWindow *child = (wxWindow *)NULL;
693 for ( wxNode *node = GetChildren().First(); node; node = node->Next() )
f5368809
RR
694 {
695 wxWindow *win = (wxWindow *)node->Data();
0138c2de 696 if ( !wxIS_KIND_OF(win,wxFrame) && !wxIS_KIND_OF(win,wxDialog) )
f5368809 697 {
0138c2de
VZ
698 if ( child )
699 {
700 // it's the second one: do nothing
701 return;
702 }
703
f5368809
RR
704 child = win;
705 }
706 }
ed7a557b 707
0138c2de
VZ
708 // no children at all?
709 if ( child )
710 {
711 // yes: set it's size to fill all the frame
712 int client_x, client_y;
713 GetClientSize( &client_x, &client_y );
714 child->SetSize( 1, 1, client_x-2, client_y-2 );
715 }
362c6693 716 }
362c6693 717}
c801d85f 718
716b7364 719static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
c801d85f 720{
f5368809 721 menu->SetInvokingWindow( win );
c626a8b7 722 wxNode *node = menu->GetItems().First();
f5368809
RR
723 while (node)
724 {
725 wxMenuItem *menuitem = (wxMenuItem*)node->Data();
726 if (menuitem->IsSubMenu())
727 SetInvokingWindow( menuitem->GetSubMenu(), win );
728 node = node->Next();
729 }
362c6693 730}
c801d85f
KB
731
732void wxFrame::SetMenuBar( wxMenuBar *menuBar )
733{
ed9b9841
OK
734 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
735 wxASSERT_MSG( (m_wxwindow != NULL), _T("invalid frame") );
8bbe427f 736
f5368809 737 m_frameMenuBar = menuBar;
8bbe427f 738
f5368809 739 if (m_frameMenuBar)
30dea054 740 {
c626a8b7 741 wxNode *node = m_frameMenuBar->GetMenus().First();
f5368809
RR
742 while (node)
743 {
744 wxMenu *menu = (wxMenu*)node->Data();
745 SetInvokingWindow( menu, this );
746 node = node->Next();
747 }
8bbe427f 748
f5368809
RR
749 if (m_frameMenuBar->m_parent != this)
750 {
751 m_frameMenuBar->m_parent = this;
f362b96d 752 gtk_myfixed_put( GTK_MYFIXED(m_mainWidget),
f5368809 753 m_frameMenuBar->m_widget, m_frameMenuBar->m_x, m_frameMenuBar->m_y );
16bcc879
RR
754
755 if (menuBar->m_windowStyle & wxMB_DOCKABLE)
756 {
757 gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_attached",
758 GTK_SIGNAL_FUNC(gtk_menu_attached_callback), (gpointer)this );
759
760 gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_detached",
761 GTK_SIGNAL_FUNC(gtk_menu_detached_callback), (gpointer)this );
762 }
f5368809 763 }
716b7364 764 }
8bbe427f 765
5b077d48 766 m_sizeSet = FALSE;
362c6693 767}
c801d85f 768
8bbe427f 769wxMenuBar *wxFrame::GetMenuBar() const
46dc76ba 770{
f5368809 771 return m_frameMenuBar;
362c6693 772}
46dc76ba 773
342b6a2f
RR
774void wxFrame::OnMenuHighlight(wxMenuEvent& event)
775{
776 if (GetStatusBar())
777 {
0138c2de
VZ
778 // if no help string found, we will clear the status bar text
779 wxString helpString;
780
781 int menuId = event.GetMenuId();
782 if ( menuId != -1 )
342b6a2f
RR
783 {
784 wxMenuBar *menuBar = GetMenuBar();
785 if (menuBar)
786 {
342b6a2f 787 helpString = menuBar->GetHelpString(menuId);
342b6a2f
RR
788 }
789 }
0138c2de
VZ
790
791 SetStatusText(helpString);
342b6a2f
RR
792 }
793}
794
362c6693 795wxToolBar* wxFrame::CreateToolBar(long style, wxWindowID id, const wxString& name)
46dc76ba 796{
ed9b9841 797 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 798
ed9b9841 799 wxCHECK_MSG( m_frameToolBar == NULL, FALSE, _T("recreating toolbar in wxFrame") );
362c6693 800
f5368809 801 m_frameToolBar = OnCreateToolBar( style, id, name );
8bbe427f 802
db1b4961 803 GetChildren().DeleteObject( m_frameToolBar );
8bbe427f 804
5b077d48 805 m_sizeSet = FALSE;
8bbe427f 806
f5368809 807 return m_frameToolBar;
362c6693 808}
46dc76ba 809
362c6693 810wxToolBar* wxFrame::OnCreateToolBar( long style, wxWindowID id, const wxString& name )
46dc76ba 811{
f5368809 812 return new wxToolBar( this, id, wxDefaultPosition, wxDefaultSize, style, name );
362c6693
RR
813}
814
8bbe427f
VZ
815wxToolBar *wxFrame::GetToolBar() const
816{
817 return m_frameToolBar;
362c6693 818}
46dc76ba 819
e3e65dac 820wxStatusBar* wxFrame::CreateStatusBar( int number, long style, wxWindowID id, const wxString& name )
c801d85f 821{
ed9b9841 822 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 823
ed9b9841 824 wxCHECK_MSG( m_frameStatusBar == NULL, FALSE, _T("recreating status bar in wxFrame") );
c801d85f 825
f5368809 826 m_frameStatusBar = OnCreateStatusBar( number, style, id, name );
8bbe427f 827
5b077d48 828 m_sizeSet = FALSE;
8bbe427f 829
f5368809 830 return m_frameStatusBar;
362c6693
RR
831}
832
833wxStatusBar *wxFrame::OnCreateStatusBar( int number, long style, wxWindowID id, const wxString& name )
834{
f5368809 835 wxStatusBar *statusBar = (wxStatusBar *) NULL;
8bbe427f 836
f5368809 837 statusBar = new wxStatusBar(this, id, wxPoint(0, 0), wxSize(100, 20), style, name);
8bbe427f 838
f5368809
RR
839 // Set the height according to the font and the border size
840 wxClientDC dc(statusBar);
8bbe427f 841 dc.SetFont( statusBar->GetFont() );
362c6693 842
f5368809
RR
843 long x, y;
844 dc.GetTextExtent( "X", &x, &y );
362c6693 845
f5368809 846 int height = (int)( (y * 1.1) + 2* statusBar->GetBorderY());
362c6693 847
f5368809 848 statusBar->SetSize( -1, -1, 100, height );
362c6693 849
f5368809
RR
850 statusBar->SetFieldsCount( number );
851 return statusBar;
362c6693 852}
c801d85f 853
30f1b5f3
RR
854void wxFrame::Command( int id )
855{
856 wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, id);
857 commandEvent.SetInt( id );
858 commandEvent.SetEventObject( this );
859
860 wxMenuBar *bar = GetMenuBar();
861 if (!bar) return;
862
863 wxMenuItem *item = bar->FindItemForId(id) ;
864 if (item && item->IsCheckable())
865 {
866 bar->Check(id,!bar->Checked(id)) ;
867 }
e702ff0f 868
6c41a418 869 wxEvtHandler* evtHandler = GetEventHandler();
e702ff0f
JS
870
871 evtHandler->ProcessEvent(commandEvent);
30f1b5f3
RR
872}
873
362c6693 874void wxFrame::SetStatusText(const wxString& text, int number)
c801d85f 875{
ed9b9841 876 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 877
ed9b9841 878 wxCHECK_RET( m_frameStatusBar != NULL, _T("no statusbar to set text for") );
c801d85f 879
f5368809 880 m_frameStatusBar->SetStatusText(text, number);
362c6693
RR
881}
882
883void wxFrame::SetStatusWidths(int n, const int widths_field[] )
c801d85f 884{
ed9b9841 885 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 886
ed9b9841 887 wxCHECK_RET( m_frameStatusBar != NULL, _T("no statusbar to set widths for") );
362c6693 888
f5368809 889 m_frameStatusBar->SetStatusWidths(n, widths_field);
362c6693 890}
c801d85f 891
8bbe427f 892wxStatusBar *wxFrame::GetStatusBar() const
c801d85f 893{
f5368809 894 return m_frameStatusBar;
362c6693 895}
c801d85f 896
c801d85f
KB
897void wxFrame::SetTitle( const wxString &title )
898{
ed9b9841 899 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 900
f5368809 901 m_title = title;
ed9b9841
OK
902 if (m_title.IsNull()) m_title = _T("");
903 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
362c6693 904}
c801d85f 905
d355d3fe
RR
906void wxFrame::SetIcon( const wxIcon &icon )
907{
ed9b9841 908 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 909
f5368809
RR
910 m_icon = icon;
911 if (!icon.Ok()) return;
8bbe427f 912
f5368809
RR
913 wxMask *mask = icon.GetMask();
914 GdkBitmap *bm = (GdkBitmap *) NULL;
915 if (mask) bm = mask->GetBitmap();
8bbe427f 916
f5368809 917 gdk_window_set_icon( m_widget->window, (GdkWindow *) NULL, icon.GetPixmap(), bm );
d355d3fe 918}
b2b3ccc5 919