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