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