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