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