]> git.saurik.com Git - wxWidgets.git/blob - src/motif/mdi.cpp
0ecb45e87ba080dc3ad8dd5268d8d592abc52890
[wxWidgets.git] / src / motif / mdi.cpp
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 #include "wx/mdi.h"
17 #include "wx/menu.h"
18 #include "wx/settings.h"
19
20 #include <Xm/Xm.h>
21 #include <Xm/BulletinB.h>
22 #include <Xm/Form.h>
23 #include <Xm/MainW.h>
24 #include <Xm/RowColumn.h>
25 #include <Xm/CascadeBG.h>
26 #include <Xm/Text.h>
27 #include <Xm/PushBG.h>
28 #include <Xm/AtomMgr.h>
29 #include <Xm/Protocols.h>
30
31 #include "mdi/lib/XsMDICanvas.h"
32 #include "mdi/lib/XsMotifWindow.h"
33
34 #include "wx/motif/private.h"
35
36 extern wxList wxModelessWindows;
37
38 // Implemented in frame.cpp
39 extern void wxFrameFocusProc(Widget workArea, XtPointer clientData,
40 XmAnyCallbackStruct *cbs);
41
42 #if !USE_SHARED_LIBRARY
43 IMPLEMENT_DYNAMIC_CLASS(wxMDIParentFrame, wxFrame)
44 IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame, wxFrame)
45 IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow, wxWindow)
46
47 BEGIN_EVENT_TABLE(wxMDIParentFrame, wxFrame)
48 EVT_SIZE(wxMDIParentFrame::OnSize)
49 EVT_ACTIVATE(wxMDIParentFrame::OnActivate)
50 EVT_SYS_COLOUR_CHANGED(wxMDIParentFrame::OnSysColourChanged)
51 END_EVENT_TABLE()
52
53 BEGIN_EVENT_TABLE(wxMDIClientWindow, wxWindow)
54 EVT_SCROLL(wxMDIClientWindow::OnScroll)
55 END_EVENT_TABLE()
56
57 #endif
58
59 /*
60 static void _doNothingCallback (Widget, XtPointer, XtPointer)
61 {
62 }
63 */
64
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.
71
72 // Note: see XsMotifWindow.C, _XsMotifMenu::_processItem for
73 // where user menu selections are processed.
74 // When Close is selected, _win->close() is called.
75
76 class wxXsMDIWindow: public XsMotifWindow
77 {
78 public:
79 wxMDIChildFrame* m_childFrame;
80
81 wxXsMDIWindow(const char* name, wxMDIChildFrame* frame): XsMotifWindow(name)
82 {
83 m_childFrame = frame;
84 }
85 virtual void setSize(Dimension w, Dimension h)
86 {
87 XsMotifWindow::setSize(w, h);
88
89 // Generate wxSizeEvent here, I think. Maybe also restore, maximize
90 // Probably don't need to generate size event here since work area
91 // is used
92 wxSizeEvent event(wxSize(w, h), m_childFrame->GetId());
93 event.SetEventObject(m_childFrame);
94 m_childFrame->ProcessEvent(event);
95 }
96 virtual void close()
97 {
98 XsMotifWindow::close();
99 m_childFrame->Close();
100 }
101 virtual void _buildClientArea(Widget parent)
102 {
103 m_childFrame->BuildClientArea((WXWidget) parent);
104
105 // Code from MDI sample
106 #if 0
107 assert (parent != 0);
108
109 Widget pulldown;
110 Widget cascade;
111 Widget button;
112
113 // Create a main window with some dummy menus
114
115 Widget mainW = XtVaCreateWidget ("mainWin", xmMainWindowWidgetClass, parent,
116 XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM,
117 XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM,
118 NULL);
119
120 // Create a menubar
121
122 Widget menuBar = XmCreateMenuBar (mainW, "menuBar", NULL, 0);
123
124 // Create the "file" menu
125
126 pulldown = XmCreatePulldownMenu (menuBar, "pulldown", NULL, 0);
127 cascade = XtVaCreateManagedWidget ("fileMenu", xmCascadeButtonGadgetClass,
128 menuBar, XmNsubMenuId, pulldown, NULL);
129
130 button = XtVaCreateManagedWidget ("openMenuItem", xmPushButtonGadgetClass,
131 pulldown, NULL);
132 XtAddCallback (button, XmNactivateCallback, _doNothingCallback, (XtPointer)this);
133
134 button = XtVaCreateManagedWidget ("newMenuItem", xmPushButtonGadgetClass,
135 pulldown, NULL);
136 // XtAddCallback (button, XmNactivateCallback, _newWindowCallback, (XtPointer)this);
137
138 // Create the "edit" menu
139
140 pulldown = XmCreatePulldownMenu (menuBar, "pulldown", NULL, 0);
141 cascade = XtVaCreateManagedWidget ("editMenu", xmCascadeButtonGadgetClass,
142 menuBar, XmNsubMenuId, pulldown, NULL);
143
144 button = XtVaCreateManagedWidget ("cutMenuItem", xmPushButtonGadgetClass,
145 pulldown, NULL);
146 XtAddCallback (button, XmNactivateCallback, _doNothingCallback, (XtPointer)this);
147
148 button = XtVaCreateManagedWidget ("copyMenuItem", xmPushButtonGadgetClass,
149 pulldown, NULL);
150 XtAddCallback (button, XmNactivateCallback, _doNothingCallback, (XtPointer)this);
151
152 button = XtVaCreateManagedWidget ("pasteMenuItem", xmPushButtonGadgetClass,
153 pulldown, NULL);
154 XtAddCallback (button, XmNactivateCallback, _doNothingCallback, (XtPointer)this);
155
156 // Create the help menu
157
158 pulldown = XmCreatePulldownMenu (menuBar, "pulldown", NULL, 0);
159 cascade = XtVaCreateManagedWidget ("helpMenu", xmCascadeButtonGadgetClass,
160 menuBar, XmNsubMenuId, pulldown, NULL);
161
162 button = XtVaCreateManagedWidget ("aboutMenuItem", xmPushButtonGadgetClass,
163 pulldown, NULL);
164 XtAddCallback (button, XmNactivateCallback, _doNothingCallback, (XtPointer)this);
165
166 XtVaSetValues (menuBar, XmNmenuHelpWidget, cascade, NULL);
167
168 // Manage the menubar
169
170 XtManageChild (menuBar);
171
172 // Create the work area
173
174 const int nargs = 8;
175 Arg args[nargs];
176 int n;
177
178 n = 0;
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++;
186
187 assert (n <= nargs);
188
189 Widget scrolledText = XmCreateScrolledText (mainW, "scrolledText", args, n);
190 XtManageChild (scrolledText);
191
192 // Set the main window area
193
194 XtVaSetValues (mainW, XmNmenuBar, menuBar, XmNworkWindow,
195 XtParent (scrolledText), NULL);
196
197 XtManageChild (mainW);
198 #endif
199 }
200 void Show() { show(); }
201 };
202
203 // Parent frame
204
205 wxMDIParentFrame::wxMDIParentFrame()
206 {
207 m_clientWindow = NULL;
208 }
209
210 bool wxMDIParentFrame::Create(wxWindow *parent,
211 wxWindowID id,
212 const wxString& title,
213 const wxPoint& pos,
214 const wxSize& size,
215 long style,
216 const wxString& name)
217 {
218 m_clientWindow = NULL;
219
220 bool success = wxFrame::Create(parent, id, title, pos, size, style, name);
221 if (success)
222 {
223 // TODO: app cannot override OnCreateClient since
224 // wxMDIParentFrame::OnCreateClient will still be called
225 // (we're in the constructor). How to resolve?
226
227 m_clientWindow = OnCreateClient();
228 // Uses own style for client style
229 m_clientWindow->CreateClient(this, GetWindowStyleFlag());
230 return TRUE;
231 }
232 else
233 return FALSE;
234 }
235
236 wxMDIParentFrame::~wxMDIParentFrame()
237 {
238 DestroyChildren();
239 delete m_clientWindow;
240 }
241
242 // Get size *available for subwindows* i.e. excluding menu bar.
243 void wxMDIParentFrame::GetClientSize(int *x, int *y) const
244 {
245 wxFrame::GetClientSize(x, y);
246 }
247
248 void wxMDIParentFrame::SetMenuBar(wxMenuBar *menu_bar)
249 {
250 wxFrame::SetMenuBar(menu_bar);
251 }
252
253 void wxMDIParentFrame::OnSize(wxSizeEvent& event)
254 {
255 #if wxUSE_CONSTRAINTS
256 if (GetAutoLayout())
257 Layout();
258 #endif
259 int x = 0;
260 int y = 0;
261 int width, height;
262 GetClientSize(&width, &height);
263
264 if ( GetClientWindow() )
265 GetClientWindow()->SetSize(x, y, width, height);
266 }
267
268 void wxMDIParentFrame::OnActivate(wxActivateEvent& event)
269 {
270 // Do nothing
271 }
272
273 // Returns the active MDI child window
274 wxMDIChildFrame *wxMDIParentFrame::GetActiveChild() const
275 {
276 // TODO
277 return NULL;
278 }
279
280 // Create the client window class (don't Create the window,
281 // just return a new class)
282 wxMDIClientWindow *wxMDIParentFrame::OnCreateClient()
283 {
284 return new wxMDIClientWindow ;
285 }
286
287 // Responds to colour changes, and passes event on to children.
288 void wxMDIParentFrame::OnSysColourChanged(wxSysColourChangedEvent& event)
289 {
290 // TODO
291
292 // Propagate the event to the non-top-level children
293 wxFrame::OnSysColourChanged(event);
294 }
295
296 // MDI operations
297 void wxMDIParentFrame::Cascade()
298 {
299 // TODO
300 }
301
302 void wxMDIParentFrame::Tile()
303 {
304 // TODO
305 }
306
307 void wxMDIParentFrame::ArrangeIcons()
308 {
309 // TODO
310 }
311
312 void wxMDIParentFrame::ActivateNext()
313 {
314 // TODO
315 }
316
317 void wxMDIParentFrame::ActivatePrevious()
318 {
319 // TODO
320 }
321
322 // Child frame
323
324 wxMDIChildFrame::wxMDIChildFrame()
325 {
326 }
327
328 bool wxMDIChildFrame::Create(wxMDIParentFrame *parent,
329 wxWindowID id,
330 const wxString& title,
331 const wxPoint& pos,
332 const wxSize& size,
333 long style,
334 const wxString& name)
335 {
336 SetName(name);
337
338 if ( id > -1 )
339 m_windowId = id;
340 else
341 m_windowId = (int)NewControlId();
342
343 if (parent) parent->AddChild(this);
344
345 int x = pos.x; int y = pos.y;
346 int width = size.x; int height = size.y;
347
348 wxMDIClientWindow* clientWindow = parent->GetClientWindow();
349 if (!clientWindow)
350 return FALSE;
351
352 m_mdiWindow = new wxXsMDIWindow("mdiChildWindow", this);
353 clientWindow->GetMDICanvas()->add(m_mdiWindow);
354 m_mdiWindow->Show();
355 #if 0
356 m_mainWidget = (WXWidget) (Widget) (*m_mdiWindow);
357
358 m_frameWidget = (WXWidget) XtVaCreateManagedWidget("main_window",
359 xmMainWindowWidgetClass, (Widget) m_mainWidget,
360 XmNresizePolicy, XmRESIZE_NONE,
361 NULL);
362
363 m_workArea = (WXWidget) XtVaCreateWidget("form",
364 xmFormWidgetClass, (Widget) m_frameWidget,
365 XmNresizePolicy, XmRESIZE_NONE,
366 NULL);
367
368 m_clientArea = (WXWidget) XtVaCreateWidget("client",
369 xmBulletinBoardWidgetClass, (Widget) m_workArea,
370 XmNmarginWidth, 0,
371 XmNmarginHeight, 0,
372 XmNrightAttachment, XmATTACH_FORM,
373 XmNleftAttachment, XmATTACH_FORM,
374 XmNtopAttachment, XmATTACH_FORM,
375 XmNbottomAttachment, XmATTACH_FORM,
376 // XmNresizePolicy, XmRESIZE_ANY,
377 NULL);
378
379 XtVaSetValues((Widget) m_frameWidget,
380 XmNworkWindow, (Widget) m_workArea,
381 NULL);
382
383 XtManageChild((Widget) m_clientArea);
384 XtManageChild((Widget) m_workArea);
385
386 wxASSERT_MSG ((wxWidgetHashTable->Get((long)m_workArea) == (wxObject*) NULL), "Widget table clash in frame.cpp") ;
387
388 wxAddWindowToTable((Widget) m_workArea, this);
389
390 XtTranslations ptr ;
391
392 XtOverrideTranslations((Widget) m_workArea,
393 ptr = XtParseTranslationTable("<Configure>: resize()"));
394
395 XtFree((char *)ptr);
396
397 XtAddCallback((Widget) m_workArea, XmNfocusCallback,
398 (XtCallbackProc)wxFrameFocusProc, (XtPointer)this);
399
400 if (x > -1)
401 XtVaSetValues((Widget) m_mainWidget, XmNx, x, NULL);
402 if (y > -1)
403 XtVaSetValues((Widget) m_mainWidget, XmNy, y, NULL);
404 if (width > -1)
405 XtVaSetValues((Widget) m_mainWidget, XmNwidth, width, NULL);
406 if (height > -1)
407 XtVaSetValues((Widget) m_mainWidget, XmNheight, height, NULL);
408 #endif
409
410 SetTitle(title);
411
412 PreResize();
413
414 wxSizeEvent sizeEvent(wxSize(width, height), GetId());
415 sizeEvent.SetEventObject(this);
416
417 GetEventHandler()->ProcessEvent(sizeEvent);
418
419 wxModelessWindows.Append(this);
420 return TRUE;
421 }
422
423 void wxMDIChildFrame::BuildClientArea(WXWidget parent)
424 {
425 m_mainWidget = parent;
426
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,
434 NULL);
435
436 m_workArea = (WXWidget) XtVaCreateWidget("form",
437 xmFormWidgetClass, (Widget) m_frameWidget,
438 XmNresizePolicy, XmRESIZE_NONE,
439 NULL);
440
441 m_clientArea = (WXWidget) XtVaCreateWidget("client",
442 xmBulletinBoardWidgetClass, (Widget) m_workArea,
443 XmNmarginWidth, 0,
444 XmNmarginHeight, 0,
445 XmNrightAttachment, XmATTACH_FORM,
446 XmNleftAttachment, XmATTACH_FORM,
447 XmNtopAttachment, XmATTACH_FORM,
448 XmNbottomAttachment, XmATTACH_FORM,
449 // XmNresizePolicy, XmRESIZE_ANY,
450 NULL);
451
452 XtVaSetValues((Widget) m_frameWidget,
453 XmNworkWindow, (Widget) m_workArea,
454 NULL);
455
456 XtManageChild((Widget) m_clientArea);
457 XtManageChild((Widget) m_workArea);
458
459 wxASSERT_MSG ((wxWidgetHashTable->Get((long)m_workArea) == (wxObject*) NULL), "Widget table clash in frame.cpp") ;
460
461 wxAddWindowToTable((Widget) m_workArea, this);
462
463 XtTranslations ptr ;
464
465 XtOverrideTranslations((Widget) m_workArea,
466 ptr = XtParseTranslationTable("<Configure>: resize()"));
467
468 XtFree((char *)ptr);
469
470 XtAddCallback((Widget) m_workArea, XmNfocusCallback,
471 (XtCallbackProc)wxFrameFocusProc, (XtPointer)this);
472
473 /*
474 int x = pos.x; int y = pos.y;
475 int width = size.x; int height = size.y;
476
477 if (x > -1)
478 XtVaSetValues((Widget) m_mainWidget, XmNx, x, NULL);
479 if (y > -1)
480 XtVaSetValues((Widget) m_mainWidget, XmNy, y, NULL);
481 if (width > -1)
482 XtVaSetValues((Widget) m_mainWidget, XmNwidth, width, NULL);
483 if (height > -1)
484 XtVaSetValues((Widget) m_mainWidget, XmNheight, height, NULL);
485 */
486
487 XtManageChild((Widget) m_frameWidget);
488 }
489
490
491 wxMDIChildFrame::~wxMDIChildFrame()
492 {
493 wxMDIClientWindow* clientWindow = ((wxMDIParentFrame*)GetParent())->GetClientWindow();
494 clientWindow->GetMDICanvas()->remove(m_mdiWindow);
495 m_mainWidget = (WXWidget) 0;
496 }
497
498 // Set the client size (i.e. leave the calculation of borders etc.
499 // to wxWindows)
500 void wxMDIChildFrame::SetClientSize(int width, int height)
501 {
502 wxFrame::SetClientSize(width, height);
503 }
504
505 void wxMDIChildFrame::GetClientSize(int* width, int* height) const
506 {
507 wxFrame::GetClientSize(width, height);
508 }
509
510 void wxMDIChildFrame::SetSize(int x, int y, int width, int height, int sizeFlags)
511 {
512 wxWindow::SetSize(x, y, width, height, sizeFlags);
513 }
514
515 void wxMDIChildFrame::GetSize(int* width, int* height) const
516 {
517 wxWindow::GetSize(width, height);
518 }
519
520 void wxMDIChildFrame::GetPosition(int *x, int *y) const
521 {
522 wxWindow::GetPosition(x, y);
523 }
524
525 bool wxMDIChildFrame::Show(bool show)
526 {
527 m_visibleStatus = show; /* show-&-hide fix */
528 return TRUE;
529 }
530
531 void wxMDIChildFrame::SetMenuBar(wxMenuBar *menu_bar)
532 {
533 // TODO
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);
538 }
539
540 // Set icon
541 void wxMDIChildFrame::SetIcon(const wxIcon& icon)
542 {
543 m_icon = icon;
544 if (m_icon.Ok())
545 {
546 /* TODO: doesn't work yet (crashes in XCopyArea)
547 Pixmap pixmap = (Pixmap) m_icon.GetPixmap();
548 m_mdiWindow->setPixmap(pixmap);
549 */
550 }
551 }
552
553 void wxMDIChildFrame::SetTitle(const wxString& title)
554 {
555 m_title = title;
556 m_mdiWindow->setTitle(title);
557 m_mdiWindow->setIconName(title);
558 }
559
560 // MDI operations
561 void wxMDIChildFrame::Maximize()
562 {
563 m_mdiWindow->maximize();
564 }
565
566 void wxMDIChildFrame::Iconize(bool iconize)
567 {
568 if (iconize)
569 m_mdiWindow->minimize();
570 else
571 m_mdiWindow->restore();
572 }
573
574 bool wxMDIChildFrame::IsIconized() const
575 {
576 return m_mdiWindow->minimized();
577 }
578
579 void wxMDIChildFrame::Restore()
580 {
581 m_mdiWindow->restore();
582 }
583
584 void wxMDIChildFrame::Activate()
585 {
586 m_mdiWindow->raise();
587 }
588
589 // Client window
590
591 wxMDIClientWindow::wxMDIClientWindow()
592 {
593 m_mdiCanvas = NULL;
594 m_topWidget = (WXWidget) 0;
595 }
596
597 wxMDIClientWindow::~wxMDIClientWindow()
598 {
599 DestroyChildren();
600 delete m_mdiCanvas;
601
602 m_mainWidget = (WXWidget) 0;
603 m_topWidget = (WXWidget) 0;
604 }
605
606 bool wxMDIClientWindow::CreateClient(wxMDIParentFrame *parent, long style)
607 {
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);
614
615 m_mdiCanvas->show();
616
617 return TRUE;
618 }
619
620 void wxMDIClientWindow::SetSize(int x, int y, int width, int height, int sizeFlags)
621 {
622 wxWindow::SetSize(x, y, width, height, sizeFlags);
623 }
624
625 void wxMDIClientWindow::SetClientSize(int width, int height)
626 {
627 wxWindow::SetClientSize(width, height);
628 }
629
630 void wxMDIClientWindow::GetClientSize(int *width, int *height) const
631 {
632 wxWindow::GetClientSize(width, height);
633 }
634
635 void wxMDIClientWindow::GetSize(int *width, int *height) const
636 {
637 wxWindow::GetSize(width, height);
638 }
639
640 void wxMDIClientWindow::GetPosition(int *x, int *y) const
641 {
642 wxWindow::GetPosition(x, y);
643 }
644
645 // Explicitly call default scroll behaviour
646 void wxMDIClientWindow::OnScroll(wxScrollEvent& event)
647 {
648 Default(); // Default processing
649 }
650