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