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