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