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