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