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