Added Set/GetThemeEnabled and used this for determining whether to paint a theme
[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 // ============================================================================
11 // declarations
12 // ============================================================================
13
14 // ----------------------------------------------------------------------------
15 // headers
16 // ----------------------------------------------------------------------------
17
18 #ifdef __GNUG__
19 #pragma implementation "frame.h"
20 #endif
21
22 #ifdef __VMS
23 #define XIconifyWindow XICONIFYWINDOW
24 #endif
25
26 #include "wx/frame.h"
27 #include "wx/dialog.h"
28 #include "wx/control.h"
29 #include "wx/app.h"
30 #include "wx/menu.h"
31 #if wxUSE_TOOLBAR
32 #include "wx/toolbar.h"
33 #endif
34 #if wxUSE_STATUSBAR
35 #include "wx/statusbr.h"
36 #endif
37 #include "wx/dcclient.h"
38
39 #include <glib.h>
40 #include <gdk/gdk.h>
41 #include <gtk/gtk.h>
42 #include <gdk/gdkkeysyms.h>
43 #include <gdk/gdkx.h>
44
45 #include "wx/gtk/win_gtk.h"
46
47 // ----------------------------------------------------------------------------
48 // constants
49 // ----------------------------------------------------------------------------
50
51 const int wxMENU_HEIGHT = 27;
52 const int wxSTATUS_HEIGHT = 25;
53 const int wxPLACE_HOLDER = 0;
54
55 // ----------------------------------------------------------------------------
56 // idle system
57 // ----------------------------------------------------------------------------
58
59 extern void wxapp_install_idle_handler();
60 extern bool g_isIdle;
61 extern int g_openDialogs;
62
63 // ----------------------------------------------------------------------------
64 // event tables
65 // ----------------------------------------------------------------------------
66
67 IMPLEMENT_DYNAMIC_CLASS(wxFrame,wxWindow)
68
69 // ----------------------------------------------------------------------------
70 // data
71 // ----------------------------------------------------------------------------
72
73 extern wxList wxPendingDelete;
74
75 // ----------------------------------------------------------------------------
76 // debug
77 // ----------------------------------------------------------------------------
78
79 #ifdef __WXDEBUG__
80
81 extern void debug_focus_in( GtkWidget* widget, const wxChar* name, const wxChar *window );
82
83 #endif
84
85 // ============================================================================
86 // implementation
87 // ============================================================================
88
89 // ----------------------------------------------------------------------------
90 // GTK callbacks
91 // ----------------------------------------------------------------------------
92
93 //-----------------------------------------------------------------------------
94 // "focus" from m_window
95 //-----------------------------------------------------------------------------
96
97 static gint gtk_frame_focus_callback( GtkWidget *widget, GtkDirectionType WXUNUSED(d), wxWindow *WXUNUSED(win) )
98 {
99 if (g_isIdle)
100 wxapp_install_idle_handler();
101
102 // This disables GTK's tab traversal
103 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus" );
104 return TRUE;
105 }
106
107 //-----------------------------------------------------------------------------
108 // "size_allocate"
109 //-----------------------------------------------------------------------------
110
111 static void gtk_frame_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation* alloc, wxFrame *win )
112 {
113 if (g_isIdle)
114 wxapp_install_idle_handler();
115
116 if (!win->m_hasVMT)
117 return;
118
119 if ((win->m_width != alloc->width) || (win->m_height != alloc->height))
120 {
121 /*
122 wxPrintf( "OnSize from " );
123 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
124 wxPrintf( win->GetClassInfo()->GetClassName() );
125 wxPrintf( " %d %d %d %d\n", (int)alloc->x,
126 (int)alloc->y,
127 (int)alloc->width,
128 (int)alloc->height );
129 */
130
131 win->m_width = alloc->width;
132 win->m_height = alloc->height;
133 win->m_queuedFullRedraw = TRUE;
134 win->GtkUpdateSize();
135 }
136 }
137
138 //-----------------------------------------------------------------------------
139 // "delete_event"
140 //-----------------------------------------------------------------------------
141
142 static gint gtk_frame_delete_callback( GtkWidget *WXUNUSED(widget), GdkEvent *WXUNUSED(event), wxFrame *win )
143 {
144 if (g_isIdle)
145 wxapp_install_idle_handler();
146
147 if ((g_openDialogs == 0) && (win->IsEnabled()))
148 win->Close();
149
150 return TRUE;
151 }
152
153 //-----------------------------------------------------------------------------
154 // "child_attached" of menu bar
155 //-----------------------------------------------------------------------------
156
157 static void gtk_menu_attached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
158 {
159 if (!win->m_hasVMT) return;
160
161 win->m_menuBarDetached = FALSE;
162 win->GtkUpdateSize();
163 }
164
165 //-----------------------------------------------------------------------------
166 // "child_detached" of menu bar
167 //-----------------------------------------------------------------------------
168
169 static void gtk_menu_detached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
170 {
171 if (!win->m_hasVMT) return;
172
173 win->m_menuBarDetached = TRUE;
174 win->GtkUpdateSize();
175 }
176
177 #if wxUSE_TOOLBAR
178 //-----------------------------------------------------------------------------
179 // "child_attached" of tool bar
180 //-----------------------------------------------------------------------------
181
182 static void gtk_toolbar_attached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
183 {
184 if (!win->m_hasVMT) return;
185
186 win->m_toolBarDetached = FALSE;
187
188 win->GtkUpdateSize();
189 }
190
191 //-----------------------------------------------------------------------------
192 // "child_detached" of tool bar
193 //-----------------------------------------------------------------------------
194
195 static void gtk_toolbar_detached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
196 {
197 if (g_isIdle)
198 wxapp_install_idle_handler();
199
200 if (!win->m_hasVMT) return;
201
202 win->m_toolBarDetached = TRUE;
203 win->GtkUpdateSize();
204 }
205 #endif // wxUSE_TOOLBAR
206
207 //-----------------------------------------------------------------------------
208 // "configure_event"
209 //-----------------------------------------------------------------------------
210
211 static gint
212 #if (GTK_MINOR_VERSION > 0)
213 gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *WXUNUSED(event), wxFrame *win )
214 #else
215 gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *event, wxFrame *win )
216 #endif
217 {
218 if (g_isIdle)
219 wxapp_install_idle_handler();
220
221 if (!win->m_hasVMT)
222 return FALSE;
223
224 #if (GTK_MINOR_VERSION > 0)
225 int x = 0;
226 int y = 0;
227 gdk_window_get_root_origin( win->m_widget->window, &x, &y );
228 win->m_x = x;
229 win->m_y = y;
230 #else
231 win->m_x = event->x;
232 win->m_y = event->y;
233 #endif
234
235 wxMoveEvent mevent( wxPoint(win->m_x,win->m_y), win->GetId() );
236 mevent.SetEventObject( win );
237 win->GetEventHandler()->ProcessEvent( mevent );
238
239 return FALSE;
240 }
241
242 //-----------------------------------------------------------------------------
243 // "realize" from m_widget
244 //-----------------------------------------------------------------------------
245
246 /* we cannot MWM hints and icons before the widget has been realized,
247 so we do this directly after realization */
248
249 static void
250 gtk_frame_realized_callback( GtkWidget * WXUNUSED(widget), wxFrame *win )
251 {
252 if (g_isIdle)
253 wxapp_install_idle_handler();
254
255 if ((win->m_miniEdge > 0) || (win->HasFlag(wxSIMPLE_BORDER)) || (win->HasFlag(wxNO_BORDER)))
256 {
257 /* This is a mini-frame or a borderless frame. */
258 gdk_window_set_decorations( win->m_widget->window, (GdkWMDecoration)0 );
259 gdk_window_set_functions( win->m_widget->window, (GdkWMFunction)0 );
260 }
261 else
262 {
263 /* All this is for Motif Window Manager "hints" and is supposed to be
264 recognized by other WM as well. Not tested. */
265 long decor = (long) GDK_DECOR_BORDER;
266 long func = (long) GDK_FUNC_MOVE;
267
268 if ((win->GetWindowStyle() & wxCAPTION) != 0)
269 decor |= GDK_DECOR_TITLE;
270 if ((win->GetWindowStyle() & wxSYSTEM_MENU) != 0)
271 {
272 decor |= GDK_DECOR_MENU;
273 func |= GDK_FUNC_CLOSE;
274 }
275 if ((win->GetWindowStyle() & wxMINIMIZE_BOX) != 0)
276 {
277 func |= GDK_FUNC_MINIMIZE;
278 decor |= GDK_DECOR_MINIMIZE;
279 }
280 if ((win->GetWindowStyle() & wxMAXIMIZE_BOX) != 0)
281 {
282 func |= GDK_FUNC_MAXIMIZE;
283 decor |= GDK_DECOR_MAXIMIZE;
284 }
285 if ((win->GetWindowStyle() & wxRESIZE_BORDER) != 0)
286 {
287 func |= GDK_FUNC_RESIZE;
288 decor |= GDK_DECOR_RESIZEH;
289 }
290
291 gdk_window_set_decorations( win->m_widget->window, (GdkWMDecoration)decor);
292 gdk_window_set_functions( win->m_widget->window, (GdkWMFunction)func);
293 }
294
295 /* GTK's shrinking/growing policy */
296 if ((win->GetWindowStyle() & wxRESIZE_BORDER) == 0)
297 gtk_window_set_policy(GTK_WINDOW(win->m_widget), 0, 0, 1);
298 else
299 gtk_window_set_policy(GTK_WINDOW(win->m_widget), 1, 1, 1);
300
301 /* reset the icon */
302 wxIcon iconOld = win->GetIcon();
303 if ( iconOld != wxNullIcon )
304 {
305 wxIcon icon( iconOld );
306 win->SetIcon( wxNullIcon );
307 win->SetIcon( icon );
308 }
309
310 /* we set the focus to the child that accepts the focus. this
311 doesn't really have to be done in "realize" but why not? */
312 wxWindowList::Node *node = win->GetChildren().GetFirst();
313 while (node)
314 {
315 wxWindow *child = node->GetData();
316 if (child->AcceptsFocus())
317 {
318 child->SetFocus();
319 break;
320 }
321
322 node = node->GetNext();
323 }
324 }
325
326 //-----------------------------------------------------------------------------
327 // "map_event" from m_widget
328 //-----------------------------------------------------------------------------
329
330 static void
331 gtk_frame_map_callback( GtkWidget * WXUNUSED(widget),
332 GdkEvent * WXUNUSED(event),
333 wxFrame *win )
334 {
335 win->m_isIconized = FALSE;
336 }
337
338 //-----------------------------------------------------------------------------
339 // "unmap_event" from m_widget
340 //-----------------------------------------------------------------------------
341
342 static void
343 gtk_frame_unmap_callback( GtkWidget * WXUNUSED(widget),
344 GdkEvent * WXUNUSED(event),
345 wxFrame *win )
346 {
347 win->m_isIconized = TRUE;
348 }
349
350 //-----------------------------------------------------------------------------
351 // "expose_event" of m_client
352 //-----------------------------------------------------------------------------
353
354 static int gtk_window_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxWindow *win )
355 {
356 GtkPizza *pizza = GTK_PIZZA(widget);
357
358 gtk_paint_flat_box (win->m_widget->style, pizza->bin_window, GTK_STATE_NORMAL,
359 GTK_SHADOW_NONE, &gdk_event->area, win->m_widget, "base", 0, 0, -1, -1);
360
361 return TRUE;
362 }
363
364 //-----------------------------------------------------------------------------
365 // "draw" of m_client
366 //-----------------------------------------------------------------------------
367
368
369 static void gtk_window_draw_callback( GtkWidget *widget, GdkRectangle *rect, wxWindow *win )
370 {
371 GtkPizza *pizza = GTK_PIZZA(widget);
372
373 gtk_paint_flat_box (win->m_widget->style, pizza->bin_window, GTK_STATE_NORMAL,
374 GTK_SHADOW_NONE, rect, win->m_widget, "base", 0, 0, -1, -1);
375 }
376
377 // ----------------------------------------------------------------------------
378 // wxFrame itself
379 // ----------------------------------------------------------------------------
380
381 //-----------------------------------------------------------------------------
382 // InsertChild for wxFrame
383 //-----------------------------------------------------------------------------
384
385 /* Callback for wxFrame. This very strange beast has to be used because
386 * C++ has no virtual methods in a constructor. We have to emulate a
387 * virtual function here as wxWindows requires different ways to insert
388 * a child in container classes. */
389
390 static void wxInsertChildInFrame( wxFrame* parent, wxWindow* child )
391 {
392 wxASSERT( GTK_IS_WIDGET(child->m_widget) );
393
394 if (!parent->m_insertInClientArea)
395 {
396 /* these are outside the client area */
397 wxFrame* frame = (wxFrame*) parent;
398 gtk_pizza_put( GTK_PIZZA(frame->m_mainWidget),
399 GTK_WIDGET(child->m_widget),
400 child->m_x,
401 child->m_y,
402 child->m_width,
403 child->m_height );
404
405 #if wxUSE_TOOLBAR_NATIVE
406 /* we connect to these events for recalculating the client area
407 space when the toolbar is floating */
408 if (wxIS_KIND_OF(child,wxToolBar))
409 {
410 wxToolBar *toolBar = (wxToolBar*) child;
411 if (toolBar->GetWindowStyle() & wxTB_DOCKABLE)
412 {
413 gtk_signal_connect( GTK_OBJECT(toolBar->m_widget), "child_attached",
414 GTK_SIGNAL_FUNC(gtk_toolbar_attached_callback), (gpointer)parent );
415
416 gtk_signal_connect( GTK_OBJECT(toolBar->m_widget), "child_detached",
417 GTK_SIGNAL_FUNC(gtk_toolbar_detached_callback), (gpointer)parent );
418 }
419 }
420 #endif // wxUSE_TOOLBAR
421 }
422 else
423 {
424 /* these are inside the client area */
425 gtk_pizza_put( GTK_PIZZA(parent->m_wxwindow),
426 GTK_WIDGET(child->m_widget),
427 child->m_x,
428 child->m_y,
429 child->m_width,
430 child->m_height );
431 }
432
433 /* resize on OnInternalIdle */
434 parent->GtkUpdateSize();
435 }
436
437 // ----------------------------------------------------------------------------
438 // wxFrame creation
439 // ----------------------------------------------------------------------------
440
441 void wxFrame::Init()
442 {
443 m_sizeSet = FALSE;
444 m_miniEdge = 0;
445 m_miniTitle = 0;
446 m_mainWidget = (GtkWidget*) NULL;
447 m_menuBarDetached = FALSE;
448 m_toolBarDetached = FALSE;
449 m_insertInClientArea = TRUE;
450 m_isIconized = FALSE;
451 m_fsIsShowing = FALSE;
452 m_themeEnabled = TRUE;
453 }
454
455 bool wxFrame::Create( wxWindow *parent,
456 wxWindowID id,
457 const wxString &title,
458 const wxPoint &pos,
459 const wxSize &size,
460 long style,
461 const wxString &name )
462 {
463 wxTopLevelWindows.Append( this );
464
465 m_needParent = FALSE;
466
467 if (!PreCreation( parent, pos, size ) ||
468 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
469 {
470 wxFAIL_MSG( wxT("wxFrame creation failed") );
471 return FALSE;
472 }
473
474 m_title = title;
475
476 m_insertCallback = (wxInsertChildFunction) wxInsertChildInFrame;
477
478 GtkWindowType win_type = GTK_WINDOW_TOPLEVEL;
479
480 if (style & wxFRAME_TOOL_WINDOW)
481 win_type = GTK_WINDOW_POPUP;
482
483 m_widget = gtk_window_new( win_type );
484
485 if ((m_parent) && (HasFlag(wxFRAME_FLOAT_ON_PARENT)) && (GTK_IS_WINDOW(m_parent->m_widget)))
486 gtk_window_set_transient_for( GTK_WINDOW(m_widget), GTK_WINDOW(m_parent->m_widget) );
487
488 if (!name.IsEmpty())
489 gtk_window_set_wmclass( GTK_WINDOW(m_widget), name.mb_str(), name.mb_str() );
490
491 #ifdef __WXDEBUG__
492 debug_focus_in( m_widget, wxT("wxFrame::m_widget"), name );
493 #endif
494
495 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
496 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
497
498 gtk_signal_connect( GTK_OBJECT(m_widget), "delete_event",
499 GTK_SIGNAL_FUNC(gtk_frame_delete_callback), (gpointer)this );
500
501 /* m_mainWidget holds the toolbar, the menubar and the client area */
502 m_mainWidget = gtk_pizza_new();
503 gtk_widget_show( m_mainWidget );
504 GTK_WIDGET_UNSET_FLAGS( m_mainWidget, GTK_CAN_FOCUS );
505 gtk_container_add( GTK_CONTAINER(m_widget), m_mainWidget );
506
507 /* for m_mainWidget themes */
508 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "expose_event",
509 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
510 gtk_signal_connect( GTK_OBJECT(m_mainWidget), "draw",
511 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
512
513 #ifdef __WXDEBUG__
514 debug_focus_in( m_mainWidget, wxT("wxFrame::m_mainWidget"), name );
515 #endif
516
517 /* m_wxwindow only represents the client area without toolbar and menubar */
518 m_wxwindow = gtk_pizza_new();
519 gtk_widget_show( m_wxwindow );
520 gtk_container_add( GTK_CONTAINER(m_mainWidget), m_wxwindow );
521
522 #ifdef __WXDEBUG__
523 debug_focus_in( m_wxwindow, wxT("wxFrame::m_wxwindow"), name );
524 #endif
525
526 /* we donm't allow the frame to get the focus as otherwise
527 the frame will grabit at arbitrary fcous changes. */
528 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
529
530 if (m_parent) m_parent->AddChild( this );
531
532 /* the user resized the frame by dragging etc. */
533 gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
534 GTK_SIGNAL_FUNC(gtk_frame_size_callback), (gpointer)this );
535
536 PostCreation();
537
538 if ((m_x != -1) || (m_y != -1))
539 gtk_widget_set_uposition( m_widget, m_x, m_y );
540 gtk_widget_set_usize( m_widget, m_width, m_height );
541
542 /* we cannot set MWM hints and icons before the widget has
543 been realized, so we do this directly after realization */
544 gtk_signal_connect( GTK_OBJECT(m_widget), "realize",
545 GTK_SIGNAL_FUNC(gtk_frame_realized_callback), (gpointer) this );
546
547 /* the only way to get the window size is to connect to this event */
548 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
549 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
550
551 /* map and unmap for iconized state */
552 gtk_signal_connect( GTK_OBJECT(m_widget), "map_event",
553 GTK_SIGNAL_FUNC(gtk_frame_map_callback), (gpointer)this );
554 gtk_signal_connect( GTK_OBJECT(m_widget), "unmap_event",
555 GTK_SIGNAL_FUNC(gtk_frame_unmap_callback), (gpointer)this );
556
557 /* the only way to get the window size is to connect to this event */
558 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
559 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
560
561 /* disable native tab traversal */
562 gtk_signal_connect( GTK_OBJECT(m_widget), "focus",
563 GTK_SIGNAL_FUNC(gtk_frame_focus_callback), (gpointer)this );
564
565 return TRUE;
566 }
567
568 wxFrame::~wxFrame()
569 {
570 m_isBeingDeleted = TRUE;
571
572 DeleteAllBars();
573
574 wxTopLevelWindows.DeleteObject( this );
575
576 if (wxTheApp->GetTopWindow() == this)
577 wxTheApp->SetTopWindow( (wxWindow*) NULL );
578
579 if ((wxTopLevelWindows.Number() == 0) &&
580 (wxTheApp->GetExitOnFrameDelete()))
581 {
582 wxTheApp->ExitMainLoop();
583 }
584 }
585
586 bool wxFrame::ShowFullScreen(bool show, long style )
587 {
588 if (show == m_fsIsShowing) return FALSE; // return what?
589
590 m_fsIsShowing = show;
591
592 if (show)
593 {
594 m_fsSaveStyle = m_windowStyle;
595 m_fsSaveFlag = style;
596 GetPosition( &m_fsSaveFrame.x, &m_fsSaveFrame.y );
597 GetSize( &m_fsSaveFrame.width, &m_fsSaveFrame.height );
598
599 gtk_widget_hide( m_widget );
600 gtk_widget_unrealize( m_widget );
601
602 m_windowStyle = wxSIMPLE_BORDER;
603
604 int x;
605 int y;
606 wxDisplaySize( &x, &y );
607 SetSize( 0, 0, x, y );
608
609 gtk_widget_realize( m_widget );
610 gtk_widget_show( m_widget );
611 }
612 else
613 {
614 gtk_widget_hide( m_widget );
615 gtk_widget_unrealize( m_widget );
616
617 m_windowStyle = m_fsSaveStyle;
618
619 SetSize( m_fsSaveFrame.x, m_fsSaveFrame.y, m_fsSaveFrame.width, m_fsSaveFrame.height );
620
621 gtk_widget_realize( m_widget );
622 gtk_widget_show( m_widget );
623 }
624
625 return TRUE;
626 }
627
628 // ----------------------------------------------------------------------------
629 // overridden wxWindow methods
630 // ----------------------------------------------------------------------------
631
632 bool wxFrame::Show( bool show )
633 {
634 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
635
636 if (show && !m_sizeSet)
637 {
638 /* by calling GtkOnSize here, we don't have to call
639 either after showing the frame, which would entail
640 much ugly flicker or from within the size_allocate
641 handler, because GTK 1.1.X forbids that. */
642
643 GtkOnSize( m_x, m_y, m_width, m_height );
644 }
645
646 return wxWindow::Show( show );
647 }
648
649 void wxFrame::DoMoveWindow(int WXUNUSED(x), int WXUNUSED(y), int WXUNUSED(width), int WXUNUSED(height) )
650 {
651 wxFAIL_MSG( wxT("DoMoveWindow called for wxFrame") );
652 }
653
654 void wxFrame::DoSetSize( int x, int y, int width, int height, int sizeFlags )
655 {
656 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
657
658 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
659 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
660
661 /* avoid recursions */
662 if (m_resizing)
663 return;
664 m_resizing = TRUE;
665
666 int old_x = m_x;
667 int old_y = m_y;
668
669 int old_width = m_width;
670 int old_height = m_height;
671
672 if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
673 {
674 if (x != -1) m_x = x;
675 if (y != -1) m_y = y;
676 if (width != -1) m_width = width;
677 if (height != -1) m_height = height;
678 }
679 else
680 {
681 m_x = x;
682 m_y = y;
683 m_width = width;
684 m_height = height;
685 }
686
687 /*
688 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
689 {
690 if (width == -1) m_width = 80;
691 }
692
693 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
694 {
695 if (height == -1) m_height = 26;
696 }
697 */
698
699 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
700 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
701 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
702 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
703
704 if ((m_x != -1) || (m_y != -1))
705 {
706 if ((m_x != old_x) || (m_y != old_y))
707 {
708 gtk_widget_set_uposition( m_widget, m_x, m_y );
709 }
710 }
711
712 if ((m_width != old_width) || (m_height != old_height))
713 {
714 gtk_widget_set_usize( m_widget, m_width, m_height );
715
716 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
717 done either directly before the frame is shown or in idle time
718 so that different calls to SetSize() don't lead to flicker. */
719 m_sizeSet = FALSE;
720 }
721
722 m_resizing = FALSE;
723 }
724
725 void wxFrame::DoGetClientSize( int *width, int *height ) const
726 {
727 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
728
729 wxWindow::DoGetClientSize( width, height );
730 if (height)
731 {
732 /* menu bar */
733 if (m_frameMenuBar)
734 {
735 if (!m_menuBarDetached)
736 (*height) -= wxMENU_HEIGHT;
737 else
738 (*height) -= wxPLACE_HOLDER;
739 }
740
741 #if wxUSE_STATUSBAR
742 /* status bar */
743 if (m_frameStatusBar && m_frameStatusBar->IsShown()) (*height) -= wxSTATUS_HEIGHT;
744 #endif // wxUSE_STATUSBAR
745
746 #if wxUSE_TOOLBAR
747 /* tool bar */
748 if (m_frameToolBar && m_frameToolBar->IsShown())
749 {
750 if (m_toolBarDetached)
751 {
752 *height -= wxPLACE_HOLDER;
753 }
754 else
755 {
756 int x, y;
757 m_frameToolBar->GetSize( &x, &y );
758 if ( m_frameToolBar->GetWindowStyle() & wxTB_VERTICAL )
759 {
760 *width -= x;
761 }
762 else
763 {
764 *height -= y;
765 }
766 }
767 }
768 #endif // wxUSE_TOOLBAR
769
770 /* mini edge */
771 *height -= m_miniEdge*2 + m_miniTitle;
772 }
773 if (width)
774 {
775 *width -= m_miniEdge*2;
776 }
777 }
778
779 void wxFrame::DoSetClientSize( int width, int height )
780 {
781 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
782
783 /* menu bar */
784 if (m_frameMenuBar)
785 {
786 if (!m_menuBarDetached)
787 height += wxMENU_HEIGHT;
788 else
789 height += wxPLACE_HOLDER;
790 }
791
792 #if wxUSE_STATUSBAR
793 /* status bar */
794 if (m_frameStatusBar && m_frameStatusBar->IsShown()) height += wxSTATUS_HEIGHT;
795 #endif
796
797 #if wxUSE_TOOLBAR
798 /* tool bar */
799 if (m_frameToolBar && m_frameToolBar->IsShown())
800 {
801 if (m_toolBarDetached)
802 {
803 height += wxPLACE_HOLDER;
804 }
805 else
806 {
807 int x, y;
808 m_frameToolBar->GetSize( &x, &y );
809 if ( m_frameToolBar->GetWindowStyle() & wxTB_VERTICAL )
810 {
811 width += x;
812 }
813 else
814 {
815 height += y;
816 }
817 }
818 }
819 #endif
820
821 DoSetSize( -1, -1, width + m_miniEdge*2, height + m_miniEdge*2 + m_miniTitle, 0 );
822 }
823
824 void wxFrame::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y),
825 int width, int height )
826 {
827 // due to a bug in gtk, x,y are always 0
828 // m_x = x;
829 // m_y = y;
830
831 /* avoid recursions */
832 if (m_resizing) return;
833 m_resizing = TRUE;
834
835 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
836 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
837
838 m_width = width;
839 m_height = height;
840
841 /* space occupied by m_frameToolBar and m_frameMenuBar */
842 int client_area_x_offset = 0,
843 client_area_y_offset = 0;
844
845 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
846 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
847 set in wxFrame::Create so it is used to check what kind of frame we
848 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
849 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
850 importantly) m_mainWidget */
851
852 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
853 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
854 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
855 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
856
857 if (m_mainWidget)
858 {
859 /* set size hints */
860 gint flag = 0; // GDK_HINT_POS;
861 if ((m_minWidth != -1) || (m_minHeight != -1)) flag |= GDK_HINT_MIN_SIZE;
862 if ((m_maxWidth != -1) || (m_maxHeight != -1)) flag |= GDK_HINT_MAX_SIZE;
863 GdkGeometry geom;
864 geom.min_width = m_minWidth;
865 geom.min_height = m_minHeight;
866 geom.max_width = m_maxWidth;
867 geom.max_height = m_maxHeight;
868 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget),
869 (GtkWidget*) NULL,
870 &geom,
871 (GdkWindowHints) flag );
872
873 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
874 * menubar, the toolbar and the client area, which is represented by
875 * m_wxwindow.
876 * this hurts in the eye, but I don't want to call SetSize()
877 * because I don't want to call any non-native functions here. */
878
879 if (m_frameMenuBar)
880 {
881 int xx = m_miniEdge;
882 int yy = m_miniEdge + m_miniTitle;
883 int ww = m_width - 2*m_miniEdge;
884 int hh = wxMENU_HEIGHT;
885 if (m_menuBarDetached) hh = wxPLACE_HOLDER;
886 m_frameMenuBar->m_x = xx;
887 m_frameMenuBar->m_y = yy;
888 m_frameMenuBar->m_width = ww;
889 m_frameMenuBar->m_height = hh;
890 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
891 m_frameMenuBar->m_widget,
892 xx, yy, ww, hh );
893 client_area_y_offset += hh;
894 }
895
896 #if wxUSE_TOOLBAR
897 if ((m_frameToolBar) && m_frameToolBar->IsShown() &&
898 (m_frameToolBar->m_widget->parent == m_mainWidget))
899 {
900 int xx = m_miniEdge;
901 int yy = m_miniEdge + m_miniTitle;
902 if (m_frameMenuBar)
903 {
904 if (!m_menuBarDetached)
905 yy += wxMENU_HEIGHT;
906 else
907 yy += wxPLACE_HOLDER;
908 }
909
910 m_frameToolBar->m_x = xx;
911 m_frameToolBar->m_y = yy;
912
913 /* don't change the toolbar's reported height/width */
914 int ww, hh;
915 if ( m_frameToolBar->GetWindowStyle() & wxTB_VERTICAL )
916 {
917 ww = m_toolBarDetached ? wxPLACE_HOLDER
918 : m_frameToolBar->m_width;
919 hh = m_height - 2*m_miniEdge;
920
921 client_area_x_offset += ww;
922 }
923 else
924 {
925 ww = m_width - 2*m_miniEdge;
926 hh = m_toolBarDetached ? wxPLACE_HOLDER
927 : m_frameToolBar->m_height;
928
929 client_area_y_offset += hh;
930 }
931
932 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
933 m_frameToolBar->m_widget,
934 xx, yy, ww, hh );
935 }
936 #endif // wxUSE_TOOLBAR
937
938 int client_x = client_area_x_offset + m_miniEdge;
939 int client_y = client_area_y_offset + m_miniEdge + m_miniTitle;
940 int client_w = m_width - client_area_x_offset - 2*m_miniEdge;
941 int client_h = m_height - client_area_y_offset- 2*m_miniEdge - m_miniTitle;
942 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
943 m_wxwindow,
944 client_x, client_y, client_w, client_h );
945 }
946 else
947 {
948 /* if there is no m_mainWidget between m_widget and m_wxwindow there
949 is no need to set the size or position of m_wxwindow. */
950 }
951
952 #if wxUSE_STATUSBAR
953 if (m_frameStatusBar && m_frameStatusBar->IsShown())
954 {
955 int xx = 0 + m_miniEdge;
956 int yy = m_height - wxSTATUS_HEIGHT - m_miniEdge - client_area_y_offset;
957 int ww = m_width - 2*m_miniEdge;
958 int hh = wxSTATUS_HEIGHT;
959 m_frameStatusBar->m_x = xx;
960 m_frameStatusBar->m_y = yy;
961 m_frameStatusBar->m_width = ww;
962 m_frameStatusBar->m_height = hh;
963 gtk_pizza_set_size( GTK_PIZZA(m_wxwindow),
964 m_frameStatusBar->m_widget,
965 xx, yy, ww, hh );
966 gtk_widget_draw( m_frameStatusBar->m_widget, (GdkRectangle*) NULL );
967 }
968 #endif
969
970 m_sizeSet = TRUE;
971
972 // send size event to frame
973 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
974 event.SetEventObject( this );
975 GetEventHandler()->ProcessEvent( event );
976
977 // send size event to status bar
978 if (m_frameStatusBar)
979 {
980 wxSizeEvent event2( wxSize(m_frameStatusBar->m_width,m_frameStatusBar->m_height), m_frameStatusBar->GetId() );
981 event2.SetEventObject( m_frameStatusBar );
982 m_frameStatusBar->GetEventHandler()->ProcessEvent( event2 );
983 }
984
985 m_resizing = FALSE;
986 }
987
988 void wxFrame::MakeModal( bool modal )
989 {
990 if (modal)
991 gtk_grab_add( m_widget );
992 else
993 gtk_grab_remove( m_widget );
994 }
995
996 void wxFrame::OnInternalIdle()
997 {
998 if (!m_sizeSet && GTK_WIDGET_REALIZED(m_wxwindow))
999 {
1000 GtkOnSize( m_x, m_y, m_width, m_height );
1001
1002 // we'll come back later
1003 if (g_isIdle)
1004 wxapp_install_idle_handler();
1005 return;
1006 }
1007
1008 if (m_frameMenuBar) m_frameMenuBar->OnInternalIdle();
1009 #if wxUSE_TOOLBAR
1010 if (m_frameToolBar) m_frameToolBar->OnInternalIdle();
1011 #endif
1012 #if wxUSE_STATUSBAR
1013 if (m_frameStatusBar) m_frameStatusBar->OnInternalIdle();
1014 #endif
1015
1016 wxWindow::OnInternalIdle();
1017 }
1018
1019 // ----------------------------------------------------------------------------
1020 // menu/tool/status bar stuff
1021 // ----------------------------------------------------------------------------
1022
1023 void wxFrame::SetMenuBar( wxMenuBar *menuBar )
1024 {
1025 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
1026 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
1027
1028 if (menuBar == m_frameMenuBar)
1029 return;
1030
1031 if (m_frameMenuBar)
1032 {
1033 m_frameMenuBar->UnsetInvokingWindow( this );
1034
1035 if (m_frameMenuBar->GetWindowStyle() & wxMB_DOCKABLE)
1036 {
1037 gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar->m_widget),
1038 GTK_SIGNAL_FUNC(gtk_menu_attached_callback), (gpointer)this );
1039
1040 gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar->m_widget),
1041 GTK_SIGNAL_FUNC(gtk_menu_detached_callback), (gpointer)this );
1042 }
1043
1044 gtk_container_remove( GTK_CONTAINER(m_mainWidget), m_frameMenuBar->m_widget );
1045 gtk_widget_ref( m_frameMenuBar->m_widget );
1046 gtk_widget_unparent( m_frameMenuBar->m_widget );
1047 }
1048
1049 m_frameMenuBar = menuBar;
1050
1051 if (m_frameMenuBar)
1052 {
1053 m_frameMenuBar->SetInvokingWindow( this );
1054
1055 m_frameMenuBar->SetParent(this);
1056 gtk_pizza_put( GTK_PIZZA(m_mainWidget),
1057 m_frameMenuBar->m_widget,
1058 m_frameMenuBar->m_x,
1059 m_frameMenuBar->m_y,
1060 m_frameMenuBar->m_width,
1061 m_frameMenuBar->m_height );
1062
1063 if (menuBar->GetWindowStyle() & wxMB_DOCKABLE)
1064 {
1065 gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_attached",
1066 GTK_SIGNAL_FUNC(gtk_menu_attached_callback), (gpointer)this );
1067
1068 gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_detached",
1069 GTK_SIGNAL_FUNC(gtk_menu_detached_callback), (gpointer)this );
1070 }
1071
1072 m_frameMenuBar->Show( TRUE );
1073 }
1074
1075 /* resize window in OnInternalIdle */
1076 m_sizeSet = FALSE;
1077 }
1078
1079 #if wxUSE_TOOLBAR
1080 wxToolBar* wxFrame::CreateToolBar( long style, wxWindowID id, const wxString& name )
1081 {
1082 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
1083
1084 m_insertInClientArea = FALSE;
1085
1086 m_frameToolBar = wxFrameBase::CreateToolBar( style, id, name );
1087
1088 m_insertInClientArea = TRUE;
1089
1090 m_sizeSet = FALSE;
1091
1092 return m_frameToolBar;
1093 }
1094
1095 void wxFrame::SetToolBar(wxToolBar *toolbar)
1096 {
1097 wxFrameBase::SetToolBar(toolbar);
1098
1099 if (m_frameToolBar)
1100 {
1101 /* insert into toolbar area if not already there */
1102 if ((m_frameToolBar->m_widget->parent) &&
1103 (m_frameToolBar->m_widget->parent != m_mainWidget))
1104 {
1105 GetChildren().DeleteObject( m_frameToolBar );
1106
1107 gtk_widget_reparent( m_frameToolBar->m_widget, m_mainWidget );
1108 GtkUpdateSize();
1109 }
1110 }
1111 }
1112
1113 #endif // wxUSE_TOOLBAR
1114
1115 #if wxUSE_STATUSBAR
1116
1117 wxStatusBar* wxFrame::CreateStatusBar(int number,
1118 long style,
1119 wxWindowID id,
1120 const wxString& name)
1121 {
1122 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
1123
1124 // because it will change when toolbar is added
1125 m_sizeSet = FALSE;
1126
1127 return wxFrameBase::CreateStatusBar( number, style, id, name );
1128 }
1129
1130 void wxFrame::PositionStatusBar()
1131 {
1132 if ( !m_frameStatusBar )
1133 return;
1134
1135 m_sizeSet = FALSE;
1136 }
1137 #endif // wxUSE_STATUSBAR
1138
1139 // ----------------------------------------------------------------------------
1140 // frame title/icon
1141 // ----------------------------------------------------------------------------
1142
1143 void wxFrame::SetTitle( const wxString &title )
1144 {
1145 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
1146
1147 m_title = title;
1148 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
1149 }
1150
1151 void wxFrame::SetIcon( const wxIcon &icon )
1152 {
1153 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
1154
1155 wxFrameBase::SetIcon(icon);
1156
1157 if ( !m_icon.Ok() )
1158 return;
1159
1160 if (!m_widget->window)
1161 return;
1162
1163 wxMask *mask = icon.GetMask();
1164 GdkBitmap *bm = (GdkBitmap *) NULL;
1165 if (mask) bm = mask->GetBitmap();
1166
1167 gdk_window_set_icon( m_widget->window, (GdkWindow *) NULL, icon.GetPixmap(), bm );
1168 }
1169
1170 // ----------------------------------------------------------------------------
1171 // frame state: maximized/iconized/normal
1172 // ----------------------------------------------------------------------------
1173
1174 void wxFrame::Maximize(bool WXUNUSED(maximize))
1175 {
1176 wxFAIL_MSG( _T("not implemented") );
1177 }
1178
1179 bool wxFrame::IsMaximized() const
1180 {
1181 // wxFAIL_MSG( _T("not implemented") );
1182
1183 // This is an approximation
1184 return FALSE;
1185 }
1186
1187 void wxFrame::Restore()
1188 {
1189 wxFAIL_MSG( _T("not implemented") );
1190 }
1191
1192 void wxFrame::Iconize( bool iconize )
1193 {
1194 if (iconize)
1195 {
1196 XIconifyWindow( GDK_WINDOW_XDISPLAY( m_widget->window ),
1197 GDK_WINDOW_XWINDOW( m_widget->window ),
1198 DefaultScreen( GDK_DISPLAY() ) );
1199 }
1200 }
1201
1202 bool wxFrame::IsIconized() const
1203 {
1204 return m_isIconized;
1205 }