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