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