]> git.saurik.com Git - wxWidgets.git/blob - src/motif/frame.cpp
Added an #ifdef
[wxWidgets.git] / src / motif / frame.cpp
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
53 extern wxHashTable *wxWidgetHashTable;
54
55 void wxCloseFrameCallback(Widget, XtPointer, XmAnyCallbackStruct *cbs);
56 void wxFrameFocusProc(Widget workArea, XtPointer clientData,
57 XmAnyCallbackStruct *cbs);
58 static void wxFrameMapProc(Widget frameShell, XtPointer clientData,
59 XCrossingEvent * event);
60
61 extern wxList wxModelessWindows;
62 extern wxList wxPendingDelete;
63
64 // TODO: this should be tidied so that any frame can be the
65 // top frame
66 static bool wxTopLevelUsed = FALSE;
67
68 #if !USE_SHARED_LIBRARY
69 BEGIN_EVENT_TABLE(wxFrame, wxWindow)
70 EVT_SIZE(wxFrame::OnSize)
71 EVT_ACTIVATE(wxFrame::OnActivate)
72 EVT_MENU_HIGHLIGHT_ALL(wxFrame::OnMenuHighlight)
73 EVT_SYS_COLOUR_CHANGED(wxFrame::OnSysColourChanged)
74 EVT_IDLE(wxFrame::OnIdle)
75 EVT_CLOSE(wxFrame::OnCloseWindow)
76 END_EVENT_TABLE()
77
78 IMPLEMENT_DYNAMIC_CLASS(wxFrame, wxWindow)
79 #endif
80
81 #if wxUSE_NATIVE_STATUSBAR
82 bool wxFrame::m_useNativeStatusBar = TRUE;
83 #else
84 bool wxFrame::m_useNativeStatusBar = FALSE;
85 #endif
86
87 wxFrame::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
108 bool 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
293 wxFrame::~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.
369 void 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)
418 void 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
457 void 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
464 void 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
486 void 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
508 bool 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
526 void 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
536 void wxFrame::Maximize(bool maximize)
537 {
538 Show(TRUE);
539
540 if (maximize && m_frameShell)
541 XtVaSetValues((Widget) m_frameShell, XmNiconic, FALSE, NULL);
542 }
543
544 bool 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?
555 bool wxFrame::IsMaximized(void) const
556 {
557 // No maximizing in Motif (?)
558 return FALSE;
559 }
560
561 void 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
575 void 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
588 wxStatusBar *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
611 wxStatusBar* 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
629 void 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
636 void 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
644 void 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
659 WXWidget wxFrame::GetMenuBarWidget() const
660 {
661 if (GetMenuBar())
662 return GetMenuBar()->GetMainWidget();
663 else
664 return (WXWidget) NULL;
665 }
666
667 void 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
688 void 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.
718 void 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
736 void 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.
779 void 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
797 void wxFrame::OnCloseWindow(wxCloseEvent& event)
798 {
799 this->Destroy();
800 }
801
802 // Destroy the window (delayed, if a managed window)
803 bool 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
811 void 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
830 wxMenuBar *wxFrame::GetMenuBar() const
831 {
832 return m_frameMenuBar;
833 }
834
835 void 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
852 void wxFrame::Command(int id)
853 {
854 ProcessCommand(id);
855 }
856
857 void 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
881 wxPoint 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
904 void 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
916 void 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
929 wxToolBar* 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
947 wxToolBar* 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
952 void wxFrame::SetToolBar(wxToolBar *toolbar)
953 {
954 m_frameToolBar = toolbar;
955 }
956
957 wxToolBar *wxFrame::GetToolBar() const
958 {
959 return m_frameToolBar;
960 }
961
962 void 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
989 void 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
999 void wxFrame::ReleaseMouse()
1000 {
1001 if (!m_winCaptured)
1002 return;
1003
1004 if (GetMainWidget())
1005 XtRemoveGrab((Widget) m_frameShell);
1006 m_winCaptured = FALSE;
1007 }
1008
1009 void 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
1026 void 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
1043 void 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 */
1053 static 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
1078 bool wxFrame::PreResize()
1079 {
1080 #if wxUSE_TOOLBAR
1081 PositionToolBar();
1082 #endif // wxUSE_TOOLBAR
1083 PositionStatusBar();
1084 return TRUE;
1085 }
1086
1087 WXWidget wxFrame::GetClientWidget() const
1088 {
1089 return m_clientArea;
1090 }
1091
1092 void wxFrame::ChangeFont(bool keepOriginalSize)
1093 {
1094 // TODO
1095 }
1096
1097 void wxFrame::ChangeBackgroundColour()
1098 {
1099 if (GetClientWidget())
1100 DoChangeBackgroundColour(GetClientWidget(), m_backgroundColour);
1101 }
1102
1103 void wxFrame::ChangeForegroundColour()
1104 {
1105 if (GetClientWidget())
1106 DoChangeForegroundColour(GetClientWidget(), m_foregroundColour);
1107 }
1108
1109 void 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