1 ///////////////////////////////////////////////////////////////////////////////
2 // Name:        src/generic/aboutdlgg.cpp
3 // Purpose:     implements wxGenericAboutBox() function
4 // Author:      Vadim Zeitlin
5 // Created:     2006-10-08
6 // Copyright:   (c) 2006 Vadim Zeitlin <vadim@wxwidgets.org>
7 // Licence:     wxWindows licence
8 ///////////////////////////////////////////////////////////////////////////////
9 
10 // ============================================================================
11 // declarations
12 // ============================================================================
13 
14 // ----------------------------------------------------------------------------
15 // headers
16 // ----------------------------------------------------------------------------
17 
18 // for compilers that support precompilation, includes "wx.h".
19 #include "wx/wxprec.h"
20 
21 
22 #if wxUSE_ABOUTDLG
23 
24 #ifndef WX_PRECOMP
25     #include "wx/sizer.h"
26     #include "wx/statbmp.h"
27     #include "wx/stattext.h"
28     #include "wx/button.h"
29 #endif //WX_PRECOMP
30 
31 #include "wx/aboutdlg.h"
32 #include "wx/generic/aboutdlgg.h"
33 
34 #include "wx/hyperlink.h"
35 #include "wx/collpane.h"
36 
37 // ============================================================================
38 // implementation
39 // ============================================================================
40 
41 // helper function: returns all array elements in a single comma-separated and
42 // newline-terminated string
AllAsString(const wxArrayString & a)43 static wxString AllAsString(const wxArrayString& a)
44 {
45     wxString s;
46     const size_t count = a.size();
47     s.reserve(20*count);
48     for ( size_t n = 0; n < count; n++ )
49     {
50         s << a[n] << (n == count - 1 ? wxT("\n") : wxT(", "));
51     }
52 
53     return s;
54 }
55 
56 // ----------------------------------------------------------------------------
57 // wxAboutDialogInfo
58 // ----------------------------------------------------------------------------
59 
GetDescriptionAndCredits() const60 wxString wxAboutDialogInfo::GetDescriptionAndCredits() const
61 {
62     wxString s = GetDescription();
63     if ( !s.empty() )
64         s << wxT('\n');
65 
66     if ( HasDevelopers() )
67         s << wxT('\n') << _("Developed by ") << AllAsString(GetDevelopers());
68 
69     if ( HasDocWriters() )
70         s << wxT('\n') << _("Documentation by ") << AllAsString(GetDocWriters());
71 
72     if ( HasArtists() )
73         s << wxT('\n') << _("Graphics art by ") << AllAsString(GetArtists());
74 
75     if ( HasTranslators() )
76         s << wxT('\n') << _("Translations by ") << AllAsString(GetTranslators());
77 
78     return s;
79 }
80 
GetIcon() const81 wxIcon wxAboutDialogInfo::GetIcon() const
82 {
83     wxIcon icon = m_icon;
84     if ( !icon.IsOk() )
85     {
86         const wxTopLevelWindow * const
87             tlw = wxDynamicCast(wxApp::GetMainTopWindow(), wxTopLevelWindow);
88         if ( tlw )
89             icon = tlw->GetIcon();
90     }
91 
92     return icon;
93 }
94 
GetCopyrightToDisplay() const95 wxString wxAboutDialogInfo::GetCopyrightToDisplay() const
96 {
97     wxString ret = m_copyright;
98 
99 #if wxUSE_UNICODE
100     const wxString copyrightSign = wxString::FromUTF8("\xc2\xa9");
101     ret.Replace("(c)", copyrightSign);
102     ret.Replace("(C)", copyrightSign);
103 #endif // wxUSE_UNICODE
104 
105     return ret;
106 }
107 
SetVersion(const wxString & version,const wxString & longVersion)108 void wxAboutDialogInfo::SetVersion(const wxString& version,
109                                    const wxString& longVersion)
110 {
111     if ( version.empty() )
112     {
113         m_version.clear();
114 
115         wxASSERT_MSG( longVersion.empty(),
116                       "long version should be empty if version is");
117 
118         m_longVersion.clear();
119     }
120     else // setting valid version
121     {
122         m_version = version;
123 
124         if ( longVersion.empty() )
125             m_longVersion = _("Version ") + m_version;
126         else
127             m_longVersion = longVersion;
128     }
129 }
130 
131 // ----------------------------------------------------------------------------
132 // wxGenericAboutDialog
133 // ----------------------------------------------------------------------------
134 
Create(const wxAboutDialogInfo & info,wxWindow * parent)135 bool wxGenericAboutDialog::Create(const wxAboutDialogInfo& info, wxWindow* parent)
136 {
137     if ( !wxDialog::Create(parent, wxID_ANY, wxString::Format(_("About %s"), info.GetName()),
138                            wxDefaultPosition, wxDefaultSize, wxRESIZE_BORDER|wxDEFAULT_DIALOG_STYLE) )
139         return false;
140 
141     m_sizerText = new wxBoxSizer(wxVERTICAL);
142     wxString nameAndVersion = info.GetName();
143     if ( info.HasVersion() )
144         nameAndVersion << wxT(' ') << info.GetVersion();
145     wxStaticText *label = new wxStaticText(this, wxID_ANY, nameAndVersion);
146     wxFont fontBig(*wxNORMAL_FONT);
147     fontBig.SetFractionalPointSize(fontBig.GetFractionalPointSize() + 2.0);
148     fontBig.SetWeight(wxFONTWEIGHT_BOLD);
149     label->SetFont(fontBig);
150 
151     m_sizerText->Add(label, wxSizerFlags().Centre().Border());
152     m_sizerText->AddSpacer(5);
153 
154     AddText(info.GetCopyrightToDisplay());
155     AddText(info.GetDescription());
156 
157     if ( info.HasWebSite() )
158     {
159 #if wxUSE_HYPERLINKCTRL
160         AddControl(new wxHyperlinkCtrl(this, wxID_ANY,
161                                        info.GetWebSiteDescription(),
162                                        info.GetWebSiteURL()));
163 #else
164         AddText(info.GetWebSiteURL());
165 #endif // wxUSE_HYPERLINKCTRL/!wxUSE_HYPERLINKCTRL
166     }
167 
168 #if wxUSE_COLLPANE
169     if ( info.HasLicence() )
170         AddCollapsiblePane(_("License"), info.GetLicence());
171 
172     if ( info.HasDevelopers() )
173         AddCollapsiblePane(_("Developers"),
174                            AllAsString(info.GetDevelopers()));
175 
176     if ( info.HasDocWriters() )
177         AddCollapsiblePane(_("Documentation writers"),
178                            AllAsString(info.GetDocWriters()));
179 
180     if ( info.HasArtists() )
181         AddCollapsiblePane(_("Artists"),
182                            AllAsString(info.GetArtists()));
183 
184     if ( info.HasTranslators() )
185         AddCollapsiblePane(_("Translators"),
186                            AllAsString(info.GetTranslators()));
187 #endif // wxUSE_COLLPANE
188 
189     DoAddCustomControls();
190 
191 
192     wxSizer *sizerIconAndText = new wxBoxSizer(wxHORIZONTAL);
193 #if wxUSE_STATBMP
194     wxIcon icon = info.GetIcon();
195     if ( icon.IsOk() )
196     {
197         sizerIconAndText->Add(new wxStaticBitmap(this, wxID_ANY, icon),
198                                 wxSizerFlags().Border(wxRIGHT));
199     }
200 #endif // wxUSE_STATBMP
201     sizerIconAndText->Add(m_sizerText, wxSizerFlags(1).Expand());
202 
203     wxSizer *sizerTop = new wxBoxSizer(wxVERTICAL);
204     sizerTop->Add(sizerIconAndText, wxSizerFlags(1).Expand().Border());
205 
206 // Mac typically doesn't use OK buttons just for dismissing dialogs.
207 #if !defined(__WXMAC__)
208     wxSizer *sizerBtns = CreateButtonSizer(wxOK);
209     if ( sizerBtns )
210     {
211         sizerTop->Add(sizerBtns, wxSizerFlags().Expand().Border());
212     }
213 #endif
214 
215     SetSizerAndFit(sizerTop);
216 
217     CentreOnParent();
218 
219 #if !wxUSE_MODAL_ABOUT_DIALOG
220     Bind(wxEVT_CLOSE_WINDOW, &wxGenericAboutDialog::OnCloseWindow, this);
221     Bind(wxEVT_BUTTON, &wxGenericAboutDialog::OnOK, this, wxID_OK);
222 #endif // !wxUSE_MODAL_ABOUT_DIALOG
223 
224     return true;
225 }
226 
AddControl(wxWindow * win,const wxSizerFlags & flags)227 void wxGenericAboutDialog::AddControl(wxWindow *win, const wxSizerFlags& flags)
228 {
229     wxCHECK_RET( m_sizerText, wxT("can only be called after Create()") );
230     wxASSERT_MSG( win, wxT("can't add NULL window to about dialog") );
231 
232     m_sizerText->Add(win, flags);
233 }
234 
AddControl(wxWindow * win)235 void wxGenericAboutDialog::AddControl(wxWindow *win)
236 {
237     AddControl(win, wxSizerFlags().Border(wxDOWN).Centre());
238 }
239 
AddText(const wxString & text)240 void wxGenericAboutDialog::AddText(const wxString& text)
241 {
242     if ( !text.empty() )
243         AddControl(new wxStaticText(this, wxID_ANY, text));
244 }
245 
246 #if wxUSE_COLLPANE
AddCollapsiblePane(const wxString & title,const wxString & text)247 void wxGenericAboutDialog::AddCollapsiblePane(const wxString& title,
248                                               const wxString& text)
249 {
250     wxCollapsiblePane *pane = new wxCollapsiblePane(this, wxID_ANY, title);
251     wxWindow * const paneContents = pane->GetPane();
252     wxStaticText *txt = new wxStaticText(paneContents, wxID_ANY, text,
253                                          wxDefaultPosition, wxDefaultSize,
254                                          wxALIGN_CENTRE);
255 
256     // don't make the text unreasonably wide
257     static const int maxWidth = wxGetDisplaySize().x/3;
258     txt->Wrap(maxWidth);
259 
260 
261     // we need a sizer to make this text expand to fill the entire pane area
262     wxSizer * const sizerPane = new wxBoxSizer(wxHORIZONTAL);
263     sizerPane->Add(txt, wxSizerFlags(1).Expand());
264     paneContents->SetSizer(sizerPane);
265 
266     // NB: all the wxCollapsiblePanes must be added with a null proportion value
267     m_sizerText->Add(pane, wxSizerFlags(0).Expand().Border(wxBOTTOM));
268 }
269 #endif
270 
271 #if !wxUSE_MODAL_ABOUT_DIALOG
272 
OnCloseWindow(wxCloseEvent & event)273 void wxGenericAboutDialog::OnCloseWindow(wxCloseEvent& event)
274 {
275     // safeguards in case the window is still shown using ShowModal
276     if ( !IsModal() )
277         Destroy();
278 
279     event.Skip();
280 }
281 
OnOK(wxCommandEvent & event)282 void wxGenericAboutDialog::OnOK(wxCommandEvent& event)
283 {
284     // safeguards in case the window is still shown using ShowModal
285     if ( !IsModal() )
286     {
287         // By default a modeless dialog would be just hidden, destroy this one
288         // instead.
289         Destroy();
290     }
291     else
292         event.Skip();
293 }
294 
295 #endif // !wxUSE_MODAL_ABOUT_DIALOG
296 
297 // ----------------------------------------------------------------------------
298 // public functions
299 // ----------------------------------------------------------------------------
300 
wxGenericAboutBox(const wxAboutDialogInfo & info,wxWindow * parent)301 void wxGenericAboutBox(const wxAboutDialogInfo& info, wxWindow* parent)
302 {
303 #if wxUSE_MODAL_ABOUT_DIALOG
304     wxGenericAboutDialog dlg(info, parent);
305     dlg.ShowModal();
306 #else
307     wxGenericAboutDialog* dlg = new wxGenericAboutDialog(info, parent);
308     dlg->Show();
309 #endif
310 }
311 
312 // currently wxAboutBox is implemented natively only under these platforms, for
313 // the others we provide a generic fallback here
314 #if !defined(__WXMSW__) && !defined(__WXMAC__) && \
315         (!defined(__WXGTK20__) || defined(__WXUNIVERSAL__))
316 
wxAboutBox(const wxAboutDialogInfo & info,wxWindow * parent)317 void wxAboutBox(const wxAboutDialogInfo& info, wxWindow* parent)
318 {
319     wxGenericAboutBox(info, parent);
320 }
321 
322 #endif // platforms without native about dialog
323 
324 
325 #endif // wxUSE_ABOUTDLG
326