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