1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/motif/dialog.cpp 
   3 // Purpose:     wxDialog class 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // For compilers that support precompilation, includes "wx.h". 
  13 #include "wx/wxprec.h" 
  16 #define XtDisplay XTDISPLAY 
  17 #define XtWindow XTWINDOW 
  18 #define XtParent XTPARENT 
  19 #define XtScreen XTSCREEN 
  22 #include "wx/dialog.h" 
  25 #include "wx/settings.h" 
  26 #include "wx/evtloop.h" 
  29 #pragma message disable nosimpint 
  33 #include <X11/Shell.h> 
  37 #include <Xm/MwmUtil.h> 
  39 #include <Xm/BulletinB.h> 
  42 #include <Xm/DialogS.h> 
  43 #include <Xm/FileSB.h> 
  44 #include <Xm/RowColumn.h> 
  45 #include <Xm/LabelG.h> 
  46 #include <Xm/AtomMgr.h> 
  48 #include <Xm/Protocols.h> 
  51 #pragma message enable nosimpint 
  54 #include "wx/motif/private.h" 
  56 // A stack of modal_showing flags, since we can't rely 
  57 // on accessing wxDialog::m_modalShowing within 
  58 // wxDialog::Show in case a callback has deleted the wxDialog. 
  59 // static wxList wxModalShowingStack; 
  61 // Lists to keep track of windows, so we can disable/enable them 
  63 wxList wxModalDialogs
; 
  64 extern wxList wxModelessWindows
;  // Frames and modeless dialogs 
  65 extern wxList wxPendingDelete
; 
  67 #define wxUSE_INVISIBLE_RESIZE 1 
  69 IMPLEMENT_DYNAMIC_CLASS(wxDialog
, wxTopLevelWindow
) 
  71 BEGIN_EVENT_TABLE(wxDialog
, wxTopLevelWindow
) 
  72   EVT_BUTTON(wxID_OK
, wxDialog::OnOK
) 
  73   EVT_BUTTON(wxID_APPLY
, wxDialog::OnApply
) 
  74   EVT_BUTTON(wxID_CANCEL
, wxDialog::OnCancel
) 
  75   EVT_CHAR_HOOK(wxDialog::OnCharHook
) 
  76   EVT_SYS_COLOUR_CHANGED(wxDialog::OnSysColourChanged
) 
  77   EVT_CLOSE(wxDialog::OnCloseWindow
) 
  83     m_modalShowing 
= false; 
  85     m_backgroundColour 
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
); 
  88 bool wxDialog::Create(wxWindow 
*parent
, wxWindowID id
, 
  89                       const wxString
& title
, 
  95     SetExtraStyle(GetExtraStyle() | wxTOPLEVEL_EX_DIALOG
); 
  97     if( !wxTopLevelWindow::Create( parent
, id
, title
, pos
, size
, style
, 
 101     m_modalShowing 
= false; 
 104     m_backgroundColour 
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
); 
 105     m_foregroundColour 
= *wxBLACK
; 
 107     Widget dialogShell 
= (Widget
) m_mainWidget
; 
 108     Widget shell 
= XtParent(dialogShell
) ; 
 112     m_font 
= wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
); 
 115     // Can't remember what this was about... but I think it's necessary. 
 116 #if wxUSE_INVISIBLE_RESIZE 
 118         XtVaSetValues(dialogShell
, XmNx
, pos
.x
, 
 121         XtVaSetValues(dialogShell
, XmNy
, pos
.y
, 
 125         XtVaSetValues(dialogShell
, XmNwidth
, size
.x
, NULL
); 
 127         XtVaSetValues(dialogShell
, XmNheight
, size
.y
, NULL
); 
 130     // Positioning of the dialog doesn't work properly unless the dialog 
 131     // is managed, so we manage without mapping to the screen. 
 132     // To show, we map the shell (actually it's parent). 
 133 #if !wxUSE_INVISIBLE_RESIZE 
 134     XtVaSetValues(shell
, XmNmappedWhenManaged
, False
, NULL
); 
 137 #if !wxUSE_INVISIBLE_RESIZE 
 138     XtManageChild(dialogShell
); 
 139     SetSize(pos
.x
, pos
.y
, size
.x
, size
.y
); 
 142     XtAddEventHandler(dialogShell
,ExposureMask
,False
, 
 143         wxUniversalRepaintProc
, (XtPointer
) this); 
 145     ChangeBackgroundColour(); 
 150 bool wxDialog::XmDoCreateTLW(wxWindow
* parent
, 
 151                              wxWindowID 
WXUNUSED(id
), 
 152                              const wxString
& WXUNUSED(title
), 
 153                              const wxPoint
& WXUNUSED(pos
), 
 154                              const wxSize
& WXUNUSED(size
), 
 155                              long WXUNUSED(style
), 
 156                              const wxString
& name
) 
 158     Widget parentWidget 
= (Widget
) 0; 
 160         parentWidget 
= (Widget
) parent
->GetTopWidget(); 
 162         parentWidget 
= (Widget
) wxTheApp
->GetTopLevelWidget(); 
 164     wxASSERT_MSG( (parentWidget 
!= (Widget
) 0), 
 165                   "Could not find a suitable parent shell for dialog." ); 
 168     XtSetArg (args
[0], XmNdefaultPosition
, False
); 
 169     XtSetArg (args
[1], XmNautoUnmanage
, False
); 
 171         XmCreateBulletinBoardDialog( parentWidget
, 
 172                                      wxConstCast(name
.c_str(), char), 
 174     m_mainWidget 
= (WXWidget
) dialogShell
; 
 176     // We don't want margins, since there is enough elsewhere. 
 177     XtVaSetValues( dialogShell
, 
 180                    XmNresizePolicy
, XmRESIZE_NONE
, 
 184     XtOverrideTranslations(dialogShell
, 
 185         ptr 
= XtParseTranslationTable("<Configure>: resize()")); 
 188     XtRealizeWidget(dialogShell
); 
 190     wxAddWindowToTable( (Widget
)m_mainWidget
, this ); 
 195 void wxDialog::SetModal(bool flag
) 
 198 #pragma message disable codcauunr 
 201         m_windowStyle 
|= wxDIALOG_MODAL 
; 
 203         if ( m_windowStyle 
& wxDIALOG_MODAL 
) 
 204             m_windowStyle 
-= wxDIALOG_MODAL 
; 
 206         wxModelessWindows
.DeleteObject(this); 
 208             wxModelessWindows
.Append(this); 
 210 #pragma message enable codcauunr 
 214 wxDialog::~wxDialog() 
 216     m_isBeingDeleted 
= true; 
 222         XtRemoveEventHandler((Widget
) m_mainWidget
, ExposureMask
, False
, 
 223                              wxUniversalRepaintProc
, (XtPointer
) this); 
 226     m_modalShowing 
= false; 
 228 #if !wxUSE_INVISIBLE_RESIZE 
 231         XtUnmapWidget((Widget
) m_mainWidget
); 
 239         wxDeleteWindowFromTable( (Widget
)m_mainWidget 
); 
 240         XtDestroyWidget( (Widget
)m_mainWidget 
); 
 244 // By default, pressing escape cancels the dialog 
 245 void wxDialog::OnCharHook(wxKeyEvent
& event
) 
 247     if (event
.m_keyCode 
== WXK_ESCAPE
) 
 249         // Behaviour changed in 2.0: we'll send a Cancel message 
 250         // to the dialog instead of Close. 
 251         wxCommandEvent 
cancelEvent(wxEVT_COMMAND_BUTTON_CLICKED
, wxID_CANCEL
); 
 252         cancelEvent
.SetEventObject( this ); 
 253         GetEventHandler()->ProcessEvent(cancelEvent
); 
 257     // We didn't process this event. 
 261 void wxDialog::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
) 
 263     XtVaSetValues((Widget
) m_mainWidget
, XmNresizePolicy
, XmRESIZE_ANY
, NULL
); 
 264     wxWindow::DoSetSize(x
, y
, width
, height
, sizeFlags
); 
 265     XtVaSetValues((Widget
) m_mainWidget
, XmNresizePolicy
, XmRESIZE_NONE
, NULL
); 
 268 void wxDialog::DoSetClientSize(int width
, int height
) 
 270     wxWindow::SetSize(-1, -1, width
, height
); 
 273 void wxDialog::SetTitle(const wxString
& title
) 
 275     wxTopLevelWindow::SetTitle( title 
); 
 279         wxXmString 
str( title 
); 
 280         XtVaSetValues( (Widget
)m_mainWidget
, 
 281                        XmNtitle
, title
.c_str(), 
 282                        XmNdialogTitle
, str(), // Roberto Cocchi 
 283                        XmNiconName
, title
.c_str(), 
 288 bool wxDialog::Show( bool show 
) 
 290     if( !wxWindowBase::Show( show 
) ) 
 297         // this usually will result in TransferDataToWindow() being called 
 298         // which will change the controls values so do it before showing as 
 299         // otherwise we could have some flicker 
 305 #if !wxUSE_INVISIBLE_RESIZE 
 306         XtMapWidget(XtParent((Widget
) m_mainWidget
)); 
 308         XtManageChild((Widget
)m_mainWidget
) ; 
 311         XRaiseWindow( XtDisplay( (Widget
)m_mainWidget 
), 
 312                       XtWindow( (Widget
)m_mainWidget
) ); 
 317 #if !wxUSE_INVISIBLE_RESIZE 
 318         XtUnmapWidget(XtParent((Widget
) m_mainWidget
)); 
 320         XtUnmanageChild((Widget
)m_mainWidget
) ; 
 323         XFlush(XtDisplay((Widget
)m_mainWidget
)); 
 324         XSync(XtDisplay((Widget
)m_mainWidget
), False
); 
 330 // Shows a dialog modally, returning a return code 
 331 int wxDialog::ShowModal() 
 333     m_windowStyle 
|= wxDIALOG_MODAL
; 
 337     // after the event loop ran, the widget might already have been destroyed 
 338     WXDisplay
* display 
= (WXDisplay
*)XtDisplay( (Widget
)m_mainWidget 
); 
 342     m_eventLoop 
= new wxEventLoop
; 
 344     m_modalShowing 
= true; 
 345     XtAddGrab((Widget
) m_mainWidget
, True
, False
); 
 349     // Now process all events in case they get sent to a destroyed dialog 
 350     wxFlushEvents( display 
); 
 355     // TODO: is it safe to call this, if the dialog may have been deleted 
 356     // by now? Probably only if we're using delayed deletion of dialogs. 
 357     return GetReturnCode(); 
 360 void wxDialog::EndModal(int retCode
) 
 365     SetReturnCode(retCode
); 
 367     // Strangely, we don't seem to need this now. 
 368     //    XtRemoveGrab((Widget) m_mainWidget); 
 372     m_modalShowing 
= false; 
 379 void wxDialog::OnOK(wxCommandEvent
& WXUNUSED(event
)) 
 381     if ( Validate() && TransferDataFromWindow() ) 
 387             SetReturnCode(wxID_OK
); 
 393 void wxDialog::OnApply(wxCommandEvent
& WXUNUSED(event
)) 
 396         TransferDataFromWindow(); 
 397     // TODO probably need to disable the Apply button until things change again 
 400 void wxDialog::OnCancel(wxCommandEvent
& WXUNUSED(event
)) 
 403         EndModal(wxID_CANCEL
); 
 406         SetReturnCode(wxID_CANCEL
); 
 411 void wxDialog::OnCloseWindow(wxCloseEvent
& WXUNUSED(event
)) 
 413     // We'll send a Cancel message by default, 
 414     // which may close the dialog. 
 415     // Check for looping if the Cancel event handler calls Close(). 
 417     // Note that if a cancel button and handler aren't present in the dialog, 
 418     // nothing will happen when you close the dialog via the window manager, or 
 420     // We wouldn't want to destroy the dialog by default, since the dialog may have been 
 421     // created on the stack. 
 422     // However, this does mean that calling dialog->Close() won't delete the dialog 
 423     // unless the handler for wxID_CANCEL does so. So use Destroy() if you want to be 
 424     // sure to destroy the dialog. 
 425     // The default OnCancel (above) simply ends a modal dialog, and hides a modeless dialog. 
 427     static wxList closing
; 
 429     if ( closing
.Member(this) ) 
 432     closing
.Append(this); 
 434     wxCommandEvent 
cancelEvent(wxEVT_COMMAND_BUTTON_CLICKED
, wxID_CANCEL
); 
 435     cancelEvent
.SetEventObject( this ); 
 436     GetEventHandler()->ProcessEvent(cancelEvent
); // This may close the dialog 
 438     closing
.DeleteObject(this); 
 441 // Destroy the window (delayed, if a managed window) 
 442 bool wxDialog::Destroy() 
 444     if (!wxPendingDelete
.Member(this)) 
 445         wxPendingDelete
.Append(this); 
 449 void wxDialog::OnSysColourChanged(wxSysColourChangedEvent
& WXUNUSED(event
)) 
 451     SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
)); 
 455 void wxDialog::ChangeFont(bool keepOriginalSize
) 
 457     wxWindow::ChangeFont(keepOriginalSize
); 
 460 void wxDialog::ChangeBackgroundColour() 
 463         wxDoChangeBackgroundColour(GetMainWidget(), m_backgroundColour
); 
 466 void wxDialog::ChangeForegroundColour() 
 469         wxDoChangeForegroundColour(GetMainWidget(), m_foregroundColour
);