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