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" 
  27     #include "wx/settings.h" 
  30 #include "wx/evtloop.h" 
  33 #pragma message disable nosimpint 
  37 #include <X11/Shell.h> 
  41 #include <Xm/MwmUtil.h> 
  43 #include <Xm/BulletinB.h> 
  46 #include <Xm/DialogS.h> 
  47 #include <Xm/FileSB.h> 
  48 #include <Xm/RowColumn.h> 
  49 #include <Xm/LabelG.h> 
  50 #include <Xm/AtomMgr.h> 
  52 #include <Xm/Protocols.h> 
  55 #pragma message enable nosimpint 
  58 #include "wx/motif/private.h" 
  60 // A stack of modal_showing flags, since we can't rely 
  61 // on accessing wxDialog::m_modalShowing within 
  62 // wxDialog::Show in case a callback has deleted the wxDialog. 
  63 // static wxList wxModalShowingStack; 
  65 // Lists to keep track of windows, so we can disable/enable them 
  67 wxList wxModalDialogs
; 
  68 extern wxList wxModelessWindows
;  // Frames and modeless dialogs 
  70 #define wxUSE_INVISIBLE_RESIZE 1 
  72 IMPLEMENT_DYNAMIC_CLASS(wxDialog
, wxTopLevelWindow
) 
  74 BEGIN_EVENT_TABLE(wxDialog
, wxTopLevelWindow
) 
  75     EVT_BUTTON(wxID_OK
, wxDialog::OnOK
) 
  76     EVT_BUTTON(wxID_APPLY
, wxDialog::OnApply
) 
  77     EVT_BUTTON(wxID_CANCEL
, wxDialog::OnCancel
) 
  78     EVT_CHAR_HOOK(wxDialog::OnCharHook
) 
  79     EVT_SYS_COLOUR_CHANGED(wxDialog::OnSysColourChanged
) 
  80     EVT_CLOSE(wxDialog::OnCloseWindow
) 
  86     m_modalShowing 
= false; 
  88     m_backgroundColour 
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
); 
  91 bool wxDialog::Create(wxWindow 
*parent
, wxWindowID id
, 
  92                       const wxString
& title
, 
  98     SetExtraStyle(GetExtraStyle() | wxTOPLEVEL_EX_DIALOG
); 
 100     if( !wxTopLevelWindow::Create( parent
, id
, title
, pos
, size
, style
, 
 104     m_modalShowing 
= false; 
 107     m_backgroundColour 
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
); 
 108     m_foregroundColour 
= *wxBLACK
; 
 110     Widget dialogShell 
= (Widget
) m_mainWidget
; 
 114     m_font 
= wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
); 
 117     // Can't remember what this was about... but I think it's necessary. 
 118 #if wxUSE_INVISIBLE_RESIZE 
 120         XtVaSetValues(dialogShell
, XmNx
, pos
.x
, 
 123         XtVaSetValues(dialogShell
, XmNy
, pos
.y
, 
 127         XtVaSetValues(dialogShell
, XmNwidth
, size
.x
, NULL
); 
 129         XtVaSetValues(dialogShell
, XmNheight
, size
.y
, NULL
); 
 132     // Positioning of the dialog doesn't work properly unless the dialog 
 133     // is managed, so we manage without mapping to the screen. 
 134     // To show, we map the shell (actually it's parent). 
 135 #if !wxUSE_INVISIBLE_RESIZE 
 136     Widget shell 
= XtParent(dialogShell
) ; 
 137     XtVaSetValues(shell
, XmNmappedWhenManaged
, False
, NULL
); 
 140 #if !wxUSE_INVISIBLE_RESIZE 
 141     XtManageChild(dialogShell
); 
 142     SetSize(pos
.x
, pos
.y
, size
.x
, size
.y
); 
 145     XtAddEventHandler(dialogShell
,ExposureMask
,False
, 
 146         wxUniversalRepaintProc
, (XtPointer
) this); 
 148     ChangeBackgroundColour(); 
 153 bool wxDialog::XmDoCreateTLW(wxWindow
* parent
, 
 154                              wxWindowID 
WXUNUSED(id
), 
 155                              const wxString
& WXUNUSED(title
), 
 156                              const wxPoint
& WXUNUSED(pos
), 
 157                              const wxSize
& WXUNUSED(size
), 
 158                              long WXUNUSED(style
), 
 159                              const wxString
& name
) 
 161     Widget parentWidget 
= (Widget
) 0; 
 163         parentWidget 
= (Widget
) parent
->GetTopWidget(); 
 165         parentWidget 
= (Widget
) wxTheApp
->GetTopLevelWidget(); 
 167     wxASSERT_MSG( (parentWidget 
!= (Widget
) 0), 
 168                   "Could not find a suitable parent shell for dialog." ); 
 171     XtSetArg (args
[0], XmNdefaultPosition
, False
); 
 172     XtSetArg (args
[1], XmNautoUnmanage
, False
); 
 174         XmCreateBulletinBoardDialog( parentWidget
, 
 175                                      wxConstCast(name
.c_str(), char), 
 177     m_mainWidget 
= (WXWidget
) dialogShell
; 
 179     // We don't want margins, since there is enough elsewhere. 
 180     XtVaSetValues( dialogShell
, 
 183                    XmNresizePolicy
, XmRESIZE_NONE
, 
 187     XtOverrideTranslations(dialogShell
, 
 188         ptr 
= XtParseTranslationTable("<Configure>: resize()")); 
 191     XtRealizeWidget(dialogShell
); 
 193     wxAddWindowToTable( (Widget
)m_mainWidget
, this ); 
 198 void wxDialog::SetModal(bool flag
) 
 201        wxModelessWindows
.DeleteObject(this); 
 203        wxModelessWindows
.Append(this); 
 206 wxDialog::~wxDialog() 
 208     m_isBeingDeleted 
= true; 
 214         XtRemoveEventHandler((Widget
) m_mainWidget
, ExposureMask
, False
, 
 215                              wxUniversalRepaintProc
, (XtPointer
) this); 
 218     m_modalShowing 
= false; 
 220 #if !wxUSE_INVISIBLE_RESIZE 
 223         XtUnmapWidget((Widget
) m_mainWidget
); 
 231         wxDeleteWindowFromTable( (Widget
)m_mainWidget 
); 
 232         XtDestroyWidget( (Widget
)m_mainWidget 
); 
 236 // By default, pressing escape cancels the dialog 
 237 void wxDialog::OnCharHook(wxKeyEvent
& event
) 
 239     if (event
.m_keyCode 
== WXK_ESCAPE
) 
 241         // Behaviour changed in 2.0: we'll send a Cancel message 
 242         // to the dialog instead of Close. 
 243         wxCommandEvent 
cancelEvent(wxEVT_COMMAND_BUTTON_CLICKED
, wxID_CANCEL
); 
 244         cancelEvent
.SetEventObject( this ); 
 245         GetEventHandler()->ProcessEvent(cancelEvent
); 
 249     // We didn't process this event. 
 253 void wxDialog::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
) 
 255     XtVaSetValues((Widget
) m_mainWidget
, XmNresizePolicy
, XmRESIZE_ANY
, NULL
); 
 256     wxWindow::DoSetSize(x
, y
, width
, height
, sizeFlags
); 
 257     XtVaSetValues((Widget
) m_mainWidget
, XmNresizePolicy
, XmRESIZE_NONE
, NULL
); 
 260 void wxDialog::DoSetClientSize(int width
, int height
) 
 262     wxWindow::SetSize(-1, -1, width
, height
); 
 265 void wxDialog::SetTitle(const wxString
& title
) 
 267     wxTopLevelWindow::SetTitle( title 
); 
 271         wxXmString 
str( title 
); 
 272         XtVaSetValues( (Widget
)m_mainWidget
, 
 273                        XmNtitle
, title
.c_str(), 
 274                        XmNdialogTitle
, str(), // Roberto Cocchi 
 275                        XmNiconName
, title
.c_str(), 
 280 bool wxDialog::Show( bool show 
) 
 282     if( !wxWindowBase::Show( show 
) ) 
 289         // this usually will result in TransferDataToWindow() being called 
 290         // which will change the controls values so do it before showing as 
 291         // otherwise we could have some flicker 
 297 #if !wxUSE_INVISIBLE_RESIZE 
 298         XtMapWidget(XtParent((Widget
) m_mainWidget
)); 
 300         XtManageChild((Widget
)m_mainWidget
) ; 
 303         XRaiseWindow( XtDisplay( (Widget
)m_mainWidget 
), 
 304                       XtWindow( (Widget
)m_mainWidget
) ); 
 309 #if !wxUSE_INVISIBLE_RESIZE 
 310         XtUnmapWidget(XtParent((Widget
) m_mainWidget
)); 
 312         XtUnmanageChild((Widget
)m_mainWidget
) ; 
 315         XFlush(XtDisplay((Widget
)m_mainWidget
)); 
 316         XSync(XtDisplay((Widget
)m_mainWidget
), False
); 
 322 // Shows a dialog modally, returning a return code 
 323 int wxDialog::ShowModal() 
 327     // after the event loop ran, the widget might already have been destroyed 
 328     WXDisplay
* display 
= (WXDisplay
*)XtDisplay( (Widget
)m_mainWidget 
); 
 332     m_eventLoop 
= new wxEventLoop
; 
 334     m_modalShowing 
= true; 
 335     XtAddGrab((Widget
) m_mainWidget
, True
, False
); 
 339     // Now process all events in case they get sent to a destroyed dialog 
 340     wxFlushEvents( display 
); 
 345     // TODO: is it safe to call this, if the dialog may have been deleted 
 346     // by now? Probably only if we're using delayed deletion of dialogs. 
 347     return GetReturnCode(); 
 350 void wxDialog::EndModal(int retCode
) 
 355     SetReturnCode(retCode
); 
 357     // Strangely, we don't seem to need this now. 
 358     //    XtRemoveGrab((Widget) m_mainWidget); 
 362     m_modalShowing 
= false; 
 369 void wxDialog::OnOK(wxCommandEvent
& WXUNUSED(event
)) 
 371     if ( Validate() && TransferDataFromWindow() ) 
 377             SetReturnCode(wxID_OK
); 
 383 void wxDialog::OnApply(wxCommandEvent
& WXUNUSED(event
)) 
 386         TransferDataFromWindow(); 
 387     // TODO probably need to disable the Apply button until things change again 
 390 void wxDialog::OnCancel(wxCommandEvent
& WXUNUSED(event
)) 
 393         EndModal(wxID_CANCEL
); 
 396         SetReturnCode(wxID_CANCEL
); 
 401 void wxDialog::OnCloseWindow(wxCloseEvent
& WXUNUSED(event
)) 
 403     // We'll send a Cancel message by default, 
 404     // which may close the dialog. 
 405     // Check for looping if the Cancel event handler calls Close(). 
 407     // Note that if a cancel button and handler aren't present in the dialog, 
 408     // nothing will happen when you close the dialog via the window manager, or 
 410     // We wouldn't want to destroy the dialog by default, since the dialog may have been 
 411     // created on the stack. 
 412     // However, this does mean that calling dialog->Close() won't delete the dialog 
 413     // unless the handler for wxID_CANCEL does so. So use Destroy() if you want to be 
 414     // sure to destroy the dialog. 
 415     // The default OnCancel (above) simply ends a modal dialog, and hides a modeless dialog. 
 417     static wxList closing
; 
 419     if ( closing
.Member(this) ) 
 422     closing
.Append(this); 
 424     wxCommandEvent 
cancelEvent(wxEVT_COMMAND_BUTTON_CLICKED
, wxID_CANCEL
); 
 425     cancelEvent
.SetEventObject( this ); 
 426     GetEventHandler()->ProcessEvent(cancelEvent
); // This may close the dialog 
 428     closing
.DeleteObject(this); 
 431 // Destroy the window (delayed, if a managed window) 
 432 bool wxDialog::Destroy() 
 434     if (!wxPendingDelete
.Member(this)) 
 435         wxPendingDelete
.Append(this); 
 439 void wxDialog::OnSysColourChanged(wxSysColourChangedEvent
& WXUNUSED(event
)) 
 441     SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
)); 
 445 void wxDialog::ChangeFont(bool keepOriginalSize
) 
 447     wxWindow::ChangeFont(keepOriginalSize
); 
 450 void wxDialog::ChangeBackgroundColour() 
 453         wxDoChangeBackgroundColour(GetMainWidget(), m_backgroundColour
); 
 456 void wxDialog::ChangeForegroundColour() 
 459         wxDoChangeForegroundColour(GetMainWidget(), m_foregroundColour
);