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