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