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