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