]> git.saurik.com Git - wxWidgets.git/blame - src/motif/frame.cpp
interchanged w and h in wxSplitterWindow::OnSashPositionChange (now
[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;
4bb6408c
JS
131
132 if ( id > -1 )
133 m_windowId = id;
134 else
135 m_windowId = (int)NewControlId();
136
137 if (parent) parent->AddChild(this);
138
139 wxModelessWindows.Append(this);
140
141 int x = pos.x; int y = pos.y;
142 int width = size.x; int height = size.y;
143
144 if (wxTopLevelUsed)
145 // Change suggested by Matthew Flatt
146 m_frameShell = (WXWidget) XtAppCreateShell(name, wxTheApp->GetClassName(), topLevelShellWidgetClass, (Display*) wxGetDisplay(), NULL, 0);
147 else
148 {
149 m_frameShell = wxTheApp->GetTopLevelWidget();
150 wxTopLevelUsed = TRUE;
151 }
152
153 XtVaSetValues((Widget) m_frameShell,
154 // Allows menu to resize
155 XmNallowShellResize, True,
156 XmNdeleteResponse, XmDO_NOTHING,
157 XmNmappedWhenManaged, False,
158 XmNiconic, (style & wxICONIZE) ? TRUE : FALSE,
159 NULL);
160
161 if (!title.IsNull())
162 XtVaSetValues((Widget) m_frameShell,
163 XmNtitle, (const char*) title,
164 NULL);
165
166 m_frameWidget = (WXWidget) XtVaCreateManagedWidget("main_window",
167 xmMainWindowWidgetClass, (Widget) m_frameShell,
168 XmNresizePolicy, XmRESIZE_NONE,
169 NULL);
170
171 m_workArea = (WXWidget) XtVaCreateWidget("form",
172 xmFormWidgetClass, (Widget) m_frameWidget,
173 XmNresizePolicy, XmRESIZE_NONE,
174 NULL);
175
176 m_clientArea = (WXWidget) XtVaCreateWidget("client",
177 xmBulletinBoardWidgetClass, (Widget) m_workArea,
178 XmNmarginWidth, 0,
179 XmNmarginHeight, 0,
180 XmNrightAttachment, XmATTACH_FORM,
181 XmNleftAttachment, XmATTACH_FORM,
182 XmNtopAttachment, XmATTACH_FORM,
183 XmNbottomAttachment, XmATTACH_FORM,
184// XmNresizePolicy, XmRESIZE_ANY,
185 NULL);
186
187 XtVaSetValues((Widget) m_frameWidget,
188 XmNworkWindow, (Widget) m_workArea,
189 NULL);
190
191
192 XtManageChild((Widget) m_clientArea);
193 XtManageChild((Widget) m_workArea);
194
195 wxASSERT_MSG ((wxWidgetHashTable->Get((long)m_workArea) == (wxObject*) NULL), "Widget table clash in frame.cpp") ;
196
197 wxAddWindowToTable((Widget) m_workArea, this);
198
199 XtTranslations ptr ;
200
201 XtOverrideTranslations((Widget) m_workArea,
202 ptr = XtParseTranslationTable("<Configure>: resize()"));
203
204 XtFree((char *)ptr);
205
206 XtAddCallback((Widget) m_workArea, XmNfocusCallback,
207 (XtCallbackProc)wxFrameFocusProc, (XtPointer)this);
208
209 /* Part of show-&-hide fix */
210 XtAddEventHandler((Widget) m_frameShell, StructureNotifyMask,
211 False, (XtEventHandler)wxFrameMapProc,
212 (XtPointer)m_workArea);
213
214 if (x > -1)
215 XtVaSetValues((Widget) m_frameShell, XmNx, x, NULL);
216 if (y > -1)
217 XtVaSetValues((Widget) m_frameShell, XmNy, y, NULL);
218 if (width > -1)
219 XtVaSetValues((Widget) m_frameShell, XmNwidth, width, NULL);
220 if (height > -1)
221 XtVaSetValues((Widget) m_frameShell, XmNheight, height, NULL);
222
223 m_mainWidget = m_frameWidget;
224
225 // This patch comes from Torsten Liermann lier@lier1.muc.de
dfc54541 226 if (XmIsMotifWMRunning( (Widget) m_frameShell ))
4bb6408c
JS
227 {
228 int decor = 0 ;
229 if (style & wxRESIZE_BORDER)
230 decor |= MWM_DECOR_RESIZEH ;
231 if (style & wxSYSTEM_MENU)
232 decor |= MWM_DECOR_MENU;
233 if ((style & wxCAPTION) ||
234 (style & wxTINY_CAPTION_HORIZ) ||
235 (style & wxTINY_CAPTION_VERT))
236 decor |= MWM_DECOR_TITLE;
237 if (style & wxTHICK_FRAME)
238 decor |= MWM_DECOR_BORDER;
239 if (style & wxTHICK_FRAME)
240 decor |= MWM_DECOR_BORDER;
241 if (style & wxMINIMIZE_BOX)
242 decor |= MWM_DECOR_MINIMIZE;
243 if (style & wxMAXIMIZE_BOX)
244 decor |= MWM_DECOR_MAXIMIZE;
245 XtVaSetValues((Widget) m_frameShell,XmNmwmDecorations,decor,NULL) ;
246 }
247 // This allows non-Motif window managers to support at least the
248 // no-decorations case.
249 else
250 {
251 if (style == 0)
dfc54541 252 XtVaSetValues((Widget) m_frameShell,XmNoverrideRedirect,TRUE,NULL);
4bb6408c
JS
253 }
254 XtRealizeWidget((Widget) m_frameShell);
255
256 // Intercept CLOSE messages from the window manager
257 Atom WM_DELETE_WINDOW = XmInternAtom(XtDisplay((Widget) m_frameShell), "WM_DELETE_WINDOW", False);
258#if (XmREVISION > 1 || XmVERSION > 1)
259 XmAddWMProtocolCallback((Widget) m_frameShell, WM_DELETE_WINDOW, (XtCallbackProc) wxCloseFrameCallback, (XtPointer)this);
260#else
261#if XmREVISION == 1
262 XmAddWMProtocolCallback((Widget) m_frameShell, WM_DELETE_WINDOW, (XtCallbackProc) wxCloseFrameCallback, (caddr_t)this);
263#else
264 XmAddWMProtocolCallback((Widget) m_frameShell, WM_DELETE_WINDOW, (void (*)())wxCloseFrameCallback, (caddr_t)this);
265#endif
266#endif
267
0d57be45
JS
268 ChangeBackgroundColour();
269
4bb6408c
JS
270 PreResize();
271
272 wxSizeEvent sizeEvent(wxSize(width, height), GetId());
273 sizeEvent.SetEventObject(this);
274
275 GetEventHandler()->ProcessEvent(sizeEvent);
276
277 return TRUE;
278}
279
280wxFrame::~wxFrame()
281{
282 if (GetMainWidget())
283 Show(FALSE);
284
285 if (m_frameMenuBar)
286 {
287// Hack to stop core dump on Ultrix, OSF, for some strange reason.
288#if MOTIF_MENUBAR_DELETE_FIX
289 GetMenuBar()->SetMainWidget((WXWidget) NULL);
290#endif
291 delete m_frameMenuBar;
292 m_frameMenuBar = NULL;
293 }
294
295 wxTopLevelWindows.DeleteObject(this);
296 wxModelessWindows.DeleteObject(this);
297
298 if (m_frameStatusBar)
299 delete m_frameStatusBar;
300
301 DestroyChildren();
302
303/*
304 int i;
305 for (i = 0; i < wxMAX_STATUS; i++)
306 if (statusTextWidget[i])
307 XtDestroyWidget (statusTextWidget[i]);
308
309 if (statusLineForm)
310 XtDestroyWidget (statusLineForm);
311
312 if (statusLineWidget)
313 XtDestroyWidget (statusLineWidget);
314 */
315
8704bf74
JS
316 if (m_workArea)
317 {
318 wxDeleteWindowFromTable((Widget) m_workArea);
4bb6408c 319
8704bf74
JS
320 XtDestroyWidget ((Widget) m_workArea);
321 }
4bb6408c 322
8704bf74
JS
323 if (m_frameWidget)
324 {
325 wxDeleteWindowFromTable((Widget) m_frameWidget);
326 XtDestroyWidget ((Widget) m_frameWidget);
327 }
4bb6408c 328
8704bf74
JS
329 if (m_frameShell)
330 XtDestroyWidget ((Widget) m_frameShell);
4bb6408c
JS
331
332 SetMainWidget((WXWidget) NULL);
333
334/* Check if it's the last top-level window */
335
336 if (wxTheApp && (wxTopLevelWindows.Number() == 0))
337 {
338 wxTheApp->SetTopWindow(NULL);
339
340 if (wxTheApp->GetExitOnFrameDelete())
341 {
dfc54541 342 // Signal to the app that we're going to close
4bb6408c
JS
343 wxTheApp->ExitMainLoop();
344 }
345 }
346
347}
348
349// Get size *available for subwindows* i.e. excluding menu bar, toolbar etc.
350void wxFrame::GetClientSize(int *x, int *y) const
351{
352 Dimension xx, yy;
353 XtVaGetValues((Widget) m_workArea, XmNwidth, &xx, XmNheight, &yy, NULL);
354
89c7e962 355 if (m_frameStatusBar)
4bb6408c 356 {
89c7e962
JS
357 int sbw, sbh;
358 m_frameStatusBar->GetSize(& sbw, & sbh);
359 yy -= sbh;
4bb6408c 360 }
a4294b78
JS
361 if (m_frameToolBar)
362 {
363 int tbw, tbh;
364 m_frameToolBar->GetSize(& tbw, & tbh);
365 if (m_frameToolBar->GetWindowStyleFlag() & wxTB_VERTICAL)
366 xx -= tbw;
367 else
368 yy -= tbh;
369 }
370/*
4bb6408c
JS
371 if (GetMenuBar() != (wxMenuBar*) NULL)
372 {
373 // it seems that if a frame holds a panel, the menu bar size
374 // gets automatically taken care of --- grano@cs.helsinki.fi 4.4.95
375 bool hasSubPanel = FALSE;
376 for(wxNode* node = GetChildren()->First(); node; node = node->Next())
377 {
378 wxWindow *win = (wxWindow *)node->Data();
379 hasSubPanel = (win->IsKindOf(CLASSINFO(wxPanel)) && !win->IsKindOf(CLASSINFO(wxDialog)));
380
381 if (hasSubPanel)
382 break;
383 }
384 if (! hasSubPanel) {
385 Dimension ys;
386 XtVaGetValues((Widget) GetMenuBarWidget(), XmNheight, &ys, NULL);
387 yy -= ys;
388 }
389 }
a4294b78 390 */
4bb6408c
JS
391
392 *x = xx; *y = yy;
393}
394
395// Set the client size (i.e. leave the calculation of borders etc.
396// to wxWindows)
397void wxFrame::SetClientSize(int width, int height)
398{
399 // Calculate how large the new main window should be
400 // by finding the difference between the client area and the
401 // main window area, and adding on to the new client area
402 if (width > -1)
403 XtVaSetValues((Widget) m_workArea, XmNwidth, width, NULL);
404
405 if (height > -1)
406 {
a4294b78 407 if (m_frameStatusBar)
4bb6408c 408 {
a4294b78
JS
409 int sbw, sbh;
410 m_frameStatusBar->GetSize(& sbw, & sbh);
411 height += sbh;
4bb6408c 412 }
a4294b78
JS
413 if (m_frameToolBar)
414 {
415 int tbw, tbh;
416 m_frameToolBar->GetSize(& tbw, & tbh);
417 if (m_frameToolBar->GetWindowStyleFlag() & wxTB_VERTICAL)
418 width += tbw;
419 else
420 height += tbh;
421 }
422
4bb6408c
JS
423 XtVaSetValues((Widget) m_workArea, XmNheight, height, NULL);
424 }
425 PreResize();
426
427 wxSizeEvent sizeEvent(wxSize(width, height), GetId());
428 sizeEvent.SetEventObject(this);
429
430 GetEventHandler()->ProcessEvent(sizeEvent);
431
432}
433
434void wxFrame::GetSize(int *width, int *height) const
435{
436 Dimension xx, yy;
437 XtVaGetValues((Widget) m_frameShell, XmNwidth, &xx, XmNheight, &yy, NULL);
438 *width = xx; *height = yy;
439}
440
441void wxFrame::GetPosition(int *x, int *y) const
442{
443 Window parent_window = XtWindow((Widget) m_frameShell),
444 next_parent = XtWindow((Widget) m_frameShell),
445 root = RootWindowOfScreen(XtScreen((Widget) m_frameShell));
446
447 // search for the parent that is child of ROOT, because the WM may
448 // reparent twice and notify only the next parent (like FVWM)
449 while (next_parent != root) {
450 Window *theChildren; unsigned int n;
451 parent_window = next_parent;
452 XQueryTree(XtDisplay((Widget) m_frameShell), parent_window, &root,
453 &next_parent, &theChildren, &n);
454 XFree(theChildren); // not needed
455 }
456 int xx, yy; unsigned int dummy;
457 XGetGeometry(XtDisplay((Widget) m_frameShell), parent_window, &root,
458 &xx, &yy, &dummy, &dummy, &dummy, &dummy);
459 if (x) *x = xx;
460 if (y) *y = yy;
461}
462
463void wxFrame::SetSize(int x, int y, int width, int height, int sizeFlags)
464{
465 if (x > -1)
466 XtVaSetValues((Widget) m_frameShell, XmNx, x, NULL);
467 if (y > -1)
468 XtVaSetValues((Widget) m_frameShell, XmNy, y, NULL);
469 if (width > -1)
470 XtVaSetValues((Widget) m_frameWidget, XmNwidth, width, NULL);
471 if (height > -1)
472 XtVaSetValues((Widget) m_frameWidget, XmNheight, height, NULL);
473
474 if (!(height == -1 && width == -1))
475 {
476 PreResize();
477 wxSizeEvent sizeEvent(wxSize(width, height), GetId());
478 sizeEvent.SetEventObject(this);
479
480 GetEventHandler()->ProcessEvent(sizeEvent);
481 }
482}
483
484bool wxFrame::Show(bool show)
485{
486 m_visibleStatus = show; /* show-&-hide fix */
487
488 m_isShown = show;
489 if (show) {
490 XtMapWidget((Widget) m_frameShell);
491 XRaiseWindow(XtDisplay((Widget) m_frameShell), XtWindow((Widget) m_frameShell));
492 } else {
493 XtUnmapWidget((Widget) m_frameShell);
494// XmUpdateDisplay(wxTheApp->topLevel); // Experimental: may be responsible for crashes
495 }
496 return TRUE;
497}
498
499void wxFrame::Iconize(bool iconize)
500{
501 if (!iconize)
502 Show(TRUE);
503
504 XtVaSetValues((Widget) m_frameShell, XmNiconic, (Boolean)iconize, NULL);
505}
506
507// Equivalent to maximize/restore in Windows
508void wxFrame::Maximize(bool maximize)
509{
510 Show(TRUE);
511
512 if (maximize)
513 XtVaSetValues((Widget) m_frameShell, XmNiconic, FALSE, NULL);
514}
515
516bool wxFrame::IsIconized() const
517{
518 Boolean iconic;
519 XtVaGetValues((Widget) m_frameShell, XmNiconic, &iconic, NULL);
520 return iconic;
521}
522
523void wxFrame::SetTitle(const wxString& title)
524{
525 if (title == m_title)
526 return;
527
528 m_title = title;
529
530 if (!title.IsNull())
531 XtVaSetValues((Widget) m_frameShell,
532 XmNtitle, (const char*) title,
533 XmNiconName, (const char*) title,
534 NULL);
535}
536
537void wxFrame::SetIcon(const wxIcon& icon)
538{
539 m_icon = icon;
540
541 // TODO
542 /*
543 if (!icon.Ok() || !icon.GetPixmap())
544 return;
545
546 XtVaSetValues((Widget) m_frameShell, XtNiconPixmap, icon->.GetPixmap(), NULL);
547 */
548}
549
550wxStatusBar *wxFrame::OnCreateStatusBar(int number, long style, wxWindowID id,
551 const wxString& name)
552{
553 wxStatusBar *statusBar = NULL;
554
555 statusBar = new wxStatusBar(this, id, wxPoint(0, 0), wxSize(100, 20),
556 style, name);
557
558 // Set the height according to the font and the border size
559 wxClientDC dc(statusBar);
560 dc.SetFont(* statusBar->GetFont());
561
562 long x, y;
563 dc.GetTextExtent("X", &x, &y);
564
565 int height = (int)( (y * 1.1) + 2* statusBar->GetBorderY());
566
567 statusBar->SetSize(-1, -1, 100, height);
568
569 statusBar->SetFieldsCount(number);
570 return statusBar;
571}
572
573wxStatusBar* wxFrame::CreateStatusBar(int number, long style, wxWindowID id,
574 const wxString& name)
575{
576 // Calling CreateStatusBar twice is an error.
577 wxCHECK_MSG( m_frameStatusBar == NULL, FALSE,
578 "recreating status bar in wxFrame" );
579
580 m_frameStatusBar = OnCreateStatusBar(number, style, id,
581 name);
582 if ( m_frameStatusBar )
583 {
584 PositionStatusBar();
585 return m_frameStatusBar;
586 }
587 else
588 return NULL;
589}
590
591void wxFrame::SetStatusText(const wxString& text, int number)
592{
593 wxCHECK_RET( m_frameStatusBar != NULL, "no statusbar to set text for" );
594
595 m_frameStatusBar->SetStatusText(text, number);
596}
597
598void wxFrame::SetStatusWidths(int n, const int widths_field[])
599{
600 wxCHECK_RET( m_frameStatusBar != NULL, "no statusbar to set widths for" );
601
602 m_frameStatusBar->SetStatusWidths(n, widths_field);
603 PositionStatusBar();
604}
605
606void wxFrame::PositionStatusBar()
607{
50414e24
JS
608 if (!m_frameStatusBar)
609 return;
610
4bb6408c
JS
611 int w, h;
612 GetClientSize(&w, &h);
613 int sw, sh;
614 m_frameStatusBar->GetSize(&sw, &sh);
615
616 // Since we wish the status bar to be directly under the client area,
617 // we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS.
89c7e962 618 m_frameStatusBar->SetSize(0, h, w, sh);
4bb6408c
JS
619}
620
621WXWidget wxFrame::GetMenuBarWidget() const
622{
4bb6408c
JS
623 if (GetMenuBar())
624 return GetMenuBar()->GetMainWidget();
625 else
4bb6408c
JS
626 return (WXWidget) NULL;
627}
628
629void wxFrame::SetMenuBar(wxMenuBar *menuBar)
630{
631 if (!menuBar)
632 {
633 m_frameMenuBar = NULL;
634 return;
635 }
636
637 // Currently can't set it twice
638 wxASSERT_MSG( (m_frameMenuBar == (wxMenuBar*) NULL), "Cannot set the menubar more than once");
639
640 m_frameMenuBar = menuBar;
641
4bb6408c
JS
642 Widget menuBarW = XmCreateMenuBar ((Widget) m_frameWidget, "MenuBar", NULL, 0);
643 m_frameMenuBar->SetMainWidget( (WXWidget) menuBarW);
644
645 int i;
646 for (i = 0; i < menuBar->GetMenuCount(); i++)
647 {
648 wxMenu *menu = menuBar->GetMenu(i);
50414e24
JS
649 wxString title(menuBar->m_titles[i]);
650 menu->SetButtonWidget(menu->CreateMenu (menuBar, menuBarW, menu, title, TRUE));
4bb6408c
JS
651
652 /*
653 * COMMENT THIS OUT IF YOU DON'T LIKE A RIGHT-JUSTIFIED HELP MENU
654 */
50414e24 655 wxStripMenuCodes ((char*) (const char*) title, wxBuffer);
4bb6408c
JS
656
657 if (strcmp (wxBuffer, "Help") == 0)
658 XtVaSetValues ((Widget) menuBarW, XmNmenuHelpWidget, (Widget) menu->GetButtonWidget(), NULL);
659 }
660
661 XtRealizeWidget ((Widget) menuBarW);
662 XtManageChild ((Widget) menuBarW);
663 menuBar->SetMenuBarFrame(this);
4bb6408c
JS
664}
665
666void wxFrame::Fit()
667{
668 // Work out max. size
669 wxNode *node = GetChildren()->First();
670 int max_width = 0;
671 int max_height = 0;
672 while (node)
673 {
674 // Find a child that's a subwindow, but not a dialog box.
675 wxWindow *win = (wxWindow *)node->Data();
676
677 if (!win->IsKindOf(CLASSINFO(wxFrame)) &&
678 !win->IsKindOf(CLASSINFO(wxDialog)))
679 {
680 int width, height;
681 int x, y;
682 win->GetSize(&width, &height);
683 win->GetPosition(&x, &y);
684
685 if ((x + width) > max_width)
686 max_width = x + width;
687 if ((y + height) > max_height)
688 max_height = y + height;
689 }
690 node = node->Next();
691 }
692 SetClientSize(max_width, max_height);
693}
694
695// Responds to colour changes, and passes event on to children.
696void wxFrame::OnSysColourChanged(wxSysColourChangedEvent& event)
697{
698 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE));
699 Refresh();
700
701 if ( m_frameStatusBar )
702 {
703 wxSysColourChangedEvent event2;
704 event2.SetEventObject( m_frameStatusBar );
705 m_frameStatusBar->ProcessEvent(event2);
706 }
707
708 // Propagate the event to the non-top-level children
709 wxWindow::OnSysColourChanged(event);
710}
711
712// Default resizing behaviour - if only ONE subwindow,
713// resize to client rectangle size
714void wxFrame::OnSize(wxSizeEvent& event)
715{
716 // if we're using constraints - do use them
47d67540 717 #if wxUSE_CONSTRAINTS
4bb6408c
JS
718 if ( GetAutoLayout() ) {
719 Layout();
720 return;
721 }
722 #endif
723
724 // do we have _exactly_ one child?
725 wxWindow *child = NULL;
726 for ( wxNode *node = GetChildren()->First(); node; node = node->Next() )
727 {
728 wxWindow *win = (wxWindow *)node->Data();
729 if ( !win->IsKindOf(CLASSINFO(wxFrame)) &&
730 !win->IsKindOf(CLASSINFO(wxDialog)) &&
731 (win != GetStatusBar()) &&
732 (win != GetToolBar()) )
733 {
734 if ( child )
735 return; // it's our second subwindow - nothing to do
736 child = win;
737 }
738 }
739
740 if ( child ) {
741 // we have exactly one child - set it's size to fill the whole frame
742 int clientW, clientH;
743 GetClientSize(&clientW, &clientH);
744
745 int x = 0;
746 int y = 0;
747
748 child->SetSize(x, y, clientW, clientH);
749 }
750}
751
752// Default activation behaviour - set the focus for the first child
753// subwindow found.
754void wxFrame::OnActivate(wxActivateEvent& event)
755{
756 for(wxNode *node = GetChildren()->First(); node; node = node->Next())
757 {
758 // Find a child that's a subwindow, but not a dialog box.
759 wxWindow *child = (wxWindow *)node->Data();
760 if (!child->IsKindOf(CLASSINFO(wxFrame)) &&
761 !child->IsKindOf(CLASSINFO(wxDialog)))
762 {
763#if WXDEBUG > 1
764 wxDebugMsg("wxFrame::OnActivate: about to set the child's focus.\n");
765#endif
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
886wxToolBar* wxFrame::CreateToolBar(long style, wxWindowID id, const wxString& name)
887{
888 wxCHECK_MSG( m_frameToolBar == NULL, FALSE,
889 "recreating toolbar in wxFrame" );
890
891 wxToolBar* toolBar = OnCreateToolBar(style, id, name);
892 if (toolBar)
893 {
894 SetToolBar(toolBar);
895 PositionToolBar();
896 return toolBar;
897 }
898 else
899 {
900 return NULL;
901 }
902}
903
904wxToolBar* wxFrame::OnCreateToolBar(long style, wxWindowID id, const wxString& name)
905{
a4294b78 906 return new wxToolBar(this, id, wxPoint(0, 0), wxSize(100, 24), style, name);
4bb6408c
JS
907}
908
909void wxFrame::PositionToolBar()
910{
911 int cw, ch;
912
4bb6408c
JS
913 GetClientSize(& cw, &ch);
914
4bb6408c
JS
915 if (GetToolBar())
916 {
917 int tw, th;
918 GetToolBar()->GetSize(& tw, & th);
919
920 if (GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL)
921 {
922 // Use the 'real' position. wxSIZE_NO_ADJUSTMENTS
923 // means, pretend we don't have toolbar/status bar, so we
924 // have the original client size.
a4294b78 925 GetToolBar()->SetSize(0, 0, tw, ch + th, wxSIZE_NO_ADJUSTMENTS);
4bb6408c
JS
926 }
927 else
928 {
929 // Use the 'real' position
930 GetToolBar()->SetSize(0, 0, cw, th, wxSIZE_NO_ADJUSTMENTS);
931 }
932 }
933}
934
935void wxFrame::CaptureMouse()
936{
937 if (m_winCaptured)
938 return;
939
940 if (GetMainWidget())
941 XtAddGrab((Widget) m_frameShell, TRUE, FALSE);
942 m_winCaptured = TRUE;
943}
944
945void wxFrame::ReleaseMouse()
946{
947 if (!m_winCaptured)
948 return;
949
950 if (GetMainWidget())
951 XtRemoveGrab((Widget) m_frameShell);
952 m_winCaptured = FALSE;
953}
954
955void wxFrame::Raise(void)
956{
957 Window parent_window = XtWindow((Widget) m_frameShell),
958 next_parent = XtWindow((Widget) m_frameShell),
959 root = RootWindowOfScreen(XtScreen((Widget) m_frameShell));
960 // search for the parent that is child of ROOT, because the WM may
961 // reparent twice and notify only the next parent (like FVWM)
962 while (next_parent != root) {
963 Window *theChildren; unsigned int n;
964 parent_window = next_parent;
965 XQueryTree(XtDisplay((Widget) m_frameShell), parent_window, &root,
966 &next_parent, &theChildren, &n);
967 XFree(theChildren); // not needed
968 }
969 XRaiseWindow(XtDisplay((Widget) m_frameShell), parent_window);
970}
971
972void wxFrame::Lower(void)
973{
974 Window parent_window = XtWindow((Widget) m_frameShell),
975 next_parent = XtWindow((Widget) m_frameShell),
976 root = RootWindowOfScreen(XtScreen((Widget) m_frameShell));
977 // search for the parent that is child of ROOT, because the WM may
978 // reparent twice and notify only the next parent (like FVWM)
979 while (next_parent != root) {
980 Window *theChildren; unsigned int n;
981 parent_window = next_parent;
982 XQueryTree(XtDisplay((Widget) m_frameShell), parent_window, &root,
983 &next_parent, &theChildren, &n);
984 XFree(theChildren); // not needed
985 }
986 XLowerWindow(XtDisplay((Widget) m_frameShell), parent_window);
987}
988
989void wxFrame::SetToolBar(wxToolBar *toolbar)
990{ m_frameToolBar = toolbar; }
991
992wxToolBar *wxFrame::GetToolBar() const
993{ return m_frameToolBar; }
994
8704bf74 995void wxFrameFocusProc(Widget workArea, XtPointer clientData,
4bb6408c
JS
996 XmAnyCallbackStruct *cbs)
997{
998 wxFrame *frame = (wxFrame *)clientData;
999
1000 // wxDebugMsg("focus proc from frame %ld\n",(long)frame);
1001 // TODO
1002 // frame->GetEventHandler()->OnSetFocus();
1003}
1004
1005/* MATTEW: Used to insure that hide-&-show within an event cycle works */
1006static void wxFrameMapProc(Widget frameShell, XtPointer clientData,
1007 XCrossingEvent * event)
1008{
1009 wxFrame *frame = (wxFrame *)wxWidgetHashTable->Get((long)clientData);
1010
1011 if (frame) {
1012 XEvent *e = (XEvent *)event;
1013
1014 if (e->xany.type == MapNotify)
1015 {
1016 // Iconize fix
1017 XtVaSetValues(frameShell, XmNiconic, (Boolean)False, NULL);
1018 if (!frame->GetVisibleStatus())
1019 {
1020 /* We really wanted this to be hidden! */
1021 XtUnmapWidget((Widget) frame->GetShellWidget());
1022 }
1023 }
1024 else if (e->xany.type == UnmapNotify)
1025 // Iconize fix
1026 XtVaSetValues(frameShell, XmNiconic, (Boolean)True, NULL);
1027 }
1028}
1029
1030//// Motif-specific
1031bool wxFrame::PreResize()
1032{
a4294b78 1033 PositionToolBar();
50414e24 1034 PositionStatusBar();
4bb6408c
JS
1035 return TRUE;
1036}
1037
50414e24
JS
1038WXWidget wxFrame::GetClientWidget() const
1039{
1040 return m_clientArea;
1041}
1042
0d57be45
JS
1043void wxFrame::ChangeFont()
1044{
1045 // TODO
1046}
1047
1048void wxFrame::ChangeBackgroundColour()
1049{
1050 // TODO
1051}
1052
1053void wxFrame::ChangeForegroundColour()
1054{
1055 // TODO
1056}
1057
4bb6408c
JS
1058void wxCloseFrameCallback(Widget widget, XtPointer client_data, XmAnyCallbackStruct *cbs)
1059{
1060 wxFrame *frame = (wxFrame *)client_data;
1061
1062 wxCloseEvent closeEvent(wxEVT_CLOSE_WINDOW, frame->GetId());
1063 closeEvent.SetEventObject(frame);
1064
1065 // May delete the frame (with delayed deletion)
1066 frame->GetEventHandler()->ProcessEvent(closeEvent);
1067}
0d57be45 1068