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