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