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