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