34#include <wx/textfile.h>
36#include <wx/clipbrd.h>
37#include <wx/html/htmlwin.h>
38#include <wx/tokenzr.h>
45#include "OCPNPlatform.h"
48#include "std_filesystem.h"
50#include "androidUTIL.h"
52#include "ocpn_frame.h"
56extern About* g_pAboutDlgLegacy;
59wxString OpenCPNVersion(
"\n Version ");
65const wxString AboutText =
67 "(c) 2000-2024 The OpenCPN Authors<br><br>";
69const wxString OpenCPNInfo =
71 "OpenCPN is a Free Software project, built by sailors. "
72 "It is freely available to download and distribute "
73 "without charge at opencpn.org.<br><br>"
74 "If you use OpenCPN, please consider contributing "
75 "or donating funds to the project.<br><br>"
76 "For more information, visit http://opencpn.org<br><br>";
78const wxString OpenCPNInfoAlt =
80 "OpenCPN is a Free Software project, built by sailors."
81 "The complete source code and many other resources "
82 "are freely available for your download and use, "
83 "subject to applicable License agreements."
85 "For more information, visit http://opencpn.org<br><br>";
89BEGIN_EVENT_TABLE(
About, wxDialog)
90EVT_BUTTON(xID_OK, About::OnXidOkClick)
91EVT_BUTTON(ID_DONATE, About::OnDonateClick)
92EVT_BUTTON(ID_COPYINI, About::OnCopyClick)
93EVT_BUTTON(ID_COPYLOG, About::OnCopyClick)
94EVT_CLOSE(About::OnClose)
98 : m_DataLocn(wxEmptyString), m_parent(NULL), m_btips_loaded(FALSE) {
100 pLicenseHTMLCtl = NULL;
101 pAuthorHTMLCtl = NULL;
102 m_blicensePageSet =
false;
105About::About(wxWindow* parent, wxString Data_Locn,
106 std::function<
void()> launch_local_help, wxWindowID
id,
107 const wxString& caption,
const wxPoint& pos,
const wxSize& size,
109 : m_DataLocn(Data_Locn),
111 m_launch_local_help(launch_local_help),
112 m_btips_loaded(FALSE) {
113 pAboutHTMLCtl = NULL;
114 pLicenseHTMLCtl = NULL;
115 pAuthorHTMLCtl = NULL;
116 m_blicensePageSet =
false;
118 if (strlen(DEBIAN_PPA_VERSION))
119 OpenCPNVersion += wxString(DEBIAN_PPA_VERSION);
121 OpenCPNVersion += wxString(PACKAGE_VERSION);
123 Create(parent,
id, caption, pos, size, style);
126bool About::Create(wxWindow* parent, wxWindowID
id,
const wxString& caption,
127 const wxPoint& pos,
const wxSize& size,
long style) {
130 style |= wxSTAY_ON_TOP;
133 SetExtraStyle(GetExtraStyle() | wxWS_EX_BLOCK_EVENTS);
134 wxDialog::Create(parent,
id, caption, pos, size, style);
147void About::SetColorScheme(
void) {
149 wxColor bg = GetBackgroundColour();
150 if (pAboutHTMLCtl) pAboutHTMLCtl->SetBackgroundColour(bg);
151 if (pLicenseHTMLCtl) pLicenseHTMLCtl->SetBackgroundColour(bg);
152 if (pAuthorHTMLCtl) pAuthorHTMLCtl->SetBackgroundColour(bg);
156 SetBackgroundColour(bg);
160 wxBitmap tbm(GetSize().x, GetSize().y, -1);
162 tdc.SetBackground(bg);
164 if (pAboutHTMLCtl) pAboutHTMLCtl->SetBackgroundImage(tbm);
165 if (pLicenseHTMLCtl) pLicenseHTMLCtl->SetBackgroundImage(tbm);
166 if (pAuthorHTMLCtl) pAuthorHTMLCtl->SetBackgroundImage(tbm);
170void About::Populate(
void) {
171 wxColor bg = GetBackgroundColour();
172 wxColor fg = wxColour(0, 0, 0);
175 wxString aboutText = wxString::Format(
176 "<html><body bgcolor=#%02x%02x%02x><font color=#%02x%02x%02x>", bg.Red(),
177 bg.Blue(), bg.Green(), fg.Red(), fg.Blue(), fg.Green());
179 wxFont* dFont = FontMgr::Get().
GetFont(_(
"Dialog"));
182 int points = dFont->GetPointSize();
187 for (
int i = -2; i < 5; i++) {
188 sizes[i + 2] = points + i + (i > 0 ? i : 0);
190 wxString face = dFont->GetFaceName();
191 pAboutHTMLCtl->SetFonts(face, face, sizes);
193 if (wxFONTSTYLE_ITALIC == dFont->GetStyle()) aboutText.Append(
"<i>");
195#ifdef __OCPN__ANDROID__
197 msg.Printf(
" [%d]", androidGetVersionCode());
198 wxString OpenCPNVersionAndroid =
199 "OpenCPN for Android Version " + androidGetVersionName() + msg;
201 aboutText.Append(AboutText + OpenCPNVersionAndroid + OpenCPNInfoAlt);
203 aboutText.Append(AboutText + OpenCPNVersion + OpenCPNInfo);
207 wxString log_string =
"Logfile location: " + g_Platform->GetLogFileName();
208 log_string.Replace(
"/",
"/ ");
210 aboutText.Append(log_string);
213 wxString config_string =
214 "<br><br>Config file location: " + g_Platform->GetConfigFileName();
215 config_string.Replace(
"/",
"/ ");
216 aboutText.Append(config_string);
218 if (wxFONTSTYLE_ITALIC == dFont->GetStyle()) aboutText.Append(
"</i>");
221 aboutText.Append(
"</font></body></html>");
223 pAboutHTMLCtl->SetPage(aboutText);
228 fs::path data_path(g_Platform->GetSharedDataDir().ToStdString());
229 std::ifstream istream(data_path /
"Authors.html");
230 std::stringstream ss;
231 ss << istream.rdbuf();
232 pAuthorHTMLCtl->SetPage(ss.str());
238 wxString licenseText =
240 _T(
"<html><body bgcolor=#%02x%02x%02x><font color=#%02x%02x%02x>" ),
241 bg.Red(), bg.Blue(), bg.Green(), fg.Red(), fg.Blue(), fg.Green() );
243 pLicenseHTMLCtl->SetFonts( face, face, sizes );
245 wxTextFile license_filea( m_DataLocn + _T(
"license.txt") );
246 if ( license_filea.Open() ) {
247 for ( wxString str = license_filea.GetFirstLine(); !license_filea.Eof() ; str = license_filea.GetNextLine() )
248 licenseText.Append( str + _T(
"<br>") );
249 license_filea.Close();
251 wxLogMessage( _T(
"Could not open License file: ") + m_DataLocn );
254 wxString suppLicense = g_Platform->GetSupplementalLicenseString();
256 wxStringTokenizer st(suppLicense, _T(
"\n"), wxTOKEN_DEFAULT);
257 while( st.HasMoreTokens() )
259 wxString s1 = st.GetNextToken();
260 licenseText.Append( s1 + _T(
"<br>") );
264 licenseText.Append( _T(
"</font></body></html>") );
266 pLicenseHTMLCtl->SetPage( licenseText );
272void About::RecalculateSize(
void) {
276 esize.x = GetCharWidth() * 110;
277 esize.y = GetCharHeight() * 44;
279 wxSize dsize = GetParent()->GetSize();
280 esize.y = wxMin(esize.y, dsize.y - (0 * GetCharHeight()));
281 esize.x = wxMin(esize.x, dsize.x - (0 * GetCharHeight()));
282 SetClientSize(esize);
284 wxSize fsize = GetSize();
285 fsize.y = wxMin(fsize.y, dsize.y - (0 * GetCharHeight()));
286 fsize.x = wxMin(fsize.x, dsize.x - (0 * GetCharHeight()));
293void About::CreateControls(
void) {
296 wxBoxSizer* mainSizer =
new wxBoxSizer(wxVERTICAL);
299 new wxStaticText(
this, -1, _(
"The Open Source Chart Plotter/Navigator"),
300 wxDefaultPosition, wxSize(-1, 50 ),
306 14, wxFONTFAMILY_DEFAULT, qFont->GetStyle(), wxFONTWEIGHT_BOLD,
false,
307 qFont->GetFaceName());
308 pST1->SetFont(*headerFont);
309 mainSizer->Add(pST1, 0, wxALL | wxEXPAND, 8);
311 bool orient = m_displaySize.x < m_displaySize.y;
312#ifndef __OCPN__ANDROID__
313 wxBoxSizer* buttonSizer =
new wxBoxSizer(orient ? wxVERTICAL : wxHORIZONTAL);
314 mainSizer->Add(buttonSizer, 0, wxALL, 0);
316 wxButton* donateButton =
new wxBitmapButton(
317 this, ID_DONATE, g_StyleManager->GetCurrentStyle()->GetIcon(
"donate"),
318 wxDefaultPosition, wxDefaultSize, 0);
321 new wxButton(
this, ID_COPYLOG, _(
"Copy Log File to Clipboard")), 1,
322 wxALL | wxEXPAND, 3);
324 new wxButton(
this, ID_COPYINI, _(
"Copy Settings File to Clipboard")), 1,
325 wxALL | wxEXPAND, 3);
329 (buttonSizer->GetOrientation() == wxHORIZONTAL ? wxALIGN_RIGHT : 0),
334 pNotebook =
new wxNotebook(
this, ID_NOTEBOOK_HELP, wxDefaultPosition,
335 wxSize(-1, -1), wxNB_TOP);
337 pNotebook->Connect(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED,
338 wxNotebookEventHandler(About::OnNBPageChange), NULL,
this);
340 pNotebook->InheritAttributes();
341 mainSizer->Add(pNotebook, 1,
342 (orient ? wxALIGN_CENTER_VERTICAL : 0) | wxEXPAND | wxALL, 5);
345 itemPanelAbout =
new wxPanel(pNotebook, -1, wxDefaultPosition, wxDefaultSize,
346 wxSUNKEN_BORDER | wxTAB_TRAVERSAL);
347 itemPanelAbout->InheritAttributes();
348 pNotebook->AddPage(itemPanelAbout, _(
"About"), TRUE );
351 new wxHtmlWindow(itemPanelAbout, wxID_ANY, wxDefaultPosition,
352 wxDefaultSize, wxHW_SCROLLBAR_AUTO | wxHW_NO_SELECTION);
353 pAboutHTMLCtl->SetBorders(5);
354 wxBoxSizer* aboutSizer =
new wxBoxSizer(wxVERTICAL);
355 aboutSizer->Add(pAboutHTMLCtl, 1,
356 wxALIGN_CENTER_HORIZONTAL | wxEXPAND | wxALL, 5);
357 itemPanelAbout->SetSizer(aboutSizer);
362 new wxPanel(pNotebook, -1, wxDefaultPosition, wxDefaultSize,
363 wxSUNKEN_BORDER | wxTAB_TRAVERSAL);
364 itemPanelAuthors->InheritAttributes();
365 pNotebook->AddPage(itemPanelAuthors, _(
"Authors"));
368 new wxHtmlWindow(itemPanelAuthors, wxID_ANY, wxDefaultPosition,
369 wxDefaultSize, wxHW_SCROLLBAR_AUTO | wxHW_NO_SELECTION);
370 pAuthorHTMLCtl->SetBorders(5);
371 wxBoxSizer* authorSizer =
new wxBoxSizer(wxVERTICAL);
372 authorSizer->Add(pAuthorHTMLCtl, 1,
373 wxALIGN_CENTER_HORIZONTAL | wxEXPAND | wxALL, 5);
374 itemPanelAuthors->SetSizer(authorSizer);
378 new wxPanel(pNotebook, -1, wxDefaultPosition, wxDefaultSize,
379 wxSUNKEN_BORDER | wxTAB_TRAVERSAL);
380 itemPanelLicense->InheritAttributes();
381 pNotebook->AddPage(itemPanelLicense, _(
"License"));
384 new wxHtmlWindow(itemPanelLicense, wxID_ANY, wxDefaultPosition,
385 wxDefaultSize, wxHW_SCROLLBAR_AUTO | wxHW_NO_SELECTION);
386 pLicenseHTMLCtl->SetBorders(5);
387 wxBoxSizer* licenseSizer =
new wxBoxSizer(wxVERTICAL);
388 licenseSizer->Add(pLicenseHTMLCtl, 1,
389 wxALIGN_CENTER_HORIZONTAL | wxEXPAND | wxALL, 5);
390 itemPanelLicense->SetSizer(licenseSizer);
393 itemPanelTips =
new wxPanel(pNotebook, -1, wxDefaultPosition, wxDefaultSize,
394 wxSUNKEN_BORDER | wxTAB_TRAVERSAL);
395 itemPanelTips->InheritAttributes();
396 pNotebook->AddPage(itemPanelTips, _(
"Help"));
398 wxBoxSizer* helpSizer =
new wxBoxSizer(wxVERTICAL);
399 itemPanelTips->SetSizer(helpSizer);
402 wxButton* closeButton =
new wxButton(
this, xID_OK, _(
"Close"),
403 wxDefaultPosition, wxDefaultSize, 0);
404 closeButton->SetDefault();
405 closeButton->InheritAttributes();
406 mainSizer->Add(closeButton, 0, wxALIGN_RIGHT | wxALL, 5);
409void About::OnNBPageChange(wxNotebookEvent& event) {
410 unsigned int i =
event.GetSelection();
413 m_launch_local_help();
414 pNotebook->ChangeSelection(0);
417 else if ((i == 2) && !m_blicensePageSet) {
419 wxColor bg = GetBackgroundColour();
420 wxColor fg = wxColour(0, 0, 0);
421 wxFont* dFont = FontMgr::Get().
GetFont(_(
"Dialog"));
424 int points = dFont->GetPointSize();
429 for (
int i = -2; i < 5; i++) {
430 sizes[i + 2] = points + i + (i > 0 ? i : 0);
432 wxString face = dFont->GetFaceName();
435 g_Platform->ShowBusySpinner();
438 wxString licenseText = wxString::Format(
439 "<html><body bgcolor=#%02x%02x%02x><font color=#%02x%02x%02x>",
440 bg.Red(), bg.Blue(), bg.Green(), fg.Red(), fg.Blue(), fg.Green());
442 pLicenseHTMLCtl->SetFonts(face, face, sizes);
444 wxTextFile license_filea(m_DataLocn +
"license.txt");
445 if (license_filea.Open()) {
446 for (wxString str = license_filea.GetFirstLine(); !license_filea.Eof();
447 str = license_filea.GetNextLine())
448 licenseText.Append(str +
"<br>");
449 license_filea.Close();
451 wxLogMessage(
"Could not open License file: " + m_DataLocn);
454 wxString suppLicense = g_Platform->GetSupplementalLicenseString();
456 wxStringTokenizer st(suppLicense,
"\n", wxTOKEN_DEFAULT);
457 while (st.HasMoreTokens()) {
458 wxString s1 = st.GetNextToken();
459 licenseText.Append(s1 +
"<br>");
463 licenseText.Append(
"</font></body></html>");
465 pLicenseHTMLCtl->SetPage(licenseText);
467 g_Platform->HideBusySpinner();
470 m_blicensePageSet =
true;
474void About::OnXidOkClick(wxCommandEvent& event) { Close(); }
476void About::OnClose(wxCloseEvent& event) {
478 wxTheApp->GetTopWindow()->Raise();
481 g_pAboutDlgLegacy = NULL;
484void About::OnDonateClick(wxCommandEvent& event) {
485 wxLaunchDefaultBrowser(
486 "https://sourceforge.net/donate/index.php?group_id=180842");
489void About::OnCopyClick(wxCommandEvent& event) {
490 wxString filename =
event.GetId() == ID_COPYLOG
491 ? g_Platform->GetLogFileName()
492 : g_Platform->GetConfigFileName();
494 wxFFile file(filename);
496 if (!file.IsOpened()) {
497 wxLogMessage(
"Failed to open file for Copy to Clipboard.");
501 wxString fileContent;
503 while (!file.Eof()) {
504 int c = file.Read(&buf, 1024);
505 if (c) fileContent += wxString(buf, wxConvUTF8, c);
509 int length = fileContent.Length();
511 if (event.GetId() == ID_COPYLOG) {
512 wxString lastLogs = fileContent;
513 int pos = lastLogs.Find(
"________");
514 while (pos != wxNOT_FOUND && lastLogs.Length() > 65000) {
515 lastLogs = lastLogs.Right(lastLogs.Length() - pos - 8);
516 pos = lastLogs.Find(
"________");
518 fileContent = lastLogs;
521 ::wxBeginBusyCursor();
522 if (wxTheClipboard->Open()) {
523 if (!wxTheClipboard->SetData(
new wxTextDataObject(fileContent)))
524 wxLogMessage(
"wxTheClipboard->Open() failed.");
525 wxTheClipboard->Close();
527 wxLogMessage(
"wxTheClipboard->Open() failed.");
bool g_bresponsive
Flag to control adaptive UI scaling.
The OpenCPN About dialog displaying information including version, authors, license,...
wxFont * FindOrCreateFont(int point_size, wxFontFamily family, wxFontStyle style, wxFontWeight weight, bool underline=false, const wxString &facename=wxEmptyString, wxFontEncoding encoding=wxFONTENCODING_DEFAULT)
Creates or finds a matching font in the font cache.
wxFont * GetFont(const wxString &TextElement, int requested_font_size=0)
Gets a font object for a UI element.
wxFont * GetOCPNScaledFont(wxString item, int default_size)
Retrieves a font from FontMgr, optionally scaled for physical readability.
General purpose GUI support.