]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/motif/mdi.cpp
fix bug in Borland (bcc32 really hates ?)
[wxWidgets.git] / src / motif / mdi.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: mdi.cpp
3// Purpose: MDI classes
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 "mdi.h"
14#endif
15
16#ifdef __VMS
17#define XtDisplay XTDISPLAY
18#define XtWindow XTWINDOW
19#endif
20
21#include "wx/tab.h"
22#include "wx/mdi.h"
23#include "wx/menu.h"
24#include "wx/settings.h"
25#include "wx/icon.h"
26
27#ifdef __VMS__
28#pragma message disable nosimpint
29#endif
30#include <Xm/Xm.h>
31#include <Xm/BulletinB.h>
32#include <Xm/Form.h>
33#include <Xm/MainW.h>
34#include <Xm/RowColumn.h>
35#include <Xm/CascadeBG.h>
36#include <Xm/Text.h>
37#include <Xm/PushBG.h>
38#include <Xm/AtomMgr.h>
39#include <Xm/Protocols.h>
40#ifdef __VMS__
41#pragma message enable nosimpint
42#endif
43
44#include "wx/motif/private.h"
45
46extern wxList wxModelessWindows;
47
48// Implemented in frame.cpp
49extern void wxFrameFocusProc(Widget workArea, XtPointer clientData,
50 XmAnyCallbackStruct *cbs);
51
52#define wxID_NOTEBOOK_CLIENT_AREA wxID_HIGHEST + 100
53
54IMPLEMENT_DYNAMIC_CLASS(wxMDIParentFrame, wxFrame)
55IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame, wxFrame)
56IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow, wxNotebook)
57
58BEGIN_EVENT_TABLE(wxMDIParentFrame, wxFrame)
59 EVT_SIZE(wxMDIParentFrame::OnSize)
60 EVT_ACTIVATE(wxMDIParentFrame::OnActivate)
61 EVT_SYS_COLOUR_CHANGED(wxMDIParentFrame::OnSysColourChanged)
62 EVT_MENU_HIGHLIGHT_ALL(wxMDIParentFrame::OnMenuHighlight)
63END_EVENT_TABLE()
64
65BEGIN_EVENT_TABLE(wxMDIClientWindow, wxNotebook)
66 EVT_SCROLL(wxMDIClientWindow::OnScroll)
67 EVT_NOTEBOOK_PAGE_CHANGED(wxID_NOTEBOOK_CLIENT_AREA, wxMDIClientWindow::OnPageChanged)
68END_EVENT_TABLE()
69
70
71// Parent frame
72
73wxMDIParentFrame::wxMDIParentFrame()
74{
75 m_clientWindow = (wxMDIClientWindow*) NULL;
76 m_activeChild = (wxMDIChildFrame*) NULL;
77 m_activeMenuBar = (wxMenuBar*) NULL;
78}
79
80bool wxMDIParentFrame::Create(wxWindow *parent,
81 wxWindowID id,
82 const wxString& title,
83 const wxPoint& pos,
84 const wxSize& size,
85 long style,
86 const wxString& name)
87{
88 m_clientWindow = (wxMDIClientWindow*) NULL;
89 m_activeChild = (wxMDIChildFrame*) NULL;
90 m_activeMenuBar = (wxMenuBar*) NULL;
91
92 bool success = wxFrame::Create(parent, id, title, pos, size, style, name);
93 if (success)
94 {
95 // TODO: app cannot override OnCreateClient since
96 // wxMDIParentFrame::OnCreateClient will still be called
97 // (we're in the constructor). How to resolve?
98
99 m_clientWindow = OnCreateClient();
100
101 // Uses own style for client style
102 m_clientWindow->CreateClient(this, GetWindowStyleFlag());
103
104 int w, h;
105 GetClientSize(& w, & h);
106 m_clientWindow->SetSize(0, 0, w, h);
107 return TRUE;
108 }
109 else
110 return FALSE;
111}
112
113wxMDIParentFrame::~wxMDIParentFrame()
114{
115 // Make sure we delete the client window last of all
116 RemoveChild(m_clientWindow);
117
118 DestroyChildren();
119
120 delete m_clientWindow;
121 m_clientWindow = NULL;
122}
123
124void wxMDIParentFrame::SetMenuBar(wxMenuBar *menu_bar)
125{
126 m_frameMenuBar = menu_bar;
127
128 SetChildMenuBar((wxMDIChildFrame*) NULL);
129}
130
131void wxMDIParentFrame::OnSize(wxSizeEvent& WXUNUSED(event))
132{
133#if wxUSE_CONSTRAINTS
134 if (GetAutoLayout())
135 Layout();
136#endif
137 int x = 0;
138 int y = 0;
139 int width, height;
140 GetClientSize(&width, &height);
141
142 if ( GetClientWindow() )
143 GetClientWindow()->SetSize(x, y, width, height);
144}
145
146void wxMDIParentFrame::DoGetClientSize(int *width, int *height) const
147{
148 wxFrame::DoGetClientSize(width, height);
149}
150
151void wxMDIParentFrame::OnActivate(wxActivateEvent& WXUNUSED(event))
152{
153 // Do nothing
154}
155
156// Returns the active MDI child window
157wxMDIChildFrame *wxMDIParentFrame::GetActiveChild() const
158{
159 return m_activeChild;
160}
161
162// Create the client window class (don't Create the window,
163// just return a new class)
164wxMDIClientWindow *wxMDIParentFrame::OnCreateClient()
165{
166 return new wxMDIClientWindow ;
167}
168
169// Set the child's menu into the parent frame
170void wxMDIParentFrame::SetChildMenuBar(wxMDIChildFrame* child)
171{
172 wxMenuBar* oldMenuBar = m_activeMenuBar;
173
174 if (child == (wxMDIChildFrame*) NULL) // No child: use parent frame
175 {
176 if (GetMenuBar() && (GetMenuBar() != m_activeMenuBar))
177 {
178 // if (m_activeMenuBar)
179 // m_activeMenuBar->DestroyMenuBar();
180
181 m_activeMenuBar = GetMenuBar();
182 m_activeMenuBar->CreateMenuBar(this);
183 /*
184 if (oldMenuBar && XtIsManaged((Widget) oldMenuBar->GetMainWidget()))
185 XtUnmanageChild((Widget) oldMenuBar->GetMainWidget());
186 */
187 if (oldMenuBar && oldMenuBar->GetMainWidget())
188 XtUnmapWidget((Widget) oldMenuBar->GetMainWidget());
189
190 }
191 }
192 else if (child->GetMenuBar() == (wxMenuBar*) NULL) // No child menu bar: use parent frame
193 {
194 if (GetMenuBar() && (GetMenuBar() != m_activeMenuBar))
195 {
196 // if (m_activeMenuBar)
197 // m_activeMenuBar->DestroyMenuBar();
198 m_activeMenuBar = GetMenuBar();
199 m_activeMenuBar->CreateMenuBar(this);
200 /*
201 if (oldMenuBar && XtIsManaged((Widget) oldMenuBar->GetMainWidget()))
202 XtUnmanageChild((Widget) oldMenuBar->GetMainWidget());
203 */
204 if (oldMenuBar && oldMenuBar->GetMainWidget())
205 XtUnmapWidget((Widget) oldMenuBar->GetMainWidget());
206 }
207 }
208 else // The child has a menubar
209 {
210 if (child->GetMenuBar() != m_activeMenuBar)
211 {
212 // if (m_activeMenuBar)
213 // m_activeMenuBar->DestroyMenuBar();
214
215 m_activeMenuBar = child->GetMenuBar();
216 m_activeMenuBar->CreateMenuBar(this);
217 /*
218 if (oldMenuBar && XtIsManaged((Widget) oldMenuBar->GetMainWidget()))
219 XtUnmanageChild((Widget) oldMenuBar->GetMainWidget());
220 */
221 if (oldMenuBar && oldMenuBar->GetMainWidget())
222 XtUnmapWidget((Widget) oldMenuBar->GetMainWidget());
223 }
224 }
225}
226
227// Redirect events to active child first
228bool wxMDIParentFrame::ProcessEvent(wxEvent& event)
229{
230 // Stops the same event being processed repeatedly
231 static wxEventType inEvent = wxEVT_NULL;
232 if (inEvent == event.GetEventType())
233 return FALSE;
234
235 inEvent = event.GetEventType();
236
237 bool res = FALSE;
238 if (m_activeChild && event.IsKindOf(CLASSINFO(wxCommandEvent)))
239 {
240 res = m_activeChild->GetEventHandler()->ProcessEvent(event);
241 }
242
243 if (!res)
244 res = GetEventHandler()->wxEvtHandler::ProcessEvent(event);
245
246 inEvent = wxEVT_NULL;
247
248 return res;
249}
250
251void wxMDIParentFrame::DoSetSize(int x, int y,
252 int width, int height,
253 int sizeFlags)
254{
255 wxWindow::DoSetSize(x, y, width, height, sizeFlags);
256}
257
258void wxMDIParentFrame::DoSetClientSize(int width, int height)
259{
260 wxWindow::DoSetClientSize(width, height);
261}
262
263// Responds to colour changes, and passes event on to children.
264void wxMDIParentFrame::OnSysColourChanged(wxSysColourChangedEvent& event)
265{
266 // TODO
267
268 // Propagate the event to the non-top-level children
269 wxFrame::OnSysColourChanged(event);
270}
271
272// MDI operations
273void wxMDIParentFrame::Cascade()
274{
275 // TODO
276}
277
278void wxMDIParentFrame::Tile()
279{
280 // TODO
281}
282
283void wxMDIParentFrame::ArrangeIcons()
284{
285 // TODO
286}
287
288void wxMDIParentFrame::ActivateNext()
289{
290 // TODO
291}
292
293void wxMDIParentFrame::ActivatePrevious()
294{
295 // TODO
296}
297
298// Default menu selection behaviour - display a help string
299void wxMDIParentFrame::OnMenuHighlight(wxMenuEvent& event)
300{
301 if (GetStatusBar())
302 {
303 if (event.GetMenuId() == -1)
304 SetStatusText("");
305 else
306 {
307 wxMenuBar *menuBar = (wxMenuBar*) NULL;
308 if (GetActiveChild())
309 menuBar = GetActiveChild()->GetMenuBar();
310 else
311 menuBar = GetMenuBar();
312 if (menuBar)
313 {
314 wxString helpString(menuBar->GetHelpString(event.GetMenuId()));
315 if (helpString != "")
316 SetStatusText(helpString);
317 }
318 }
319 }
320}
321
322// Child frame
323
324wxMDIChildFrame::wxMDIChildFrame()
325{
326 m_mdiParentFrame = (wxMDIParentFrame*) NULL;
327}
328
329bool wxMDIChildFrame::Create(wxMDIParentFrame *parent,
330 wxWindowID id,
331 const wxString& title,
332 const wxPoint& pos,
333 const wxSize& size,
334 long style,
335 const wxString& name)
336{
337 SetName(name);
338 SetWindowStyleFlag(style);
339
340 m_backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE);
341 m_foregroundColour = *wxBLACK;
342 m_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
343
344 if ( id > -1 )
345 m_windowId = id;
346 else
347 m_windowId = (int)NewControlId();
348
349 wxMDIClientWindow* clientWindow = parent->GetClientWindow();
350
351 wxASSERT_MSG( (clientWindow != (wxWindow*) NULL), "Missing MDI client window.");
352
353 if (clientWindow) clientWindow->AddChild(this);
354
355 SetMDIParentFrame(parent);
356
357 int width = size.x;
358 int height = size.y;
359 if (width == -1)
360 width = 200; // TODO: give reasonable default
361 if (height == -1)
362 height = 200; // TODO: give reasonable default
363
364 // We're deactivating the old child
365 wxMDIChildFrame* oldActiveChild = parent->GetActiveChild();
366 if (oldActiveChild)
367 {
368 wxActivateEvent event(wxEVT_ACTIVATE, FALSE, oldActiveChild->GetId());
369 event.SetEventObject( oldActiveChild );
370 oldActiveChild->GetEventHandler()->ProcessEvent(event);
371 }
372
373 // This is the currently active child
374 parent->SetActiveChild((wxMDIChildFrame*) this);
375
376 // This time we'll try a bog-standard bulletin board for
377 // the 'frame'. A main window doesn't seem to work.
378
379 m_mainWidget = (WXWidget) XtVaCreateWidget("client",
380 xmBulletinBoardWidgetClass, (Widget) clientWindow->GetTopWidget(),
381 XmNmarginWidth, 0,
382 XmNmarginHeight, 0,
383 /*
384 XmNrightAttachment, XmATTACH_FORM,
385 XmNleftAttachment, XmATTACH_FORM,
386 XmNtopAttachment, XmATTACH_FORM,
387 XmNbottomAttachment, XmATTACH_FORM,
388 */
389 XmNresizePolicy, XmRESIZE_NONE,
390 NULL);
391
392 XtAddEventHandler((Widget) m_mainWidget, ExposureMask,FALSE,
393 wxUniversalRepaintProc, (XtPointer) this);
394
395 SetCanAddEventHandler(TRUE);
396 AttachWidget (parent, m_mainWidget, (WXWidget) NULL, pos.x, pos.y, size.x, size.y);
397
398 ChangeBackgroundColour();
399
400 XtManageChild((Widget) m_mainWidget);
401
402 SetTitle(title);
403
404 clientWindow->AddPage(this, title, TRUE);
405 clientWindow->Refresh();
406
407 // Positions the toolbar and status bar -- but we don't have any.
408 // PreResize();
409
410 wxModelessWindows.Append(this);
411 return TRUE;
412}
413
414
415wxMDIChildFrame::~wxMDIChildFrame()
416{
417 if (m_mainWidget)
418 XtRemoveEventHandler((Widget) m_mainWidget, ExposureMask,FALSE,
419 wxUniversalRepaintProc, (XtPointer) this);
420
421 if (GetMDIParentFrame())
422 {
423 wxMDIParentFrame* parentFrame = GetMDIParentFrame();
424
425 if (parentFrame->GetActiveChild() == this)
426 parentFrame->SetActiveChild((wxMDIChildFrame*) NULL);
427 wxMDIClientWindow* clientWindow = parentFrame->GetClientWindow();
428
429 // Remove page if still there
430 if (clientWindow->RemovePage(this))
431 clientWindow->Refresh();
432
433 // Set the selection to the first remaining page
434 if (clientWindow->GetPageCount() > 0)
435 {
436 wxMDIChildFrame* child = (wxMDIChildFrame*) clientWindow->GetPage(0);
437 parentFrame->SetActiveChild(child);
438 parentFrame->SetChildMenuBar(child);
439 }
440 else
441 {
442 parentFrame->SetActiveChild((wxMDIChildFrame*) NULL);
443 parentFrame->SetChildMenuBar((wxMDIChildFrame*) NULL);
444 }
445 }
446}
447
448#if 0
449// Implementation: intercept and act upon raise and lower commands.
450void wxMDIChildFrame::OnRaise()
451{
452 wxMDIParentFrame* parentFrame = (wxMDIParentFrame*) GetParent() ;
453 wxMDIChildFrame* oldActiveChild = parentFrame->GetActiveChild();
454 parentFrame->SetActiveChild(this);
455
456 if (oldActiveChild)
457 {
458 wxActivateEvent event(wxEVT_ACTIVATE, FALSE, oldActiveChild->GetId());
459 event.SetEventObject( oldActiveChild );
460 oldActiveChild->GetEventHandler()->ProcessEvent(event);
461 }
462
463 wxActivateEvent event(wxEVT_ACTIVATE, TRUE, this->GetId());
464 event.SetEventObject( this );
465 this->GetEventHandler()->ProcessEvent(event);
466}
467
468void wxMDIChildFrame::OnLower()
469{
470 wxMDIParentFrame* parentFrame = (wxMDIParentFrame*) GetParent() ;
471 wxMDIChildFrame* oldActiveChild = parentFrame->GetActiveChild();
472
473 if (oldActiveChild == this)
474 {
475 wxActivateEvent event(wxEVT_ACTIVATE, FALSE, oldActiveChild->GetId());
476 event.SetEventObject( oldActiveChild );
477 oldActiveChild->GetEventHandler()->ProcessEvent(event);
478 }
479 // TODO: unfortunately we don't now know which is the top-most child,
480 // so make the active child NULL.
481 parentFrame->SetActiveChild((wxMDIChildFrame*) NULL);
482}
483#endif
484
485// Set the client size (i.e. leave the calculation of borders etc.
486// to wxWindows)
487void wxMDIChildFrame::DoSetClientSize(int width, int height)
488{
489 wxWindow::DoSetClientSize(width, height);
490}
491
492void wxMDIChildFrame::DoGetClientSize(int* width, int* height) const
493{
494 wxWindow::DoGetSize(width, height);
495}
496
497void wxMDIChildFrame::DoSetSize(int x, int y, int width, int height, int sizeFlags)
498{
499 wxWindow::DoSetSize(x, y, width, height, sizeFlags);
500}
501
502void wxMDIChildFrame::DoGetSize(int* width, int* height) const
503{
504 wxWindow::DoGetSize(width, height);
505}
506
507void wxMDIChildFrame::DoGetPosition(int *x, int *y) const
508{
509 wxWindow::DoGetPosition(x, y);
510}
511
512bool wxMDIChildFrame::Show(bool show)
513{
514 SetVisibleStatus( show );
515 return wxWindow::Show(show);
516}
517
518void wxMDIChildFrame::SetMenuBar(wxMenuBar *menuBar)
519{
520 // Don't create the underlying menubar yet; need to recreate
521 // it every time the child is activated.
522 m_frameMenuBar = menuBar;
523
524 // We make the assumption that if you're setting the menubar,
525 // this is the currently active child.
526 GetMDIParentFrame()->SetChildMenuBar(this);
527}
528
529// Set icon
530void wxMDIChildFrame::SetIcon(const wxIcon& icon)
531{
532 m_icons = wxIconBundle( icon );
533
534 if (icon.Ok())
535 {
536 // Not appropriate since there are no icons in
537 // a tabbed window
538 }
539}
540
541void wxMDIChildFrame::SetIcons(const wxIconBundle& icons)
542{
543 m_icons = icons;
544}
545
546void wxMDIChildFrame::SetTitle(const wxString& title)
547{
548 wxTopLevelWindow::SetTitle( title );
549 wxMDIClientWindow* clientWindow = GetMDIParentFrame()->GetClientWindow();
550 int pageNo = clientWindow->FindPagePosition(this);
551 if (pageNo > -1)
552 clientWindow->SetPageText(pageNo, title);
553}
554
555// MDI operations
556void wxMDIChildFrame::Maximize()
557{
558 // TODO
559}
560
561void wxMDIChildFrame::Iconize(bool WXUNUSED(iconize))
562{
563 // TODO
564}
565
566bool wxMDIChildFrame::IsIconized() const
567{
568 return FALSE;
569}
570
571// Is it maximized? Always maximized under Motif, using the
572// tabbed MDI implementation.
573bool wxMDIChildFrame::IsMaximized(void) const
574{
575 return TRUE;
576}
577
578void wxMDIChildFrame::Restore()
579{
580 // TODO
581}
582
583void wxMDIChildFrame::Activate()
584{
585 // TODO
586}
587
588void wxMDIChildFrame::CaptureMouse()
589{
590 wxWindow::CaptureMouse();
591}
592
593void wxMDIChildFrame::ReleaseMouse()
594{
595 wxWindow::ReleaseMouse();
596}
597
598void wxMDIChildFrame::Raise()
599{
600 wxWindow::Raise();
601}
602
603void wxMDIChildFrame::Lower(void)
604{
605 wxWindow::Raise();
606}
607
608void wxMDIChildFrame::SetSizeHints(int WXUNUSED(minW), int WXUNUSED(minH), int WXUNUSED(maxW), int WXUNUSED(maxH), int WXUNUSED(incW), int WXUNUSED(incH))
609{
610}
611
612// Client window
613
614wxMDIClientWindow::wxMDIClientWindow()
615{
616}
617
618wxMDIClientWindow::~wxMDIClientWindow()
619{
620 // By the time this destructor is called, the child frames will have been
621 // deleted and removed from the notebook/client window.
622 DestroyChildren();
623
624 m_mainWidget = (WXWidget) 0;
625}
626
627bool wxMDIClientWindow::CreateClient(wxMDIParentFrame *parent, long style)
628{
629 SetWindowStyleFlag(style);
630
631 // m_windowParent = parent;
632 // m_backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE);
633
634 bool success = wxNotebook::Create(parent, wxID_NOTEBOOK_CLIENT_AREA, wxPoint(0, 0), wxSize(100, 100), 0);
635 if (success)
636 {
637 wxFont font(10, wxSWISS, wxNORMAL, wxNORMAL);
638 wxFont selFont(10, wxSWISS, wxNORMAL, wxBOLD);
639 GetTabView()->SetTabFont(font);
640 GetTabView()->SetSelectedTabFont(selFont);
641 GetTabView()->SetTabSize(120, 18);
642 GetTabView()->SetTabSelectionHeight(20);
643 return TRUE;
644 }
645 else
646 return FALSE;
647}
648
649void wxMDIClientWindow::DoSetSize(int x, int y, int width, int height, int sizeFlags)
650{
651 wxWindow::DoSetSize(x, y, width, height, sizeFlags);
652}
653
654void wxMDIClientWindow::DoSetClientSize(int width, int height)
655{
656 wxWindow::DoSetClientSize(width, height);
657}
658
659void wxMDIClientWindow::DoGetClientSize(int *width, int *height) const
660{
661 wxWindow::DoGetClientSize(width, height);
662}
663
664void wxMDIClientWindow::DoGetSize(int *width, int *height) const
665{
666 wxWindow::DoGetSize(width, height);
667}
668
669void wxMDIClientWindow::DoGetPosition(int *x, int *y) const
670{
671 wxWindow::DoGetPosition(x, y);
672}
673
674void wxMDIClientWindow::OnScroll(wxScrollEvent& event)
675{
676 // Default(); // Default processing: OBSOLETE FUNCTION
677 event.Skip();
678}
679
680void wxMDIClientWindow::OnPageChanged(wxNotebookEvent& event)
681{
682 // Notify child that it has been activated
683 if (event.GetOldSelection() != -1)
684 {
685 wxMDIChildFrame* oldChild = (wxMDIChildFrame*) GetPage(event.GetOldSelection());
686 if (oldChild)
687 {
688 wxActivateEvent event(wxEVT_ACTIVATE, FALSE, oldChild->GetId());
689 event.SetEventObject( oldChild );
690 oldChild->GetEventHandler()->ProcessEvent(event);
691 }
692 }
693 if (event.GetSelection() != -1)
694 {
695 wxMDIChildFrame* activeChild = (wxMDIChildFrame*) GetPage(event.GetSelection());
696 if (activeChild)
697 {
698 wxActivateEvent event(wxEVT_ACTIVATE, TRUE, activeChild->GetId());
699 event.SetEventObject( activeChild );
700 activeChild->GetEventHandler()->ProcessEvent(event);
701
702 if (activeChild->GetMDIParentFrame())
703 {
704 activeChild->GetMDIParentFrame()->SetActiveChild(activeChild);
705 activeChild->GetMDIParentFrame()->SetChildMenuBar(activeChild);
706 }
707 }
708 }
709 event.Skip();
710}