X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/4bb6408c2631988fab9925014c6619358bf867de..184b5d99a5382cd7a19888c85aff11f8a21af2f6:/src/motif/mdi.cpp?ds=inline diff --git a/src/motif/mdi.cpp b/src/motif/mdi.cpp index b1685194a4..75a528cedb 100644 --- a/src/motif/mdi.cpp +++ b/src/motif/mdi.cpp @@ -17,8 +17,28 @@ #include "wx/menu.h" #include "wx/settings.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mdi/lib/XsMDICanvas.h" +#include "mdi/lib/XsMotifWindow.h" + +#include "wx/motif/private.h" + extern wxList wxModelessWindows; +// Implemented in frame.cpp +extern void wxFrameFocusProc(Widget workArea, XtPointer clientData, + XmAnyCallbackStruct *cbs); + #if !USE_SHARED_LIBRARY IMPLEMENT_DYNAMIC_CLASS(wxMDIParentFrame, wxFrame) IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame, wxFrame) @@ -36,10 +56,166 @@ END_EVENT_TABLE() #endif + /* +static void _doNothingCallback (Widget, XtPointer, XtPointer) +{ +} +*/ + +// wxXsMDIWindow represents the MDI child frame, as far as the MDI +// package is concerned. +// TODO: override raise, so we can tell which is the 'active' +// (raised) window. We can also use it to send wxActivateEvents, +// and switching menubars when we make the child frame menubar +// appear on the parent frame. + +// Note: see XsMotifWindow.C, _XsMotifMenu::_processItem for +// where user menu selections are processed. +// When Close is selected, _win->close() is called. + +class wxXsMDIWindow: public XsMotifWindow +{ +public: + wxMDIChildFrame* m_childFrame; + + wxXsMDIWindow(const char* name, wxMDIChildFrame* frame): XsMotifWindow(name) + { + m_childFrame = frame; + } + virtual void setSize(Dimension w, Dimension h) + { + XsMotifWindow::setSize(w, h); + + // Generate wxSizeEvent here, I think. Maybe also restore, maximize + // Probably don't need to generate size event here since work area + // is used (???) + wxSizeEvent event(wxSize(w, h), m_childFrame->GetId()); + event.SetEventObject(m_childFrame); + m_childFrame->ProcessEvent(event); + } + virtual void close() + { + XsMotifWindow::close(); + m_childFrame->Close(); + } + virtual void raise() + { + XsMotifWindow::raise(); + m_childFrame->OnRaise(); + } + virtual void lower() + { + XsMotifWindow::lower(); + m_childFrame->OnLower(); + } + virtual void _buildClientArea(Widget parent) + { + m_childFrame->BuildClientArea((WXWidget) parent); + + // Code from MDI sample +#if 0 + assert (parent != 0); + + Widget pulldown; + Widget cascade; + Widget button; + +// Create a main window with some dummy menus + + Widget mainW = XtVaCreateWidget ("mainWin", xmMainWindowWidgetClass, parent, + XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, + XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, + NULL); + +// Create a menubar + + Widget menuBar = XmCreateMenuBar (mainW, "menuBar", NULL, 0); + +// Create the "file" menu + + pulldown = XmCreatePulldownMenu (menuBar, "pulldown", NULL, 0); + cascade = XtVaCreateManagedWidget ("fileMenu", xmCascadeButtonGadgetClass, + menuBar, XmNsubMenuId, pulldown, NULL); + + button = XtVaCreateManagedWidget ("openMenuItem", xmPushButtonGadgetClass, + pulldown, NULL); + XtAddCallback (button, XmNactivateCallback, _doNothingCallback, (XtPointer)this); + + button = XtVaCreateManagedWidget ("newMenuItem", xmPushButtonGadgetClass, + pulldown, NULL); + // XtAddCallback (button, XmNactivateCallback, _newWindowCallback, (XtPointer)this); + +// Create the "edit" menu + + pulldown = XmCreatePulldownMenu (menuBar, "pulldown", NULL, 0); + cascade = XtVaCreateManagedWidget ("editMenu", xmCascadeButtonGadgetClass, + menuBar, XmNsubMenuId, pulldown, NULL); + + button = XtVaCreateManagedWidget ("cutMenuItem", xmPushButtonGadgetClass, + pulldown, NULL); + XtAddCallback (button, XmNactivateCallback, _doNothingCallback, (XtPointer)this); + + button = XtVaCreateManagedWidget ("copyMenuItem", xmPushButtonGadgetClass, + pulldown, NULL); + XtAddCallback (button, XmNactivateCallback, _doNothingCallback, (XtPointer)this); + + button = XtVaCreateManagedWidget ("pasteMenuItem", xmPushButtonGadgetClass, + pulldown, NULL); + XtAddCallback (button, XmNactivateCallback, _doNothingCallback, (XtPointer)this); + +// Create the help menu + + pulldown = XmCreatePulldownMenu (menuBar, "pulldown", NULL, 0); + cascade = XtVaCreateManagedWidget ("helpMenu", xmCascadeButtonGadgetClass, + menuBar, XmNsubMenuId, pulldown, NULL); + + button = XtVaCreateManagedWidget ("aboutMenuItem", xmPushButtonGadgetClass, + pulldown, NULL); + XtAddCallback (button, XmNactivateCallback, _doNothingCallback, (XtPointer)this); + + XtVaSetValues (menuBar, XmNmenuHelpWidget, cascade, NULL); + +// Manage the menubar + + XtManageChild (menuBar); + +// Create the work area + + const int nargs = 8; + Arg args[nargs]; + int n; + + n = 0; + XtSetArg (args[n], XmNscrollingPolicy, XmAUTOMATIC); n++; + XtSetArg (args[n], XmNhighlightThickness, (Dimension)0); n++; + XtSetArg (args[n], XmNeditMode, XmMULTI_LINE_EDIT); n++; + XtSetArg (args[n], XmNeditable, True); n++; + XtSetArg (args[n], XmNwordWrap, False); n++; + XtSetArg (args[n], XmNcursorPositionVisible, True); n++; + XtSetArg (args[n], XmNverifyBell, True); n++; + + assert (n <= nargs); + + Widget scrolledText = XmCreateScrolledText (mainW, "scrolledText", args, n); + XtManageChild (scrolledText); + +// Set the main window area + + XtVaSetValues (mainW, XmNmenuBar, menuBar, XmNworkWindow, + XtParent (scrolledText), NULL); + + XtManageChild (mainW); +#endif + } + void Show() { show(); } +}; + // Parent frame wxMDIParentFrame::wxMDIParentFrame() { + m_clientWindow = (wxMDIClientWindow*) NULL; + m_activeChild = (wxMDIChildFrame*) NULL; } bool wxMDIParentFrame::Create(wxWindow *parent, @@ -50,54 +226,45 @@ bool wxMDIParentFrame::Create(wxWindow *parent, long style, const wxString& name) { - if (!parent) - wxTopLevelWindows.Append(this); - - SetName(name); - m_windowStyle = style; + m_clientWindow = (wxMDIClientWindow*) NULL; + m_activeChild = (wxMDIChildFrame*) NULL; - if (parent) parent->AddChild(this); - - if ( id > -1 ) - m_windowId = id; + bool success = wxFrame::Create(parent, id, title, pos, size, style, name); + if (success) + { + // TODO: app cannot override OnCreateClient since + // wxMDIParentFrame::OnCreateClient will still be called + // (we're in the constructor). How to resolve? + + m_clientWindow = OnCreateClient(); + // Uses own style for client style + m_clientWindow->CreateClient(this, GetWindowStyleFlag()); + return TRUE; + } else - m_windowId = (int)NewControlId(); - - // TODO: create MDI parent frame - - wxModelessWindows.Append(this); - - return TRUE; + return FALSE; } wxMDIParentFrame::~wxMDIParentFrame() { + DestroyChildren(); + delete m_clientWindow; } // Get size *available for subwindows* i.e. excluding menu bar. void wxMDIParentFrame::GetClientSize(int *x, int *y) const { - // TODO + wxFrame::GetClientSize(x, y); } void wxMDIParentFrame::SetMenuBar(wxMenuBar *menu_bar) { - // TODO - if (!menu_bar) - { - m_frameMenuBar = NULL; - return; - } - - if (menu_bar->m_menuBarFrame) - return; - - m_frameMenuBar = menu_bar; + wxFrame::SetMenuBar(menu_bar); } void wxMDIParentFrame::OnSize(wxSizeEvent& event) { -#if USE_CONSTRAINTS +#if wxUSE_CONSTRAINTS if (GetAutoLayout()) Layout(); #endif @@ -118,8 +285,7 @@ void wxMDIParentFrame::OnActivate(wxActivateEvent& event) // Returns the active MDI child window wxMDIChildFrame *wxMDIParentFrame::GetActiveChild() const { - // TODO - return NULL; + return m_activeChild; } // Create the client window class (don't Create the window, @@ -187,74 +353,358 @@ bool wxMDIChildFrame::Create(wxMDIParentFrame *parent, if (parent) parent->AddChild(this); - // TODO: create child frame + int x = pos.x; int y = pos.y; + int width = size.x; int height = size.y; + if (width == -1) + width = 200; // TODO: give reasonable default + if (height == -1) + height = 200; // TODO: give reasonable default + + wxMDIClientWindow* clientWindow = parent->GetClientWindow(); + if (!clientWindow) + return FALSE; + + // We're deactivating the old child + wxMDIChildFrame* oldActiveChild = parent->GetActiveChild(); + if (oldActiveChild) + { + wxActivateEvent event(wxEVT_ACTIVATE, FALSE, oldActiveChild->GetId()); + event.SetEventObject( oldActiveChild ); + oldActiveChild->GetEventHandler()->ProcessEvent(event); + } + + m_mdiWindow = new wxXsMDIWindow("mdiChildWindow", this); + clientWindow->GetMDICanvas()->add(m_mdiWindow); + + // This is the currently active child + parent->SetActiveChild((wxMDIChildFrame*) this); + + m_mdiWindow->Show(); + +#if 0 + m_mainWidget = (WXWidget) (Widget) (*m_mdiWindow); + + m_frameWidget = (WXWidget) XtVaCreateManagedWidget("main_window", + xmMainWindowWidgetClass, (Widget) m_mainWidget, + XmNresizePolicy, XmRESIZE_NONE, + NULL); + + m_workArea = (WXWidget) XtVaCreateWidget("form", + xmFormWidgetClass, (Widget) m_frameWidget, + XmNresizePolicy, XmRESIZE_NONE, + NULL); + + m_clientArea = (WXWidget) XtVaCreateWidget("client", + xmBulletinBoardWidgetClass, (Widget) m_workArea, + XmNmarginWidth, 0, + XmNmarginHeight, 0, + XmNrightAttachment, XmATTACH_FORM, + XmNleftAttachment, XmATTACH_FORM, + XmNtopAttachment, XmATTACH_FORM, + XmNbottomAttachment, XmATTACH_FORM, +// XmNresizePolicy, XmRESIZE_ANY, + NULL); + + XtVaSetValues((Widget) m_frameWidget, + XmNworkWindow, (Widget) m_workArea, + NULL); + + XtManageChild((Widget) m_clientArea); + XtManageChild((Widget) m_workArea); + + wxASSERT_MSG ((wxWidgetHashTable->Get((long)m_workArea) == (wxObject*) NULL), "Widget table clash in frame.cpp") ; + + wxAddWindowToTable((Widget) m_workArea, this); + + XtTranslations ptr ; + + XtOverrideTranslations((Widget) m_workArea, + ptr = XtParseTranslationTable(": resize()")); + + XtFree((char *)ptr); + + XtAddCallback((Widget) m_workArea, XmNfocusCallback, + (XtCallbackProc)wxFrameFocusProc, (XtPointer)this); + + if (x > -1) + XtVaSetValues((Widget) m_mainWidget, XmNx, x, NULL); + if (y > -1) + XtVaSetValues((Widget) m_mainWidget, XmNy, y, NULL); + if (width > -1) + XtVaSetValues((Widget) m_mainWidget, XmNwidth, width, NULL); + if (height > -1) + XtVaSetValues((Widget) m_mainWidget, XmNheight, height, NULL); +#endif + + SetTitle(title); + + PreResize(); + + m_mdiWindow->setSize(width, height); wxModelessWindows.Append(this); - return FALSE; + return TRUE; +} + +void wxMDIChildFrame::BuildClientArea(WXWidget parent) +{ + m_mainWidget = parent; + + m_frameWidget = (WXWidget) XtVaCreateManagedWidget("main_window", + xmMainWindowWidgetClass, (Widget) m_mainWidget, + XmNresizePolicy, XmRESIZE_NONE, + XmNtopAttachment, XmATTACH_FORM, + XmNbottomAttachment, XmATTACH_FORM, + XmNleftAttachment, XmATTACH_FORM, + XmNrightAttachment, XmATTACH_FORM, + NULL); + + m_workArea = (WXWidget) XtVaCreateWidget("form", + xmFormWidgetClass, (Widget) m_frameWidget, + XmNresizePolicy, XmRESIZE_NONE, + NULL); + + m_clientArea = (WXWidget) XtVaCreateWidget("client", + xmBulletinBoardWidgetClass, (Widget) m_workArea, + XmNmarginWidth, 0, + XmNmarginHeight, 0, + XmNrightAttachment, XmATTACH_FORM, + XmNleftAttachment, XmATTACH_FORM, + XmNtopAttachment, XmATTACH_FORM, + XmNbottomAttachment, XmATTACH_FORM, +// XmNresizePolicy, XmRESIZE_ANY, + NULL); + + XtVaSetValues((Widget) m_frameWidget, + XmNworkWindow, (Widget) m_workArea, + NULL); + + XtManageChild((Widget) m_clientArea); + XtManageChild((Widget) m_workArea); + + wxASSERT_MSG ((wxWidgetHashTable->Get((long)m_workArea) == (wxObject*) NULL), "Widget table clash in frame.cpp") ; + + wxAddWindowToTable((Widget) m_workArea, this); + + XtTranslations ptr ; + + XtOverrideTranslations((Widget) m_workArea, + ptr = XtParseTranslationTable(": resize()")); + + XtFree((char *)ptr); + + XtAddCallback((Widget) m_workArea, XmNfocusCallback, + (XtCallbackProc)wxFrameFocusProc, (XtPointer)this); + + /* + int x = pos.x; int y = pos.y; + int width = size.x; int height = size.y; + + if (x > -1) + XtVaSetValues((Widget) m_mainWidget, XmNx, x, NULL); + if (y > -1) + XtVaSetValues((Widget) m_mainWidget, XmNy, y, NULL); + if (width > -1) + XtVaSetValues((Widget) m_mainWidget, XmNwidth, width, NULL); + if (height > -1) + XtVaSetValues((Widget) m_mainWidget, XmNheight, height, NULL); + */ + + XtManageChild((Widget) m_frameWidget); } + wxMDIChildFrame::~wxMDIChildFrame() { + wxMDIParentFrame* parentFrame = (wxMDIParentFrame*) GetParent() ; + if (parentFrame->GetActiveChild() == this) + parentFrame->SetActiveChild((wxMDIChildFrame*) NULL); + + wxMDIClientWindow* clientWindow = parentFrame->GetClientWindow(); + clientWindow->GetMDICanvas()->remove(m_mdiWindow); + m_mainWidget = (WXWidget) 0; +} + +// Implementation: intercept and act upon raise and lower commands. +void wxMDIChildFrame::OnRaise() +{ + wxMDIParentFrame* parentFrame = (wxMDIParentFrame*) GetParent() ; + wxMDIChildFrame* oldActiveChild = parentFrame->GetActiveChild(); + parentFrame->SetActiveChild(this); + + if (oldActiveChild) + { + wxActivateEvent event(wxEVT_ACTIVATE, FALSE, oldActiveChild->GetId()); + event.SetEventObject( oldActiveChild ); + oldActiveChild->GetEventHandler()->ProcessEvent(event); + } + + wxActivateEvent event(wxEVT_ACTIVATE, TRUE, this->GetId()); + event.SetEventObject( this ); + this->GetEventHandler()->ProcessEvent(event); +} + +void wxMDIChildFrame::OnLower() +{ + wxMDIParentFrame* parentFrame = (wxMDIParentFrame*) GetParent() ; + wxMDIChildFrame* oldActiveChild = parentFrame->GetActiveChild(); + + if (oldActiveChild == this) + { + wxActivateEvent event(wxEVT_ACTIVATE, FALSE, oldActiveChild->GetId()); + event.SetEventObject( oldActiveChild ); + oldActiveChild->GetEventHandler()->ProcessEvent(event); + } + // TODO: unfortunately we don't now know which is the top-most child, + // so make the active child NULL. + parentFrame->SetActiveChild((wxMDIChildFrame*) NULL); } // Set the client size (i.e. leave the calculation of borders etc. // to wxWindows) void wxMDIChildFrame::SetClientSize(int width, int height) { - // TODO + wxFrame::SetClientSize(width, height); +} + +void wxMDIChildFrame::GetClientSize(int* width, int* height) const +{ + wxFrame::GetClientSize(width, height); +} + +void wxMDIChildFrame::SetSize(int x, int y, int width, int height, int sizeFlags) +{ + wxWindow::SetSize(x, y, width, height, sizeFlags); +} + +void wxMDIChildFrame::GetSize(int* width, int* height) const +{ + wxWindow::GetSize(width, height); } void wxMDIChildFrame::GetPosition(int *x, int *y) const { - // TODO + wxWindow::GetPosition(x, y); +} + +bool wxMDIChildFrame::Show(bool show) +{ + m_visibleStatus = show; /* show-&-hide fix */ + return TRUE; } void wxMDIChildFrame::SetMenuBar(wxMenuBar *menu_bar) { // TODO - if (!menu_bar) + // Currently, the menu appears on the child frame. + // It should eventually be recreated on the main frame + // whenever the child is activated. + wxFrame::SetMenuBar(menu_bar); +} + +// Set icon +void wxMDIChildFrame::SetIcon(const wxIcon& icon) +{ + m_icon = icon; + if (m_icon.Ok()) { - m_frameMenuBar = NULL; - return; + /* TODO: doesn't work yet (crashes in XCopyArea) + Pixmap pixmap = (Pixmap) m_icon.GetPixmap(); + m_mdiWindow->setPixmap(pixmap); + */ } - - if (menu_bar->m_menuBarFrame) - return; - m_frameMenuBar = menu_bar; +} + +void wxMDIChildFrame::SetTitle(const wxString& title) +{ + m_title = title; + m_mdiWindow->setTitle(title); + m_mdiWindow->setIconName(title); } // MDI operations void wxMDIChildFrame::Maximize() { - // TODO + m_mdiWindow->maximize(); +} + +void wxMDIChildFrame::Iconize(bool iconize) +{ + if (iconize) + m_mdiWindow->minimize(); + else + m_mdiWindow->restore(); +} + +bool wxMDIChildFrame::IsIconized() const +{ + return m_mdiWindow->minimized(); } void wxMDIChildFrame::Restore() { - // TODO + m_mdiWindow->restore(); } void wxMDIChildFrame::Activate() { - // TODO + m_mdiWindow->raise(); } // Client window wxMDIClientWindow::wxMDIClientWindow() { + m_mdiCanvas = NULL; + m_topWidget = (WXWidget) 0; } wxMDIClientWindow::~wxMDIClientWindow() { + DestroyChildren(); + delete m_mdiCanvas; + + m_mainWidget = (WXWidget) 0; + m_topWidget = (WXWidget) 0; } bool wxMDIClientWindow::CreateClient(wxMDIParentFrame *parent, long style) { - // TODO create client window + m_windowParent = parent; m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE); + m_mdiCanvas = new XsMDICanvas("mdiClientWindow", (Widget) parent->GetClientWidget()); + m_mainWidget = (WXWidget) m_mdiCanvas->GetDrawingArea(); + // m_topWidget = (WXWidget) m_mdiCanvas->GetBase(); + m_topWidget = (WXWidget) (Widget) (*m_mdiCanvas); + + m_mdiCanvas->show(); + + return TRUE; +} + +void wxMDIClientWindow::SetSize(int x, int y, int width, int height, int sizeFlags) +{ + wxWindow::SetSize(x, y, width, height, sizeFlags); +} + +void wxMDIClientWindow::SetClientSize(int width, int height) +{ + wxWindow::SetClientSize(width, height); +} - return FALSE; +void wxMDIClientWindow::GetClientSize(int *width, int *height) const +{ + wxWindow::GetClientSize(width, height); +} + +void wxMDIClientWindow::GetSize(int *width, int *height) const +{ + wxWindow::GetSize(width, height); +} + +void wxMDIClientWindow::GetPosition(int *x, int *y) const +{ + wxWindow::GetPosition(x, y); } // Explicitly call default scroll behaviour