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