]> git.saurik.com Git - wxWidgets.git/blame - src/motif/frame.cpp
wxWindow::Fit() infinite loop bug fixed
[wxWidgets.git] / src / motif / frame.cpp
CommitLineData
4bb6408c
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: frame.cpp
3// Purpose: wxFrame
4// Author: Julian Smart
5// Modified by:
6// Created: 17/09/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "frame.h"
14#endif
15
16#include "wx/frame.h"
17#include "wx/statusbr.h"
18#include "wx/toolbar.h"
19#include "wx/menuitem.h"
20#include "wx/menu.h"
21#include "wx/dcclient.h"
22#include "wx/dialog.h"
23#include "wx/settings.h"
24#include "wx/app.h"
25#include "wx/utils.h"
26
27#if defined(__ultrix) || defined(__sgi)
28#include <Xm/Frame.h>
29#endif
30
31#include <Xm/Xm.h>
32#include <X11/Shell.h>
33#if XmVersion >= 1002
34#include <Xm/XmAll.h>
35#else
36#include <Xm/Frame.h>
37#endif
38#include <Xm/MwmUtil.h>
39#include <Xm/BulletinB.h>
40#include <Xm/Form.h>
41#include <Xm/MainW.h>
42#include <Xm/RowColumn.h>
43#include <Xm/Label.h>
44#include <Xm/AtomMgr.h>
45#include <Xm/LabelG.h>
46#include <Xm/Frame.h>
47#if XmVersion > 1000
48#include <Xm/Protocols.h>
49#endif
50
51#include "wx/motif/private.h"
52
53void wxCloseFrameCallback(Widget, XtPointer, XmAnyCallbackStruct *cbs);
8704bf74 54void wxFrameFocusProc(Widget workArea, XtPointer clientData,
4bb6408c
JS
55 XmAnyCallbackStruct *cbs);
56static void wxFrameMapProc(Widget frameShell, XtPointer clientData,
2d120f83 57 XCrossingEvent * event);
4bb6408c
JS
58
59extern wxList wxModelessWindows;
60extern wxList wxPendingDelete;
61
62// TODO: this should be tidied so that any frame can be the
63// top frame
64static bool wxTopLevelUsed = FALSE;
65
66#if !USE_SHARED_LIBRARY
67BEGIN_EVENT_TABLE(wxFrame, wxWindow)
2d120f83
JS
68EVT_SIZE(wxFrame::OnSize)
69EVT_ACTIVATE(wxFrame::OnActivate)
70EVT_MENU_HIGHLIGHT_ALL(wxFrame::OnMenuHighlight)
71EVT_SYS_COLOUR_CHANGED(wxFrame::OnSysColourChanged)
72EVT_IDLE(wxFrame::OnIdle)
73EVT_CLOSE(wxFrame::OnCloseWindow)
4bb6408c
JS
74END_EVENT_TABLE()
75
76IMPLEMENT_DYNAMIC_CLASS(wxFrame, wxWindow)
77#endif
78
47d67540 79#if wxUSE_NATIVE_STATUSBAR
4bb6408c
JS
80bool wxFrame::m_useNativeStatusBar = TRUE;
81#else
82bool wxFrame::m_useNativeStatusBar = FALSE;
83#endif
84
85wxFrame::wxFrame()
86{
1ccbb61a 87#if wxUSE_TOOLBAR
4bb6408c 88 m_frameToolBar = NULL ;
1ccbb61a
VZ
89#endif // wxUSE_TOOLBAR
90
4bb6408c
JS
91 m_frameMenuBar = NULL;
92 m_frameStatusBar = NULL;
2d120f83 93
4bb6408c
JS
94 m_windowParent = NULL;
95 m_iconized = FALSE;
2d120f83 96
4bb6408c
JS
97 //// Motif-specific
98 m_frameShell = (WXWidget) NULL;
99 m_frameWidget = (WXWidget) NULL;;
100 m_workArea = (WXWidget) NULL;;
101 m_clientArea = (WXWidget) NULL;;
102 m_visibleStatus = TRUE;
103 m_title = "";
104}
105
106bool wxFrame::Create(wxWindow *parent,
2d120f83
JS
107 wxWindowID id,
108 const wxString& title,
109 const wxPoint& pos,
110 const wxSize& size,
111 long style,
112 const wxString& name)
4bb6408c 113{
2d120f83
JS
114 if (!parent)
115 wxTopLevelWindows.Append(this);
116
117 SetName(name);
118
119 m_windowStyle = style;
120 m_frameMenuBar = NULL;
1ccbb61a 121#if wxUSE_TOOLBAR
2d120f83 122 m_frameToolBar = NULL ;
1ccbb61a 123#endif // wxUSE_TOOLBAR
2d120f83
JS
124 m_frameStatusBar = NULL;
125
126 //// Motif-specific
127 m_frameShell = (WXWidget) NULL;
128 m_frameWidget = (WXWidget) NULL;;
129 m_workArea = (WXWidget) NULL;;
130 m_clientArea = (WXWidget) NULL;;
131 m_visibleStatus = TRUE;
132 m_title = "";
133
134 m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE);
135 m_foregroundColour = *wxBLACK;
136 m_windowFont = wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT);
137
138 if ( id > -1 )
139 m_windowId = id;
140 else
141 m_windowId = (int)NewControlId();
142
143 if (parent) parent->AddChild(this);
144
145 wxModelessWindows.Append(this);
146
147 int x = pos.x; int y = pos.y;
148 int width = size.x; int height = size.y;
149
150 if (wxTopLevelUsed)
151 // Change suggested by Matthew Flatt
152 m_frameShell = (WXWidget) XtAppCreateShell(name, wxTheApp->GetClassName(), topLevelShellWidgetClass, (Display*) wxGetDisplay(), NULL, 0);
153 else
154 {
155 m_frameShell = wxTheApp->GetTopLevelWidget();
156 wxTopLevelUsed = TRUE;
157 }
158
4bb6408c 159 XtVaSetValues((Widget) m_frameShell,
2d120f83
JS
160 // Allows menu to resize
161 XmNallowShellResize, True,
162 XmNdeleteResponse, XmDO_NOTHING,
163 XmNmappedWhenManaged, False,
164 XmNiconic, (style & wxICONIZE) ? TRUE : FALSE,
165 NULL);
166
167 if (!title.IsNull())
168 XtVaSetValues((Widget) m_frameShell,
169 XmNtitle, (const char*) title,
170 NULL);
171
172 m_frameWidget = (WXWidget) XtVaCreateManagedWidget("main_window",
173 xmMainWindowWidgetClass, (Widget) m_frameShell,
174 XmNresizePolicy, XmRESIZE_NONE,
175 NULL);
176
177 m_workArea = (WXWidget) XtVaCreateWidget("form",
178 xmFormWidgetClass, (Widget) m_frameWidget,
179 XmNresizePolicy, XmRESIZE_NONE,
180 NULL);
181
182 m_clientArea = (WXWidget) XtVaCreateWidget("client",
183 xmBulletinBoardWidgetClass, (Widget) m_workArea,
184 XmNmarginWidth, 0,
185 XmNmarginHeight, 0,
186 XmNrightAttachment, XmATTACH_FORM,
187 XmNleftAttachment, XmATTACH_FORM,
188 XmNtopAttachment, XmATTACH_FORM,
189 XmNbottomAttachment, XmATTACH_FORM,
190 // XmNresizePolicy, XmRESIZE_ANY,
191 NULL);
0492c5a0 192
2e35f56f
JS
193 XtAddEventHandler((Widget) m_clientArea, ExposureMask,FALSE,
194 wxUniversalRepaintProc, (XtPointer) this);
195
2d120f83
JS
196 XtVaSetValues((Widget) m_frameWidget,
197 XmNworkWindow, (Widget) m_workArea,
198 NULL);
199
2d120f83
JS
200 XtManageChild((Widget) m_clientArea);
201 XtManageChild((Widget) m_workArea);
202
203 wxASSERT_MSG ((wxWidgetHashTable->Get((long)m_workArea) == (wxObject*) NULL), "Widget table clash in frame.cpp") ;
204
205 wxAddWindowToTable((Widget) m_workArea, this);
206
207 XtTranslations ptr ;
208
209 XtOverrideTranslations((Widget) m_workArea,
210 ptr = XtParseTranslationTable("<Configure>: resize()"));
211
212 XtFree((char *)ptr);
213
214 XtAddCallback((Widget) m_workArea, XmNfocusCallback,
215 (XtCallbackProc)wxFrameFocusProc, (XtPointer)this);
216
217 /* Part of show-&-hide fix */
218 XtAddEventHandler((Widget) m_frameShell, StructureNotifyMask,
219 False, (XtEventHandler)wxFrameMapProc,
220 (XtPointer)m_workArea);
221
222 if (x > -1)
223 XtVaSetValues((Widget) m_frameShell, XmNx, x, NULL);
224 if (y > -1)
225 XtVaSetValues((Widget) m_frameShell, XmNy, y, NULL);
226 if (width > -1)
227 XtVaSetValues((Widget) m_frameShell, XmNwidth, width, NULL);
228 if (height > -1)
229 XtVaSetValues((Widget) m_frameShell, XmNheight, height, NULL);
230
231 m_mainWidget = m_frameWidget;
232
233 ChangeFont(FALSE);
234
235 // This patch comes from Torsten Liermann lier@lier1.muc.de
236 if (XmIsMotifWMRunning( (Widget) m_frameShell ))
237 {
238 int decor = 0 ;
239 if (style & wxRESIZE_BORDER)
240 decor |= MWM_DECOR_RESIZEH ;
241 if (style & wxSYSTEM_MENU)
242 decor |= MWM_DECOR_MENU;
243 if ((style & wxCAPTION) ||
244 (style & wxTINY_CAPTION_HORIZ) ||
245 (style & wxTINY_CAPTION_VERT))
246 decor |= MWM_DECOR_TITLE;
247 if (style & wxTHICK_FRAME)
248 decor |= MWM_DECOR_BORDER;
249 if (style & wxTHICK_FRAME)
250 decor |= MWM_DECOR_BORDER;
251 if (style & wxMINIMIZE_BOX)
252 decor |= MWM_DECOR_MINIMIZE;
253 if (style & wxMAXIMIZE_BOX)
254 decor |= MWM_DECOR_MAXIMIZE;
255 XtVaSetValues((Widget) m_frameShell,XmNmwmDecorations,decor,NULL) ;
256 }
257 // This allows non-Motif window managers to support at least the
258 // no-decorations case.
259 else
260 {
261 if (style == 0)
262 XtVaSetValues((Widget) m_frameShell,XmNoverrideRedirect,TRUE,NULL);
263 }
264 XtRealizeWidget((Widget) m_frameShell);
265
266 // Intercept CLOSE messages from the window manager
267 Atom WM_DELETE_WINDOW = XmInternAtom(XtDisplay((Widget) m_frameShell), "WM_DELETE_WINDOW", False);
4bb6408c 268#if (XmREVISION > 1 || XmVERSION > 1)
2d120f83 269 XmAddWMProtocolCallback((Widget) m_frameShell, WM_DELETE_WINDOW, (XtCallbackProc) wxCloseFrameCallback, (XtPointer)this);
4bb6408c
JS
270#else
271#if XmREVISION == 1
2d120f83 272 XmAddWMProtocolCallback((Widget) m_frameShell, WM_DELETE_WINDOW, (XtCallbackProc) wxCloseFrameCallback, (caddr_t)this);
4bb6408c 273#else
2d120f83 274 XmAddWMProtocolCallback((Widget) m_frameShell, WM_DELETE_WINDOW, (void (*)())wxCloseFrameCallback, (caddr_t)this);
4bb6408c
JS
275#endif
276#endif
2d120f83
JS
277
278 ChangeBackgroundColour();
279
280 PreResize();
281
282 wxSizeEvent sizeEvent(wxSize(width, height), GetId());
283 sizeEvent.SetEventObject(this);
284
285 GetEventHandler()->ProcessEvent(sizeEvent);
286
287 return TRUE;
4bb6408c
JS
288}
289
290wxFrame::~wxFrame()
291{
2e35f56f
JS
292 if (m_clientArea)
293 XtRemoveEventHandler((Widget) m_clientArea, ExposureMask, FALSE,
294 wxUniversalRepaintProc, (XtPointer) this);
295
2d120f83
JS
296 if (GetMainWidget())
297 Show(FALSE);
0492c5a0 298
2d120f83
JS
299 if (m_frameMenuBar)
300 {
301 m_frameMenuBar->DestroyMenuBar();
302
303 // Hack to stop core dump on Ultrix, OSF, for some strange reason.
4bb6408c 304#if MOTIF_MENUBAR_DELETE_FIX
2d120f83 305 GetMenuBar()->SetMainWidget((WXWidget) NULL);
4bb6408c 306#endif
2d120f83
JS
307 delete m_frameMenuBar;
308 m_frameMenuBar = NULL;
309 }
310
311 wxTopLevelWindows.DeleteObject(this);
312 wxModelessWindows.DeleteObject(this);
313
314 if (m_frameStatusBar)
315 delete m_frameStatusBar;
316
317 DestroyChildren();
318
319 /*
320 int i;
321 for (i = 0; i < wxMAX_STATUS; i++)
4bb6408c 322 if (statusTextWidget[i])
2d120f83
JS
323 XtDestroyWidget (statusTextWidget[i]);
324
325 if (statusLineForm)
326 XtDestroyWidget (statusLineForm);
327
328 if (statusLineWidget)
329 XtDestroyWidget (statusLineWidget);
330 */
331
332 if (m_workArea)
4bb6408c 333 {
2d120f83
JS
334 wxDeleteWindowFromTable((Widget) m_workArea);
335
336 XtDestroyWidget ((Widget) m_workArea);
4bb6408c 337 }
2d120f83
JS
338
339 if (m_frameWidget)
340 {
341 wxDeleteWindowFromTable((Widget) m_frameWidget);
342 XtDestroyWidget ((Widget) m_frameWidget);
343 }
344
345 if (m_frameShell)
346 XtDestroyWidget ((Widget) m_frameShell);
347
348 SetMainWidget((WXWidget) NULL);
349
350 /* Check if it's the last top-level window */
351
352 if (wxTheApp && (wxTopLevelWindows.Number() == 0))
353 {
354 wxTheApp->SetTopWindow(NULL);
355
356 if (wxTheApp->GetExitOnFrameDelete())
357 {
358 // Signal to the app that we're going to close
359 wxTheApp->ExitMainLoop();
360 }
361 }
362
4bb6408c
JS
363}
364
365// Get size *available for subwindows* i.e. excluding menu bar, toolbar etc.
366void wxFrame::GetClientSize(int *x, int *y) const
367{
2d120f83
JS
368 Dimension xx, yy;
369 XtVaGetValues((Widget) m_workArea, XmNwidth, &xx, XmNheight, &yy, NULL);
370
371 if (m_frameStatusBar)
372 {
373 int sbw, sbh;
374 m_frameStatusBar->GetSize(& sbw, & sbh);
375 yy -= sbh;
376 }
1ccbb61a 377#if wxUSE_TOOLBAR
2d120f83
JS
378 if (m_frameToolBar)
379 {
380 int tbw, tbh;
381 m_frameToolBar->GetSize(& tbw, & tbh);
382 if (m_frameToolBar->GetWindowStyleFlag() & wxTB_VERTICAL)
383 xx -= tbw;
384 else
385 yy -= tbh;
386 }
1ccbb61a 387#endif // wxUSE_TOOLBAR
2d120f83
JS
388 /*
389 if (GetMenuBar() != (wxMenuBar*) NULL)
390 {
4bb6408c
JS
391 // it seems that if a frame holds a panel, the menu bar size
392 // gets automatically taken care of --- grano@cs.helsinki.fi 4.4.95
393 bool hasSubPanel = FALSE;
c0ed460c 394 for(wxNode* node = GetChildren().First(); node; node = node->Next())
4bb6408c 395 {
2d120f83
JS
396 wxWindow *win = (wxWindow *)node->Data();
397 hasSubPanel = (win->IsKindOf(CLASSINFO(wxPanel)) && !win->IsKindOf(CLASSINFO(wxDialog)));
398
4bb6408c 399 if (hasSubPanel)
2d120f83
JS
400 break;
401 }
402 if (! hasSubPanel) {
4bb6408c
JS
403 Dimension ys;
404 XtVaGetValues((Widget) GetMenuBarWidget(), XmNheight, &ys, NULL);
405 yy -= ys;
2d120f83
JS
406 }
407 }
408 */
409
410 *x = xx; *y = yy;
4bb6408c
JS
411}
412
413// Set the client size (i.e. leave the calculation of borders etc.
414// to wxWindows)
bfc6fde4 415void wxFrame::DoSetClientSize(int width, int height)
4bb6408c 416{
2d120f83
JS
417 // Calculate how large the new main window should be
418 // by finding the difference between the client area and the
419 // main window area, and adding on to the new client area
420 if (width > -1)
421 XtVaSetValues((Widget) m_workArea, XmNwidth, width, NULL);
422
423 if (height > -1)
a4294b78 424 {
2d120f83
JS
425 if (m_frameStatusBar)
426 {
427 int sbw, sbh;
428 m_frameStatusBar->GetSize(& sbw, & sbh);
429 height += sbh;
430 }
1ccbb61a 431#if wxUSE_TOOLBAR
2d120f83
JS
432 if (m_frameToolBar)
433 {
434 int tbw, tbh;
435 m_frameToolBar->GetSize(& tbw, & tbh);
436 if (m_frameToolBar->GetWindowStyleFlag() & wxTB_VERTICAL)
437 width += tbw;
438 else
439 height += tbh;
440 }
1ccbb61a 441#endif // wxUSE_TOOLBAR
2d120f83
JS
442
443 XtVaSetValues((Widget) m_workArea, XmNheight, height, NULL);
a4294b78 444 }
2d120f83
JS
445 PreResize();
446
447 wxSizeEvent sizeEvent(wxSize(width, height), GetId());
448 sizeEvent.SetEventObject(this);
449
450 GetEventHandler()->ProcessEvent(sizeEvent);
451
4bb6408c
JS
452}
453
454void wxFrame::GetSize(int *width, int *height) const
455{
2d120f83
JS
456 Dimension xx, yy;
457 XtVaGetValues((Widget) m_frameShell, XmNwidth, &xx, XmNheight, &yy, NULL);
458 *width = xx; *height = yy;
4bb6408c
JS
459}
460
461void wxFrame::GetPosition(int *x, int *y) const
462{
463 Window parent_window = XtWindow((Widget) m_frameShell),
2d120f83
JS
464 next_parent = XtWindow((Widget) m_frameShell),
465 root = RootWindowOfScreen(XtScreen((Widget) m_frameShell));
466
4bb6408c
JS
467 // search for the parent that is child of ROOT, because the WM may
468 // reparent twice and notify only the next parent (like FVWM)
469 while (next_parent != root) {
2d120f83
JS
470 Window *theChildren; unsigned int n;
471 parent_window = next_parent;
472 XQueryTree(XtDisplay((Widget) m_frameShell), parent_window, &root,
473 &next_parent, &theChildren, &n);
474 XFree(theChildren); // not needed
4bb6408c
JS
475 }
476 int xx, yy; unsigned int dummy;
477 XGetGeometry(XtDisplay((Widget) m_frameShell), parent_window, &root,
2d120f83 478 &xx, &yy, &dummy, &dummy, &dummy, &dummy);
4bb6408c
JS
479 if (x) *x = xx;
480 if (y) *y = yy;
481}
482
bfc6fde4 483void wxFrame::DoSetSize(int x, int y, int width, int height, int sizeFlags)
4bb6408c 484{
2d120f83
JS
485 if (x > -1)
486 XtVaSetValues((Widget) m_frameShell, XmNx, x, NULL);
487 if (y > -1)
488 XtVaSetValues((Widget) m_frameShell, XmNy, y, NULL);
489 if (width > -1)
490 XtVaSetValues((Widget) m_frameWidget, XmNwidth, width, NULL);
491 if (height > -1)
492 XtVaSetValues((Widget) m_frameWidget, XmNheight, height, NULL);
493
494 if (!(height == -1 && width == -1))
495 {
496 PreResize();
497
498 wxSizeEvent sizeEvent(wxSize(width, height), GetId());
499 sizeEvent.SetEventObject(this);
500
501 GetEventHandler()->ProcessEvent(sizeEvent);
502 }
4bb6408c
JS
503}
504
505bool wxFrame::Show(bool show)
506{
2d120f83
JS
507 if (!m_frameShell)
508 return wxWindow::Show(show);
509
510 m_visibleStatus = show; /* show-&-hide fix */
511
512 m_isShown = show;
513 if (show) {
514 XtMapWidget((Widget) m_frameShell);
515 XRaiseWindow(XtDisplay((Widget) m_frameShell), XtWindow((Widget) m_frameShell));
516 } else {
517 XtUnmapWidget((Widget) m_frameShell);
518 // XmUpdateDisplay(wxTheApp->topLevel); // Experimental: may be responsible for crashes
519 }
520 return TRUE;
4bb6408c
JS
521}
522
523void wxFrame::Iconize(bool iconize)
524{
2d120f83
JS
525 if (!iconize)
526 Show(TRUE);
527
528 if (m_frameShell)
529 XtVaSetValues((Widget) m_frameShell, XmNiconic, (Boolean)iconize, NULL);
4bb6408c
JS
530}
531
532// Equivalent to maximize/restore in Windows
533void wxFrame::Maximize(bool maximize)
534{
2d120f83
JS
535 Show(TRUE);
536
537 if (maximize && m_frameShell)
538 XtVaSetValues((Widget) m_frameShell, XmNiconic, FALSE, NULL);
4bb6408c
JS
539}
540
541bool wxFrame::IsIconized() const
542{
2d120f83
JS
543 if (!m_frameShell)
544 return FALSE;
545
546 Boolean iconic;
547 XtVaGetValues((Widget) m_frameShell, XmNiconic, &iconic, NULL);
548 return iconic;
4bb6408c
JS
549}
550
6f63ec3f
JS
551// Is it maximized?
552bool wxFrame::IsMaximized(void) const
553{
554 // No maximizing in Motif (?)
555 return FALSE;
556}
557
4bb6408c
JS
558void wxFrame::SetTitle(const wxString& title)
559{
2d120f83
JS
560 if (title == m_title)
561 return;
4bb6408c 562
2d120f83
JS
563 m_title = title;
564
565 if (!title.IsNull())
566 XtVaSetValues((Widget) m_frameShell,
567 XmNtitle, (const char*) title,
568 XmNiconName, (const char*) title,
569 NULL);
4bb6408c
JS
570}
571
572void wxFrame::SetIcon(const wxIcon& icon)
573{
2d120f83
JS
574 m_icon = icon;
575
576 if (!m_frameShell)
577 return;
578
579 if (!icon.Ok() || !icon.GetPixmap())
580 return;
581
582 XtVaSetValues((Widget) m_frameShell, XtNiconPixmap, icon.GetPixmap(), NULL);
4bb6408c
JS
583}
584
585wxStatusBar *wxFrame::OnCreateStatusBar(int number, long style, wxWindowID id,
2d120f83 586 const wxString& name)
4bb6408c
JS
587{
588 wxStatusBar *statusBar = NULL;
2d120f83 589
4bb6408c
JS
590 statusBar = new wxStatusBar(this, id, wxPoint(0, 0), wxSize(100, 20),
591 style, name);
2d120f83 592
4bb6408c
JS
593 // Set the height according to the font and the border size
594 wxClientDC dc(statusBar);
c0ed460c 595 dc.SetFont(statusBar->GetFont());
2d120f83 596
4bb6408c
JS
597 long x, y;
598 dc.GetTextExtent("X", &x, &y);
2d120f83 599
4bb6408c 600 int height = (int)( (y * 1.1) + 2* statusBar->GetBorderY());
2d120f83 601
4bb6408c 602 statusBar->SetSize(-1, -1, 100, height);
2d120f83 603
4bb6408c
JS
604 statusBar->SetFieldsCount(number);
605 return statusBar;
606}
607
608wxStatusBar* wxFrame::CreateStatusBar(int number, long style, wxWindowID id,
2d120f83 609 const wxString& name)
4bb6408c 610{
2d120f83
JS
611 // Calling CreateStatusBar twice is an error.
612 wxCHECK_MSG( m_frameStatusBar == NULL, FALSE,
613 "recreating status bar in wxFrame" );
614
615 m_frameStatusBar = OnCreateStatusBar(number, style, id,
616 name);
617 if ( m_frameStatusBar )
618 {
619 PositionStatusBar();
620 return m_frameStatusBar;
621 }
622 else
623 return NULL;
4bb6408c
JS
624}
625
626void wxFrame::SetStatusText(const wxString& text, int number)
627{
2d120f83
JS
628 wxCHECK_RET( m_frameStatusBar != NULL, "no statusbar to set text for" );
629
630 m_frameStatusBar->SetStatusText(text, number);
4bb6408c
JS
631}
632
633void wxFrame::SetStatusWidths(int n, const int widths_field[])
634{
2d120f83
JS
635 wxCHECK_RET( m_frameStatusBar != NULL, "no statusbar to set widths for" );
636
637 m_frameStatusBar->SetStatusWidths(n, widths_field);
638 PositionStatusBar();
4bb6408c
JS
639}
640
641void wxFrame::PositionStatusBar()
642{
50414e24 643 if (!m_frameStatusBar)
2d120f83
JS
644 return;
645
4bb6408c
JS
646 int w, h;
647 GetClientSize(&w, &h);
648 int sw, sh;
649 m_frameStatusBar->GetSize(&sw, &sh);
2d120f83 650
4bb6408c
JS
651 // Since we wish the status bar to be directly under the client area,
652 // we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS.
89c7e962 653 m_frameStatusBar->SetSize(0, h, w, sh);
4bb6408c
JS
654}
655
656WXWidget wxFrame::GetMenuBarWidget() const
657{
2d120f83
JS
658 if (GetMenuBar())
659 return GetMenuBar()->GetMainWidget();
660 else
661 return (WXWidget) NULL;
4bb6408c
JS
662}
663
664void wxFrame::SetMenuBar(wxMenuBar *menuBar)
665{
666 if (!menuBar)
667 {
668 m_frameMenuBar = NULL;
669 return;
670 }
2d120f83 671
4bb6408c 672 // Currently can't set it twice
2d120f83
JS
673 // wxASSERT_MSG( (m_frameMenuBar == (wxMenuBar*) NULL), "Cannot set the menubar more than once");
674
621793f4 675 if (m_frameMenuBar)
4bb6408c 676 {
621793f4
JS
677 m_frameMenuBar->DestroyMenuBar();
678 delete m_frameMenuBar;
4bb6408c 679 }
2d120f83 680
621793f4
JS
681 m_frameMenuBar = menuBar;
682 m_frameMenuBar->CreateMenuBar(this);
4bb6408c
JS
683}
684
685void wxFrame::Fit()
686{
2d120f83
JS
687 // Work out max. size
688 wxNode *node = GetChildren().First();
689 int max_width = 0;
690 int max_height = 0;
691 while (node)
4bb6408c 692 {
2d120f83
JS
693 // Find a child that's a subwindow, but not a dialog box.
694 wxWindow *win = (wxWindow *)node->Data();
695
696 if (!win->IsKindOf(CLASSINFO(wxFrame)) &&
697 !win->IsKindOf(CLASSINFO(wxDialog)))
698 {
699 int width, height;
700 int x, y;
701 win->GetSize(&width, &height);
702 win->GetPosition(&x, &y);
703
704 if ((x + width) > max_width)
705 max_width = x + width;
706 if ((y + height) > max_height)
707 max_height = y + height;
708 }
709 node = node->Next();
4bb6408c 710 }
2d120f83 711 SetClientSize(max_width, max_height);
4bb6408c
JS
712}
713
714// Responds to colour changes, and passes event on to children.
715void wxFrame::OnSysColourChanged(wxSysColourChangedEvent& event)
716{
717 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE));
718 Refresh();
2d120f83 719
4bb6408c
JS
720 if ( m_frameStatusBar )
721 {
722 wxSysColourChangedEvent event2;
723 event2.SetEventObject( m_frameStatusBar );
724 m_frameStatusBar->ProcessEvent(event2);
725 }
2d120f83 726
4bb6408c
JS
727 // Propagate the event to the non-top-level children
728 wxWindow::OnSysColourChanged(event);
729}
730
731// Default resizing behaviour - if only ONE subwindow,
732// resize to client rectangle size
733void wxFrame::OnSize(wxSizeEvent& event)
734{
2d120f83
JS
735 // if we're using constraints - do use them
736#if wxUSE_CONSTRAINTS
4bb6408c 737 if ( GetAutoLayout() ) {
2d120f83
JS
738 Layout();
739 return;
4bb6408c 740 }
2d120f83
JS
741#endif
742
743 // do we have _exactly_ one child?
744 wxWindow *child = NULL;
745 for ( wxNode *node = GetChildren().First(); node; node = node->Next() )
4bb6408c 746 {
2d120f83
JS
747 wxWindow *win = (wxWindow *)node->Data();
748 if ( !win->IsKindOf(CLASSINFO(wxFrame)) &&
749 !win->IsKindOf(CLASSINFO(wxDialog)) &&
1ccbb61a
VZ
750 (win != GetStatusBar())
751#if wxUSE_TOOLBAR
752 && (win != GetToolBar())
753#endif // wxUSE_TOOLBAR
754 )
2d120f83
JS
755 {
756 if ( child )
757 return; // it's our second subwindow - nothing to do
758 child = win;
759 }
760 }
761
762 if ( child ) {
763 // we have exactly one child - set it's size to fill the whole frame
764 int clientW, clientH;
765 GetClientSize(&clientW, &clientH);
766
767 int x = 0;
768 int y = 0;
769
770 child->SetSize(x, y, clientW, clientH);
4bb6408c 771 }
4bb6408c
JS
772}
773
774// Default activation behaviour - set the focus for the first child
775// subwindow found.
776void wxFrame::OnActivate(wxActivateEvent& event)
777{
2d120f83 778 for(wxNode *node = GetChildren().First(); node; node = node->Next())
4bb6408c 779 {
2d120f83
JS
780 // Find a child that's a subwindow, but not a dialog box.
781 wxWindow *child = (wxWindow *)node->Data();
782 if (!child->IsKindOf(CLASSINFO(wxFrame)) &&
783 !child->IsKindOf(CLASSINFO(wxDialog)))
784 {
785 child->SetFocus();
786 return;
787 }
4bb6408c 788 }
4bb6408c
JS
789}
790
e3065973 791// The default implementation for the close window event.
4bb6408c
JS
792// OnClose for backward compatibility.
793
794void wxFrame::OnCloseWindow(wxCloseEvent& event)
795{
e3065973 796 this->Destroy();
4bb6408c
JS
797}
798
799// Destroy the window (delayed, if a managed window)
800bool wxFrame::Destroy()
801{
2d120f83
JS
802 if (!wxPendingDelete.Member(this))
803 wxPendingDelete.Append(this);
804 return TRUE;
4bb6408c
JS
805}
806
807// Default menu selection behaviour - display a help string
808void wxFrame::OnMenuHighlight(wxMenuEvent& event)
809{
2d120f83 810 if (GetStatusBar())
4bb6408c 811 {
2d120f83
JS
812 if (event.GetMenuId() == -1)
813 SetStatusText("");
814 else
815 {
816 wxMenuBar *menuBar = GetMenuBar();
817 if (menuBar)
818 {
819 wxString helpString(menuBar->GetHelpString(event.GetMenuId()));
820 if (helpString != "")
821 SetStatusText(helpString);
822 }
823 }
4bb6408c 824 }
4bb6408c
JS
825}
826
827wxMenuBar *wxFrame::GetMenuBar() const
828{
2d120f83 829 return m_frameMenuBar;
4bb6408c
JS
830}
831
832void wxFrame::Centre(int direction)
833{
2d120f83
JS
834 int display_width, display_height, width, height, x, y;
835 wxDisplaySize(&display_width, &display_height);
836
837 GetSize(&width, &height);
838 GetPosition(&x, &y);
839
840 if (direction & wxHORIZONTAL)
841 x = (int)((display_width - width)/2);
842 if (direction & wxVERTICAL)
843 y = (int)((display_height - height)/2);
844
845 SetSize(x, y, width, height);
4bb6408c
JS
846}
847
848// Call this to simulate a menu command
849void wxFrame::Command(int id)
850{
2d120f83 851 ProcessCommand(id);
4bb6408c
JS
852}
853
854void wxFrame::ProcessCommand(int id)
855{
c75e6695
VZ
856 wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, id);
857 commandEvent.SetInt( id );
858 commandEvent.SetEventObject( this );
859
860 wxMenuBar *bar = GetMenuBar() ;
861 if (!bar)
862 return;
863
864/* TODO: check the menu item if required
865 wxMenuItem *item = bar->FindItemForId(id) ;
866 if (item && item->IsCheckable())
867 {
868 bar->Check(id,!bar->Checked(id)) ;
869 }
870*/
871
6c41a418 872 wxEvtHandler* evtHandler = GetEventHandler();
e702ff0f
JS
873
874 evtHandler->ProcessEvent(commandEvent);
4bb6408c
JS
875}
876
877// Checks if there is a toolbar, and returns the first free client position
878wxPoint wxFrame::GetClientAreaOrigin() const
879{
880 wxPoint pt(0, 0);
1ccbb61a 881#if wxUSE_TOOLBAR
4bb6408c
JS
882 if (GetToolBar())
883 {
884 int w, h;
885 GetToolBar()->GetSize(& w, & h);
2d120f83 886
4bb6408c
JS
887 if (GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL)
888 {
889 pt.x += w;
890 }
891 else
892 {
893 pt.y += h;
894 }
895 }
1ccbb61a
VZ
896#endif // wxUSE_TOOLBAR
897
4bb6408c
JS
898 return pt;
899}
900
87d1e11f
JS
901void wxFrame::ScreenToClient(int *x, int *y) const
902{
903 wxWindow::ScreenToClient(x, y);
2d120f83 904
87d1e11f
JS
905 // We may be faking the client origin.
906 // So a window that's really at (0, 30) may appear
907 // (to wxWin apps) to be at (0, 0).
908 wxPoint pt(GetClientAreaOrigin());
909 *x -= pt.x;
910 *y -= pt.y;
911}
912
913void wxFrame::ClientToScreen(int *x, int *y) const
914{
915 // We may be faking the client origin.
916 // So a window that's really at (0, 30) may appear
917 // (to wxWin apps) to be at (0, 0).
918 wxPoint pt1(GetClientAreaOrigin());
919 *x += pt1.x;
920 *y += pt1.y;
2d120f83 921
87d1e11f
JS
922 wxWindow::ClientToScreen(x, y);
923}
924
1ccbb61a 925#if wxUSE_TOOLBAR
4bb6408c
JS
926wxToolBar* wxFrame::CreateToolBar(long style, wxWindowID id, const wxString& name)
927{
928 wxCHECK_MSG( m_frameToolBar == NULL, FALSE,
2d120f83
JS
929 "recreating toolbar in wxFrame" );
930
4bb6408c
JS
931 wxToolBar* toolBar = OnCreateToolBar(style, id, name);
932 if (toolBar)
933 {
934 SetToolBar(toolBar);
935 PositionToolBar();
936 return toolBar;
937 }
938 else
939 {
940 return NULL;
941 }
942}
943
944wxToolBar* wxFrame::OnCreateToolBar(long style, wxWindowID id, const wxString& name)
945{
a4294b78 946 return new wxToolBar(this, id, wxPoint(0, 0), wxSize(100, 24), style, name);
4bb6408c
JS
947}
948
1ccbb61a
VZ
949void wxFrame::SetToolBar(wxToolBar *toolbar)
950{
951 m_frameToolBar = toolbar;
952}
953
954wxToolBar *wxFrame::GetToolBar() const
955{
956 return m_frameToolBar;
957}
958
4bb6408c
JS
959void wxFrame::PositionToolBar()
960{
961 int cw, ch;
2d120f83 962
4bb6408c 963 GetClientSize(& cw, &ch);
2d120f83 964
4bb6408c
JS
965 if (GetToolBar())
966 {
967 int tw, th;
968 GetToolBar()->GetSize(& tw, & th);
2d120f83 969
4bb6408c
JS
970 if (GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL)
971 {
972 // Use the 'real' position. wxSIZE_NO_ADJUSTMENTS
973 // means, pretend we don't have toolbar/status bar, so we
974 // have the original client size.
a4294b78 975 GetToolBar()->SetSize(0, 0, tw, ch + th, wxSIZE_NO_ADJUSTMENTS);
4bb6408c
JS
976 }
977 else
978 {
979 // Use the 'real' position
980 GetToolBar()->SetSize(0, 0, cw, th, wxSIZE_NO_ADJUSTMENTS);
981 }
982 }
983}
1ccbb61a 984#endif // wxUSE_TOOLBAR
4bb6408c
JS
985
986void wxFrame::CaptureMouse()
987{
2d120f83
JS
988 if (m_winCaptured)
989 return;
4bb6408c 990
2d120f83
JS
991 if (GetMainWidget())
992 XtAddGrab((Widget) m_frameShell, TRUE, FALSE);
993 m_winCaptured = TRUE;
4bb6408c
JS
994}
995
996void wxFrame::ReleaseMouse()
997{
2d120f83
JS
998 if (!m_winCaptured)
999 return;
4bb6408c 1000
2d120f83
JS
1001 if (GetMainWidget())
1002 XtRemoveGrab((Widget) m_frameShell);
1003 m_winCaptured = FALSE;
4bb6408c
JS
1004}
1005
1006void wxFrame::Raise(void)
1007{
1008 Window parent_window = XtWindow((Widget) m_frameShell),
2d120f83
JS
1009 next_parent = XtWindow((Widget) m_frameShell),
1010 root = RootWindowOfScreen(XtScreen((Widget) m_frameShell));
4bb6408c
JS
1011 // search for the parent that is child of ROOT, because the WM may
1012 // reparent twice and notify only the next parent (like FVWM)
1013 while (next_parent != root) {
2d120f83
JS
1014 Window *theChildren; unsigned int n;
1015 parent_window = next_parent;
1016 XQueryTree(XtDisplay((Widget) m_frameShell), parent_window, &root,
1017 &next_parent, &theChildren, &n);
1018 XFree(theChildren); // not needed
4bb6408c
JS
1019 }
1020 XRaiseWindow(XtDisplay((Widget) m_frameShell), parent_window);
1021}
1022
1023void wxFrame::Lower(void)
1024{
1025 Window parent_window = XtWindow((Widget) m_frameShell),
2d120f83
JS
1026 next_parent = XtWindow((Widget) m_frameShell),
1027 root = RootWindowOfScreen(XtScreen((Widget) m_frameShell));
4bb6408c
JS
1028 // search for the parent that is child of ROOT, because the WM may
1029 // reparent twice and notify only the next parent (like FVWM)
1030 while (next_parent != root) {
2d120f83
JS
1031 Window *theChildren; unsigned int n;
1032 parent_window = next_parent;
1033 XQueryTree(XtDisplay((Widget) m_frameShell), parent_window, &root,
1034 &next_parent, &theChildren, &n);
1035 XFree(theChildren); // not needed
4bb6408c
JS
1036 }
1037 XLowerWindow(XtDisplay((Widget) m_frameShell), parent_window);
1038}
1039
8704bf74 1040void wxFrameFocusProc(Widget workArea, XtPointer clientData,
4bb6408c
JS
1041 XmAnyCallbackStruct *cbs)
1042{
2d120f83
JS
1043 wxFrame *frame = (wxFrame *)clientData;
1044
1045 // wxDebugMsg("focus proc from frame %ld\n",(long)frame);
1046 // TODO
1047 // frame->GetEventHandler()->OnSetFocus();
4bb6408c
JS
1048}
1049
1050/* MATTEW: Used to insure that hide-&-show within an event cycle works */
1051static void wxFrameMapProc(Widget frameShell, XtPointer clientData,
2d120f83 1052 XCrossingEvent * event)
4bb6408c 1053{
2d120f83
JS
1054 wxFrame *frame = (wxFrame *)wxWidgetHashTable->Get((long)clientData);
1055
1056 if (frame) {
1057 XEvent *e = (XEvent *)event;
1058
1059 if (e->xany.type == MapNotify)
1060 {
1061 // Iconize fix
1062 XtVaSetValues(frameShell, XmNiconic, (Boolean)False, NULL);
1063 if (!frame->GetVisibleStatus())
1064 {
1065 /* We really wanted this to be hidden! */
1066 XtUnmapWidget((Widget) frame->GetShellWidget());
1067 }
1068 }
1069 else if (e->xany.type == UnmapNotify)
1070 // Iconize fix
1071 XtVaSetValues(frameShell, XmNiconic, (Boolean)True, NULL);
4bb6408c 1072 }
4bb6408c
JS
1073}
1074
1075//// Motif-specific
1076bool wxFrame::PreResize()
1077{
1ccbb61a 1078#if wxUSE_TOOLBAR
2d120f83 1079 PositionToolBar();
1ccbb61a 1080#endif // wxUSE_TOOLBAR
2d120f83
JS
1081 PositionStatusBar();
1082 return TRUE;
4bb6408c
JS
1083}
1084
50414e24
JS
1085WXWidget wxFrame::GetClientWidget() const
1086{
2d120f83 1087 return m_clientArea;
50414e24
JS
1088}
1089
4b5f3fe6 1090void wxFrame::ChangeFont(bool keepOriginalSize)
0d57be45
JS
1091{
1092 // TODO
1093}
1094
1095void wxFrame::ChangeBackgroundColour()
1096{
621793f4
JS
1097 if (GetClientWidget())
1098 DoChangeBackgroundColour(GetClientWidget(), m_backgroundColour);
0d57be45
JS
1099}
1100
1101void wxFrame::ChangeForegroundColour()
1102{
621793f4
JS
1103 if (GetClientWidget())
1104 DoChangeForegroundColour(GetClientWidget(), m_foregroundColour);
0d57be45
JS
1105}
1106
4bb6408c
JS
1107void wxCloseFrameCallback(Widget widget, XtPointer client_data, XmAnyCallbackStruct *cbs)
1108{
2d120f83
JS
1109 wxFrame *frame = (wxFrame *)client_data;
1110
1111 wxCloseEvent closeEvent(wxEVT_CLOSE_WINDOW, frame->GetId());
1112 closeEvent.SetEventObject(frame);
1113
1114 // May delete the frame (with delayed deletion)
1115 frame->GetEventHandler()->ProcessEvent(closeEvent);
4bb6408c 1116}
0d57be45 1117