home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / os2 / dialog.cpp < prev    next >
C/C++ Source or Header  |  2002-11-09  |  13KB  |  451 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        dialog.cpp
  3. // Purpose:     wxDialog class
  4. // Author:      David Webster
  5. // Modified by:
  6. // Created:     10/14/99
  7. // RCS-ID:      $Id: DIALOG.CPP,v 1.15.2.1 2002/10/28 23:24:09 DW Exp $
  8. // Copyright:   (c) David Webster
  9. // Licence:     wxWindows licence
  10. /////////////////////////////////////////////////////////////////////////////
  11.  
  12. // For compilers that support precompilation, includes "wx.h".
  13. #include "wx/wxprec.h"
  14.  
  15. #ifndef WX_PRECOMP
  16. #include "wx/dialog.h"
  17. #include "wx/utils.h"
  18. #include "wx/frame.h"
  19. #include "wx/app.h"
  20. #include "wx/settings.h"
  21. #include "wx/intl.h"
  22. #include "wx/log.h"
  23. #endif
  24.  
  25. #include "wx/os2/private.h"
  26. #include "wx/log.h"
  27.  
  28. #define wxDIALOG_DEFAULT_X 300
  29. #define wxDIALOG_DEFAULT_Y 300
  30.  
  31. #define wxDIALOG_DEFAULT_WIDTH 500
  32. #define wxDIALOG_DEFAULT_HEIGHT 500
  33.  
  34. wxWindowList wxModalDialogs;
  35.  
  36. IMPLEMENT_DYNAMIC_CLASS(wxDialog, wxTopLevelWindow)
  37.  
  38. BEGIN_EVENT_TABLE(wxDialog, wxDialogBase)
  39.     EVT_BUTTON(wxID_OK, wxDialog::OnOK)
  40.     EVT_BUTTON(wxID_APPLY, wxDialog::OnApply)
  41.     EVT_BUTTON(wxID_CANCEL, wxDialog::OnCancel)
  42.     EVT_CHAR_HOOK(wxDialog::OnCharHook)
  43.     EVT_SYS_COLOUR_CHANGED(wxDialog::OnSysColourChanged)
  44.     EVT_CLOSE(wxDialog::OnCloseWindow)
  45. END_EVENT_TABLE()
  46.  
  47. void wxDialog::Init()
  48. {
  49.     m_pOldFocus = (wxWindow *)NULL;
  50.     m_isShown = FALSE;
  51.     m_pWindowDisabler = (wxWindowDisabler *)NULL;
  52.     SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
  53. } // end of wxDialog::Init
  54.  
  55. bool wxDialog::Create(
  56.   wxWindow*                         pParent
  57. , wxWindowID                        vId
  58. , const wxString&                   rsTitle
  59. , const wxPoint&                    rPos
  60. , const wxSize&                     rSize
  61. , long                              lStyle
  62. , const wxString&                   rsName
  63. )
  64. {
  65.     long                            lX = rPos.x;
  66.     long                            lY = rPos.y;
  67.     long                            lWidth = rSize.x;
  68.     long                            lHeight = rSize.y;
  69.     const char*                     zDlg;
  70.     WXDWORD                         dwExtendedStyle = 0L;
  71.     HWND                            hWnd;
  72.  
  73.     Init();
  74.     SetExtraStyle(GetExtraStyle() | wxTOPLEVEL_EX_DIALOG);
  75.  
  76.     //
  77.     // Save focus before doing anything which can potentially change it
  78.     //
  79.     m_pOldFocus = FindFocus();
  80.  
  81.     //
  82.     // All dialogs should really have this style
  83.     //
  84.     lStyle |= wxTAB_TRAVERSAL;
  85.  
  86.     if (!wxTopLevelWindow::Create( pParent
  87.                                   ,vId
  88.                                   ,rsTitle
  89.                                   ,rPos
  90.                                   ,rSize
  91.                                   ,lStyle
  92.                                   ,rsName
  93.                                  ))
  94.         return FALSE;
  95.     SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
  96.  
  97.     //
  98.     // Must defer setting the title until after dialog is created and sized
  99.     //
  100.     if (!rsTitle.IsNull())
  101.         SetTitle(rsTitle);
  102.     return TRUE;
  103. } // end of wxDialog::Create
  104.  
  105. void wxDialog::SetModal(
  106.   bool                              bFlag
  107. )
  108. {
  109.     if (bFlag)
  110.     {
  111.         m_windowStyle |= wxDIALOG_MODAL ;
  112.         wxModelessWindows.DeleteObject(this);
  113.     }
  114.     else
  115.     {
  116.         m_windowStyle &= ~wxDIALOG_MODAL ;
  117.         wxModelessWindows.Append(this);
  118.     }
  119. } // end of wxDialog::SetModal
  120.  
  121. wxDialog::~wxDialog()
  122. {
  123.     m_isBeingDeleted = TRUE;
  124.     Show(FALSE);
  125. } // end of wxDialog::~wxDialog
  126.  
  127. //
  128. // By default, pressing escape cancels the dialog
  129. //
  130. void wxDialog::OnCharHook(
  131.   wxKeyEvent&                       rEvent
  132. )
  133. {
  134.     if (GetHWND())
  135.     {
  136.         if (rEvent.m_keyCode == WXK_ESCAPE)
  137.         {
  138.             //
  139.             // Behaviour changed in 2.0: we'll send a Cancel message
  140.             // to the dialog instead of Close.
  141.             //
  142.             wxCommandEvent          vCancelEvent( wxEVT_COMMAND_BUTTON_CLICKED
  143.                                                  ,wxID_CANCEL
  144.                                                 );
  145.  
  146.             vCancelEvent.SetEventObject( this );
  147.             GetEventHandler()->ProcessEvent(vCancelEvent);
  148.  
  149.             //
  150.             // Ensure that there is another message for this window so the
  151.             // ShowModal loop will exit and won't get stuck in GetMessage().
  152.             //
  153.             ::WinPostMsg(GetHwnd(), WM_NULL, 0, 0);
  154.             return;
  155.         }
  156.     }
  157.     // We didn't process this event.
  158.     rEvent.Skip();
  159. }
  160.  
  161. // ----------------------------------------------------------------------------
  162. // showing the dialogs
  163. // ----------------------------------------------------------------------------
  164.  
  165. bool wxDialog::IsModal() const
  166. {
  167.     return (GetWindowStyleFlag() & wxDIALOG_MODAL) != 0;
  168. } // end of wxDialog::IsModal
  169.  
  170. bool wxDialog::IsModalShowing() const
  171. {
  172.     return wxModalDialogs.Find((wxDialog *)this) != NULL; // const_cast
  173. } // end of wxDialog::IsModalShowing
  174.  
  175. void wxDialog::DoShowModal()
  176. {
  177.     wxWindow*                       pParent = GetParent();
  178.     wxWindow*                       pOldFocus = m_pOldFocus;
  179.     HWND                            hWndOldFocus = 0;
  180.  
  181.     wxCHECK_RET( !IsModalShowing(), _T("DoShowModal() called twice") );
  182.     wxCHECK_RET( IsModal(), _T("can't DoShowModal() modeless dialog") );
  183.  
  184.     wxModalDialogs.Append(this);
  185.     if (pOldFocus)
  186.         hWndOldFocus = (HWND)pOldFocus->GetHWND();
  187.  
  188.     //
  189.     // Remember where the focus was
  190.     //
  191.     if (!pOldFocus)
  192.     {
  193.         pOldFocus = pParent;
  194.         if (pParent)
  195.             hWndOldFocus = GetHwndOf(pParent);
  196.     }
  197.  
  198.     //
  199.     // Disable all other app windows
  200.     //
  201.     wxASSERT_MSG(!m_pWindowDisabler, _T("disabling windows twice?"));
  202.  
  203.     //
  204.     // Disables other app windows and window proc message processing
  205.     // until WinDismissDlg called
  206.     //
  207.     ::WinProcessDlg((HWND)GetHwnd());
  208.  
  209.     //
  210.     // Before entering the modal loop, reset the "is in OnIdle()" flag (see
  211.     // comment in app.cpp)
  212.     //
  213.     extern bool                     gbInOnIdle;
  214.     bool                            bWasInOnIdle = gbInOnIdle;
  215.  
  216.     gbInOnIdle = FALSE;
  217.  
  218.     //
  219.     // Enter the modal loop
  220.     //
  221.     while ( IsModalShowing() )
  222.     {
  223. #if wxUSE_THREADS
  224.         wxMutexGuiLeaveOrEnter();
  225. #endif // wxUSE_THREADS
  226.  
  227.         while ( !wxTheApp->Pending() && wxTheApp->ProcessIdle() )
  228.             ;
  229.  
  230.         // a message came or no more idle processing to do
  231.         wxTheApp->DoMessage();
  232.     }
  233.     gbInOnIdle = bWasInOnIdle;
  234.  
  235.     //
  236.     // Snd restore focus
  237.     // Note that this code MUST NOT access the dialog object's data
  238.     // in case the object has been deleted (which will be the case
  239.     // for a modal dialog that has been destroyed before calling EndModal).
  240.     //
  241.     if (pOldFocus && (pOldFocus != this) && ::WinIsWindow(vHabmain, hWndOldFocus))
  242.     {
  243.         //
  244.         // This is likely to prove that the object still exists
  245.         //
  246.         if (wxFindWinFromHandle((WXHWND) hWndOldFocus) == pOldFocus)
  247.             pOldFocus->SetFocus();
  248.     }
  249. } // end of wxDialog::DoShowModal
  250.  
  251. bool wxDialog::Show(
  252.   bool                              bShow
  253. )
  254. {
  255.     if (!bShow)
  256.     {
  257.         //
  258.         // If we had disabled other app windows, reenable them back now because
  259.         // if they stay disabled Windows will activate another window (one
  260.         // which is enabled, anyhow) and we will lose activation.  We really don't
  261.         // do this in OS/2 since PM does this for us.
  262.         //
  263.         if (m_pWindowDisabler)
  264.         {
  265.             delete m_pWindowDisabler;
  266.             m_pWindowDisabler = NULL;
  267.         }
  268.     }
  269.  
  270.     //
  271.     // ShowModal() may be called for already shown dialog
  272.     //
  273.     if (!wxDialogBase::Show(bShow) && !(bShow && IsModal()))
  274.     {
  275.         //
  276.         // Nothing to do
  277.         //
  278.         return FALSE;
  279.     }
  280.  
  281.     if (bShow)
  282.     {
  283.         //
  284.         // Usually will result in TransferDataToWindow() being called
  285.         //
  286.         InitDialog();
  287.     }
  288.  
  289.     if (GetTitle().c_str())
  290.         ::WinSetWindowText((HWND)GetHwnd(), GetTitle().c_str());
  291.     if (IsModal())
  292.     {
  293.         if (bShow)
  294.         {
  295.             //
  296.             // Modal dialog needs a parent window, so try to find one
  297.             //
  298.             if (!GetParent())
  299.             {
  300.                 wxWindow*           pParent = wxTheApp->GetTopWindow();
  301.  
  302.                 if ( pParent && pParent != this && pParent->IsShown() )
  303.                 {
  304.                     //
  305.                     // Use it
  306.                     //
  307.                     m_parent = pParent;
  308.  
  309.                 }
  310.             }
  311.             DoShowModal();
  312.         }
  313.         else // end of modal dialog
  314.         {
  315.             //
  316.             // This will cause IsModalShowing() return FALSE and our local
  317.             // message loop will terminate
  318.             //
  319.             wxModalDialogs.DeleteObject(this);
  320.         }
  321.     }
  322.     return TRUE;
  323. } // end of wxDialog::Show
  324.  
  325. //
  326. // Replacement for Show(TRUE) for modal dialogs - returns return code
  327. //
  328. int wxDialog::ShowModal()
  329. {
  330.     if (!IsModal())
  331.     {
  332.         SetModal(TRUE);
  333.     }
  334.     Show(TRUE);
  335.     return GetReturnCode();
  336. } // end of wxDialog::ShowModal
  337.  
  338. void wxDialog::EndModal(
  339.   int                               nRetCode
  340. )
  341. {
  342.     SetReturnCode(nRetCode);
  343.     Show(FALSE);
  344.     ::WinDismissDlg((HWND)GetHwnd(), nRetCode);
  345. } // end of wxDialog::EndModal
  346.  
  347. // ----------------------------------------------------------------------------
  348. // wxWin event handlers
  349. // ----------------------------------------------------------------------------
  350.  
  351. void wxDialog::OnApply(
  352.   wxCommandEvent&                   rEvent
  353. )
  354. {
  355.     if (Validate())
  356.         TransferDataFromWindow();
  357. } // end of wxDialog::OnApply
  358.  
  359. // Standard buttons
  360. void wxDialog::OnOK(
  361.   wxCommandEvent&                   rEvent
  362. )
  363. {
  364.     if ( Validate() && TransferDataFromWindow() )
  365.     {
  366.         EndModal(wxID_OK);
  367.     }
  368. } // end of wxDialog::OnOK
  369.  
  370. void wxDialog::OnCancel(
  371.   wxCommandEvent&                   rEvent
  372. )
  373. {
  374.     EndModal(wxID_CANCEL);
  375. } // end of wxDialog::OnCancel
  376.  
  377. void wxDialog::OnCloseWindow(
  378.   wxCloseEvent&                     rEvent
  379. )
  380. {
  381.     //
  382.     // We'll send a Cancel message by default,
  383.     // which may close the dialog.
  384.     // Check for looping if the Cancel event handler calls Close().
  385.     //
  386.     // Note that if a cancel button and handler aren't present in the dialog,
  387.     // nothing will happen when you close the dialog via the window manager, or
  388.     // via Close().
  389.     // We wouldn't want to destroy the dialog by default, since the dialog may have been
  390.     // created on the stack.
  391.     // However, this does mean that calling dialog->Close() won't delete the dialog
  392.     // unless the handler for wxID_CANCEL does so. So use Destroy() if you want to be
  393.     // sure to destroy the dialog.
  394.     // The default OnCancel (above) simply ends a modal dialog, and hides a modeless dialog.
  395.     //
  396.  
  397.     //
  398.     // Ugh???  This is not good but until I figure out a global list it'll have to do
  399.     //
  400.     static wxList closing;
  401.  
  402.     if ( closing.Member(this) )
  403.         return;
  404.  
  405.     closing.Append(this);
  406.  
  407.     wxCommandEvent                  vCancelEvent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
  408.  
  409.     vCancelEvent.SetEventObject( this );
  410.     GetEventHandler()->ProcessEvent(vCancelEvent); // This may close the dialog
  411.  
  412.     closing.DeleteObject(this);
  413. } // end of wxDialog::OnCloseWindow
  414.  
  415. void wxDialog::OnSysColourChanged(
  416.   wxSysColourChangedEvent&          rEvent
  417. )
  418. {
  419.     SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
  420.     Refresh();
  421. } // end of wxDialog::OnSysColourChanged
  422.  
  423. MRESULT wxDialog::OS2WindowProc(
  424.   WXUINT                            uMessage
  425. , WXWPARAM                          wParam
  426. , WXLPARAM                          lParam
  427. )
  428. {
  429.     MRESULT                         rc = 0;
  430.     bool                            bProcessed = FALSE;
  431.  
  432.     switch (uMessage)
  433.     {
  434.         case WM_CLOSE:
  435.             //
  436.             // If we can't close, tell the system that we processed the
  437.             // message - otherwise it would close us
  438.             //
  439.             bProcessed = !Close();
  440.             break;
  441.     }
  442.  
  443.     if (!bProcessed)
  444.         rc = wxWindow::OS2WindowProc( uMessage
  445.                                      ,wParam
  446.                                      ,lParam
  447.                                     );
  448.     return rc;
  449. } // end of wxDialog::OS2WindowProc
  450.  
  451.