38#include <wx/filename.h>
39#include <wx/fontdlg.h>
42#include "dashboard_pi.h"
44#include "wx/jsonreader.h"
45#include "wx/jsonwriter.h"
47#include "../../../gui/include/gui/ocpn_fontdlg.h"
50wxFontData *g_pFontTitle;
51wxFontData *g_pFontData;
52wxFontData *g_pFontLabel;
53wxFontData *g_pFontSmall;
55wxFontData g_FontTitle;
57wxFontData g_FontLabel;
58wxFontData g_FontSmall;
60wxFontData *g_pUSFontTitle;
61wxFontData *g_pUSFontData;
62wxFontData *g_pUSFontLabel;
63wxFontData *g_pUSFontSmall;
65wxFontData g_USFontTitle;
66wxFontData g_USFontData;
67wxFontData g_USFontLabel;
68wxFontData g_USFontSmall;
75int g_iDashDistanceUnit;
76int g_iDashWindSpeedUnit;
78double g_dDashDBTOffset;
79bool g_bDBtrueWindGround;
83int g_dashPrefWidth, g_dashPrefHeight;
85wxColor g_BackgroundColor;
86bool g_ForceBackgroundColor;
87wxAlignment g_TitleAlignment;
88double g_TitleVerticalOffset;
91wxAlignment g_DataAlignment;
93int g_iInstrumentSpacing;
95PI_ColorScheme aktuellColorScheme;
97static const long long lNaN = 0xfff8000000000000;
98#define NAN (*(double *)&lNaN)
101#ifdef __OCPN__ANDROID__
111extern "C" DECL_EXP
void destroy_pi(
opencpn_plugin *p) {
delete p; }
113#ifdef __OCPN__ANDROID__
115QString qtStyleSheet =
116 "QScrollBar:horizontal {\
117border: 0px solid grey;\
118background-color: rgb(240, 240, 240);\
120margin: 0px 1px 0 1px;\
122QScrollBar::handle:horizontal {\
123background-color: rgb(200, 200, 200);\
127QScrollBar::add-line:horizontal {\
128border: 0px solid grey;\
131subcontrol-position: right;\
132subcontrol-origin: margin;\
134QScrollBar::sub-line:horizontal {\
135border: 0px solid grey;\
138subcontrol-position: left;\
139subcontrol-origin: margin;\
141QScrollBar:vertical {\
142border: 0px solid grey;\
143background-color: rgb(240, 240, 240);\
145margin: 1px 0px 1px 0px;\
147QScrollBar::handle:vertical {\
148background-color: rgb(200, 200, 200);\
152QScrollBar::add-line:vertical {\
153border: 0px solid grey;\
156subcontrol-position: top;\
157subcontrol-origin: margin;\
159QScrollBar::sub-line:vertical {\
160border: 0px solid grey;\
163subcontrol-position: bottom;\
164subcontrol-origin: margin;\
169QCheckBox::indicator {\
177#ifdef __OCPN__ANDROID__
178#include <QtWidgets/QScroller>
250bool IsObsolete(
int id) {
259wxString getInstrumentCaption(
unsigned int id) {
262 return _(
"Position");
266 return _(
"Speed SOG");
268 return _(
"Speed STW");
274 return _(
"GNSS Compass");
276 return _(
"True Compass");
280 return _(
"True HDG");
285 return _(
"App. Wind Angle & Speed");
286 case ID_DBP_D_AWA_TWA:
287 return _(
"App & True Wind Angle");
289 return _(
"App. Wind Speed");
291 return _(
"App. Wind Speed");
293 return _(
"True Wind Angle & Speed");
295 return _(
"Altitude");
297 return _(
"Altitude Trace");
303 return _(
"Barometric pressure");
305 return _(
"Barometric pressure");
307 return _(
"Water Temp.");
309 return _(
"Air Temp.");
311 return _(
"App. Wind Angle");
313 return _(
"True Wind Angle");
315 return _(
"True Wind Direction");
317 return _(
"True Wind Speed");
319 return _(
"True Wind Dir. & Speed");
325 return _(
"VMG Wind");
327 return _(
"Rudder Angle");
329 return _(
"Rudder Angle");
331 return _(
"GNSS in use");
333 return _(
"GNSS Status");
336 case ID_DBP_I_GPSUTC:
337 return _(
"GNSS Clock");
339 return _(
"Sunrise/Sunset");
341 return _(
"Moon phase");
343 return _(
"Wind history");
345 return _(
"Barometric history");
347 return _(
"Trip Log");
351 return _(
"From Ownship");
356 case ID_DBP_I_GPSLCL:
357 return _(
"Local GNSS Clock");
358 case ID_DBP_I_CPULCL:
359 return _(
"Local CPU Clock");
360 case ID_DBP_I_SUNLCL:
361 return _(
"Local Sunrise/Sunset");
363 return _(
"Humidity");
365 return _(
"Windlass");
370void getListItemForInstrument(wxListItem &item,
unsigned int id) {
372 item.SetText(getInstrumentCaption(
id));
395 case ID_DBP_I_GPSUTC:
396 case ID_DBP_I_GPSLCL:
397 case ID_DBP_I_CPULCL:
399 case ID_DBP_I_SUNLCL:
417 case ID_DBP_D_AWA_TWA:
435int GetRandomNumber(
int range_min,
int range_max) {
436 long u = (long)wxRound(
437 ((
double)rand() / ((
double)(RAND_MAX) + 1) * (range_max - range_min)) +
443wxString GetUUID(
void) {
448 int time_hi_and_version;
449 int clock_seq_hi_and_rsv;
455 uuid.time_low = GetRandomNumber(
458 uuid.time_mid = GetRandomNumber(0, 65535);
459 uuid.time_hi_and_version = GetRandomNumber(0, 65535);
460 uuid.clock_seq_hi_and_rsv = GetRandomNumber(0, 255);
461 uuid.clock_seq_low = GetRandomNumber(0, 255);
462 uuid.node_hi = GetRandomNumber(0, 65535);
463 uuid.node_low = GetRandomNumber(0, 2147483647);
467 uuid.clock_seq_hi_and_rsv = (uuid.clock_seq_hi_and_rsv & 0x3F) | 0x80;
471 uuid.time_hi_and_version = (uuid.time_hi_and_version & 0x0fff) | 0x4000;
473 str.Printf(_T(
"%08x-%04x-%04x-%02x%02x-%04x%08x"), uuid.time_low,
474 uuid.time_mid, uuid.time_hi_and_version, uuid.clock_seq_hi_and_rsv,
475 uuid.clock_seq_low, uuid.node_hi, uuid.node_low);
480wxString MakeName() {
return _T(
"DASH_") + GetUUID(); }
488dashboard_pi::dashboard_pi(
void *ppimgr)
492 mCOGFilter.setType(IIRFILTER_TYPE_DEG);
495dashboard_pi::~dashboard_pi(
void) {
496 delete _img_dashboard_pi;
497 delete _img_dashboard;
499 delete _img_instrument;
504int dashboard_pi::Init(
void) {
505 AddLocaleCatalog(_T(
"opencpn-dashboard_pi"));
529 m_config_version = -1;
538 mDPT_DBT_Watchdog = 2;
556 g_pFontTitle =
new wxFontData();
557 g_pFontTitle->SetChosenFont(
558 wxFont(10, wxFONTFAMILY_SWISS, wxFONTSTYLE_ITALIC, wxFONTWEIGHT_NORMAL));
560 g_pFontData =
new wxFontData();
561 g_pFontData->SetChosenFont(
562 wxFont(14, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));
564 g_pFontLabel =
new wxFontData();
565 g_pFontLabel->SetChosenFont(
566 wxFont(8, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));
568 g_pFontSmall =
new wxFontData();
569 g_pFontSmall->SetChosenFont(
570 wxFont(8, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));
572 g_pUSFontTitle = &g_USFontTitle;
573 g_pUSFontData = &g_USFontData;
574 g_pUSFontLabel = &g_USFontLabel;
575 g_pUSFontSmall = &g_USFontSmall;
577 m_pauimgr = GetFrameAuiManager();
578 m_pauimgr->Connect(wxEVT_AUI_PANE_CLOSE,
579 wxAuiManagerEventHandler(dashboard_pi::OnPaneClose), NULL,
583 m_pconfig = GetOCPNConfigObject();
594 wxString shareLocn = *GetpSharedDataLocation() + _T(
"plugins") +
595 wxFileName::GetPathSeparator() + _T(
"dashboard_pi") +
596 wxFileName::GetPathSeparator() + _T(
"data") +
597 wxFileName::GetPathSeparator();
599 wxString normalIcon = shareLocn + _T(
"Dashboard.svg");
600 wxString toggledIcon = shareLocn + _T(
"Dashboard_toggled.svg");
601 wxString rolloverIcon = shareLocn + _T(
"Dashboard_rollover.svg");
605 if (GetActiveStyleName().Lower() != _T(
"traditional")) {
607 toggledIcon = _T(
"");
608 rolloverIcon = _T(
"");
611 m_toolbar_item_id = InsertPlugInToolSVG(
612 _T(
""), normalIcon, rolloverIcon, toggledIcon, wxITEM_CHECK,
613 _(
"Dashboard"), _T(
""), NULL, DASHBOARD_TOOL_POSITION, 0,
this);
618 if (m_config_version == 1) {
628 listener_127245 = GetListener(id_127245, EVT_N2K_127245,
this);
629 Bind(EVT_N2K_127245, [&](
ObservedEvt ev) { HandleN2K_127245(ev); });
634 listener_127257 = GetListener(id_127257, EVT_N2K_127257,
this);
635 Bind(EVT_N2K_127257, [&](
ObservedEvt ev) { HandleN2K_127257(ev); });
640 listener_128259 = GetListener(id_128259, EVT_N2K_128259,
this);
641 Bind(EVT_N2K_128259, [&](
ObservedEvt ev) { HandleN2K_128259(ev); });
646 listener_128267 = GetListener(id_128267, EVT_N2K_128267,
this);
647 Bind(EVT_N2K_128267, [&](
ObservedEvt ev) { HandleN2K_128267(ev); });
652 listener_128275 = GetListener(id_128275, EVT_N2K_128275,
this);
653 Bind(EVT_N2K_128275, [&](
ObservedEvt ev) { HandleN2K_128275(ev); });
658 listener_128777 = GetListener(id_128777, EVT_N2K_128777,
this);
659 Bind(EVT_N2K_128777, [&](
ObservedEvt ev) { HandleN2K_128777(ev); });
664 listener_129029 = GetListener(id_129029, EVT_N2K_129029,
this);
665 Bind(EVT_N2K_129029, [&](
ObservedEvt ev) { HandleN2K_129029(ev); });
670 listener_129540 = GetListener(id_129540, EVT_N2K_129540,
this);
671 Bind(EVT_N2K_129540, [&](
ObservedEvt ev) { HandleN2K_129540(ev); });
676 listener_130306 = GetListener(id_130306, EVT_N2K_130306,
this);
677 Bind(EVT_N2K_130306, [&](
ObservedEvt ev) { HandleN2K_130306(ev); });
682 listener_130310 = GetListener(id_130310, EVT_N2K_130310,
this);
683 Bind(EVT_N2K_130310, [&](
ObservedEvt ev) { HandleN2K_130310(ev); });
688 listener_130313 = GetListener(id_130313, EVT_N2K_130313,
this);
689 Bind(EVT_N2K_130313, [&](
ObservedEvt ev) { HandleN2K_130313(ev); });
691 Start(1000, wxTIMER_CONTINUOUS);
698bool dashboard_pi::DeInit(
void) {
703 for (
size_t i = 0; i < m_ArrayOfDashboardWindow.GetCount(); i++) {
705 m_ArrayOfDashboardWindow.Item(i)->m_pDashboardWindow;
706 if (dashboard_window) {
707 m_pauimgr->DetachPane(dashboard_window);
708 dashboard_window->Close();
709 dashboard_window->Destroy();
710 m_ArrayOfDashboardWindow.Item(i)->m_pDashboardWindow = NULL;
714 for (
size_t i = 0; i < m_ArrayOfDashboardWindow.GetCount(); i++) {
729 if (value.IsDouble()) {
730 d_ret = value.AsDouble();
732 }
else if (value.IsLong()) {
733 int i_ret = value.AsLong();
740void dashboard_pi::Notify() {
741 SendUtcTimeToAllInstruments(mUTCDateTime);
742 for (
size_t i = 0; i < m_ArrayOfDashboardWindow.GetCount(); i++) {
744 m_ArrayOfDashboardWindow.Item(i)->m_pDashboardWindow;
745 if (dashboard_window) {
746 dashboard_window->Refresh();
747#ifdef __OCPN__ANDROID__
748 wxWindowList list = dashboard_window->GetChildren();
749 wxWindowListNode *node = list.GetFirst();
750 for (
size_t i = 0; i < list.GetCount(); i++) {
751 wxWindow *win = node->GetData();
754 node = node->GetNext();
762 if (mHDx_Watchdog <= 0) {
765 SendSentenceToAllInstruments(OCPN_DBP_STC_HDM, mHdm, _T(
"\u00B0"));
766 mHDx_Watchdog = gps_watchdog_timeout_ticks;
770 if (mHDT_Watchdog <= 0) {
772 SendSentenceToAllInstruments(OCPN_DBP_STC_HDT, NAN, _T(
"\u00B0T"));
773 mHDT_Watchdog = gps_watchdog_timeout_ticks;
777 if (mVar_Watchdog <= 0) {
780 SendSentenceToAllInstruments(OCPN_DBP_STC_HMV, NAN, _T(
"\u00B0T"));
781 mVar_Watchdog = gps_watchdog_timeout_ticks;
785 if (mSatsUsed_Wdog <= 0) {
788 SendSentenceToAllInstruments(OCPN_DBP_STC_SAT, NAN, _T(
""));
789 mSatsUsed_Wdog = gps_watchdog_timeout_ticks;
792 if (m_PriN2kTalker < -1e6) m_PriN2kTalker = 0;
795 if (mSatStatus_Wdog <= 0) {
797 for (
int i = 0; i < 4; i++) {
798 sats[i].SatNumber = 0;
799 sats[i].SignalToNoiseRatio = 0;
801 SendSatInfoToAllInstruments(0, 1, wxEmptyString, sats);
802 SendSatInfoToAllInstruments(0, 2, wxEmptyString, sats);
803 SendSatInfoToAllInstruments(0, 3, wxEmptyString, sats);
805 mSatStatus_Wdog = gps_watchdog_timeout_ticks;
809 std::vector<std::string> PriorityIDs = GetActivePriorityIdentifiers();
812 std::string satID = PriorityIDs[4].substr(0, PriorityIDs[4].find(
':'));
813 if (satID.find(
"nmea0183") != std::string::npos)
815 else if (satID.find(
"ignal") != std::string::npos)
817 else if (satID.find(
"nmea2000") != std::string::npos) {
818 prioN2kPGNsat = PriorityIDs[4];
823 if (mMWVA_Watchdog <= 0) {
824 SendSentenceToAllInstruments(OCPN_DBP_STC_AWA, NAN, _T(
"-"));
825 SendSentenceToAllInstruments(OCPN_DBP_STC_AWS, NAN, _T(
"-"));
827 mMWVA_Watchdog = gps_watchdog_timeout_ticks;
831 if (mMWVT_Watchdog <= 0) {
832 SendSentenceToAllInstruments(OCPN_DBP_STC_TWA, NAN, _T(
"-"));
833 SendSentenceToAllInstruments(OCPN_DBP_STC_TWS, NAN, _T(
"-"));
834 SendSentenceToAllInstruments(OCPN_DBP_STC_TWS2, NAN, _T(
"-"));
836 mMWVT_Watchdog = gps_watchdog_timeout_ticks;
840 if (mDPT_DBT_Watchdog <= 0) {
842 SendSentenceToAllInstruments(OCPN_DBP_STC_DPT, NAN, _T(
"-"));
843 mDPT_DBT_Watchdog = gps_watchdog_timeout_ticks;
847 if (mSTW_Watchdog <= 0) {
849 SendSentenceToAllInstruments(OCPN_DBP_STC_STW, NAN, _T(
"-"));
850 mSTW_Watchdog = gps_watchdog_timeout_ticks;
854 if (mWTP_Watchdog <= 0) {
856 SendSentenceToAllInstruments(OCPN_DBP_STC_TMP, NAN,
"-");
857 mWTP_Watchdog = no_nav_watchdog_timeout_ticks;
860 if (mRSA_Watchdog <= 0) {
862 SendSentenceToAllInstruments(OCPN_DBP_STC_RSA, NAN,
"-");
863 mRSA_Watchdog = gps_watchdog_timeout_ticks;
866 if (mVMG_Watchdog <= 0) {
867 SendSentenceToAllInstruments(OCPN_DBP_STC_VMG, NAN,
"-");
868 mVMG_Watchdog = gps_watchdog_timeout_ticks;
871 if (mVMGW_Watchdog <= 0) {
872 SendSentenceToAllInstruments(OCPN_DBP_STC_VMGW, NAN,
"-");
873 mVMGW_Watchdog = gps_watchdog_timeout_ticks;
876 if (mUTC_Watchdog <= 0) {
878 mUTC_Watchdog = gps_watchdog_timeout_ticks;
881 if (mATMP_Watchdog <= 0) {
882 SendSentenceToAllInstruments(OCPN_DBP_STC_ATMP, NAN,
"-");
884 mATMP_Watchdog = gps_watchdog_timeout_ticks;
887 if (mWDN_Watchdog <= 0) {
888 SendSentenceToAllInstruments(OCPN_DBP_STC_TWD, NAN, _T(
"-"));
890 mWDN_Watchdog = no_nav_watchdog_timeout_ticks;
893 if (mMDA_Watchdog <= 0) {
894 SendSentenceToAllInstruments(OCPN_DBP_STC_MDA, NAN, _T(
"-"));
896 mMDA_Watchdog = gps_watchdog_timeout_ticks;
899 if (mPITCH_Watchdog <= 0) {
901 SendSentenceToAllInstruments(OCPN_DBP_STC_PITCH, NAN, _T(
"-"));
902 mPITCH_Watchdog = gps_watchdog_timeout_ticks;
905 if (mHEEL_Watchdog <= 0) {
907 SendSentenceToAllInstruments(OCPN_DBP_STC_HEEL, NAN, _T(
"-"));
908 mHEEL_Watchdog = gps_watchdog_timeout_ticks;
911 if (mALT_Watchdog <= 0) {
913 SendSentenceToAllInstruments(OCPN_DBP_STC_ALTI, NAN, _T(
"-"));
914 mALT_Watchdog = gps_watchdog_timeout_ticks;
918 if (mLOG_Watchdog <= 0) {
919 SendSentenceToAllInstruments(OCPN_DBP_STC_VLW2, NAN, _T(
"-"));
920 mLOG_Watchdog = no_nav_watchdog_timeout_ticks;
923 if (mTrLOG_Watchdog <= 0) {
924 SendSentenceToAllInstruments(OCPN_DBP_STC_VLW1, NAN, _T(
"-"));
925 mTrLOG_Watchdog = no_nav_watchdog_timeout_ticks;
928 if (mHUM_Watchdog <= 0) {
930 SendSentenceToAllInstruments(OCPN_DBP_STC_HUM, NAN, _T(
"-"));
931 mHUM_Watchdog = no_nav_watchdog_timeout_ticks;
934 if (mWCC_Watchdog <= 0) {
935 SendSentenceToAllInstruments(OCPN_DBP_STC_WCC, NAN, _T(
"-"));
936 mWCC_Watchdog = no_nav_watchdog_timeout_ticks;
940int dashboard_pi::GetAPIVersionMajor() {
return MY_API_VERSION_MAJOR; }
942int dashboard_pi::GetAPIVersionMinor() {
return MY_API_VERSION_MINOR; }
944int dashboard_pi::GetPlugInVersionMajor() {
return PLUGIN_VERSION_MAJOR; }
946int dashboard_pi::GetPlugInVersionMinor() {
return PLUGIN_VERSION_MINOR; }
950wxString dashboard_pi::GetCommonName() {
return _(
"Dashboard"); }
952wxString dashboard_pi::GetShortDescription() {
953 return _(
"Dashboard PlugIn for OpenCPN");
956wxString dashboard_pi::GetLongDescription() {
958 "Dashboard PlugIn for OpenCPN\n\
959Provides navigation instrument display from NMEA source.");
962void dashboard_pi::SendSentenceToAllInstruments(DASH_CAP st,
double value,
964 for (
size_t i = 0; i < m_ArrayOfDashboardWindow.GetCount(); i++) {
966 m_ArrayOfDashboardWindow.Item(i)->m_pDashboardWindow;
967 if (dashboard_window)
968 dashboard_window->SendSentenceToAllInstruments(st, value,
unit);
970 if (st == OCPN_DBP_STC_HDT) {
973 if (st == OCPN_DBP_STC_SOG) {
976 if (st == OCPN_DBP_STC_COG) {
981void dashboard_pi::SendUtcTimeToAllInstruments(wxDateTime value) {
982 for (
size_t i = 0; i < m_ArrayOfDashboardWindow.GetCount(); i++) {
984 m_ArrayOfDashboardWindow.Item(i)->m_pDashboardWindow;
985 if (dashboard_window) dashboard_window->SendUtcTimeToAllInstruments(value);
989void dashboard_pi::SendSatInfoToAllInstruments(
int cnt,
int seq, wxString talk,
991 for (
size_t i = 0; i < m_ArrayOfDashboardWindow.GetCount(); i++) {
993 m_ArrayOfDashboardWindow.Item(i)->m_pDashboardWindow;
994 if (dashboard_window)
995 dashboard_window->SendSatInfoToAllInstruments(cnt, seq, talk, sats);
1001 m_NMEA0183 << sentence;
1003 if (m_NMEA0183.PreParse()) {
1004 if (m_NMEA0183.LastSentenceIDReceived == _T(
"DBT")) {
1005 if (mPriDepth >= 5) {
1006 if (m_NMEA0183.Parse()) {
1013 if (!std::isnan(m_NMEA0183.Dbt.DepthMeters))
1014 depth = m_NMEA0183.Dbt.DepthMeters;
1015 else if (!std::isnan(m_NMEA0183.Dbt.DepthFeet))
1016 depth = m_NMEA0183.Dbt.DepthFeet * 0.3048;
1017 else if (!std::isnan(m_NMEA0183.Dbt.DepthFathoms))
1018 depth = m_NMEA0183.Dbt.DepthFathoms * 1.82880;
1019 if (!std::isnan(depth)) depth += g_dDashDBTOffset;
1020 if (!std::isnan(depth)) {
1021 SendSentenceToAllInstruments(
1023 toUsrDistance_Plugin(depth / 1852.0, g_iDashDepthUnit),
1024 getUsrDistanceUnit_Plugin(g_iDashDepthUnit));
1026 mDPT_DBT_Watchdog = gps_watchdog_timeout_ticks;
1032 else if (m_NMEA0183.LastSentenceIDReceived == _T(
"DPT")) {
1033 if (mPriDepth >= 4) {
1034 if (m_NMEA0183.Parse()) {
1039 double depth = m_NMEA0183.Dpt.DepthMeters;
1040 if (!std::isnan(m_NMEA0183.Dpt.OffsetFromTransducerMeters)) {
1041 depth += m_NMEA0183.Dpt.OffsetFromTransducerMeters;
1043 depth += g_dDashDBTOffset;
1044 if (!std::isnan(depth)) {
1045 SendSentenceToAllInstruments(
1047 toUsrDistance_Plugin(depth / 1852.0, g_iDashDepthUnit),
1048 getUsrDistanceUnit_Plugin(g_iDashDepthUnit));
1050 mDPT_DBT_Watchdog = gps_watchdog_timeout_ticks;
1056 else if (m_NMEA0183.LastSentenceIDReceived == _T(
"GGA")) {
1058 printf(
"GGA mPriPosition=%d mPriSatUsed=%d \tnSat=%d alt=%3.2f\n",
1059 mPriPosition, mPriSatUsed,
1060 m_NMEA0183.Gga.NumberOfSatellitesInUse,
1061 m_NMEA0183.Gga.AntennaAltitudeMeters);
1062 if (mPriAlt >= 3 && (mPriPosition >= 1 || mPriSatUsed >= 1)) {
1063 if (m_NMEA0183.Parse()) {
1064 if (m_NMEA0183.Gga.GPSQuality > 0 &&
1065 m_NMEA0183.Gga.NumberOfSatellitesInUse >= 5) {
1068 double alt = m_NMEA0183.Gga.AntennaAltitudeMeters;
1069 SendSentenceToAllInstruments(OCPN_DBP_STC_ALTI, alt, _T(
"m"));
1071 mALT_Watchdog = gps_watchdog_timeout_ticks;
1075 if (mPriPosition >= 4 || mPriSatUsed >= 3) {
1076 if (m_NMEA0183.Parse()) {
1077 if (m_NMEA0183.Gga.GPSQuality > 0) {
1078 if (mPriPosition >= 4) {
1081 float llt = m_NMEA0183.Gga.Position.Latitude.Latitude;
1082 int lat_deg_int = (int)(llt / 100);
1083 float lat_deg = lat_deg_int;
1084 float lat_min = llt - (lat_deg * 100);
1085 lat = lat_deg + (lat_min / 60.);
1086 if (m_NMEA0183.Gga.Position.Latitude.Northing == South)
1088 SendSentenceToAllInstruments(OCPN_DBP_STC_LAT, lat, _T(
"SDMM"));
1090 float lln = m_NMEA0183.Gga.Position.Longitude.Longitude;
1091 int lon_deg_int = (int)(lln / 100);
1092 float lon_deg = lon_deg_int;
1093 float lon_min = lln - (lon_deg * 100);
1094 lon = lon_deg + (lon_min / 60.);
1095 if (m_NMEA0183.Gga.Position.Longitude.Easting == West) lon = -lon;
1096 SendSentenceToAllInstruments(OCPN_DBP_STC_LON, lon, _T(
"SDMM"));
1098 if (mPriSatUsed >= 3) {
1099 mSatsInUse = m_NMEA0183.Gga.NumberOfSatellitesInUse;
1100 SendSentenceToAllInstruments(OCPN_DBP_STC_SAT, mSatsInUse,
1103 mSatsUsed_Wdog = gps_watchdog_timeout_ticks;
1117 else if (m_NMEA0183.LastSentenceIDReceived == _T(
"GLL")) {
1118 if (mPriPosition >= 3) {
1119 if (m_NMEA0183.Parse()) {
1120 if (m_NMEA0183.Gll.IsDataValid == NTrue) {
1122 float llt = m_NMEA0183.Gll.Position.Latitude.Latitude;
1123 int lat_deg_int = (int)(llt / 100);
1124 float lat_deg = lat_deg_int;
1125 float lat_min = llt - (lat_deg * 100);
1126 lat = lat_deg + (lat_min / 60.);
1127 if (m_NMEA0183.Gll.Position.Latitude.Northing == South) lat = -lat;
1128 SendSentenceToAllInstruments(OCPN_DBP_STC_LAT, lat, _T(
"SDMM"));
1130 float lln = m_NMEA0183.Gll.Position.Longitude.Longitude;
1131 int lon_deg_int = (int)(lln / 100);
1132 float lon_deg = lon_deg_int;
1133 float lon_min = lln - (lon_deg * 100);
1134 lon = lon_deg + (lon_min / 60.);
1135 if (m_NMEA0183.Gll.Position.Longitude.Easting == West) lon = -lon;
1136 SendSentenceToAllInstruments(OCPN_DBP_STC_LON, lon, _T(
"SDMM"));
1151 else if (m_NMEA0183.LastSentenceIDReceived == _T(
"GSV")) {
1152 if (mPriSatStatus >= 3 || mPriSatUsed >= 5) {
1153 if (m_NMEA0183.Parse()) {
1154 if (m_NMEA0183.Gsv.MessageNumber == 1) {
1157 mSatsInView = m_NMEA0183.Gsv.SatsInView;
1159 if (mPriSatUsed >= 5) {
1160 SendSentenceToAllInstruments(OCPN_DBP_STC_SAT,
1161 m_NMEA0183.Gsv.SatsInView, _T (
""));
1163 mSatsUsed_Wdog = gps_watchdog_timeout_ticks;
1167 if (mPriSatStatus >= 3) {
1168 SendSatInfoToAllInstruments(
1169 mSatsInView, m_NMEA0183.Gsv.MessageNumber, m_NMEA0183.TalkerID,
1170 m_NMEA0183.Gsv.SatInfo);
1172 mSatStatus_Wdog = gps_watchdog_timeout_ticks;
1178 else if (m_NMEA0183.LastSentenceIDReceived == _T(
"HDG")) {
1179 if (mPriVar >= 3 || mPriHeadingM >= 3 || mPriHeadingT >= 7) {
1180 if (m_NMEA0183.Parse()) {
1185 if ((!std::isnan(m_NMEA0183.Hdg.MagneticVariationDegrees)) &&
1186 0.0 != m_NMEA0183.Hdg.MagneticVariationDegrees) {
1188 if (m_NMEA0183.Hdg.MagneticVariationDirection == East)
1189 mVar = m_NMEA0183.Hdg.MagneticVariationDegrees;
1190 else if (m_NMEA0183.Hdg.MagneticVariationDirection == West)
1191 mVar = -m_NMEA0183.Hdg.MagneticVariationDegrees;
1192 SendSentenceToAllInstruments(OCPN_DBP_STC_HMV, mVar,
1196 if (mPriHeadingM >= 3) {
1197 if (!std::isnan(m_NMEA0183.Hdg.MagneticSensorHeadingDegrees)) {
1199 mHdm = m_NMEA0183.Hdg.MagneticSensorHeadingDegrees;
1200 SendSentenceToAllInstruments(OCPN_DBP_STC_HDM, mHdm,
1204 if (!std::isnan(m_NMEA0183.Hdg.MagneticSensorHeadingDegrees))
1205 mHDx_Watchdog = gps_watchdog_timeout_ticks;
1209 if (!std::isnan(m_NMEA0183.Hdg.MagneticSensorHeadingDegrees)) {
1210 if (!std::isnan(mVar) && (mPriHeadingT >= 7)) {
1212 double heading = mHdm + mVar;
1215 else if (heading >= 360.0)
1217 SendSentenceToAllInstruments(OCPN_DBP_STC_HDT, heading,
1219 mHDT_Watchdog = gps_watchdog_timeout_ticks;
1226 else if (m_NMEA0183.LastSentenceIDReceived == _T(
"HDM")) {
1227 if (mPriHeadingM >= 4 || mPriHeadingT >= 5) {
1228 if (m_NMEA0183.Parse()) {
1229 if (mPriHeadingM >= 4) {
1230 if (!std::isnan(m_NMEA0183.Hdm.DegreesMagnetic)) {
1232 mHdm = m_NMEA0183.Hdm.DegreesMagnetic;
1233 SendSentenceToAllInstruments(OCPN_DBP_STC_HDM, mHdm,
1235 mHDx_Watchdog = gps_watchdog_timeout_ticks;
1241 if (!std::isnan(m_NMEA0183.Hdm.DegreesMagnetic)) {
1242 if (!std::isnan(mVar) && (mPriHeadingT >= 5)) {
1244 double heading = mHdm + mVar;
1247 else if (heading >= 360.0)
1249 SendSentenceToAllInstruments(OCPN_DBP_STC_HDT, heading,
1251 mHDT_Watchdog = gps_watchdog_timeout_ticks;
1258 else if (m_NMEA0183.LastSentenceIDReceived == _T(
"HDT")) {
1259 if (mPriHeadingT >= 3) {
1260 if (m_NMEA0183.Parse()) {
1261 if (!std::isnan(m_NMEA0183.Hdt.DegreesTrue)) {
1262 SendSentenceToAllInstruments(
1263 OCPN_DBP_STC_HDT, m_NMEA0183.Hdt.DegreesTrue, _T(
"\u00B0T"));
1265 mHDT_Watchdog = gps_watchdog_timeout_ticks;
1269 }
else if (m_NMEA0183.LastSentenceIDReceived ==
1271 if (mPriATMP >= 3) {
1272 if (m_NMEA0183.Parse()) {
1274 SendSentenceToAllInstruments(
1276 toUsrTemp_Plugin(m_NMEA0183.Mta.Temperature, g_iDashTempUnit),
1277 getUsrTempUnit_Plugin(g_iDashTempUnit));
1278 mATMP_Watchdog = gps_watchdog_timeout_ticks;
1281 }
else if (m_NMEA0183.LastSentenceIDReceived == _T(
"MDA") &&
1282 (mPriMDA >= 5 || mPriATMP >= 5 || mPriHUM >= 4)) {
1284 if (m_NMEA0183.Parse()) {
1290 if (mPriMDA >= 5 && m_NMEA0183.Mda.Pressure > .8 &&
1291 m_NMEA0183.Mda.Pressure < 1.1) {
1292 SendSentenceToAllInstruments(
1293 OCPN_DBP_STC_MDA, m_NMEA0183.Mda.Pressure * 1000, _T(
"hPa"));
1295 mMDA_Watchdog = no_nav_watchdog_timeout_ticks;
1297 if (mPriATMP >= 5) {
1298 double airtemp = m_NMEA0183.Mda.AirTemp;
1299 if (!std::isnan(airtemp) && airtemp < 999.0) {
1300 SendSentenceToAllInstruments(
1301 OCPN_DBP_STC_ATMP, toUsrTemp_Plugin(airtemp, g_iDashTempUnit),
1302 getUsrTempUnit_Plugin(g_iDashTempUnit));
1303 mATMP_Watchdog = no_nav_watchdog_timeout_ticks;
1308 double humidity = m_NMEA0183.Mda.Humidity;
1309 if (!std::isnan(humidity)) {
1310 SendSentenceToAllInstruments(OCPN_DBP_STC_HUM, humidity,
"%");
1311 mHUM_Watchdog = no_nav_watchdog_timeout_ticks;
1317 }
else if (m_NMEA0183.LastSentenceIDReceived == _T(
"MTW")) {
1319 if (m_NMEA0183.Parse()) {
1321 SendSentenceToAllInstruments(
1323 toUsrTemp_Plugin(m_NMEA0183.Mtw.Temperature, g_iDashTempUnit),
1324 getUsrTempUnit_Plugin(g_iDashTempUnit));
1325 mWTP_Watchdog = no_nav_watchdog_timeout_ticks;
1329 }
else if (m_NMEA0183.LastSentenceIDReceived == _T(
"VLW")) {
1330 if (m_NMEA0183.Parse()) {
1335 SendSentenceToAllInstruments(
1337 toUsrDistance_Plugin(m_NMEA0183.Vlw.TripMileage,
1338 g_iDashDistanceUnit),
1339 getUsrDistanceUnit_Plugin(g_iDashDistanceUnit));
1340 mTrLOG_Watchdog = no_nav_watchdog_timeout_ticks;
1342 SendSentenceToAllInstruments(
1344 toUsrDistance_Plugin(m_NMEA0183.Vlw.TotalMileage,
1345 g_iDashDistanceUnit),
1346 getUsrDistanceUnit_Plugin(g_iDashDistanceUnit));
1347 mLOG_Watchdog = no_nav_watchdog_timeout_ticks;
1352 else if (m_NMEA0183.LastSentenceIDReceived == _T(
"MWD")) {
1354 if (m_NMEA0183.Parse()) {
1357 if (!std::isnan(m_NMEA0183.Mwd.WindAngleTrue)) {
1359 SendSentenceToAllInstruments(
1360 OCPN_DBP_STC_TWD, m_NMEA0183.Mwd.WindAngleTrue, _T(
"\u00B0"));
1363 mWDN_Watchdog = no_nav_watchdog_timeout_ticks;
1364 }
else if (!std::isnan(m_NMEA0183.Mwd.WindAngleMagnetic)) {
1366 if (!std::isnan(mVar)) {
1367 double twd = m_NMEA0183.Mwd.WindAngleMagnetic;
1371 }
else if (twd < 0.) {
1374 SendSentenceToAllInstruments(OCPN_DBP_STC_TWD, twd, _T(
"\u00B0"));
1376 mWDN_Watchdog = no_nav_watchdog_timeout_ticks;
1379 SendSentenceToAllInstruments(
1381 toUsrSpeed_Plugin(m_NMEA0183.Mwd.WindSpeedKnots,
1382 g_iDashWindSpeedUnit),
1383 getUsrSpeedUnit_Plugin(g_iDashWindSpeedUnit));
1384 SendSentenceToAllInstruments(
1386 toUsrSpeed_Plugin(m_NMEA0183.Mwd.WindSpeedKnots,
1387 g_iDashWindSpeedUnit),
1388 getUsrSpeedUnit_Plugin(g_iDashWindSpeedUnit));
1389 mMWVT_Watchdog = gps_watchdog_timeout_ticks;
1396 else if (m_NMEA0183.LastSentenceIDReceived == _T(
"MWV")) {
1397 if (mPriAWA >= 4 || mPriTWA >= 5 || mPriWDN >= 5) {
1398 if (m_NMEA0183.Parse()) {
1399 if (m_NMEA0183.Mwv.IsDataValid == NTrue) {
1402 double m_wSpeedFactor = 1.0;
1403 if (m_NMEA0183.Mwv.WindSpeedUnits == _T(
"K"))
1404 m_wSpeedFactor = 0.53995;
1405 if (m_NMEA0183.Mwv.WindSpeedUnits == _T(
"M"))
1406 m_wSpeedFactor = 1.94384;
1408 if (m_NMEA0183.Mwv.Reference ==
1415 if (m_NMEA0183.Mwv.WindAngle > 180) {
1416 m_awaunit = _T(
"\u00B0L");
1417 m_awaangle = 180.0 - (m_NMEA0183.Mwv.WindAngle - 180.0);
1419 m_awaunit = _T(
"\u00B0R");
1420 m_awaangle = m_NMEA0183.Mwv.WindAngle;
1422 SendSentenceToAllInstruments(OCPN_DBP_STC_AWA, m_awaangle,
1424 SendSentenceToAllInstruments(
1426 toUsrSpeed_Plugin(m_NMEA0183.Mwv.WindSpeed * m_wSpeedFactor,
1427 g_iDashWindSpeedUnit),
1428 getUsrSpeedUnit_Plugin(g_iDashWindSpeedUnit));
1429 mMWVA_Watchdog = gps_watchdog_timeout_ticks;
1437 CalculateAndUpdateTWDS(
1438 m_NMEA0183.Mwv.WindSpeed * m_wSpeedFactor,
1439 m_NMEA0183.Mwv.WindAngle);
1441 mWDN_Watchdog = no_nav_watchdog_timeout_ticks;
1442 mMWVT_Watchdog = gps_watchdog_timeout_ticks;
1444 }
else if (m_NMEA0183.Mwv.Reference ==
1452 if (m_NMEA0183.Mwv.WindAngle > 180) {
1453 m_twaunit = _T(
"\u00B0L");
1454 m_twaangle = 180.0 - (m_NMEA0183.Mwv.WindAngle - 180.0);
1456 m_twaunit = _T(
"\u00B0R");
1457 m_twaangle = m_NMEA0183.Mwv.WindAngle;
1460 SendSentenceToAllInstruments(OCPN_DBP_STC_TWA, m_twaangle,
1468 if (g_dHDT < 361. && g_dHDT >= 0.0) {
1469 double g_dCalWdir = (m_NMEA0183.Mwv.WindAngle) + g_dHDT;
1470 if (g_dCalWdir > 360.) {
1472 }
else if (g_dCalWdir < 0.) {
1475 SendSentenceToAllInstruments(OCPN_DBP_STC_TWD, g_dCalWdir,
1478 mWDN_Watchdog = no_nav_watchdog_timeout_ticks;
1482 SendSentenceToAllInstruments(
1484 toUsrSpeed_Plugin(m_NMEA0183.Mwv.WindSpeed * m_wSpeedFactor,
1485 g_iDashWindSpeedUnit),
1486 getUsrSpeedUnit_Plugin(g_iDashWindSpeedUnit));
1487 SendSentenceToAllInstruments(
1489 toUsrSpeed_Plugin(m_NMEA0183.Mwv.WindSpeed * m_wSpeedFactor,
1490 g_iDashWindSpeedUnit),
1491 getUsrSpeedUnit_Plugin(g_iDashWindSpeedUnit));
1492 mMWVT_Watchdog = gps_watchdog_timeout_ticks;
1500 else if (m_NMEA0183.LastSentenceIDReceived == _T(
"RMC")) {
1501 if (mPriPosition >= 5 || mPriCOGSOG >= 3 || mPriVar >= 4 ||
1502 mPriDateTime >= 3) {
1503 if (m_NMEA0183.Parse()) {
1504 if (m_NMEA0183.Rmc.IsDataValid == NTrue) {
1505 if (mPriPosition >= 5) {
1508 float llt = m_NMEA0183.Rmc.Position.Latitude.Latitude;
1509 int lat_deg_int = (int)(llt / 100);
1510 float lat_deg = lat_deg_int;
1511 float lat_min = llt - (lat_deg * 100);
1512 lat = lat_deg + (lat_min / 60.);
1513 if (m_NMEA0183.Rmc.Position.Latitude.Northing == South)
1515 SendSentenceToAllInstruments(OCPN_DBP_STC_LAT, lat, _T(
"SDMM"));
1517 float lln = m_NMEA0183.Rmc.Position.Longitude.Longitude;
1518 int lon_deg_int = (int)(lln / 100);
1519 float lon_deg = lon_deg_int;
1520 float lon_min = lln - (lon_deg * 100);
1521 lon = lon_deg + (lon_min / 60.);
1522 if (m_NMEA0183.Rmc.Position.Longitude.Easting == West) lon = -lon;
1523 SendSentenceToAllInstruments(OCPN_DBP_STC_LON, lon, _T(
"SDMM"));
1526 if (mPriCOGSOG >= 3) {
1528 if (!std::isnan(m_NMEA0183.Rmc.SpeedOverGroundKnots)) {
1529 SendSentenceToAllInstruments(
1532 mSOGFilter.filter(m_NMEA0183.Rmc.SpeedOverGroundKnots),
1534 getUsrSpeedUnit_Plugin(g_iDashSpeedUnit));
1537 if (!std::isnan(m_NMEA0183.Rmc.TrackMadeGoodDegreesTrue)) {
1538 SendSentenceToAllInstruments(
1540 mCOGFilter.filter(m_NMEA0183.Rmc.TrackMadeGoodDegreesTrue),
1543 if (!std::isnan(m_NMEA0183.Rmc.TrackMadeGoodDegreesTrue) &&
1544 !std::isnan(m_NMEA0183.Rmc.MagneticVariation)) {
1545 double dMagneticCOG;
1546 if (m_NMEA0183.Rmc.MagneticVariationDirection == East) {
1548 mCOGFilter.get() - m_NMEA0183.Rmc.MagneticVariation;
1549 if (dMagneticCOG < 0.0) dMagneticCOG = 360.0 + dMagneticCOG;
1552 mCOGFilter.get() + m_NMEA0183.Rmc.MagneticVariation;
1553 if (dMagneticCOG > 360.0) dMagneticCOG = dMagneticCOG - 360.0;
1555 SendSentenceToAllInstruments(OCPN_DBP_STC_MCOG, dMagneticCOG,
1564 if ((!std::isnan(m_NMEA0183.Rmc.MagneticVariation)) &&
1565 0.0 != m_NMEA0183.Rmc.MagneticVariation) {
1567 if (m_NMEA0183.Rmc.MagneticVariationDirection == East)
1568 mVar = m_NMEA0183.Rmc.MagneticVariation;
1569 else if (m_NMEA0183.Rmc.MagneticVariationDirection == West)
1570 mVar = -m_NMEA0183.Rmc.MagneticVariation;
1571 mVar_Watchdog = gps_watchdog_timeout_ticks;
1573 SendSentenceToAllInstruments(OCPN_DBP_STC_HMV, mVar,
1578 if (mPriDateTime >= 3) {
1580 wxString dt = m_NMEA0183.Rmc.Date + m_NMEA0183.Rmc.UTCTime;
1581 mUTCDateTime.ParseFormat(dt.c_str(), _T(
"%d%m%y%H%M%S"));
1582 mUTC_Watchdog = gps_watchdog_timeout_ticks;
1589 else if (m_NMEA0183.LastSentenceIDReceived == _T(
"RSA")) {
1591 if (m_NMEA0183.Parse()) {
1592 if (m_NMEA0183.Rsa.IsStarboardDataValid == NTrue) {
1593 SendSentenceToAllInstruments(
1594 OCPN_DBP_STC_RSA, m_NMEA0183.Rsa.Starboard, _T(
"\u00B0"));
1595 }
else if (m_NMEA0183.Rsa.IsPortDataValid == NTrue) {
1596 SendSentenceToAllInstruments(OCPN_DBP_STC_RSA, -m_NMEA0183.Rsa.Port,
1599 mRSA_Watchdog = gps_watchdog_timeout_ticks;
1605 else if (m_NMEA0183.LastSentenceIDReceived == _T(
"VHW")) {
1606 if (mPriHeadingT >= 4 || mPriHeadingM >= 5 || mPriSTW >= 3) {
1607 if (m_NMEA0183.Parse()) {
1608 if (mPriHeadingT >= 4) {
1609 if (!std::isnan(m_NMEA0183.Vhw.DegreesTrue)) {
1611 SendSentenceToAllInstruments(
1612 OCPN_DBP_STC_HDT, m_NMEA0183.Vhw.DegreesTrue, _T(
"\u00B0T"));
1613 mHDT_Watchdog = gps_watchdog_timeout_ticks;
1616 if (mPriHeadingM >= 5) {
1617 if (!std::isnan(m_NMEA0183.Vhw.DegreesMagnetic)) {
1619 SendSentenceToAllInstruments(OCPN_DBP_STC_HDM,
1620 m_NMEA0183.Vhw.DegreesMagnetic,
1622 mHDx_Watchdog = gps_watchdog_timeout_ticks;
1626 double stw_kn = NAN;
1627 if (!std::isnan(m_NMEA0183.Vhw.Knots))
1628 stw_kn = m_NMEA0183.Vhw.Knots;
1629 else if (!std::isnan(m_NMEA0183.Vhw.KilometersPerHour))
1630 stw_kn = m_NMEA0183.Vhw.KilometersPerHour * 0.53995;
1632 if (!std::isnan(stw_kn)) {
1633 SendSentenceToAllInstruments(
1634 OCPN_DBP_STC_STW, toUsrSpeed_Plugin(stw_kn, g_iDashSpeedUnit),
1635 getUsrSpeedUnit_Plugin(g_iDashSpeedUnit));
1636 mSTW_Watchdog = gps_watchdog_timeout_ticks;
1644 else if (m_NMEA0183.LastSentenceIDReceived == _T(
"VTG")) {
1645 if (mPriCOGSOG >= 2) {
1646 if (m_NMEA0183.Parse()) {
1649 if (!std::isnan(m_NMEA0183.Vtg.SpeedKnots)) {
1650 SendSentenceToAllInstruments(
1652 toUsrSpeed_Plugin(mSOGFilter.filter(m_NMEA0183.Vtg.SpeedKnots),
1654 getUsrSpeedUnit_Plugin(g_iDashSpeedUnit));
1657 if (!std::isnan(m_NMEA0183.Vtg.TrackDegreesTrue)) {
1658 SendSentenceToAllInstruments(
1660 mCOGFilter.filter(m_NMEA0183.Vtg.TrackDegreesTrue),
1674 else if (m_NMEA0183.LastSentenceIDReceived == _T(
"VWR")) {
1676 if (m_NMEA0183.Parse()) {
1677 if (m_NMEA0183.Vwr.WindDirectionMagnitude < 200) {
1681 awaunit = m_NMEA0183.Vwr.DirectionOfWind == Left ? _T(
"\u00B0L")
1683 SendSentenceToAllInstruments(OCPN_DBP_STC_AWA,
1684 m_NMEA0183.Vwr.WindDirectionMagnitude,
1686 SendSentenceToAllInstruments(
1688 toUsrSpeed_Plugin(m_NMEA0183.Vwr.WindSpeedKnots,
1689 g_iDashWindSpeedUnit),
1690 getUsrSpeedUnit_Plugin(g_iDashWindSpeedUnit));
1691 mMWVA_Watchdog = gps_watchdog_timeout_ticks;
1703 double awa = m_NMEA0183.Vwr.WindDirectionMagnitude;
1704 if (m_NMEA0183.Vwr.DirectionOfWind == Left)
1705 awa = 360. - m_NMEA0183.Vwr.WindDirectionMagnitude;
1706 CalculateAndUpdateTWDS(m_NMEA0183.Vwr.WindSpeedKnots, awa);
1708 mMWVT_Watchdog = gps_watchdog_timeout_ticks;
1709 mWDN_Watchdog = no_nav_watchdog_timeout_ticks;
1720 else if (m_NMEA0183.LastSentenceIDReceived == _T(
"VWT")) {
1722 if (m_NMEA0183.Parse()) {
1723 if (m_NMEA0183.Vwt.WindDirectionMagnitude < 200) {
1726 vwtunit = m_NMEA0183.Vwt.DirectionOfWind == Left ? _T(
"\u00B0L")
1728 SendSentenceToAllInstruments(OCPN_DBP_STC_TWA,
1729 m_NMEA0183.Vwt.WindDirectionMagnitude,
1731 SendSentenceToAllInstruments(
1733 toUsrSpeed_Plugin(m_NMEA0183.Vwt.WindSpeedKnots,
1734 g_iDashWindSpeedUnit),
1735 getUsrSpeedUnit_Plugin(g_iDashWindSpeedUnit));
1736 mMWVT_Watchdog = gps_watchdog_timeout_ticks;
1746 else if (m_NMEA0183.LastSentenceIDReceived ==
1761 if (m_NMEA0183.Parse()) {
1764 for (
int i = 0; i < m_NMEA0183.Xdr.TransducerCnt; i++) {
1765 xdrdata = m_NMEA0183.Xdr.TransducerInfo[i].MeasurementData;
1767 if (m_NMEA0183.Xdr.TransducerInfo[i].TransducerType == _T(
"C")) {
1768 if (m_NMEA0183.Xdr.TransducerInfo[i]
1769 .TransducerName.MakeUpper()
1770 .Contains(_T(
"AIR")) ||
1771 m_NMEA0183.Xdr.TransducerInfo[i].TransducerName == _T(
"Te") ||
1772 m_NMEA0183.Xdr.TransducerInfo[i].TransducerName ==
1773 _T(
"ENV_OUTAIR_T") ||
1774 m_NMEA0183.Xdr.TransducerInfo[i].TransducerName ==
1775 _T(
"ENV_OUTSIDE_T")) {
1776 if (mPriATMP >= 4) {
1778 SendSentenceToAllInstruments(
1780 toUsrTemp_Plugin(xdrdata, g_iDashTempUnit),
1781 getUsrTempUnit_Plugin(g_iDashTempUnit));
1782 mATMP_Watchdog = no_nav_watchdog_timeout_ticks;
1786 if (m_NMEA0183.Xdr.TransducerInfo[i]
1787 .TransducerName.MakeUpper()
1788 .Contains(
"WATER") ||
1789 m_NMEA0183.Xdr.TransducerInfo[i].TransducerName ==
"WTHI") {
1792 SendSentenceToAllInstruments(
1795 m_NMEA0183.Xdr.TransducerInfo[i].MeasurementData,
1797 getUsrTempUnit_Plugin(g_iDashTempUnit));
1798 mWTP_Watchdog = no_nav_watchdog_timeout_ticks;
1804 if (m_NMEA0183.Xdr.TransducerInfo[i].TransducerType ==
"P") {
1805 if (m_NMEA0183.Xdr.TransducerInfo[i]
1806 .TransducerName.MakeUpper()
1807 .Contains(_T(
"BARO")) &&
1809 if (m_NMEA0183.Xdr.TransducerInfo[i].UnitOfMeasurement ==
"B") {
1811 SendSentenceToAllInstruments(OCPN_DBP_STC_MDA, xdrdata,
1814 mMDA_Watchdog = no_nav_watchdog_timeout_ticks;
1820 if (m_NMEA0183.Xdr.TransducerInfo[i].TransducerType == _T(
"A")) {
1821 if (m_NMEA0183.Xdr.TransducerInfo[i].TransducerName.Contains(
1823 m_NMEA0183.Xdr.TransducerInfo[i].TransducerName.Contains(
1825 if (mPriPitchRoll >= 3) {
1826 if (m_NMEA0183.Xdr.TransducerInfo[i].MeasurementData > 0) {
1827 xdrunit = _T(
"\u00B0\u2191") + _(
"Up");
1828 }
else if (m_NMEA0183.Xdr.TransducerInfo[i].MeasurementData <
1830 xdrunit = _T(
"\u00B0\u2193") + _(
"Down");
1833 xdrunit = _T(
"\u00B0");
1835 SendSentenceToAllInstruments(OCPN_DBP_STC_PITCH, xdrdata,
1837 mPITCH_Watchdog = gps_watchdog_timeout_ticks;
1843 if (m_NMEA0183.Xdr.TransducerInfo[i].TransducerName.Contains(
1845 if (mPriPitchRoll >= 3) {
1846 if (m_NMEA0183.Xdr.TransducerInfo[i].MeasurementData > 0) {
1847 xdrunit = _T(
"\u00B0\u003E") + _(
"Stbd");
1848 }
else if (m_NMEA0183.Xdr.TransducerInfo[i].MeasurementData <
1850 xdrunit = _T(
"\u00B0\u003C") + _(
"Port");
1853 xdrunit = _T(
"\u00B0");
1855 SendSentenceToAllInstruments(OCPN_DBP_STC_HEEL, xdrdata,
1857 mHEEL_Watchdog = gps_watchdog_timeout_ticks;
1863 if (m_NMEA0183.Xdr.TransducerInfo[i]
1864 .TransducerName.MakeUpper()
1865 .Contains(
"RUDDER")) {
1867 SendSentenceToAllInstruments(OCPN_DBP_STC_RSA, xdrdata,
1869 mRSA_Watchdog = gps_watchdog_timeout_ticks;
1876 if ((m_NMEA0183.Xdr.TransducerInfo[i].TransducerType ==
"D")) {
1877 bool good_depth =
false;
1878 if (m_NMEA0183.Xdr.TransducerInfo[i].TransducerName ==
"XDHI" &&
1882 }
else if (m_NMEA0183.Xdr.TransducerInfo[i].TransducerName ==
1889 else if (m_NMEA0183.Xdr.TransducerInfo[i].TransducerName ==
1891 m_NMEA0183.Xdr.TransducerInfo[i].TransducerName ==
1894 m_NMEA0183.Xdr.TransducerInfo[i].UnitOfMeasurement;
1895 if (
unit == wxEmptyString)
unit =
"m";
1897 SendSentenceToAllInstruments(OCPN_DBP_STC_WCC, xdrdata,
unit);
1898 mWCC_Watchdog = no_nav_watchdog_timeout_ticks;
1902 wxString
unit = m_NMEA0183.Xdr.TransducerInfo[i]
1903 .UnitOfMeasurement.MakeLower();
1907 if (!std::isnan(depth)) {
1908 depth += g_dDashDBTOffset;
1909 SendSentenceToAllInstruments(
1911 toUsrDistance_Plugin(depth / 1852.0, g_iDashDepthUnit),
1912 getUsrDistanceUnit_Plugin(g_iDashDepthUnit));
1913 mDPT_DBT_Watchdog = gps_watchdog_timeout_ticks;
1919 if (m_NMEA0183.Xdr.TransducerInfo[i].TransducerType ==
"H") {
1921 if (m_NMEA0183.Xdr.TransducerInfo[i].UnitOfMeasurement ==
"P") {
1922 SendSentenceToAllInstruments(OCPN_DBP_STC_HUM, xdrdata,
"%");
1924 mHUM_Watchdog = no_nav_watchdog_timeout_ticks;
1930 }
else if (m_NMEA0183.LastSentenceIDReceived == _T(
"ZDA")) {
1931 if (mPriDateTime >= 2) {
1932 if (m_NMEA0183.Parse()) {
1943 dt.Printf(_T(
"%4d%02d%02d"), m_NMEA0183.Zda.Year,
1944 m_NMEA0183.Zda.Month, m_NMEA0183.Zda.Day);
1945 dt.Append(m_NMEA0183.Zda.UTCTime);
1946 mUTCDateTime.ParseFormat(dt.c_str(), _T(
"%Y%m%d%H%M%S"));
1947 mUTC_Watchdog = gps_watchdog_timeout_ticks;
1953 else if (sentence.Mid(1, 5).IsSameAs(_T(
"AIVDO"))) {
1955 if (DecodeSingleVDOMessage(sentence, &gpd, &m_VDO_accumulator)) {
1956 if (!std::isnan(gpd.Lat))
1957 SendSentenceToAllInstruments(OCPN_DBP_STC_LAT, gpd.Lat, _T(
"SDMM"));
1959 if (!std::isnan(gpd.Lon))
1960 SendSentenceToAllInstruments(OCPN_DBP_STC_LON, gpd.Lon, _T(
"SDMM"));
1962 SendSentenceToAllInstruments(
1964 toUsrSpeed_Plugin(mSOGFilter.filter(gpd.Sog), g_iDashSpeedUnit),
1965 getUsrSpeedUnit_Plugin(g_iDashSpeedUnit));
1966 SendSentenceToAllInstruments(OCPN_DBP_STC_COG, mCOGFilter.filter(gpd.Cog),
1968 if (!std::isnan(gpd.Hdt)) {
1969 SendSentenceToAllInstruments(OCPN_DBP_STC_HDT, gpd.Hdt, _T(
"\u00B0T"));
1970 mHDT_Watchdog = gps_watchdog_timeout_ticks;
1981void dashboard_pi::CalculateAndUpdateTWDS(
double awsKnots,
double awaDegrees) {
1982 if (!std::isnan(g_dHDT)) {
1984 double awsx = awsKnots * cos(awaDegrees * PI / 180.);
1985 double awsy = awsKnots * sin(awaDegrees * PI / 180.);
1990 if ((!std::isnan(g_dSOG)) && (!std::isnan(g_dCOG))) {
1991 bsx = g_dSOG * cos((g_dCOG - g_dHDT) * PI / 180.);
1992 bsy = g_dSOG * sin((g_dCOG - g_dHDT) * PI / 180.);
1997 double twdx = awsx - bsx;
1998 double twdy = awsy - bsy;
2001 double tws = pow(((twdx * twdx) + (twdy * twdy)), 0.5);
2004 double twd = atan2(twdy, twdx) * 180. / PI;
2006 SendSentenceToAllInstruments(OCPN_DBP_STC_TWA, -twd, _T(
"\u00B0L"));
2008 SendSentenceToAllInstruments(OCPN_DBP_STC_TWA, twd, _T(
"\u00B0R"));
2011 double twdc = twd + g_dHDT;
2014 if (twdc < 0) twdc += 360.;
2015 if (twdc > 360.) twdc -= 360;
2019 SendSentenceToAllInstruments(OCPN_DBP_STC_TWD, twdc, _T(
"\u00B0"));
2021 SendSentenceToAllInstruments(OCPN_DBP_STC_TWS,
2022 toUsrSpeed_Plugin(tws, g_iDashWindSpeedUnit),
2023 getUsrSpeedUnit_Plugin(g_iDashWindSpeedUnit));
2024 SendSentenceToAllInstruments(OCPN_DBP_STC_TWS2,
2025 toUsrSpeed_Plugin(tws, g_iDashWindSpeedUnit),
2026 getUsrSpeedUnit_Plugin(g_iDashWindSpeedUnit));
2034void dashboard_pi::HandleN2K_127245(
ObservedEvt ev) {
2039 unsigned char source_id = v.at(7);
2041 sprintf(ss,
"%d", source_id);
2042 std::string ident = std::string(ss);
2044 source +=
":" + ident;
2049 if (source != prio127245)
return;
2052 prio127245 = source;
2055 double RudderPosition, AngleOrder;
2056 unsigned char Instance;
2057 tN2kRudderDirectionOrder RudderDirectionOrder;
2060 if (ParseN2kPGN127245(v, RudderPosition, Instance, RudderDirectionOrder,
2062 if (!N2kIsNA(RudderPosition)) {
2063 double m_rudangle = GEODESIC_RAD2DEG(RudderPosition);
2064 SendSentenceToAllInstruments(OCPN_DBP_STC_RSA, m_rudangle,
2066 mRSA_Watchdog = gps_watchdog_timeout_ticks;
2074void dashboard_pi::HandleN2K_127257(
ObservedEvt ev) {
2079 unsigned char source_id = v.at(7);
2081 sprintf(ss,
"%d", source_id);
2082 std::string ident = std::string(ss);
2084 source +=
":" + ident;
2086 if (mPriPitchRoll >= 1) {
2087 if (mPriPitchRoll == 1) {
2089 if (source != prio127257)
return;
2092 prio127257 = source;
2096 double Yaw, Pitch, Roll;
2099 if (ParseN2kPGN127257(v, SID, Yaw, Pitch, Roll)) {
2100 if (!N2kIsNA(Pitch)) {
2101 double m_pitch = GEODESIC_RAD2DEG(Pitch);
2102 wxString p_unit = _T(
"\u00B0\u2191") + _(
"Up");
2104 p_unit = _T(
"\u00B0\u2193") + _(
"Down");
2107 SendSentenceToAllInstruments(OCPN_DBP_STC_PITCH, m_pitch, p_unit);
2108 mPITCH_Watchdog = gps_watchdog_timeout_ticks;
2111 if (!N2kIsNA(Roll)) {
2112 double m_heel = GEODESIC_RAD2DEG(Roll);
2113 wxString h_unit = _T(
"\u00B0\u003E") + _(
"Stbd");
2115 h_unit = _T(
"\u00B0\u003C") + _(
"Port");
2118 SendSentenceToAllInstruments(OCPN_DBP_STC_HEEL, m_heel, h_unit);
2119 mHEEL_Watchdog = gps_watchdog_timeout_ticks;
2126void dashboard_pi::HandleN2K_128267(
ObservedEvt ev) {
2131 unsigned char source_id = v.at(7);
2133 sprintf(ss,
"%d", source_id);
2134 std::string ident = std::string(ss);
2136 source +=
":" + ident;
2138 if (mPriDepth >= 1) {
2139 if (mPriDepth == 1) {
2140 if (source != prio128267)
return;
2142 prio128267 = source;
2146 double DepthBelowTransducer, Offset, Range;
2149 if (ParseN2kPGN128267(v, SID, DepthBelowTransducer, Offset, Range)) {
2150 if (!N2kIsNA(DepthBelowTransducer)) {
2151 double depth = DepthBelowTransducer;
2153 if (!std::isnan(Offset) && !N2kIsNA(Offset))
2156 (depth += g_dDashDBTOffset);
2158 SendSentenceToAllInstruments(
2160 toUsrDistance_Plugin(depth / 1852.0, g_iDashDepthUnit),
2161 getUsrDistanceUnit_Plugin(g_iDashDepthUnit));
2163 mDPT_DBT_Watchdog = gps_watchdog_timeout_ticks;
2169void dashboard_pi::HandleN2K_128275(
ObservedEvt ev) {
2172 uint16_t DaysSince1970;
2173 double SecondsSinceMidnight;
2174 uint32_t Log, TripLog;
2177 if (ParseN2kPGN128275(v, DaysSince1970, SecondsSinceMidnight, Log, TripLog)) {
2178 if (!N2kIsNA(Log)) {
2179 double m_slog = METERS2NM((
double)Log);
2180 SendSentenceToAllInstruments(
2181 OCPN_DBP_STC_VLW2, toUsrDistance_Plugin(m_slog, g_iDashDistanceUnit),
2182 getUsrDistanceUnit_Plugin(g_iDashDistanceUnit));
2183 mLOG_Watchdog = no_nav_watchdog_timeout_ticks;
2186 if (!N2kIsNA(TripLog)) {
2187 double m_tlog = METERS2NM((
double)TripLog);
2188 SendSentenceToAllInstruments(
2189 OCPN_DBP_STC_VLW1, toUsrDistance_Plugin(m_tlog, g_iDashDistanceUnit),
2190 getUsrDistanceUnit_Plugin(g_iDashDistanceUnit));
2191 mTrLOG_Watchdog = no_nav_watchdog_timeout_ticks;
2195void dashboard_pi::HandleN2K_128259(
ObservedEvt ev) {
2200 unsigned char source_id = v.at(7);
2202 sprintf(ss,
"%d", source_id);
2203 std::string ident = std::string(ss);
2205 source +=
":" + ident;
2209 if (source != prio128259)
return;
2211 prio128259 = source;
2215 double WaterReferenced, GroundReferenced;
2216 tN2kSpeedWaterReferenceType SWRT;
2219 if (ParseN2kPGN128259(v, SID, WaterReferenced, GroundReferenced, SWRT)) {
2220 if (!N2kIsNA(WaterReferenced)) {
2221 double stw_knots = MS2KNOTS(WaterReferenced);
2222 SendSentenceToAllInstruments(
2223 OCPN_DBP_STC_STW, toUsrSpeed_Plugin(stw_knots, g_iDashSpeedUnit),
2224 getUsrSpeedUnit_Plugin(g_iDashSpeedUnit));
2226 mSTW_Watchdog = gps_watchdog_timeout_ticks;
2232void dashboard_pi::HandleN2K_128777(
ObservedEvt ev) {
2237 unsigned char WindlassIdentifier;
2238 double RodeCounterValue;
2239 double WindlassLineSpeed;
2240 tN2kWindlassMotionStates WindlassMotionStatus;
2241 tN2kRodeTypeStates RodeTypeStatus;
2242 tN2kAnchorDockingStates AnchorDockingStatus;
2243 tN2kWindlassOperatingEvents WindlassOperatingEvents;
2245 if (ParseN2kPGN128777(v, SID, WindlassIdentifier, RodeCounterValue,
2246 WindlassLineSpeed, WindlassMotionStatus, RodeTypeStatus,
2247 AnchorDockingStatus, WindlassOperatingEvents)) {
2248 if (!N2kIsNA(RodeCounterValue)) {
2249 SendSentenceToAllInstruments(OCPN_DBP_STC_WCC, RodeCounterValue,
"m");
2250 mWCC_Watchdog = no_nav_watchdog_timeout_ticks;
2255wxString talker_N2k = wxEmptyString;
2256void dashboard_pi::HandleN2K_129029(
ObservedEvt ev) {
2260 unsigned char source_id = v.at(7);
2262 sprintf(ss,
"%d", source_id);
2263 std::string ident = std::string(ss);
2265 source +=
":" + ident;
2267 if (source != prioN2kPGNsat)
return;
2270 uint16_t DaysSince1970;
2271 double SecondsSinceMidnight;
2272 double Latitude, Longitude, Altitude;
2273 tN2kGNSStype GNSStype;
2274 tN2kGNSSmethod GNSSmethod;
2275 unsigned char nSatellites;
2276 double HDOP, PDOP, GeoidalSeparation;
2277 unsigned char nReferenceStations;
2278 tN2kGNSStype ReferenceStationType;
2279 uint16_t ReferenceSationID;
2280 double AgeOfCorrection;
2283 if (ParseN2kPGN129029(v, SID, DaysSince1970, SecondsSinceMidnight, Latitude,
2284 Longitude, Altitude, GNSStype, GNSSmethod, nSatellites,
2285 HDOP, PDOP, GeoidalSeparation, nReferenceStations,
2286 ReferenceStationType, ReferenceSationID,
2296 talker_N2k =
"GPSGLONAS";
2302 talker_N2k =
"GPSGLONAS";
2305 talker_N2k =
"Chayka";
2311 talker_N2k = wxEmptyString;
2313 if (!N2kIsNA(Altitude)) {
2315 SendSentenceToAllInstruments(OCPN_DBP_STC_ALTI, Altitude, _T(
"m"));
2317 mALT_Watchdog = gps_watchdog_timeout_ticks;
2323void dashboard_pi::HandleN2K_129540(
ObservedEvt ev) {
2328 unsigned char source_id = v.at(7);
2330 sprintf(ss,
"%d", source_id);
2331 std::string ident = std::string(ss);
2333 source +=
":" + ident;
2335 if (source != prioN2kPGNsat)
return;
2338 tN2kRangeResidualMode Mode;
2339 uint8_t NumberOfSVs;
2342 if (ParseN2kPGN129540(v, SID, Mode, NumberOfSVs)) {
2343 if (!N2kIsNA(NumberOfSVs) && mPriSatStatus == 1) {
2346 SAT_INFO N2K_SatInfo[4];
2349 double dElevRad = 0;
2350 double dAzimRad = 0;
2353 for (
int iMesNum = 0; iMesNum < 3; iMesNum++) {
2354 for (idx = 0; idx < 4; idx++) {
2355 tSatelliteInfo SatelliteInfo;
2356 index = idx + 4 * iMesNum;
2357 if (index >= NumberOfSVs - 1)
break;
2358 if (ParseN2kPGN129540(v, index, SatelliteInfo)) {
2359 iPRN = (int)SatelliteInfo.PRN;
2360 dElevRad = SatelliteInfo.Elevation;
2361 dAzimRad = SatelliteInfo.Azimuth;
2362 iSNR = N2kIsNA(SatelliteInfo.SNR) ? 0 : (int)SatelliteInfo.SNR;
2364 N2K_SatInfo[idx].SatNumber = iPRN;
2365 N2K_SatInfo[idx].ElevationDegrees = GEODESIC_RAD2DEG(dElevRad);
2366 N2K_SatInfo[idx].AzimuthDegreesTrue = GEODESIC_RAD2DEG(dAzimRad);
2367 N2K_SatInfo[idx].SignalToNoiseRatio = iSNR;
2372 SendSatInfoToAllInstruments(NumberOfSVs, iMesNum + 1, talker_N2k,
2375 mSatStatus_Wdog = gps_watchdog_timeout_ticks;
2383void dashboard_pi::HandleN2K_130306(
ObservedEvt ev) {
2388 unsigned char source_id = v.at(7);
2390 sprintf(ss,
"%d", source_id);
2391 std::string ident = std::string(ss);
2393 source +=
":" + ident;
2397 if (source != prio130306)
return;
2399 prio130306 = source;
2403 double WindSpeed, WindAngle;
2404 tN2kWindReference WindReference;
2407 if (ParseN2kPGN130306(v, SID, WindSpeed, WindAngle, WindReference)) {
2408 if (!N2kIsNA(WindSpeed) && !N2kIsNA(WindAngle)) {
2409 double m_twaangle, m_twaspeed_kn;
2410 bool sendTrueWind =
false;
2412 switch (WindReference) {
2415 double m_twdT = GEODESIC_RAD2DEG(WindAngle);
2416 SendSentenceToAllInstruments(OCPN_DBP_STC_TWD, m_twdT,
2419 mWDN_Watchdog = no_nav_watchdog_timeout_ticks;
2424 double m_twdT = GEODESIC_RAD2DEG(WindAngle);
2426 if (!std::isnan(mVar)) {
2427 m_twdT = (m_twdT) + mVar;
2428 if (m_twdT > 360.) {
2430 }
else if (m_twdT < 0.) {
2434 SendSentenceToAllInstruments(OCPN_DBP_STC_TWD, m_twdT,
2437 mWDN_Watchdog = no_nav_watchdog_timeout_ticks;
2442 double m_awaangle, m_awaspeed_kn, calc_angle;
2444 m_awaangle = GEODESIC_RAD2DEG(WindAngle);
2445 calc_angle = m_awaangle;
2446 wxString m_awaunit = _T(
"\u00B0R");
2448 if (m_awaangle > 180.0) {
2449 m_awaangle = 360.0 - m_awaangle;
2450 m_awaunit = _T(
"\u00B0L");
2452 SendSentenceToAllInstruments(OCPN_DBP_STC_AWA, m_awaangle,
2455 m_awaspeed_kn = MS2KNOTS(WindSpeed);
2456 SendSentenceToAllInstruments(
2458 toUsrSpeed_Plugin(m_awaspeed_kn, g_iDashWindSpeedUnit),
2459 getUsrSpeedUnit_Plugin(g_iDashWindSpeedUnit));
2461 mMWVA_Watchdog = gps_watchdog_timeout_ticks;
2466 if (calc_angle > 180) calc_angle -= 360.0;
2467 CalculateAndUpdateTWDS(m_awaspeed_kn, calc_angle);
2470 mMWVT_Watchdog = gps_watchdog_timeout_ticks;
2471 mWDN_Watchdog = no_nav_watchdog_timeout_ticks;
2476 if (mPriTWA >= 1 && g_bDBtrueWindGround) {
2477 m_twaangle = GEODESIC_RAD2DEG(WindAngle);
2478 m_twaspeed_kn = MS2KNOTS(WindSpeed);
2479 sendTrueWind =
true;
2483 if (mPriTWA >= 1 && !g_bDBtrueWindGround) {
2484 m_twaangle = GEODESIC_RAD2DEG(WindAngle);
2485 m_twaspeed_kn = MS2KNOTS(WindSpeed);
2486 sendTrueWind =
true;
2499 wxString m_twaunit = _T(
"\u00B0R");
2501 if (m_twaangle > 180.0) {
2502 m_twaangle = 360.0 - m_twaangle;
2503 m_twaunit = _T(
"\u00B0L");
2505 SendSentenceToAllInstruments(OCPN_DBP_STC_TWA, m_twaangle, m_twaunit);
2507 SendSentenceToAllInstruments(
2509 toUsrSpeed_Plugin(m_twaspeed_kn, g_iDashWindSpeedUnit),
2510 getUsrSpeedUnit_Plugin(g_iDashWindSpeedUnit));
2511 SendSentenceToAllInstruments(
2513 toUsrSpeed_Plugin(m_twaspeed_kn, g_iDashWindSpeedUnit),
2514 getUsrSpeedUnit_Plugin(g_iDashWindSpeedUnit));
2517 mMWVT_Watchdog = gps_watchdog_timeout_ticks;
2524void dashboard_pi::HandleN2K_130310(
ObservedEvt ev) {
2528 double WaterTemperature, OutsideAmbientAirTemperature, AtmosphericPressure;
2531 if (ParseN2kPGN130310(v, SID, WaterTemperature, OutsideAmbientAirTemperature,
2532 AtmosphericPressure)) {
2534 if (!N2kIsNA(WaterTemperature)) {
2535 double m_wtemp KELVIN2C(WaterTemperature);
2536 SendSentenceToAllInstruments(OCPN_DBP_STC_TMP,
2537 toUsrTemp_Plugin(m_wtemp, g_iDashTempUnit),
2538 getUsrTempUnit_Plugin(g_iDashTempUnit));
2540 mWTP_Watchdog = no_nav_watchdog_timeout_ticks;
2544 if (mPriATMP >= 1) {
2545 if (!N2kIsNA(OutsideAmbientAirTemperature)) {
2546 double m_airtemp = KELVIN2C(OutsideAmbientAirTemperature);
2547 if (m_airtemp > -60 && m_airtemp < 100) {
2548 SendSentenceToAllInstruments(
2549 OCPN_DBP_STC_ATMP, toUsrTemp_Plugin(m_airtemp, g_iDashTempUnit),
2550 getUsrTempUnit_Plugin(g_iDashTempUnit));
2552 mATMP_Watchdog = no_nav_watchdog_timeout_ticks;
2557 if (!N2kIsNA(AtmosphericPressure) && mPriMDA >= 1) {
2558 double m_press = PA2HPA(AtmosphericPressure);
2559 SendSentenceToAllInstruments(OCPN_DBP_STC_MDA, m_press, _T(
"hPa"));
2561 mMDA_Watchdog = no_nav_watchdog_timeout_ticks;
2566void dashboard_pi::HandleN2K_130313(
ObservedEvt ev) {
2569 unsigned char SID, HumidityInstance;
2570 tN2kHumiditySource HumiditySource;
2571 double ActualHumidity, SetHumidity;
2573 if (ParseN2kPGN130313(v, SID, HumidityInstance, HumiditySource,
2574 ActualHumidity, SetHumidity)) {
2576 if (!N2kIsNA(ActualHumidity)) {
2577 SendSentenceToAllInstruments(OCPN_DBP_STC_HUM, ActualHumidity,
"%");
2579 mHUM_Watchdog = no_nav_watchdog_timeout_ticks;
2586void dashboard_pi::ParseSignalK(wxString &msg) {
2590 int errors = jsonReader.
Parse(msg, &root);
2598 if (root[
"self"].AsString().StartsWith(_T(
"vessels.")))
2599 m_self = (root[
"self"].
AsString());
2601 else if (root[
"self"].AsString().Length())
2603 _T(
"vessels.") + (root[
"self"].
AsString());
2607 auto context = root[
"context"].
AsString();
2608 if (context != m_self) {
2615 for (
int i = 0; i < updates.
Size(); ++i) {
2616 handleSKUpdate(updates[i]);
2621void dashboard_pi::handleSKUpdate(
wxJSONValue &update) {
2622 wxString sfixtime =
"";
2625 sfixtime = update[
"timestamp"].
AsString();
2627 if (update.
HasMember(
"values") && update[
"values"].IsArray()) {
2628 wxString talker = wxEmptyString;
2630 if (update[
"source"].HasMember(
"talker")) {
2631 if (update[
"source"][
"talker"].IsString()) {
2632 talker = update[
"source"][
"talker"].
AsString();
2636 for (
int j = 0; j < update[
"values"].
Size(); ++j) {
2638 updateSKItem(item, talker, sfixtime);
2643void dashboard_pi::updateSKItem(
wxJSONValue &item, wxString &talker,
2644 wxString &sfixtime) {
2646 const wxString &update_path = item[
"path"].
AsString();
2650 static wxString talkerID = wxEmptyString;
2652 static double skAWA;
2654 if (update_path == _T(
"navigation.position")) {
2655 if (mPriPosition >= 2) {
2656 if (value[
"latitude"].IsDouble() && value[
"longitude"].IsDouble()) {
2657 double lat = value[
"latitude"].
AsDouble();
2658 double lon = value[
"longitude"].AsDouble();
2659 SendSentenceToAllInstruments(OCPN_DBP_STC_LAT, lat, _T(
"SDMM"));
2660 SendSentenceToAllInstruments(OCPN_DBP_STC_LON, lon, _T(
"SDMM"));
2664 }
else if (update_path == _T(
"navigation.speedOverGround") &&
2665 2 == mPriPosition) {
2666 double sog_knot = GetJsonDouble(value);
2667 if (std::isnan(sog_knot))
return;
2669 SendSentenceToAllInstruments(
2671 toUsrSpeed_Plugin(mSOGFilter.filter(sog_knot), g_iDashSpeedUnit),
2672 getUsrSpeedUnit_Plugin(g_iDashSpeedUnit));
2673 }
else if (update_path == _T(
"navigation.courseOverGroundTrue") &&
2674 2 == mPriPosition) {
2675 double cog_rad = GetJsonDouble(value);
2676 if (std::isnan(cog_rad))
return;
2678 double cog_deg = GEODESIC_RAD2DEG(cog_rad);
2679 SendSentenceToAllInstruments(OCPN_DBP_STC_COG, mCOGFilter.filter(cog_deg),
2681 }
else if (update_path == _T(
"navigation.headingTrue")) {
2682 if (mPriHeadingT >= 2) {
2683 double hdt = GetJsonDouble(value);
2684 if (std::isnan(hdt))
return;
2686 hdt = GEODESIC_RAD2DEG(hdt);
2687 SendSentenceToAllInstruments(OCPN_DBP_STC_HDT, hdt, _T(
"\u00B0T"));
2689 mHDT_Watchdog = gps_watchdog_timeout_ticks;
2691 }
else if (update_path == _T(
"navigation.headingMagnetic")) {
2692 if (mPriHeadingM >= 2) {
2693 double hdm = GetJsonDouble(value);
2694 if (std::isnan(hdm))
return;
2696 hdm = GEODESIC_RAD2DEG(hdm);
2697 SendSentenceToAllInstruments(OCPN_DBP_STC_HDM, hdm, _T(
"\u00B0M"));
2699 mHDx_Watchdog = gps_watchdog_timeout_ticks;
2702 if (mPriHeadingT >= 6 && (!std::isnan(mVar))) {
2703 double heading = hdm + mVar;
2706 else if (heading >= 360.0)
2708 SendSentenceToAllInstruments(OCPN_DBP_STC_HDT, heading, _T(
"\u00B0"));
2710 mHDT_Watchdog = gps_watchdog_timeout_ticks;
2713 }
else if (update_path == _T(
"navigation.speedThroughWater")) {
2715 double stw_knots = GetJsonDouble(value);
2716 if (std::isnan(stw_knots))
return;
2718 stw_knots = MS2KNOTS(stw_knots);
2719 SendSentenceToAllInstruments(
2720 OCPN_DBP_STC_STW, toUsrSpeed_Plugin(stw_knots, g_iDashSpeedUnit),
2721 getUsrSpeedUnit_Plugin(g_iDashSpeedUnit));
2723 mSTW_Watchdog = gps_watchdog_timeout_ticks;
2725 }
else if (update_path == _T(
"navigation.magneticVariation")) {
2727 double dvar = GetJsonDouble(value);
2728 if (std::isnan(dvar))
return;
2730 dvar = GEODESIC_RAD2DEG(dvar);
2732 SendSentenceToAllInstruments(OCPN_DBP_STC_HMV, dvar, _T(
"\u00B0"));
2734 mVar_Watchdog = gps_watchdog_timeout_ticks;
2737 }
else if (update_path == _T(
"environment.wind.angleApparent")) {
2739 double m_awaangle = GetJsonDouble(value);
2740 if (std::isnan(m_awaangle))
return;
2742 m_awaangle = GEODESIC_RAD2DEG(m_awaangle);
2744 wxString m_awaunit = _T(
"\u00B0R");
2745 if (m_awaangle < 0) {
2746 m_awaunit = _T(
"\u00B0L");
2749 SendSentenceToAllInstruments(OCPN_DBP_STC_AWA, m_awaangle, m_awaunit);
2751 mMWVA_Watchdog = gps_watchdog_timeout_ticks;
2753 }
else if (update_path == _T(
"environment.wind.speedApparent")) {
2755 double m_awaspeed_kn = GetJsonDouble(value);
2756 if (std::isnan(m_awaspeed_kn))
return;
2758 m_awaspeed_kn = MS2KNOTS(m_awaspeed_kn);
2759 SendSentenceToAllInstruments(
2761 toUsrSpeed_Plugin(m_awaspeed_kn, g_iDashWindSpeedUnit),
2762 getUsrSpeedUnit_Plugin(g_iDashWindSpeedUnit));
2765 if (mPriTWA >= 6 && !std::isnan(skAWA)) {
2766 CalculateAndUpdateTWDS(m_awaspeed_kn, skAWA);
2768 mMWVT_Watchdog = gps_watchdog_timeout_ticks;
2769 mWDN_Watchdog = no_nav_watchdog_timeout_ticks;
2772 }
else if ((update_path == _T(
"environment.wind.angleTrueWater") &&
2773 !g_bDBtrueWindGround) ||
2774 (update_path == _T(
"environment.wind.angleTrueGround") &&
2775 g_bDBtrueWindGround)) {
2777 double m_twaangle = GetJsonDouble(value);
2778 if (std::isnan(m_twaangle))
return;
2780 m_twaangle = GEODESIC_RAD2DEG(m_twaangle);
2781 double m_twaangle_raw = m_twaangle;
2782 wxString m_twaunit = _T(
"\u00B0R");
2783 if (m_twaangle < 0) {
2784 m_twaunit = _T(
"\u00B0L");
2787 SendSentenceToAllInstruments(OCPN_DBP_STC_TWA, m_twaangle, m_twaunit);
2789 mMWVT_Watchdog = gps_watchdog_timeout_ticks;
2796 if (g_dHDT < 361. && g_dHDT >= 0.0) {
2797 double g_dCalWdir = (m_twaangle_raw) + g_dHDT;
2798 if (g_dCalWdir > 360.) {
2800 }
else if (g_dCalWdir < 0.) {
2803 SendSentenceToAllInstruments(OCPN_DBP_STC_TWD, g_dCalWdir,
2806 mWDN_Watchdog = no_nav_watchdog_timeout_ticks;
2810 }
else if ((update_path == _T(
"environment.wind.speedTrue") &&
2811 !g_bDBtrueWindGround) ||
2812 (update_path == _T(
"environment.wind.speedOverGround") &&
2813 g_bDBtrueWindGround)) {
2815 double m_twaspeed_kn = GetJsonDouble(value);
2816 if (std::isnan(m_twaspeed_kn))
return;
2818 m_twaspeed_kn = MS2KNOTS(m_twaspeed_kn);
2819 SendSentenceToAllInstruments(
2821 toUsrSpeed_Plugin(m_twaspeed_kn, g_iDashWindSpeedUnit),
2822 getUsrSpeedUnit_Plugin(g_iDashWindSpeedUnit));
2823 SendSentenceToAllInstruments(
2825 toUsrSpeed_Plugin(m_twaspeed_kn, g_iDashWindSpeedUnit),
2826 getUsrSpeedUnit_Plugin(g_iDashWindSpeedUnit));
2828 }
else if (update_path == _T(
"environment.depth.belowSurface")) {
2829 if (mPriDepth >= 3) {
2830 double depth = GetJsonDouble(value);
2831 if (std::isnan(depth))
return;
2834 depth += g_dDashDBTOffset;
2836 SendSentenceToAllInstruments(
2837 OCPN_DBP_STC_DPT, toUsrDistance_Plugin(depth, g_iDashDepthUnit),
2838 getUsrDistanceUnit_Plugin(g_iDashDepthUnit));
2839 mDPT_DBT_Watchdog = gps_watchdog_timeout_ticks;
2841 }
else if (update_path == _T(
"environment.depth.belowTransducer")) {
2842 if (mPriDepth >= 3) {
2843 double depth = GetJsonDouble(value);
2844 if (std::isnan(depth))
return;
2847 depth += g_dDashDBTOffset;
2849 SendSentenceToAllInstruments(
2850 OCPN_DBP_STC_DPT, toUsrDistance_Plugin(depth, g_iDashDepthUnit),
2851 getUsrDistanceUnit_Plugin(g_iDashDepthUnit));
2852 mDPT_DBT_Watchdog = gps_watchdog_timeout_ticks;
2854 }
else if (update_path == _T(
"environment.water.temperature")) {
2856 double m_wtemp = GetJsonDouble(value);
2857 if (std::isnan(m_wtemp))
return;
2859 m_wtemp = KELVIN2C(m_wtemp);
2860 if (m_wtemp > -60 && m_wtemp < 200 && !std::isnan(m_wtemp)) {
2861 SendSentenceToAllInstruments(
2862 OCPN_DBP_STC_TMP, toUsrTemp_Plugin(m_wtemp, g_iDashTempUnit),
2863 getUsrTempUnit_Plugin(g_iDashTempUnit));
2865 mWTP_Watchdog = no_nav_watchdog_timeout_ticks;
2868 }
else if (update_path ==
2869 _T(
"navigation.courseRhumbline.nextPoint.velocityMadeGood")) {
2870 double m_vmg_kn = GetJsonDouble(value);
2871 if (std::isnan(m_vmg_kn))
return;
2873 m_vmg_kn = MS2KNOTS(m_vmg_kn);
2874 SendSentenceToAllInstruments(
2875 OCPN_DBP_STC_VMG, toUsrSpeed_Plugin(m_vmg_kn, g_iDashSpeedUnit),
2876 getUsrSpeedUnit_Plugin(g_iDashSpeedUnit));
2877 mVMG_Watchdog = gps_watchdog_timeout_ticks;
2880 else if (update_path == _T(
"performance.velocityMadeGood")) {
2881 double m_vmgw_kn = GetJsonDouble(value);
2882 if (std::isnan(m_vmgw_kn))
return;
2884 m_vmgw_kn = MS2KNOTS(m_vmgw_kn);
2885 SendSentenceToAllInstruments(
2886 OCPN_DBP_STC_VMGW, toUsrSpeed_Plugin(m_vmgw_kn, g_iDashSpeedUnit),
2887 getUsrSpeedUnit_Plugin(g_iDashSpeedUnit));
2888 mVMGW_Watchdog = gps_watchdog_timeout_ticks;
2891 else if (update_path == _T(
"steering.rudderAngle")) {
2893 double m_rudangle = GetJsonDouble(value);
2894 if (std::isnan(m_rudangle))
return;
2896 m_rudangle = GEODESIC_RAD2DEG(m_rudangle);
2897 SendSentenceToAllInstruments(OCPN_DBP_STC_RSA, m_rudangle,
2899 mRSA_Watchdog = gps_watchdog_timeout_ticks;
2902 }
else if (update_path ==
2903 _T(
"navigation.gnss.satellites")) {
2904 if (mPriSatUsed >= 2) {
2905 int usedSats = (value).AsInt();
2906 if (usedSats < 1)
return;
2907 SendSentenceToAllInstruments(OCPN_DBP_STC_SAT, usedSats, _T (
""));
2909 mSatsUsed_Wdog = gps_watchdog_timeout_ticks;
2911 }
else if (update_path == _T(
"navigation.gnss.type")) {
2912 if (value.IsString() && value.AsString() != wxEmptyString) {
2913 talkerID = (value.AsString());
2914 talkerID.MakeUpper();
2915 m_PriN2kTalker = gps_watchdog_timeout_ticks;
2916 if ((talkerID.Contains(_T(
"GPS"))) &&
2917 (talkerID.Contains(_T(
"GLONASS"))))
2918 talkerID = _T(
"GPSGLONAS");
2919 else if (talkerID.Contains(_T(
"GPS")))
2920 talkerID = _T(
"GP");
2921 else if (talkerID.Contains(_T(
"GLONASS")))
2922 talkerID = _T(
"GL");
2923 else if (talkerID.Contains(_T(
"GALILEO")))
2924 talkerID = _T(
"GA");
2925 else if (talkerID.Contains(_T(
"BEIDOU")))
2926 talkerID = _T(
"GI");
2928 }
else if (update_path ==
2929 _T(
"navigation.gnss.satellitesInView")) {
2931 if (mPriSatUsed >= 4) {
2932 if (value.HasMember(
"count") && value[
"count"].IsInt()) {
2933 double m_SK_SatsInView = (value[
"count"].AsInt());
2934 SendSentenceToAllInstruments(OCPN_DBP_STC_SAT, m_SK_SatsInView,
2937 mSatsUsed_Wdog = gps_watchdog_timeout_ticks;
2940 if (mPriSatStatus == 2) {
2941 if (value.HasMember(
"satellites") && value[
"satellites"].IsArray()) {
2944 if (value.HasMember(
"count") && value[
"count"].IsInt()) {
2945 iNumSats = (value[
"count"].AsInt());
2947 iNumSats = value[_T (
"satellites")].Size();
2949 SAT_INFO SK_SatInfo[4];
2950 for (
int idx = 0; idx < 4; idx++) {
2951 SK_SatInfo[idx].SatNumber = 0;
2952 SK_SatInfo[idx].ElevationDegrees = 0;
2953 SK_SatInfo[idx].AzimuthDegreesTrue = 0;
2954 SK_SatInfo[idx].SignalToNoiseRatio = 0;
2961 double dElevRad = 0;
2962 double dAzimRad = 0;
2965 for (
int iMesNum = 0; iMesNum < 3; iMesNum++) {
2966 for (idx = 0; idx < 4; idx++) {
2967 arr = idx + 4 * iMesNum;
2968 if (value[
"satellites"][arr][
"id"].IsInt())
2969 iID = value[
"satellites"][arr][
"id"].AsInt();
2970 if (value[
"satellites"][arr][
"elevation"].IsDouble())
2971 dElevRad = value[
"satellites"][arr][
"elevation"].AsDouble();
2972 if (value[
"satellites"][arr][
"azimuth"].IsDouble())
2973 dAzimRad = value[
"satellites"][arr][
"azimuth"].AsDouble();
2974 if (value[
"satellites"][arr][
"SNR"].IsInt())
2975 iSNR = value[
"satellites"][arr][
"SNR"].AsInt();
2978 SK_SatInfo[idx].SatNumber = iID;
2979 SK_SatInfo[idx].ElevationDegrees = GEODESIC_RAD2DEG(dElevRad);
2980 SK_SatInfo[idx].AzimuthDegreesTrue = GEODESIC_RAD2DEG(dAzimRad);
2981 SK_SatInfo[idx].SignalToNoiseRatio = iSNR;
2984 if (m_PriN2kTalker <= 0 && talker != wxEmptyString &&
2985 (talker.StartsWith(_T(
"G")) ||
2986 talker.StartsWith(_T(
"BD")))) {
2989 SendSatInfoToAllInstruments(iNumSats, iMesNum + 1, talkerID,
2992 mSatStatus_Wdog = gps_watchdog_timeout_ticks;
3000 }
else if (update_path == _T(
"navigation.gnss.antennaAltitude")) {
3002 double m_alt = GetJsonDouble(value);
3003 if (std::isnan(m_alt))
return;
3005 SendSentenceToAllInstruments(OCPN_DBP_STC_ALTI, m_alt, _T(
"m"));
3007 mALT_Watchdog = gps_watchdog_timeout_ticks;
3010 }
else if (update_path == _T(
"navigation.datetime")) {
3011 if (mPriDateTime >= 1) {
3013 wxString s_dt = (value.AsString());
3014 s_dt.Replace(
'-', wxEmptyString);
3015 s_dt.Replace(
':', wxEmptyString);
3016 wxString utc_dt = s_dt.BeforeFirst(
'T');
3017 utc_dt.Append(s_dt.AfterFirst(
'T').Left(6));
3018 mUTCDateTime.ParseFormat(utc_dt.c_str(), _T(
"%Y%m%d%H%M%S"));
3019 mUTC_Watchdog = gps_watchdog_timeout_ticks;
3021 }
else if (update_path == _T(
"environment.outside.temperature")) {
3022 if (mPriATMP >= 2) {
3023 double m_airtemp = GetJsonDouble(value);
3024 if (std::isnan(m_airtemp))
return;
3026 m_airtemp = KELVIN2C(m_airtemp);
3027 if (m_airtemp > -60 && m_airtemp < 100) {
3028 SendSentenceToAllInstruments(
3029 OCPN_DBP_STC_ATMP, toUsrTemp_Plugin(m_airtemp, g_iDashTempUnit),
3030 getUsrTempUnit_Plugin(g_iDashTempUnit));
3032 mATMP_Watchdog = no_nav_watchdog_timeout_ticks;
3035 }
else if (update_path == _T(
"environment.outside.humidity") ||
3036 update_path == _T(
"environment.outside.relativeHumidity")) {
3038 double m_hum = GetJsonDouble(value) * 100;
3039 if (std::isnan(m_hum))
return;
3040 SendSentenceToAllInstruments(OCPN_DBP_STC_HUM, m_hum,
"%");
3042 mHUM_Watchdog = no_nav_watchdog_timeout_ticks;
3044 }
else if (update_path ==
3045 _T(
"environment.wind.directionTrue")) {
3047 double m_twdT = GetJsonDouble(value);
3048 if (std::isnan(m_twdT))
return;
3050 m_twdT = GEODESIC_RAD2DEG(m_twdT);
3051 SendSentenceToAllInstruments(OCPN_DBP_STC_TWD, m_twdT, _T(
"\u00B0"));
3053 mWDN_Watchdog = no_nav_watchdog_timeout_ticks;
3055 }
else if (update_path == _T(
"environment.wind.directionMagnetic")) {
3058 double m_twdM = GetJsonDouble(value);
3059 if (std::isnan(m_twdM))
return;
3060 m_twdM = GEODESIC_RAD2DEG(m_twdM);
3062 if (!std::isnan(mVar)) {
3063 m_twdM = (m_twdM) + mVar;
3064 if (m_twdM > 360.) {
3066 }
else if (m_twdM < 0.) {
3070 SendSentenceToAllInstruments(OCPN_DBP_STC_TWD, m_twdM, _T(
"\u00B0"));
3072 mWDN_Watchdog = no_nav_watchdog_timeout_ticks;
3074 }
else if (update_path == _T(
"navigation.trip.log")) {
3075 double m_tlog = GetJsonDouble(value);
3076 if (std::isnan(m_tlog))
return;
3078 m_tlog = METERS2NM(m_tlog);
3079 SendSentenceToAllInstruments(
3080 OCPN_DBP_STC_VLW1, toUsrDistance_Plugin(m_tlog, g_iDashDistanceUnit),
3081 getUsrDistanceUnit_Plugin(g_iDashDistanceUnit));
3082 mTrLOG_Watchdog = no_nav_watchdog_timeout_ticks;
3083 }
else if (update_path == _T(
"navigation.log")) {
3084 double m_slog = GetJsonDouble(value);
3085 if (std::isnan(m_slog))
return;
3087 m_slog = METERS2NM(m_slog);
3088 SendSentenceToAllInstruments(
3089 OCPN_DBP_STC_VLW2, toUsrDistance_Plugin(m_slog, g_iDashDistanceUnit),
3090 getUsrDistanceUnit_Plugin(g_iDashDistanceUnit));
3091 mLOG_Watchdog = no_nav_watchdog_timeout_ticks;
3092 }
else if (update_path == _T(
"environment.outside.pressure") &&
3094 double m_press = GetJsonDouble(value);
3095 if (std::isnan(m_press))
return;
3097 m_press = PA2HPA(m_press);
3098 SendSentenceToAllInstruments(OCPN_DBP_STC_MDA, m_press, _T(
"hPa"));
3100 mMDA_Watchdog = no_nav_watchdog_timeout_ticks;
3101 }
else if (update_path == _T(
"navigation.attitude")) {
3102 if (mPriPitchRoll >= 2) {
3103 if (value[
"roll"].AsString() !=
"0") {
3104 double m_heel = GEODESIC_RAD2DEG(value[
"roll"].AsDouble());
3105 wxString h_unit = _T(
"\u00B0\u003E") + _(
"Stbd");
3107 h_unit = _T(
"\u00B0\u003C") + _(
"Port");
3110 SendSentenceToAllInstruments(OCPN_DBP_STC_HEEL, m_heel, h_unit);
3111 mHEEL_Watchdog = gps_watchdog_timeout_ticks;
3114 if (value[
"pitch"].AsString() !=
"0") {
3115 double m_pitch = GEODESIC_RAD2DEG(value[
"pitch"].AsDouble());
3116 wxString p_unit = _T(
"\u00B0\u2191") + _(
"Up");
3118 p_unit = _T(
"\u00B0\u2193") + _(
"Down");
3121 SendSentenceToAllInstruments(OCPN_DBP_STC_PITCH, m_pitch, p_unit);
3122 mPITCH_Watchdog = gps_watchdog_timeout_ticks;
3132 if (mPriPosition >= 1) {
3134 SendSentenceToAllInstruments(OCPN_DBP_STC_LAT, pfix.Lat, _T(
"SDMM"));
3135 SendSentenceToAllInstruments(OCPN_DBP_STC_LON, pfix.Lon, _T(
"SDMM"));
3137 if (mPriCOGSOG >= 1) {
3138 double dMagneticCOG;
3140 SendSentenceToAllInstruments(
3142 toUsrSpeed_Plugin(mSOGFilter.filter(pfix.Sog), g_iDashSpeedUnit),
3143 getUsrSpeedUnit_Plugin(g_iDashSpeedUnit));
3144 SendSentenceToAllInstruments(OCPN_DBP_STC_COG, mCOGFilter.filter(pfix.Cog),
3146 dMagneticCOG = mCOGFilter.get() - pfix.Var;
3147 if (dMagneticCOG < 0.0) dMagneticCOG = 360.0 + dMagneticCOG;
3148 if (dMagneticCOG > 360.0) dMagneticCOG = dMagneticCOG - 360.0;
3149 SendSentenceToAllInstruments(OCPN_DBP_STC_MCOG, dMagneticCOG,
3153 if (!std::isnan(pfix.Var)) {
3156 mVar_Watchdog = gps_watchdog_timeout_ticks;
3158 SendSentenceToAllInstruments(OCPN_DBP_STC_HMV, pfix.Var, _T(
"\u00B0"));
3161 if (mPriDateTime >= 6) {
3165 if (pfix.FixTime > 0)
3166 mUTCDateTime.Set(pfix.FixTime);
3168 mUTCDateTime = wxInvalidDateTime;
3169 if (mUTCDateTime.IsValid()) {
3171 mUTCDateTime = mUTCDateTime.ToUTC();
3172 mUTC_Watchdog = gps_watchdog_timeout_ticks;
3175 if (mPriSatUsed >= 1) {
3176 mSatsInUse = pfix.nSats;
3177 if (mSatsInUse > 0) {
3178 SendSentenceToAllInstruments(OCPN_DBP_STC_SAT, mSatsInUse, _T(
""));
3180 mSatsUsed_Wdog = gps_watchdog_timeout_ticks;
3183 if (mPriHeadingT >= 1) {
3184 double hdt = pfix.Hdt;
3185 if (std::isnan(hdt))
return;
3186 SendSentenceToAllInstruments(OCPN_DBP_STC_HDT, hdt, _T(
"\u00B0T"));
3188 mHDT_Watchdog = gps_watchdog_timeout_ticks;
3190 if (mPriHeadingM >= 1) {
3191 double hdm = pfix.Hdm;
3192 if (std::isnan(hdm) && !std::isnan(pfix.Hdt) && !std::isnan(pfix.Var)) {
3193 hdm = pfix.Hdt - pfix.Var;
3196 else if (hdm >= 360.0)
3199 if (std::isnan(hdm))
return;
3200 SendSentenceToAllInstruments(OCPN_DBP_STC_HDM, hdm, _T(
"\u00B0M"));
3202 mHDx_Watchdog = gps_watchdog_timeout_ticks;
3206void dashboard_pi::SetCursorLatLon(
double lat,
double lon) {
3207 SendSentenceToAllInstruments(OCPN_DBP_STC_PLA, lat, _T(
"SDMM"));
3208 SendSentenceToAllInstruments(OCPN_DBP_STC_PLO, lon, _T(
"SDMM"));
3211void dashboard_pi::SetPluginMessage(wxString &message_id,
3212 wxString &message_body) {
3213 if (message_id == _T(
"WMM_VARIATION_BOAT")) {
3221 int numErrors = reader.
Parse(message_body, &root);
3222 if (numErrors > 0) {
3228 wxString decl = root[_T(
"Decl")].
AsString();
3230 decl.ToDouble(&decl_val);
3235 mVar_Watchdog = gps_watchdog_timeout_ticks;
3236 SendSentenceToAllInstruments(OCPN_DBP_STC_HMV, mVar, _T(
"\u00B0"));
3238 }
else if (message_id == _T(
"OCPN_CORE_SIGNALK")) {
3239 ParseSignalK(message_body);
3243int dashboard_pi::GetToolbarToolCount(
void) {
return 1; }
3245void dashboard_pi::ShowPreferencesDialog(wxWindow *parent) {
3247 parent, wxID_ANY, m_ArrayOfDashboardWindow);
3249 dialog->RecalculateSize();
3251#ifdef __OCPN__ANDROID__
3252 dialog->GetHandle()->setStyleSheet(qtStyleSheet);
3255#ifdef __OCPN__ANDROID__
3256 wxWindow *ccwin = GetOCPNCanvasWindow();
3259 int xmax = ccwin->GetSize().GetWidth();
3260 int ymax = ccwin->GetParent()
3263 dialog->SetSize(xmax, ymax);
3270 if (dialog->ShowModal() == wxID_OK) {
3271 double scaler = 1.0;
3272 if (OCPN_GetWinDIPScaleFactor() < 1.0)
3273 scaler = 1.0 + OCPN_GetWinDIPScaleFactor() / 4;
3274 scaler = wxMax(1.0, scaler);
3276 g_USFontTitle = *(dialog->m_pFontPickerTitle->GetFontData());
3277 g_FontTitle = *g_pUSFontTitle;
3278 g_FontTitle.SetChosenFont(g_pUSFontTitle->GetChosenFont().Scaled(scaler));
3279 g_FontTitle.SetColour(g_pUSFontTitle->GetColour());
3280 g_USFontTitle = *g_pUSFontTitle;
3282 g_USFontData = *(dialog->m_pFontPickerData->GetFontData());
3283 g_FontData = *g_pUSFontData;
3284 g_FontData.SetChosenFont(g_pUSFontData->GetChosenFont().Scaled(scaler));
3285 g_FontData.SetColour(g_pUSFontData->GetColour());
3286 g_USFontData = *g_pUSFontData;
3288 g_USFontLabel = *(dialog->m_pFontPickerLabel->GetFontData());
3289 g_FontLabel = *g_pUSFontLabel;
3290 g_FontLabel.SetChosenFont(g_pUSFontLabel->GetChosenFont().Scaled(scaler));
3291 g_FontLabel.SetColour(g_pUSFontLabel->GetColour());
3292 g_USFontLabel = *g_pUSFontLabel;
3294 g_USFontSmall = *(dialog->m_pFontPickerSmall->GetFontData());
3295 g_FontSmall = *g_pUSFontSmall;
3296 g_FontSmall.SetChosenFont(g_pUSFontSmall->GetChosenFont().Scaled(scaler));
3297 g_FontSmall.SetColour(g_pUSFontSmall->GetColour());
3298 g_USFontSmall = *g_pUSFontSmall;
3302 g_dashPrefWidth = dialog->GetSize().x;
3303 g_dashPrefHeight = dialog->GetSize().y;
3305 dialog->SaveDashboardConfig();
3306 m_ArrayOfDashboardWindow.Clear();
3307 m_ArrayOfDashboardWindow = dialog->m_Config;
3311 SetToolbarItemState(m_toolbar_item_id, GetDashboardWindowShownCount() != 0);
3316void dashboard_pi::SetColorScheme(PI_ColorScheme cs) {
3317 aktuellColorScheme = cs;
3318 for (
size_t i = 0; i < m_ArrayOfDashboardWindow.GetCount(); i++) {
3320 m_ArrayOfDashboardWindow.Item(i)->m_pDashboardWindow;
3321 if (dashboard_window) dashboard_window->SetColorScheme(cs);
3325int dashboard_pi::GetDashboardWindowShownCount() {
3328 for (
size_t i = 0; i < m_ArrayOfDashboardWindow.GetCount(); i++) {
3330 m_ArrayOfDashboardWindow.Item(i)->m_pDashboardWindow;
3331 if (dashboard_window) {
3332 wxAuiPaneInfo &pane = m_pauimgr->GetPane(dashboard_window);
3333 if (pane.IsOk() && pane.IsShown()) cnt++;
3339void dashboard_pi::OnPaneClose(wxAuiManagerEvent &event) {
3343 for (
size_t i = 0; i < m_ArrayOfDashboardWindow.GetCount(); i++) {
3348 if (dashboard_window != d_w) {
3349 wxAuiPaneInfo &pane = m_pauimgr->GetPane(d_w);
3350 if (pane.IsOk() && pane.IsShown()) cnt++;
3352 cont->m_bIsVisible =
false;
3356 SetToolbarItemState(m_toolbar_item_id, cnt != 0);
3361void dashboard_pi::OnToolbarToolCallback(
int id) {
3362 int cnt = GetDashboardWindowShownCount();
3364 bool b_anyviz =
false;
3365 for (
size_t i = 0; i < m_ArrayOfDashboardWindow.GetCount(); i++) {
3367 if (cont->m_bIsVisible) {
3373 for (
size_t i = 0; i < m_ArrayOfDashboardWindow.GetCount(); i++) {
3376 if (dashboard_window) {
3377 wxAuiPaneInfo &pane = m_pauimgr->GetPane(dashboard_window);
3379 bool b_reset_pos =
false;
3386 RECT frame_title_rect;
3387 frame_title_rect.left = pane.floating_pos.x;
3388 frame_title_rect.top = pane.floating_pos.y;
3389 frame_title_rect.right = pane.floating_pos.x + pane.floating_size.x;
3390 frame_title_rect.bottom = pane.floating_pos.y + 30;
3392 if (NULL == MonitorFromRect(&frame_title_rect, MONITOR_DEFAULTTONULL))
3398 wxRect window_title_rect;
3399 window_title_rect.x = pane.floating_pos.x;
3400 window_title_rect.y = pane.floating_pos.y;
3401 window_title_rect.width = pane.floating_size.x;
3402 window_title_rect.height = 30;
3404 wxRect ClientRect = wxGetClientDisplayRect();
3407 if (!ClientRect.Intersects(window_title_rect)) b_reset_pos =
true;
3411 if (b_reset_pos) pane.FloatingPosition(50, 50);
3415 pane.Show(cont->m_bIsVisible);
3417 cont->m_bIsVisible = cont->m_bPersVisible;
3418 pane.Show(cont->m_bIsVisible);
3425 if (pane.IsShown() && pane.IsDocked()) {
3426 pane.BestSize(cont->m_best_size);
3427 m_pauimgr->Update();
3438 if ((pane.dock_direction == wxAUI_DOCK_BOTTOM) && pane.IsDocked())
3444 SetToolbarItemState(m_toolbar_item_id,
3445 GetDashboardWindowShownCount() != 0 );
3446 m_pauimgr->Update();
3449void dashboard_pi::UpdateAuiStatus(
void) {
3456 for (
size_t i = 0; i < m_ArrayOfDashboardWindow.GetCount(); i++) {
3458 wxAuiPaneInfo &pane = m_pauimgr->GetPane(cont->m_pDashboardWindow);
3460 cont->m_bIsVisible = (pane.IsOk() && pane.IsShown());
3464 if (pane.IsDocked()) {
3465 if ((cont->m_persist_size.x > 50) && (cont->m_persist_size.y > 50))
3466 cont->m_pDashboardWindow->SetSize(cont->m_persist_size);
3470 if (pane.IsShown()) {
3472 m_pauimgr->Update();
3474 m_pauimgr->Update();
3478 m_pauimgr->Update();
3483 SetToolbarItemState(m_toolbar_item_id, GetDashboardWindowShownCount() != 0);
3486bool dashboard_pi::LoadConfig(
void) {
3487 wxFileConfig *pConf = (wxFileConfig *)m_pconfig;
3490 pConf->SetPath(_T(
"/PlugIns/Dashboard"));
3493 pConf->Read(_T(
"Version"), &version, wxEmptyString);
3502#ifdef __OCPN__ANDROID__
3503 TitleFont = _T(
"Roboto,16,-1,5,50,0,0,0,0,0");
3504 DataFont = _T(
"Roboto,16,-1,5,50,0,0,0,0,0");
3505 LabelFont = _T(
"Roboto,16,-1,5,50,0,0,0,0,0");
3506 SmallFont = _T(
"Roboto,14,-1,5,50,0,0,0,0,0");
3508 TitleFont = g_pFontTitle->GetChosenFont().GetNativeFontInfoDesc();
3509 DataFont = g_pFontData->GetChosenFont().GetNativeFontInfoDesc();
3510 LabelFont = g_pFontLabel->GetChosenFont().GetNativeFontInfoDesc();
3511 SmallFont = g_pFontSmall->GetChosenFont().GetNativeFontInfoDesc();
3514 double scaler = 1.0;
3516 wxFont *pDF = &DummyFont;
3518 if (OCPN_GetWinDIPScaleFactor() < 1.0)
3519 scaler = 1.0 + OCPN_GetWinDIPScaleFactor() / 4;
3520 scaler = wxMax(1.0, scaler);
3522 g_pFontTitle = &g_FontTitle;
3523 pConf->Read(_T(
"FontTitle"), &config, TitleFont);
3524 LoadFont(&pDF, config);
3525 pConf->Read(_T(
"ColorTitle"), &config,
"#000000");
3526 wxColour DummyColor(config);
3527 g_pUSFontTitle->SetChosenFont(*pDF);
3528 g_pUSFontTitle->SetColour(DummyColor);
3529 g_FontTitle = *g_pUSFontTitle;
3530 g_FontTitle.SetChosenFont(g_pUSFontTitle->GetChosenFont().Scaled(scaler));
3531 g_USFontTitle = *g_pUSFontTitle;
3533 g_pFontData = &g_FontData;
3534 pConf->Read(_T(
"FontData"), &config, DataFont);
3535 LoadFont(&pDF, config);
3536 pConf->Read(_T(
"ColorData"), &config,
"#000000");
3537 DummyColor.Set(config);
3538 g_pUSFontData->SetChosenFont(*pDF);
3539 g_pUSFontData->SetColour(DummyColor);
3540 g_FontData = *g_pUSFontData;
3541 g_FontData.SetChosenFont(g_pUSFontData->GetChosenFont().Scaled(scaler));
3542 g_USFontData = *g_pUSFontData;
3544 pConf->Read(_T(
"ForceBackgroundColor"), &g_ForceBackgroundColor, 0);
3545 pConf->Read(_T(
"BackgroundColor"), &config,
"DASHL");
3546 g_BackgroundColor.Set(config);
3549 pConf->Read(_T(
"TitleAlignment"), &alignment, (
int)wxALIGN_LEFT);
3550 g_TitleAlignment = (wxAlignment)alignment;
3551 if (g_TitleAlignment == wxALIGN_INVALID) g_TitleAlignment = wxALIGN_LEFT;
3552 pConf->Read(_T(
"TitleMargin"), &g_iTitleMargin, 5);
3553 pConf->Read(_T(
"DataShowUnit"), &g_bShowUnit,
true);
3554 pConf->Read(_T(
"DataAlignment"), &alignment, (int)wxALIGN_LEFT);
3555 g_DataAlignment = (wxAlignment)alignment;
3556 if (g_DataAlignment == wxALIGN_INVALID) g_DataAlignment = wxALIGN_LEFT;
3557 pConf->Read(_T(
"DataMargin"), &g_iDataMargin, 10);
3558 pConf->Read(_T(
"InstrumentSpacing"), &g_iInstrumentSpacing, 0);
3559 pConf->Read(_T(
"TitleVerticalOffset"), &g_TitleVerticalOffset, 0.0);
3561 g_pFontLabel = &g_FontLabel;
3562 pConf->Read(_T(
"FontLabel"), &config, LabelFont);
3563 LoadFont(&pDF, config);
3564 pConf->Read(_T(
"ColorLabel"), &config,
"#000000");
3565 DummyColor.Set(config);
3566 g_pUSFontLabel->SetChosenFont(*pDF);
3567 g_pUSFontLabel->SetColour(DummyColor);
3568 g_FontLabel = *g_pUSFontLabel;
3569 g_FontLabel.SetChosenFont(g_pUSFontLabel->GetChosenFont().Scaled(scaler));
3570 g_USFontLabel = *g_pUSFontLabel;
3572 g_pFontSmall = &g_FontSmall;
3573 pConf->Read(_T(
"FontSmall"), &config, SmallFont);
3574 LoadFont(&pDF, config);
3575 pConf->Read(_T(
"ColorSmall"), &config,
"#000000");
3576 DummyColor.Set(config);
3577 g_pUSFontSmall->SetChosenFont(*pDF);
3578 g_pUSFontSmall->SetColour(DummyColor);
3579 g_FontSmall = *g_pUSFontSmall;
3580 g_FontSmall.SetChosenFont(g_pUSFontSmall->GetChosenFont().Scaled(scaler));
3581 g_USFontSmall = *g_pUSFontSmall;
3583 pConf->Read(_T(
"SpeedometerMax"), &g_iDashSpeedMax, 12);
3584 pConf->Read(_T(
"COGDamp"), &g_iDashCOGDamp, 0);
3585 pConf->Read(_T(
"SpeedUnit"), &g_iDashSpeedUnit, 0);
3586 pConf->Read(_T(
"SOGDamp"), &g_iDashSOGDamp, 0);
3587 pConf->Read(_T(
"DepthUnit"), &g_iDashDepthUnit, 3);
3588 g_iDashDepthUnit = wxMax(g_iDashDepthUnit, 3);
3590 pConf->Read(_T(
"DepthOffset"), &g_dDashDBTOffset, 0);
3592 pConf->Read(_T(
"DistanceUnit"), &g_iDashDistanceUnit, 0);
3593 pConf->Read(_T(
"WindSpeedUnit"), &g_iDashWindSpeedUnit, 0);
3594 pConf->Read(_T(
"UseSignKtruewind"), &g_bDBtrueWindGround, 0);
3595 pConf->Read(_T(
"TemperatureUnit"), &g_iDashTempUnit, 0);
3597 pConf->Read(_T(
"UTCOffset"), &g_iUTCOffset, 0);
3599 pConf->Read(_T(
"PrefWidth"), &g_dashPrefWidth, 0);
3600 pConf->Read(_T(
"PrefHeight"), &g_dashPrefHeight, 0);
3603 pConf->Read(_T(
"DashboardCount"), &d_cnt, -1);
3605 m_ArrayOfDashboardWindow.Clear();
3606 if (version.IsEmpty() && d_cnt == -1) {
3607 m_config_version = 1;
3610 pConf->Read(_T(
"InstrumentCount"), &i_cnt, -1);
3612 wxArrayOfInstrumentProperties Property;
3614 for (
int i = 0; i < i_cnt; i++) {
3616 pConf->Read(wxString::Format(_T(
"Instrument%d"), i + 1), &
id, -1);
3617 if (
id != -1) ar.Add(
id);
3621#ifndef __OCPN__ANDROID__
3622 ar.Add(ID_DBP_I_POS);
3623 ar.Add(ID_DBP_D_COG);
3624 ar.Add(ID_DBP_D_GPS);
3626 ar.Add(ID_DBP_I_POS);
3627 ar.Add(ID_DBP_D_COG);
3628 ar.Add(ID_DBP_I_SOG);
3634 NULL, MakeName(), _(
"Dashboard"), _T(
"V"), ar, Property);
3635 cont->m_bPersVisible =
true;
3636 m_ArrayOfDashboardWindow.Add(cont);
3640 m_config_version = 2;
3641 bool b_onePersisted =
false;
3643 wxSize persist_size;
3644 for (
int k = 0; k < d_cnt; k++) {
3646 wxString::Format(_T(
"/PlugIns/Dashboard/Dashboard%d"), k + 1));
3648 pConf->Read(_T(
"Name"), &name, MakeName());
3650 pConf->Read(_T(
"Caption"), &caption, _(
"Dashboard"));
3652 pConf->Read(_T(
"Orientation"), &orient, _T(
"V"));
3654 pConf->Read(_T(
"InstrumentCount"), &i_cnt, -1);
3656 pConf->Read(_T(
"Persistence"), &b_persist, 1);
3658 pConf->Read(_T(
"BestSizeX"), &val, DefaultWidth);
3660 pConf->Read(_T(
"BestSizeY"), &val, DefaultWidth);
3662 pConf->Read(_T(
"PersistSizeX"), &val, DefaultWidth);
3663 persist_size.x = val;
3664 pConf->Read(_T(
"PersistSizeY"), &val, DefaultWidth);
3665 persist_size.y = val;
3668 wxArrayOfInstrumentProperties Property;
3669 for (
int i = 0; i < i_cnt; i++) {
3671 pConf->Read(wxString::Format(_T(
"Instrument%d"), i + 1), &
id, -1);
3675 if (pConf->Exists(wxString::Format(_T(
"InstTitleFont%d"), i + 1))) {
3678 pConf->Read(wxString::Format(_T(
"InstTitleFont%d"), i + 1),
3679 &config, TitleFont);
3680 LoadFont(&pDF, config);
3681 pConf->Read(wxString::Format(_T(
"InstTitleColor%d"), i + 1),
3682 &config,
"#000000");
3683 DummyColor.Set(config);
3684 instp->m_USTitleFont.SetChosenFont(DummyFont);
3685 instp->m_USTitleFont.SetColour(DummyColor);
3686 instp->m_TitleFont = instp->m_USTitleFont;
3687 instp->m_TitleFont.SetChosenFont(
3688 instp->m_USTitleFont.GetChosenFont().Scaled(scaler));
3690 pConf->Read(wxString::Format(_T(
"InstDataShowUnit%d"), i + 1),
3691 &instp->m_ShowUnit, -1);
3692 pConf->Read(wxString::Format(_T(
"InstDataMargin%d"), i + 1),
3693 &instp->m_DataMargin, -1);
3694 pConf->Read(wxString::Format(_T(
"InstDataAlignment%d"), i + 1),
3695 &alignment, (
int)wxALIGN_INVALID);
3696 instp->m_DataAlignment = (wxAlignment)alignment;
3698 wxString::Format(_T(
"InstInstrumentSpacing%d"), i + 1),
3699 &instp->m_InstrumentSpacing, -1);
3700 pConf->Read(wxString::Format(_T(
"InstDataFormat%d"), i + 1),
3701 &instp->m_Format,
"");
3702 pConf->Read(wxString::Format(_T(
"InstTitle%d"), i + 1),
3703 &instp->m_Title,
"");
3705 pConf->Read(wxString::Format(_T(
"InstDataFont%d"), i + 1),
3707 LoadFont(&pDF, config);
3708 pConf->Read(wxString::Format(_T(
"InstDataColor%d"), i + 1),
3709 &config,
"#000000");
3710 DummyColor.Set(config);
3711 instp->m_USDataFont.SetChosenFont(DummyFont);
3712 instp->m_USDataFont.SetColour(DummyColor);
3713 instp->m_DataFont = instp->m_USDataFont;
3714 instp->m_DataFont.SetChosenFont(
3715 instp->m_USDataFont.GetChosenFont().Scaled(scaler));
3717 pConf->Read(wxString::Format(_T(
"InstLabelFont%d"), i + 1),
3718 &config, LabelFont);
3719 LoadFont(&pDF, config);
3720 pConf->Read(wxString::Format(_T(
"InstLabelColor%d"), i + 1),
3721 &config,
"#000000");
3722 DummyColor.Set(config);
3723 instp->m_USLabelFont.SetChosenFont(DummyFont);
3724 instp->m_USLabelFont.SetColour(DummyColor);
3725 instp->m_LabelFont = instp->m_USLabelFont;
3726 instp->m_LabelFont.SetChosenFont(
3727 instp->m_USLabelFont.GetChosenFont().Scaled(scaler));
3729 pConf->Read(wxString::Format(_T(
"InstSmallFont%d"), i + 1),
3730 &config, SmallFont);
3731 LoadFont(&pDF, config);
3732 pConf->Read(wxString::Format(_T(
"InstSmallColor%d"), i + 1),
3733 &config,
"#000000");
3734 DummyColor.Set(config);
3735 instp->m_USSmallFont.SetChosenFont(DummyFont);
3736 instp->m_USSmallFont.SetColour(DummyColor);
3737 instp->m_SmallFont = instp->m_USSmallFont;
3738 instp->m_SmallFont.SetChosenFont(
3739 instp->m_USSmallFont.GetChosenFont().Scaled(scaler));
3741 pConf->Read(wxString::Format(_T(
"TitleBackColor%d"), i + 1),
3743 instp->m_TitleBackgroundColour.Set(config);
3745 pConf->Read(wxString::Format(_T(
"DataBackColor%d"), i + 1),
3747 instp->m_DataBackgroundColour.Set(config);
3749 pConf->Read(wxString::Format(_T(
"ArrowFirst%d"), i + 1), &config,
3751 instp->m_Arrow_First_Colour.Set(config);
3753 pConf->Read(wxString::Format(_T(
"ArrowSecond%d"), i + 1), &config,
3755 instp->m_Arrow_Second_Colour.Set(config);
3757 Property.Add(instp);
3764 NULL, name, caption, orient, ar, Property);
3765 cont->m_bPersVisible = b_persist;
3766 cont->m_conf_best_size = best_size;
3767 cont->m_persist_size = persist_size;
3769 if (b_persist) b_onePersisted =
true;
3771 m_ArrayOfDashboardWindow.Add(cont);
3775 if (m_ArrayOfDashboardWindow.Count() && !b_onePersisted) {
3777 if (cont) cont->m_bPersVisible =
true;
3786void dashboard_pi::LoadFont(wxFont **target, wxString native_info) {
3787 if (!native_info.IsEmpty()) {
3788#ifdef __OCPN__ANDROID__
3789 wxFont *nf =
new wxFont(native_info);
3792 (*target)->SetNativeFontInfo(native_info);
3797bool dashboard_pi::SaveConfig(
void) {
3798 wxFileConfig *pConf = (wxFileConfig *)m_pconfig;
3801 pConf->SetPath(_T(
"/PlugIns/Dashboard"));
3802 pConf->Write(_T(
"Version"), _T(
"2"));
3803 pConf->Write(_T(
"FontTitle"),
3804 g_pUSFontTitle->GetChosenFont().GetNativeFontInfoDesc());
3805 pConf->Write(_T(
"ColorTitle"),
3806 g_pUSFontTitle->GetColour().GetAsString(wxC2S_HTML_SYNTAX));
3807 pConf->Write(_T(
"FontData"),
3808 g_pUSFontData->GetChosenFont().GetNativeFontInfoDesc());
3809 pConf->Write(_T(
"ColorData"),
3810 g_pUSFontData->GetColour().GetAsString(wxC2S_HTML_SYNTAX));
3811 pConf->Write(_T(
"FontLabel"),
3812 g_pUSFontLabel->GetChosenFont().GetNativeFontInfoDesc());
3813 pConf->Write(_T(
"ColorLabel"),
3814 g_pUSFontLabel->GetColour().GetAsString(wxC2S_HTML_SYNTAX));
3815 pConf->Write(_T(
"FontSmall"),
3816 g_pUSFontSmall->GetChosenFont().GetNativeFontInfoDesc());
3817 pConf->Write(_T(
"ColorSmall"),
3818 g_pUSFontSmall->GetColour().GetAsString(wxC2S_HTML_SYNTAX));
3819 pConf->Write(_T(
"SpeedometerMax"), g_iDashSpeedMax);
3820 pConf->Write(_T(
"COGDamp"), g_iDashCOGDamp);
3821 pConf->Write(_T(
"SpeedUnit"), g_iDashSpeedUnit);
3822 pConf->Write(_T(
"SOGDamp"), g_iDashSOGDamp);
3823 pConf->Write(_T(
"DepthUnit"), g_iDashDepthUnit);
3824 pConf->Write(_T(
"DepthOffset"), g_dDashDBTOffset);
3825 pConf->Write(_T(
"DistanceUnit"), g_iDashDistanceUnit);
3826 pConf->Write(_T(
"WindSpeedUnit"), g_iDashWindSpeedUnit);
3827 pConf->Write(_T(
"UTCOffset"), g_iUTCOffset);
3828 pConf->Write(_T(
"UseSignKtruewind"), g_bDBtrueWindGround);
3829 pConf->Write(_T(
"TemperatureUnit"), g_iDashTempUnit);
3830 pConf->Write(_T(
"PrefWidth"), g_dashPrefWidth);
3831 pConf->Write(_T(
"PrefHeight"), g_dashPrefHeight);
3833 pConf->Write(_T(
"DashboardCount" ),
3834 (int)m_ArrayOfDashboardWindow.GetCount());
3836 for (
size_t i = m_ArrayOfDashboardWindow.GetCount(); i < 20; i++) {
3838 wxString::Format(_T(
"/PlugIns/Dashboard/Dashboard%zu"), i + 1))) {
3840 wxString::Format(_T(
"/PlugIns/Dashboard/Dashboard%zu"), i + 1));
3843 for (
size_t i = 0; i < m_ArrayOfDashboardWindow.GetCount(); i++) {
3846 wxString::Format(_T(
"/PlugIns/Dashboard/Dashboard%zu"), i + 1));
3847 pConf->Write(_T(
"Name"), cont->m_sName);
3848 pConf->Write(_T(
"Caption"), cont->m_sCaption);
3849 pConf->Write(_T(
"Orientation"), cont->m_sOrientation);
3850 pConf->Write(_T(
"Persistence"), cont->m_bPersVisible);
3851 pConf->Write(_T(
"InstrumentCount"),
3852 (int)cont->m_aInstrumentList.GetCount());
3853 pConf->Write(_T(
"BestSizeX"), cont->m_best_size.x);
3854 pConf->Write(_T(
"BestSizeY"), cont->m_best_size.y);
3855 pConf->Write(_T(
"PersistSizeX"), cont->m_pDashboardWindow->GetSize().x);
3856 pConf->Write(_T(
"PersistSizeY"), cont->m_pDashboardWindow->GetSize().y);
3859 for (
size_t i = cont->m_aInstrumentList.GetCount(); i < 40; i++) {
3860 if (pConf->Exists(wxString::Format(_T(
"Instrument%zu"), i + 1))) {
3861 pConf->DeleteEntry(wxString::Format(_T(
"Instrument%zu"), i + 1));
3862 if (pConf->Exists(wxString::Format(_T(
"InstTitleFont%zu"), i + 1))) {
3863 pConf->DeleteEntry(wxString::Format(_T(
"InstTitleFont%zu"), i + 1));
3865 wxString::Format(_T(
"InstTitleColor%zu"), i + 1));
3866 pConf->DeleteEntry(wxString::Format(_T(
"InstTitle%zu"), i + 1));
3868 wxString::Format(_T(
"InstDataShowUnit%zu"), i + 1));
3870 wxString::Format(_T(
"InstDataMargin%zu"), i + 1));
3872 wxString::Format(_T(
"InstDataAlignment%zu"), i + 1));
3874 wxString::Format(_T(
"InstDataFormat%zu"), i + 1));
3875 pConf->DeleteEntry(wxString::Format(_T(
"InstDataFont%zu"), i + 1));
3876 pConf->DeleteEntry(wxString::Format(_T(
"InstDataColor%zu"), i + 1));
3877 pConf->DeleteEntry(wxString::Format(_T(
"InstLabelFont%zu"), i + 1));
3879 wxString::Format(_T(
"InstLabelColor%zu"), i + 1));
3880 pConf->DeleteEntry(wxString::Format(_T(
"InstSmallFont%zu"), i + 1));
3882 wxString::Format(_T(
"InstSmallColor%zu"), i + 1));
3884 wxString::Format(_T(
"TitleBackColor%zu"), i + 1));
3885 pConf->DeleteEntry(wxString::Format(_T(
"DataBackColor%zu"), i + 1));
3886 pConf->DeleteEntry(wxString::Format(_T(
"ArrowFirst%zu"), i + 1));
3887 pConf->DeleteEntry(wxString::Format(_T(
"ArrowSecond%zu"), i + 1));
3891 for (
size_t j = 0; j < cont->m_aInstrumentList.GetCount(); j++) {
3892 pConf->Write(wxString::Format(_T(
"Instrument%zu"), j + 1),
3893 cont->m_aInstrumentList.Item(j));
3896 if (pConf->Exists(wxString::Format(_T(
"InstTitleFont%zu"), j + 1))) {
3898 for (
size_t i = 0; i < cont->m_aInstrumentPropertyList.GetCount();
3900 Inst = cont->m_aInstrumentPropertyList.Item(i);
3901 if (Inst->m_Listplace == (
int)j) {
3907 pConf->DeleteEntry(wxString::Format(_T(
"InstTitleFont%zu"), j + 1));
3909 wxString::Format(_T(
"InstTitleColor%zu"), j + 1));
3910 pConf->DeleteEntry(wxString::Format(_T(
"InstTitle%zu"), j + 1));
3912 wxString::Format(_T(
"InstDataShowUnit%zu"), i + 1));
3914 wxString::Format(_T(
"InstDataMargin%zu"), i + 1));
3916 wxString::Format(_T(
"InstDataAlignment%zu"), i + 1));
3918 wxString::Format(_T(
"InstDataFormat%zu"), i + 1));
3919 pConf->DeleteEntry(wxString::Format(_T(
"InstDataFont%zu"), j + 1));
3920 pConf->DeleteEntry(wxString::Format(_T(
"InstDataColor%zu"), j + 1));
3921 pConf->DeleteEntry(wxString::Format(_T(
"InstLabelFont%zu"), j + 1));
3923 wxString::Format(_T(
"InstLabelColor%zu"), j + 1));
3924 pConf->DeleteEntry(wxString::Format(_T(
"InstSmallFont%zu"), j + 1));
3926 wxString::Format(_T(
"InstSmallColor%zu"), j + 1));
3928 wxString::Format(_T(
"TitleBackColor%zu"), i + 1));
3929 pConf->DeleteEntry(wxString::Format(_T(
"DataBackColor%zu"), i + 1));
3930 pConf->DeleteEntry(wxString::Format(_T(
"ArrowFirst%zu"), i + 1));
3931 pConf->DeleteEntry(wxString::Format(_T(
"ArrowSecond%zu"), i + 1));
3935 for (
size_t i = 0; i < (cont->m_aInstrumentPropertyList.GetCount());
3937 Inst = cont->m_aInstrumentPropertyList.Item(i);
3938 if (Inst->m_Listplace == (
int)j) {
3940 wxString::Format(_T(
"InstTitleFont%zu"), j + 1),
3941 Inst->m_USTitleFont.GetChosenFont().GetNativeFontInfoDesc());
3943 wxString::Format(_T(
"InstTitleColor%zu"), j + 1),
3944 Inst->m_USTitleFont.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
3946 wxString::Format(_T(
"InstDataFont%zu"), j + 1),
3947 Inst->m_USDataFont.GetChosenFont().GetNativeFontInfoDesc());
3949 wxString::Format(_T(
"InstDataColor%zu"), j + 1),
3950 Inst->m_USDataFont.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
3952 wxString::Format(_T(
"InstLabelFont%zu"), j + 1),
3953 Inst->m_USLabelFont.GetChosenFont().GetNativeFontInfoDesc());
3955 wxString::Format(_T(
"InstLabelColor%zu"), j + 1),
3956 Inst->m_USLabelFont.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
3958 wxString::Format(_T(
"InstSmallFont%zu"), j + 1),
3959 Inst->m_USSmallFont.GetChosenFont().GetNativeFontInfoDesc());
3961 wxString::Format(_T(
"InstSmallColor%zu"), j + 1),
3962 Inst->m_USSmallFont.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
3964 wxString::Format(_T(
"TitleBackColor%zu"), j + 1),
3965 Inst->m_TitleBackgroundColour.GetAsString(wxC2S_HTML_SYNTAX));
3967 wxString::Format(_T(
"DataBackColor%zu"), j + 1),
3968 Inst->m_DataBackgroundColour.GetAsString(wxC2S_HTML_SYNTAX));
3970 wxString::Format(_T(
"ArrowFirst%zu"), j + 1),
3971 Inst->m_Arrow_First_Colour.GetAsString(wxC2S_HTML_SYNTAX));
3973 wxString::Format(_T(
"ArrowSecond%zu"), j + 1),
3974 Inst->m_Arrow_Second_Colour.GetAsString(wxC2S_HTML_SYNTAX));
3985void dashboard_pi::ApplyConfig(
void) {
3987 for (
size_t i = m_ArrayOfDashboardWindow.GetCount(); i > 0; i--) {
3989 int orient = (cont->m_sOrientation == _T(
"V") ? wxVERTICAL : wxHORIZONTAL);
3990 if (cont->m_bIsDeleted) {
3991 if (cont->m_pDashboardWindow) {
3992 m_pauimgr->DetachPane(cont->m_pDashboardWindow);
3993 cont->m_pDashboardWindow->Close();
3994 cont->m_pDashboardWindow->Destroy();
3995 cont->m_pDashboardWindow = NULL;
3997 m_ArrayOfDashboardWindow.Remove(cont);
4000 }
else if (!cont->m_pDashboardWindow) {
4003 GetOCPNCanvasWindow(), wxID_ANY, m_pauimgr,
this, orient, cont);
4004 cont->m_pDashboardWindow->SetInstrumentList(
4005 cont->m_aInstrumentList, &(cont->m_aInstrumentPropertyList));
4006 bool vertical = orient == wxVERTICAL;
4007 wxSize sz = cont->m_pDashboardWindow->GetMinSize();
4008 wxSize best = cont->m_conf_best_size;
4009 if (best.x < 100) best = sz;
4013 if (sz.x == 0) sz.IncTo(wxSize(160, 388));
4015 wxAuiPaneInfo p = wxAuiPaneInfo()
4016 .Name(cont->m_sName)
4017 .Caption(cont->m_sCaption)
4018 .CaptionVisible(
false)
4019 .TopDockable(!vertical)
4020 .BottomDockable(!vertical)
4021 .LeftDockable(vertical)
4022 .RightDockable(vertical)
4026 .FloatingPosition(100, 100)
4028 .Show(cont->m_bIsVisible)
4031 m_pauimgr->AddPane(cont->m_pDashboardWindow, p);
4038#ifdef __OCPN__ANDROID__
4039 wxAuiPaneInfo &pane = m_pauimgr->GetPane(cont->m_pDashboardWindow);
4040 pane.Dockable(
false);
4045 wxAuiPaneInfo &pane = m_pauimgr->GetPane(cont->m_pDashboardWindow);
4046 pane.Caption(cont->m_sCaption).Show(cont->m_bIsVisible);
4047 if (!cont->m_pDashboardWindow->isInstrumentListEqual(
4048 cont->m_aInstrumentList)) {
4049 cont->m_pDashboardWindow->SetInstrumentList(
4050 cont->m_aInstrumentList, &(cont->m_aInstrumentPropertyList));
4051 wxSize sz = cont->m_pDashboardWindow->GetMinSize();
4052 pane.MinSize(sz).BestSize(sz).FloatingSize(sz);
4054 if (cont->m_pDashboardWindow->GetSizerOrientation() != orient) {
4055 cont->m_pDashboardWindow->ChangePaneOrientation(orient,
false);
4059 m_pauimgr->Update();
4061 double sogFC = g_iDashSOGDamp ? 1.0 / (2.0 * g_iDashSOGDamp) : 0.0;
4062 double cogFC = g_iDashCOGDamp ? 1.0 / (2.0 * g_iDashCOGDamp) : 0.0;
4064 if (abs(sogFC - mSOGFilter.getFc()) > 1e-6) mSOGFilter.setFC(sogFC);
4065 if (abs(cogFC - mCOGFilter.getFc()) > 1e-6) mCOGFilter.setFC(cogFC);
4068void dashboard_pi::PopulateContextMenu(wxMenu *menu) {
4070 wxMenuItem *visItem = 0;
4071 for (
size_t i = 0; i < m_ArrayOfDashboardWindow.GetCount(); i++) {
4073 wxMenuItem *item = menu->AppendCheckItem(i + 1, cont->m_sCaption);
4074 item->Check(cont->m_bIsVisible);
4075 if (cont->m_bIsVisible) {
4080 if (nvis == 1 && visItem) visItem->Enable(
false);
4083void dashboard_pi::ShowDashboard(
size_t id,
bool visible) {
4084 if (
id < m_ArrayOfDashboardWindow.GetCount()) {
4086 m_pauimgr->GetPane(cont->m_pDashboardWindow).Show(visible);
4087 cont->m_bIsVisible = visible;
4088 cont->m_bPersVisible = visible;
4089 m_pauimgr->Update();
4097DashboardPreferencesDialog::DashboardPreferencesDialog(
4098 wxWindow *parent, wxWindowID
id, wxArrayOfDashboard config)
4099 : wxDialog(parent, id, _(
"Dashboard preferences"), wxDefaultPosition,
4100 wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) {
4106 int display_width, display_height;
4107 wxDisplaySize(&display_width, &display_height);
4109 wxString shareLocn = *GetpSharedDataLocation() + _T(
"plugins") +
4110 wxFileName::GetPathSeparator() + _T(
"dashboard_pi") +
4111 wxFileName::GetPathSeparator() + _T(
"data") +
4112 wxFileName::GetPathSeparator();
4114 Connect(wxEVT_CLOSE_WINDOW,
4115 wxCloseEventHandler(DashboardPreferencesDialog::OnCloseDialog), NULL,
4119 m_Config = wxArrayOfDashboard(config);
4121 int border_size = 2;
4123 wxBoxSizer *itemBoxSizerMainPanel =
new wxBoxSizer(wxVERTICAL);
4124 SetSizer(itemBoxSizerMainPanel);
4126 wxWindow *dparent =
this;
4128 wxScrolledWindow *scrollWin =
new wxScrolledWindow(
4129 this, wxID_ANY, wxDefaultPosition, wxSize(-1, -1), wxVSCROLL | wxHSCROLL);
4131 scrollWin->SetScrollRate(1, 1);
4132 itemBoxSizerMainPanel->Add(scrollWin, 1, wxEXPAND | wxALL, 0);
4134 dparent = scrollWin;
4136 wxBoxSizer *itemBoxSizer2 =
new wxBoxSizer(wxVERTICAL);
4137 scrollWin->SetSizer(itemBoxSizer2);
4139 wxBoxSizer *itemBoxSizer2 =
new wxBoxSizer(wxVERTICAL);
4140 itemBoxSizerMainPanel->Add(itemBoxSizer2, 1, wxEXPAND);
4143 auto *DialogButtonSizer =
new wxStdDialogButtonSizer();
4144 DialogButtonSizer->AddButton(
new wxButton(
this, wxID_OK));
4145 DialogButtonSizer->AddButton(
new wxButton(
this, wxID_CANCEL));
4146 wxButton *help_btn =
new wxButton(
this, wxID_HELP);
4147 help_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [&](wxCommandEvent) {
4148 wxString datadir = GetPluginDataDir(
"manual_pi");
4149 Manual(
this, datadir.ToStdString()).Launch(
"Dashboard");
4151 DialogButtonSizer->AddButton(help_btn);
4152 DialogButtonSizer->Realize();
4154 itemBoxSizerMainPanel->Add(DialogButtonSizer, 0, wxALIGN_RIGHT | wxALL, 5);
4156 wxNotebook *itemNotebook =
new wxNotebook(
4157 dparent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP);
4158 itemBoxSizer2->Add(itemNotebook, 0, wxALL | wxEXPAND, border_size);
4160 wxPanel *itemPanelNotebook01 =
4161 new wxPanel(itemNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize,
4163 wxFlexGridSizer *itemFlexGridSizer01 =
new wxFlexGridSizer(2);
4164 itemFlexGridSizer01->AddGrowableCol(1);
4165 itemPanelNotebook01->SetSizer(itemFlexGridSizer01);
4166 itemNotebook->AddPage(itemPanelNotebook01, _(
"Dashboard"));
4168 wxBoxSizer *itemBoxSizer01 =
new wxBoxSizer(wxVERTICAL);
4169 itemFlexGridSizer01->Add(itemBoxSizer01, 1, wxEXPAND | wxTOP | wxLEFT,
4173 int imageRefSize = GetCharWidth() * 4;
4175 wxImageList *imglist1 =
new wxImageList(imageRefSize, imageRefSize,
true, 1);
4177 wxBitmap bmDashBoard;
4179 wxString filename = shareLocn + _T(
"Dashboard.svg");
4180 bmDashBoard = GetBitmapFromSVGFile(filename, imageRefSize, imageRefSize);
4182 wxImage dash1 = wxBitmap(*_img_dashboard_pi).ConvertToImage();
4184 dash1.Scale(imageRefSize, imageRefSize, wxIMAGE_QUALITY_HIGH);
4185 bmDashBoard = wxBitmap(dash1s);
4188 imglist1->Add(bmDashBoard);
4190 m_pListCtrlDashboards =
4191 new wxListCtrl(itemPanelNotebook01, wxID_ANY, wxDefaultPosition,
4192 wxSize(imageRefSize * 3 / 2, 200),
4193 wxLC_REPORT | wxLC_NO_HEADER | wxLC_SINGLE_SEL);
4195 m_pListCtrlDashboards->AssignImageList(imglist1, wxIMAGE_LIST_SMALL);
4196 m_pListCtrlDashboards->InsertColumn(0, _T(
""));
4197 m_pListCtrlDashboards->Connect(
4198 wxEVT_COMMAND_LIST_ITEM_SELECTED,
4199 wxListEventHandler(DashboardPreferencesDialog::OnDashboardSelected), NULL,
4201 m_pListCtrlDashboards->Connect(
4202 wxEVT_COMMAND_LIST_ITEM_DESELECTED,
4203 wxListEventHandler(DashboardPreferencesDialog::OnDashboardSelected), NULL,
4205 itemBoxSizer01->Add(m_pListCtrlDashboards, 1, wxEXPAND, 0);
4207 wxBoxSizer *itemBoxSizer02 =
new wxBoxSizer(wxHORIZONTAL);
4208 itemBoxSizer01->Add(itemBoxSizer02);
4210 wxBitmap bmPlus, bmMinus;
4211 int bmSize = imageRefSize * 100 / 275;
4213#ifdef __OCPN__ANDROID__
4214 bmSize = imageRefSize / 2;
4218 bmPlus = GetBitmapFromSVGFile(shareLocn + _T(
"plus.svg"), bmSize, bmSize);
4219 bmMinus = GetBitmapFromSVGFile(shareLocn + _T(
"minus.svg"), bmSize, bmSize);
4221 wxImage plus1 = wxBitmap(*_img_plus).ConvertToImage();
4222 wxImage plus1s = plus1.Scale(bmSize, bmSize, wxIMAGE_QUALITY_HIGH);
4223 bmPlus = wxBitmap(plus1s);
4225 wxImage minus1 = wxBitmap(*_img_minus).ConvertToImage();
4226 wxImage minus1s = minus1.Scale(bmSize, bmSize, wxIMAGE_QUALITY_HIGH);
4227 bmMinus = wxBitmap(minus1s);
4230 m_pButtonAddDashboard =
new wxBitmapButton(
4231 itemPanelNotebook01, wxID_ANY, bmPlus, wxDefaultPosition, wxDefaultSize);
4232 itemBoxSizer02->Add(m_pButtonAddDashboard, 0, wxALIGN_CENTER, 2);
4233 m_pButtonAddDashboard->Connect(
4234 wxEVT_COMMAND_BUTTON_CLICKED,
4235 wxCommandEventHandler(DashboardPreferencesDialog::OnDashboardAdd), NULL,
4238 m_pButtonDeleteDashboard =
new wxBitmapButton(
4239 itemPanelNotebook01, wxID_ANY, bmMinus, wxDefaultPosition, wxDefaultSize);
4240 itemBoxSizer02->Add(m_pButtonDeleteDashboard, 0, wxALIGN_CENTER, 2);
4241 m_pButtonDeleteDashboard->Connect(
4242 wxEVT_COMMAND_BUTTON_CLICKED,
4243 wxCommandEventHandler(DashboardPreferencesDialog::OnDashboardDelete),
4247 new wxPanel(itemPanelNotebook01, wxID_ANY, wxDefaultPosition,
4248 wxDefaultSize, wxBORDER_SUNKEN);
4249 itemFlexGridSizer01->Add(m_pPanelDashboard, 1, wxEXPAND | wxTOP | wxRIGHT,
4252 wxBoxSizer *itemBoxSizer03 =
new wxBoxSizer(wxVERTICAL);
4253 m_pPanelDashboard->SetSizer(itemBoxSizer03);
4255 wxStaticBox *itemStaticBox02 =
4256 new wxStaticBox(m_pPanelDashboard, wxID_ANY, _(
"Dashboard"));
4257 wxStaticBoxSizer *itemStaticBoxSizer02 =
4258 new wxStaticBoxSizer(itemStaticBox02, wxHORIZONTAL);
4259 itemBoxSizer03->Add(itemStaticBoxSizer02, 0, wxEXPAND | wxALL, border_size);
4260 wxFlexGridSizer *itemFlexGridSizer =
new wxFlexGridSizer(2);
4261 itemFlexGridSizer->AddGrowableCol(1);
4262 itemStaticBoxSizer02->Add(itemFlexGridSizer, 1, wxEXPAND | wxALL, 0);
4264 m_pCheckBoxIsVisible =
4265 new wxCheckBox(m_pPanelDashboard, wxID_ANY, _(
"show this dashboard"),
4266 wxDefaultPosition, wxDefaultSize, 0);
4267 m_pCheckBoxIsVisible->SetMinSize(wxSize(25 * GetCharWidth(), -1));
4269 itemFlexGridSizer->Add(m_pCheckBoxIsVisible, 0, wxEXPAND | wxALL,
4271 wxStaticText *itemDummy01 =
4272 new wxStaticText(m_pPanelDashboard, wxID_ANY, _T(
""));
4273 itemFlexGridSizer->Add(itemDummy01, 0, wxEXPAND | wxALL, border_size);
4275 wxStaticText *itemStaticText01 =
4276 new wxStaticText(m_pPanelDashboard, wxID_ANY, _(
"Caption:"),
4277 wxDefaultPosition, wxDefaultSize, 0);
4278 itemFlexGridSizer->Add(itemStaticText01, 0, wxEXPAND | wxALL, border_size);
4279 m_pTextCtrlCaption =
new wxTextCtrl(m_pPanelDashboard, wxID_ANY, _T(
""),
4280 wxDefaultPosition, wxDefaultSize);
4281 m_pCheckBoxIsVisible->SetMinSize(wxSize(30 * GetCharWidth(), -1));
4282 itemFlexGridSizer->Add(m_pTextCtrlCaption, 0, wxALIGN_RIGHT | wxALL,
4285 wxStaticText *itemStaticText02 =
4286 new wxStaticText(m_pPanelDashboard, wxID_ANY, _(
"Orientation:"),
4287 wxDefaultPosition, wxDefaultSize, 0);
4288 itemFlexGridSizer->Add(itemStaticText02, 0, wxEXPAND | wxALL, border_size);
4289 m_pChoiceOrientation =
new wxChoice(m_pPanelDashboard, wxID_ANY,
4290 wxDefaultPosition, wxDefaultSize);
4291 m_pChoiceOrientation->SetMinSize(wxSize(15 * GetCharWidth(), -1));
4292 m_pChoiceOrientation->Append(_(
"Vertical"));
4293 m_pChoiceOrientation->Append(_(
"Horizontal"));
4294 itemFlexGridSizer->Add(m_pChoiceOrientation, 0, wxALIGN_RIGHT | wxALL,
4297 int instImageRefSize = 20 * GetOCPNGUIToolScaleFactor_PlugIn();
4299 wxImageList *imglist =
4300 new wxImageList(instImageRefSize, instImageRefSize,
true, 2);
4302 wxBitmap bmDial, bmInst;
4304 bmDial = GetBitmapFromSVGFile(shareLocn + _T(
"dial.svg"), instImageRefSize,
4306 bmInst = GetBitmapFromSVGFile(shareLocn + _T(
"instrument.svg"),
4307 instImageRefSize, instImageRefSize);
4309 wxImage dial1 = wxBitmap(*_img_dial).ConvertToImage();
4311 dial1.Scale(instImageRefSize, instImageRefSize, wxIMAGE_QUALITY_HIGH);
4312 bmDial = wxBitmap(dial1);
4314 wxImage inst1 = wxBitmap(*_img_instrument).ConvertToImage();
4316 inst1.Scale(instImageRefSize, instImageRefSize, wxIMAGE_QUALITY_HIGH);
4317 bmInst = wxBitmap(inst1s);
4320 imglist->Add(bmInst);
4321 imglist->Add(bmDial);
4323 wxStaticBox *itemStaticBox03 =
4324 new wxStaticBox(m_pPanelDashboard, wxID_ANY, _(
"Instruments"));
4325 wxStaticBoxSizer *itemStaticBoxSizer03 =
4326 new wxStaticBoxSizer(itemStaticBox03, wxHORIZONTAL);
4327 itemBoxSizer03->Add(itemStaticBoxSizer03, 1, wxEXPAND | wxALL, border_size);
4329 wxSize dsize = GetOCPNCanvasWindow()->GetClientSize();
4330 int vsize = dsize.y * 35 / 100;
4332#ifdef __OCPN__ANDROID__
4333 vsize = display_height * 50 / 100;
4336 m_pListCtrlInstruments =
new wxListCtrl(
4337 m_pPanelDashboard, wxID_ANY, wxDefaultPosition, wxSize(-1, vsize),
4338 wxLC_REPORT | wxLC_NO_HEADER | wxLC_SINGLE_SEL);
4340 itemStaticBoxSizer03->Add(m_pListCtrlInstruments, 1, wxEXPAND | wxALL,
4342 m_pListCtrlInstruments->AssignImageList(imglist, wxIMAGE_LIST_SMALL);
4343 m_pListCtrlInstruments->InsertColumn(0, _(
"Instruments"));
4344 m_pListCtrlInstruments->Connect(
4345 wxEVT_COMMAND_LIST_ITEM_SELECTED,
4346 wxListEventHandler(DashboardPreferencesDialog::OnInstrumentSelected),
4348 m_pListCtrlInstruments->Connect(
4349 wxEVT_COMMAND_LIST_ITEM_DESELECTED,
4350 wxListEventHandler(DashboardPreferencesDialog::OnInstrumentSelected),
4353 wxBoxSizer *itemBoxSizer04 =
new wxBoxSizer(wxVERTICAL);
4354 itemStaticBoxSizer03->Add(itemBoxSizer04, 0, wxALIGN_TOP | wxALL,
4356 m_pButtonAdd =
new wxButton(m_pPanelDashboard, wxID_ANY, _(
"Add"),
4357 wxDefaultPosition, wxSize(-1, -1));
4358 itemBoxSizer04->Add(m_pButtonAdd, 0, wxEXPAND | wxALL, border_size);
4359 m_pButtonAdd->Connect(
4360 wxEVT_COMMAND_BUTTON_CLICKED,
4361 wxCommandEventHandler(DashboardPreferencesDialog::OnInstrumentAdd), NULL,
4365 m_pButtonEdit =
new wxButton(m_pPanelDashboard, wxID_ANY, _(
"Edit"),
4366 wxDefaultPosition, wxDefaultSize);
4367 itemBoxSizer04->Add(m_pButtonEdit, 0, wxEXPAND | wxALL, border_size);
4368 m_pButtonEdit->Connect(
4369 wxEVT_COMMAND_BUTTON_CLICKED,
4370 wxCommandEventHandler(DashboardPreferencesDialog::OnInstrumentEdit), NULL,
4381 m_pButtonDelete =
new wxButton(m_pPanelDashboard, wxID_ANY, _(
"Delete"),
4382 wxDefaultPosition, wxSize(-1, -1));
4383 itemBoxSizer04->Add(m_pButtonDelete, 0, wxEXPAND | wxALL, border_size);
4384 m_pButtonDelete->Connect(
4385 wxEVT_COMMAND_BUTTON_CLICKED,
4386 wxCommandEventHandler(DashboardPreferencesDialog::OnInstrumentDelete),
4388 itemBoxSizer04->AddSpacer(10);
4389 m_pButtonUp =
new wxButton(m_pPanelDashboard, wxID_ANY, _(
"Up"),
4390 wxDefaultPosition, wxDefaultSize);
4391 itemBoxSizer04->Add(m_pButtonUp, 0, wxEXPAND | wxALL, border_size);
4392 m_pButtonUp->Connect(
4393 wxEVT_COMMAND_BUTTON_CLICKED,
4394 wxCommandEventHandler(DashboardPreferencesDialog::OnInstrumentUp), NULL,
4396 m_pButtonDown =
new wxButton(m_pPanelDashboard, wxID_ANY, _(
"Down"),
4397 wxDefaultPosition, wxDefaultSize);
4398 itemBoxSizer04->Add(m_pButtonDown, 0, wxEXPAND | wxALL, border_size);
4399 m_pButtonDown->Connect(
4400 wxEVT_COMMAND_BUTTON_CLICKED,
4401 wxCommandEventHandler(DashboardPreferencesDialog::OnInstrumentDown), NULL,
4404 wxPanel *itemPanelNotebook02 =
4405 new wxPanel(itemNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize,
4407 wxBoxSizer *itemBoxSizer05 =
new wxBoxSizer(wxVERTICAL);
4408 itemPanelNotebook02->SetSizer(itemBoxSizer05);
4409 itemNotebook->AddPage(itemPanelNotebook02, _(
"Appearance"));
4411 wxStaticBox *itemStaticBox01 =
4412 new wxStaticBox(itemPanelNotebook02, wxID_ANY, _(
"Fonts"));
4413 wxStaticBoxSizer *itemStaticBoxSizer01 =
4414 new wxStaticBoxSizer(itemStaticBox01, wxHORIZONTAL);
4415 itemBoxSizer05->Add(itemStaticBoxSizer01, 0, wxEXPAND | wxALL, border_size);
4416 wxFlexGridSizer *itemFlexGridSizer03 =
new wxFlexGridSizer(2);
4417 itemFlexGridSizer03->AddGrowableCol(1);
4418 itemStaticBoxSizer01->Add(itemFlexGridSizer03, 1, wxEXPAND | wxALL, 0);
4420 wxStaticText *itemStaticText04 =
4421 new wxStaticText(itemPanelNotebook02, wxID_ANY, _(
"Title:"),
4422 wxDefaultPosition, wxDefaultSize, 0);
4423 itemFlexGridSizer03->Add(itemStaticText04, 0, wxEXPAND | wxALL, border_size);
4424 m_pFontPickerTitle =
4425 new wxFontPickerCtrl(itemPanelNotebook02, wxID_ANY, g_USFontTitle,
4426 wxDefaultPosition, wxDefaultSize);
4427 itemFlexGridSizer03->Add(m_pFontPickerTitle, 0, wxALIGN_RIGHT | wxALL, 0);
4429 wxStaticText *itemStaticText05 =
4430 new wxStaticText(itemPanelNotebook02, wxID_ANY, _(
"Data:"),
4431 wxDefaultPosition, wxDefaultSize, 0);
4432 itemFlexGridSizer03->Add(itemStaticText05, 0, wxEXPAND | wxALL, border_size);
4434 new wxFontPickerCtrl(itemPanelNotebook02, wxID_ANY, g_USFontData,
4435 wxDefaultPosition, wxDefaultSize);
4436 itemFlexGridSizer03->Add(m_pFontPickerData, 0, wxALIGN_RIGHT | wxALL, 0);
4438 wxStaticText *itemStaticText06 =
4439 new wxStaticText(itemPanelNotebook02, wxID_ANY, _(
"Label:"),
4440 wxDefaultPosition, wxDefaultSize, 0);
4441 itemFlexGridSizer03->Add(itemStaticText06, 0, wxEXPAND | wxALL, border_size);
4442 m_pFontPickerLabel =
4443 new wxFontPickerCtrl(itemPanelNotebook02, wxID_ANY, g_USFontLabel,
4444 wxDefaultPosition, wxDefaultSize);
4445 itemFlexGridSizer03->Add(m_pFontPickerLabel, 0, wxALIGN_RIGHT | wxALL, 0);
4447 wxStaticText *itemStaticText07 =
4448 new wxStaticText(itemPanelNotebook02, wxID_ANY, _(
"Small:"),
4449 wxDefaultPosition, wxDefaultSize, 0);
4450 itemFlexGridSizer03->Add(itemStaticText07, 0, wxEXPAND | wxALL, border_size);
4451 m_pFontPickerSmall =
4452 new wxFontPickerCtrl(itemPanelNotebook02, wxID_ANY, g_USFontSmall,
4453 wxDefaultPosition, wxDefaultSize);
4454 itemFlexGridSizer03->Add(m_pFontPickerSmall, 0, wxALIGN_RIGHT | wxALL, 0);
4457 wxStaticText *itemStaticText80 =
4458 new wxStaticText(itemPanelNotebook02, wxID_ANY, _(
"Reset:"),
4459 wxDefaultPosition, wxDefaultSize, 0);
4460 itemFlexGridSizer03->Add(itemStaticText80, 0, wxEXPAND | wxALL, border_size);
4462 m_pButtondefaultFont =
new wxButton(itemPanelNotebook02, wxID_ANY,
4463 _(
"Set dashboard default fonts"),
4464 wxDefaultPosition, wxSize(-1, -1));
4465 itemFlexGridSizer03->Add(m_pButtondefaultFont, 0, wxALIGN_RIGHT | wxALL, 0);
4466 m_pButtondefaultFont->Connect(
4467 wxEVT_COMMAND_BUTTON_CLICKED,
4468 wxCommandEventHandler(DashboardPreferencesDialog::OnDashboarddefaultFont),
4471 wxStaticBox *itemStaticBox04 =
new wxStaticBox(itemPanelNotebook02, wxID_ANY,
4472 _(
"Units, Ranges, Formats"));
4473 wxStaticBoxSizer *itemStaticBoxSizer04 =
4474 new wxStaticBoxSizer(itemStaticBox04, wxHORIZONTAL);
4475 itemBoxSizer05->Add(itemStaticBoxSizer04, 0, wxEXPAND | wxALL, border_size);
4476 wxFlexGridSizer *itemFlexGridSizer04 =
new wxFlexGridSizer(2);
4477 itemFlexGridSizer04->AddGrowableCol(1);
4478 itemStaticBoxSizer04->Add(itemFlexGridSizer04, 1, wxEXPAND | wxALL, 0);
4479 wxStaticText *itemStaticText08 =
new wxStaticText(
4480 itemPanelNotebook02, wxID_ANY, _(
"Speedometer max value:"),
4481 wxDefaultPosition, wxDefaultSize, 0);
4482 itemFlexGridSizer04->Add(itemStaticText08, 0, wxEXPAND | wxALL, border_size);
4483 m_pSpinSpeedMax =
new wxSpinCtrl(itemPanelNotebook02, wxID_ANY, wxEmptyString,
4484 wxDefaultPosition, wxDefaultSize,
4485 wxSP_ARROW_KEYS, 10, 100, g_iDashSpeedMax);
4486 itemFlexGridSizer04->Add(m_pSpinSpeedMax, 0, wxALIGN_RIGHT | wxALL, 0);
4488 wxStaticText *itemStaticText10 =
new wxStaticText(
4489 itemPanelNotebook02, wxID_ANY, _(
"Speed Over Ground Damping Factor:"),
4490 wxDefaultPosition, wxDefaultSize, 0);
4491 itemFlexGridSizer04->Add(itemStaticText10, 0, wxEXPAND | wxALL, border_size);
4492 m_pSpinSOGDamp =
new wxSpinCtrl(itemPanelNotebook02, wxID_ANY, wxEmptyString,
4493 wxDefaultPosition, wxDefaultSize,
4494 wxSP_ARROW_KEYS, 0, 100, g_iDashSOGDamp);
4495 itemFlexGridSizer04->Add(m_pSpinSOGDamp, 0, wxALIGN_RIGHT | wxALL, 0);
4497 wxStaticText *itemStaticText11 =
4498 new wxStaticText(itemPanelNotebook02, wxID_ANY, _(
"COG Damping Factor:"),
4499 wxDefaultPosition, wxDefaultSize, 0);
4500 itemFlexGridSizer04->Add(itemStaticText11, 0, wxEXPAND | wxALL, border_size);
4501 m_pSpinCOGDamp =
new wxSpinCtrl(itemPanelNotebook02, wxID_ANY, wxEmptyString,
4502 wxDefaultPosition, wxDefaultSize,
4503 wxSP_ARROW_KEYS, 0, 100, g_iDashCOGDamp);
4504 itemFlexGridSizer04->Add(m_pSpinCOGDamp, 0, wxALIGN_RIGHT | wxALL, 0);
4506 wxStaticText *itemStaticText12 =
new wxStaticText(
4507 itemPanelNotebook02, wxID_ANY, _(
"Local Time Offset From UTC:"),
4508 wxDefaultPosition, wxDefaultSize, 0);
4509 itemFlexGridSizer04->Add(itemStaticText12, 0, wxEXPAND | wxALL, border_size);
4510 wxString m_UTCOffsetChoices[] = {
4511 _T(
"-12:00" ), _T(
"-11:30" ), _T(
"-11:00" ), _T(
"-10:30" ),
4512 _T(
"-10:00" ), _T(
"-09:30" ), _T(
"-09:00" ), _T(
"-08:30" ),
4513 _T(
"-08:00" ), _T(
"-07:30" ), _T(
"-07:00" ), _T(
"-06:30" ),
4514 _T(
"-06:00" ), _T(
"-05:30" ), _T(
"-05:00" ), _T(
"-04:30" ),
4515 _T(
"-04:00" ), _T(
"-03:30" ), _T(
"-03:00" ), _T(
"-02:30" ),
4516 _T(
"-02:00" ), _T(
"-01:30" ), _T(
"-01:00" ), _T(
"-00:30" ),
4517 _T(
" 00:00" ), _T(
" 00:30" ), _T(
" 01:00" ), _T(
" 01:30" ),
4518 _T(
" 02:00" ), _T(
" 02:30" ), _T(
" 03:00" ), _T(
" 03:30" ),
4519 _T(
" 04:00" ), _T(
" 04:30" ), _T(
" 05:00" ), _T(
" 05:30" ),
4520 _T(
" 06:00" ), _T(
" 06:30" ), _T(
" 07:00" ), _T(
" 07:30" ),
4521 _T(
" 08:00" ), _T(
" 08:30" ), _T(
" 09:00" ), _T(
" 09:30" ),
4522 _T(
" 10:00" ), _T(
" 10:30" ), _T(
" 11:00" ), _T(
" 11:30" ),
4524 int m_UTCOffsetNChoices =
sizeof(m_UTCOffsetChoices) /
sizeof(wxString);
4525 m_pChoiceUTCOffset =
4526 new wxChoice(itemPanelNotebook02, wxID_ANY, wxDefaultPosition,
4527 wxDefaultSize, m_UTCOffsetNChoices, m_UTCOffsetChoices, 0);
4528 m_pChoiceUTCOffset->SetSelection(g_iUTCOffset + 24);
4529 itemFlexGridSizer04->Add(m_pChoiceUTCOffset, 0, wxALIGN_RIGHT | wxALL, 0);
4531 wxStaticText *itemStaticText09 =
4532 new wxStaticText(itemPanelNotebook02, wxID_ANY, _(
"Boat speed units:"),
4533 wxDefaultPosition, wxDefaultSize, 0);
4534 itemFlexGridSizer04->Add(itemStaticText09, 0, wxEXPAND | wxALL, border_size);
4535 wxString m_SpeedUnitChoices[] = {_(
"Honor OpenCPN settings"), _(
"Kts"),
4536 _(
"mph"), _(
"km/h"), _(
"m/s")};
4537 int m_SpeedUnitNChoices =
sizeof(m_SpeedUnitChoices) /
sizeof(wxString);
4538 wxSize szSpeedUnit = wxDefaultSize;
4539 m_pChoiceSpeedUnit =
4540 new wxChoice(itemPanelNotebook02, wxID_ANY, wxDefaultPosition,
4541 szSpeedUnit, m_SpeedUnitNChoices, m_SpeedUnitChoices, 0);
4542 for (
auto const &iUnit : m_SpeedUnitChoices) {
4543 szSpeedUnit.IncTo(m_pChoiceSpeedUnit->GetTextExtent(iUnit));
4545 m_pChoiceSpeedUnit->SetSize(szSpeedUnit);
4546 m_pChoiceSpeedUnit->SetSelection(g_iDashSpeedUnit + 1);
4547 itemFlexGridSizer04->Add(m_pChoiceSpeedUnit, 0, wxALIGN_RIGHT | wxALL, 0);
4549 wxStaticText *itemStaticTextDepthU =
4550 new wxStaticText(itemPanelNotebook02, wxID_ANY, _(
"Depth units:"),
4551 wxDefaultPosition, wxDefaultSize, 0);
4552 itemFlexGridSizer04->Add(itemStaticTextDepthU, 0, wxEXPAND | wxALL,
4554 wxString m_DepthUnitChoices[] = {_(
"Meters"), _(
"Feet"), _(
"Fathoms"),
4555 _(
"Inches"), _(
"Centimeters")};
4556 int m_DepthUnitNChoices =
sizeof(m_DepthUnitChoices) /
sizeof(wxString);
4557 wxSize szDepthUnit = wxDefaultSize;
4558 m_pChoiceDepthUnit =
4559 new wxChoice(itemPanelNotebook02, wxID_ANY, wxDefaultPosition,
4560 szDepthUnit, m_DepthUnitNChoices, m_DepthUnitChoices, 0);
4561 for (
auto const &iUnit : m_DepthUnitChoices) {
4562 szDepthUnit.IncTo(m_pChoiceDepthUnit->GetTextExtent(iUnit));
4564 m_pChoiceDepthUnit->SetSize(szDepthUnit);
4565 m_pChoiceDepthUnit->SetSelection(g_iDashDepthUnit - 3);
4566 itemFlexGridSizer04->Add(m_pChoiceDepthUnit, 0, wxALIGN_RIGHT | wxALL, 0);
4567 wxString dMess = wxString::Format(_(
"Depth Offset (%s):"),
4568 m_DepthUnitChoices[g_iDashDepthUnit - 3]);
4569 wxStaticText *itemStaticDepthO =
4570 new wxStaticText(itemPanelNotebook02, wxID_ANY, dMess, wxDefaultPosition,
4573 switch (g_iDashDepthUnit - 3) {
4575 DepthOffset = g_dDashDBTOffset * 3.2808399;
4578 DepthOffset = g_dDashDBTOffset * 0.54680665;
4581 DepthOffset = g_dDashDBTOffset * 39.3700787;
4584 DepthOffset = g_dDashDBTOffset * 100;
4587 DepthOffset = g_dDashDBTOffset;
4589 itemFlexGridSizer04->Add(itemStaticDepthO, 0, wxEXPAND | wxALL, border_size);
4590 m_pSpinDBTOffset =
new wxSpinCtrlDouble(
4591 itemPanelNotebook02, wxID_ANY, wxEmptyString, wxDefaultPosition,
4592 wxDefaultSize, wxSP_ARROW_KEYS, -100, 100, DepthOffset, 0.1);
4593 itemFlexGridSizer04->Add(m_pSpinDBTOffset, 0, wxALIGN_RIGHT | wxALL, 0);
4595 wxStaticText *itemStaticText0b =
4596 new wxStaticText(itemPanelNotebook02, wxID_ANY, _(
"Distance units:"),
4597 wxDefaultPosition, wxDefaultSize, 0);
4598 itemFlexGridSizer04->Add(itemStaticText0b, 0, wxEXPAND | wxALL, border_size);
4599 wxString m_DistanceUnitChoices[] = {_(
"Honor OpenCPN settings"),
4600 _(
"Nautical miles"), _(
"Statute miles"),
4601 _(
"Kilometers"), _(
"Meters")};
4602 wxSize szDistanceUnit = wxDefaultSize;
4603 int m_DistanceUnitNChoices =
sizeof(m_DistanceUnitChoices) /
sizeof(wxString);
4604 m_pChoiceDistanceUnit =
new wxChoice(
4605 itemPanelNotebook02, wxID_ANY, wxDefaultPosition, szDistanceUnit,
4606 m_DistanceUnitNChoices, m_DistanceUnitChoices, 0);
4607 for (
auto const &iUnit : m_DistanceUnitChoices) {
4608 szDistanceUnit.IncTo(m_pChoiceDistanceUnit->GetTextExtent(iUnit));
4610 m_pChoiceDistanceUnit->SetSize(szDistanceUnit);
4611 m_pChoiceDistanceUnit->SetSelection(g_iDashDistanceUnit + 1);
4612 itemFlexGridSizer04->Add(m_pChoiceDistanceUnit, 0, wxALIGN_RIGHT | wxALL, 0);
4614 wxStaticText *itemStaticText0a =
4615 new wxStaticText(itemPanelNotebook02, wxID_ANY, _(
"Wind speed units:"),
4616 wxDefaultPosition, wxDefaultSize, 0);
4617 itemFlexGridSizer04->Add(itemStaticText0a, 0, wxEXPAND | wxALL, border_size);
4618 wxString m_WSpeedUnitChoices[] = {_(
"Kts"), _(
"mph"), _(
"km/h"), _(
"m/s")};
4619 int m_WSpeedUnitNChoices =
sizeof(m_WSpeedUnitChoices) /
sizeof(wxString);
4620 wxSize szWSpeedUnit = wxDefaultSize;
4621 m_pChoiceWindSpeedUnit =
4622 new wxChoice(itemPanelNotebook02, wxID_ANY, wxDefaultPosition,
4623 szWSpeedUnit, m_WSpeedUnitNChoices, m_WSpeedUnitChoices, 0);
4624 for (
auto const &iUnit : m_WSpeedUnitChoices) {
4625 szWSpeedUnit.IncTo(m_pChoiceWindSpeedUnit->GetTextExtent(iUnit));
4627 m_pChoiceWindSpeedUnit->SetSize(szWSpeedUnit);
4628 m_pChoiceWindSpeedUnit->SetSelection(g_iDashWindSpeedUnit);
4629 itemFlexGridSizer04->Add(m_pChoiceWindSpeedUnit, 0, wxALIGN_RIGHT | wxALL, 0);
4631 wxStaticText *itemStaticText0c =
4632 new wxStaticText(itemPanelNotebook02, wxID_ANY, _(
"Temperature units:"),
4633 wxDefaultPosition, wxDefaultSize, 0);
4634 itemFlexGridSizer04->Add(itemStaticText0c, 0, wxEXPAND | wxALL, border_size);
4635 wxString m_TempUnitChoices[] = {_(
"Celsius"), _(
"Fahrenheit"), _(
"Kelvin")};
4636 int m_TempUnitNChoices =
sizeof(m_TempUnitChoices) /
sizeof(wxString);
4637 wxSize szTempUnit = wxDefaultSize;
4639 new wxChoice(itemPanelNotebook02, wxID_ANY, wxDefaultPosition, szTempUnit,
4640 m_TempUnitNChoices, m_TempUnitChoices, 0);
4641 for (
auto const &iUnit : m_TempUnitChoices) {
4642 szTempUnit.IncTo(m_pChoiceTempUnit->GetTextExtent(iUnit));
4644 m_pChoiceTempUnit->SetSize(szTempUnit);
4645 m_pChoiceTempUnit->SetSelection(g_iDashTempUnit);
4646 itemFlexGridSizer04->Add(m_pChoiceTempUnit, 0, wxALIGN_RIGHT | wxALL, 0);
4648 m_pUseTrueWinddata =
new wxCheckBox(itemPanelNotebook02, wxID_ANY,
4649 _(
"Use N2K & SignalK true wind data over "
4650 "ground.\n(Instead of through water)"));
4651 m_pUseTrueWinddata->SetValue(g_bDBtrueWindGround);
4652 itemFlexGridSizer04->Add(m_pUseTrueWinddata, 1, wxALIGN_LEFT, border_size);
4655 for (
size_t i = 0; i < m_Config.GetCount(); i++) {
4656 m_pListCtrlDashboards->InsertItem(i, 0);
4658 m_pListCtrlDashboards->SetItemData(i, i);
4660 m_pListCtrlDashboards->SetColumnWidth(0, wxLIST_AUTOSIZE);
4662 m_pListCtrlDashboards->SetItemState(0, wxLIST_STATE_SELECTED,
4663 wxLIST_STATE_SELECTED);
4666 UpdateDashboardButtonsState();
4667 UpdateButtonsState();
4674 SetMaxSize(wxSize(display_width, display_height));
4676 wxSize canvas_size = GetOCPNCanvasWindow()->GetSize();
4677 if (display_height < 600) {
4678 if (g_dashPrefWidth > 0 && g_dashPrefHeight > 0)
4679 SetSize(wxSize(g_dashPrefWidth, g_dashPrefHeight));
4681 SetSize(wxSize(canvas_size.x * 8 / 10, canvas_size.y * 8 / 10));
4683 if (g_dashPrefWidth > 0 && g_dashPrefHeight > 0)
4684 SetSize(wxSize(g_dashPrefWidth, g_dashPrefHeight));
4686 SetSize(wxSize(canvas_size.x * 3 / 4, canvas_size.y * 8 / 10));
4693void DashboardPreferencesDialog::RecalculateSize(
void) {
4694#ifdef __OCPN__ANDROID__
4696 esize.x = GetCharWidth() * 110;
4697 esize.y = GetCharHeight() * 40;
4699 wxSize dsize = GetOCPNCanvasWindow()->GetClientSize();
4700 esize.y = wxMin(esize.y, dsize.y - (3 * GetCharHeight()));
4701 esize.x = wxMin(esize.x, dsize.x - (3 * GetCharHeight()));
4708void DashboardPreferencesDialog::OnCloseDialog(wxCloseEvent &event) {
4709 g_dashPrefWidth = GetSize().x;
4710 g_dashPrefHeight = GetSize().y;
4711 SaveDashboardConfig();
4715void DashboardPreferencesDialog::SaveDashboardConfig() {
4716 g_iDashSpeedMax = m_pSpinSpeedMax->GetValue();
4717 g_iDashCOGDamp = m_pSpinCOGDamp->GetValue();
4718 g_iDashSOGDamp = m_pSpinSOGDamp->GetValue();
4719 g_iUTCOffset = m_pChoiceUTCOffset->GetSelection() - 24;
4720 g_iDashSpeedUnit = m_pChoiceSpeedUnit->GetSelection() - 1;
4721 double DashDBTOffset = m_pSpinDBTOffset->GetValue();
4722 switch (g_iDashDepthUnit - 3) {
4724 g_dDashDBTOffset = DashDBTOffset / 3.2808399;
4727 g_dDashDBTOffset = DashDBTOffset / 0.54680665;
4730 g_dDashDBTOffset = DashDBTOffset / 39.3700787;
4733 g_dDashDBTOffset = DashDBTOffset / 100;
4736 g_dDashDBTOffset = DashDBTOffset;
4738 g_iDashDepthUnit = m_pChoiceDepthUnit->GetSelection() + 3;
4739 g_iDashDistanceUnit = m_pChoiceDistanceUnit->GetSelection() - 1;
4740 g_iDashWindSpeedUnit = m_pChoiceWindSpeedUnit->GetSelection();
4741 g_bDBtrueWindGround = m_pUseTrueWinddata->GetValue();
4742 g_iDashTempUnit = m_pChoiceTempUnit->GetSelection();
4745 cont->m_bIsVisible = m_pCheckBoxIsVisible->IsChecked();
4746 cont->m_sCaption = m_pTextCtrlCaption->GetValue();
4747 cont->m_sOrientation =
4748 m_pChoiceOrientation->GetSelection() == 0 ? _T(
"V") : _T(
"H");
4749 cont->m_aInstrumentList.Clear();
4750 for (
int i = 0; i < m_pListCtrlInstruments->GetItemCount(); i++)
4751 cont->m_aInstrumentList.Add((
int)m_pListCtrlInstruments->GetItemData(i));
4755void DashboardPreferencesDialog::OnDashboardSelected(wxListEvent &event) {
4757 SaveDashboardConfig();
4758 UpdateDashboardButtonsState();
4761void DashboardPreferencesDialog::UpdateDashboardButtonsState() {
4763 item = m_pListCtrlDashboards->GetNextItem(item, wxLIST_NEXT_ALL,
4764 wxLIST_STATE_SELECTED);
4765 bool enable = (item != -1);
4769 bool delete_enable = enable;
4771 int sel = m_pListCtrlDashboards->GetItemData(item);
4774 if (dash_sel == GetParent()) delete_enable =
false;
4776 m_pButtonDeleteDashboard->Enable(delete_enable);
4778 m_pPanelDashboard->Enable(enable);
4781 curSel = m_pListCtrlDashboards->GetItemData(item);
4783 m_pCheckBoxIsVisible->SetValue(cont->m_bIsVisible);
4784 m_pTextCtrlCaption->SetValue(cont->m_sCaption);
4785 m_pChoiceOrientation->SetSelection(cont->m_sOrientation == _T(
"V") ? 0 : 1);
4786 m_pListCtrlInstruments->DeleteAllItems();
4787 for (
size_t i = 0; i < cont->m_aInstrumentList.GetCount(); i++) {
4789 getListItemForInstrument(item, cont->m_aInstrumentList.Item(i));
4790 item.SetId(m_pListCtrlInstruments->GetItemCount());
4791 m_pListCtrlInstruments->InsertItem(item);
4794 m_pListCtrlInstruments->SetColumnWidth(0, wxLIST_AUTOSIZE);
4797 m_pCheckBoxIsVisible->SetValue(
false);
4798 m_pTextCtrlCaption->SetValue(_T(
""));
4799 m_pChoiceOrientation->SetSelection(0);
4800 m_pListCtrlInstruments->DeleteAllItems();
4805void DashboardPreferencesDialog::OnDashboarddefaultFont(wxCommandEvent &event) {
4806 m_pFontPickerTitle->SetSelectedFont(
4807 wxFont(10, wxFONTFAMILY_SWISS, wxFONTSTYLE_ITALIC, wxFONTWEIGHT_NORMAL));
4808 m_pFontPickerTitle->SetSelectedColour(wxColour(0, 0, 0));
4809 m_pFontPickerData->SetSelectedFont(
4810 wxFont(14, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));
4811 m_pFontPickerData->SetSelectedColour(wxColour(0, 0, 0));
4812 m_pFontPickerLabel->SetSelectedFont(
4813 wxFont(8, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));
4814 m_pFontPickerLabel->SetSelectedColour(wxColour(0, 0, 0));
4815 m_pFontPickerSmall->SetSelectedFont(
4816 wxFont(8, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));
4817 m_pFontPickerSmall->SetSelectedColour(wxColour(0, 0, 0));
4818 double scaler = 1.0;
4819 if (OCPN_GetWinDIPScaleFactor() < 1.0)
4820 scaler = 1.0 + OCPN_GetWinDIPScaleFactor() / 4;
4821 scaler = wxMax(1.0, scaler);
4823 g_USFontTitle = *(m_pFontPickerTitle->GetFontData());
4824 g_FontTitle = *g_pUSFontTitle;
4825 g_FontTitle.SetChosenFont(g_pUSFontTitle->GetChosenFont().Scaled(scaler));
4826 g_FontTitle.SetColour(g_pUSFontTitle->GetColour());
4827 g_USFontTitle = *g_pUSFontTitle;
4829 g_USFontData = *(m_pFontPickerData->GetFontData());
4830 g_FontData = *g_pUSFontData;
4831 g_FontData.SetChosenFont(g_pUSFontData->GetChosenFont().Scaled(scaler));
4832 g_FontData.SetColour(g_pUSFontData->GetColour());
4833 g_USFontData = *g_pUSFontData;
4835 g_USFontLabel = *(m_pFontPickerLabel->GetFontData());
4836 g_FontLabel = *g_pUSFontLabel;
4837 g_FontLabel.SetChosenFont(g_pUSFontLabel->GetChosenFont().Scaled(scaler));
4838 g_FontLabel.SetColour(g_pUSFontLabel->GetColour());
4839 g_USFontLabel = *g_pUSFontLabel;
4841 g_USFontSmall = *(m_pFontPickerSmall->GetFontData());
4842 g_FontSmall = *g_pUSFontSmall;
4843 g_FontSmall.SetChosenFont(g_pUSFontSmall->GetChosenFont().Scaled(scaler));
4844 g_FontSmall.SetColour(g_pUSFontSmall->GetColour());
4845 g_USFontSmall = *g_pUSFontSmall;
4848void DashboardPreferencesDialog::OnDashboardAdd(wxCommandEvent &event) {
4849 int idx = m_pListCtrlDashboards->GetItemCount();
4850 m_pListCtrlDashboards->InsertItem(idx, 0);
4852 m_pListCtrlDashboards->SetItemData(idx, m_Config.GetCount());
4854 wxArrayOfInstrumentProperties Property;
4856 NULL, MakeName(), _(
"Dashboard"), _T(
"V"), ar, Property);
4857 dwc->m_bIsVisible =
true;
4861void DashboardPreferencesDialog::OnDashboardDelete(wxCommandEvent &event) {
4863 itemID = m_pListCtrlDashboards->GetNextItem(itemID, wxLIST_NEXT_ALL,
4864 wxLIST_STATE_SELECTED);
4866 int idx = m_pListCtrlDashboards->GetItemData(itemID);
4867 m_pListCtrlDashboards->DeleteItem(itemID);
4868 m_Config.Item(idx)->m_bIsDeleted =
true;
4869 UpdateDashboardButtonsState();
4872void DashboardPreferencesDialog::OnInstrumentSelected(wxListEvent &event) {
4873 UpdateButtonsState();
4876void DashboardPreferencesDialog::UpdateButtonsState() {
4878 item = m_pListCtrlInstruments->GetNextItem(item, wxLIST_NEXT_ALL,
4879 wxLIST_STATE_SELECTED);
4880 bool enable = (item != -1);
4882 m_pButtonDelete->Enable(enable);
4883 m_pButtonEdit->Enable(enable);
4884 m_pButtonUp->Enable(item > 0);
4885 m_pButtonDown->Enable(item != -1 &&
4886 item < m_pListCtrlInstruments->GetItemCount() - 1);
4889void DashboardPreferencesDialog::OnInstrumentAdd(wxCommandEvent &event) {
4892#ifdef __OCPN__ANDROID__
4897 esize.x = GetCharWidth() * 110;
4898 esize.y = GetCharHeight() * 40;
4900 wxSize dsize = GetOCPNCanvasWindow()->GetClientSize();
4901 esize.y = wxMin(esize.y, dsize.y - (3 * GetCharHeight()));
4902 esize.x = wxMin(esize.x, dsize.x - (3 * GetCharHeight()));
4903 pdlg.SetSize(esize);
4905 pdlg.CentreOnScreen();
4908 if (pdlg.GetReturnCode() == wxID_OK) {
4910 getListItemForInstrument(item, pdlg.GetInstrumentAdded());
4911 item.SetId(m_pListCtrlInstruments->GetItemCount());
4912 m_pListCtrlInstruments->InsertItem(item);
4913 m_pListCtrlInstruments->SetColumnWidth(0, wxLIST_AUTOSIZE);
4914 UpdateButtonsState();
4918void DashboardPreferencesDialog::OnInstrumentDelete(wxCommandEvent &event) {
4919 long itemIDWindow = -1;
4920 itemIDWindow = m_pListCtrlDashboards->GetNextItem(
4921 itemIDWindow, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
4923 itemID = m_pListCtrlInstruments->GetNextItem(itemID, wxLIST_NEXT_ALL,
4924 wxLIST_STATE_SELECTED);
4926 m_Config.Item(m_pListCtrlDashboards->GetItemData(itemIDWindow));
4930 for (
unsigned int i = 0; i < (cont->m_aInstrumentPropertyList.GetCount());
4932 Inst = cont->m_aInstrumentPropertyList.Item(i);
4933 if (Inst->m_aInstrument ==
4934 (
int)m_pListCtrlInstruments->GetItemData(itemID) &&
4935 Inst->m_Listplace == itemID) {
4936 cont->m_aInstrumentPropertyList.Remove(Inst);
4940 if (Inst->m_Listplace > itemID) Inst->m_Listplace--;
4944 m_pListCtrlInstruments->DeleteItem(itemID);
4946 cont->m_pDashboardWindow->SetInstrumentList(
4947 cont->m_aInstrumentList, &(cont->m_aInstrumentPropertyList));
4950 UpdateButtonsState();
4953inline void GetFontData(
OCPNFontButton *FontButton, wxFontData &UnScaledFont,
4954 wxFontData &ScaledFont,
double scaler) {
4955 UnScaledFont = *(FontButton->GetFontData());
4956 ScaledFont = UnScaledFont;
4957 ScaledFont.SetChosenFont(UnScaledFont.GetChosenFont().Scaled(scaler));
4960void DashboardPreferencesDialog::OnInstrumentEdit(wxCommandEvent &event) {
4963 long itemIDWindow = -1;
4964 itemIDWindow = m_pListCtrlDashboards->GetNextItem(
4965 itemIDWindow, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
4967 itemID = m_pListCtrlInstruments->GetNextItem(itemID, wxLIST_NEXT_ALL,
4968 wxLIST_STATE_SELECTED);
4974 m_Config.Item(m_pListCtrlDashboards->GetItemData(itemIDWindow));
4977 for (
unsigned int i = 0; i < (cont->m_aInstrumentPropertyList.GetCount());
4979 Inst = cont->m_aInstrumentPropertyList.Item(
4981 if (Inst->m_aInstrument == (
int)m_pListCtrlInstruments->GetItemData(
4984 if (Inst->m_Listplace == itemID)
break;
4991 cont->m_aInstrumentPropertyList.Add(Inst);
4995 bool DefaultFont =
false;
4996 if (Edit->ShowModal() == wxID_OK) {
4998 double scaler = 1.0;
4999 if (OCPN_GetWinDIPScaleFactor() < 1.0)
5000 scaler = 1.0 + OCPN_GetWinDIPScaleFactor() / 4;
5001 scaler = wxMax(1.0, scaler);
5002 if (Edit->m_fontPicker2->GetFont().Scaled(scaler) !=
5003 g_FontTitle.GetChosenFont() ||
5004 Edit->m_fontPicker2->GetSelectedColour() != g_FontTitle.GetColour())
5005 DefaultFont =
false;
5006 if (Edit->m_fontPicker4->GetFont().Scaled(scaler) !=
5007 g_FontData.GetChosenFont() ||
5008 Edit->m_fontPicker4->GetSelectedColour() != g_FontData.GetColour())
5009 DefaultFont =
false;
5010 if (Edit->m_fontPicker5->GetFont().Scaled(scaler) !=
5011 g_FontLabel.GetChosenFont() ||
5012 Edit->m_fontPicker5->GetSelectedColour() != g_FontLabel.GetColour())
5013 DefaultFont =
false;
5014 if (Edit->m_fontPicker6->GetFont().Scaled(scaler) !=
5015 g_FontSmall.GetChosenFont() ||
5016 Edit->m_fontPicker6->GetSelectedColour() != g_FontSmall.GetColour())
5017 DefaultFont =
false;
5019 GetGlobalColor(_T(
"DASHL"), &dummy);
5020 if (Edit->m_colourPicker1->GetColour() != dummy) DefaultFont =
false;
5021 GetGlobalColor(_T(
"DASHB"), &dummy);
5022 if (Edit->m_colourPicker2->GetColour() != dummy) DefaultFont =
false;
5023 GetGlobalColor(_T(
"DASHN"), &dummy);
5024 if (Edit->m_colourPicker3->GetColour() != dummy) DefaultFont =
false;
5025 GetGlobalColor(_T(
"BLUE3"), &dummy);
5026 if (Edit->m_colourPicker4->GetColour() != dummy) DefaultFont =
false;
5028 cont->m_aInstrumentPropertyList.Remove(Inst);
5030 GetFontData(Edit->m_fontPicker2, Inst->m_USTitleFont, Inst->m_TitleFont,
5032 GetFontData(Edit->m_fontPicker4, Inst->m_USDataFont, Inst->m_DataFont,
5034 GetFontData(Edit->m_fontPicker5, Inst->m_USLabelFont, Inst->m_LabelFont,
5036 GetFontData(Edit->m_fontPicker6, Inst->m_USSmallFont, Inst->m_SmallFont,
5038 Inst->m_DataBackgroundColour = Edit->m_colourPicker2->GetColour();
5039 Inst->m_TitleBackgroundColour = Edit->m_colourPicker1->GetColour();
5040 Inst->m_Arrow_First_Colour = Edit->m_colourPicker3->GetColour();
5041 Inst->m_Arrow_Second_Colour = Edit->m_colourPicker4->GetColour();
5045 if (cont->m_pDashboardWindow) {
5046 cont->m_pDashboardWindow->SetInstrumentList(
5047 cont->m_aInstrumentList, &(cont->m_aInstrumentPropertyList));
5049 if (DefaultFont)
delete Inst;
5052void DashboardPreferencesDialog::OnInstrumentUp(wxCommandEvent &event) {
5053 long itemIDWindow = -1;
5054 itemIDWindow = m_pListCtrlDashboards->GetNextItem(
5055 itemIDWindow, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
5057 itemID = m_pListCtrlInstruments->GetNextItem(itemID, wxLIST_NEXT_ALL,
5058 wxLIST_STATE_SELECTED);
5061 item.SetMask(wxLIST_MASK_TEXT | wxLIST_MASK_IMAGE | wxLIST_MASK_DATA);
5062 m_pListCtrlInstruments->GetItem(item);
5063 item.SetId(itemID - 1);
5067 m_Config.Item(m_pListCtrlDashboards->GetItemData(itemIDWindow));
5070 for (
unsigned int i = 0; i < (cont->m_aInstrumentPropertyList.GetCount());
5072 Inst = cont->m_aInstrumentPropertyList.Item(i);
5073 if (Inst->m_Listplace == (itemID - 1)) Inst->m_Listplace = itemID;
5074 if (Inst->m_aInstrument ==
5075 (
int)m_pListCtrlInstruments->GetItemData(itemID) &&
5076 Inst->m_Listplace == itemID) {
5077 cont->m_aInstrumentPropertyList.Item(i)->m_Listplace = itemID - 1;
5081 m_pListCtrlInstruments->DeleteItem(itemID);
5082 m_pListCtrlInstruments->InsertItem(item);
5083 for (
int i = 0; i < m_pListCtrlInstruments->GetItemCount(); i++)
5084 m_pListCtrlInstruments->SetItemState(i, 0, wxLIST_STATE_SELECTED);
5086 m_pListCtrlInstruments->SetItemState(itemID - 1, wxLIST_STATE_SELECTED,
5087 wxLIST_STATE_SELECTED);
5089 UpdateButtonsState();
5092void DashboardPreferencesDialog::OnInstrumentDown(wxCommandEvent &event) {
5093 long itemIDWindow = -1;
5094 itemIDWindow = m_pListCtrlDashboards->GetNextItem(
5095 itemIDWindow, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
5097 itemID = m_pListCtrlInstruments->GetNextItem(itemID, wxLIST_NEXT_ALL,
5098 wxLIST_STATE_SELECTED);
5102 item.SetMask(wxLIST_MASK_TEXT | wxLIST_MASK_IMAGE | wxLIST_MASK_DATA);
5103 m_pListCtrlInstruments->GetItem(item);
5104 item.SetId(itemID + 1);
5108 m_Config.Item(m_pListCtrlDashboards->GetItemData(itemIDWindow));
5111 for (
unsigned int i = 0; i < (cont->m_aInstrumentPropertyList.GetCount());
5113 Inst = cont->m_aInstrumentPropertyList.Item(i);
5114 if (Inst->m_Listplace == (itemID + 1) &&
5115 Inst->m_aInstrument !=
5116 (int)m_pListCtrlInstruments->GetItemData(itemID))
5117 Inst->m_Listplace = itemID;
5118 if (Inst->m_aInstrument ==
5119 (
int)m_pListCtrlInstruments->GetItemData(itemID) &&
5120 Inst->m_Listplace == itemID) {
5121 cont->m_aInstrumentPropertyList.Item(i)->m_Listplace = itemID + 1;
5126 m_pListCtrlInstruments->DeleteItem(itemID);
5127 m_pListCtrlInstruments->InsertItem(item);
5128 for (
int i = 0; i < m_pListCtrlInstruments->GetItemCount(); i++)
5129 m_pListCtrlInstruments->SetItemState(i, 0, wxLIST_STATE_SELECTED);
5131 m_pListCtrlInstruments->SetItemState(itemID + 1, wxLIST_STATE_SELECTED,
5132 wxLIST_STATE_SELECTED);
5134 UpdateButtonsState();
5143AddInstrumentDlg::AddInstrumentDlg(wxWindow *pparent, wxWindowID
id)
5144 : wxDialog(pparent, id, _(
"Add instrument"), wxDefaultPosition,
5145 wxDefaultSize, wxDEFAULT_DIALOG_STYLE) {
5146 wxBoxSizer *itemBoxSizer01 =
new wxBoxSizer(wxVERTICAL);
5147 SetSizer(itemBoxSizer01);
5148 wxStaticText *itemStaticText01 =
5149 new wxStaticText(
this, wxID_ANY, _(
"Select instrument to add:"),
5150 wxDefaultPosition, wxDefaultSize, 0);
5151 itemBoxSizer01->Add(itemStaticText01, 0, wxEXPAND | wxALL, 5);
5153 int instImageRefSize = 20 * GetOCPNGUIToolScaleFactor_PlugIn();
5155 wxImageList *imglist =
5156 new wxImageList(instImageRefSize, instImageRefSize,
true, 2);
5158 wxImage inst1 = wxBitmap(*_img_instrument).ConvertToImage();
5160 inst1.Scale(instImageRefSize, instImageRefSize, wxIMAGE_QUALITY_HIGH);
5161 imglist->Add(wxBitmap(inst1s));
5163 wxImage dial1 = wxBitmap(*_img_dial).ConvertToImage();
5165 dial1.Scale(instImageRefSize, instImageRefSize, wxIMAGE_QUALITY_HIGH);
5166 imglist->Add(wxBitmap(dial1s));
5168 wxSize dsize = GetOCPNCanvasWindow()->GetClientSize();
5169 int vsize = dsize.y * 50 / 100;
5171#ifdef __OCPN__ANDROID__
5173 wxDisplaySize(&dw, &dh);
5174 vsize = dh * 50 / 100;
5177 m_pListCtrlInstruments =
new wxListCtrl(
5178 this, wxID_ANY, wxDefaultPosition, wxSize(-1, vsize ),
5179 wxLC_REPORT | wxLC_NO_HEADER | wxLC_SINGLE_SEL | wxLC_SORT_ASCENDING);
5180 itemBoxSizer01->Add(m_pListCtrlInstruments, 0, wxEXPAND | wxALL, 5);
5181 m_pListCtrlInstruments->AssignImageList(imglist, wxIMAGE_LIST_SMALL);
5182 m_pListCtrlInstruments->InsertColumn(0, _(
"Instruments"));
5185 m_pListCtrlInstruments->SetFont(*pF);
5187#ifdef __OCPN__ANDROID__
5188 m_pListCtrlInstruments->GetHandle()->setStyleSheet(qtStyleSheet);
5192 wxStdDialogButtonSizer *DialogButtonSizer =
5193 CreateStdDialogButtonSizer(wxOK | wxCANCEL);
5194 itemBoxSizer01->Add(DialogButtonSizer, 0, wxALIGN_RIGHT | wxALL, 5);
5197 for (
unsigned int i = ID_DBP_I_POS; i < ID_DBP_LAST_ENTRY;
5201 if (IsObsolete(i))
continue;
5202 getListItemForInstrument(item, i);
5204 m_pListCtrlInstruments->InsertItem(item);
5208 m_pListCtrlInstruments->SetColumnWidth(0, wxLIST_AUTOSIZE);
5209 m_pListCtrlInstruments->SetItemState(0, wxLIST_STATE_SELECTED,
5210 wxLIST_STATE_SELECTED);
5214unsigned int AddInstrumentDlg::GetInstrumentAdded() {
5216 itemID = m_pListCtrlInstruments->GetNextItem(itemID, wxLIST_NEXT_ALL,
5217 wxLIST_STATE_SELECTED);
5219 return (
int)m_pListCtrlInstruments->GetItemData(itemID);
5229DashboardWindow::DashboardWindow(wxWindow *pparent, wxWindowID
id,
5232 : wxWindow(pparent, id, wxDefaultPosition, wxDefaultSize, 0) {
5238 m_Container = mycont;
5241 itemBoxSizer =
new wxBoxSizer(orient);
5242 SetSizer(itemBoxSizer);
5243 Connect(wxEVT_SIZE, wxSizeEventHandler(DashboardWindow::OnSize), NULL,
this);
5244 Connect(wxEVT_CONTEXT_MENU,
5245 wxContextMenuEventHandler(DashboardWindow::OnContextMenu), NULL,
5247 Connect(wxEVT_COMMAND_MENU_SELECTED,
5248 wxCommandEventHandler(DashboardWindow::OnContextMenuSelect), NULL,
5251#ifdef __OCPN__ANDROID__
5252 Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(DashboardWindow::OnMouseEvent));
5253 Connect(wxEVT_LEFT_UP, wxMouseEventHandler(DashboardWindow::OnMouseEvent));
5254 Connect(wxEVT_MOTION, wxMouseEventHandler(DashboardWindow::OnMouseEvent));
5256 GetHandle()->setAttribute(Qt::WA_AcceptTouchEvents);
5257 GetHandle()->grabGesture(Qt::PinchGesture);
5258 GetHandle()->grabGesture(Qt::PanGesture);
5260 Connect(wxEVT_QT_PINCHGESTURE,
5265 wxEVT_QT_PANGESTURE,
5266 (wxObjectEventFunction)(wxEventFunction)&DashboardWindow::OnEvtPanGesture,
5272 m_binResize =
false;
5276DashboardWindow::~DashboardWindow() {
5277 for (
size_t i = 0; i < m_ArrayOfInstrument.GetCount(); i++) {
5283#ifdef __OCPN__ANDROID__
5284void DashboardWindow::OnEvtPinchGesture(wxQT_PinchGestureEvent &event) {
5285 float zoom_gain = 0.3;
5287 float total_zoom_val;
5289 if (event.GetScaleFactor() > 1)
5290 zoom_val = ((
event.GetScaleFactor() - 1.0) * zoom_gain) + 1.0;
5292 zoom_val = 1.0 - ((1.0 -
event.GetScaleFactor()) * zoom_gain);
5294 if (event.GetTotalScaleFactor() > 1)
5295 total_zoom_val = ((event.GetTotalScaleFactor() - 1.0) * zoom_gain) + 1.0;
5297 total_zoom_val = 1.0 - ((1.0 -
event.GetTotalScaleFactor()) * zoom_gain);
5299 wxAuiPaneInfo &pane = m_pauimgr->GetPane(
this);
5301 wxSize currentSize = wxSize(pane.floating_size.x, pane.floating_size.y);
5302 double aRatio = (double)currentSize.y / (
double)currentSize.x;
5304 wxSize par_size = GetOCPNCanvasWindow()->GetClientSize();
5305 wxPoint par_pos = wxPoint(pane.floating_pos.x, pane.floating_pos.y);
5307 switch (event.GetState()) {
5308 case GestureStarted:
5312 case GestureUpdated:
5313 currentSize.y *= zoom_val;
5314 currentSize.x *= zoom_val;
5316 if ((par_pos.y + currentSize.y) > par_size.y)
5317 currentSize.y = par_size.y - par_pos.y;
5319 if ((par_pos.x + currentSize.x) > par_size.x)
5320 currentSize.x = par_size.x - par_pos.x;
5323 currentSize.x = currentSize.y / aRatio;
5325 currentSize.x = wxMax(currentSize.x, 150);
5326 currentSize.y = wxMax(currentSize.y, 150);
5328 pane.FloatingSize(currentSize);
5329 m_pauimgr->Update();
5333 case GestureFinished: {
5334 if (itemBoxSizer->GetOrientation() == wxVERTICAL) {
5335 currentSize.y *= total_zoom_val;
5336 currentSize.x = currentSize.y / aRatio;
5338 currentSize.x *= total_zoom_val;
5339 currentSize.y = currentSize.x * aRatio;
5343 if ((par_pos.y + currentSize.y) > par_size.y)
5344 currentSize.y = par_size.y - par_pos.y;
5346 if ((par_pos.x + currentSize.x) > par_size.x)
5347 currentSize.x = par_size.x - par_pos.x;
5350 currentSize.x = wxMax(currentSize.x, 150);
5351 currentSize.y = wxMax(currentSize.y, 150);
5356 if (itemBoxSizer->GetOrientation() == wxVERTICAL) {
5358 for (
unsigned int i = 0; i < m_ArrayOfInstrument.size(); i++) {
5360 m_ArrayOfInstrument.Item(i)->m_pInstrument;
5362 inst->GetSize(itemBoxSizer->GetOrientation(), currentSize);
5366 currentSize.y = total_y;
5369 pane.FloatingSize(currentSize);
5372 for (
unsigned int i = 0; i < m_ArrayOfInstrument.size(); i++) {
5377 m_pauimgr->Update();
5380 m_binResize =
false;
5385 case GestureCanceled:
5387 m_binResize =
false;
5395void DashboardWindow::OnEvtPanGesture(wxQT_PanGestureEvent &event) {
5396 if (m_binPinch)
return;
5398 if (m_binResize)
return;
5400 int x =
event.GetOffset().x;
5401 int y =
event.GetOffset().y;
5403 int lx =
event.GetLastOffset().x;
5404 int ly =
event.GetLastOffset().y;
5409 switch (event.GetState()) {
5410 case GestureStarted:
5411 if (m_binPan)
break;
5416 case GestureUpdated:
5418 wxSize par_size = GetOCPNCanvasWindow()->GetClientSize();
5419 wxPoint par_pos_old = ClientToScreen(wxPoint(0, 0));
5421 wxPoint par_pos = par_pos_old;
5425 par_pos.x = wxMax(par_pos.x, 0);
5426 par_pos.y = wxMax(par_pos.y, 0);
5428 wxSize mySize = GetSize();
5430 if ((par_pos.y + mySize.y) > par_size.y)
5431 par_pos.y = par_size.y - mySize.y;
5433 if ((par_pos.x + mySize.x) > par_size.x)
5434 par_pos.x = par_size.x - mySize.x;
5436 wxAuiPaneInfo &pane = m_pauimgr->GetPane(
this);
5437 pane.FloatingPosition(par_pos).Float();
5438 m_pauimgr->Update();
5442 case GestureFinished:
5449 case GestureCanceled:
5458void DashboardWindow::OnMouseEvent(wxMouseEvent &event) {
5459 if (m_binPinch)
return;
5462 wxAuiPaneInfo &pane = m_pauimgr->GetPane(
this);
5463 wxSize currentSize = wxSize(pane.floating_size.x, pane.floating_size.y);
5464 double aRatio = (double)currentSize.y / (
double)currentSize.x;
5466 wxSize par_size = GetOCPNCanvasWindow()->GetClientSize();
5467 wxPoint par_pos = wxPoint(pane.floating_pos.x, pane.floating_pos.y);
5469 if (event.LeftDown()) {
5470 m_resizeStartPoint =
event.GetPosition();
5471 m_resizeStartSize = currentSize;
5472 m_binResize2 =
true;
5476 if (event.Dragging()) {
5477 wxPoint p =
event.GetPosition();
5479 wxSize dragSize = m_resizeStartSize;
5481 dragSize.y += p.y - m_resizeStartPoint.y;
5482 dragSize.x += p.x - m_resizeStartPoint.x;
5485 if ((par_pos.y + dragSize.y) > par_size.y)
5486 dragSize.y = par_size.y - par_pos.y;
5488 if ((par_pos.x + dragSize.x) > par_size.x)
5489 dragSize.x = par_size.x - par_pos.x;
5495 dragSize.x = wxMax(dragSize.x, 150);
5496 dragSize.y = wxMax(dragSize.y, 150);
5498 pane.FloatingSize(dragSize);
5499 m_pauimgr->Update();
5502 if (event.LeftUp()) {
5503 wxPoint p =
event.GetPosition();
5505 wxSize dragSize = m_resizeStartSize;
5507 dragSize.y += p.y - m_resizeStartPoint.y;
5508 dragSize.x += p.x - m_resizeStartPoint.x;
5511 if ((par_pos.y + dragSize.y) > par_size.y)
5512 dragSize.y = par_size.y - par_pos.y;
5514 if ((par_pos.x + dragSize.x) > par_size.x)
5515 dragSize.x = par_size.x - par_pos.x;
5518 dragSize.x = wxMax(dragSize.x, 150);
5519 dragSize.y = wxMax(dragSize.y, 150);
5526 pane.FloatingSize(dragSize);
5527 m_pauimgr->Update();
5529 m_binResize =
false;
5530 m_binResize2 =
false;
5537void DashboardWindow::OnSize(wxSizeEvent &event) {
5539 for (
unsigned int i = 0; i < m_ArrayOfInstrument.size(); i++) {
5542 inst->GetSize(itemBoxSizer->GetOrientation(), GetClientSize()));
5547 this->m_Container->m_best_size =
event.GetSize();
5550void DashboardWindow::OnContextMenu(wxContextMenuEvent &event) {
5551 wxMenu *contextMenu =
new wxMenu();
5558 new wxMenuItem(contextMenu, ID_DASH_PREFS, _(
"Preferences..."));
5559 item1->SetFont(*pf);
5560 contextMenu->Append(item1);
5563 new wxMenuItem(contextMenu, ID_DASH_RESIZE, _(
"Resize..."));
5564 item2->SetFont(*pf);
5565 contextMenu->Append(item2);
5569 wxAuiPaneInfo &pane = m_pauimgr->GetPane(
this);
5570 if (pane.IsOk() && pane.IsDocked()) {
5571 contextMenu->Append(ID_DASH_UNDOCK, _(
"Undock"));
5573 wxMenuItem *btnVertical =
5574 contextMenu->AppendRadioItem(ID_DASH_VERTICAL, _(
"Vertical"));
5575 btnVertical->Check(itemBoxSizer->GetOrientation() == wxVERTICAL);
5576 wxMenuItem *btnHorizontal =
5577 contextMenu->AppendRadioItem(ID_DASH_HORIZONTAL, _(
"Horizontal"));
5578 btnHorizontal->Check(itemBoxSizer->GetOrientation() == wxHORIZONTAL);
5579 contextMenu->AppendSeparator();
5581 m_plugin->PopulateContextMenu(contextMenu);
5583 contextMenu->AppendSeparator();
5584 contextMenu->Append(ID_DASH_PREFS, _(
"Preferences..."));
5588 PopupMenu(contextMenu);
5592void DashboardWindow::OnContextMenuSelect(wxCommandEvent &event) {
5593 if (event.GetId() < ID_DASH_PREFS) {
5594 if (m_plugin->GetDashboardWindowShownCount() > 1 || event.IsChecked())
5595 m_plugin->ShowDashboard(event.GetId() - 1, event.IsChecked());
5597 m_plugin->ShowDashboard(event.GetId() - 1,
true);
5599 SetToolbarItemState(m_plugin->GetToolbarItemId(),
5600 m_plugin->GetDashboardWindowShownCount() != 0);
5603 switch (event.GetId()) {
5604 case ID_DASH_PREFS: {
5606 wxPoint fp = m_pauimgr->GetPane(
this).floating_pos;
5607 m_plugin->ShowPreferencesDialog(
this);
5610 ChangePaneOrientation(GetSizerOrientation(),
true, fp.x, fp.y);
5613 case ID_DASH_RESIZE: {
5624 case ID_DASH_VERTICAL: {
5625 ChangePaneOrientation(wxVERTICAL,
true);
5626 m_Container->m_sOrientation = _T(
"V");
5629 case ID_DASH_HORIZONTAL: {
5630 ChangePaneOrientation(wxHORIZONTAL,
true);
5631 m_Container->m_sOrientation = _T(
"H");
5634 case ID_DASH_UNDOCK: {
5635 ChangePaneOrientation(GetSizerOrientation(),
true);
5639 m_plugin->SaveConfig();
5642void DashboardWindow::SetColorScheme(PI_ColorScheme cs) {
5646 wxColour col = g_BackgroundColor;
5648 if (!g_ForceBackgroundColor) GetGlobalColor(_T(
"DASHL"), &col);
5649 SetBackgroundColour(col);
5654void DashboardWindow::ChangePaneOrientation(
int orient,
bool updateAUImgr,
5656 m_pauimgr->DetachPane(
this);
5657 SetSizerOrientation(orient);
5658 bool vertical = orient == wxVERTICAL;
5660 wxSize sz = GetMinSize();
5662 m_Container->m_sName = MakeName();
5663 m_pauimgr->AddPane(
this, wxAuiPaneInfo()
5664 .Name(m_Container->m_sName)
5665 .Caption(m_Container->m_sCaption)
5666 .CaptionVisible(
true)
5667 .TopDockable(!vertical)
5668 .BottomDockable(!vertical)
5669 .LeftDockable(vertical)
5670 .RightDockable(vertical)
5674 .FloatingPosition(fpx, fpy)
5676 .Show(m_Container->m_bIsVisible));
5678#ifdef __OCPN__ANDROID__
5679 wxAuiPaneInfo &pane = m_pauimgr->GetPane(
this);
5680 pane.Dockable(
false);
5683 if (updateAUImgr) m_pauimgr->Update();
5686void DashboardWindow::SetSizerOrientation(
int orient) {
5687 itemBoxSizer->SetOrientation(orient);
5689 wxWindowListNode *node = GetChildren().GetFirst();
5691 node->GetData()->SetMinSize(wxDefaultSize);
5692 node = node->GetNext();
5694 SetMinSize(wxDefaultSize);
5696 SetMinSize(itemBoxSizer->GetMinSize());
5699int DashboardWindow::GetSizerOrientation() {
5700 return itemBoxSizer->GetOrientation();
5703bool isArrayIntEqual(
const wxArrayInt &l1,
const wxArrayOfInstrument &l2) {
5704 if (l1.GetCount() != l2.GetCount())
return false;
5706 for (
size_t i = 0; i < l1.GetCount(); i++)
5707 if (l1.Item(i) != l2.Item(i)->m_ID)
return false;
5712bool DashboardWindow::isInstrumentListEqual(
const wxArrayInt &list) {
5713 return isArrayIntEqual(list, m_ArrayOfInstrument);
5716void DashboardWindow::SetInstrumentList(
5717 wxArrayInt list, wxArrayOfInstrumentProperties *InstrumentPropertyList) {
5731 m_ArrayOfInstrument.Clear();
5732 itemBoxSizer->Clear(
true);
5733 for (
size_t i = 0; i < list.GetCount(); i++) {
5734 int id = list.Item(i);
5736 for (
size_t j = 0; j < InstrumentPropertyList->GetCount(); j++) {
5737 if (InstrumentPropertyList->Item(j)->m_aInstrument ==
id &&
5738 InstrumentPropertyList->Item(j)->m_Listplace == (
int)i) {
5739 Properties = InstrumentPropertyList->Item(j);
5747 this, wxID_ANY, getInstrumentCaption(
id), Properties);
5751 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5752 OCPN_DBP_STC_SOG, _T(
"%5.1f"));
5756 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5757 OCPN_DBP_STC_SOG, 0, g_iDashSpeedMax);
5759 ->SetOptionLabel(g_iDashSpeedMax / 20 + 1, DIAL_LABEL_HORIZONTAL);
5763 ->SetOptionMarker(0.5, DIAL_MARKER_SIMPLE, 2);
5765 ->SetOptionExtraValue(OCPN_DBP_STC_STW,
"STW %.1f",
5766 DIAL_POSITION_BOTTOMMIDDLE);
5770 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5771 OCPN_DBP_STC_STW, 0, g_iDashSpeedMax);
5773 ->SetOptionLabel(g_iDashSpeedMax / 20 + 1, DIAL_LABEL_HORIZONTAL);
5777 ->SetOptionMarker(0.5, DIAL_MARKER_SIMPLE, 2);
5779 ->SetOptionExtraValue(OCPN_DBP_STC_SOG,
"SOG %.1f",
5780 DIAL_POSITION_BOTTOMMIDDLE);
5784 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5785 OCPN_DBP_STC_COG, _T(
"%03.0f"));
5789 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5790 OCPN_DBP_STC_MCOG, _T(
"%03.0f"));
5794 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5797 ->SetOptionMarker(5, DIAL_MARKER_SIMPLE, 2);
5799 ->SetOptionLabel(30, DIAL_LABEL_ROTATED);
5801 ->SetOptionExtraValue(OCPN_DBP_STC_SOG, _T(
"SOG\n%.2f"),
5802 DIAL_POSITION_BOTTOMLEFT);
5806 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5809 ->SetOptionMarker(5, DIAL_MARKER_SIMPLE, 2);
5811 ->SetOptionLabel(30, DIAL_LABEL_ROTATED);
5813 ->SetOptionExtraValue(OCPN_DBP_STC_STW, _T(
"STW\n%.1f"),
5814 DIAL_POSITION_BOTTOMLEFT);
5818 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5819 OCPN_DBP_STC_STW, _T(
"%.1f"));
5824 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5825 OCPN_DBP_STC_HDT, _T(
"%03.0f"));
5829 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5830 OCPN_DBP_STC_HDM, _T(
"%03.0f"));
5835 getInstrumentCaption(
id),
5836 Properties, OCPN_DBP_STC_AWA);
5838 ->SetOptionMainValue(_T(
"%.0f"), DIAL_POSITION_BOTTOMLEFT);
5840 ->SetOptionExtraValue(OCPN_DBP_STC_AWS, _T(
"%.1f"),
5841 DIAL_POSITION_INSIDE);
5845 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5846 OCPN_DBP_STC_AWS, _T(
"%.1f"));
5850 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5851 OCPN_DBP_STC_AWS, 0, 45);
5853 ->SetOptionLabel(5, DIAL_LABEL_HORIZONTAL);
5855 ->SetOptionMarker(1, DIAL_MARKER_SIMPLE, 5);
5857 ->SetOptionMainValue(_T(
"A %.1f"), DIAL_POSITION_BOTTOMLEFT);
5859 ->SetOptionExtraValue(OCPN_DBP_STC_TWS, _T(
"T %.1f"),
5860 DIAL_POSITION_BOTTOMRIGHT);
5864 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5867 ->SetOptionMainValue(_T(
"%.0f"), DIAL_POSITION_BOTTOMLEFT);
5869 ->SetOptionExtraValue(OCPN_DBP_STC_TWS, _T(
"%.1f"),
5870 DIAL_POSITION_INSIDE);
5872 case ID_DBP_D_AWA_TWA:
5874 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5878 ->SetOptionMainValue(_T(
"%.0f"), DIAL_POSITION_NONE);
5880 ->SetOptionExtraValue(OCPN_DBP_STC_TWS, _T(
"%.1f"),
5881 DIAL_POSITION_NONE);
5883 ->SetOptionExtraValue(OCPN_DBP_STC_AWS, _T(
"%.1f"),
5884 DIAL_POSITION_NONE);
5888 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5891 ->SetOptionMainValue(_T(
"%.0f"), DIAL_POSITION_BOTTOMLEFT);
5893 ->SetOptionExtraValue(OCPN_DBP_STC_TWS2, _T(
"%.1f"),
5894 DIAL_POSITION_INSIDE);
5898 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5899 OCPN_DBP_STC_ALTI, _T(
"%6.1f"));
5903 this, wxID_ANY, getInstrumentCaption(
id), Properties);
5907 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5908 OCPN_DBP_STC_DPT, _T(
"%5.2f"));
5912 this, wxID_ANY, getInstrumentCaption(
id), Properties);
5916 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5917 OCPN_DBP_STC_TMP, _T(
"%2.1f"));
5921 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5922 OCPN_DBP_STC_MDA, _T(
"%5.1f"));
5926 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5927 OCPN_DBP_STC_MDA, 938, 1088);
5929 ->SetOptionLabel(15, DIAL_LABEL_HORIZONTAL);
5931 ->SetOptionMarker(7.5, DIAL_MARKER_SIMPLE, 1);
5933 ->SetOptionMainValue(_T(
"%5.1f"), DIAL_POSITION_INSIDE);
5937 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5938 OCPN_DBP_STC_ATMP, _T(
"%2.1f"));
5942 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5943 OCPN_DBP_STC_VLW1, _T(
"%2.1f"));
5948 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5949 OCPN_DBP_STC_VLW2, _T(
"%2.1f"));
5954 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5955 OCPN_DBP_STC_TWA, _T(
"%5.0f"));
5959 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5960 OCPN_DBP_STC_TWD, _T(
"%3.0f"));
5964 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5965 OCPN_DBP_STC_TWS, _T(
"%2.1f"));
5969 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5970 OCPN_DBP_STC_AWA, _T(
"%3.0f"));
5974 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5975 OCPN_DBP_STC_VMGW, _T(
"%2.1f"));
5979 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5980 OCPN_DBP_STC_VMG, _T(
"%5.1f"));
5984 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5985 OCPN_DBP_STC_VMG, 0, g_iDashSpeedMax);
5987 ->SetOptionLabel(1, DIAL_LABEL_HORIZONTAL);
5989 ->SetOptionMarker(0.5, DIAL_MARKER_SIMPLE, 2);
5991 ->SetOptionExtraValue(OCPN_DBP_STC_SOG, _T(
"SOG\n%.1f"),
5992 DIAL_POSITION_BOTTOMLEFT);
5996 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5997 OCPN_DBP_STC_RSA, _T(
"%5.0f"));
6001 this, wxID_ANY, getInstrumentCaption(
id), Properties);
6005 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6006 OCPN_DBP_STC_SAT, _T(
"%5.0f"));
6010 this, wxID_ANY, getInstrumentCaption(
id), Properties);
6014 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6015 OCPN_DBP_STC_PLA, OCPN_DBP_STC_PLO);
6017 case ID_DBP_I_GPSUTC:
6019 this, wxID_ANY, getInstrumentCaption(
id), Properties);
6023 this, wxID_ANY, getInstrumentCaption(
id), Properties);
6027 this, wxID_ANY, getInstrumentCaption(
id), Properties);
6031 this, wxID_ANY, getInstrumentCaption(
id), Properties);
6035 this, wxID_ANY, getInstrumentCaption(
id), Properties);
6039 this, wxID_ANY, getInstrumentCaption(
id), Properties);
6041 case ID_DBP_I_PITCH:
6043 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6044 OCPN_DBP_STC_PITCH, _T(
"%2.1f"));
6048 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6049 OCPN_DBP_STC_HEEL, _T(
"%2.1f"));
6053 case ID_DBP_I_SUNLCL:
6055 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6056 _T(
"%02i:%02i:%02i LCL" ));
6058 case ID_DBP_I_GPSLCL:
6060 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6061 OCPN_DBP_STC_CLK, _T(
"%02i:%02i:%02i LCL" ));
6063 case ID_DBP_I_CPULCL:
6065 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6066 _T(
"%02i:%02i:%02i LCL" ));
6070 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6071 OCPN_DBP_STC_HUM,
"%3.0f");
6075 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6076 OCPN_DBP_STC_WCC, _T(
"%5.1f"));
6080 instrument->instrumentTypeId = id;
6082 id, instrument, instrument->GetCapacity()));
6083 itemBoxSizer->Add(instrument, 0, wxEXPAND, 0);
6084 if (itemBoxSizer->GetOrientation() == wxHORIZONTAL) {
6085 itemBoxSizer->AddSpacer(5);
6096 wxSize Hint = wxSize(DefaultWidth, DefaultWidth);
6098 for (
unsigned int i = 0; i < m_ArrayOfInstrument.size(); i++) {
6100 inst->SetMinSize(inst->GetSize(itemBoxSizer->GetOrientation(), Hint));
6101 Hint = inst->GetMinSize();
6106 SetMinSize(itemBoxSizer->GetMinSize());
6109void DashboardWindow::SendSentenceToAllInstruments(DASH_CAP st,
double value,
6111 for (
size_t i = 0; i < m_ArrayOfInstrument.GetCount(); i++) {
6112 if (m_ArrayOfInstrument.Item(i)->m_cap_flag.test(st))
6113 m_ArrayOfInstrument.Item(i)->m_pInstrument->SetData(st, value,
unit);
6117void DashboardWindow::SendSatInfoToAllInstruments(
int cnt,
int seq,
6120 for (
size_t i = 0; i < m_ArrayOfInstrument.GetCount(); i++) {
6121 if ((m_ArrayOfInstrument.Item(i)->m_cap_flag.test(OCPN_DBP_STC_GPS)) &&
6123 m_ArrayOfInstrument.Item(i)->m_pInstrument))
6125 ->SetSatInfo(cnt, seq, talk, sats);
6129void DashboardWindow::SendUtcTimeToAllInstruments(wxDateTime value) {
6130 for (
size_t i = 0; i < m_ArrayOfInstrument.GetCount(); i++) {
6131 if ((m_ArrayOfInstrument.Item(i)->m_cap_flag.test(OCPN_DBP_STC_CLK)) &&
6133 m_ArrayOfInstrument.Item(i)->m_pInstrument))
6141 ->SetUtcTime(value);
6157bool OCPNFontButton::Create(wxWindow *parent, wxWindowID
id,
6158 const wxFontData &initial,
const wxPoint &pos,
6159 const wxSize &size,
long style,
6160 const wxValidator &validator,
6161 const wxString &name) {
6162 wxString label = (style & wxFNTP_FONTDESC_AS_LABEL)
6168 if (!wxButton::Create(parent,
id, label, pos, size, style, validator, name)) {
6169 wxFAIL_MSG(wxT(
"OCPNFontButton creation failed"));
6174 Connect(GetId(), wxEVT_BUTTON,
6175 wxCommandEventHandler(OCPNFontButton::OnButtonClick), NULL,
this);
6179 initial.GetChosenFont().IsOk() ? initial.GetChosenFont() : *wxNORMAL_FONT;
6185void OCPNFontButton::OnButtonClick(wxCommandEvent &WXUNUSED(ev)) {
6187 m_data.SetInitialFont(m_selectedFont);
6192 int display_height = wxGetDisplaySize().y;
6193 if (display_height < 800) {
6197 if (dlg.ShowModal() == wxID_OK) {
6198 m_data = dlg.GetFontData();
6199 m_selectedFont = m_data.GetChosenFont();
6201 wxFontPickerEvent event(
this, GetId(), m_selectedFont);
6202 GetEventHandler()->ProcessEvent(event);
6207 wxFontDialog dlg(
this, m_data);
6209 if (dlg.ShowModal() == wxID_OK) {
6210 m_data = dlg.GetFontData();
6211 m_selectedFont = m_data.GetChosenFont();
6213 wxFontPickerEvent event(
this, GetId(), m_selectedFont);
6214 GetEventHandler()->ProcessEvent(event);
6221 wxFontDialog dlg(
this, m_data);
6227 wxSize proposed_size = GetParent()->GetSize();
6229 float font_size = pF->GetPointSize();
6231 if ((proposed_size.y / font_size) < n_lines) {
6232 float new_font_size = proposed_size.y / n_lines;
6233 wxFont *smallFont =
new wxFont(*pF);
6234 smallFont->SetPointSize(new_font_size);
6235 dlg.SetFont(*smallFont);
6238 dlg.SetSize(GetParent()->GetSize());
6242 if (dlg.ShowModal() == wxID_OK) {
6243 m_data = dlg.GetFontData();
6244 m_selectedFont = m_data.GetChosenFont();
6247 wxFontPickerEvent event(
this, GetId(), m_selectedFont);
6248 GetEventHandler()->ProcessEvent(event);
6255void OCPNFontButton::UpdateFont() {
6256 if (!m_selectedFont.IsOk())
return;
6261 if (HasFlag(wxFNTP_USEFONT_FOR_LABEL)) {
6263 wxButton::SetFont(m_selectedFont);
6264 wxButton::SetForegroundColour(GetSelectedColour());
6268 wxString::Format(wxT(
"%s, %d"), m_selectedFont.GetFaceName().c_str(),
6269 m_selectedFont.GetPointSize());
6271 if (HasFlag(wxFNTP_FONTDESC_AS_LABEL)) {
6275 auto minsize = GetTextExtent(label);
6278 GetParent()->Layout();
6285 wxWindowID
id,
const wxString &title,
const wxPoint &pos,
6286 const wxSize &size,
long style)
6287 : wxDialog(parent, id, title, pos, size, style) {
6288 this->SetSizeHints(wxDefaultSize, wxDefaultSize);
6290 wxBoxSizer *bSizer5;
6291 bSizer5 =
new wxBoxSizer(wxVERTICAL);
6293 wxFlexGridSizer *fgSizer2;
6294 fgSizer2 =
new wxFlexGridSizer(0, 2, 0, 0);
6295 fgSizer2->SetFlexibleDirection(wxBOTH);
6296 fgSizer2->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);
6298 m_staticText1 =
new wxStaticText(
this, wxID_ANY, _(
"Title:"),
6299 wxDefaultPosition, wxDefaultSize, 0);
6300 m_staticText1->Wrap(-1);
6301 fgSizer2->Add(m_staticText1, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
6303 m_fontPicker2 =
new wxFontPickerCtrl(
this, wxID_ANY, Properties.m_USTitleFont,
6304 wxDefaultPosition, wxDefaultSize);
6305 fgSizer2->Add(m_fontPicker2, 0, wxALL, 5);
6307 m_staticText5 =
new wxStaticText(
this, wxID_ANY, _(
"Title background color:"),
6308 wxDefaultPosition, wxDefaultSize, 0);
6309 m_staticText5->Wrap(-1);
6310 fgSizer2->Add(m_staticText5, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
6312 m_colourPicker1 =
new wxColourPickerCtrl(
6313 this, wxID_ANY, Properties.m_TitleBackgroundColour, wxDefaultPosition,
6314 wxDefaultSize, wxCLRP_DEFAULT_STYLE);
6315 fgSizer2->Add(m_colourPicker1, 0, wxALL, 5);
6317 m_staticText2 =
new wxStaticText(
this, wxID_ANY, _(
"Data:"),
6318 wxDefaultPosition, wxDefaultSize, 0);
6319 m_staticText2->Wrap(-1);
6320 fgSizer2->Add(m_staticText2, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
6322 m_fontPicker4 =
new wxFontPickerCtrl(
this, wxID_ANY, Properties.m_USDataFont,
6323 wxDefaultPosition, wxDefaultSize);
6324 fgSizer2->Add(m_fontPicker4, 0, wxALL, 5);
6326 m_staticText6 =
new wxStaticText(
this, wxID_ANY, _(
"Data background color:"),
6327 wxDefaultPosition, wxDefaultSize, 0);
6328 m_staticText6->Wrap(-1);
6329 fgSizer2->Add(m_staticText6, 0, wxALL, 5);
6331 m_colourPicker2 =
new wxColourPickerCtrl(
6332 this, wxID_ANY, Properties.m_DataBackgroundColour, wxDefaultPosition,
6333 wxDefaultSize, wxCLRP_DEFAULT_STYLE);
6334 fgSizer2->Add(m_colourPicker2, 0, wxALL, 5);
6336 m_staticText3 =
new wxStaticText(
this, wxID_ANY, _(
"Label:"),
6337 wxDefaultPosition, wxDefaultSize, 0);
6338 m_staticText3->Wrap(-1);
6339 fgSizer2->Add(m_staticText3, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
6341 m_fontPicker5 =
new wxFontPickerCtrl(
this, wxID_ANY, Properties.m_USLabelFont,
6342 wxDefaultPosition, wxDefaultSize);
6343 fgSizer2->Add(m_fontPicker5, 0, wxALL, 5);
6345 m_staticText4 =
new wxStaticText(
this, wxID_ANY, _(
"Small:"),
6346 wxDefaultPosition, wxDefaultSize, 0);
6347 m_staticText4->Wrap(-1);
6348 fgSizer2->Add(m_staticText4, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
6350 m_fontPicker6 =
new wxFontPickerCtrl(
this, wxID_ANY, Properties.m_USSmallFont,
6351 wxDefaultPosition, wxDefaultSize);
6352 fgSizer2->Add(m_fontPicker6, 0, wxALL, 5);
6354 m_staticText9 =
new wxStaticText(
this, wxID_ANY, _(
"Arrow 1 Color :"),
6355 wxDefaultPosition, wxDefaultSize, 0);
6356 m_staticText9->Wrap(-1);
6357 fgSizer2->Add(m_staticText9, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
6359 m_colourPicker3 =
new wxColourPickerCtrl(
6360 this, wxID_ANY, Properties.m_Arrow_First_Colour, wxDefaultPosition,
6361 wxDefaultSize, wxCLRP_DEFAULT_STYLE);
6362 fgSizer2->Add(m_colourPicker3, 0, wxALL, 5);
6364 m_staticText10 =
new wxStaticText(
this, wxID_ANY, _(
"Arrow 2 Color :"),
6365 wxDefaultPosition, wxDefaultSize, 0);
6366 m_staticText10->Wrap(-1);
6367 fgSizer2->Add(m_staticText10, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
6369 m_colourPicker4 =
new wxColourPickerCtrl(
6370 this, wxID_ANY, Properties.m_Arrow_Second_Colour, wxDefaultPosition,
6371 wxDefaultSize, wxCLRP_DEFAULT_STYLE);
6372 fgSizer2->Add(m_colourPicker4, 0, wxALL, 5);
6374 m_staticline1 =
new wxStaticLine(
this, wxID_ANY, wxDefaultPosition,
6375 wxDefaultSize, wxLI_HORIZONTAL);
6376 fgSizer2->Add(m_staticline1, 0, wxEXPAND | wxALL, 5);
6378 m_staticline2 =
new wxStaticLine(
this, wxID_ANY, wxDefaultPosition,
6379 wxDefaultSize, wxLI_HORIZONTAL);
6380 fgSizer2->Add(m_staticline2, 0, wxEXPAND | wxALL, 5);
6382 fgSizer2->Add(0, 5, 1, wxEXPAND, 5);
6384 fgSizer2->Add(0, 0, 1, wxEXPAND, 5);
6386 m_staticText7 =
new wxStaticText(
this, wxID_ANY, wxEmptyString,
6387 wxDefaultPosition, wxDefaultSize, 0);
6388 m_staticText7->Wrap(-1);
6389 fgSizer2->Add(m_staticText7, 0, wxALL, 5);
6391 m_button1 =
new wxButton(
this, wxID_ANY, _(
"Set default"), wxDefaultPosition,
6393 fgSizer2->Add(m_button1, 0, wxALL, 5);
6395 fgSizer2->Add(0, 5, 1, wxEXPAND, 5);
6397 fgSizer2->Add(5, 0, 1, wxEXPAND, 5);
6399 bSizer5->Add(fgSizer2, 1, wxALL | wxEXPAND, 5);
6401 m_sdbSizer3 =
new wxStdDialogButtonSizer();
6402 m_sdbSizer3OK =
new wxButton(
this, wxID_OK);
6403 m_sdbSizer3->AddButton(m_sdbSizer3OK);
6404 m_sdbSizer3Cancel =
new wxButton(
this, wxID_CANCEL);
6405 m_sdbSizer3->AddButton(m_sdbSizer3Cancel);
6406 m_sdbSizer3->Realize();
6408 bSizer5->Add(m_sdbSizer3, 0, 0, 1);
6410 bSizer5->Add(0, 10, 0, wxEXPAND, 5);
6412 this->SetSizer(bSizer5);
6416 this->Centre(wxBOTH);
6419 m_button1->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
6420 wxCommandEventHandler(EditDialog::OnSetdefault), NULL,
6424EditDialog::~EditDialog() {
6426 m_button1->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED,
6427 wxCommandEventHandler(EditDialog::OnSetdefault), NULL,
6431void EditDialog::OnSetdefault(wxCommandEvent &event) {
6432 m_fontPicker2->SetSelectedFont(g_USFontTitle.GetChosenFont());
6433 m_fontPicker2->SetSelectedColour(g_USFontTitle.GetColour());
6434 m_fontPicker4->SetSelectedFont(g_USFontData.GetChosenFont());
6435 m_fontPicker4->SetSelectedColour(g_USFontData.GetColour());
6436 m_fontPicker5->SetSelectedFont(g_USFontLabel.GetChosenFont());
6437 m_fontPicker5->SetSelectedColour(g_USFontLabel.GetColour());
6438 m_fontPicker6->SetSelectedFont(g_USFontSmall.GetChosenFont());
6439 m_fontPicker6->SetSelectedColour(g_USFontSmall.GetColour());
6441 GetGlobalColor(_T(
"DASHL"), &dummy);
6442 m_colourPicker1->SetColour(dummy);
6443 GetGlobalColor(_T(
"DASHB"), &dummy);
6444 m_colourPicker2->SetColour(dummy);
6445 GetGlobalColor(_T(
"DASHN"), &dummy);
6446 m_colourPicker3->SetColour(dummy);
6447 GetGlobalColor(_T(
"BLUE3"), &dummy);
6448 m_colourPicker4->SetColour(dummy);
A dashboard instrument that displays the current computer time.
A dashboard instrument that displays the GNSS clock time, if available.
A dashboard instrument that displays current moon phase information.
A dashboard instrument that displays sunrise and sunset times.
Adds a std::shared<void> element to wxCommandEvent.
wxBitmap * GetPlugInBitmap()
FIXME static wxBitmap* LoadSVG(const wxString filename, unsigned int width, ...
void SetNMEASentence(wxString &sentence)
Receive all NMEA 0183 sentences from OpenCPN.
int Parse(const wxString &doc, wxJSONValue *val)
Parse the JSON document.
The JSON value class implementation.
bool IsArray() const
Return TRUE if the type of the value stored is an array type.
int Size() const
Return the size of the array or map stored in this value.
bool HasMember(unsigned index) const
Return TRUE if the object contains an element at the specified index.
double AsDouble() const
Return the stored value as a double.
bool IsString() const
Return TRUE if the type of the value stored is a wxString object.
wxString AsString() const
Return the stored value as a wxWidget's string.
#define WANTS_NMEA_EVENTS
Receive decoded NMEA events with parsed data.
#define USES_AUI_MANAGER
Plugin uses wxAuiManager for window management.
#define WANTS_NMEA_SENTENCES
Receive raw NMEA 0183 sentences from all active ports.
#define WANTS_PREFERENCES
Plugin will add page(s) to global preferences dialog.
#define WANTS_CONFIG
Plugin requires persistent configuration storage.
#define WANTS_PLUGIN_MESSAGING
Enable message passing between plugins.
#define INSTALLS_TOOLBAR_TOOL
Plugin will add one or more toolbar buttons.
#define WANTS_CURSOR_LATLON
Receive updates when cursor moves over chart.
#define WANTS_TOOLBAR_CALLBACK
Receive notification when user left-clicks plugin's toolbar buttons.
wxFont * OCPNGetFont(wxString TextElement, int default_size)
Gets a font for UI elements.
std::string GetN2000Source(NMEA2000Id id, ObservedEvt ev)
Return source identifier (iface) of a received n2000 message of type id in ev.
vector< uint8_t > GetN2000Payload(NMEA2000Id id, ObservedEvt ev)
Return N2K payload for a received n2000 message of type id in ev.