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