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