1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/dlgcmn.cpp
3 // Purpose: common (to all ports) wxDialog functions
4 // Author: Vadim Zeitlin
8 // Copyright: (c) Vadim Zeitlin
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
27 #include "wx/dialog.h"
31 #include "wx/button.h"
32 #include "wx/dcclient.h"
34 #include "wx/settings.h"
35 #include "wx/stattext.h"
37 #include "wx/containr.h"
40 #include "wx/statline.h"
41 #include "wx/sysopt.h"
42 #include "wx/module.h"
43 #include "wx/private/stattext.h"
44 #include "wx/bookctrl.h"
45 #include "wx/scrolwin.h"
48 #include "wx/display.h"
51 // ----------------------------------------------------------------------------
53 // ----------------------------------------------------------------------------
55 BEGIN_EVENT_TABLE(wxDialogBase
, wxTopLevelWindow
)
56 EVT_BUTTON(wxID_ANY
, wxDialogBase
::OnButton
)
58 EVT_CLOSE(wxDialogBase
::OnCloseWindow
)
60 EVT_CHAR_HOOK(wxDialogBase
::OnCharHook
)
63 wxDialogLayoutAdapter
* wxDialogBase
::sm_layoutAdapter
= NULL
;
64 bool wxDialogBase
::sm_layoutAdaptation
= false;
66 void wxDialogBase
::Init()
69 m_affirmativeId
= wxID_OK
;
70 m_escapeId
= wxID_ANY
;
71 m_layoutAdaptationLevel
= 3;
72 m_layoutAdaptationDone
= FALSE
;
73 m_layoutAdaptationMode
= wxDIALOG_ADAPTATION_MODE_DEFAULT
;
75 // the dialogs have this flag on by default to prevent the events from the
76 // dialog controls from reaching the parent frame which is usually
77 // undesirable and can lead to unexpected and hard to find bugs
78 SetExtraStyle(GetExtraStyle() | wxWS_EX_BLOCK_EVENTS
);
81 wxWindow
*wxDialogBase
::CheckIfCanBeUsedAsParent(wxWindow
*parent
) const
83 extern WXDLLIMPEXP_DATA_CORE(wxList
) wxPendingDelete
;
85 if ( wxPendingDelete
.Member(parent
) || parent
->IsBeingDeleted() )
87 // this window is being deleted and we shouldn't create any children
92 if ( parent
->HasExtraStyle(wxWS_EX_TRANSIENT
) )
94 // this window is not being deleted yet but it's going to disappear
95 // soon so still don't parent this window under it
99 if ( !parent
->IsShownOnScreen() )
101 // using hidden parent won't work correctly neither
105 if ( parent
== this )
107 // not sure if this can really happen but it doesn't hurt to guard
108 // against this clearly invalid situation
115 wxWindow
*wxDialogBase
::GetParentForModalDialog(wxWindow
*parent
) const
117 // creating a parent-less modal dialog will result (under e.g. wxGTK2)
118 // in an unfocused dialog, so try to find a valid parent for it unless we
119 // were explicitly asked not to
120 if ( HasFlag(wxDIALOG_NO_PARENT
) )
123 // by default, use the parent specified in the ctor
125 parent
= GetParent();
127 // first try the given parent
129 parent
= CheckIfCanBeUsedAsParent(wxGetTopLevelParent(parent
));
131 // then the currently active window
133 parent
= CheckIfCanBeUsedAsParent(wxGetActiveWindow());
135 // and finally the application main window
137 parent
= CheckIfCanBeUsedAsParent(wxTheApp
->GetTopWindow());
144 class wxTextSizerWrapper
: public wxTextWrapper
147 wxTextSizerWrapper(wxWindow
*win
)
153 wxSizer
*CreateSizer(const wxString
& text
, int widthMax
)
155 m_sizer
= new wxBoxSizer(wxVERTICAL
);
156 Wrap(m_win
, text
, widthMax
);
161 virtual void OnOutputLine(const wxString
& line
)
165 m_sizer
->Add(new wxStaticText(m_win
, wxID_ANY
, line
));
167 else // empty line, no need to create a control for it
170 m_hLine
= m_win
->GetCharHeight();
172 m_sizer
->Add(5, m_hLine
);
182 wxSizer
*wxDialogBase
::CreateTextSizer(const wxString
& message
)
184 // I admit that this is complete bogus, but it makes
185 // message boxes work for pda screens temporarily..
187 const bool is_pda
= wxSystemSettings
::GetScreenType() <= wxSYS_SCREEN_PDA
;
190 widthMax
= wxSystemSettings
::GetMetric( wxSYS_SCREEN_X
) - 25;
193 // '&' is used as accel mnemonic prefix in the wxWidgets controls but in
194 // the static messages created by CreateTextSizer() (used by wxMessageBox,
195 // for example), we don't want this special meaning, so we need to quote it
196 wxString
text(message
);
197 text
.Replace(_T("&"), _T("&&"));
199 wxTextSizerWrapper
wrapper(this);
201 return wrapper
.CreateSizer(text
, widthMax
);
204 #endif // wxUSE_STATTEXT
206 wxSizer
*wxDialogBase
::CreateButtonSizer(long flags
)
208 #ifdef __SMARTPHONE__
209 wxDialog
* dialog
= (wxDialog
*) this;
211 dialog
->SetLeftMenu(wxID_OK
);
213 if ( flags
& wxCANCEL
)
214 dialog
->SetRightMenu(wxID_CANCEL
);
217 dialog
->SetLeftMenu(wxID_YES
);
220 dialog
->SetRightMenu(wxID_NO
);
223 #else // !__SMARTPHONE__
228 // PocketPC guidelines recommend for Ok/Cancel dialogs to use OK button
229 // located inside caption bar and implement Cancel functionality through
230 // Undo outside dialog. As native behaviour this will be default here but
231 // can be replaced with real wxButtons by setting the option below to 1
232 if ( (flags
& ~(wxCANCEL
|wxNO_DEFAULT
)) != wxOK
||
233 wxSystemOptions
::GetOptionInt(wxT("wince.dialog.real-ok-cancel")) )
234 #endif // __POCKETPC__
236 return CreateStdDialogButtonSizer(flags
);
240 #endif // __POCKETPC__
242 #else // !wxUSE_BUTTON
246 #endif // wxUSE_BUTTON/!wxUSE_BUTTON
248 #endif // __SMARTPHONE__/!__SMARTPHONE__
251 wxSizer
*wxDialogBase
::CreateSeparatedButtonSizer(long flags
)
253 wxSizer
*sizer
= CreateButtonSizer(flags
);
257 // Mac Human Interface Guidelines recommend not to use static lines as
259 #if wxUSE_STATLINE && !defined(__WXMAC__)
260 wxBoxSizer
*topsizer
= new wxBoxSizer(wxVERTICAL
);
261 topsizer
->Add(new wxStaticLine(this),
262 wxSizerFlags().Expand().DoubleBorder(wxBOTTOM
));
263 topsizer
->Add(sizer
, wxSizerFlags().Expand());
265 #endif // wxUSE_STATLINE
272 wxStdDialogButtonSizer
*wxDialogBase
::CreateStdDialogButtonSizer( long flags
)
274 wxStdDialogButtonSizer
*sizer
= new wxStdDialogButtonSizer();
277 wxButton
*yes
= NULL
;
282 ok
= new wxButton(this, wxID_OK
);
283 sizer
->AddButton(ok
);
286 if (flags
& wxCANCEL
)
288 wxButton
*cancel
= new wxButton(this, wxID_CANCEL
);
289 sizer
->AddButton(cancel
);
294 yes
= new wxButton(this, wxID_YES
);
295 sizer
->AddButton(yes
);
300 no
= new wxButton(this, wxID_NO
);
301 sizer
->AddButton(no
);
306 wxButton
*apply
= new wxButton(this, wxID_APPLY
);
307 sizer
->AddButton(apply
);
312 wxButton
*close
= new wxButton(this, wxID_CLOSE
);
313 sizer
->AddButton(close
);
318 wxButton
*help
= new wxButton(this, wxID_HELP
);
319 sizer
->AddButton(help
);
322 if (flags
& wxNO_DEFAULT
)
345 SetAffirmativeId(wxID_OK
);
346 else if (flags
& wxYES
)
347 SetAffirmativeId(wxID_YES
);
354 #endif // wxUSE_BUTTON
356 // ----------------------------------------------------------------------------
357 // standard buttons handling
358 // ----------------------------------------------------------------------------
360 void wxDialogBase
::EndDialog(int rc
)
368 void wxDialogBase
::AcceptAndClose()
370 if ( Validate() && TransferDataFromWindow() )
372 EndDialog(m_affirmativeId
);
376 void wxDialogBase
::SetAffirmativeId(int affirmativeId
)
378 m_affirmativeId
= affirmativeId
;
381 void wxDialogBase
::SetEscapeId(int escapeId
)
383 m_escapeId
= escapeId
;
386 bool wxDialogBase
::EmulateButtonClickIfPresent(int id
)
389 wxButton
*btn
= wxDynamicCast(FindWindow(id
), wxButton
);
391 if ( !btn
|| !btn
->IsEnabled() || !btn
->IsShown() )
394 wxCommandEvent
event(wxEVT_COMMAND_BUTTON_CLICKED
, id
);
395 event
.SetEventObject(btn
);
396 btn
->GetEventHandler()->ProcessEvent(event
);
399 #else // !wxUSE_BUTTON
402 #endif // wxUSE_BUTTON/!wxUSE_BUTTON
405 bool wxDialogBase
::IsEscapeKey(const wxKeyEvent
& event
)
407 // for most platforms, Esc key is used to close the dialogs
408 return event
.GetKeyCode() == WXK_ESCAPE
&&
409 event
.GetModifiers() == wxMOD_NONE
;
412 void wxDialogBase
::OnCharHook(wxKeyEvent
& event
)
414 if ( event
.GetKeyCode() == WXK_ESCAPE
)
416 int idCancel
= GetEscapeId();
420 // don't handle Esc specially at all
424 // this value is special: it means translate Esc to wxID_CANCEL
425 // but if there is no such button, then fall back to wxID_OK
426 if ( EmulateButtonClickIfPresent(wxID_CANCEL
) )
428 idCancel
= GetAffirmativeId();
432 // translate Esc to button press for the button with given id
433 if ( EmulateButtonClickIfPresent(idCancel
) )
441 void wxDialogBase
::OnButton(wxCommandEvent
& event
)
443 const int id
= event
.GetId();
444 if ( id
== GetAffirmativeId() )
448 else if ( id
== wxID_APPLY
)
451 TransferDataFromWindow();
453 // TODO: disable the Apply button until things change again
455 else if ( id
== GetEscapeId() ||
456 (id
== wxID_CANCEL
&& GetEscapeId() == wxID_ANY
) )
458 EndDialog(wxID_CANCEL
);
460 else // not a standard button
466 // ----------------------------------------------------------------------------
467 // other event handlers
468 // ----------------------------------------------------------------------------
470 void wxDialogBase
::OnCloseWindow(wxCloseEvent
& WXUNUSED(event
))
472 // We'll send a Cancel message by default, which may close the dialog.
473 // Check for looping if the Cancel event handler calls Close().
475 // Note that if a cancel button and handler aren't present in the dialog,
476 // nothing will happen when you close the dialog via the window manager, or
477 // via Close(). We wouldn't want to destroy the dialog by default, since
478 // the dialog may have been created on the stack. However, this does mean
479 // that calling dialog->Close() won't delete the dialog unless the handler
480 // for wxID_CANCEL does so. So use Destroy() if you want to be sure to
481 // destroy the dialog. The default OnCancel (above) simply ends a modal
482 // dialog, and hides a modeless dialog.
484 int idCancel
= GetEscapeId();
485 if ( idCancel
== wxID_NONE
)
487 if ( idCancel
== wxID_ANY
)
488 idCancel
= wxID_CANCEL
;
490 // VZ: this is horrible and MT-unsafe. Can't we reuse some of these global
491 // lists here? don't dare to change it now, but should be done later!
492 static wxList closing
;
494 if ( closing
.Member(this) )
497 closing
.Append(this);
499 wxCommandEvent
cancelEvent(wxEVT_COMMAND_BUTTON_CLICKED
, idCancel
);
500 cancelEvent
.SetEventObject( this );
501 GetEventHandler()->ProcessEvent(cancelEvent
); // This may close the dialog
503 closing
.DeleteObject(this);
506 void wxDialogBase
::OnSysColourChanged(wxSysColourChangedEvent
& event
)
509 SetBackgroundColour(wxSystemSettings
::GetColour(wxSYS_COLOUR_3DFACE
));
516 /// Do the adaptation
517 bool wxDialogBase
::DoLayoutAdaptation()
519 if (GetLayoutAdapter())
521 wxWindow
* focusWindow
= wxFindFocusDescendant(this); // from event.h
522 if (GetLayoutAdapter()->DoLayoutAdaptation((wxDialog
*) this))
525 focusWindow
->SetFocus();
535 /// Can we do the adaptation?
536 bool wxDialogBase
::CanDoLayoutAdaptation()
538 // Check if local setting overrides the global setting
539 bool layoutEnabled
= (GetLayoutAdaptationMode() == wxDIALOG_ADAPTATION_MODE_ENABLED
) || (IsLayoutAdaptationEnabled() && (GetLayoutAdaptationMode() != wxDIALOG_ADAPTATION_MODE_DISABLED
));
541 return (layoutEnabled
&& !m_layoutAdaptationDone
&& GetLayoutAdaptationLevel() != 0 && GetLayoutAdapter() != NULL
&& GetLayoutAdapter()->CanDoLayoutAdaptation((wxDialog
*) this));
544 /// Set scrolling adapter class, returning old adapter
545 wxDialogLayoutAdapter
* wxDialogBase
::SetLayoutAdapter(wxDialogLayoutAdapter
* adapter
)
547 wxDialogLayoutAdapter
* oldLayoutAdapter
= sm_layoutAdapter
;
548 sm_layoutAdapter
= adapter
;
549 return oldLayoutAdapter
;
556 IMPLEMENT_CLASS(wxDialogLayoutAdapter
, wxObject
)
558 IMPLEMENT_CLASS(wxStandardDialogLayoutAdapter
, wxDialogLayoutAdapter
)
560 // Allow for caption size on wxWidgets < 2.9
561 #if defined(__WXGTK__) && !wxCHECK_VERSION(2,9,0)
562 #define wxEXTRA_DIALOG_HEIGHT 30
564 #define wxEXTRA_DIALOG_HEIGHT 0
567 /// Indicate that adaptation should be done
568 bool wxStandardDialogLayoutAdapter
::CanDoLayoutAdaptation(wxDialog
* dialog
)
570 if (dialog
->GetSizer())
572 wxSize windowSize
, displaySize
;
573 return MustScroll(dialog
, windowSize
, displaySize
) != 0;
579 bool wxStandardDialogLayoutAdapter
::DoLayoutAdaptation(wxDialog
* dialog
)
581 if (dialog
->GetSizer())
584 wxBookCtrlBase
* bookContentWindow
= wxDynamicCast(dialog
->GetContentWindow(), wxBookCtrlBase
);
586 if (bookContentWindow
)
588 // If we have a book control, make all the pages (that use sizers) scrollable
589 wxWindowList windows
;
590 for (size_t i
= 0; i
< bookContentWindow
->GetPageCount(); i
++)
592 wxWindow
* page
= bookContentWindow
->GetPage(i
);
594 wxScrolledWindow
* scrolledWindow
= wxDynamicCast(page
, wxScrolledWindow
);
596 windows
.Append(scrolledWindow
);
597 else if (!scrolledWindow
&& page
->GetSizer())
599 // Create a scrolled window and reparent
600 scrolledWindow
= CreateScrolledWindow(page
);
601 wxSizer
* oldSizer
= page
->GetSizer();
603 wxSizer
* newSizer
= new wxBoxSizer(wxVERTICAL
);
604 newSizer
->Add(scrolledWindow
,1, wxEXPAND
, 0);
606 page
->SetSizer(newSizer
, false /* don't delete the old sizer */);
608 scrolledWindow
->SetSizer(oldSizer
);
610 ReparentControls(page
, scrolledWindow
);
612 windows
.Append(scrolledWindow
);
616 FitWithScrolling(dialog
, windows
);
619 #endif // wxUSE_BOOKCTRL
621 // If we have an arbitrary dialog, create a scrolling area for the main content, and a button sizer
622 // for the main buttons.
623 wxScrolledWindow
* scrolledWindow
= CreateScrolledWindow(dialog
);
625 int buttonSizerBorder
= 0;
627 // First try to find a wxStdDialogButtonSizer
628 wxSizer
* buttonSizer
= FindButtonSizer(true /* find std button sizer */, dialog
, dialog
->GetSizer(), buttonSizerBorder
);
630 // Next try to find a wxBoxSizer containing the controls
631 if (!buttonSizer
&& dialog
->GetLayoutAdaptationLevel() > wxDIALOG_ADAPTATION_STANDARD_SIZER
)
632 buttonSizer
= FindButtonSizer(false /* find ordinary sizer */, dialog
, dialog
->GetSizer(), buttonSizerBorder
);
634 // If we still don't have a button sizer, collect any 'loose' buttons in the layout
635 if (!buttonSizer
&& dialog
->GetLayoutAdaptationLevel() > wxDIALOG_ADAPTATION_ANY_SIZER
)
638 wxStdDialogButtonSizer
* stdButtonSizer
= new wxStdDialogButtonSizer
;
639 buttonSizer
= stdButtonSizer
;
641 FindLooseButtons(dialog
, stdButtonSizer
, dialog
->GetSizer(), count
);
643 stdButtonSizer
->Realize();
651 if (buttonSizerBorder
== 0)
652 buttonSizerBorder
= 5;
654 ReparentControls(dialog
, scrolledWindow
, buttonSizer
);
656 wxBoxSizer
* newTopSizer
= new wxBoxSizer(wxVERTICAL
);
657 wxSizer
* oldSizer
= dialog
->GetSizer();
659 dialog
->SetSizer(newTopSizer
, false /* don't delete old sizer */);
661 newTopSizer
->Add(scrolledWindow
, 1, wxEXPAND
|wxALL
, 0);
663 newTopSizer
->Add(buttonSizer
, 0, wxEXPAND
|wxALL
, buttonSizerBorder
);
665 scrolledWindow
->SetSizer(oldSizer
);
667 FitWithScrolling(dialog
, scrolledWindow
);
671 dialog
->SetLayoutAdaptationDone(true);
675 // Create the scrolled window
676 wxScrolledWindow
* wxStandardDialogLayoutAdapter
::CreateScrolledWindow(wxWindow
* parent
)
678 wxScrolledWindow
* scrolledWindow
= new wxScrolledWindow(parent
, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
, wxTAB_TRAVERSAL
|wxVSCROLL
|wxHSCROLL
|wxBORDER_NONE
);
679 return scrolledWindow
;
682 /// Find and remove the button sizer, if any
683 wxSizer
* wxStandardDialogLayoutAdapter
::FindButtonSizer(bool stdButtonSizer
, wxDialog
* dialog
, wxSizer
* sizer
, int& retBorder
, int accumlatedBorder
)
685 for ( wxSizerItemList
::compatibility_iterator node
= sizer
->GetChildren().GetFirst();
686 node
; node
= node
->GetNext() )
688 wxSizerItem
*item
= node
->GetData();
689 wxSizer
*childSizer
= item
->GetSizer();
693 int newBorder
= accumlatedBorder
;
694 if (item
->GetFlag() & wxALL
)
695 newBorder
+= item
->GetBorder();
697 if (stdButtonSizer
) // find wxStdDialogButtonSizer
699 wxStdDialogButtonSizer
* buttonSizer
= wxDynamicCast(childSizer
, wxStdDialogButtonSizer
);
702 sizer
->Detach(childSizer
);
703 retBorder
= newBorder
;
707 else // find a horizontal box sizer containing standard buttons
709 wxBoxSizer
* buttonSizer
= wxDynamicCast(childSizer
, wxBoxSizer
);
710 if (buttonSizer
&& IsOrdinaryButtonSizer(dialog
, buttonSizer
))
712 sizer
->Detach(childSizer
);
713 retBorder
= newBorder
;
718 wxSizer
* s
= FindButtonSizer(stdButtonSizer
, dialog
, childSizer
, retBorder
, newBorder
);
726 /// Check if this sizer contains standard buttons, and so can be repositioned in the dialog
727 bool wxStandardDialogLayoutAdapter
::IsOrdinaryButtonSizer(wxDialog
* dialog
, wxBoxSizer
* sizer
)
729 if (sizer
->GetOrientation() != wxHORIZONTAL
)
732 for ( wxSizerItemList
::compatibility_iterator node
= sizer
->GetChildren().GetFirst();
733 node
; node
= node
->GetNext() )
735 wxSizerItem
*item
= node
->GetData();
736 wxButton
*childButton
= wxDynamicCast(item
->GetWindow(), wxButton
);
738 if (childButton
&& IsStandardButton(dialog
, childButton
))
744 /// Check if this is a standard button
745 bool wxStandardDialogLayoutAdapter
::IsStandardButton(wxDialog
* dialog
, wxButton
* button
)
747 wxWindowID id
= button
->GetId();
749 return (id
== wxID_OK
|| id
== wxID_CANCEL
|| id
== wxID_YES
|| id
== wxID_NO
|| id
== wxID_SAVE
||
750 id
== wxID_APPLY
|| id
== wxID_HELP
|| id
== wxID_CONTEXT_HELP
|| dialog
->IsMainButtonId(id
));
753 /// Find 'loose' main buttons in the existing layout and add them to the standard dialog sizer
754 bool wxStandardDialogLayoutAdapter
::FindLooseButtons(wxDialog
* dialog
, wxStdDialogButtonSizer
* buttonSizer
, wxSizer
* sizer
, int& count
)
756 wxSizerItemList
::compatibility_iterator node
= sizer
->GetChildren().GetFirst();
759 wxSizerItemList
::compatibility_iterator next
= node
->GetNext();
760 wxSizerItem
*item
= node
->GetData();
761 wxSizer
*childSizer
= item
->GetSizer();
762 wxButton
*childButton
= wxDynamicCast(item
->GetWindow(), wxButton
);
764 if (childButton
&& IsStandardButton(dialog
, childButton
))
766 sizer
->Detach(childButton
);
767 buttonSizer
->AddButton(childButton
);
772 FindLooseButtons(dialog
, buttonSizer
, childSizer
, count
);
779 /// Reparent the controls to the scrolled window
780 void wxStandardDialogLayoutAdapter
::ReparentControls(wxWindow
* parent
, wxWindow
* reparentTo
, wxSizer
* buttonSizer
)
782 DoReparentControls(parent
, reparentTo
, buttonSizer
);
785 void wxStandardDialogLayoutAdapter
::DoReparentControls(wxWindow
* parent
, wxWindow
* reparentTo
, wxSizer
* buttonSizer
)
787 wxWindowList
::compatibility_iterator node
= parent
->GetChildren().GetFirst();
790 wxWindowList
::compatibility_iterator next
= node
->GetNext();
792 wxWindow
*win
= node
->GetData();
794 // Don't reparent the scrolled window or buttons in the button sizer
795 if (win
!= reparentTo
&& (!buttonSizer
|| !buttonSizer
->GetItem(win
)))
797 win
->Reparent(reparentTo
);
799 // Restore correct tab order
800 ::SetWindowPos((HWND
) win
->GetHWND(), HWND_BOTTOM
, -1, -1, -1, -1, SWP_NOMOVE
|SWP_NOSIZE
);
808 /// Find whether scrolling will be necessary for the dialog, returning wxVERTICAL, wxHORIZONTAL or both
809 int wxStandardDialogLayoutAdapter
::MustScroll(wxDialog
* dialog
, wxSize
& windowSize
, wxSize
& displaySize
)
811 return DoMustScroll(dialog
, windowSize
, displaySize
);
814 /// Find whether scrolling will be necessary for the dialog, returning wxVERTICAL, wxHORIZONTAL or both
815 int wxStandardDialogLayoutAdapter
::DoMustScroll(wxDialog
* dialog
, wxSize
& windowSize
, wxSize
& displaySize
)
817 wxSize minWindowSize
= dialog
->GetSizer()->GetMinSize();
818 windowSize
= dialog
->GetSize();
819 windowSize
= wxSize(wxMax(windowSize
.x
, minWindowSize
.x
), wxMax(windowSize
.y
, minWindowSize
.y
));
821 displaySize
= wxDisplay(wxDisplay
::GetFromWindow(dialog
)).GetClientArea().GetSize();
823 displaySize
= wxGetClientDisplayRect().GetSize();
828 if (windowSize
.y
>= (displaySize
.y
- wxEXTRA_DIALOG_HEIGHT
))
830 if (windowSize
.x
>= displaySize
.x
)
831 flags
|= wxHORIZONTAL
;
836 // A function to fit the dialog around its contents, and then adjust for screen size.
837 // If scrolled windows are passed, scrolling is enabled in the required orientation(s).
838 bool wxStandardDialogLayoutAdapter
::FitWithScrolling(wxDialog
* dialog
, wxWindowList
& windows
)
840 return DoFitWithScrolling(dialog
, windows
);
843 // A function to fit the dialog around its contents, and then adjust for screen size.
844 // If a scrolled window is passed, scrolling is enabled in the required orientation(s).
845 bool wxStandardDialogLayoutAdapter
::FitWithScrolling(wxDialog
* dialog
, wxScrolledWindow
* scrolledWindow
)
847 return DoFitWithScrolling(dialog
, scrolledWindow
);
850 // A function to fit the dialog around its contents, and then adjust for screen size.
851 // If a scrolled window is passed, scrolling is enabled in the required orientation(s).
852 bool wxStandardDialogLayoutAdapter
::DoFitWithScrolling(wxDialog
* dialog
, wxScrolledWindow
* scrolledWindow
)
854 wxWindowList windows
;
855 windows
.Append(scrolledWindow
);
856 return DoFitWithScrolling(dialog
, windows
);
859 bool wxStandardDialogLayoutAdapter
::DoFitWithScrolling(wxDialog
* dialog
, wxWindowList
& windows
)
861 wxSizer
* sizer
= dialog
->GetSizer();
865 sizer
->SetSizeHints(dialog
);
867 wxSize windowSize
, displaySize
;
868 int scrollFlags
= DoMustScroll(dialog
, windowSize
, displaySize
);
869 int scrollBarSize
= 20;
873 int scrollBarExtraX
= 0, scrollBarExtraY
= 0;
874 bool resizeHorizontally
= (scrollFlags
& wxHORIZONTAL
) != 0;
875 bool resizeVertically
= (scrollFlags
& wxVERTICAL
) != 0;
877 if (windows
.GetCount() != 0)
879 // Allow extra for a scrollbar, assuming we resizing in one direction only.
880 if ((resizeVertically
&& !resizeHorizontally
) && (windowSize
.x
< (displaySize
.x
- scrollBarSize
)))
881 scrollBarExtraX
= scrollBarSize
;
882 if ((resizeHorizontally
&& !resizeVertically
) && (windowSize
.y
< (displaySize
.y
- scrollBarSize
)))
883 scrollBarExtraY
= scrollBarSize
;
886 wxWindowList
::compatibility_iterator node
= windows
.GetFirst();
889 wxWindow
*win
= node
->GetData();
890 wxScrolledWindow
* scrolledWindow
= wxDynamicCast(win
, wxScrolledWindow
);
893 scrolledWindow
->SetScrollRate(resizeHorizontally ?
10 : 0, resizeVertically ?
10 : 0);
895 if (scrolledWindow
->GetSizer())
896 scrolledWindow
->GetSizer()->Fit(scrolledWindow
);
899 node
= node
->GetNext();
902 wxSize limitTo
= windowSize
+ wxSize(scrollBarExtraX
, scrollBarExtraY
);
903 if (resizeVertically
)
904 limitTo
.y
= displaySize
.y
- wxEXTRA_DIALOG_HEIGHT
;
905 if (resizeHorizontally
)
906 limitTo
.x
= displaySize
.x
;
908 dialog
->SetMinSize(limitTo
);
909 dialog
->SetSize(limitTo
);
911 dialog
->SetSizeHints( limitTo
.x
, limitTo
.y
, dialog
->GetMaxWidth(), dialog
->GetMaxHeight() );
918 * Module to initialise standard adapter
921 class wxDialogLayoutAdapterModule
: public wxModule
923 DECLARE_DYNAMIC_CLASS(wxDialogLayoutAdapterModule
)
925 wxDialogLayoutAdapterModule() {}
926 virtual void OnExit() { delete wxDialogBase
::SetLayoutAdapter(NULL
); }
927 virtual bool OnInit() { wxDialogBase
::SetLayoutAdapter(new wxStandardDialogLayoutAdapter
); return true; }
930 IMPLEMENT_DYNAMIC_CLASS(wxDialogLayoutAdapterModule
, wxModule
)