1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: MDI classes
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "mdi.h"
18 #include "wx/settings.h"
21 #include <Xm/BulletinB.h>
24 #include <Xm/RowColumn.h>
25 #include <Xm/CascadeBG.h>
27 #include <Xm/PushBG.h>
28 #include <Xm/AtomMgr.h>
29 #include <Xm/Protocols.h>
31 #include "mdi/lib/XsMDICanvas.h"
32 #include "mdi/lib/XsMotifWindow.h"
34 #include "wx/motif/private.h"
36 extern wxList wxModelessWindows
;
38 // Implemented in frame.cpp
39 extern void wxFrameFocusProc(Widget workArea
, XtPointer clientData
,
40 XmAnyCallbackStruct
*cbs
);
42 #if !USE_SHARED_LIBRARY
43 IMPLEMENT_DYNAMIC_CLASS(wxMDIParentFrame
, wxFrame
)
44 IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame
, wxFrame
)
45 IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow
, wxWindow
)
47 BEGIN_EVENT_TABLE(wxMDIParentFrame
, wxFrame
)
48 EVT_SIZE(wxMDIParentFrame::OnSize
)
49 EVT_ACTIVATE(wxMDIParentFrame::OnActivate
)
50 EVT_SYS_COLOUR_CHANGED(wxMDIParentFrame::OnSysColourChanged
)
53 BEGIN_EVENT_TABLE(wxMDIClientWindow
, wxWindow
)
54 EVT_SCROLL(wxMDIClientWindow::OnScroll
)
60 static void _doNothingCallback (Widget, XtPointer, XtPointer)
65 // wxXsMDIWindow represents the MDI child frame, as far as the MDI
66 // package is concerned.
67 // TODO: override raise, so we can tell which is the 'active'
68 // (raised) window. We can also use it to send wxActivateEvents,
69 // and switching menubars when we make the child frame menubar
70 // appear on the parent frame.
72 // Note: see XsMotifWindow.C, _XsMotifMenu::_processItem for
73 // where user menu selections are processed.
74 // When Close is selected, _win->close() is called.
76 class wxXsMDIWindow
: public XsMotifWindow
79 wxMDIChildFrame
* m_childFrame
;
81 wxXsMDIWindow(const char* name
, wxMDIChildFrame
* frame
): XsMotifWindow(name
)
85 virtual void setSize(Dimension w
, Dimension h
)
87 XsMotifWindow::setSize(w
, h
);
89 // Generate wxSizeEvent here, I think. Maybe also restore, maximize
90 // Probably don't need to generate size event here since work area
92 wxSizeEvent
event(wxSize(w
, h
), m_childFrame
->GetId());
93 event
.SetEventObject(m_childFrame
);
94 m_childFrame
->ProcessEvent(event
);
98 XsMotifWindow::close();
99 m_childFrame
->Close();
101 virtual void _buildClientArea(Widget parent
)
103 m_childFrame
->BuildClientArea((WXWidget
) parent
);
105 // Code from MDI sample
107 assert (parent
!= 0);
113 // Create a main window with some dummy menus
115 Widget mainW
= XtVaCreateWidget ("mainWin", xmMainWindowWidgetClass
, parent
,
116 XmNtopAttachment
, XmATTACH_FORM
, XmNbottomAttachment
, XmATTACH_FORM
,
117 XmNleftAttachment
, XmATTACH_FORM
, XmNrightAttachment
, XmATTACH_FORM
,
122 Widget menuBar
= XmCreateMenuBar (mainW
, "menuBar", NULL
, 0);
124 // Create the "file" menu
126 pulldown
= XmCreatePulldownMenu (menuBar
, "pulldown", NULL
, 0);
127 cascade
= XtVaCreateManagedWidget ("fileMenu", xmCascadeButtonGadgetClass
,
128 menuBar
, XmNsubMenuId
, pulldown
, NULL
);
130 button
= XtVaCreateManagedWidget ("openMenuItem", xmPushButtonGadgetClass
,
132 XtAddCallback (button
, XmNactivateCallback
, _doNothingCallback
, (XtPointer
)this);
134 button
= XtVaCreateManagedWidget ("newMenuItem", xmPushButtonGadgetClass
,
136 // XtAddCallback (button, XmNactivateCallback, _newWindowCallback, (XtPointer)this);
138 // Create the "edit" menu
140 pulldown
= XmCreatePulldownMenu (menuBar
, "pulldown", NULL
, 0);
141 cascade
= XtVaCreateManagedWidget ("editMenu", xmCascadeButtonGadgetClass
,
142 menuBar
, XmNsubMenuId
, pulldown
, NULL
);
144 button
= XtVaCreateManagedWidget ("cutMenuItem", xmPushButtonGadgetClass
,
146 XtAddCallback (button
, XmNactivateCallback
, _doNothingCallback
, (XtPointer
)this);
148 button
= XtVaCreateManagedWidget ("copyMenuItem", xmPushButtonGadgetClass
,
150 XtAddCallback (button
, XmNactivateCallback
, _doNothingCallback
, (XtPointer
)this);
152 button
= XtVaCreateManagedWidget ("pasteMenuItem", xmPushButtonGadgetClass
,
154 XtAddCallback (button
, XmNactivateCallback
, _doNothingCallback
, (XtPointer
)this);
156 // Create the help menu
158 pulldown
= XmCreatePulldownMenu (menuBar
, "pulldown", NULL
, 0);
159 cascade
= XtVaCreateManagedWidget ("helpMenu", xmCascadeButtonGadgetClass
,
160 menuBar
, XmNsubMenuId
, pulldown
, NULL
);
162 button
= XtVaCreateManagedWidget ("aboutMenuItem", xmPushButtonGadgetClass
,
164 XtAddCallback (button
, XmNactivateCallback
, _doNothingCallback
, (XtPointer
)this);
166 XtVaSetValues (menuBar
, XmNmenuHelpWidget
, cascade
, NULL
);
168 // Manage the menubar
170 XtManageChild (menuBar
);
172 // Create the work area
179 XtSetArg (args
[n
], XmNscrollingPolicy
, XmAUTOMATIC
); n
++;
180 XtSetArg (args
[n
], XmNhighlightThickness
, (Dimension
)0); n
++;
181 XtSetArg (args
[n
], XmNeditMode
, XmMULTI_LINE_EDIT
); n
++;
182 XtSetArg (args
[n
], XmNeditable
, True
); n
++;
183 XtSetArg (args
[n
], XmNwordWrap
, False
); n
++;
184 XtSetArg (args
[n
], XmNcursorPositionVisible
, True
); n
++;
185 XtSetArg (args
[n
], XmNverifyBell
, True
); n
++;
189 Widget scrolledText
= XmCreateScrolledText (mainW
, "scrolledText", args
, n
);
190 XtManageChild (scrolledText
);
192 // Set the main window area
194 XtVaSetValues (mainW
, XmNmenuBar
, menuBar
, XmNworkWindow
,
195 XtParent (scrolledText
), NULL
);
197 XtManageChild (mainW
);
200 void Show() { show(); }
205 wxMDIParentFrame::wxMDIParentFrame()
207 m_clientWindow
= NULL
;
210 bool wxMDIParentFrame::Create(wxWindow
*parent
,
212 const wxString
& title
,
216 const wxString
& name
)
218 m_clientWindow
= NULL
;
220 bool success
= wxFrame::Create(parent
, id
, title
, pos
, size
, style
, name
);
223 // TODO: app cannot override OnCreateClient since
224 // wxMDIParentFrame::OnCreateClient will still be called
225 // (we're in the constructor). How to resolve?
227 m_clientWindow
= OnCreateClient();
228 // Uses own style for client style
229 m_clientWindow
->CreateClient(this, GetWindowStyleFlag());
236 wxMDIParentFrame::~wxMDIParentFrame()
239 delete m_clientWindow
;
242 // Get size *available for subwindows* i.e. excluding menu bar.
243 void wxMDIParentFrame::GetClientSize(int *x
, int *y
) const
245 wxFrame::GetClientSize(x
, y
);
248 void wxMDIParentFrame::SetMenuBar(wxMenuBar
*menu_bar
)
250 wxFrame::SetMenuBar(menu_bar
);
253 void wxMDIParentFrame::OnSize(wxSizeEvent
& event
)
255 #if wxUSE_CONSTRAINTS
262 GetClientSize(&width
, &height
);
264 if ( GetClientWindow() )
265 GetClientWindow()->SetSize(x
, y
, width
, height
);
268 void wxMDIParentFrame::OnActivate(wxActivateEvent
& event
)
273 // Returns the active MDI child window
274 wxMDIChildFrame
*wxMDIParentFrame::GetActiveChild() const
280 // Create the client window class (don't Create the window,
281 // just return a new class)
282 wxMDIClientWindow
*wxMDIParentFrame::OnCreateClient()
284 return new wxMDIClientWindow
;
287 // Responds to colour changes, and passes event on to children.
288 void wxMDIParentFrame::OnSysColourChanged(wxSysColourChangedEvent
& event
)
292 // Propagate the event to the non-top-level children
293 wxFrame::OnSysColourChanged(event
);
297 void wxMDIParentFrame::Cascade()
302 void wxMDIParentFrame::Tile()
307 void wxMDIParentFrame::ArrangeIcons()
312 void wxMDIParentFrame::ActivateNext()
317 void wxMDIParentFrame::ActivatePrevious()
324 wxMDIChildFrame::wxMDIChildFrame()
328 bool wxMDIChildFrame::Create(wxMDIParentFrame
*parent
,
330 const wxString
& title
,
334 const wxString
& name
)
341 m_windowId
= (int)NewControlId();
343 if (parent
) parent
->AddChild(this);
345 int x
= pos
.x
; int y
= pos
.y
;
346 int width
= size
.x
; int height
= size
.y
;
348 wxMDIClientWindow
* clientWindow
= parent
->GetClientWindow();
352 m_mdiWindow
= new wxXsMDIWindow("mdiChildWindow", this);
353 clientWindow
->GetMDICanvas()->add(m_mdiWindow
);
356 m_mainWidget
= (WXWidget
) (Widget
) (*m_mdiWindow
);
358 m_frameWidget
= (WXWidget
) XtVaCreateManagedWidget("main_window",
359 xmMainWindowWidgetClass
, (Widget
) m_mainWidget
,
360 XmNresizePolicy
, XmRESIZE_NONE
,
363 m_workArea
= (WXWidget
) XtVaCreateWidget("form",
364 xmFormWidgetClass
, (Widget
) m_frameWidget
,
365 XmNresizePolicy
, XmRESIZE_NONE
,
368 m_clientArea
= (WXWidget
) XtVaCreateWidget("client",
369 xmBulletinBoardWidgetClass
, (Widget
) m_workArea
,
372 XmNrightAttachment
, XmATTACH_FORM
,
373 XmNleftAttachment
, XmATTACH_FORM
,
374 XmNtopAttachment
, XmATTACH_FORM
,
375 XmNbottomAttachment
, XmATTACH_FORM
,
376 // XmNresizePolicy, XmRESIZE_ANY,
379 XtVaSetValues((Widget
) m_frameWidget
,
380 XmNworkWindow
, (Widget
) m_workArea
,
383 XtManageChild((Widget
) m_clientArea
);
384 XtManageChild((Widget
) m_workArea
);
386 wxASSERT_MSG ((wxWidgetHashTable
->Get((long)m_workArea
) == (wxObject
*) NULL
), "Widget table clash in frame.cpp") ;
388 wxAddWindowToTable((Widget
) m_workArea
, this);
392 XtOverrideTranslations((Widget
) m_workArea
,
393 ptr
= XtParseTranslationTable("<Configure>: resize()"));
397 XtAddCallback((Widget
) m_workArea
, XmNfocusCallback
,
398 (XtCallbackProc
)wxFrameFocusProc
, (XtPointer
)this);
401 XtVaSetValues((Widget
) m_mainWidget
, XmNx
, x
, NULL
);
403 XtVaSetValues((Widget
) m_mainWidget
, XmNy
, y
, NULL
);
405 XtVaSetValues((Widget
) m_mainWidget
, XmNwidth
, width
, NULL
);
407 XtVaSetValues((Widget
) m_mainWidget
, XmNheight
, height
, NULL
);
414 wxSizeEvent
sizeEvent(wxSize(width
, height
), GetId());
415 sizeEvent
.SetEventObject(this);
417 GetEventHandler()->ProcessEvent(sizeEvent
);
419 wxModelessWindows
.Append(this);
423 void wxMDIChildFrame::BuildClientArea(WXWidget parent
)
425 m_mainWidget
= parent
;
427 m_frameWidget
= (WXWidget
) XtVaCreateManagedWidget("main_window",
428 xmMainWindowWidgetClass
, (Widget
) m_mainWidget
,
429 XmNresizePolicy
, XmRESIZE_NONE
,
430 XmNtopAttachment
, XmATTACH_FORM
,
431 XmNbottomAttachment
, XmATTACH_FORM
,
432 XmNleftAttachment
, XmATTACH_FORM
,
433 XmNrightAttachment
, XmATTACH_FORM
,
436 m_workArea
= (WXWidget
) XtVaCreateWidget("form",
437 xmFormWidgetClass
, (Widget
) m_frameWidget
,
438 XmNresizePolicy
, XmRESIZE_NONE
,
441 m_clientArea
= (WXWidget
) XtVaCreateWidget("client",
442 xmBulletinBoardWidgetClass
, (Widget
) m_workArea
,
445 XmNrightAttachment
, XmATTACH_FORM
,
446 XmNleftAttachment
, XmATTACH_FORM
,
447 XmNtopAttachment
, XmATTACH_FORM
,
448 XmNbottomAttachment
, XmATTACH_FORM
,
449 // XmNresizePolicy, XmRESIZE_ANY,
452 XtVaSetValues((Widget
) m_frameWidget
,
453 XmNworkWindow
, (Widget
) m_workArea
,
456 XtManageChild((Widget
) m_clientArea
);
457 XtManageChild((Widget
) m_workArea
);
459 wxASSERT_MSG ((wxWidgetHashTable
->Get((long)m_workArea
) == (wxObject
*) NULL
), "Widget table clash in frame.cpp") ;
461 wxAddWindowToTable((Widget
) m_workArea
, this);
465 XtOverrideTranslations((Widget
) m_workArea
,
466 ptr
= XtParseTranslationTable("<Configure>: resize()"));
470 XtAddCallback((Widget
) m_workArea
, XmNfocusCallback
,
471 (XtCallbackProc
)wxFrameFocusProc
, (XtPointer
)this);
474 int x = pos.x; int y = pos.y;
475 int width = size.x; int height = size.y;
478 XtVaSetValues((Widget) m_mainWidget, XmNx, x, NULL);
480 XtVaSetValues((Widget) m_mainWidget, XmNy, y, NULL);
482 XtVaSetValues((Widget) m_mainWidget, XmNwidth, width, NULL);
484 XtVaSetValues((Widget) m_mainWidget, XmNheight, height, NULL);
487 XtManageChild((Widget
) m_frameWidget
);
491 wxMDIChildFrame::~wxMDIChildFrame()
493 wxMDIClientWindow
* clientWindow
= ((wxMDIParentFrame
*)GetParent())->GetClientWindow();
494 clientWindow
->GetMDICanvas()->remove(m_mdiWindow
);
495 m_mainWidget
= (WXWidget
) 0;
498 // Set the client size (i.e. leave the calculation of borders etc.
500 void wxMDIChildFrame::SetClientSize(int width
, int height
)
502 wxFrame::SetClientSize(width
, height
);
505 void wxMDIChildFrame::GetClientSize(int* width
, int* height
) const
507 wxFrame::GetClientSize(width
, height
);
510 void wxMDIChildFrame::SetSize(int x
, int y
, int width
, int height
, int sizeFlags
)
512 wxWindow::SetSize(x
, y
, width
, height
, sizeFlags
);
515 void wxMDIChildFrame::GetSize(int* width
, int* height
) const
517 wxWindow::GetSize(width
, height
);
520 void wxMDIChildFrame::GetPosition(int *x
, int *y
) const
522 wxWindow::GetPosition(x
, y
);
525 bool wxMDIChildFrame::Show(bool show
)
527 m_visibleStatus
= show
; /* show-&-hide fix */
531 void wxMDIChildFrame::SetMenuBar(wxMenuBar
*menu_bar
)
534 // Currently, the menu appears on the child frame.
535 // It should eventually be recreated on the main frame
536 // whenever the child is activated.
537 wxFrame::SetMenuBar(menu_bar
);
541 void wxMDIChildFrame::SetIcon(const wxIcon
& icon
)
546 /* TODO: doesn't work yet (crashes in XCopyArea)
547 Pixmap pixmap = (Pixmap) m_icon.GetPixmap();
548 m_mdiWindow->setPixmap(pixmap);
553 void wxMDIChildFrame::SetTitle(const wxString
& title
)
556 m_mdiWindow
->setTitle(title
);
557 m_mdiWindow
->setIconName(title
);
561 void wxMDIChildFrame::Maximize()
563 m_mdiWindow
->maximize();
566 void wxMDIChildFrame::Iconize(bool iconize
)
569 m_mdiWindow
->minimize();
571 m_mdiWindow
->restore();
574 bool wxMDIChildFrame::IsIconized() const
576 return m_mdiWindow
->minimized();
579 void wxMDIChildFrame::Restore()
581 m_mdiWindow
->restore();
584 void wxMDIChildFrame::Activate()
586 m_mdiWindow
->raise();
591 wxMDIClientWindow::wxMDIClientWindow()
594 m_topWidget
= (WXWidget
) 0;
597 wxMDIClientWindow::~wxMDIClientWindow()
602 m_mainWidget
= (WXWidget
) 0;
603 m_topWidget
= (WXWidget
) 0;
606 bool wxMDIClientWindow::CreateClient(wxMDIParentFrame
*parent
, long style
)
608 m_windowParent
= parent
;
609 m_backgroundColour
= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE
);
610 m_mdiCanvas
= new XsMDICanvas("mdiClientWindow", (Widget
) parent
->GetClientWidget());
611 m_mainWidget
= (WXWidget
) m_mdiCanvas
->GetDrawingArea();
612 // m_topWidget = (WXWidget) m_mdiCanvas->GetBase();
613 m_topWidget
= (WXWidget
) (Widget
) (*m_mdiCanvas
);
620 void wxMDIClientWindow::SetSize(int x
, int y
, int width
, int height
, int sizeFlags
)
622 wxWindow::SetSize(x
, y
, width
, height
, sizeFlags
);
625 void wxMDIClientWindow::SetClientSize(int width
, int height
)
627 wxWindow::SetClientSize(width
, height
);
630 void wxMDIClientWindow::GetClientSize(int *width
, int *height
) const
632 wxWindow::GetClientSize(width
, height
);
635 void wxMDIClientWindow::GetSize(int *width
, int *height
) const
637 wxWindow::GetSize(width
, height
);
640 void wxMDIClientWindow::GetPosition(int *x
, int *y
) const
642 wxWindow::GetPosition(x
, y
);
645 // Explicitly call default scroll behaviour
646 void wxMDIClientWindow::OnScroll(wxScrollEvent
& event
)
648 Default(); // Default processing