]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/frame.cpp
Unicode compilation fix for find_*_of()
[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
252static void wxInsertChildInFrame( wxWindow* parent, wxWindow* child )
253{
254 if (wxIS_KIND_OF(child,wxToolBar) || wxIS_KIND_OF(child,wxMenuBar))
255 {
16bcc879 256 /* actually, menubars are never inserted here, but this
f03fc89f 257 may change one day */
16bcc879 258
f362b96d 259 /* these are outside the client area */
f03fc89f 260 wxFrame* frame = (wxFrame*) parent;
f362b96d 261 gtk_myfixed_put( GTK_MYFIXED(frame->m_mainWidget),
a2053b27
RR
262 GTK_WIDGET(child->m_widget),
263 child->m_x,
264 child->m_y,
265 child->m_width,
266 child->m_height );
f03fc89f
VZ
267
268 /* we connect to these events for recalculating the client area
269 space when the toolbar is floating */
270 if (wxIS_KIND_OF(child,wxToolBar))
271 {
272 wxToolBar *toolBar = (wxToolBar*) child;
273 if (toolBar->GetWindowStyle() & wxTB_DOCKABLE)
274 {
a2053b27 275 gtk_signal_connect( GTK_OBJECT(toolBar->m_widget), "child_attached",
41ca191f 276 GTK_SIGNAL_FUNC(gtk_toolbar_attached_callback), (gpointer)parent );
f03fc89f 277
a2053b27 278 gtk_signal_connect( GTK_OBJECT(toolBar->m_widget), "child_detached",
41ca191f 279 GTK_SIGNAL_FUNC(gtk_toolbar_detached_callback), (gpointer)parent );
f03fc89f
VZ
280 }
281 }
f362b96d
RR
282 }
283 else
284 {
285 /* these are inside the client area */
a2053b27
RR
286 gtk_myfixed_put( GTK_MYFIXED(parent->m_wxwindow),
287 GTK_WIDGET(child->m_widget),
288 child->m_x,
289 child->m_y,
290 child->m_width,
291 child->m_height );
f362b96d
RR
292 }
293
f362b96d 294 /* resize on OnInternalIdle */
f03fc89f 295 parent->UpdateSize();
f362b96d
RR
296}
297
2f2aa628
RR
298//-----------------------------------------------------------------------------
299// wxFrame
c801d85f
KB
300//-----------------------------------------------------------------------------
301
302BEGIN_EVENT_TABLE(wxFrame, wxWindow)
fb1585ae 303 EVT_SIZE(wxFrame::OnSize)
fe4e9e6c 304 EVT_CLOSE(wxFrame::OnCloseWindow)
342b6a2f 305 EVT_MENU_HIGHLIGHT_ALL(wxFrame::OnMenuHighlight)
c801d85f
KB
306END_EVENT_TABLE()
307
308IMPLEMENT_DYNAMIC_CLASS(wxFrame,wxWindow)
309
19717c50 310wxFrame::wxFrame()
c801d85f 311{
fb1585ae
RR
312 m_frameMenuBar = (wxMenuBar *) NULL;
313 m_frameStatusBar = (wxStatusBar *) NULL;
314 m_frameToolBar = (wxToolBar *) NULL;
315 m_sizeSet = FALSE;
b2b3ccc5
RR
316 m_miniEdge = 0;
317 m_miniTitle = 0;
ab2b3dd4 318 m_mainWidget = (GtkWidget*) NULL;
16bcc879
RR
319 m_menuBarDetached = FALSE;
320 m_toolBarDetached = FALSE;
031bc97f 321 m_insertCallback = wxInsertChildInFrame;
362c6693 322}
c801d85f 323
ed7a557b 324wxFrame::wxFrame( wxWindow *parent, wxWindowID id, const wxString &title,
debe6624
JS
325 const wxPoint &pos, const wxSize &size,
326 long style, const wxString &name )
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;
fb1585ae 338 Create( parent, id, title, pos, size, style, name );
362c6693 339}
c801d85f 340
debe6624 341bool wxFrame::Create( wxWindow *parent, wxWindowID id, const wxString &title,
c801d85f 342 const wxPoint &pos, const wxSize &size,
debe6624 343 long style, const wxString &name )
c801d85f 344{
a802c3a1 345 wxTopLevelWindows.Append( this );
8bbe427f 346
fb1585ae 347 m_needParent = FALSE;
ed7a557b 348
fb1585ae 349 PreCreation( parent, id, pos, size, style, name );
c801d85f 350
fb1585ae 351 m_title = title;
f362b96d
RR
352
353 m_insertCallback = wxInsertChildInFrame;
ed7a557b 354
fb1585ae
RR
355 GtkWindowType win_type = GTK_WINDOW_TOPLEVEL;
356 if (style & wxSIMPLE_BORDER) win_type = GTK_WINDOW_POPUP;
8bbe427f 357
fb1585ae 358 m_widget = gtk_window_new( win_type );
de1c750f
RR
359
360 if (!name.IsEmpty())
361 gtk_window_set_wmclass( GTK_WINDOW(m_widget), name.mb_str(), name.mb_str() );
8bbe427f 362
2e563988
RR
363#ifdef __WXDEBUG__
364 debug_focus_in( m_widget, _T("wxFrame::m_widget"), name );
365#endif
366
ed9b9841 367 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
fb1585ae 368 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
ed7a557b 369
fb1585ae
RR
370 gtk_signal_connect( GTK_OBJECT(m_widget), "delete_event",
371 GTK_SIGNAL_FUNC(gtk_frame_delete_callback), (gpointer)this );
ed7a557b 372
f362b96d
RR
373 /* m_mainWidget holds the toolbar, the menubar and the client area */
374 m_mainWidget = gtk_myfixed_new();
375 gtk_widget_show( m_mainWidget );
376 GTK_WIDGET_UNSET_FLAGS( m_mainWidget, GTK_CAN_FOCUS );
377 gtk_container_add( GTK_CONTAINER(m_widget), m_mainWidget );
f362b96d 378
2e563988
RR
379#ifdef __WXDEBUG__
380 debug_focus_in( m_mainWidget, _T("wxFrame::m_mainWidget"), name );
381#endif
382
f362b96d 383 /* m_wxwindow only represents the client area without toolbar and menubar */
fb1585ae
RR
384 m_wxwindow = gtk_myfixed_new();
385 gtk_widget_show( m_wxwindow );
f362b96d 386 gtk_container_add( GTK_CONTAINER(m_mainWidget), m_wxwindow );
1e133b7d 387
2e563988
RR
388#ifdef __WXDEBUG__
389 debug_focus_in( m_wxwindow, _T("wxFrame::m_wxwindow"), name );
390#endif
391
392 /* we donm't allow the frame to get the focus as otherwise
393 the frame will grabit at arbitrary fcous changes. */
394 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
ed7a557b 395
de8113d9
RR
396 if (m_parent) m_parent->AddChild( this );
397
398 PostCreation();
399
58dea4b0 400 /* we cannot set MWM hints and icons before the widget has
2b07d713
RR
401 been realized, so we do this directly after realization */
402 gtk_signal_connect( GTK_OBJECT(m_widget), "realize",
f03fc89f 403 GTK_SIGNAL_FUNC(gtk_frame_realized_callback), (gpointer) this );
de8113d9 404
ab2b3dd4 405 /* the user resized the frame by dragging etc. */
fb1585ae
RR
406 gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
407 GTK_SIGNAL_FUNC(gtk_frame_size_callback), (gpointer)this );
ed7a557b 408
ab2b3dd4 409 /* the only way to get the window size is to connect to this event */
fb1585ae
RR
410 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
411 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
8bbe427f 412
fb1585ae 413 return TRUE;
362c6693 414}
c801d85f 415
19717c50 416wxFrame::~wxFrame()
c801d85f 417{
31c6b4fc
RR
418 m_isBeingDeleted = TRUE;
419
fb1585ae 420 if (m_frameMenuBar) delete m_frameMenuBar;
e27ce4e9
RR
421 m_frameMenuBar = (wxMenuBar *) NULL;
422
fb1585ae 423 if (m_frameStatusBar) delete m_frameStatusBar;
e27ce4e9
RR
424 m_frameStatusBar = (wxStatusBar *) NULL;
425
fb1585ae 426 if (m_frameToolBar) delete m_frameToolBar;
e27ce4e9 427 m_frameToolBar = (wxToolBar *) NULL;
ed7a557b 428
fb1585ae 429 wxTopLevelWindows.DeleteObject( this );
2b854a32 430
0d2a2b60 431 if (wxTheApp->GetTopWindow() == this)
0d2a2b60 432 wxTheApp->SetTopWindow( (wxWindow*) NULL );
2b854a32 433
0d2a2b60 434 if (wxTopLevelWindows.Number() == 0)
0d2a2b60 435 wxTheApp->ExitMainLoop();
362c6693 436}
ed7a557b 437
debe6624 438bool wxFrame::Show( bool show )
c801d85f 439{
ed9b9841 440 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 441
35178437 442 if (show && !m_sizeSet)
fb1585ae 443 {
e27ce4e9
RR
444 /* by calling GtkOnSize here, we don't have to call
445 either after showing the frame, which would entail
f362b96d 446 much ugly flicker or from within the size_allocate
e27ce4e9 447 handler, because GTK 1.1.X forbids that. */
8bbe427f 448
35178437 449 GtkOnSize( m_x, m_y, m_width, m_height );
fb1585ae 450 }
8bbe427f 451
fb1585ae 452 return wxWindow::Show( show );
362c6693 453}
c801d85f 454
19717c50 455bool wxFrame::Destroy()
c801d85f 456{
ed9b9841 457 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 458
fb1585ae 459 if (!wxPendingDelete.Member(this)) wxPendingDelete.Append(this);
ed7a557b 460
fb1585ae 461 return TRUE;
c801d85f
KB
462}
463
bfc6fde4 464void wxFrame::DoSetSize( int x, int y, int width, int height, int sizeFlags )
903f689b 465{
ed9b9841 466 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 467
ab2b3dd4 468 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
ed9b9841 469 wxASSERT_MSG( (m_wxwindow != NULL), _T("invalid frame") );
ab2b3dd4
RR
470
471 /* avoid recursions */
472 if (m_resizing) return;
fb1585ae
RR
473 m_resizing = TRUE;
474
475 int old_x = m_x;
476 int old_y = m_y;
477 int old_width = m_width;
478 int old_height = m_height;
8bbe427f 479
fb1585ae
RR
480 if ((sizeFlags & wxSIZE_USE_EXISTING) == wxSIZE_USE_EXISTING)
481 {
482 if (x != -1) m_x = x;
483 if (y != -1) m_y = y;
484 if (width != -1) m_width = width;
485 if (height != -1) m_height = height;
486 }
487 else
488 {
489 m_x = x;
490 m_y = y;
491 m_width = width;
492 m_height = height;
493 }
494
495 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
496 {
497 if (width == -1) m_width = 80;
498 }
499
500 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
501 {
502 if (height == -1) m_height = 26;
503 }
8bbe427f 504
fb1585ae
RR
505 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
506 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
0c77152e
RR
507 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
508 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
fb1585ae
RR
509
510 if ((m_x != -1) || (m_y != -1))
511 {
8bbe427f 512 if ((m_x != old_x) || (m_y != old_y))
0138c2de 513 {
227e5e99 514 /* we set the size here and in gtk_frame_map_callback */
f03fc89f 515 gtk_widget_set_uposition( m_widget, m_x, m_y );
0138c2de 516 }
fb1585ae 517 }
8bbe427f 518
fb1585ae
RR
519 if ((m_width != old_width) || (m_height != old_height))
520 {
ab2b3dd4 521 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
f03fc89f
VZ
522 done either directly before the frame is shown or in idle time
523 so that different calls to SetSize() don't lead to flicker. */
de8113d9 524 m_sizeSet = FALSE;
fb1585ae 525 }
8bbe427f 526
fb1585ae 527 m_resizing = FALSE;
903f689b
RR
528}
529
530void wxFrame::Centre( int direction )
531{
ed9b9841 532 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 533
43a18898
RR
534 int x = 0;
535 int y = 0;
8bbe427f 536
f5eafd0e
RR
537 if ((direction & wxHORIZONTAL) == wxHORIZONTAL) x = (gdk_screen_width () - m_width) / 2;
538 if ((direction & wxVERTICAL) == wxVERTICAL) y = (gdk_screen_height () - m_height) / 2;
8bbe427f 539
fb1585ae 540 Move( x, y );
903f689b
RR
541}
542
f9241296 543void wxFrame::DoGetClientSize( int *width, int *height ) const
c801d85f 544{
ed9b9841 545 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 546
f9241296 547 wxWindow::DoGetClientSize( width, height );
fb1585ae 548 if (height)
46dc76ba 549 {
41ca191f
RR
550 /* menu bar */
551 if (m_frameMenuBar)
f03fc89f
VZ
552 {
553 if (!m_menuBarDetached)
554 (*height) -= wxMENU_HEIGHT;
555 else
556 (*height) -= wxPLACE_HOLDER;
557 }
558
559 /* status bar */
fb1585ae 560 if (m_frameStatusBar) (*height) -= wxSTATUS_HEIGHT;
f03fc89f
VZ
561
562 /* tool bar */
fb1585ae
RR
563 if (m_frameToolBar)
564 {
f03fc89f
VZ
565 if (!m_toolBarDetached)
566 {
41ca191f
RR
567 int y = 0;
568 m_frameToolBar->GetSize( (int *) NULL, &y );
569 (*height) -= y;
f03fc89f
VZ
570 }
571 else
41ca191f 572 (*height) -= wxPLACE_HOLDER;
fb1585ae 573 }
f03fc89f
VZ
574
575 /* mini edge */
b2b3ccc5
RR
576 (*height) -= m_miniEdge*2 + m_miniTitle;
577 }
578 if (width)
579 {
580 (*width) -= m_miniEdge*2;
46dc76ba 581 }
362c6693 582}
c801d85f 583
bfc6fde4 584void wxFrame::DoSetClientSize( int width, int height )
b593568e 585{
ed9b9841 586 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 587
41ca191f
RR
588 /* menu bar */
589 if (m_frameMenuBar)
f03fc89f
VZ
590 {
591 if (!m_menuBarDetached)
592 height += wxMENU_HEIGHT;
593 else
594 height += wxPLACE_HOLDER;
595 }
596
597 /* status bar */
41ca191f 598 if (m_frameStatusBar) height += wxSTATUS_HEIGHT;
f03fc89f
VZ
599
600 /* tool bar */
41ca191f
RR
601 if (m_frameToolBar)
602 {
f03fc89f
VZ
603 if (!m_toolBarDetached)
604 {
41ca191f
RR
605 int y = 0;
606 m_frameToolBar->GetSize( (int *) NULL, &y );
607 height += y;
f03fc89f
VZ
608 }
609 else
41ca191f
RR
610 height += wxPLACE_HOLDER;
611 }
f03fc89f 612
41ca191f 613 wxWindow::DoSetClientSize( width + m_miniEdge*2, height + m_miniEdge*2 + m_miniTitle );
362c6693 614}
b593568e 615
47908e25 616void wxFrame::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y), int width, int height )
c801d85f 617{
f5368809
RR
618 // due to a bug in gtk, x,y are always 0
619 // m_x = x;
620 // m_y = y;
621
ab2b3dd4 622 /* avoid recursions */
e52f60e6
RR
623 if (m_resizing) return;
624 m_resizing = TRUE;
8bbe427f 625
ab2b3dd4 626 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
ed9b9841 627 wxASSERT_MSG( (m_wxwindow != NULL), _T("invalid frame") );
ab2b3dd4 628
f5368809
RR
629 m_width = width;
630 m_height = height;
8bbe427f 631
ab2b3dd4 632 /* space occupied by m_frameToolBar and m_frameMenuBar */
f362b96d 633 int client_area_y_offset = 0;
8bbe427f 634
ab2b3dd4
RR
635 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
636 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
637 set in wxFrame::Create so it is used to check what kind of frame we
638 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
639 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
640 importantly) m_mainWidget */
641
642 if (m_mainWidget)
f5368809 643 {
ab2b3dd4
RR
644 /* check if size is in legal range */
645 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
646 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
647 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
648 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
649
650 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
651 * menubar, the toolbar and the client area, which is represented by
652 * m_wxwindow.
653 * this hurts in the eye, but I don't want to call SetSize()
654 * because I don't want to call any non-native functions here. */
655
656 if (m_frameMenuBar)
657 {
658 int xx = m_miniEdge;
659 int yy = m_miniEdge + m_miniTitle;
660 int ww = m_width - 2*m_miniEdge;
41ca191f 661 int hh = wxMENU_HEIGHT;
f03fc89f 662 if (m_menuBarDetached) hh = wxPLACE_HOLDER;
121a3581
RR
663 m_frameMenuBar->m_x = xx;
664 m_frameMenuBar->m_y = yy;
665 m_frameMenuBar->m_width = ww;
666 m_frameMenuBar->m_height = hh;
fdd3ed7a 667 gtk_myfixed_set_size( GTK_MYFIXED(m_mainWidget),
a2053b27 668 m_frameMenuBar->m_widget,
f03fc89f
VZ
669 xx, yy, ww, hh );
670 client_area_y_offset += hh;
ab2b3dd4 671 }
e27ce4e9 672
ab2b3dd4
RR
673 if (m_frameToolBar)
674 {
675 int xx = m_miniEdge;
676 int yy = m_miniEdge + m_miniTitle;
41ca191f 677 if (m_frameMenuBar)
f03fc89f
VZ
678 {
679 if (!m_menuBarDetached)
680 yy += wxMENU_HEIGHT;
681 else
682 yy += wxPLACE_HOLDER;
683 }
ab2b3dd4 684 int ww = m_width - 2*m_miniEdge;
a2053b27 685 int hh = m_frameToolBar->m_height;
121a3581
RR
686 if (m_toolBarDetached) hh = wxPLACE_HOLDER;
687 m_frameToolBar->m_x = xx;
688 m_frameToolBar->m_y = yy;
689 /* m_frameToolBar->m_height = hh; don't change the toolbar's height */
690 m_frameToolBar->m_width = ww;
fdd3ed7a 691 gtk_myfixed_set_size( GTK_MYFIXED(m_mainWidget),
a2053b27 692 m_frameToolBar->m_widget,
f03fc89f
VZ
693 xx, yy, ww, hh );
694 client_area_y_offset += hh;
ab2b3dd4
RR
695 }
696
32a95f9f 697 int client_x = m_miniEdge;
f03fc89f 698 int client_y = client_area_y_offset + m_miniEdge + m_miniTitle;
32a95f9f 699 int client_w = m_width - 2*m_miniEdge;
f03fc89f 700 int client_h = m_height - client_area_y_offset- 2*m_miniEdge - m_miniTitle;
fdd3ed7a 701 gtk_myfixed_set_size( GTK_MYFIXED(m_mainWidget),
f03fc89f
VZ
702 m_wxwindow,
703 client_x, client_y, client_w, client_h );
32a95f9f
RR
704 }
705 else
706 {
707 /* if there is no m_mainWidget between m_widget and m_wxwindow there
f03fc89f 708 is no need to set the size or position of m_wxwindow. */
f5368809 709 }
f362b96d 710
f5368809
RR
711 if (m_frameStatusBar)
712 {
b2b3ccc5 713 int xx = 0 + m_miniEdge;
f362b96d 714 int yy = m_height - wxSTATUS_HEIGHT - m_miniEdge - client_area_y_offset;
ac57418f
RR
715 int ww = m_width - 2*m_miniEdge;
716 int hh = wxSTATUS_HEIGHT;
121a3581
RR
717 m_frameStatusBar->m_x = xx;
718 m_frameStatusBar->m_y = yy;
719 m_frameStatusBar->m_width = ww;
720 m_frameStatusBar->m_height = hh;
fdd3ed7a 721 gtk_myfixed_set_size( GTK_MYFIXED(m_wxwindow),
a2053b27 722 m_frameStatusBar->m_widget,
f03fc89f 723 xx, yy, ww, hh );
f5368809 724 }
8bbe427f 725
de8113d9
RR
726 /* we actually set the size of a frame here and no-where else */
727 gtk_widget_set_usize( m_widget, m_width, m_height );
e208b369 728
f5368809 729 m_sizeSet = TRUE;
8bbe427f 730
884470b1 731 /* send size event to frame */
43a18898
RR
732 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
733 event.SetEventObject( this );
e52f60e6 734 GetEventHandler()->ProcessEvent( event );
8bbe427f 735
884470b1 736 /* send size event to status bar */
5aa5e35a
RR
737 if (m_frameStatusBar)
738 {
a2053b27 739 wxSizeEvent event2( wxSize(m_frameStatusBar->m_width,m_frameStatusBar->m_height), m_frameStatusBar->GetId() );
5aa5e35a
RR
740 event2.SetEventObject( m_frameStatusBar );
741 m_frameStatusBar->GetEventHandler()->ProcessEvent( event2 );
742 }
884470b1 743
e52f60e6
RR
744 m_resizing = FALSE;
745}
746
9390a202 747void wxFrame::OnInternalIdle()
e52f60e6 748{
1b3667ab 749 if (!m_sizeSet && GTK_WIDGET_REALIZED(m_wxwindow))
e52f60e6 750 GtkOnSize( m_x, m_y, m_width, m_height );
8bbe427f 751
e52f60e6 752 DoMenuUpdates();
362c6693 753}
c801d85f 754
fe4e9e6c
VZ
755void wxFrame::OnCloseWindow( wxCloseEvent& event )
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
VZ
791 int client_x, client_y;
792 GetClientSize( &client_x, &client_y );
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
362c6693 890wxToolBar* wxFrame::CreateToolBar(long style, wxWindowID id, const wxString& name)
46dc76ba 891{
ed9b9841 892 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 893
ed9b9841 894 wxCHECK_MSG( m_frameToolBar == NULL, FALSE, _T("recreating toolbar in wxFrame") );
362c6693 895
f5368809 896 m_frameToolBar = OnCreateToolBar( style, id, name );
8bbe427f 897
db1b4961 898 GetChildren().DeleteObject( m_frameToolBar );
8bbe427f 899
5b077d48 900 m_sizeSet = FALSE;
8bbe427f 901
f5368809 902 return m_frameToolBar;
362c6693 903}
46dc76ba 904
362c6693 905wxToolBar* wxFrame::OnCreateToolBar( long style, wxWindowID id, const wxString& name )
46dc76ba 906{
f5368809 907 return new wxToolBar( this, id, wxDefaultPosition, wxDefaultSize, style, name );
362c6693
RR
908}
909
8bbe427f
VZ
910wxToolBar *wxFrame::GetToolBar() const
911{
912 return m_frameToolBar;
362c6693 913}
46dc76ba 914
e3e65dac 915wxStatusBar* wxFrame::CreateStatusBar( int number, long style, wxWindowID id, const wxString& name )
c801d85f 916{
ed9b9841 917 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 918
ed9b9841 919 wxCHECK_MSG( m_frameStatusBar == NULL, FALSE, _T("recreating status bar in wxFrame") );
c801d85f 920
f5368809 921 m_frameStatusBar = OnCreateStatusBar( number, style, id, name );
8bbe427f 922
5b077d48 923 m_sizeSet = FALSE;
8bbe427f 924
f5368809 925 return m_frameStatusBar;
362c6693
RR
926}
927
928wxStatusBar *wxFrame::OnCreateStatusBar( int number, long style, wxWindowID id, const wxString& name )
929{
f5368809 930 wxStatusBar *statusBar = (wxStatusBar *) NULL;
8bbe427f 931
f5368809 932 statusBar = new wxStatusBar(this, id, wxPoint(0, 0), wxSize(100, 20), style, name);
8bbe427f 933
f5368809
RR
934 // Set the height according to the font and the border size
935 wxClientDC dc(statusBar);
8bbe427f 936 dc.SetFont( statusBar->GetFont() );
362c6693 937
f5368809
RR
938 long x, y;
939 dc.GetTextExtent( "X", &x, &y );
362c6693 940
f5368809 941 int height = (int)( (y * 1.1) + 2* statusBar->GetBorderY());
362c6693 942
f5368809 943 statusBar->SetSize( -1, -1, 100, height );
362c6693 944
f5368809
RR
945 statusBar->SetFieldsCount( number );
946 return statusBar;
362c6693 947}
c801d85f 948
30f1b5f3
RR
949void wxFrame::Command( int id )
950{
951 wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, id);
952 commandEvent.SetInt( id );
953 commandEvent.SetEventObject( this );
954
955 wxMenuBar *bar = GetMenuBar();
956 if (!bar) return;
957
958 wxMenuItem *item = bar->FindItemForId(id) ;
959 if (item && item->IsCheckable())
960 {
961 bar->Check(id,!bar->Checked(id)) ;
962 }
e702ff0f 963
6c41a418 964 wxEvtHandler* evtHandler = GetEventHandler();
e702ff0f
JS
965
966 evtHandler->ProcessEvent(commandEvent);
30f1b5f3
RR
967}
968
362c6693 969void wxFrame::SetStatusText(const wxString& text, int number)
c801d85f 970{
ed9b9841 971 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 972
ed9b9841 973 wxCHECK_RET( m_frameStatusBar != NULL, _T("no statusbar to set text for") );
c801d85f 974
f5368809 975 m_frameStatusBar->SetStatusText(text, number);
362c6693
RR
976}
977
978void wxFrame::SetStatusWidths(int n, const int widths_field[] )
c801d85f 979{
ed9b9841 980 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 981
ed9b9841 982 wxCHECK_RET( m_frameStatusBar != NULL, _T("no statusbar to set widths for") );
362c6693 983
f5368809 984 m_frameStatusBar->SetStatusWidths(n, widths_field);
362c6693 985}
c801d85f 986
8bbe427f 987wxStatusBar *wxFrame::GetStatusBar() const
c801d85f 988{
f5368809 989 return m_frameStatusBar;
362c6693 990}
c801d85f 991
c801d85f
KB
992void wxFrame::SetTitle( const wxString &title )
993{
ed9b9841 994 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 995
f5368809 996 m_title = title;
ed9b9841
OK
997 if (m_title.IsNull()) m_title = _T("");
998 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
362c6693 999}
c801d85f 1000
d355d3fe
RR
1001void wxFrame::SetIcon( const wxIcon &icon )
1002{
ed9b9841 1003 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
8bbe427f 1004
f5368809
RR
1005 m_icon = icon;
1006 if (!icon.Ok()) return;
8bbe427f 1007
58dea4b0
RR
1008 if (!m_widget->window) return;
1009
f5368809
RR
1010 wxMask *mask = icon.GetMask();
1011 GdkBitmap *bm = (GdkBitmap *) NULL;
1012 if (mask) bm = mask->GetBitmap();
8bbe427f 1013
f5368809 1014 gdk_window_set_icon( m_widget->window, (GdkWindow *) NULL, icon.GetPixmap(), bm );
d355d3fe 1015}
b2b3ccc5 1016