]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/frame.cpp
Empty notebooks show up again. I'm afraid this
[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 wxFrame::wxFrame()
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_insertCallback = (wxInsertChildFunction) NULL;
319 m_insertInClientArea = TRUE;
320 }
321
322 wxFrame::wxFrame( wxWindow *parent, wxWindowID id, const wxString &title,
323 const wxPoint &pos, const wxSize &size,
324 long style, const wxString &name )
325 {
326 m_frameMenuBar = (wxMenuBar *) NULL;
327 m_frameStatusBar = (wxStatusBar *) NULL;
328 m_frameToolBar = (wxToolBar *) NULL;
329 m_sizeSet = FALSE;
330 m_miniEdge = 0;
331 m_miniTitle = 0;
332 m_mainWidget = (GtkWidget*) NULL;
333 m_menuBarDetached = FALSE;
334 m_toolBarDetached = FALSE;
335 m_insertCallback = (wxInsertChildFunction) NULL;
336 m_insertInClientArea = TRUE;
337 Create( parent, id, title, pos, size, style, name );
338 }
339
340 bool wxFrame::Create( wxWindow *parent, wxWindowID id, const wxString &title,
341 const wxPoint &pos, const wxSize &size,
342 long style, const wxString &name )
343 {
344 wxTopLevelWindows.Append( this );
345
346 m_needParent = FALSE;
347
348 PreCreation( parent, id, pos, size, style, name );
349
350 m_title = title;
351
352 m_insertCallback = (wxInsertChildFunction) wxInsertChildInFrame;
353
354 GtkWindowType win_type = GTK_WINDOW_TOPLEVEL;
355 if (style & wxSIMPLE_BORDER) win_type = GTK_WINDOW_POPUP;
356
357 m_widget = gtk_window_new( win_type );
358
359 if (!name.IsEmpty())
360 gtk_window_set_wmclass( GTK_WINDOW(m_widget), name.mb_str(), name.mb_str() );
361
362 #ifdef __WXDEBUG__
363 debug_focus_in( m_widget, _T("wxFrame::m_widget"), name );
364 #endif
365
366 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
367 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
368
369 gtk_signal_connect( GTK_OBJECT(m_widget), "delete_event",
370 GTK_SIGNAL_FUNC(gtk_frame_delete_callback), (gpointer)this );
371
372 /* m_mainWidget holds the toolbar, the menubar and the client area */
373 m_mainWidget = gtk_myfixed_new();
374 gtk_widget_show( m_mainWidget );
375 GTK_WIDGET_UNSET_FLAGS( m_mainWidget, GTK_CAN_FOCUS );
376 gtk_container_add( GTK_CONTAINER(m_widget), m_mainWidget );
377
378 #ifdef __WXDEBUG__
379 debug_focus_in( m_mainWidget, _T("wxFrame::m_mainWidget"), name );
380 #endif
381
382 /* m_wxwindow only represents the client area without toolbar and menubar */
383 m_wxwindow = gtk_myfixed_new();
384 gtk_widget_show( m_wxwindow );
385 gtk_container_add( GTK_CONTAINER(m_mainWidget), m_wxwindow );
386
387 #ifdef __WXDEBUG__
388 debug_focus_in( m_wxwindow, _T("wxFrame::m_wxwindow"), name );
389 #endif
390
391 /* we donm't allow the frame to get the focus as otherwise
392 the frame will grabit at arbitrary fcous changes. */
393 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
394
395 if (m_parent) m_parent->AddChild( this );
396
397 PostCreation();
398
399 /* we cannot set MWM hints and icons before the widget has
400 been realized, so we do this directly after realization */
401 gtk_signal_connect( GTK_OBJECT(m_widget), "realize",
402 GTK_SIGNAL_FUNC(gtk_frame_realized_callback), (gpointer) this );
403
404 /* the user resized the frame by dragging etc. */
405 gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
406 GTK_SIGNAL_FUNC(gtk_frame_size_callback), (gpointer)this );
407
408 /* the only way to get the window size is to connect to this event */
409 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
410 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
411
412 return TRUE;
413 }
414
415 wxFrame::~wxFrame()
416 {
417 m_isBeingDeleted = TRUE;
418
419 if (m_frameMenuBar) delete m_frameMenuBar;
420 m_frameMenuBar = (wxMenuBar *) NULL;
421
422 if (m_frameStatusBar) delete m_frameStatusBar;
423 m_frameStatusBar = (wxStatusBar *) NULL;
424
425 if (m_frameToolBar) delete m_frameToolBar;
426 m_frameToolBar = (wxToolBar *) NULL;
427
428 wxTopLevelWindows.DeleteObject( this );
429
430 if (wxTheApp->GetTopWindow() == this)
431 wxTheApp->SetTopWindow( (wxWindow*) NULL );
432
433 if (wxTopLevelWindows.Number() == 0)
434 wxTheApp->ExitMainLoop();
435 }
436
437 bool wxFrame::Show( bool show )
438 {
439 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
440
441 if (show && !m_sizeSet)
442 {
443 /* by calling GtkOnSize here, we don't have to call
444 either after showing the frame, which would entail
445 much ugly flicker or from within the size_allocate
446 handler, because GTK 1.1.X forbids that. */
447
448 GtkOnSize( m_x, m_y, m_width, m_height );
449 }
450
451 return wxWindow::Show( show );
452 }
453
454 bool wxFrame::Destroy()
455 {
456 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
457
458 if (!wxPendingDelete.Member(this)) wxPendingDelete.Append(this);
459
460 return TRUE;
461 }
462
463 void wxFrame::DoSetSize( int x, int y, int width, int height, int sizeFlags )
464 {
465 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
466
467 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
468 wxASSERT_MSG( (m_wxwindow != NULL), _T("invalid frame") );
469
470 /* avoid recursions */
471 if (m_resizing) return;
472 m_resizing = TRUE;
473
474 int old_x = m_x;
475 int old_y = m_y;
476 int old_width = m_width;
477 int old_height = m_height;
478
479 if ((sizeFlags & wxSIZE_USE_EXISTING) == wxSIZE_USE_EXISTING)
480 {
481 if (x != -1) m_x = x;
482 if (y != -1) m_y = y;
483 if (width != -1) m_width = width;
484 if (height != -1) m_height = height;
485 }
486 else
487 {
488 m_x = x;
489 m_y = y;
490 m_width = width;
491 m_height = height;
492 }
493
494 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
495 {
496 if (width == -1) m_width = 80;
497 }
498
499 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
500 {
501 if (height == -1) m_height = 26;
502 }
503
504 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
505 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
506 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
507 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
508
509 if ((m_x != -1) || (m_y != -1))
510 {
511 if ((m_x != old_x) || (m_y != old_y))
512 {
513 /* we set the size here and in gtk_frame_map_callback */
514 gtk_widget_set_uposition( m_widget, m_x, m_y );
515 }
516 }
517
518 if ((m_width != old_width) || (m_height != old_height))
519 {
520 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
521 done either directly before the frame is shown or in idle time
522 so that different calls to SetSize() don't lead to flicker. */
523 m_sizeSet = FALSE;
524 }
525
526 m_resizing = FALSE;
527 }
528
529 void wxFrame::Centre( int direction )
530 {
531 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
532
533 int x = 0;
534 int y = 0;
535
536 if ((direction & wxHORIZONTAL) == wxHORIZONTAL) x = (gdk_screen_width () - m_width) / 2;
537 if ((direction & wxVERTICAL) == wxVERTICAL) y = (gdk_screen_height () - m_height) / 2;
538
539 Move( x, y );
540 }
541
542 void wxFrame::DoGetClientSize( int *width, int *height ) const
543 {
544 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
545
546 wxWindow::DoGetClientSize( width, height );
547 if (height)
548 {
549 /* menu bar */
550 if (m_frameMenuBar)
551 {
552 if (!m_menuBarDetached)
553 (*height) -= wxMENU_HEIGHT;
554 else
555 (*height) -= wxPLACE_HOLDER;
556 }
557
558 /* status bar */
559 if (m_frameStatusBar) (*height) -= wxSTATUS_HEIGHT;
560
561 /* tool bar */
562 if (m_frameToolBar)
563 {
564 if (!m_toolBarDetached)
565 {
566 int y = 0;
567 m_frameToolBar->GetSize( (int *) NULL, &y );
568 (*height) -= y;
569 }
570 else
571 (*height) -= wxPLACE_HOLDER;
572 }
573
574 /* mini edge */
575 (*height) -= m_miniEdge*2 + m_miniTitle;
576 }
577 if (width)
578 {
579 (*width) -= m_miniEdge*2;
580 }
581 }
582
583 void wxFrame::DoSetClientSize( int width, int height )
584 {
585 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
586
587 /* menu bar */
588 if (m_frameMenuBar)
589 {
590 if (!m_menuBarDetached)
591 height += wxMENU_HEIGHT;
592 else
593 height += wxPLACE_HOLDER;
594 }
595
596 /* status bar */
597 if (m_frameStatusBar) height += wxSTATUS_HEIGHT;
598
599 /* tool bar */
600 if (m_frameToolBar)
601 {
602 if (!m_toolBarDetached)
603 {
604 int y = 0;
605 m_frameToolBar->GetSize( (int *) NULL, &y );
606 height += y;
607 }
608 else
609 height += wxPLACE_HOLDER;
610 }
611
612 wxWindow::DoSetClientSize( width + m_miniEdge*2, height + m_miniEdge*2 + m_miniTitle );
613 }
614
615 void wxFrame::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y), int width, int height )
616 {
617 // due to a bug in gtk, x,y are always 0
618 // m_x = x;
619 // m_y = y;
620
621 /* avoid recursions */
622 if (m_resizing) return;
623 m_resizing = TRUE;
624
625 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
626 wxASSERT_MSG( (m_wxwindow != NULL), _T("invalid frame") );
627
628 m_width = width;
629 m_height = height;
630
631 /* space occupied by m_frameToolBar and m_frameMenuBar */
632 int client_area_y_offset = 0;
633
634 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
635 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
636 set in wxFrame::Create so it is used to check what kind of frame we
637 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
638 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
639 importantly) m_mainWidget */
640
641 if (m_mainWidget)
642 {
643 /* check if size is in legal range */
644 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
645 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
646 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
647 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
648
649 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
650 * menubar, the toolbar and the client area, which is represented by
651 * m_wxwindow.
652 * this hurts in the eye, but I don't want to call SetSize()
653 * because I don't want to call any non-native functions here. */
654
655 if (m_frameMenuBar)
656 {
657 int xx = m_miniEdge;
658 int yy = m_miniEdge + m_miniTitle;
659 int ww = m_width - 2*m_miniEdge;
660 int hh = wxMENU_HEIGHT;
661 if (m_menuBarDetached) hh = wxPLACE_HOLDER;
662 m_frameMenuBar->m_x = xx;
663 m_frameMenuBar->m_y = yy;
664 m_frameMenuBar->m_width = ww;
665 m_frameMenuBar->m_height = hh;
666 gtk_myfixed_set_size( GTK_MYFIXED(m_mainWidget),
667 m_frameMenuBar->m_widget,
668 xx, yy, ww, hh );
669 client_area_y_offset += hh;
670 }
671
672 if (m_frameToolBar)
673 {
674 int xx = m_miniEdge;
675 int yy = m_miniEdge + m_miniTitle;
676 if (m_frameMenuBar)
677 {
678 if (!m_menuBarDetached)
679 yy += wxMENU_HEIGHT;
680 else
681 yy += wxPLACE_HOLDER;
682 }
683 int ww = m_width - 2*m_miniEdge;
684 int hh = m_frameToolBar->m_height;
685 if (m_toolBarDetached) hh = wxPLACE_HOLDER;
686 m_frameToolBar->m_x = xx;
687 m_frameToolBar->m_y = yy;
688 /* m_frameToolBar->m_height = hh; don't change the toolbar's height */
689 m_frameToolBar->m_width = ww;
690 gtk_myfixed_set_size( GTK_MYFIXED(m_mainWidget),
691 m_frameToolBar->m_widget,
692 xx, yy, ww, hh );
693 client_area_y_offset += hh;
694 }
695
696 int client_x = m_miniEdge;
697 int client_y = client_area_y_offset + m_miniEdge + m_miniTitle;
698 int client_w = m_width - 2*m_miniEdge;
699 int client_h = m_height - client_area_y_offset- 2*m_miniEdge - m_miniTitle;
700 gtk_myfixed_set_size( GTK_MYFIXED(m_mainWidget),
701 m_wxwindow,
702 client_x, client_y, client_w, client_h );
703 }
704 else
705 {
706 /* if there is no m_mainWidget between m_widget and m_wxwindow there
707 is no need to set the size or position of m_wxwindow. */
708 }
709
710 if (m_frameStatusBar)
711 {
712 int xx = 0 + m_miniEdge;
713 int yy = m_height - wxSTATUS_HEIGHT - m_miniEdge - client_area_y_offset;
714 int ww = m_width - 2*m_miniEdge;
715 int hh = wxSTATUS_HEIGHT;
716 m_frameStatusBar->m_x = xx;
717 m_frameStatusBar->m_y = yy;
718 m_frameStatusBar->m_width = ww;
719 m_frameStatusBar->m_height = hh;
720 gtk_myfixed_set_size( GTK_MYFIXED(m_wxwindow),
721 m_frameStatusBar->m_widget,
722 xx, yy, ww, hh );
723 }
724
725 /* we actually set the size of a frame here and no-where else */
726 gtk_widget_set_usize( m_widget, m_width, m_height );
727
728 m_sizeSet = TRUE;
729
730 /* send size event to frame */
731 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
732 event.SetEventObject( this );
733 GetEventHandler()->ProcessEvent( event );
734
735 /* send size event to status bar */
736 if (m_frameStatusBar)
737 {
738 wxSizeEvent event2( wxSize(m_frameStatusBar->m_width,m_frameStatusBar->m_height), m_frameStatusBar->GetId() );
739 event2.SetEventObject( m_frameStatusBar );
740 m_frameStatusBar->GetEventHandler()->ProcessEvent( event2 );
741 }
742
743 m_resizing = FALSE;
744 }
745
746 void wxFrame::OnInternalIdle()
747 {
748 if (!m_sizeSet && GTK_WIDGET_REALIZED(m_wxwindow))
749 GtkOnSize( m_x, m_y, m_width, m_height );
750
751 DoMenuUpdates();
752 }
753
754 void wxFrame::OnCloseWindow( wxCloseEvent& WXUNUSED(event) )
755 {
756 Destroy();
757 }
758
759 void wxFrame::OnSize( wxSizeEvent &WXUNUSED(event) )
760 {
761 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
762
763 if (GetAutoLayout())
764 {
765 Layout();
766 }
767 else
768 {
769 /* do we have exactly one child? */
770 wxWindow *child = (wxWindow *)NULL;
771 for ( wxNode *node = GetChildren().First(); node; node = node->Next() )
772 {
773 wxWindow *win = (wxWindow *)node->Data();
774 if ( !wxIS_KIND_OF(win,wxFrame) && !wxIS_KIND_OF(win,wxDialog) )
775 {
776 if (child)
777 {
778 /* it's the second one: do nothing */
779 return;
780 }
781
782 child = win;
783 }
784 }
785
786 /* no children at all? */
787 if (child)
788 {
789 /* yes: set it's size to fill all the frame */
790 int client_x, client_y;
791 DoGetClientSize( &client_x, &client_y );
792 child->SetSize( 1, 1, client_x-2, client_y-2 );
793 }
794 }
795 }
796
797 static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
798 {
799 menu->SetInvokingWindow( win );
800
801 #if (GTK_MINOR_VERSION > 0)
802 /* support for native hot keys */
803 gtk_accel_group_attach( menu->m_accel, GTK_OBJECT(win->m_widget));
804 #endif
805
806 wxNode *node = menu->GetItems().First();
807 while (node)
808 {
809 wxMenuItem *menuitem = (wxMenuItem*)node->Data();
810 if (menuitem->IsSubMenu())
811 SetInvokingWindow( menuitem->GetSubMenu(), win );
812 node = node->Next();
813 }
814 }
815
816 void wxFrame::SetMenuBar( wxMenuBar *menuBar )
817 {
818 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
819 wxASSERT_MSG( (m_wxwindow != NULL), _T("invalid frame") );
820
821 m_frameMenuBar = menuBar;
822
823 if (m_frameMenuBar)
824 {
825 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
826 /* support for native key accelerators indicated by underscroes */
827 gtk_accel_group_attach( m_frameMenuBar->m_accel, GTK_OBJECT(m_widget));
828 #endif
829
830 wxNode *node = m_frameMenuBar->GetMenus().First();
831 while (node)
832 {
833 wxMenu *menu = (wxMenu*)node->Data();
834 SetInvokingWindow( menu, this );
835 node = node->Next();
836 }
837
838 if (m_frameMenuBar->GetParent() != this)
839 {
840 m_frameMenuBar->SetParent(this);
841 gtk_myfixed_put( GTK_MYFIXED(m_mainWidget),
842 m_frameMenuBar->m_widget,
843 m_frameMenuBar->m_x,
844 m_frameMenuBar->m_y,
845 m_frameMenuBar->m_width,
846 m_frameMenuBar->m_height );
847
848 if (menuBar->GetWindowStyle() & wxMB_DOCKABLE)
849 {
850 gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_attached",
851 GTK_SIGNAL_FUNC(gtk_menu_attached_callback), (gpointer)this );
852
853 gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_detached",
854 GTK_SIGNAL_FUNC(gtk_menu_detached_callback), (gpointer)this );
855 }
856 }
857 }
858
859 /* resize window in OnInternalIdle */
860 m_sizeSet = FALSE;
861 }
862
863 wxMenuBar *wxFrame::GetMenuBar() const
864 {
865 return m_frameMenuBar;
866 }
867
868 void wxFrame::OnMenuHighlight(wxMenuEvent& event)
869 {
870 if (GetStatusBar())
871 {
872 // if no help string found, we will clear the status bar text
873 wxString helpString;
874
875 int menuId = event.GetMenuId();
876 if ( menuId != -1 )
877 {
878 wxMenuBar *menuBar = GetMenuBar();
879 if (menuBar)
880 {
881 helpString = menuBar->GetHelpString(menuId);
882 }
883 }
884
885 SetStatusText(helpString);
886 }
887 }
888
889 wxToolBar* wxFrame::CreateToolBar( long style, wxWindowID id, const wxString& name )
890 {
891 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
892
893 wxCHECK_MSG( m_frameToolBar == NULL, FALSE, _T("recreating toolbar in wxFrame") );
894
895 m_insertInClientArea = FALSE;
896
897 m_frameToolBar = OnCreateToolBar( style, id, name );
898
899 if (m_frameToolBar) GetChildren().DeleteObject( m_frameToolBar );
900
901 m_insertInClientArea = TRUE;
902
903 m_sizeSet = FALSE;
904
905 return m_frameToolBar;
906 }
907
908 wxToolBar* wxFrame::OnCreateToolBar( long style, wxWindowID id, const wxString& name )
909 {
910 return new wxToolBar( this, id, wxDefaultPosition, wxDefaultSize, style, name );
911 }
912
913 wxToolBar *wxFrame::GetToolBar() const
914 {
915 return m_frameToolBar;
916 }
917
918 wxStatusBar* wxFrame::CreateStatusBar( int number, long style, wxWindowID id, const wxString& name )
919 {
920 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
921
922 wxCHECK_MSG( m_frameStatusBar == NULL, FALSE, _T("recreating status bar in wxFrame") );
923
924 m_frameStatusBar = OnCreateStatusBar( number, style, id, name );
925
926 m_sizeSet = FALSE;
927
928 return m_frameStatusBar;
929 }
930
931 wxStatusBar *wxFrame::OnCreateStatusBar( int number, long style, wxWindowID id, const wxString& name )
932 {
933 wxStatusBar *statusBar = (wxStatusBar *) NULL;
934
935 statusBar = new wxStatusBar(this, id, wxPoint(0, 0), wxSize(100, 20), style, name);
936
937 // Set the height according to the font and the border size
938 wxClientDC dc(statusBar);
939 dc.SetFont( statusBar->GetFont() );
940
941 long x, y;
942 dc.GetTextExtent( "X", &x, &y );
943
944 int height = (int)( (y * 1.1) + 2* statusBar->GetBorderY());
945
946 statusBar->SetSize( -1, -1, 100, height );
947
948 statusBar->SetFieldsCount( number );
949 return statusBar;
950 }
951
952 void wxFrame::Command( int id )
953 {
954 wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, id);
955 commandEvent.SetInt( id );
956 commandEvent.SetEventObject( this );
957
958 wxMenuBar *bar = GetMenuBar();
959 if (!bar) return;
960
961 wxMenuItem *item = bar->FindItemForId(id) ;
962 if (item && item->IsCheckable())
963 {
964 bar->Check(id,!bar->Checked(id)) ;
965 }
966
967 wxEvtHandler* evtHandler = GetEventHandler();
968
969 evtHandler->ProcessEvent(commandEvent);
970 }
971
972 void wxFrame::SetStatusText(const wxString& text, int number)
973 {
974 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
975
976 wxCHECK_RET( m_frameStatusBar != NULL, _T("no statusbar to set text for") );
977
978 m_frameStatusBar->SetStatusText(text, number);
979 }
980
981 void wxFrame::SetStatusWidths(int n, const int widths_field[] )
982 {
983 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
984
985 wxCHECK_RET( m_frameStatusBar != NULL, _T("no statusbar to set widths for") );
986
987 m_frameStatusBar->SetStatusWidths(n, widths_field);
988 }
989
990 wxStatusBar *wxFrame::GetStatusBar() const
991 {
992 return m_frameStatusBar;
993 }
994
995 void wxFrame::SetTitle( const wxString &title )
996 {
997 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
998
999 m_title = title;
1000 if (m_title.IsNull()) m_title = _T("");
1001 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
1002 }
1003
1004 void wxFrame::SetIcon( const wxIcon &icon )
1005 {
1006 wxASSERT_MSG( (m_widget != NULL), _T("invalid frame") );
1007
1008 m_icon = icon;
1009 if (!icon.Ok()) return;
1010
1011 if (!m_widget->window) return;
1012
1013 wxMask *mask = icon.GetMask();
1014 GdkBitmap *bm = (GdkBitmap *) NULL;
1015 if (mask) bm = mask->GetBitmap();
1016
1017 gdk_window_set_icon( m_widget->window, (GdkWindow *) NULL, icon.GetPixmap(), bm );
1018 }
1019