]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/motif/frame.cpp
Added lots of files. Enough now so that all wxHTML samples link.
[wxWidgets.git] / src / motif / frame.cpp
... / ...
CommitLineData
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
53extern wxHashTable *wxWidgetHashTable;
54
55void wxCloseFrameCallback(Widget, XtPointer, XmAnyCallbackStruct *cbs);
56void wxFrameFocusProc(Widget workArea, XtPointer clientData,
57 XmAnyCallbackStruct *cbs);
58static void wxFrameMapProc(Widget frameShell, XtPointer clientData,
59 XCrossingEvent * event);
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)
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)
76END_EVENT_TABLE()
77
78IMPLEMENT_DYNAMIC_CLASS(wxFrame, wxWindow)
79#endif
80
81#if wxUSE_NATIVE_STATUSBAR
82bool wxFrame::m_useNativeStatusBar = TRUE;
83#else
84bool wxFrame::m_useNativeStatusBar = FALSE;
85#endif
86
87wxFrame::wxFrame()
88{
89#if wxUSE_TOOLBAR
90 m_frameToolBar = NULL ;
91#endif // wxUSE_TOOLBAR
92
93 m_frameMenuBar = NULL;
94 m_frameStatusBar = NULL;
95
96 m_parent = NULL;
97 m_iconized = FALSE;
98
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,
109 wxWindowID id,
110 const wxString& title,
111 const wxPoint& pos,
112 const wxSize& size,
113 long style,
114 const wxString& name)
115{
116 if (!parent)
117 wxTopLevelWindows.Append(this);
118
119 SetName(name);
120
121 m_windowStyle = style;
122 m_frameMenuBar = NULL;
123#if wxUSE_TOOLBAR
124 m_frameToolBar = NULL ;
125#endif // wxUSE_TOOLBAR
126 m_frameStatusBar = NULL;
127
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 = "";
135
136 m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE);
137 m_foregroundColour = *wxBLACK;
138 m_font = wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT);
139
140 if ( id > -1 )
141 m_windowId = id;
142 else
143 m_windowId = (int)NewControlId();
144
145 if (parent) parent->AddChild(this);
146
147 wxModelessWindows.Append(this);
148
149 int x = pos.x; int y = pos.y;
150 int width = size.x; int height = size.y;
151
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 }
160
161 XtVaSetValues((Widget) m_frameShell,
162 // Allows menu to resize
163 XmNallowShellResize, True,
164 XmNdeleteResponse, XmDO_NOTHING,
165 XmNmappedWhenManaged, False,
166 XmNiconic, (style & wxICONIZE) ? TRUE : FALSE,
167 NULL);
168
169 if (!title.IsNull())
170 XtVaSetValues((Widget) m_frameShell,
171 XmNtitle, (const char*) title,
172 NULL);
173
174 m_frameWidget = (WXWidget) XtVaCreateManagedWidget("main_window",
175 xmMainWindowWidgetClass, (Widget) m_frameShell,
176 XmNresizePolicy, XmRESIZE_NONE,
177 NULL);
178
179 m_workArea = (WXWidget) XtVaCreateWidget("form",
180 xmFormWidgetClass, (Widget) m_frameWidget,
181 XmNresizePolicy, XmRESIZE_NONE,
182 NULL);
183
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);
194
195 XtAddEventHandler((Widget) m_clientArea, ExposureMask,FALSE,
196 wxUniversalRepaintProc, (XtPointer) this);
197
198 XtVaSetValues((Widget) m_frameWidget,
199 XmNworkWindow, (Widget) m_workArea,
200 NULL);
201
202 XtManageChild((Widget) m_clientArea);
203 XtManageChild((Widget) m_workArea);
204
205 wxASSERT_MSG( !wxGetWindowFromTable((Widget)m_workArea),
206 "Widget table clash in frame.cpp") ;
207
208 wxAddWindowToTable((Widget) m_workArea, this);
209
210 XtTranslations ptr ;
211
212 XtOverrideTranslations((Widget) m_workArea,
213 ptr = XtParseTranslationTable("<Configure>: resize()"));
214
215 XtFree((char *)ptr);
216
217 XtAddCallback((Widget) m_workArea, XmNfocusCallback,
218 (XtCallbackProc)wxFrameFocusProc, (XtPointer)this);
219
220 /* Part of show-&-hide fix */
221 XtAddEventHandler((Widget) m_frameShell, StructureNotifyMask,
222 False, (XtEventHandler)wxFrameMapProc,
223 (XtPointer)m_workArea);
224
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);
233
234 m_mainWidget = m_frameWidget;
235
236 ChangeFont(FALSE);
237
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);
268
269 // Intercept CLOSE messages from the window manager
270 Atom WM_DELETE_WINDOW = XmInternAtom(XtDisplay((Widget) m_frameShell), "WM_DELETE_WINDOW", False);
271#if (XmREVISION > 1 || XmVERSION > 1)
272 XmAddWMProtocolCallback((Widget) m_frameShell, WM_DELETE_WINDOW, (XtCallbackProc) wxCloseFrameCallback, (XtPointer)this);
273#else
274#if XmREVISION == 1
275 XmAddWMProtocolCallback((Widget) m_frameShell, WM_DELETE_WINDOW, (XtCallbackProc) wxCloseFrameCallback, (caddr_t)this);
276#else
277 XmAddWMProtocolCallback((Widget) m_frameShell, WM_DELETE_WINDOW, (void (*)())wxCloseFrameCallback, (caddr_t)this);
278#endif
279#endif
280
281 ChangeBackgroundColour();
282
283 PreResize();
284
285 wxSizeEvent sizeEvent(wxSize(width, height), GetId());
286 sizeEvent.SetEventObject(this);
287
288 GetEventHandler()->ProcessEvent(sizeEvent);
289
290 return TRUE;
291}
292
293wxFrame::~wxFrame()
294{
295 if (m_clientArea)
296 XtRemoveEventHandler((Widget) m_clientArea, ExposureMask, FALSE,
297 wxUniversalRepaintProc, (XtPointer) this);
298
299 if (GetMainWidget())
300 Show(FALSE);
301
302 if (m_frameMenuBar)
303 {
304 m_frameMenuBar->DestroyMenuBar();
305
306 // Hack to stop core dump on Ultrix, OSF, for some strange reason.
307#if MOTIF_MENUBAR_DELETE_FIX
308 GetMenuBar()->SetMainWidget((WXWidget) NULL);
309#endif
310 delete m_frameMenuBar;
311 m_frameMenuBar = NULL;
312 }
313
314 wxTopLevelWindows.DeleteObject(this);
315 wxModelessWindows.DeleteObject(this);
316
317 if (m_frameStatusBar)
318 delete m_frameStatusBar;
319
320 DestroyChildren();
321
322 /*
323 int i;
324 for (i = 0; i < wxMAX_STATUS; i++)
325 if (statusTextWidget[i])
326 XtDestroyWidget (statusTextWidget[i]);
327
328 if (statusLineForm)
329 XtDestroyWidget (statusLineForm);
330
331 if (statusLineWidget)
332 XtDestroyWidget (statusLineWidget);
333 */
334
335 if (m_workArea)
336 {
337 wxDeleteWindowFromTable((Widget) m_workArea);
338
339 XtDestroyWidget ((Widget) m_workArea);
340 }
341
342 if (m_frameWidget)
343 {
344 wxDeleteWindowFromTable((Widget) m_frameWidget);
345 XtDestroyWidget ((Widget) m_frameWidget);
346 }
347
348 if (m_frameShell)
349 XtDestroyWidget ((Widget) m_frameShell);
350
351 SetMainWidget((WXWidget) NULL);
352
353 /* Check if it's the last top-level window */
354
355 if (wxTheApp && (wxTopLevelWindows.Number() == 0))
356 {
357 wxTheApp->SetTopWindow(NULL);
358
359 if (wxTheApp->GetExitOnFrameDelete())
360 {
361 // Signal to the app that we're going to close
362 wxTheApp->ExitMainLoop();
363 }
364 }
365
366}
367
368// Get size *available for subwindows* i.e. excluding menu bar, toolbar etc.
369void wxFrame::GetClientSize(int *x, int *y) const
370{
371 Dimension xx, yy;
372 XtVaGetValues((Widget) m_workArea, XmNwidth, &xx, XmNheight, &yy, NULL);
373
374 if (m_frameStatusBar)
375 {
376 int sbw, sbh;
377 m_frameStatusBar->GetSize(& sbw, & sbh);
378 yy -= sbh;
379 }
380#if wxUSE_TOOLBAR
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 }
390#endif // wxUSE_TOOLBAR
391 /*
392 if (GetMenuBar() != (wxMenuBar*) NULL)
393 {
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;
397 for(wxNode* node = GetChildren().First(); node; node = node->Next())
398 {
399 wxWindow *win = (wxWindow *)node->Data();
400 hasSubPanel = (win->IsKindOf(CLASSINFO(wxPanel)) && !win->IsKindOf(CLASSINFO(wxDialog)));
401
402 if (hasSubPanel)
403 break;
404 }
405 if (! hasSubPanel) {
406 Dimension ys;
407 XtVaGetValues((Widget) GetMenuBarWidget(), XmNheight, &ys, NULL);
408 yy -= ys;
409 }
410 }
411 */
412
413 *x = xx; *y = yy;
414}
415
416// Set the client size (i.e. leave the calculation of borders etc.
417// to wxWindows)
418void wxFrame::DoSetClientSize(int width, int height)
419{
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);
425
426 if (height > -1)
427 {
428 if (m_frameStatusBar)
429 {
430 int sbw, sbh;
431 m_frameStatusBar->GetSize(& sbw, & sbh);
432 height += sbh;
433 }
434#if wxUSE_TOOLBAR
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 }
444#endif // wxUSE_TOOLBAR
445
446 XtVaSetValues((Widget) m_workArea, XmNheight, height, NULL);
447 }
448 PreResize();
449
450 wxSizeEvent sizeEvent(wxSize(width, height), GetId());
451 sizeEvent.SetEventObject(this);
452
453 GetEventHandler()->ProcessEvent(sizeEvent);
454
455}
456
457void wxFrame::GetSize(int *width, int *height) const
458{
459 Dimension xx, yy;
460 XtVaGetValues((Widget) m_frameShell, XmNwidth, &xx, XmNheight, &yy, NULL);
461 *width = xx; *height = yy;
462}
463
464void wxFrame::GetPosition(int *x, int *y) const
465{
466 Window parent_window = XtWindow((Widget) m_frameShell),
467 next_parent = XtWindow((Widget) m_frameShell),
468 root = RootWindowOfScreen(XtScreen((Widget) m_frameShell));
469
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) {
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
478 }
479 int xx, yy; unsigned int dummy;
480 XGetGeometry(XtDisplay((Widget) m_frameShell), parent_window, &root,
481 &xx, &yy, &dummy, &dummy, &dummy, &dummy);
482 if (x) *x = xx;
483 if (y) *y = yy;
484}
485
486void wxFrame::DoSetSize(int x, int y, int width, int height, int sizeFlags)
487{
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);
496
497 if (!(height == -1 && width == -1))
498 {
499 PreResize();
500
501 wxSizeEvent sizeEvent(wxSize(width, height), GetId());
502 sizeEvent.SetEventObject(this);
503
504 GetEventHandler()->ProcessEvent(sizeEvent);
505 }
506}
507
508bool wxFrame::Show(bool show)
509{
510 if (!m_frameShell)
511 return wxWindow::Show(show);
512
513 m_visibleStatus = show; /* show-&-hide fix */
514
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;
524}
525
526void wxFrame::Iconize(bool iconize)
527{
528 if (!iconize)
529 Show(TRUE);
530
531 if (m_frameShell)
532 XtVaSetValues((Widget) m_frameShell, XmNiconic, (Boolean)iconize, NULL);
533}
534
535// Equivalent to maximize/restore in Windows
536void wxFrame::Maximize(bool maximize)
537{
538 Show(TRUE);
539
540 if (maximize && m_frameShell)
541 XtVaSetValues((Widget) m_frameShell, XmNiconic, FALSE, NULL);
542}
543
544bool wxFrame::IsIconized() const
545{
546 if (!m_frameShell)
547 return FALSE;
548
549 Boolean iconic;
550 XtVaGetValues((Widget) m_frameShell, XmNiconic, &iconic, NULL);
551 return iconic;
552}
553
554// Is it maximized?
555bool wxFrame::IsMaximized(void) const
556{
557 // No maximizing in Motif (?)
558 return FALSE;
559}
560
561void wxFrame::SetTitle(const wxString& title)
562{
563 if (title == m_title)
564 return;
565
566 m_title = title;
567
568 if (!title.IsNull())
569 XtVaSetValues((Widget) m_frameShell,
570 XmNtitle, (const char*) title,
571 XmNiconName, (const char*) title,
572 NULL);
573}
574
575void wxFrame::SetIcon(const wxIcon& icon)
576{
577 m_icon = icon;
578
579 if (!m_frameShell)
580 return;
581
582 if (!icon.Ok() || !icon.GetPixmap())
583 return;
584
585 XtVaSetValues((Widget) m_frameShell, XtNiconPixmap, icon.GetPixmap(), NULL);
586}
587
588wxStatusBar *wxFrame::OnCreateStatusBar(int number, long style, wxWindowID id,
589 const wxString& name)
590{
591 wxStatusBar *statusBar = NULL;
592
593 statusBar = new wxStatusBar(this, id, wxPoint(0, 0), wxSize(100, 20),
594 style, name);
595
596 // Set the height according to the font and the border size
597 wxClientDC dc(statusBar);
598 dc.SetFont(statusBar->GetFont());
599
600 long x, y;
601 dc.GetTextExtent("X", &x, &y);
602
603 int height = (int)( (y * 1.1) + 2* statusBar->GetBorderY());
604
605 statusBar->SetSize(-1, -1, 100, height);
606
607 statusBar->SetFieldsCount(number);
608 return statusBar;
609}
610
611wxStatusBar* wxFrame::CreateStatusBar(int number, long style, wxWindowID id,
612 const wxString& name)
613{
614 // Calling CreateStatusBar twice is an error.
615 wxCHECK_MSG( m_frameStatusBar == NULL, FALSE,
616 "recreating status bar in wxFrame" );
617
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;
627}
628
629void wxFrame::SetStatusText(const wxString& text, int number)
630{
631 wxCHECK_RET( m_frameStatusBar != NULL, "no statusbar to set text for" );
632
633 m_frameStatusBar->SetStatusText(text, number);
634}
635
636void wxFrame::SetStatusWidths(int n, const int widths_field[])
637{
638 wxCHECK_RET( m_frameStatusBar != NULL, "no statusbar to set widths for" );
639
640 m_frameStatusBar->SetStatusWidths(n, widths_field);
641 PositionStatusBar();
642}
643
644void wxFrame::PositionStatusBar()
645{
646 if (!m_frameStatusBar)
647 return;
648
649 int w, h;
650 GetClientSize(&w, &h);
651 int sw, sh;
652 m_frameStatusBar->GetSize(&sw, &sh);
653
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.
656 m_frameStatusBar->SetSize(0, h, w, sh);
657}
658
659WXWidget wxFrame::GetMenuBarWidget() const
660{
661 if (GetMenuBar())
662 return GetMenuBar()->GetMainWidget();
663 else
664 return (WXWidget) NULL;
665}
666
667void wxFrame::SetMenuBar(wxMenuBar *menuBar)
668{
669 if (!menuBar)
670 {
671 m_frameMenuBar = NULL;
672 return;
673 }
674
675 // Currently can't set it twice
676 // wxASSERT_MSG( (m_frameMenuBar == (wxMenuBar*) NULL), "Cannot set the menubar more than once");
677
678 if (m_frameMenuBar)
679 {
680 m_frameMenuBar->DestroyMenuBar();
681 delete m_frameMenuBar;
682 }
683
684 m_frameMenuBar = menuBar;
685 m_frameMenuBar->CreateMenuBar(this);
686}
687
688void wxFrame::Fit()
689{
690 // Work out max. size
691 wxNode *node = GetChildren().First();
692 int max_width = 0;
693 int max_height = 0;
694 while (node)
695 {
696 // Find a child that's a subwindow, but not a dialog box.
697 wxWindow *win = (wxWindow *)node->Data();
698
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);
706
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();
713 }
714 SetClientSize(max_width, max_height);
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();
722
723 if ( m_frameStatusBar )
724 {
725 wxSysColourChangedEvent event2;
726 event2.SetEventObject( m_frameStatusBar );
727 m_frameStatusBar->ProcessEvent(event2);
728 }
729
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{
738 // if we're using constraints - do use them
739#if wxUSE_CONSTRAINTS
740 if ( GetAutoLayout() ) {
741 Layout();
742 return;
743 }
744#endif
745
746 // do we have _exactly_ one child?
747 wxWindow *child = NULL;
748 for ( wxNode *node = GetChildren().First(); node; node = node->Next() )
749 {
750 wxWindow *win = (wxWindow *)node->Data();
751 if ( !win->IsKindOf(CLASSINFO(wxFrame)) &&
752 !win->IsKindOf(CLASSINFO(wxDialog)) &&
753 (win != GetStatusBar())
754#if wxUSE_TOOLBAR
755 && (win != GetToolBar())
756#endif // wxUSE_TOOLBAR
757 )
758 {
759 if ( child )
760 return; // it's our second subwindow - nothing to do
761 child = win;
762 }
763 }
764
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);
769
770 int x = 0;
771 int y = 0;
772
773 child->SetSize(x, y, clientW, clientH);
774 }
775}
776
777// Default activation behaviour - set the focus for the first child
778// subwindow found.
779void wxFrame::OnActivate(wxActivateEvent& event)
780{
781 for(wxNode *node = GetChildren().First(); node; node = node->Next())
782 {
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 }
791 }
792}
793
794// The default implementation for the close window event.
795// OnClose for backward compatibility.
796
797void wxFrame::OnCloseWindow(wxCloseEvent& event)
798{
799 this->Destroy();
800}
801
802// Destroy the window (delayed, if a managed window)
803bool wxFrame::Destroy()
804{
805 if (!wxPendingDelete.Member(this))
806 wxPendingDelete.Append(this);
807 return TRUE;
808}
809
810// Default menu selection behaviour - display a help string
811void wxFrame::OnMenuHighlight(wxMenuEvent& event)
812{
813 if (GetStatusBar())
814 {
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 }
827 }
828}
829
830wxMenuBar *wxFrame::GetMenuBar() const
831{
832 return m_frameMenuBar;
833}
834
835void wxFrame::Centre(int direction)
836{
837 int display_width, display_height, width, height, x, y;
838 wxDisplaySize(&display_width, &display_height);
839
840 GetSize(&width, &height);
841 GetPosition(&x, &y);
842
843 if (direction & wxHORIZONTAL)
844 x = (int)((display_width - width)/2);
845 if (direction & wxVERTICAL)
846 y = (int)((display_height - height)/2);
847
848 SetSize(x, y, width, height);
849}
850
851// Call this to simulate a menu command
852void wxFrame::Command(int id)
853{
854 ProcessCommand(id);
855}
856
857void wxFrame::ProcessCommand(int id)
858{
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
875 wxEvtHandler* evtHandler = GetEventHandler();
876
877 evtHandler->ProcessEvent(commandEvent);
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);
884#if wxUSE_TOOLBAR
885 if (GetToolBar())
886 {
887 int w, h;
888 GetToolBar()->GetSize(& w, & h);
889
890 if (GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL)
891 {
892 pt.x += w;
893 }
894 else
895 {
896 pt.y += h;
897 }
898 }
899#endif // wxUSE_TOOLBAR
900
901 return pt;
902}
903
904void wxFrame::ScreenToClient(int *x, int *y) const
905{
906 wxWindow::ScreenToClient(x, y);
907
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;
924
925 wxWindow::ClientToScreen(x, y);
926}
927
928#if wxUSE_TOOLBAR
929wxToolBar* wxFrame::CreateToolBar(long style, wxWindowID id, const wxString& name)
930{
931 wxCHECK_MSG( m_frameToolBar == NULL, FALSE,
932 "recreating toolbar in wxFrame" );
933
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{
949 return new wxToolBar(this, id, wxPoint(0, 0), wxSize(100, 24), style, name);
950}
951
952void wxFrame::SetToolBar(wxToolBar *toolbar)
953{
954 m_frameToolBar = toolbar;
955}
956
957wxToolBar *wxFrame::GetToolBar() const
958{
959 return m_frameToolBar;
960}
961
962void wxFrame::PositionToolBar()
963{
964 int cw, ch;
965
966 GetClientSize(& cw, &ch);
967
968 if (GetToolBar())
969 {
970 int tw, th;
971 GetToolBar()->GetSize(& tw, & th);
972
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.
978 GetToolBar()->SetSize(0, 0, tw, ch + th, wxSIZE_NO_ADJUSTMENTS);
979 }
980 else
981 {
982 // Use the 'real' position
983 GetToolBar()->SetSize(0, 0, cw, th, wxSIZE_NO_ADJUSTMENTS);
984 }
985 }
986}
987#endif // wxUSE_TOOLBAR
988
989void wxFrame::CaptureMouse()
990{
991 if (m_winCaptured)
992 return;
993
994 if (GetMainWidget())
995 XtAddGrab((Widget) m_frameShell, TRUE, FALSE);
996 m_winCaptured = TRUE;
997}
998
999void wxFrame::ReleaseMouse()
1000{
1001 if (!m_winCaptured)
1002 return;
1003
1004 if (GetMainWidget())
1005 XtRemoveGrab((Widget) m_frameShell);
1006 m_winCaptured = FALSE;
1007}
1008
1009void wxFrame::Raise(void)
1010{
1011 Window parent_window = XtWindow((Widget) m_frameShell),
1012 next_parent = XtWindow((Widget) m_frameShell),
1013 root = RootWindowOfScreen(XtScreen((Widget) m_frameShell));
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) {
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
1022 }
1023 XRaiseWindow(XtDisplay((Widget) m_frameShell), parent_window);
1024}
1025
1026void wxFrame::Lower(void)
1027{
1028 Window parent_window = XtWindow((Widget) m_frameShell),
1029 next_parent = XtWindow((Widget) m_frameShell),
1030 root = RootWindowOfScreen(XtScreen((Widget) m_frameShell));
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) {
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
1039 }
1040 XLowerWindow(XtDisplay((Widget) m_frameShell), parent_window);
1041}
1042
1043void wxFrameFocusProc(Widget workArea, XtPointer clientData,
1044 XmAnyCallbackStruct *cbs)
1045{
1046 // wxDebugMsg("focus proc from frame %ld\n",(long)frame);
1047 // TODO
1048 // wxFrame *frame = (wxFrame *)clientData;
1049 // frame->GetEventHandler()->OnSetFocus();
1050}
1051
1052/* MATTEW: Used to insure that hide-&-show within an event cycle works */
1053static void wxFrameMapProc(Widget frameShell, XtPointer clientData,
1054 XCrossingEvent * event)
1055{
1056 wxFrame *frame = (wxFrame *)wxGetWindowFromTable((Widget)clientData);
1057
1058 if (frame) {
1059 XEvent *e = (XEvent *)event;
1060
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);
1074 }
1075}
1076
1077//// Motif-specific
1078bool wxFrame::PreResize()
1079{
1080#if wxUSE_TOOLBAR
1081 PositionToolBar();
1082#endif // wxUSE_TOOLBAR
1083 PositionStatusBar();
1084 return TRUE;
1085}
1086
1087WXWidget wxFrame::GetClientWidget() const
1088{
1089 return m_clientArea;
1090}
1091
1092void wxFrame::ChangeFont(bool keepOriginalSize)
1093{
1094 // TODO
1095}
1096
1097void wxFrame::ChangeBackgroundColour()
1098{
1099 if (GetClientWidget())
1100 DoChangeBackgroundColour(GetClientWidget(), m_backgroundColour);
1101}
1102
1103void wxFrame::ChangeForegroundColour()
1104{
1105 if (GetClientWidget())
1106 DoChangeForegroundColour(GetClientWidget(), m_foregroundColour);
1107}
1108
1109void wxCloseFrameCallback(Widget widget, XtPointer client_data, XmAnyCallbackStruct *cbs)
1110{
1111 wxFrame *frame = (wxFrame *)client_data;
1112
1113 wxCloseEvent closeEvent(wxEVT_CLOSE_WINDOW, frame->GetId());
1114 closeEvent.SetEventObject(frame);
1115
1116 // May delete the frame (with delayed deletion)
1117 frame->GetEventHandler()->ProcessEvent(closeEvent);
1118}
1119