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