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