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