36#include <wx/filename.h>
37#include <wx/fontdlg.h>
41#include "manual/manual.h"
52#include "jsonreader.h"
53#include "jsonwriter.h"
56wxFontData *g_pFontTitle;
57wxFontData *g_pFontData;
58wxFontData *g_pFontLabel;
59wxFontData *g_pFontSmall;
61wxFontData g_FontTitle;
63wxFontData g_FontLabel;
64wxFontData g_FontSmall;
66wxFontData *g_pUSFontTitle;
67wxFontData *g_pUSFontData;
68wxFontData *g_pUSFontLabel;
69wxFontData *g_pUSFontSmall;
71wxFontData g_USFontTitle;
72wxFontData g_USFontData;
73wxFontData g_USFontLabel;
74wxFontData g_USFontSmall;
83int g_iDashDistanceUnit;
84int g_iDashWindSpeedUnit;
86double g_dDashDBTOffset;
87bool g_bUseInternSumLog;
90int logCount, confprint;
91bool g_bDBtrueWindGround;
95int g_dashPrefWidth, g_dashPrefHeight;
97wxColor g_BackgroundColor;
98bool g_ForceBackgroundColor;
99wxAlignment g_TitleAlignment;
100double g_TitleVerticalOffset;
103wxAlignment g_DataAlignment;
105int g_iInstrumentSpacing;
109static const long long lNaN = 0xfff8000000000000;
110#define NAN (*(double *)&lNaN)
123extern "C" DECL_EXP
void destroy_pi(
opencpn_plugin *p) {
delete p; }
127QString qtStyleSheet =
128 "QScrollBar:horizontal {\
129border: 0px solid grey;\
130background-color: rgb(240, 240, 240);\
132margin: 0px 1px 0 1px;\
134QScrollBar::handle:horizontal {\
135background-color: rgb(200, 200, 200);\
139QScrollBar::add-line:horizontal {\
140border: 0px solid grey;\
143subcontrol-position: right;\
144subcontrol-origin: margin;\
146QScrollBar::sub-line:horizontal {\
147border: 0px solid grey;\
150subcontrol-position: left;\
151subcontrol-origin: margin;\
153QScrollBar:vertical {\
154border: 0px solid grey;\
155background-color: rgb(240, 240, 240);\
157margin: 1px 0px 1px 0px;\
159QScrollBar::handle:vertical {\
160background-color: rgb(200, 200, 200);\
164QScrollBar::add-line:vertical {\
165border: 0px solid grey;\
168subcontrol-position: top;\
169subcontrol-origin: margin;\
171QScrollBar::sub-line:vertical {\
172border: 0px solid grey;\
175subcontrol-position: bottom;\
176subcontrol-origin: margin;\
181QCheckBox::indicator {\
190#include <QtWidgets/QScroller>
262bool IsObsolete(
int id) {
return id == ID_DBP_D_AWA; }
264wxString getInstrumentCaption(
unsigned int id) {
267 return _(
"Position");
271 return _(
"Speed SOG");
273 return _(
"Speed STW");
279 return _(
"GNSS Compass");
281 return _(
"True Compass");
285 return _(
"True HDG");
290 return _(
"App. Wind Angle & Speed");
291 case ID_DBP_D_AWA_TWA:
292 return _(
"App & True Wind Angle");
295 return _(
"App. Wind Speed");
297 return _(
"True Wind Angle & Speed");
299 return _(
"Altitude");
301 return _(
"Altitude Trace");
307 return _(
"Barometric pressure");
309 return _(
"Water Temp.");
311 return _(
"Air Temp.");
313 return _(
"App. Wind Angle");
315 return _(
"True Wind Angle");
317 return _(
"True Wind Direction");
319 return _(
"True Wind Speed");
321 return _(
"True Wind Dir. & Speed");
326 return _(
"VMG Wind");
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");
357 return _(
"Local GNSS Clock");
359 return _(
"Local CPU Clock");
361 return _(
"Local Sunrise/Sunset");
363 return _(
"Humidity");
365 return _(
"Windlass");
371void getListItemForInstrument(wxListItem &item,
unsigned int id) {
373 item.SetText(getInstrumentCaption(
id));
396 case ID_DBP_I_GPSUTC:
418 case ID_DBP_D_AWA_TWA:
433 assert(
false &&
"Illegal instrument ID");
438int GetRandomNumber(
int range_min,
int range_max) {
439 long u = (long)wxRound(
440 ((
double)rand() / ((
double)(RAND_MAX) + 1) * (range_max - range_min)) +
451 int time_hi_and_version;
452 int clock_seq_hi_and_rsv;
458 uuid.time_low = GetRandomNumber(
461 uuid.time_mid = GetRandomNumber(0, 65535);
462 uuid.time_hi_and_version = GetRandomNumber(0, 65535);
463 uuid.clock_seq_hi_and_rsv = GetRandomNumber(0, 255);
464 uuid.clock_seq_low = GetRandomNumber(0, 255);
465 uuid.node_hi = GetRandomNumber(0, 65535);
466 uuid.node_low = GetRandomNumber(0, 2147483647);
470 uuid.clock_seq_hi_and_rsv = (uuid.clock_seq_hi_and_rsv & 0x3F) | 0x80;
474 uuid.time_hi_and_version = (uuid.time_hi_and_version & 0x0fff) | 0x4000;
476 str.Printf(
"%08x-%04x-%04x-%02x%02x-%04x%08x", uuid.time_low, uuid.time_mid,
477 uuid.time_hi_and_version, uuid.clock_seq_hi_and_rsv,
478 uuid.clock_seq_low, uuid.node_hi, uuid.node_low);
483wxString MakeName() {
return "DASH_" + GetUUID(); }
491dashboard_pi::dashboard_pi(
void *ppimgr)
496 m_cog_filter.SetType(IIRFILTER_TYPE_DEG);
497 m_awa_filter.SetType(IIRFILTER_TYPE_DEG);
498 m_aws_filter.SetType(IIRFILTER_TYPE_LINEAR);
501dashboard_pi::~dashboard_pi() {
502 delete _img_dashboard_pi;
503 delete _img_dashboard;
505 delete _img_instrument;
516 m_pri_heading_t = 99;
517 m_pri_heading_m = 99;
519 m_pri_date_time = 99;
528 m_pri_sat_status = 99;
533 m_pri_pitch_roll = 99;
535 m_config_version = -1;
538 m_sats_used_wdog = 2;
539 m_sat_status_wdog = 2;
540 m_pri_n2_k_talker = 2;
544 m_dpt_dbt_watchdog = 2;
554 m_pitch_watchdog = 2;
558 m_tr_log_watchdog = 2;
562 g_pFontTitle =
new wxFontData();
563 g_pFontTitle->SetChosenFont(
564 wxFont(10, wxFONTFAMILY_SWISS, wxFONTSTYLE_ITALIC, wxFONTWEIGHT_NORMAL));
566 g_pFontData =
new wxFontData();
567 g_pFontData->SetChosenFont(
568 wxFont(14, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));
570 g_pFontLabel =
new wxFontData();
571 g_pFontLabel->SetChosenFont(
572 wxFont(8, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));
574 g_pFontSmall =
new wxFontData();
575 g_pFontSmall->SetChosenFont(
576 wxFont(8, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));
578 g_pUSFontTitle = &g_USFontTitle;
579 g_pUSFontData = &g_USFontData;
580 g_pUSFontLabel = &g_USFontLabel;
581 g_pUSFontSmall = &g_USFontSmall;
584 m_pauimgr->Connect(wxEVT_AUI_PANE_CLOSE,
585 wxAuiManagerEventHandler(dashboard_pi::OnPaneClose),
601 wxFileName::GetPathSeparator() +
"dashboard_pi" +
602 wxFileName::GetPathSeparator() +
"data" +
603 wxFileName::GetPathSeparator();
605 wxString normalIcon = shareLocn +
"Dashboard.svg";
606 wxString toggledIcon = shareLocn +
"Dashboard_toggled.svg";
607 wxString rolloverIcon = shareLocn +
"Dashboard_rollover.svg";
618 "", normalIcon, rolloverIcon, toggledIcon, wxITEM_CHECK, _(
"Dashboard"),
619 "",
nullptr, DASHBOARD_TOOL_POSITION, 0,
this);
624 if (m_config_version == 1) {
629 logCount = confprint = 0;
631 if (g_bUseInternSumLog) UpdateSumLog(
false);
639 listener_127245 =
GetListener(id_127245, EVT_N2K_127245,
this);
640 Bind(EVT_N2K_127245, [&](
ObservedEvt &ev) { HandleN2K_127245(ev); });
645 listener_127257 =
GetListener(id_127257, EVT_N2K_127257,
this);
646 Bind(EVT_N2K_127257, [&](
ObservedEvt &ev) { HandleN2K_127257(ev); });
651 listener_128259 =
GetListener(id_128259, EVT_N2K_128259,
this);
652 Bind(EVT_N2K_128259, [&](
ObservedEvt &ev) { HandleN2K_128259(ev); });
657 listener_128267 =
GetListener(id_128267, EVT_N2K_128267,
this);
658 Bind(EVT_N2K_128267, [&](
ObservedEvt &ev) { HandleN2K_128267(ev); });
663 listener_128275 =
GetListener(id_128275, EVT_N2K_128275,
this);
664 Bind(EVT_N2K_128275, [&](
ObservedEvt &ev) { HandleN2K_128275(ev); });
669 listener_128777 =
GetListener(id_128777, EVT_N2K_128777,
this);
670 Bind(EVT_N2K_128777, [&](
ObservedEvt &ev) { HandleN2K_128777(ev); });
675 listener_129029 =
GetListener(id_129029, EVT_N2K_129029,
this);
676 Bind(EVT_N2K_129029, [&](
ObservedEvt &ev) { HandleN2K_129029(ev); });
681 listener_129540 =
GetListener(id_129540, EVT_N2K_129540,
this);
682 Bind(EVT_N2K_129540, [&](
ObservedEvt &ev) { HandleN2K_129540(ev); });
687 listener_130306 =
GetListener(id_130306, EVT_N2K_130306,
this);
688 Bind(EVT_N2K_130306, [&](
ObservedEvt &ev) { HandleN2K_130306(ev); });
693 listener_130310 =
GetListener(id_130310, EVT_N2K_130310,
this);
694 Bind(EVT_N2K_130310, [&](
ObservedEvt &ev) { HandleN2K_130310(ev); });
699 listener_130313 =
GetListener(id_130313, EVT_N2K_130313,
this);
700 Bind(EVT_N2K_130313, [&](
ObservedEvt &ev) { HandleN2K_130313(ev); });
702 Start(1000, wxTIMER_CONTINUOUS);
714 for (
size_t i = 0; i < m_ArrayOfDashboardWindow.GetCount(); i++) {
716 m_ArrayOfDashboardWindow.Item(i)->m_pDashboardWindow;
717 if (dashboard_window) {
718 m_pauimgr->DetachPane(dashboard_window);
719 dashboard_window->Close();
720 dashboard_window->Destroy();
721 m_ArrayOfDashboardWindow.Item(i)->m_pDashboardWindow =
nullptr;
725 for (
size_t i = 0; i < m_ArrayOfDashboardWindow.GetCount(); i++) {
740 if (value.IsDouble()) {
741 d_ret = value.AsDouble();
743 }
else if (value.IsLong()) {
744 long i_ret = value.AsLong();
745 d_ret =
static_cast<double>(i_ret);
751void dashboard_pi::Notify() {
752 SendUtcTimeToAllInstruments(m_utc_date_time);
753 for (
size_t i = 0; i < m_ArrayOfDashboardWindow.GetCount(); i++) {
755 m_ArrayOfDashboardWindow.Item(i)->m_pDashboardWindow;
756 if (dashboard_window) {
757 dashboard_window->Refresh();
759 wxWindowList list = dashboard_window->GetChildren();
760 wxWindowListNode *node = list.GetFirst();
761 for (
size_t i = 0; i < list.GetCount(); i++) {
762 wxWindow *win = node->GetData();
765 node = node->GetNext();
773 if (m_h_dx_watchdog <= 0) {
775 m_pri_heading_m = 99;
777 m_h_dx_watchdog = gps_watchdog_timeout_ticks;
781 if (m_hdt_watchdog <= 0) {
782 m_pri_heading_t = 99;
784 m_hdt_watchdog = gps_watchdog_timeout_ticks;
788 if (m_var_watchdog <= 0) {
792 m_var_watchdog = gps_watchdog_timeout_ticks;
796 if (m_sats_used_wdog <= 0) {
800 m_sats_used_wdog = gps_watchdog_timeout_ticks;
803 if (m_pri_n2_k_talker < -1e6) m_pri_n2_k_talker = 0;
806 if (m_sat_status_wdog <= 0) {
808 for (
int i = 0; i < 4; i++) {
809 sats[i].SatNumber = 0;
810 sats[i].SignalToNoiseRatio = 0;
812 SendSatInfoToAllInstruments(0, 1, wxEmptyString, sats);
813 SendSatInfoToAllInstruments(0, 2, wxEmptyString, sats);
814 SendSatInfoToAllInstruments(0, 3, wxEmptyString, sats);
815 m_pri_sat_status = 99;
816 m_sat_status_wdog = gps_watchdog_timeout_ticks;
823 std::string satID = PriorityIDs[4].substr(0, PriorityIDs[4].find(
':'));
824 if (satID.find(
"nmea0183") != std::string::npos)
825 m_pri_sat_status = 3;
826 else if (satID.find(
"ignal") != std::string::npos)
827 m_pri_sat_status = 2;
828 else if (satID.find(
"N2k") != std::string::npos) {
829 prioN2kPGNsat = PriorityIDs[4];
830 m_pri_sat_status = 1;
834 if (m_mwva_watchdog <= 0) {
838 m_mwva_watchdog = gps_watchdog_timeout_ticks;
842 if (m_mwvt_watchdog <= 0) {
847 m_mwvt_watchdog = gps_watchdog_timeout_ticks;
850 m_dpt_dbt_watchdog--;
851 if (m_dpt_dbt_watchdog <= 0) {
854 m_dpt_dbt_watchdog = gps_watchdog_timeout_ticks;
858 if (m_stw_watchdog <= 0) {
861 m_stw_watchdog = gps_watchdog_timeout_ticks;
865 if (m_wtp_watchdog <= 0) {
868 m_wtp_watchdog = no_nav_watchdog_timeout_ticks;
871 if (m_rsa_watchdog <= 0) {
874 m_rsa_watchdog = gps_watchdog_timeout_ticks;
877 if (m_vmg_watchdog <= 0) {
879 m_vmg_watchdog = gps_watchdog_timeout_ticks;
882 if (m_vmgw_watchdog <= 0) {
884 m_vmgw_watchdog = gps_watchdog_timeout_ticks;
887 if (m_utc_watchdog <= 0) {
888 m_pri_date_time = 99;
889 m_utc_watchdog = gps_watchdog_timeout_ticks;
892 if (m_atmp_watchdog <= 0) {
895 m_atmp_watchdog = gps_watchdog_timeout_ticks;
898 if (m_wdn_watchdog <= 0) {
901 m_wdn_watchdog = no_nav_watchdog_timeout_ticks;
904 if (m_mda_watchdog <= 0) {
907 m_mda_watchdog = gps_watchdog_timeout_ticks;
910 if (m_pitch_watchdog <= 0) {
911 m_pri_pitch_roll = 99;
913 m_pitch_watchdog = gps_watchdog_timeout_ticks;
916 if (m_heel_watchdog <= 0) {
917 m_pri_pitch_roll = 99;
919 m_heel_watchdog = gps_watchdog_timeout_ticks;
922 if (m_alt_watchdog <= 0) {
925 m_alt_watchdog = gps_watchdog_timeout_ticks;
929 if (m_log_watchdog <= 0) {
930 if (g_bUseInternSumLog) {
934 m_log_watchdog = no_nav_watchdog_timeout_ticks;
938 if (m_tr_log_watchdog <= 0) {
940 m_tr_log_watchdog = no_nav_watchdog_timeout_ticks;
943 if (m_hum_watchdog <= 0) {
946 m_hum_watchdog = no_nav_watchdog_timeout_ticks;
949 if (m_wcc_watchdog <= 0) {
951 m_wcc_watchdog = no_nav_watchdog_timeout_ticks;
968 return _(
"Dashboard PlugIn for OpenCPN");
973 "Dashboard PlugIn for OpenCPN\n\
974Provides navigation instrument display from NMEA source.");
977void dashboard_pi::SendSentenceToAllInstruments(
DASH_CAP st,
double value,
978 const wxString &
unit) {
979 for (
size_t i = 0; i < m_ArrayOfDashboardWindow.GetCount(); i++) {
981 m_ArrayOfDashboardWindow.Item(i)->m_pDashboardWindow;
982 if (dashboard_window)
983 dashboard_window->SendSentenceToAllInstruments(st, value,
unit);
996void dashboard_pi::SendUtcTimeToAllInstruments(wxDateTime value) {
997 for (
size_t i = 0; i < m_ArrayOfDashboardWindow.GetCount(); i++) {
999 m_ArrayOfDashboardWindow.Item(i)->m_pDashboardWindow;
1000 if (dashboard_window) dashboard_window->SendUtcTimeToAllInstruments(value);
1004void dashboard_pi::SendSatInfoToAllInstruments(
int cnt,
int seq,
1005 const wxString &talk,
1007 for (
size_t i = 0; i < m_ArrayOfDashboardWindow.GetCount(); i++) {
1009 m_ArrayOfDashboardWindow.Item(i)->m_pDashboardWindow;
1010 if (dashboard_window)
1011 dashboard_window->SendSatInfoToAllInstruments(cnt, seq, talk, sats);
1017 m_nmea0183 << sentence;
1019 if (m_nmea0183.PreParse()) {
1020 if (m_nmea0183.LastSentenceIDReceived ==
"DBT") {
1021 if (m_pri_depth >= 5) {
1022 if (m_nmea0183.Parse()) {
1029 if (!std::isnan(m_nmea0183.Dbt.DepthMeters))
1030 depth = m_nmea0183.Dbt.DepthMeters;
1031 else if (!std::isnan(m_nmea0183.Dbt.DepthFeet))
1032 depth = m_nmea0183.Dbt.DepthFeet * 0.3048;
1033 else if (!std::isnan(m_nmea0183.Dbt.DepthFathoms))
1034 depth = m_nmea0183.Dbt.DepthFathoms * 1.82880;
1035 if (!std::isnan(depth)) depth += g_dDashDBTOffset;
1036 if (!std::isnan(depth)) {
1037 SendSentenceToAllInstruments(
1042 m_dpt_dbt_watchdog = gps_watchdog_timeout_ticks;
1048 else if (m_nmea0183.LastSentenceIDReceived ==
"DPT") {
1049 if (m_pri_depth >= 4) {
1050 if (m_nmea0183.Parse()) {
1055 double depth = m_nmea0183.Dpt.DepthMeters;
1056 if (!std::isnan(m_nmea0183.Dpt.OffsetFromTransducerMeters)) {
1057 depth += m_nmea0183.Dpt.OffsetFromTransducerMeters;
1059 depth += g_dDashDBTOffset;
1060 if (!std::isnan(depth)) {
1061 SendSentenceToAllInstruments(
1066 m_dpt_dbt_watchdog = gps_watchdog_timeout_ticks;
1072 else if (m_nmea0183.LastSentenceIDReceived ==
"GGA") {
1074 printf(
"GGA mPriPosition=%d mPriSatUsed=%d \tnSat=%d alt=%3.2f\n",
1075 m_pri_position, m_pri_sat_used,
1076 m_nmea0183.Gga.NumberOfSatellitesInUse,
1077 m_nmea0183.Gga.AntennaAltitudeMeters);
1078 if (m_pri_alt >= 3 && (m_pri_position >= 1 || m_pri_sat_used >= 1)) {
1079 if (m_nmea0183.Parse()) {
1080 if (m_nmea0183.Gga.GPSQuality > 0 &&
1081 m_nmea0183.Gga.NumberOfSatellitesInUse >= 5) {
1084 double alt = m_nmea0183.Gga.AntennaAltitudeMeters;
1087 m_alt_watchdog = gps_watchdog_timeout_ticks;
1091 if (m_pri_position >= 4 || m_pri_sat_used >= 3) {
1092 if (m_nmea0183.Parse()) {
1093 if (m_nmea0183.Gga.GPSQuality > 0) {
1094 if (m_pri_position >= 4) {
1098 static_cast<float>(m_nmea0183.Gga.Position.Latitude.Latitude);
1099 int lat_deg_int = (int)(llt / 100);
1100 auto lat_deg =
static_cast<float>(lat_deg_int);
1101 float lat_min = llt - (lat_deg * 100);
1102 lat = lat_deg + (lat_min / 60.);
1103 if (m_nmea0183.Gga.Position.Latitude.Northing == South)
1107 auto lln =
static_cast<float>(
1108 m_nmea0183.Gga.Position.Longitude.Longitude);
1109 int lon_deg_int = (int)(lln / 100);
1110 auto lon_deg =
static_cast<float>(lon_deg_int);
1111 float lon_min = lln - (lon_deg * 100);
1112 lon = lon_deg + (lon_min / 60.);
1113 if (m_nmea0183.Gga.Position.Longitude.Easting == West) lon = -lon;
1116 if (m_pri_sat_used >= 3) {
1117 m_sats_in_use = m_nmea0183.Gga.NumberOfSatellitesInUse;
1121 m_sats_used_wdog = gps_watchdog_timeout_ticks;
1135 else if (m_nmea0183.LastSentenceIDReceived ==
"GLL") {
1136 if (m_pri_position >= 3) {
1137 if (m_nmea0183.Parse()) {
1138 if (m_nmea0183.Gll.IsDataValid == NTrue) {
1141 static_cast<float>(m_nmea0183.Gll.Position.Latitude.Latitude);
1142 int lat_deg_int = (int)(llt / 100);
1143 auto lat_deg =
static_cast<float>(lat_deg_int);
1144 float lat_min = llt - (lat_deg * 100);
1145 lat = lat_deg + (lat_min / 60.);
1146 if (m_nmea0183.Gll.Position.Latitude.Northing == South) lat = -lat;
1150 static_cast<float>(m_nmea0183.Gll.Position.Longitude.Longitude);
1151 int lon_deg_int = (int)(lln / 100);
1152 auto lon_deg =
static_cast<float>(lon_deg_int);
1153 float lon_min = lln - (lon_deg * 100);
1154 lon = lon_deg + (lon_min / 60.);
1155 if (m_nmea0183.Gll.Position.Longitude.Easting == West) lon = -lon;
1171 else if (m_nmea0183.LastSentenceIDReceived ==
"GSV") {
1172 if (m_pri_sat_status >= 3 || m_pri_sat_used >= 5) {
1173 if (m_nmea0183.Parse()) {
1174 if (m_nmea0183.Gsv.MessageNumber == 1) {
1177 m_sats_in_view = m_nmea0183.Gsv.SatsInView;
1179 if (m_pri_sat_used >= 5) {
1181 m_nmea0183.Gsv.SatsInView, _T (
""));
1183 m_sats_used_wdog = gps_watchdog_timeout_ticks;
1187 if (m_pri_sat_status >= 3) {
1188 SendSatInfoToAllInstruments(
1189 m_sats_in_view, m_nmea0183.Gsv.MessageNumber,
1190 m_nmea0183.TalkerID, m_nmea0183.Gsv.SatInfo);
1191 m_pri_sat_status = 3;
1192 m_sat_status_wdog = gps_watchdog_timeout_ticks;
1198 else if (m_nmea0183.LastSentenceIDReceived ==
"HDG") {
1199 if (m_pri_var >= 3 || m_pri_heading_m >= 3 || m_pri_heading_t >= 7) {
1200 if (m_nmea0183.Parse()) {
1201 if (m_pri_var >= 3) {
1205 if ((!std::isnan(m_nmea0183.Hdg.MagneticVariationDegrees)) &&
1206 0.0 != m_nmea0183.Hdg.MagneticVariationDegrees) {
1208 if (m_nmea0183.Hdg.MagneticVariationDirection == East)
1209 m_var = m_nmea0183.Hdg.MagneticVariationDegrees;
1210 else if (m_nmea0183.Hdg.MagneticVariationDirection == West)
1211 m_var = -m_nmea0183.Hdg.MagneticVariationDegrees;
1215 if (m_pri_heading_m >= 3) {
1216 if (!std::isnan(m_nmea0183.Hdg.MagneticSensorHeadingDegrees)) {
1217 m_pri_heading_m = 3;
1218 m_hdm = m_nmea0183.Hdg.MagneticSensorHeadingDegrees;
1222 if (!std::isnan(m_nmea0183.Hdg.MagneticSensorHeadingDegrees))
1223 m_h_dx_watchdog = gps_watchdog_timeout_ticks;
1227 if (!std::isnan(m_nmea0183.Hdg.MagneticSensorHeadingDegrees)) {
1228 if (!std::isnan(m_var) && (m_pri_heading_t >= 7)) {
1229 m_pri_heading_t = 7;
1230 double heading = m_hdm + m_var;
1233 else if (heading >= 360.0)
1236 m_hdt_watchdog = gps_watchdog_timeout_ticks;
1243 else if (m_nmea0183.LastSentenceIDReceived ==
"HDM") {
1244 if (m_pri_heading_m >= 4 || m_pri_heading_t >= 5) {
1245 if (m_nmea0183.Parse()) {
1246 if (m_pri_heading_m >= 4) {
1247 if (!std::isnan(m_nmea0183.Hdm.DegreesMagnetic)) {
1248 m_pri_heading_m = 4;
1249 m_hdm = m_nmea0183.Hdm.DegreesMagnetic;
1251 m_h_dx_watchdog = gps_watchdog_timeout_ticks;
1257 if (!std::isnan(m_nmea0183.Hdm.DegreesMagnetic)) {
1258 if (!std::isnan(m_var) && (m_pri_heading_t >= 5)) {
1259 m_pri_heading_t = 5;
1260 double heading = m_hdm + m_var;
1263 else if (heading >= 360.0)
1266 m_hdt_watchdog = gps_watchdog_timeout_ticks;
1273 else if (m_nmea0183.LastSentenceIDReceived ==
"HDT") {
1274 if (m_pri_heading_t >= 3) {
1275 if (m_nmea0183.Parse()) {
1276 if (!std::isnan(m_nmea0183.Hdt.DegreesTrue)) {
1278 m_nmea0183.Hdt.DegreesTrue,
"\u00B0T");
1279 m_pri_heading_t = 3;
1280 m_hdt_watchdog = gps_watchdog_timeout_ticks;
1284 }
else if (m_nmea0183.LastSentenceIDReceived ==
"MTA") {
1285 if (m_pri_atmp >= 3) {
1286 if (m_nmea0183.Parse()) {
1288 SendSentenceToAllInstruments(
1292 m_atmp_watchdog = gps_watchdog_timeout_ticks;
1295 }
else if (m_nmea0183.LastSentenceIDReceived ==
"MDA" &&
1296 (m_pri_mda >= 5 || m_pri_atmp >= 5 || m_pri_hum >= 4)) {
1298 if (m_nmea0183.Parse()) {
1304 if (m_pri_mda >= 5 && m_nmea0183.Mda.Pressure > .8 &&
1305 m_nmea0183.Mda.Pressure < 1.1) {
1307 m_nmea0183.Mda.Pressure * 1000,
"hPa");
1309 m_mda_watchdog = no_nav_watchdog_timeout_ticks;
1311 if (m_pri_atmp >= 5) {
1312 double airtemp = m_nmea0183.Mda.AirTemp;
1313 if (!std::isnan(airtemp) && airtemp < 999.0) {
1314 SendSentenceToAllInstruments(
1317 m_atmp_watchdog = no_nav_watchdog_timeout_ticks;
1321 if (m_pri_hum >= 4) {
1322 double humidity = m_nmea0183.Mda.Humidity;
1323 if (!std::isnan(humidity)) {
1325 m_hum_watchdog = no_nav_watchdog_timeout_ticks;
1331 }
else if (m_nmea0183.LastSentenceIDReceived ==
"MTW") {
1332 if (m_pri_wtp >= 4) {
1333 if (m_nmea0183.Parse()) {
1335 SendSentenceToAllInstruments(
1339 m_wtp_watchdog = no_nav_watchdog_timeout_ticks;
1343 }
else if (m_nmea0183.LastSentenceIDReceived ==
"VLW") {
1344 if (m_nmea0183.Parse()) {
1349 SendSentenceToAllInstruments(
1352 g_iDashDistanceUnit),
1354 m_tr_log_watchdog = no_nav_watchdog_timeout_ticks;
1356 if (!g_bUseInternSumLog) {
1357 SendSentenceToAllInstruments(
1360 g_iDashDistanceUnit),
1362 m_log_watchdog = no_nav_watchdog_timeout_ticks;
1368 else if (m_nmea0183.LastSentenceIDReceived ==
"MWD") {
1369 if (m_pri_wdn >= 6) {
1370 if (m_nmea0183.Parse()) {
1373 if (!std::isnan(m_nmea0183.Mwd.WindAngleTrue)) {
1375 SendSentenceToAllInstruments(
1379 m_wdn_watchdog = no_nav_watchdog_timeout_ticks;
1380 }
else if (!std::isnan(m_nmea0183.Mwd.WindAngleMagnetic)) {
1382 if (!std::isnan(m_var)) {
1383 double twd = m_nmea0183.Mwd.WindAngleMagnetic;
1387 }
else if (twd < 0.) {
1392 m_wdn_watchdog = no_nav_watchdog_timeout_ticks;
1395 SendSentenceToAllInstruments(
1398 g_iDashWindSpeedUnit),
1400 SendSentenceToAllInstruments(
1403 g_iDashWindSpeedUnit),
1405 m_mwvt_watchdog = gps_watchdog_timeout_ticks;
1412 else if (m_nmea0183.LastSentenceIDReceived ==
"MWV") {
1413 if (m_pri_awa >= 4 || m_pri_twa >= 5 || m_pri_wdn >= 5) {
1414 if (m_nmea0183.Parse()) {
1415 if (m_nmea0183.Mwv.IsDataValid == NTrue) {
1418 double m_wSpeedFactor = 1.0;
1419 if (m_nmea0183.Mwv.WindSpeedUnits ==
"K")
1420 m_wSpeedFactor = 0.53995;
1421 if (m_nmea0183.Mwv.WindSpeedUnits ==
"M")
1422 m_wSpeedFactor = 1.94384;
1424 if (m_nmea0183.Mwv.Reference ==
"R")
1426 if (m_pri_awa >= 4) {
1430 if (m_nmea0183.Mwv.WindAngle > 180) {
1431 m_awaunit =
"\u00B0L";
1432 m_awaangle = 180.0 - (m_nmea0183.Mwv.WindAngle - 180.0);
1434 m_awaunit =
"\u00B0R";
1435 m_awaangle = m_nmea0183.Mwv.WindAngle;
1438 m_awa_filter.Filter(m_awaangle),
1440 SendSentenceToAllInstruments(
1443 m_aws_filter.Filter(m_nmea0183.Mwv.WindSpeed) *
1445 g_iDashWindSpeedUnit),
1447 m_mwva_watchdog = gps_watchdog_timeout_ticks;
1454 if (m_pri_wdn >= 8) {
1455 CalculateAndUpdateTWDS(
1456 m_nmea0183.Mwv.WindSpeed * m_wSpeedFactor,
1457 m_nmea0183.Mwv.WindAngle);
1459 m_wdn_watchdog = no_nav_watchdog_timeout_ticks;
1460 m_mwvt_watchdog = gps_watchdog_timeout_ticks;
1462 }
else if (m_nmea0183.Mwv.Reference ==
1465 if (m_pri_twa >= 5) {
1469 if (m_nmea0183.Mwv.WindAngle > 180) {
1470 m_twaunit =
"\u00B0L";
1471 m_twaangle = 180.0 - (m_nmea0183.Mwv.WindAngle - 180.0);
1473 m_twaunit =
"\u00B0R";
1474 m_twaangle = m_nmea0183.Mwv.WindAngle;
1479 if (m_pri_wdn >= 7) {
1484 if (g_dHDT < 361. && g_dHDT >= 0.0) {
1485 double g_dCalWdir = (m_nmea0183.Mwv.WindAngle) + g_dHDT;
1486 if (g_dCalWdir > 360.) {
1488 }
else if (g_dCalWdir < 0.) {
1494 m_wdn_watchdog = no_nav_watchdog_timeout_ticks;
1498 SendSentenceToAllInstruments(
1501 g_iDashWindSpeedUnit),
1503 SendSentenceToAllInstruments(
1506 g_iDashWindSpeedUnit),
1508 m_mwvt_watchdog = gps_watchdog_timeout_ticks;
1516 else if (m_nmea0183.LastSentenceIDReceived ==
"RMC") {
1517 if (m_pri_position >= 5 || m_pri_cogsog >= 3 || m_pri_var >= 4 ||
1518 m_pri_date_time >= 3) {
1519 if (m_nmea0183.Parse()) {
1520 if (m_nmea0183.Rmc.IsDataValid == NTrue) {
1521 if (m_pri_position >= 5) {
1525 static_cast<float>(m_nmea0183.Rmc.Position.Latitude.Latitude);
1526 int lat_deg_int = (int)(llt / 100);
1527 auto lat_deg =
static_cast<float>(lat_deg_int);
1528 float lat_min = llt - (lat_deg * 100);
1529 lat = lat_deg + (lat_min / 60.);
1530 if (m_nmea0183.Rmc.Position.Latitude.Northing == South)
1534 auto lln =
static_cast<float>(
1535 m_nmea0183.Rmc.Position.Longitude.Longitude);
1536 int lon_deg_int = (int)(lln / 100);
1537 auto lon_deg =
static_cast<float>(lon_deg_int);
1538 float lon_min = lln - (lon_deg * 100);
1539 lon = lon_deg + (lon_min / 60.);
1540 if (m_nmea0183.Rmc.Position.Longitude.Easting == West) lon = -lon;
1544 if (m_pri_cogsog >= 3) {
1546 if (!std::isnan(m_nmea0183.Rmc.SpeedOverGroundKnots)) {
1547 SendSentenceToAllInstruments(
1550 m_nmea0183.Rmc.SpeedOverGroundKnots),
1555 if (!std::isnan(m_nmea0183.Rmc.TrackMadeGoodDegreesTrue)) {
1556 SendSentenceToAllInstruments(
1558 m_cog_filter.Filter(
1559 m_nmea0183.Rmc.TrackMadeGoodDegreesTrue),
1562 if (!std::isnan(m_nmea0183.Rmc.TrackMadeGoodDegreesTrue) &&
1563 !std::isnan(m_nmea0183.Rmc.MagneticVariation)) {
1564 double dMagneticCOG;
1565 if (m_nmea0183.Rmc.MagneticVariationDirection == East) {
1567 m_cog_filter.get() - m_nmea0183.Rmc.MagneticVariation;
1568 if (dMagneticCOG < 0.0) dMagneticCOG = 360.0 + dMagneticCOG;
1571 m_cog_filter.get() + m_nmea0183.Rmc.MagneticVariation;
1572 if (dMagneticCOG > 360.0) dMagneticCOG = dMagneticCOG - 360.0;
1579 if (m_pri_var >= 4) {
1583 if ((!std::isnan(m_nmea0183.Rmc.MagneticVariation)) &&
1584 0.0 != m_nmea0183.Rmc.MagneticVariation) {
1586 if (m_nmea0183.Rmc.MagneticVariationDirection == East)
1587 m_var = m_nmea0183.Rmc.MagneticVariation;
1588 else if (m_nmea0183.Rmc.MagneticVariationDirection == West)
1589 m_var = -m_nmea0183.Rmc.MagneticVariation;
1590 m_var_watchdog = gps_watchdog_timeout_ticks;
1596 if (m_pri_date_time >= 3) {
1597 m_pri_date_time = 3;
1598 wxString dt = m_nmea0183.Rmc.Date + m_nmea0183.Rmc.UTCTime;
1599 m_utc_date_time.ParseFormat(dt.c_str(),
"%d%m%y%H%M%S");
1600 m_utc_watchdog = gps_watchdog_timeout_ticks;
1607 else if (m_nmea0183.LastSentenceIDReceived ==
"RSA") {
1608 if (m_pri_rsa >= 3) {
1609 if (m_nmea0183.Parse()) {
1610 if (m_nmea0183.Rsa.IsStarboardDataValid == NTrue) {
1612 m_nmea0183.Rsa.Starboard,
"\u00B0");
1613 }
else if (m_nmea0183.Rsa.IsPortDataValid == NTrue) {
1617 m_rsa_watchdog = gps_watchdog_timeout_ticks;
1623 else if (m_nmea0183.LastSentenceIDReceived ==
"VHW") {
1624 if (m_pri_heading_t >= 4 || m_pri_heading_m >= 5 || m_pri_stw >= 3) {
1625 if (m_nmea0183.Parse()) {
1626 if (m_pri_heading_t >= 4) {
1627 if (!std::isnan(m_nmea0183.Vhw.DegreesTrue)) {
1628 m_pri_heading_t = 4;
1629 SendSentenceToAllInstruments(
1631 m_hdt_watchdog = gps_watchdog_timeout_ticks;
1634 if (m_pri_heading_m >= 5) {
1635 if (!std::isnan(m_nmea0183.Vhw.DegreesMagnetic)) {
1636 m_pri_heading_m = 5;
1637 SendSentenceToAllInstruments(
1639 m_h_dx_watchdog = gps_watchdog_timeout_ticks;
1642 if (m_pri_stw >= 3) {
1643 double stw_kn = NAN;
1644 if (!std::isnan(m_nmea0183.Vhw.Knots))
1645 stw_kn = m_nmea0183.Vhw.Knots;
1646 else if (!std::isnan(m_nmea0183.Vhw.KilometersPerHour))
1647 stw_kn = m_nmea0183.Vhw.KilometersPerHour * 0.53995;
1649 if (!std::isnan(stw_kn)) {
1650 SendSentenceToAllInstruments(
1653 m_stw_watchdog = gps_watchdog_timeout_ticks;
1661 else if (m_nmea0183.LastSentenceIDReceived ==
"VTG") {
1662 if (m_pri_cogsog >= 2) {
1663 if (m_nmea0183.Parse()) {
1666 if (!std::isnan(m_nmea0183.Vtg.SpeedKnots)) {
1667 SendSentenceToAllInstruments(
1670 m_sog_filter.Filter(m_nmea0183.Vtg.SpeedKnots),
1675 if (!std::isnan(m_nmea0183.Vtg.TrackDegreesTrue)) {
1676 SendSentenceToAllInstruments(
1678 m_cog_filter.Filter(m_nmea0183.Vtg.TrackDegreesTrue),
"\u00B0");
1691 else if (m_nmea0183.LastSentenceIDReceived ==
"VWR") {
1692 if (m_pri_awa >= 3) {
1693 if (m_nmea0183.Parse()) {
1694 if (m_nmea0183.Vwr.WindDirectionMagnitude < 200) {
1699 m_nmea0183.Vwr.DirectionOfWind == Left ?
"\u00B0L" :
"\u00B0R";
1701 m_nmea0183.Vwr.WindDirectionMagnitude,
1703 SendSentenceToAllInstruments(
1706 g_iDashWindSpeedUnit),
1708 m_mwva_watchdog = gps_watchdog_timeout_ticks;
1719 if (m_pri_wdn >= 9) {
1720 double awa = m_nmea0183.Vwr.WindDirectionMagnitude;
1721 if (m_nmea0183.Vwr.DirectionOfWind == Left)
1722 awa = 360. - m_nmea0183.Vwr.WindDirectionMagnitude;
1723 CalculateAndUpdateTWDS(m_nmea0183.Vwr.WindSpeedKnots, awa);
1725 m_mwvt_watchdog = gps_watchdog_timeout_ticks;
1726 m_wdn_watchdog = no_nav_watchdog_timeout_ticks;
1737 else if (m_nmea0183.LastSentenceIDReceived ==
"VWT") {
1738 if (m_pri_twa >= 4) {
1739 if (m_nmea0183.Parse()) {
1740 if (m_nmea0183.Vwt.WindDirectionMagnitude < 200) {
1744 m_nmea0183.Vwt.DirectionOfWind == Left ?
"\u00B0L" :
"\u00B0R";
1746 m_nmea0183.Vwt.WindDirectionMagnitude,
1748 SendSentenceToAllInstruments(
1751 g_iDashWindSpeedUnit),
1753 m_mwvt_watchdog = gps_watchdog_timeout_ticks;
1763 else if (m_nmea0183.LastSentenceIDReceived ==
1778 if (m_nmea0183.Parse()) {
1781 for (
int i = 0; i < m_nmea0183.Xdr.TransducerCnt; i++) {
1782 xdrdata = m_nmea0183.Xdr.TransducerInfo[i].MeasurementData;
1784 if (m_nmea0183.Xdr.TransducerInfo[i].TransducerType ==
"C") {
1785 if (m_nmea0183.Xdr.TransducerInfo[i]
1786 .TransducerName.Upper()
1788 m_nmea0183.Xdr.TransducerInfo[i].TransducerName ==
"Te" ||
1789 m_nmea0183.Xdr.TransducerInfo[i].TransducerName ==
1791 m_nmea0183.Xdr.TransducerInfo[i].TransducerName ==
1793 if (m_pri_atmp >= 4) {
1795 SendSentenceToAllInstruments(
1799 m_atmp_watchdog = no_nav_watchdog_timeout_ticks;
1803 if (m_nmea0183.Xdr.TransducerInfo[i]
1804 .TransducerName.Upper()
1805 .Contains(
"WATER") ||
1806 m_nmea0183.Xdr.TransducerInfo[i].TransducerName ==
"WTHI") {
1807 if (m_pri_wtp >= 3) {
1809 SendSentenceToAllInstruments(
1812 m_nmea0183.Xdr.TransducerInfo[i].MeasurementData,
1815 m_wtp_watchdog = no_nav_watchdog_timeout_ticks;
1821 if (m_nmea0183.Xdr.TransducerInfo[i].TransducerType ==
"P") {
1822 if (m_nmea0183.Xdr.TransducerInfo[i]
1823 .TransducerName.Upper()
1824 .Contains(
"BARO") &&
1826 if (m_nmea0183.Xdr.TransducerInfo[i].UnitOfMeasurement ==
"B") {
1830 m_mda_watchdog = no_nav_watchdog_timeout_ticks;
1836 if (m_nmea0183.Xdr.TransducerInfo[i].TransducerType ==
"A") {
1837 if (m_nmea0183.Xdr.TransducerInfo[i].TransducerName.Contains(
1839 m_nmea0183.Xdr.TransducerInfo[i]
1840 .TransducerName.Upper()
1841 .Contains(
"PITCH")) {
1842 if (m_pri_pitch_roll >= 3) {
1843 if (m_nmea0183.Xdr.TransducerInfo[i].MeasurementData > 0) {
1844 xdrunit = L
"\u00B0\u2191" + _(
"Up");
1845 }
else if (m_nmea0183.Xdr.TransducerInfo[i].MeasurementData <
1847 xdrunit = L
"\u00B0\u2193" + _(
"Down");
1854 m_pitch_watchdog = gps_watchdog_timeout_ticks;
1855 m_pri_pitch_roll = 3;
1860 if (m_nmea0183.Xdr.TransducerInfo[i]
1861 .TransducerName.Upper()
1862 .Contains(
"ROLL")) {
1863 if (m_pri_pitch_roll >= 3) {
1864 if (m_nmea0183.Xdr.TransducerInfo[i].MeasurementData > 0) {
1865 xdrunit = L
"\u00B0\u003E" + _(
"Stbd");
1866 }
else if (m_nmea0183.Xdr.TransducerInfo[i].MeasurementData <
1868 xdrunit = L
"\u00B0\u003C" + _(
"Port");
1875 m_heel_watchdog = gps_watchdog_timeout_ticks;
1876 m_pri_pitch_roll = 3;
1881 if (m_nmea0183.Xdr.TransducerInfo[i]
1882 .TransducerName.Upper()
1883 .Contains(
"RUDDER")) {
1884 if (m_pri_rsa > 4) {
1887 m_rsa_watchdog = gps_watchdog_timeout_ticks;
1894 if ((m_nmea0183.Xdr.TransducerInfo[i].TransducerType ==
"D")) {
1895 bool good_depth =
false;
1896 if (m_nmea0183.Xdr.TransducerInfo[i].TransducerName ==
"XDHI" &&
1900 }
else if (m_nmea0183.Xdr.TransducerInfo[i].TransducerName ==
1907 else if (m_nmea0183.Xdr.TransducerInfo[i].TransducerName ==
1909 m_nmea0183.Xdr.TransducerInfo[i].TransducerName ==
1912 m_nmea0183.Xdr.TransducerInfo[i].UnitOfMeasurement;
1913 if (
unit == wxEmptyString)
unit =
"m";
1916 m_wcc_watchdog = no_nav_watchdog_timeout_ticks;
1920 wxString
unit = m_nmea0183.Xdr.TransducerInfo[i]
1921 .UnitOfMeasurement.MakeLower();
1925 if (!std::isnan(depth)) {
1926 depth += g_dDashDBTOffset;
1927 SendSentenceToAllInstruments(
1931 m_dpt_dbt_watchdog = gps_watchdog_timeout_ticks;
1937 if (m_nmea0183.Xdr.TransducerInfo[i].TransducerType ==
"H") {
1938 if (m_pri_hum >= 3) {
1939 if (m_nmea0183.Xdr.TransducerInfo[i].UnitOfMeasurement ==
"P") {
1942 m_hum_watchdog = no_nav_watchdog_timeout_ticks;
1948 }
else if (m_nmea0183.LastSentenceIDReceived ==
"ZDA") {
1949 if (m_pri_date_time >= 2) {
1950 if (m_nmea0183.Parse()) {
1951 m_pri_date_time = 2;
1961 dt.Printf(
"%4d%02d%02d", m_nmea0183.Zda.Year, m_nmea0183.Zda.Month,
1962 m_nmea0183.Zda.Day);
1963 dt.Append(m_nmea0183.Zda.UTCTime);
1964 m_utc_date_time.ParseFormat(dt.c_str(),
"%Y%m%d%H%M%S");
1965 m_utc_watchdog = gps_watchdog_timeout_ticks;
1971 else if (sentence.Mid(1, 5).IsSameAs(
"AIVDO")) {
1974 if (!std::isnan(gpd.
Lat))
1977 if (!std::isnan(gpd.
Lon))
1980 SendSentenceToAllInstruments(
1985 m_cog_filter.Filter(gpd.
Cog),
"\u00B0");
1986 if (!std::isnan(gpd.
Hdt)) {
1988 m_hdt_watchdog = gps_watchdog_timeout_ticks;
1999void dashboard_pi::CalculateAndUpdateTWDS(
double awsKnots,
double awaDegrees) {
2000 if (!std::isnan(g_dHDT)) {
2002 double awsx = awsKnots * cos(awaDegrees * PI / 180.);
2003 double awsy = awsKnots * sin(awaDegrees * PI / 180.);
2008 if ((!std::isnan(g_dSOG)) && (!std::isnan(g_dCOG))) {
2009 bsx = g_dSOG * cos((g_dCOG - g_dHDT) * PI / 180.);
2010 bsy = g_dSOG * sin((g_dCOG - g_dHDT) * PI / 180.);
2015 double twdx = awsx - bsx;
2016 double twdy = awsy - bsy;
2019 double tws = pow(((twdx * twdx) + (twdy * twdy)), 0.5);
2022 double twd = atan2(twdy, twdx) * 180. / PI;
2029 double twdc = twd + g_dHDT;
2032 if (twdc < 0) twdc += 360.;
2033 if (twdc > 360.) twdc -= 360;
2052void dashboard_pi::HandleN2K_127245(
ObservedEvt &ev) {
2057 unsigned char source_id = v.at(7);
2059 sprintf(ss,
"%d", source_id);
2060 std::string ident = std::string(ss);
2062 source +=
":" + ident;
2064 if (m_pri_rsa >= 1) {
2065 if (m_pri_rsa == 1) {
2067 if (source != prio127245)
return;
2070 prio127245 = source;
2073 double RudderPosition, AngleOrder;
2074 unsigned char Instance;
2075 tN2kRudderDirectionOrder RudderDirectionOrder;
2078 if (ParseN2kPGN127245(v, RudderPosition, Instance, RudderDirectionOrder,
2080 if (!N2kIsNA(RudderPosition)) {
2081 double m_rudangle = GEODESIC_RAD2DEG(RudderPosition);
2083 m_rsa_watchdog = gps_watchdog_timeout_ticks;
2091void dashboard_pi::HandleN2K_127257(
ObservedEvt &ev) {
2096 unsigned char source_id = v.at(7);
2098 sprintf(ss,
"%d", source_id);
2099 std::string ident = std::string(ss);
2101 source +=
":" + ident;
2103 if (m_pri_pitch_roll >= 1) {
2104 if (m_pri_pitch_roll == 1) {
2106 if (source != prio127257)
return;
2109 prio127257 = source;
2113 double Yaw, Pitch, Roll;
2116 if (ParseN2kPGN127257(v, SID, Yaw, Pitch, Roll)) {
2117 if (!N2kIsNA(Pitch)) {
2118 double m_pitch = GEODESIC_RAD2DEG(Pitch);
2119 wxString p_unit = L
"\u00B0\u2191" + _(
"Up");
2121 p_unit = L
"\u00B0\u2193" + _(
"Down");
2125 m_pitch_watchdog = gps_watchdog_timeout_ticks;
2126 m_pri_pitch_roll = 1;
2128 if (!N2kIsNA(Roll)) {
2129 double m_heel = GEODESIC_RAD2DEG(Roll);
2130 wxString h_unit = L
"\u00B0\u003E" + _(
"Stbd");
2132 h_unit = L
"\u00B0\u003C" + _(
"Port");
2136 m_heel_watchdog = gps_watchdog_timeout_ticks;
2137 m_pri_pitch_roll = 1;
2143void dashboard_pi::HandleN2K_128267(
ObservedEvt &ev) {
2148 unsigned char source_id = v.at(7);
2150 sprintf(ss,
"%d", source_id);
2151 std::string ident = std::string(ss);
2153 source +=
":" + ident;
2155 if (m_pri_depth >= 1) {
2156 if (m_pri_depth == 1) {
2157 if (source != prio128267)
return;
2159 prio128267 = source;
2163 double DepthBelowTransducer, Offset, Range;
2166 if (ParseN2kPGN128267(v, SID, DepthBelowTransducer, Offset, Range)) {
2167 if (!N2kIsNA(DepthBelowTransducer)) {
2168 double depth = DepthBelowTransducer;
2170 if (!std::isnan(Offset) && !N2kIsNA(Offset))
2173 (depth += g_dDashDBTOffset);
2175 SendSentenceToAllInstruments(
2180 m_dpt_dbt_watchdog = gps_watchdog_timeout_ticks;
2186void dashboard_pi::HandleN2K_128275(
ObservedEvt &ev) {
2189 uint16_t DaysSince1970;
2190 double SecondsSinceMidnight;
2191 uint32_t Log, TripLog;
2194 if (ParseN2kPGN128275(v, DaysSince1970, SecondsSinceMidnight, Log, TripLog)) {
2195 if (!N2kIsNA(Log) && !g_bUseInternSumLog) {
2196 double m_slog = METERS2NM((
double)Log);
2197 SendSentenceToAllInstruments(
2200 m_log_watchdog = no_nav_watchdog_timeout_ticks;
2203 if (!N2kIsNA(TripLog)) {
2204 double m_tlog = METERS2NM((
double)TripLog);
2205 SendSentenceToAllInstruments(
2208 m_tr_log_watchdog = no_nav_watchdog_timeout_ticks;
2212void dashboard_pi::HandleN2K_128259(
ObservedEvt &ev) {
2217 unsigned char source_id = v.at(7);
2219 sprintf(ss,
"%d", source_id);
2220 std::string ident = std::string(ss);
2222 source +=
":" + ident;
2224 if (m_pri_stw >= 1) {
2225 if (m_pri_stw == 1) {
2226 if (source != prio128259)
return;
2228 prio128259 = source;
2232 double WaterReferenced, GroundReferenced;
2233 tN2kSpeedWaterReferenceType SWRT;
2236 if (ParseN2kPGN128259(v, SID, WaterReferenced, GroundReferenced, SWRT)) {
2237 if (!N2kIsNA(WaterReferenced)) {
2238 double stw_knots = MS2KNOTS(WaterReferenced);
2239 SendSentenceToAllInstruments(
2243 m_stw_watchdog = gps_watchdog_timeout_ticks;
2249void dashboard_pi::HandleN2K_128777(
ObservedEvt &ev) {
2254 unsigned char WindlassIdentifier;
2255 double RodeCounterValue;
2256 double WindlassLineSpeed;
2257 tN2kWindlassMotionStates WindlassMotionStatus;
2258 tN2kRodeTypeStates RodeTypeStatus;
2259 tN2kAnchorDockingStates AnchorDockingStatus;
2260 tN2kWindlassOperatingEvents WindlassOperatingEvents;
2262 if (ParseN2kPGN128777(v, SID, WindlassIdentifier, RodeCounterValue,
2263 WindlassLineSpeed, WindlassMotionStatus, RodeTypeStatus,
2264 AnchorDockingStatus, WindlassOperatingEvents)) {
2265 if (!N2kIsNA(RodeCounterValue)) {
2267 m_wcc_watchdog = no_nav_watchdog_timeout_ticks;
2272wxString talker_N2k = wxEmptyString;
2273void dashboard_pi::HandleN2K_129029(
ObservedEvt &ev) {
2277 unsigned char source_id = v.at(7);
2279 sprintf(ss,
"%d", source_id);
2280 std::string ident = std::string(ss);
2282 std::string prio_ID(prioN2kPGNsat.substr(prioN2kPGNsat.find(
':') + 1, 5));
2283 if (prio_ID.find(ident) == std::string::npos)
return;
2286 uint16_t DaysSince1970;
2287 double SecondsSinceMidnight;
2288 double Latitude, Longitude, Altitude;
2289 tN2kGNSStype GNSStype;
2290 tN2kGNSSmethod GNSSmethod;
2291 unsigned char nSatellites;
2292 double HDOP, PDOP, GeoidalSeparation;
2293 unsigned char nReferenceStations;
2294 tN2kGNSStype ReferenceStationType;
2295 uint16_t ReferenceSationID;
2296 double AgeOfCorrection;
2299 if (ParseN2kPGN129029(v, SID, DaysSince1970, SecondsSinceMidnight, Latitude,
2300 Longitude, Altitude, GNSStype, GNSSmethod, nSatellites,
2301 HDOP, PDOP, GeoidalSeparation, nReferenceStations,
2302 ReferenceStationType, ReferenceSationID,
2312 talker_N2k =
"GPSGLONAS";
2318 talker_N2k =
"GPSGLONAS";
2321 talker_N2k =
"Chayka";
2327 talker_N2k = wxEmptyString;
2329 if (!N2kIsNA(Altitude)) {
2330 if (m_pri_alt >= 1) {
2333 m_alt_watchdog = gps_watchdog_timeout_ticks;
2339void dashboard_pi::HandleN2K_129540(
ObservedEvt &ev) {
2344 unsigned char source_id = v.at(7);
2346 sprintf(ss,
"%d", source_id);
2347 std::string ident = std::string(ss);
2349 std::string prio_ID(prioN2kPGNsat.substr(prioN2kPGNsat.find(
':') + 1, 5));
2350 if (prio_ID.find(ident) == std::string::npos)
return;
2353 tN2kRangeResidualMode Mode;
2354 uint8_t NumberOfSVs;
2357 if (ParseN2kPGN129540(v, SID, Mode, NumberOfSVs)) {
2358 if (!N2kIsNA(NumberOfSVs) && m_pri_sat_status == 1) {
2361 SAT_INFO N2K_SatInfo[4];
2364 double dElevRad = 0;
2365 double dAzimRad = 0;
2368 for (
int iMesNum = 0; iMesNum < 3; iMesNum++) {
2369 for (idx = 0; idx < 4; idx++) {
2370 tSatelliteInfo SatelliteInfo;
2371 index = idx + 4 * iMesNum;
2372 if (index >= NumberOfSVs - 1)
break;
2373 if (ParseN2kPGN129540(v, index, SatelliteInfo)) {
2374 iPRN = (int)SatelliteInfo.PRN;
2375 dElevRad = SatelliteInfo.Elevation;
2376 dAzimRad = SatelliteInfo.Azimuth;
2377 iSNR = N2kIsNA(SatelliteInfo.SNR) ? 0 : (int)SatelliteInfo.SNR;
2379 N2K_SatInfo[idx].SatNumber = iPRN;
2380 N2K_SatInfo[idx].ElevationDegrees = GEODESIC_RAD2DEG(dElevRad);
2381 N2K_SatInfo[idx].AzimuthDegreesTrue = GEODESIC_RAD2DEG(dAzimRad);
2382 N2K_SatInfo[idx].SignalToNoiseRatio = iSNR;
2387 SendSatInfoToAllInstruments(NumberOfSVs, iMesNum + 1, talker_N2k,
2390 m_sat_status_wdog = gps_watchdog_timeout_ticks;
2398void dashboard_pi::HandleN2K_130306(
ObservedEvt &ev) {
2406 double WindSpeed, WindAngle;
2407 tN2kWindReference WindReference;
2410 if (ParseN2kPGN130306(v, SID, WindSpeed, WindAngle, WindReference)) {
2411 if (!N2kIsNA(WindSpeed) && !N2kIsNA(WindAngle)) {
2412 double wind_angle_degr = GEODESIC_RAD2DEG(WindAngle);
2413 double wind_speed_kn = MS2KNOTS(WindSpeed);
2414 bool sendTWA =
false, sendTWS =
false;
2416 switch (WindReference) {
2418 if (m_pri_wdn >= 1) {
2423 m_wdn_watchdog = no_nav_watchdog_timeout_ticks;
2427 if (m_pri_wdn >= 1) {
2429 if (!std::isnan(m_var)) {
2430 wind_angle_degr += m_var;
2431 if (wind_angle_degr > 360.) {
2432 wind_angle_degr -= 360;
2433 }
else if (wind_angle_degr < 0.) {
2434 wind_angle_degr += 360;
2441 m_wdn_watchdog = no_nav_watchdog_timeout_ticks;
2445 if (m_pri_awa >= 1) {
2446 double calc_angle = wind_angle_degr;
2448 wxString m_awaunit =
"\u00B0R";
2450 if (wind_angle_degr > 180.0) {
2451 wind_angle_degr = 360.0 - wind_angle_degr;
2452 m_awaunit =
"\u00B0L";
2455 m_awa_filter.Filter(wind_angle_degr),
2458 SendSentenceToAllInstruments(
2461 g_iDashWindSpeedUnit),
2465 m_mwva_watchdog = gps_watchdog_timeout_ticks;
2468 if (m_pri_twa != 1) {
2470 if (calc_angle > 180) calc_angle -= 360.0;
2471 CalculateAndUpdateTWDS(wind_speed_kn, calc_angle);
2474 m_mwvt_watchdog = gps_watchdog_timeout_ticks;
2475 m_wdn_watchdog = no_nav_watchdog_timeout_ticks;
2480 if (m_pri_twa >= 1 && g_bDBtrueWindGround) {
2487 if (m_pri_twa >= 1 && !g_bDBtrueWindGround) {
2501 wxString m_twaunit =
"\u00B0R";
2503 if (wind_angle_degr > 180.0) {
2504 wind_angle_degr = 360.0 - wind_angle_degr;
2505 m_twaunit =
"\u00B0L";
2513 SendSentenceToAllInstruments(
2517 SendSentenceToAllInstruments(
2521 m_mwvt_watchdog = gps_watchdog_timeout_ticks;
2527void dashboard_pi::HandleN2K_130310(
ObservedEvt &ev) {
2531 double WaterTemperature, OutsideAmbientAirTemperature, AtmosphericPressure;
2534 if (ParseN2kPGN130310(v, SID, WaterTemperature, OutsideAmbientAirTemperature,
2535 AtmosphericPressure)) {
2536 if (m_pri_wtp >= 1) {
2537 if (!N2kIsNA(WaterTemperature)) {
2538 double m_wtemp KELVIN2C(WaterTemperature);
2543 m_wtp_watchdog = no_nav_watchdog_timeout_ticks;
2547 if (m_pri_atmp >= 1) {
2548 if (!N2kIsNA(OutsideAmbientAirTemperature)) {
2549 double m_airtemp = KELVIN2C(OutsideAmbientAirTemperature);
2550 if (m_airtemp > -60 && m_airtemp < 100) {
2551 SendSentenceToAllInstruments(
2555 m_atmp_watchdog = no_nav_watchdog_timeout_ticks;
2560 if (!N2kIsNA(AtmosphericPressure) && m_pri_mda >= 1) {
2561 double m_press = PA2HPA(AtmosphericPressure);
2564 m_mda_watchdog = no_nav_watchdog_timeout_ticks;
2569void dashboard_pi::HandleN2K_130313(
ObservedEvt &ev) {
2572 unsigned char SID, HumidityInstance;
2573 tN2kHumiditySource HumiditySource;
2574 double ActualHumidity, SetHumidity;
2576 if (ParseN2kPGN130313(v, SID, HumidityInstance, HumiditySource,
2577 ActualHumidity, SetHumidity)) {
2578 if (m_pri_hum >= 1) {
2579 if (!N2kIsNA(ActualHumidity)) {
2582 m_hum_watchdog = no_nav_watchdog_timeout_ticks;
2589void dashboard_pi::ParseSignalK(wxString &msg) {
2599 if (root[
"self"].AsString().StartsWith(
"vessels."))
2600 m_self = (root[
"self"].
AsString());
2602 else if (root[
"self"].AsString().Length())
2603 m_self =
"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 ==
"navigation.position") {
2655 if (m_pri_position >= 2) {
2656 if (value[
"latitude"].IsDouble() && value[
"longitude"].IsDouble()) {
2657 double lat = value[
"latitude"].
AsDouble();
2658 double lon = value[
"longitude"].AsDouble();
2664 }
else if (update_path ==
"navigation.speedOverGround" &&
2665 2 == m_pri_position) {
2666 double sog_knot = GetJsonDouble(value);
2667 if (std::isnan(sog_knot))
return;
2669 SendSentenceToAllInstruments(
2673 }
else if (update_path ==
"navigation.courseOverGroundTrue" &&
2674 2 == m_pri_position) {
2675 double cog_rad = GetJsonDouble(value);
2676 if (std::isnan(cog_rad))
return;
2678 double cog_deg = GEODESIC_RAD2DEG(cog_rad);
2680 m_cog_filter.Filter(cog_deg),
"\u00B0");
2681 }
else if (update_path ==
"navigation.headingTrue") {
2682 if (m_pri_heading_t >= 2) {
2683 double hdt = GetJsonDouble(value);
2684 if (std::isnan(hdt))
return;
2686 hdt = GEODESIC_RAD2DEG(hdt);
2688 m_pri_heading_t = 2;
2689 m_hdt_watchdog = gps_watchdog_timeout_ticks;
2691 }
else if (update_path ==
"navigation.headingMagnetic") {
2692 if (m_pri_heading_m >= 2) {
2693 double hdm = GetJsonDouble(value);
2694 if (std::isnan(hdm))
return;
2696 hdm = GEODESIC_RAD2DEG(hdm);
2698 m_pri_heading_m = 2;
2699 m_h_dx_watchdog = gps_watchdog_timeout_ticks;
2702 if (m_pri_heading_t >= 6 && (!std::isnan(m_var))) {
2703 double heading = hdm + m_var;
2706 else if (heading >= 360.0)
2709 m_pri_heading_t = 6;
2710 m_hdt_watchdog = gps_watchdog_timeout_ticks;
2713 }
else if (update_path ==
"navigation.speedThroughWater") {
2714 if (m_pri_stw >= 2) {
2715 double stw_knots = GetJsonDouble(value);
2716 if (std::isnan(stw_knots))
return;
2718 stw_knots = MS2KNOTS(stw_knots);
2719 SendSentenceToAllInstruments(
2723 m_stw_watchdog = gps_watchdog_timeout_ticks;
2725 }
else if (update_path ==
"navigation.magneticVariation") {
2726 if (m_pri_var >= 2) {
2727 double dvar = GetJsonDouble(value);
2728 if (std::isnan(dvar))
return;
2730 dvar = GEODESIC_RAD2DEG(dvar);
2734 m_var_watchdog = gps_watchdog_timeout_ticks;
2737 }
else if (update_path ==
"environment.wind.angleApparent") {
2738 if (m_pri_awa >= 2) {
2739 double m_awaangle = GetJsonDouble(value);
2740 if (std::isnan(m_awaangle))
return;
2742 m_awaangle = GEODESIC_RAD2DEG(m_awaangle);
2744 wxString m_awaunit =
"\u00B0R";
2745 if (m_awaangle < 0) {
2746 m_awaunit =
"\u00B0L";
2749 SendSentenceToAllInstruments(
2753 m_mwva_watchdog = gps_watchdog_timeout_ticks;
2755 }
else if (update_path ==
"environment.wind.speedApparent") {
2756 if (m_pri_awa >= 2) {
2757 double m_awaspeed_kn = GetJsonDouble(value);
2758 if (std::isnan(m_awaspeed_kn))
return;
2760 m_awaspeed_kn = MS2KNOTS(m_awaspeed_kn);
2761 SendSentenceToAllInstruments(
2764 g_iDashWindSpeedUnit),
2768 if (m_pri_twa >= 6 && !std::isnan(skAWA)) {
2769 CalculateAndUpdateTWDS(m_awaspeed_kn, skAWA);
2771 m_mwvt_watchdog = gps_watchdog_timeout_ticks;
2772 m_wdn_watchdog = no_nav_watchdog_timeout_ticks;
2775 }
else if ((update_path ==
"environment.wind.angleTrueWater" &&
2776 !g_bDBtrueWindGround) ||
2777 (update_path ==
"environment.wind.angleTrueGround" &&
2778 g_bDBtrueWindGround)) {
2779 if (m_pri_twa >= 3) {
2780 double m_twaangle = GetJsonDouble(value);
2781 if (std::isnan(m_twaangle))
return;
2783 m_twaangle = GEODESIC_RAD2DEG(m_twaangle);
2784 double m_twaangle_raw = m_twaangle;
2785 wxString m_twaunit =
"\u00B0R";
2786 if (m_twaangle < 0) {
2787 m_twaunit =
"\u00B0L";
2793 m_mwvt_watchdog = gps_watchdog_timeout_ticks;
2795 if (m_pri_wdn >= 5) {
2800 if (g_dHDT < 361. && g_dHDT >= 0.0) {
2801 double g_dCalWdir = (m_twaangle_raw) + g_dHDT;
2802 if (g_dCalWdir > 360.) {
2804 }
else if (g_dCalWdir < 0.) {
2810 m_wdn_watchdog = no_nav_watchdog_timeout_ticks;
2814 }
else if ((update_path ==
"environment.wind.speedTrue" &&
2815 !g_bDBtrueWindGround) ||
2816 (update_path ==
"environment.wind.speedOverGround" &&
2817 g_bDBtrueWindGround)) {
2818 if (m_pri_twa >= 3) {
2819 double m_twaspeed_kn = GetJsonDouble(value);
2820 if (std::isnan(m_twaspeed_kn))
return;
2822 m_twaspeed_kn = MS2KNOTS(m_twaspeed_kn);
2823 SendSentenceToAllInstruments(
2827 SendSentenceToAllInstruments(
2832 }
else if (update_path ==
"environment.depth.belowSurface") {
2833 if (m_pri_depth >= 3) {
2834 double depth = GetJsonDouble(value);
2835 if (std::isnan(depth))
return;
2838 depth += g_dDashDBTOffset;
2840 SendSentenceToAllInstruments(
2843 m_dpt_dbt_watchdog = gps_watchdog_timeout_ticks;
2845 }
else if (update_path ==
"environment.depth.belowTransducer") {
2846 if (m_pri_depth >= 3) {
2847 double depth = GetJsonDouble(value);
2848 if (std::isnan(depth))
return;
2851 depth += g_dDashDBTOffset;
2853 SendSentenceToAllInstruments(
2856 m_dpt_dbt_watchdog = gps_watchdog_timeout_ticks;
2858 }
else if (update_path ==
"environment.water.temperature") {
2859 if (m_pri_wtp >= 2) {
2860 double m_wtemp = GetJsonDouble(value);
2861 if (std::isnan(m_wtemp))
return;
2863 m_wtemp = KELVIN2C(m_wtemp);
2864 if (m_wtemp > -60 && m_wtemp < 200 && !std::isnan(m_wtemp)) {
2865 SendSentenceToAllInstruments(
2869 m_wtp_watchdog = no_nav_watchdog_timeout_ticks;
2872 }
else if (update_path ==
2873 "navigation.courseRhumbline.nextPoint.velocityMadeGood") {
2874 double m_vmg_kn = GetJsonDouble(value);
2875 if (std::isnan(m_vmg_kn))
return;
2877 m_vmg_kn = MS2KNOTS(m_vmg_kn);
2878 SendSentenceToAllInstruments(
2881 m_vmg_watchdog = gps_watchdog_timeout_ticks;
2884 else if (update_path ==
"performance.velocityMadeGood") {
2885 double m_vmgw_kn = GetJsonDouble(value);
2886 if (std::isnan(m_vmgw_kn))
return;
2888 m_vmgw_kn = MS2KNOTS(m_vmgw_kn);
2889 SendSentenceToAllInstruments(
2892 m_vmgw_watchdog = gps_watchdog_timeout_ticks;
2895 else if (update_path ==
"steering.rudderAngle") {
2896 if (m_pri_rsa >= 2) {
2897 double m_rudangle = GetJsonDouble(value);
2898 if (std::isnan(m_rudangle))
return;
2900 m_rudangle = GEODESIC_RAD2DEG(m_rudangle);
2902 m_rsa_watchdog = gps_watchdog_timeout_ticks;
2905 }
else if (update_path ==
2906 "navigation.gnss.satellites") {
2907 if (m_pri_sat_used >= 2) {
2908 int usedSats = (value).AsInt();
2909 if (usedSats < 1)
return;
2912 m_sats_used_wdog = gps_watchdog_timeout_ticks;
2914 }
else if (update_path ==
"navigation.gnss.type") {
2915 if (value.IsString() && value.AsString() != wxEmptyString) {
2916 talkerID = (value.AsString());
2917 talkerID.MakeUpper();
2918 m_pri_n2_k_talker = gps_watchdog_timeout_ticks;
2919 if ((talkerID.Contains(
"GPS")) && (talkerID.Contains(
"GLONASS")))
2920 talkerID =
"GPSGLONAS";
2921 else if (talkerID.Contains(
"GPS"))
2923 else if (talkerID.Contains(
"GLONASS"))
2925 else if (talkerID.Contains(
"GALILEO"))
2927 else if (talkerID.Contains(
"BEIDOU"))
2930 }
else if (update_path ==
2931 "navigation.gnss.satellitesInView") {
2933 if (m_pri_sat_used >= 4) {
2934 if (value.HasMember(
"count") && value[
"count"].IsInt()) {
2935 double m_SK_SatsInView = (value[
"count"].AsInt());
2939 m_sats_used_wdog = gps_watchdog_timeout_ticks;
2942 if (m_pri_sat_status == 2) {
2943 if (value.HasMember(
"satellites") && value[
"satellites"].IsArray()) {
2946 if (value.HasMember(
"count") && value[
"count"].IsInt()) {
2947 iNumSats = (value[
"count"].AsInt());
2949 iNumSats = value[_T (
"satellites")].Size();
2951 SAT_INFO SK_SatInfo[4];
2952 for (
int idx = 0; idx < 4; idx++) {
2953 SK_SatInfo[idx].SatNumber = 0;
2954 SK_SatInfo[idx].ElevationDegrees = 0;
2955 SK_SatInfo[idx].AzimuthDegreesTrue = 0;
2956 SK_SatInfo[idx].SignalToNoiseRatio = 0;
2963 double dElevRad = 0;
2964 double dAzimRad = 0;
2967 for (
int iMesNum = 0; iMesNum < 3; iMesNum++) {
2968 for (idx = 0; idx < 4; idx++) {
2969 arr = idx + 4 * iMesNum;
2970 if (value[
"satellites"][arr][
"id"].IsInt())
2971 iID = value[
"satellites"][arr][
"id"].AsInt();
2972 if (value[
"satellites"][arr][
"elevation"].IsDouble())
2973 dElevRad = value[
"satellites"][arr][
"elevation"].AsDouble();
2974 if (value[
"satellites"][arr][
"azimuth"].IsDouble())
2975 dAzimRad = value[
"satellites"][arr][
"azimuth"].AsDouble();
2976 if (value[
"satellites"][arr][
"SNR"].IsInt())
2977 iSNR = value[
"satellites"][arr][
"SNR"].AsInt();
2980 SK_SatInfo[idx].SatNumber = iID;
2981 SK_SatInfo[idx].ElevationDegrees = GEODESIC_RAD2DEG(dElevRad);
2982 SK_SatInfo[idx].AzimuthDegreesTrue = GEODESIC_RAD2DEG(dAzimRad);
2983 SK_SatInfo[idx].SignalToNoiseRatio = iSNR;
2986 if (m_pri_n2_k_talker <= 0 && talker != wxEmptyString &&
2987 (talker.StartsWith(
"G") || talker.StartsWith(
"BD"))) {
2990 SendSatInfoToAllInstruments(iNumSats, iMesNum + 1, talkerID,
2993 m_sat_status_wdog = gps_watchdog_timeout_ticks;
3001 }
else if (update_path ==
"navigation.gnss.antennaAltitude") {
3002 if (m_pri_alt >= 2) {
3003 double m_alt = GetJsonDouble(value);
3004 if (std::isnan(m_alt))
return;
3008 m_alt_watchdog = gps_watchdog_timeout_ticks;
3011 }
else if (update_path ==
"navigation.datetime") {
3012 if (m_pri_date_time >= 1) {
3013 m_pri_date_time = 1;
3014 wxString s_dt = (value.AsString());
3015 s_dt.Replace(
'-', wxEmptyString);
3016 s_dt.Replace(
':', wxEmptyString);
3017 wxString utc_dt = s_dt.BeforeFirst(
'T');
3018 utc_dt.Append(s_dt.AfterFirst(
'T').Left(6));
3019 m_utc_date_time.ParseFormat(utc_dt.c_str(),
"%Y%m%d%H%M%S");
3020 m_utc_watchdog = gps_watchdog_timeout_ticks;
3022 }
else if (update_path ==
"environment.outside.temperature") {
3023 if (m_pri_atmp >= 2) {
3024 double m_airtemp = GetJsonDouble(value);
3025 if (std::isnan(m_airtemp))
return;
3027 m_airtemp = KELVIN2C(m_airtemp);
3028 if (m_airtemp > -60 && m_airtemp < 100) {
3029 SendSentenceToAllInstruments(
3033 m_atmp_watchdog = no_nav_watchdog_timeout_ticks;
3036 }
else if (update_path ==
"environment.outside.humidity" ||
3037 update_path ==
"environment.outside.relativeHumidity") {
3038 if (m_pri_hum >= 2) {
3039 double m_hum = GetJsonDouble(value) * 100;
3040 if (std::isnan(m_hum))
return;
3043 m_hum_watchdog = no_nav_watchdog_timeout_ticks;
3045 }
else if (update_path ==
3046 "environment.wind.directionTrue") {
3047 if (m_pri_wdn >= 3) {
3048 double m_twdT = GetJsonDouble(value);
3049 if (std::isnan(m_twdT))
return;
3051 m_twdT = GEODESIC_RAD2DEG(m_twdT);
3054 m_wdn_watchdog = no_nav_watchdog_timeout_ticks;
3056 }
else if (update_path ==
"environment.wind.directionMagnetic") {
3058 if (m_pri_wdn >= 4) {
3059 double m_twdM = GetJsonDouble(value);
3060 if (std::isnan(m_twdM))
return;
3061 m_twdM = GEODESIC_RAD2DEG(m_twdM);
3063 if (!std::isnan(m_var)) {
3064 m_twdM = (m_twdM) + m_var;
3065 if (m_twdM > 360.) {
3067 }
else if (m_twdM < 0.) {
3073 m_wdn_watchdog = no_nav_watchdog_timeout_ticks;
3075 }
else if (update_path ==
"navigation.trip.log") {
3076 double m_tlog = GetJsonDouble(value);
3077 if (std::isnan(m_tlog))
return;
3079 m_tlog = METERS2NM(m_tlog);
3080 SendSentenceToAllInstruments(
3083 m_tr_log_watchdog = no_nav_watchdog_timeout_ticks;
3084 }
else if (update_path ==
"navigation.log" && !g_bUseInternSumLog) {
3085 double m_slog = GetJsonDouble(value);
3086 if (std::isnan(m_slog))
return;
3088 m_slog = METERS2NM(m_slog);
3089 SendSentenceToAllInstruments(
3092 m_log_watchdog = no_nav_watchdog_timeout_ticks;
3093 }
else if (update_path ==
"environment.outside.pressure" &&
3095 double m_press = GetJsonDouble(value);
3096 if (std::isnan(m_press))
return;
3098 m_press = PA2HPA(m_press);
3101 m_mda_watchdog = no_nav_watchdog_timeout_ticks;
3102 }
else if (update_path ==
"navigation.attitude") {
3103 if (m_pri_pitch_roll >= 2) {
3104 if (value[
"roll"].AsString() !=
"0") {
3105 double m_heel = GEODESIC_RAD2DEG(value[
"roll"].AsDouble());
3106 wxString h_unit = L
"\u00B0\u003E" + _(
"Stbd");
3108 h_unit = L
"\u00B0\u003C" + _(
"Port");
3112 m_heel_watchdog = gps_watchdog_timeout_ticks;
3113 m_pri_pitch_roll = 2;
3115 if (value[
"pitch"].AsString() !=
"0") {
3116 double m_pitch = GEODESIC_RAD2DEG(value[
"pitch"].AsDouble());
3117 wxString p_unit = L
"\u00B0\u2191" + _(
"Up");
3119 p_unit = L
"\u00B0\u2193" + _(
"Down");
3123 m_pitch_watchdog = gps_watchdog_timeout_ticks;
3124 m_pri_pitch_roll = 2;
3133 if (m_pri_position >= 1) {
3138 if (m_pri_cogsog >= 1) {
3139 double dMagneticCOG;
3141 SendSentenceToAllInstruments(
3146 m_cog_filter.Filter(pfix.
Cog),
"\u00B0");
3149 double logSOG = m_sog_filter.Filter(pfix.
Sog);
3151 d_tripNM += logSOG / 3600;
3153 if (++logCount > 60) {
3160 dMagneticCOG = m_cog_filter.get() - pfix.
Var;
3161 if (dMagneticCOG < 0.0) dMagneticCOG = 360.0 + dMagneticCOG;
3162 if (dMagneticCOG > 360.0) dMagneticCOG = dMagneticCOG - 360.0;
3165 if (m_pri_var >= 1) {
3166 if (!std::isnan(pfix.
Var)) {
3169 m_var_watchdog = gps_watchdog_timeout_ticks;
3174 if (m_pri_date_time >= 6) {
3179 m_utc_date_time.Set(pfix.
FixTime);
3181 m_utc_date_time = wxInvalidDateTime;
3182 if (m_utc_date_time.IsValid()) {
3183 m_pri_date_time = 6;
3184 m_utc_date_time = m_utc_date_time.ToUTC();
3185 m_utc_watchdog = gps_watchdog_timeout_ticks;
3188 if (m_pri_sat_used >= 1) {
3189 m_sats_in_use = pfix.
nSats;
3190 if (m_sats_in_use > 0) {
3193 m_sats_used_wdog = gps_watchdog_timeout_ticks;
3196 if (m_pri_heading_t >= 1) {
3197 double hdt = pfix.
Hdt;
3198 if (std::isnan(hdt))
return;
3200 m_pri_heading_t = 1;
3201 m_hdt_watchdog = gps_watchdog_timeout_ticks;
3203 if (m_pri_heading_m >= 1) {
3204 double hdm = pfix.
Hdm;
3205 if (std::isnan(hdm) && !std::isnan(pfix.
Hdt) && !std::isnan(pfix.
Var)) {
3206 hdm = pfix.
Hdt - pfix.
Var;
3209 else if (hdm >= 360.0)
3212 if (std::isnan(hdm))
return;
3214 m_pri_heading_m = 1;
3215 m_h_dx_watchdog = gps_watchdog_timeout_ticks;
3224void dashboard_pi::SetPluginMessage(wxString &message_id,
3225 wxString &message_body) {
3226 if (message_id ==
"WMM_VARIATION_BOAT") {
3234 int numErrors = reader.
Parse(message_body, &root);
3235 if (numErrors > 0) {
3241 wxString decl = root[
"Decl"].
AsString();
3243 decl.ToDouble(&decl_val);
3245 if (m_pri_var >= 5) {
3248 m_var_watchdog = gps_watchdog_timeout_ticks;
3251 }
else if (message_id ==
"OCPN_CORE_SIGNALK") {
3252 ParseSignalK(message_body);
3260 parent, wxID_ANY, m_ArrayOfDashboardWindow);
3262 dialog->RecalculateSize();
3265 dialog->GetHandle()->setStyleSheet(qtStyleSheet);
3272 int xmax = ccwin->GetSize().GetWidth();
3273 int ymax = ccwin->GetParent()
3276 dialog->SetSize(xmax, ymax);
3283 if (dialog->ShowModal() == wxID_OK) {
3284 double scaler = 1.0;
3287 scaler = wxMax(1.0, scaler);
3289 g_USFontTitle = *(dialog->m_font_picker_title->GetFontData());
3290 g_FontTitle = *g_pUSFontTitle;
3291 g_FontTitle.SetChosenFont(g_pUSFontTitle->GetChosenFont().Scaled(scaler));
3292 g_FontTitle.SetColour(g_pUSFontTitle->GetColour());
3293 g_USFontTitle = *g_pUSFontTitle;
3295 g_USFontData = *(dialog->m_font_picker_data->GetFontData());
3296 g_FontData = *g_pUSFontData;
3297 g_FontData.SetChosenFont(g_pUSFontData->GetChosenFont().Scaled(scaler));
3298 g_FontData.SetColour(g_pUSFontData->GetColour());
3299 g_USFontData = *g_pUSFontData;
3301 g_USFontLabel = *(dialog->m_font_picker_label->GetFontData());
3302 g_FontLabel = *g_pUSFontLabel;
3303 g_FontLabel.SetChosenFont(g_pUSFontLabel->GetChosenFont().Scaled(scaler));
3304 g_FontLabel.SetColour(g_pUSFontLabel->GetColour());
3305 g_USFontLabel = *g_pUSFontLabel;
3307 g_USFontSmall = *(dialog->m_font_picker_small->GetFontData());
3308 g_FontSmall = *g_pUSFontSmall;
3309 g_FontSmall.SetChosenFont(g_pUSFontSmall->GetChosenFont().Scaled(scaler));
3310 g_FontSmall.SetColour(g_pUSFontSmall->GetColour());
3311 g_USFontSmall = *g_pUSFontSmall;
3315 g_dashPrefWidth = dialog->GetSize().x;
3316 g_dashPrefHeight = dialog->GetSize().y;
3318 dialog->SaveDashboardConfig();
3319 m_ArrayOfDashboardWindow.Clear();
3320 m_ArrayOfDashboardWindow = dialog->m_config;
3330 aktuellColorScheme = cs;
3331 for (
size_t i = 0; i < m_ArrayOfDashboardWindow.GetCount(); i++) {
3333 m_ArrayOfDashboardWindow.Item(i)->m_pDashboardWindow;
3334 if (dashboard_window) dashboard_window->SetColorScheme(cs);
3338int dashboard_pi::GetDashboardWindowShownCount() {
3341 for (
size_t i = 0; i < m_ArrayOfDashboardWindow.GetCount(); i++) {
3343 m_ArrayOfDashboardWindow.Item(i)->m_pDashboardWindow;
3344 if (dashboard_window) {
3345 wxAuiPaneInfo &pane = m_pauimgr->GetPane(dashboard_window);
3346 if (pane.IsOk() && pane.IsShown()) cnt++;
3352void dashboard_pi::OnPaneClose(wxAuiManagerEvent &event) {
3356 for (
size_t i = 0; i < m_ArrayOfDashboardWindow.GetCount(); i++) {
3361 if (dashboard_window != d_w) {
3362 wxAuiPaneInfo &pane = m_pauimgr->GetPane(d_w);
3363 if (pane.IsOk() && pane.IsShown()) cnt++;
3365 cont->m_bIsVisible =
false;
3375 int cnt = GetDashboardWindowShownCount();
3377 bool b_anyviz =
false;
3378 for (
size_t i = 0; i < m_ArrayOfDashboardWindow.GetCount(); i++) {
3380 if (cont->m_bIsVisible) {
3386 for (
size_t i = 0; i < m_ArrayOfDashboardWindow.GetCount(); i++) {
3389 if (dashboard_window) {
3390 wxAuiPaneInfo &pane = m_pauimgr->GetPane(dashboard_window);
3392 bool b_reset_pos =
false;
3399 RECT frame_title_rect;
3400 frame_title_rect.left = pane.floating_pos.x;
3401 frame_title_rect.top = pane.floating_pos.y;
3402 frame_title_rect.right = pane.floating_pos.x + pane.floating_size.x;
3403 frame_title_rect.bottom = pane.floating_pos.y + 30;
3405 if (NULL == MonitorFromRect(&frame_title_rect, MONITOR_DEFAULTTONULL))
3411 wxRect window_title_rect;
3412 window_title_rect.x = pane.floating_pos.x;
3413 window_title_rect.y = pane.floating_pos.y;
3414 window_title_rect.width = pane.floating_size.x;
3415 window_title_rect.height = 30;
3417 wxRect ClientRect = wxGetClientDisplayRect();
3420 if (!ClientRect.Intersects(window_title_rect)) b_reset_pos =
true;
3424 if (b_reset_pos) pane.FloatingPosition(50, 50);
3428 pane.Show(cont->m_bIsVisible);
3430 cont->m_bIsVisible = cont->m_bPersVisible;
3431 pane.Show(cont->m_bIsVisible);
3438 if (pane.IsShown() && pane.IsDocked()) {
3439 pane.BestSize(cont->m_best_size);
3440 m_pauimgr->Update();
3451 if ((pane.dock_direction == wxAUI_DOCK_BOTTOM) && pane.IsDocked())
3458 GetDashboardWindowShownCount() != 0 );
3459 m_pauimgr->Update();
3469 for (
size_t i = 0; i < m_ArrayOfDashboardWindow.GetCount(); i++) {
3471 wxAuiPaneInfo &pane = m_pauimgr->GetPane(cont->m_pDashboardWindow);
3473 cont->m_bIsVisible = (pane.IsOk() && pane.IsShown());
3477 if (pane.IsDocked()) {
3478 if ((cont->m_persist_size.x > 50) && (cont->m_persist_size.y > 50))
3479 cont->m_pDashboardWindow->SetSize(cont->m_persist_size);
3483 if (pane.IsShown()) {
3485 m_pauimgr->Update();
3487 m_pauimgr->Update();
3491 m_pauimgr->Update();
3499bool dashboard_pi::LoadConfig() {
3500 auto *pConf = (wxFileConfig *)m_pconfig;
3503 pConf->SetPath(
"/PlugIns/Dashboard");
3506 pConf->Read(
"Version", &version, wxEmptyString);
3516 TitleFont =
"Roboto,16,-1,5,50,0,0,0,0,0";
3517 DataFont =
"Roboto,16,-1,5,50,0,0,0,0,0";
3518 LabelFont =
"Roboto,16,-1,5,50,0,0,0,0,0";
3519 SmallFont =
"Roboto,14,-1,5,50,0,0,0,0,0";
3521 TitleFont = g_pFontTitle->GetChosenFont().GetNativeFontInfoDesc();
3522 DataFont = g_pFontData->GetChosenFont().GetNativeFontInfoDesc();
3523 LabelFont = g_pFontLabel->GetChosenFont().GetNativeFontInfoDesc();
3524 SmallFont = g_pFontSmall->GetChosenFont().GetNativeFontInfoDesc();
3527 double scaler = 1.0;
3529 wxFont *pDF = &DummyFont;
3533 scaler = wxMax(1.0, scaler);
3535 g_pFontTitle = &g_FontTitle;
3536 pConf->Read(
"FontTitle", &config, TitleFont);
3537 LoadFont(&pDF, config);
3538 wxFont DummyFontTitle = *pDF;
3539 pConf->Read(
"ColorTitle", &config,
"#000000");
3540 wxColour DummyColor(config);
3541 g_pUSFontTitle->SetChosenFont(DummyFontTitle);
3542 g_pUSFontTitle->SetColour(DummyColor);
3544 g_FontTitle = *g_pUSFontTitle;
3545 g_FontTitle.SetChosenFont(g_pUSFontTitle->GetChosenFont().Scaled(scaler));
3546 g_USFontTitle = *g_pUSFontTitle;
3548 g_pFontData = &g_FontData;
3549 pConf->Read(
"FontData", &config, DataFont);
3550 LoadFont(&pDF, config);
3551 wxFont DummyFontData = *pDF;
3552 pConf->Read(
"ColorData", &config,
"#000000");
3553 DummyColor.Set(config);
3554 g_pUSFontData->SetChosenFont(DummyFontData);
3555 g_pUSFontData->SetColour(DummyColor);
3556 g_FontData = *g_pUSFontData;
3557 g_FontData.SetChosenFont(g_pUSFontData->GetChosenFont().Scaled(scaler));
3558 g_USFontData = *g_pUSFontData;
3560 pConf->Read(
"ForceBackgroundColor", &g_ForceBackgroundColor,
false);
3561 pConf->Read(
"BackgroundColor", &config,
"DASHL");
3562 g_BackgroundColor.Set(config);
3565 pConf->Read(
"TitleAlignment", &alignment, (
int)wxALIGN_LEFT);
3566 g_TitleAlignment = (wxAlignment)alignment;
3567 if (g_TitleAlignment == wxALIGN_INVALID) g_TitleAlignment = wxALIGN_LEFT;
3568 pConf->Read(
"TitleMargin", &g_iTitleMargin, 5);
3569 pConf->Read(
"DataShowUnit", &g_bShowUnit,
true);
3570 pConf->Read(
"DataAlignment", &alignment, (
int)wxALIGN_LEFT);
3571 g_DataAlignment = (wxAlignment)alignment;
3572 if (g_DataAlignment == wxALIGN_INVALID) g_DataAlignment = wxALIGN_LEFT;
3573 pConf->Read(
"DataMargin", &g_iDataMargin, 10);
3574 pConf->Read(
"InstrumentSpacing", &g_iInstrumentSpacing, 0);
3575 pConf->Read(
"TitleVerticalOffset", &g_TitleVerticalOffset, 0.0);
3577 g_pFontLabel = &g_FontLabel;
3578 pConf->Read(
"FontLabel", &config, LabelFont);
3579 LoadFont(&pDF, config);
3580 wxFont DummyFontLabel = *pDF;
3581 pConf->Read(
"ColorLabel", &config,
"#000000");
3582 DummyColor.Set(config);
3583 g_pUSFontLabel->SetChosenFont(DummyFontLabel);
3584 g_pUSFontLabel->SetColour(DummyColor);
3585 g_FontLabel = *g_pUSFontLabel;
3586 g_FontLabel.SetChosenFont(g_pUSFontLabel->GetChosenFont().Scaled(scaler));
3587 g_USFontLabel = *g_pUSFontLabel;
3589 g_pFontSmall = &g_FontSmall;
3590 pConf->Read(
"FontSmall", &config, SmallFont);
3591 LoadFont(&pDF, config);
3592 wxFont DummyFontSmall = *pDF;
3593 pConf->Read(
"ColorSmall", &config,
"#000000");
3594 DummyColor.Set(config);
3595 g_pUSFontSmall->SetChosenFont(DummyFontSmall);
3596 g_pUSFontSmall->SetColour(DummyColor);
3597 g_FontSmall = *g_pUSFontSmall;
3598 g_FontSmall.SetChosenFont(g_pUSFontSmall->GetChosenFont().Scaled(scaler));
3599 g_USFontSmall = *g_pUSFontSmall;
3601 pConf->Read(
"SpeedometerMax", &g_iDashSpeedMax, 12);
3602 pConf->Read(
"COGDamp", &g_iDashCOGDamp, 0);
3603 pConf->Read(
"SpeedUnit", &g_iDashSpeedUnit, 0);
3604 pConf->Read(
"SOGDamp", &g_iDashSOGDamp, 0);
3605 pConf->Read(
"DepthUnit", &g_iDashDepthUnit, 3);
3606 g_iDashDepthUnit = wxMax(g_iDashDepthUnit, 3);
3607 pConf->Read(
"AWADamp", &g_iDashAWADamp, 0);
3608 pConf->Read(
"AWSDamp", &g_iDashAWSDamp, 0);
3610 pConf->Read(
"DepthOffset", &g_dDashDBTOffset, 0);
3612 pConf->Read(
"DistanceUnit", &g_iDashDistanceUnit, 0);
3613 pConf->Read(
"WindSpeedUnit", &g_iDashWindSpeedUnit, 0);
3614 pConf->Read(
"UseSignKtruewind", &g_bDBtrueWindGround,
false);
3615 pConf->Read(
"UseInternSumlog", &g_bUseInternSumLog,
false);
3616 pConf->Read(
"SumLogNM", &g_dSumLogNM, 0.0);
3617 pConf->Read(
"TemperatureUnit", &g_iDashTempUnit, 0);
3619 pConf->Read(
"UTCOffset", &g_iUTCOffset, 0);
3621 pConf->Read(
"PrefWidth", &g_dashPrefWidth, 0);
3622 pConf->Read(
"PrefHeight", &g_dashPrefHeight, 0);
3625 pConf->Read(
"DashboardCount", &d_cnt, -1);
3627 m_ArrayOfDashboardWindow.Clear();
3628 if (version.IsEmpty() && d_cnt == -1) {
3629 m_config_version = 1;
3632 pConf->Read(
"InstrumentCount", &i_cnt, -1);
3634 wxArrayOfInstrumentProperties Property;
3636 for (
int i = 0; i < i_cnt; i++) {
3638 pConf->Read(wxString::Format(
"Instrument%d", i + 1), &
id, -1);
3639 if (
id != -1) ar.Add(
id);
3644 ar.Add(ID_DBP_I_POS);
3645 ar.Add(ID_DBP_D_COG);
3646 ar.Add(ID_DBP_D_GPS);
3648 ar.Add(ID_DBP_I_POS);
3649 ar.Add(ID_DBP_D_COG);
3650 ar.Add(ID_DBP_I_SOG);
3656 nullptr, MakeName(), _(
"Dashboard"),
"V", ar, Property);
3657 cont->m_bPersVisible =
true;
3658 m_ArrayOfDashboardWindow.Add(cont);
3662 m_config_version = 2;
3663 bool b_onePersisted =
false;
3665 wxSize persist_size;
3666 for (
int k = 0; k < d_cnt; k++) {
3668 wxString::Format(
"/PlugIns/Dashboard/Dashboard%d", k + 1));
3670 pConf->Read(
"Name", &name, MakeName());
3672 pConf->Read(
"Caption", &caption, _(
"Dashboard"));
3674 pConf->Read(
"Orientation", &orient,
"V");
3676 pConf->Read(
"InstrumentCount", &i_cnt, -1);
3678 pConf->Read(
"Persistence", &b_persist,
true);
3680 pConf->Read(
"BestSizeX", &val, DefaultWidth);
3682 pConf->Read(
"BestSizeY", &val, DefaultWidth);
3684 pConf->Read(
"PersistSizeX", &val, DefaultWidth);
3685 persist_size.x = val;
3686 pConf->Read(
"PersistSizeY", &val, DefaultWidth);
3687 persist_size.y = val;
3690 wxArrayOfInstrumentProperties Property;
3691 for (
int i = 0; i < i_cnt; i++) {
3693 pConf->Read(wxString::Format(
"Instrument%d", i + 1), &
id, -1);
3697 if (pConf->Exists(wxString::Format(
"InstTitleFont%d", i + 1))) {
3700 pConf->Read(wxString::Format(
"InstTitleFont%d", i + 1), &config,
3702 LoadFont(&pDF, config);
3703 wxFont DummyFontTitleA = *pDF;
3704 pConf->Read(wxString::Format(
"InstTitleColor%d", i + 1), &config,
3706 DummyColor.Set(config);
3707 instp->m_USTitleFont.SetChosenFont(DummyFontTitleA);
3708 instp->m_USTitleFont.SetColour(DummyColor);
3709 instp->m_TitleFont = instp->m_USTitleFont;
3710 instp->m_TitleFont.SetChosenFont(
3711 instp->m_USTitleFont.GetChosenFont().Scaled(scaler));
3713 pConf->Read(wxString::Format(
"InstDataShowUnit%d", i + 1),
3714 &instp->m_ShowUnit, -1);
3715 pConf->Read(wxString::Format(
"InstDataMargin%d", i + 1),
3716 &instp->m_DataMargin, -1);
3717 pConf->Read(wxString::Format(
"InstDataAlignment%d", i + 1),
3718 &alignment, (
int)wxALIGN_INVALID);
3719 instp->m_DataAlignment = (wxAlignment)alignment;
3720 pConf->Read(wxString::Format(
"InstInstrumentSpacing%d", i + 1),
3721 &instp->m_InstrumentSpacing, -1);
3722 pConf->Read(wxString::Format(
"InstDataFormat%d", i + 1),
3723 &instp->m_Format,
"");
3724 pConf->Read(wxString::Format(
"InstTitle%d", i + 1),
3725 &instp->m_Title,
"");
3727 pConf->Read(wxString::Format(
"InstDataFont%d", i + 1), &config,
3729 LoadFont(&pDF, config);
3730 wxFont DummyFontDataA = *pDF;
3731 pConf->Read(wxString::Format(
"InstDataColor%d", i + 1), &config,
3733 DummyColor.Set(config);
3734 instp->m_USDataFont.SetChosenFont(DummyFontDataA);
3735 instp->m_USDataFont.SetColour(DummyColor);
3736 instp->m_DataFont = instp->m_USDataFont;
3737 instp->m_DataFont.SetChosenFont(
3738 instp->m_USDataFont.GetChosenFont().Scaled(scaler));
3740 pConf->Read(wxString::Format(
"InstLabelFont%d", i + 1), &config,
3742 LoadFont(&pDF, config);
3743 wxFont DummyFontLabelA = *pDF;
3744 pConf->Read(wxString::Format(
"InstLabelColor%d", i + 1), &config,
3746 DummyColor.Set(config);
3747 instp->m_USLabelFont.SetChosenFont(DummyFontLabelA);
3748 instp->m_USLabelFont.SetColour(DummyColor);
3749 instp->m_LabelFont = instp->m_USLabelFont;
3750 instp->m_LabelFont.SetChosenFont(
3751 instp->m_USLabelFont.GetChosenFont().Scaled(scaler));
3753 pConf->Read(wxString::Format(
"InstSmallFont%d", i + 1), &config,
3755 LoadFont(&pDF, config);
3756 wxFont DummyFontSmallA = *pDF;
3757 pConf->Read(wxString::Format(
"InstSmallColor%d", i + 1), &config,
3759 DummyColor.Set(config);
3760 instp->m_USSmallFont.SetChosenFont(DummyFontSmallA);
3761 instp->m_USSmallFont.SetColour(DummyColor);
3762 instp->m_SmallFont = instp->m_USSmallFont;
3763 instp->m_SmallFont.SetChosenFont(
3764 instp->m_USSmallFont.GetChosenFont().Scaled(scaler));
3766 pConf->Read(wxString::Format(
"TitleBackColor%d", i + 1), &config,
3768 instp->m_TitleBackgroundColour.Set(config);
3770 pConf->Read(wxString::Format(
"DataBackColor%d", i + 1), &config,
3772 instp->m_DataBackgroundColour.Set(config);
3774 pConf->Read(wxString::Format(
"ArrowFirst%d", i + 1), &config,
3776 instp->m_Arrow_First_Colour.Set(config);
3778 pConf->Read(wxString::Format(
"ArrowSecond%d", i + 1), &config,
3780 instp->m_Arrow_Second_Colour.Set(config);
3782 Property.Add(instp);
3789 orient, ar, Property);
3790 cont->m_bPersVisible = b_persist;
3791 cont->m_conf_best_size = best_size;
3792 cont->m_persist_size = persist_size;
3794 if (b_persist) b_onePersisted =
true;
3796 m_ArrayOfDashboardWindow.Add(cont);
3800 if (m_ArrayOfDashboardWindow.Count() && !b_onePersisted) {
3802 if (cont) cont->m_bPersVisible =
true;
3811void dashboard_pi::LoadFont(wxFont **target,
const wxString &native_info) {
3812 if (!native_info.IsEmpty()) {
3814 wxFont *nf =
new wxFont(native_info);
3817 (*target)->SetNativeFontInfo(native_info);
3822bool dashboard_pi::SaveConfig() {
3823 auto *pConf = (wxFileConfig *)m_pconfig;
3826 pConf->SetPath(
"/PlugIns/Dashboard");
3827 pConf->Write(
"Version",
"2");
3828 pConf->Write(
"FontTitle",
3829 g_pUSFontTitle->GetChosenFont().GetNativeFontInfoDesc());
3830 pConf->Write(
"ColorTitle",
3831 g_pUSFontTitle->GetColour().GetAsString(wxC2S_HTML_SYNTAX));
3832 pConf->Write(
"FontData",
3833 g_pUSFontData->GetChosenFont().GetNativeFontInfoDesc());
3834 pConf->Write(
"ColorData",
3835 g_pUSFontData->GetColour().GetAsString(wxC2S_HTML_SYNTAX));
3836 pConf->Write(
"FontLabel",
3837 g_pUSFontLabel->GetChosenFont().GetNativeFontInfoDesc());
3838 pConf->Write(
"ColorLabel",
3839 g_pUSFontLabel->GetColour().GetAsString(wxC2S_HTML_SYNTAX));
3840 pConf->Write(
"FontSmall",
3841 g_pUSFontSmall->GetChosenFont().GetNativeFontInfoDesc());
3842 pConf->Write(
"ColorSmall",
3843 g_pUSFontSmall->GetColour().GetAsString(wxC2S_HTML_SYNTAX));
3844 pConf->Write(
"SpeedometerMax", g_iDashSpeedMax);
3845 pConf->Write(
"COGDamp", g_iDashCOGDamp);
3846 pConf->Write(
"SpeedUnit", g_iDashSpeedUnit);
3847 pConf->Write(
"SOGDamp", g_iDashSOGDamp);
3848 pConf->Write(
"AWSDamp", g_iDashAWSDamp);
3849 pConf->Write(
"AWADamp", g_iDashAWADamp);
3850 pConf->Write(
"DepthUnit", g_iDashDepthUnit);
3851 pConf->Write(
"DepthOffset", g_dDashDBTOffset);
3852 pConf->Write(
"DistanceUnit", g_iDashDistanceUnit);
3853 pConf->Write(
"WindSpeedUnit", g_iDashWindSpeedUnit);
3854 pConf->Write(
"UseInternSumlog", g_bUseInternSumLog);
3855 pConf->Write(
"SumLogNM", g_dSumLogNM);
3856 pConf->Write(
"UTCOffset", g_iUTCOffset);
3857 pConf->Write(
"UseSignKtruewind", g_bDBtrueWindGround);
3858 pConf->Write(
"TemperatureUnit", g_iDashTempUnit);
3859 pConf->Write(
"PrefWidth", g_dashPrefWidth);
3860 pConf->Write(
"PrefHeight", g_dashPrefHeight);
3862 pConf->Write(
"DashboardCount", (
int)m_ArrayOfDashboardWindow.GetCount());
3864 for (
size_t i = m_ArrayOfDashboardWindow.GetCount(); i < 20; i++) {
3866 wxString::Format(
"/PlugIns/Dashboard/Dashboard%zu", i + 1))) {
3868 wxString::Format(
"/PlugIns/Dashboard/Dashboard%zu", i + 1));
3871 for (
size_t i = 0; i < m_ArrayOfDashboardWindow.GetCount(); i++) {
3874 wxString::Format(
"/PlugIns/Dashboard/Dashboard%zu", i + 1));
3875 pConf->Write(
"Name", cont->m_sName);
3876 pConf->Write(
"Caption", cont->m_sCaption);
3877 pConf->Write(
"Orientation", cont->m_sOrientation);
3878 pConf->Write(
"Persistence", cont->m_bPersVisible);
3879 pConf->Write(
"InstrumentCount", (
int)cont->m_aInstrumentList.GetCount());
3880 pConf->Write(
"BestSizeX", cont->m_best_size.x);
3881 pConf->Write(
"BestSizeY", cont->m_best_size.y);
3882 pConf->Write(
"PersistSizeX", cont->m_pDashboardWindow->GetSize().x);
3883 pConf->Write(
"PersistSizeY", cont->m_pDashboardWindow->GetSize().y);
3886 for (
size_t ii = cont->m_aInstrumentList.GetCount(); ii < 40; ii++) {
3887 if (pConf->Exists(wxString::Format(
"Instrument%zu", ii + 1))) {
3888 pConf->DeleteEntry(wxString::Format(
"Instrument%zu", ii + 1));
3889 if (pConf->Exists(wxString::Format(
"InstTitleFont%zu", ii + 1))) {
3890 pConf->DeleteEntry(wxString::Format(
"InstTitleFont%zu", ii + 1));
3891 pConf->DeleteEntry(wxString::Format(
"InstTitleColor%zu", ii + 1));
3892 pConf->DeleteEntry(wxString::Format(
"InstTitle%zu", ii + 1));
3893 pConf->DeleteEntry(wxString::Format(
"InstDataShowUnit%zu", ii + 1));
3894 pConf->DeleteEntry(wxString::Format(
"InstDataMargin%zu", ii + 1));
3896 wxString::Format(
"InstDataAlignment%zu", ii + 1));
3897 pConf->DeleteEntry(wxString::Format(
"InstDataFormat%zu", ii + 1));
3898 pConf->DeleteEntry(wxString::Format(
"InstDataFont%zu", ii + 1));
3899 pConf->DeleteEntry(wxString::Format(
"InstDataColor%zu", ii + 1));
3900 pConf->DeleteEntry(wxString::Format(
"InstLabelFont%zu", ii + 1));
3901 pConf->DeleteEntry(wxString::Format(
"InstLabelColor%zu", ii + 1));
3902 pConf->DeleteEntry(wxString::Format(
"InstSmallFont%zu", ii + 1));
3903 pConf->DeleteEntry(wxString::Format(
"InstSmallColor%zu", ii + 1));
3904 pConf->DeleteEntry(wxString::Format(
"TitleBackColor%zu", ii + 1));
3905 pConf->DeleteEntry(wxString::Format(
"DataBackColor%zu", ii + 1));
3906 pConf->DeleteEntry(wxString::Format(
"ArrowFirst%zu", ii + 1));
3907 pConf->DeleteEntry(wxString::Format(
"ArrowSecond%zu", ii + 1));
3911 for (
size_t j = 0; j < cont->m_aInstrumentList.GetCount(); j++) {
3912 pConf->Write(wxString::Format(
"Instrument%zu", j + 1),
3913 cont->m_aInstrumentList.Item(j));
3916 if (pConf->Exists(wxString::Format(
"InstTitleFont%zu", j + 1))) {
3918 for (
size_t ii = 0; ii < cont->m_aInstrumentPropertyList.GetCount();
3920 Inst = cont->m_aInstrumentPropertyList.Item(ii);
3921 if (Inst->m_Listplace == (
int)j) {
3927 pConf->DeleteEntry(wxString::Format(
"InstTitleFont%zu", j + 1));
3928 pConf->DeleteEntry(wxString::Format(
"InstTitleColor%zu", j + 1));
3929 pConf->DeleteEntry(wxString::Format(
"InstTitle%zu", j + 1));
3930 pConf->DeleteEntry(wxString::Format(
"InstDataShowUnit%zu", i + 1));
3931 pConf->DeleteEntry(wxString::Format(
"InstDataMargin%zu", i + 1));
3932 pConf->DeleteEntry(wxString::Format(
"InstDataAlignment%zu", i + 1));
3933 pConf->DeleteEntry(wxString::Format(
"InstDataFormat%zu", i + 1));
3934 pConf->DeleteEntry(wxString::Format(
"InstDataFont%zu", j + 1));
3935 pConf->DeleteEntry(wxString::Format(
"InstDataColor%zu", j + 1));
3936 pConf->DeleteEntry(wxString::Format(
"InstLabelFont%zu", j + 1));
3937 pConf->DeleteEntry(wxString::Format(
"InstLabelColor%zu", j + 1));
3938 pConf->DeleteEntry(wxString::Format(
"InstSmallFont%zu", j + 1));
3939 pConf->DeleteEntry(wxString::Format(
"InstSmallColor%zu", j + 1));
3940 pConf->DeleteEntry(wxString::Format(
"TitleBackColor%zu", i + 1));
3941 pConf->DeleteEntry(wxString::Format(
"DataBackColor%zu", i + 1));
3942 pConf->DeleteEntry(wxString::Format(
"ArrowFirst%zu", i + 1));
3943 pConf->DeleteEntry(wxString::Format(
"ArrowSecond%zu", i + 1));
3947 for (
size_t ii = 0; ii < (cont->m_aInstrumentPropertyList.GetCount());
3949 Inst = cont->m_aInstrumentPropertyList.Item(ii);
3950 if (Inst->m_Listplace == (
int)j) {
3952 wxString::Format(
"InstTitleFont%zu", j + 1),
3953 Inst->m_USTitleFont.GetChosenFont().GetNativeFontInfoDesc());
3955 wxString::Format(
"InstTitleColor%zu", j + 1),
3956 Inst->m_USTitleFont.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
3958 wxString::Format(
"InstDataFont%zu", j + 1),
3959 Inst->m_USDataFont.GetChosenFont().GetNativeFontInfoDesc());
3961 wxString::Format(
"InstDataColor%zu", j + 1),
3962 Inst->m_USDataFont.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
3964 wxString::Format(
"InstLabelFont%zu", j + 1),
3965 Inst->m_USLabelFont.GetChosenFont().GetNativeFontInfoDesc());
3967 wxString::Format(
"InstLabelColor%zu", j + 1),
3968 Inst->m_USLabelFont.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
3970 wxString::Format(
"InstSmallFont%zu", j + 1),
3971 Inst->m_USSmallFont.GetChosenFont().GetNativeFontInfoDesc());
3973 wxString::Format(
"InstSmallColor%zu", j + 1),
3974 Inst->m_USSmallFont.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
3976 wxString::Format(
"TitleBackColor%zu", j + 1),
3977 Inst->m_TitleBackgroundColour.GetAsString(wxC2S_HTML_SYNTAX));
3979 wxString::Format(
"DataBackColor%zu", j + 1),
3980 Inst->m_DataBackgroundColour.GetAsString(wxC2S_HTML_SYNTAX));
3982 wxString::Format(
"ArrowFirst%zu", j + 1),
3983 Inst->m_Arrow_First_Colour.GetAsString(wxC2S_HTML_SYNTAX));
3985 wxString::Format(
"ArrowSecond%zu", j + 1),
3986 Inst->m_Arrow_Second_Colour.GetAsString(wxC2S_HTML_SYNTAX));
3998void dashboard_pi::ApplyConfig() {
4000 for (
size_t i = m_ArrayOfDashboardWindow.GetCount(); i > 0; i--) {
4002 int orient = (cont->m_sOrientation ==
"V" ? wxVERTICAL : wxHORIZONTAL);
4003 if (cont->m_bIsDeleted) {
4004 if (cont->m_pDashboardWindow) {
4005 m_pauimgr->DetachPane(cont->m_pDashboardWindow);
4006 cont->m_pDashboardWindow->Close();
4007 cont->m_pDashboardWindow->Destroy();
4008 cont->m_pDashboardWindow =
nullptr;
4010 m_ArrayOfDashboardWindow.Remove(cont);
4013 }
else if (!cont->m_pDashboardWindow) {
4017 cont->m_pDashboardWindow->SetInstrumentList(
4018 cont->m_aInstrumentList, &(cont->m_aInstrumentPropertyList));
4019 bool vertical = orient == wxVERTICAL;
4020 wxSize sz = cont->m_pDashboardWindow->GetMinSize();
4021 wxSize best = cont->m_conf_best_size;
4022 if (best.x < 100) best = sz;
4026 if (sz.x == 0) sz.IncTo(wxSize(160, 388));
4028 wxAuiPaneInfo p = wxAuiPaneInfo()
4029 .Name(cont->m_sName)
4030 .Caption(cont->m_sCaption)
4031 .CaptionVisible(
false)
4032 .TopDockable(!vertical)
4033 .BottomDockable(!vertical)
4034 .LeftDockable(vertical)
4035 .RightDockable(vertical)
4039 .FloatingPosition(100, 100)
4041 .Show(cont->m_bIsVisible)
4044 m_pauimgr->AddPane(cont->m_pDashboardWindow, p);
4052 wxAuiPaneInfo &pane = m_pauimgr->GetPane(cont->m_pDashboardWindow);
4053 pane.Dockable(
false);
4058 wxAuiPaneInfo &pane = m_pauimgr->GetPane(cont->m_pDashboardWindow);
4059 pane.Caption(cont->m_sCaption).Show(cont->m_bIsVisible);
4060 if (!cont->m_pDashboardWindow->isInstrumentListEqual(
4061 cont->m_aInstrumentList)) {
4062 cont->m_pDashboardWindow->SetInstrumentList(
4063 cont->m_aInstrumentList, &(cont->m_aInstrumentPropertyList));
4064 wxSize sz = cont->m_pDashboardWindow->GetMinSize();
4065 pane.MinSize(sz).BestSize(sz).FloatingSize(sz);
4067 if (cont->m_pDashboardWindow->GetSizerOrientation() != orient) {
4068 cont->m_pDashboardWindow->ChangePaneOrientation(orient,
false);
4072 m_pauimgr->Update();
4075 double sogFC = g_iDashSOGDamp ? 1.0 / (2.0 * g_iDashSOGDamp) : 0.0;
4076 double cogFC = g_iDashCOGDamp ? 1.0 / (2.0 * g_iDashCOGDamp) : 0.0;
4077 double awaFC = g_iDashAWADamp ? 1.0 / (2.0 * g_iDashAWADamp) : 0.0;
4078 double awsFC = g_iDashAWSDamp ? 1.0 / (2.0 * g_iDashAWSDamp) : 0.0;
4080 if (abs(sogFC - m_sog_filter.GetFc()) > 1e-6) {
4081 m_sog_filter.SetFc(sogFC);
4083 if (abs(cogFC - m_cog_filter.GetFc()) > 1e-6) {
4084 m_cog_filter.SetFc(cogFC);
4086 if (abs(awaFC - m_awa_filter.GetFc()) > 1e-6) {
4087 m_awa_filter.SetFc(awaFC);
4089 if (abs(awsFC - m_aws_filter.GetFc()) > 1e-6) {
4090 m_aws_filter.SetFc(awsFC);
4094void dashboard_pi::PopulateContextMenu(wxMenu *menu) {
4096 wxMenuItem *visItem =
nullptr;
4097 for (
size_t i = 0; i < m_ArrayOfDashboardWindow.GetCount(); i++) {
4099 wxMenuItem *item = menu->AppendCheckItem(i + 1, cont->m_sCaption);
4100 item->Check(cont->m_bIsVisible);
4101 if (cont->m_bIsVisible) {
4106 if (nvis == 1 && visItem) visItem->Enable(
false);
4109void dashboard_pi::ShowDashboard(
size_t id,
bool visible) {
4110 if (
id < m_ArrayOfDashboardWindow.GetCount()) {
4112 m_pauimgr->GetPane(cont->m_pDashboardWindow).Show(visible);
4113 cont->m_bIsVisible = visible;
4114 cont->m_bPersVisible = visible;
4115 m_pauimgr->Update();
4123DashboardPreferencesDialog::DashboardPreferencesDialog(
4124 wxWindow *parent, wxWindowID
id, wxArrayOfDashboard config)
4125 : wxDialog(parent, id, _(
"Dashboard preferences"), wxDefaultPosition,
4126 wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) {
4132 int display_width, display_height;
4133 wxDisplaySize(&display_width, &display_height);
4136 wxFileName::GetPathSeparator() +
"dashboard_pi" +
4137 wxFileName::GetPathSeparator() +
"data" +
4138 wxFileName::GetPathSeparator();
4140 Connect(wxEVT_CLOSE_WINDOW,
4141 wxCloseEventHandler(DashboardPreferencesDialog::OnCloseDialog),
4145 m_config = wxArrayOfDashboard(config);
4147 int border_size = 2;
4149 auto *itemBoxSizerMainPanel =
new wxBoxSizer(wxVERTICAL);
4150 SetSizer(itemBoxSizerMainPanel);
4152 wxWindow *dparent =
this;
4153 auto *scrollWin =
new wxScrolledWindow(
this, wxID_ANY, wxDefaultPosition,
4154 wxSize(-1, -1), wxVSCROLL | wxHSCROLL);
4156 scrollWin->SetScrollRate(1, 1);
4157 itemBoxSizerMainPanel->Add(scrollWin, 1, wxEXPAND | wxALL, 0);
4159 dparent = scrollWin;
4161 auto *itemBoxSizer2 =
new wxBoxSizer(wxVERTICAL);
4162 scrollWin->SetSizer(itemBoxSizer2);
4164 auto *DialogButtonSizer =
new wxStdDialogButtonSizer();
4165 DialogButtonSizer->AddButton(
new wxButton(
this, wxID_OK));
4166 DialogButtonSizer->AddButton(
new wxButton(
this, wxID_CANCEL));
4167 auto *help_btn =
new wxButton(
this, wxID_HELP);
4168 help_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [&](wxCommandEvent &) {
4170 Manual(
this, datadir.ToStdString()).Launch(
"Dashboard");
4172 DialogButtonSizer->AddButton(help_btn);
4173 DialogButtonSizer->Realize();
4175 itemBoxSizerMainPanel->Add(DialogButtonSizer, 0, wxALIGN_RIGHT | wxALL, 5);
4177 auto *itemNotebook =
new wxNotebook(dparent, wxID_ANY, wxDefaultPosition,
4178 wxDefaultSize, wxNB_TOP);
4179 itemBoxSizer2->Add(itemNotebook, 0, wxALL | wxEXPAND, border_size);
4181 auto *itemPanelNotebook01 =
4182 new wxPanel(itemNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize,
4184 auto *itemFlexGridSizer01 =
new wxFlexGridSizer(2);
4185 itemFlexGridSizer01->AddGrowableCol(1);
4186 itemPanelNotebook01->SetSizer(itemFlexGridSizer01);
4187 itemNotebook->AddPage(itemPanelNotebook01, _(
"Dashboard"));
4189 auto *itemBoxSizer01 =
new wxBoxSizer(wxVERTICAL);
4190 itemFlexGridSizer01->Add(itemBoxSizer01, 1, wxEXPAND | wxTOP | wxLEFT,
4194 int imageRefSize = wxWindow::GetCharWidth() * 4;
4196 auto *imglist1 =
new wxImageList(imageRefSize, imageRefSize,
true, 1);
4198 wxBitmap bmDashBoard;
4200 wxString filename = shareLocn +
"Dashboard.svg";
4203 wxImage dash1 = wxBitmap(*_img_dashboard_pi).ConvertToImage();
4205 dash1.Scale(imageRefSize, imageRefSize, wxIMAGE_QUALITY_HIGH);
4206 bmDashBoard = wxBitmap(dash1s);
4209 imglist1->Add(bmDashBoard);
4211 m_pListCtrlDashboards =
4212 new wxListCtrl(itemPanelNotebook01, wxID_ANY, wxDefaultPosition,
4213 wxSize(imageRefSize * 3 / 2, 200),
4214 wxLC_REPORT | wxLC_NO_HEADER | wxLC_SINGLE_SEL);
4216 m_pListCtrlDashboards->AssignImageList(imglist1, wxIMAGE_LIST_SMALL);
4217 m_pListCtrlDashboards->InsertColumn(0,
"");
4218 m_pListCtrlDashboards->Connect(
4219 wxEVT_COMMAND_LIST_ITEM_SELECTED,
4220 wxListEventHandler(DashboardPreferencesDialog::OnDashboardSelected),
4222 m_pListCtrlDashboards->Connect(
4223 wxEVT_COMMAND_LIST_ITEM_DESELECTED,
4224 wxListEventHandler(DashboardPreferencesDialog::OnDashboardSelected),
4226 itemBoxSizer01->Add(m_pListCtrlDashboards, 1, wxEXPAND, 0);
4228 auto *itemBoxSizer02 =
new wxBoxSizer(wxHORIZONTAL);
4229 itemBoxSizer01->Add(itemBoxSizer02);
4231 wxBitmap bmPlus, bmMinus;
4232 int bmSize = imageRefSize * 100 / 275;
4235 bmSize = imageRefSize / 2;
4242 wxImage plus1 = wxBitmap(*_img_plus).ConvertToImage();
4243 wxImage plus1s = plus1.Scale(bmSize, bmSize, wxIMAGE_QUALITY_HIGH);
4244 bmPlus = wxBitmap(plus1s);
4246 wxImage minus1 = wxBitmap(*_img_minus).ConvertToImage();
4247 wxImage minus1s = minus1.Scale(bmSize, bmSize, wxIMAGE_QUALITY_HIGH);
4248 bmMinus = wxBitmap(minus1s);
4251 m_pButtonAddDashboard =
new wxBitmapButton(
4252 itemPanelNotebook01, wxID_ANY, bmPlus, wxDefaultPosition, wxDefaultSize);
4253 itemBoxSizer02->Add(m_pButtonAddDashboard, 0, wxALIGN_CENTER, 2);
4254 m_pButtonAddDashboard->Connect(
4255 wxEVT_COMMAND_BUTTON_CLICKED,
4256 wxCommandEventHandler(DashboardPreferencesDialog::OnDashboardAdd),
4259 m_pButtonDeleteDashboard =
new wxBitmapButton(
4260 itemPanelNotebook01, wxID_ANY, bmMinus, wxDefaultPosition, wxDefaultSize);
4261 itemBoxSizer02->Add(m_pButtonDeleteDashboard, 0, wxALIGN_CENTER, 2);
4262 m_pButtonDeleteDashboard->Connect(
4263 wxEVT_COMMAND_BUTTON_CLICKED,
4264 wxCommandEventHandler(DashboardPreferencesDialog::OnDashboardDelete),
4268 new wxPanel(itemPanelNotebook01, wxID_ANY, wxDefaultPosition,
4269 wxDefaultSize, wxBORDER_SUNKEN);
4270 itemFlexGridSizer01->Add(m_pPanelDashboard, 1, wxEXPAND | wxTOP | wxRIGHT,
4273 auto *itemBoxSizer03 =
new wxBoxSizer(wxVERTICAL);
4274 m_pPanelDashboard->SetSizer(itemBoxSizer03);
4276 auto *itemStaticBox02 =
4277 new wxStaticBox(m_pPanelDashboard, wxID_ANY, _(
"Dashboard"));
4278 auto *itemStaticBoxSizer02 =
4279 new wxStaticBoxSizer(itemStaticBox02, wxHORIZONTAL);
4280 itemBoxSizer03->Add(itemStaticBoxSizer02, 0, wxEXPAND | wxALL, border_size);
4281 auto *itemFlexGridSizer =
new wxFlexGridSizer(2);
4282 itemFlexGridSizer->AddGrowableCol(1);
4283 itemStaticBoxSizer02->Add(itemFlexGridSizer, 1, wxEXPAND | wxALL, 0);
4285 m_pCheckBoxIsVisible =
4286 new wxCheckBox(m_pPanelDashboard, wxID_ANY, _(
"show this dashboard"),
4287 wxDefaultPosition, wxDefaultSize, 0);
4288 m_pCheckBoxIsVisible->SetMinSize(wxSize(25 * wxWindow::GetCharWidth(), -1));
4290 itemFlexGridSizer->Add(m_pCheckBoxIsVisible, 0, wxEXPAND | wxALL,
4292 auto *itemDummy01 =
new wxStaticText(m_pPanelDashboard, wxID_ANY,
"");
4293 itemFlexGridSizer->Add(itemDummy01, 0, wxEXPAND | wxALL, border_size);
4295 auto *itemStaticText01 =
4296 new wxStaticText(m_pPanelDashboard, wxID_ANY, _(
"Caption:"),
4297 wxDefaultPosition, wxDefaultSize, 0);
4298 itemFlexGridSizer->Add(itemStaticText01, 0, wxEXPAND | wxALL, border_size);
4299 m_pTextCtrlCaption =
new wxTextCtrl(m_pPanelDashboard, wxID_ANY,
"",
4300 wxDefaultPosition, wxDefaultSize);
4301 m_pCheckBoxIsVisible->SetMinSize(wxSize(30 * wxWindow::GetCharWidth(), -1));
4302 itemFlexGridSizer->Add(m_pTextCtrlCaption, 0, wxALIGN_RIGHT | wxALL,
4305 auto *itemStaticText02 =
4306 new wxStaticText(m_pPanelDashboard, wxID_ANY, _(
"Orientation:"),
4307 wxDefaultPosition, wxDefaultSize, 0);
4308 itemFlexGridSizer->Add(itemStaticText02, 0, wxEXPAND | wxALL, border_size);
4309 m_pChoiceOrientation =
new wxChoice(m_pPanelDashboard, wxID_ANY,
4310 wxDefaultPosition, wxDefaultSize);
4311 m_pChoiceOrientation->SetMinSize(wxSize(15 * wxWindow::GetCharWidth(), -1));
4312 m_pChoiceOrientation->Append(_(
"Vertical"));
4313 m_pChoiceOrientation->Append(_(
"Horizontal"));
4314 itemFlexGridSizer->Add(m_pChoiceOrientation, 0, wxALIGN_RIGHT | wxALL,
4319 auto *imglist =
new wxImageList(instImageRefSize, instImageRefSize,
true, 2);
4321 wxBitmap bmDial, bmInst;
4328 wxImage dial1 = wxBitmap(*_img_dial).ConvertToImage();
4330 dial1.Scale(instImageRefSize, instImageRefSize, wxIMAGE_QUALITY_HIGH);
4331 bmDial = wxBitmap(dial1);
4333 wxImage inst1 = wxBitmap(*_img_instrument).ConvertToImage();
4335 inst1.Scale(instImageRefSize, instImageRefSize, wxIMAGE_QUALITY_HIGH);
4336 bmInst = wxBitmap(inst1s);
4339 imglist->Add(bmInst);
4340 imglist->Add(bmDial);
4342 auto *itemStaticBox03 =
4343 new wxStaticBox(m_pPanelDashboard, wxID_ANY, _(
"Instruments"));
4344 auto *itemStaticBoxSizer03 =
4345 new wxStaticBoxSizer(itemStaticBox03, wxHORIZONTAL);
4346 itemBoxSizer03->Add(itemStaticBoxSizer03, 1, wxEXPAND | wxALL, border_size);
4349 wxSize list_size = wxSize(-1, dsize.y * 35 / 100);
4352 int xsize = GetCharWidth() * 30;
4353 list_size = wxSize(xsize, dsize.y * 50 / 100);
4356 m_pListCtrlInstruments =
4357 new wxListCtrl(m_pPanelDashboard, wxID_ANY, wxDefaultPosition, list_size,
4358 wxLC_REPORT | wxLC_NO_HEADER | wxLC_SINGLE_SEL);
4360 itemStaticBoxSizer03->Add(m_pListCtrlInstruments, 1, wxEXPAND | wxALL,
4362 m_pListCtrlInstruments->AssignImageList(imglist, wxIMAGE_LIST_SMALL);
4363 m_pListCtrlInstruments->InsertColumn(0, _(
"Instruments"));
4364 m_pListCtrlInstruments->Connect(
4365 wxEVT_COMMAND_LIST_ITEM_SELECTED,
4366 wxListEventHandler(DashboardPreferencesDialog::OnInstrumentSelected),
4368 m_pListCtrlInstruments->Connect(
4369 wxEVT_COMMAND_LIST_ITEM_DESELECTED,
4370 wxListEventHandler(DashboardPreferencesDialog::OnInstrumentSelected),
4373 auto *itemBoxSizer04 =
new wxBoxSizer(wxVERTICAL);
4374 itemStaticBoxSizer03->Add(itemBoxSizer04, 0, wxALIGN_TOP | wxALL,
4376 m_pButtonAdd =
new wxButton(m_pPanelDashboard, wxID_ANY, _(
"Add..."),
4377 wxDefaultPosition, wxSize(-1, -1));
4378 itemBoxSizer04->Add(m_pButtonAdd, 0, wxEXPAND | wxALL, border_size);
4379 m_pButtonAdd->Connect(
4380 wxEVT_COMMAND_BUTTON_CLICKED,
4381 wxCommandEventHandler(DashboardPreferencesDialog::OnInstrumentAdd),
4385 m_pButtonEdit =
new wxButton(m_pPanelDashboard, wxID_ANY, _(
"Edit..."),
4386 wxDefaultPosition, wxDefaultSize);
4387 itemBoxSizer04->Add(m_pButtonEdit, 0, wxEXPAND | wxALL, border_size);
4388 m_pButtonEdit->Connect(
4389 wxEVT_COMMAND_BUTTON_CLICKED,
4390 wxCommandEventHandler(DashboardPreferencesDialog::OnInstrumentEdit),
4401 m_pButtonDelete =
new wxButton(m_pPanelDashboard, wxID_ANY, _(
"Delete"),
4402 wxDefaultPosition, wxSize(-1, -1));
4403 itemBoxSizer04->Add(m_pButtonDelete, 0, wxEXPAND | wxALL, border_size);
4404 m_pButtonDelete->Connect(
4405 wxEVT_COMMAND_BUTTON_CLICKED,
4406 wxCommandEventHandler(DashboardPreferencesDialog::OnInstrumentDelete),
4408 itemBoxSizer04->AddSpacer(10);
4409 m_pButtonUp =
new wxButton(m_pPanelDashboard, wxID_ANY, _(
"Up"),
4410 wxDefaultPosition, wxDefaultSize);
4411 itemBoxSizer04->Add(m_pButtonUp, 0, wxEXPAND | wxALL, border_size);
4412 m_pButtonUp->Connect(
4413 wxEVT_COMMAND_BUTTON_CLICKED,
4414 wxCommandEventHandler(DashboardPreferencesDialog::OnInstrumentUp),
4416 m_pButtonDown =
new wxButton(m_pPanelDashboard, wxID_ANY, _(
"Down"),
4417 wxDefaultPosition, wxDefaultSize);
4418 itemBoxSizer04->Add(m_pButtonDown, 0, wxEXPAND | wxALL, border_size);
4419 m_pButtonDown->Connect(
4420 wxEVT_COMMAND_BUTTON_CLICKED,
4421 wxCommandEventHandler(DashboardPreferencesDialog::OnInstrumentDown),
4424 auto *itemPanelNotebook02 =
4425 new wxPanel(itemNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize,
4427 auto *itemBoxSizer05 =
new wxBoxSizer(wxVERTICAL);
4428 itemPanelNotebook02->SetSizer(itemBoxSizer05);
4429 itemNotebook->AddPage(itemPanelNotebook02, _(
"Appearance"));
4431 auto *itemStaticBox01 =
4432 new wxStaticBox(itemPanelNotebook02, wxID_ANY, _(
"Fonts"));
4433 auto *itemStaticBoxSizer01 =
4434 new wxStaticBoxSizer(itemStaticBox01, wxHORIZONTAL);
4435 itemBoxSizer05->Add(itemStaticBoxSizer01, 0, wxEXPAND | wxALL, border_size);
4436 auto *itemFlexGridSizer03 =
new wxFlexGridSizer(2);
4437 itemFlexGridSizer03->AddGrowableCol(1);
4438 itemStaticBoxSizer01->Add(itemFlexGridSizer03, 1, wxEXPAND | wxALL, 0);
4440 auto *itemStaticText04 =
4441 new wxStaticText(itemPanelNotebook02, wxID_ANY, _(
"Title:"),
4442 wxDefaultPosition, wxDefaultSize, 0);
4443 itemFlexGridSizer03->Add(itemStaticText04, 0, wxEXPAND | wxALL, border_size);
4445 m_font_picker_title =
4446 new wxFontPickerCtrl(itemPanelNotebook02, wxID_ANY, g_USFontTitle,
4447 wxDefaultPosition, wxDefaultSize);
4448 itemFlexGridSizer03->Add(m_font_picker_title, 0, wxALIGN_RIGHT | wxALL, 0);
4450 auto *itemStaticText05 =
4451 new wxStaticText(itemPanelNotebook02, wxID_ANY, _(
"Data:"),
4452 wxDefaultPosition, wxDefaultSize, 0);
4453 itemFlexGridSizer03->Add(itemStaticText05, 0, wxEXPAND | wxALL, border_size);
4454 m_font_picker_data =
4455 new wxFontPickerCtrl(itemPanelNotebook02, wxID_ANY, g_USFontData,
4456 wxDefaultPosition, wxDefaultSize);
4457 itemFlexGridSizer03->Add(m_font_picker_data, 0, wxALIGN_RIGHT | wxALL, 0);
4459 auto *itemStaticText06 =
4460 new wxStaticText(itemPanelNotebook02, wxID_ANY, _(
"Label:"),
4461 wxDefaultPosition, wxDefaultSize, 0);
4462 itemFlexGridSizer03->Add(itemStaticText06, 0, wxEXPAND | wxALL, border_size);
4463 m_font_picker_label =
4464 new wxFontPickerCtrl(itemPanelNotebook02, wxID_ANY, g_USFontLabel,
4465 wxDefaultPosition, wxDefaultSize);
4466 itemFlexGridSizer03->Add(m_font_picker_label, 0, wxALIGN_RIGHT | wxALL, 0);
4468 auto *itemStaticText07 =
4469 new wxStaticText(itemPanelNotebook02, wxID_ANY, _(
"Small:"),
4470 wxDefaultPosition, wxDefaultSize, 0);
4471 itemFlexGridSizer03->Add(itemStaticText07, 0, wxEXPAND | wxALL, border_size);
4472 m_font_picker_small =
4473 new wxFontPickerCtrl(itemPanelNotebook02, wxID_ANY, g_USFontSmall,
4474 wxDefaultPosition, wxDefaultSize);
4475 itemFlexGridSizer03->Add(m_font_picker_small, 0, wxALIGN_RIGHT | wxALL, 0);
4478 auto *itemStaticText80 =
4479 new wxStaticText(itemPanelNotebook02, wxID_ANY, _(
"Reset:"),
4480 wxDefaultPosition, wxDefaultSize, 0);
4481 itemFlexGridSizer03->Add(itemStaticText80, 0, wxEXPAND | wxALL, border_size);
4483 m_pButtondefaultFont =
new wxButton(itemPanelNotebook02, wxID_ANY,
4484 _(
"Set dashboard default fonts"),
4485 wxDefaultPosition, wxSize(-1, -1));
4486 itemFlexGridSizer03->Add(m_pButtondefaultFont, 0, wxALIGN_RIGHT | wxALL, 0);
4487 m_pButtondefaultFont->Connect(
4488 wxEVT_COMMAND_BUTTON_CLICKED,
4489 wxCommandEventHandler(DashboardPreferencesDialog::OnDashboarddefaultFont),
4492 auto *itemStaticBox04 =
new wxStaticBox(itemPanelNotebook02, wxID_ANY,
4493 _(
"Units, Ranges, Formats"));
4494 auto *itemStaticBoxSizer04 =
4495 new wxStaticBoxSizer(itemStaticBox04, wxHORIZONTAL);
4496 itemBoxSizer05->Add(itemStaticBoxSizer04, 0, wxEXPAND | wxALL, border_size);
4497 auto *itemFlexGridSizer04 =
new wxFlexGridSizer(2);
4498 itemFlexGridSizer04->AddGrowableCol(1);
4499 itemStaticBoxSizer04->Add(itemFlexGridSizer04, 1, wxEXPAND | wxALL, 0);
4500 auto *itemStaticText08 =
new wxStaticText(
4501 itemPanelNotebook02, wxID_ANY, _(
"Speedometer max value:"),
4502 wxDefaultPosition, wxDefaultSize, 0);
4503 itemFlexGridSizer04->Add(itemStaticText08, 0, wxEXPAND | wxALL, border_size);
4504 m_spin_speed_max =
new wxSpinCtrl(
4505 itemPanelNotebook02, wxID_ANY, wxEmptyString, wxDefaultPosition,
4506 wxDefaultSize, wxSP_ARROW_KEYS, 10, 100, g_iDashSpeedMax);
4507 itemFlexGridSizer04->Add(m_spin_speed_max, 0, wxALIGN_RIGHT | wxALL, 0);
4509 auto *itemStaticText10 =
new wxStaticText(
4510 itemPanelNotebook02, wxID_ANY, _(
"Speed Over Ground Damping Factor:"),
4511 wxDefaultPosition, wxDefaultSize, 0);
4512 itemFlexGridSizer04->Add(itemStaticText10, 0, wxEXPAND | wxALL, border_size);
4513 m_spin_sog_damp =
new wxSpinCtrl(itemPanelNotebook02, wxID_ANY, wxEmptyString,
4514 wxDefaultPosition, wxDefaultSize,
4515 wxSP_ARROW_KEYS, 0, 100, g_iDashSOGDamp);
4516 itemFlexGridSizer04->Add(m_spin_sog_damp, 0, wxALIGN_RIGHT | wxALL, 0);
4518 auto *itemStaticText11 =
4519 new wxStaticText(itemPanelNotebook02, wxID_ANY, _(
"COG Damping Factor:"),
4520 wxDefaultPosition, wxDefaultSize, 0);
4521 itemFlexGridSizer04->Add(itemStaticText11, 0, wxEXPAND | wxALL, border_size);
4522 m_spin_cog_damp =
new wxSpinCtrl(itemPanelNotebook02, wxID_ANY, wxEmptyString,
4523 wxDefaultPosition, wxDefaultSize,
4524 wxSP_ARROW_KEYS, 0, 100, g_iDashCOGDamp);
4525 itemFlexGridSizer04->Add(m_spin_cog_damp, 0, wxALIGN_RIGHT | wxALL, 0);
4527 auto *itemStaticText13 =
new wxStaticText(
4528 itemPanelNotebook02, wxID_ANY, _(
"Wind speed Damping Factor:"),
4529 wxDefaultPosition, wxDefaultSize, 0);
4530 itemFlexGridSizer04->Add(itemStaticText13, 0, wxEXPAND | wxALL, border_size);
4531 m_spin_aws_damp =
new wxSpinCtrl(itemPanelNotebook02, wxID_ANY, wxEmptyString,
4532 wxDefaultPosition, wxDefaultSize,
4533 wxSP_ARROW_KEYS, 0, 100, g_iDashAWSDamp);
4534 itemFlexGridSizer04->Add(m_spin_aws_damp, 0, wxALIGN_RIGHT | wxALL, 0);
4536 auto *itemStaticText14 =
new wxStaticText(
4537 itemPanelNotebook02, wxID_ANY, _(
"Wind angle Damping Factor:"),
4538 wxDefaultPosition, wxDefaultSize, 0);
4539 itemFlexGridSizer04->Add(itemStaticText14, 0, wxEXPAND | wxALL, border_size);
4540 m_spin_awa_damp =
new wxSpinCtrl(itemPanelNotebook02, wxID_ANY, wxEmptyString,
4541 wxDefaultPosition, wxDefaultSize,
4542 wxSP_ARROW_KEYS, 0, 100, g_iDashAWADamp);
4543 itemFlexGridSizer04->Add(m_spin_awa_damp, 0, wxALIGN_RIGHT | wxALL, 0);
4545 auto *itemStaticText12 =
new wxStaticText(
4546 itemPanelNotebook02, wxID_ANY, _(
"Local Time Offset From UTC:"),
4547 wxDefaultPosition, wxDefaultSize, 0);
4548 itemFlexGridSizer04->Add(itemStaticText12, 0, wxEXPAND | wxALL, border_size);
4549 wxString m_UTCOffsetChoices[] = {
4550 "-12:00",
"-11:30",
"-11:00",
"-10:30",
"-10:00",
"-09:30",
"-09:00",
4551 "-08:30",
"-08:00",
"-07:30",
"-07:00",
"-06:30",
"-06:00",
"-05:30",
4552 "-05:00",
"-04:30",
"-04:00",
"-03:30",
"-03:00",
"-02:30",
"-02:00",
4553 "-01:30",
"-01:00",
"-00:30",
" 00:00",
" 00:30",
" 01:00",
" 01:30",
4554 " 02:00",
" 02:30",
" 03:00",
" 03:30",
" 04:00",
" 04:30",
" 05:00",
4555 " 05:30",
" 06:00",
" 06:30",
" 07:00",
" 07:30",
" 08:00",
" 08:30",
4556 " 09:00",
" 09:30",
" 10:00",
" 10:30",
" 11:00",
" 11:30",
" 12:00"};
4557 int m_UTCOffsetNChoices =
sizeof(m_UTCOffsetChoices) /
sizeof(wxString);
4558 m_choice_utc_offset =
4559 new wxChoice(itemPanelNotebook02, wxID_ANY, wxDefaultPosition,
4560 wxDefaultSize, m_UTCOffsetNChoices, m_UTCOffsetChoices, 0);
4561 m_choice_utc_offset->SetSelection(g_iUTCOffset + 24);
4562 itemFlexGridSizer04->Add(m_choice_utc_offset, 0, wxALIGN_RIGHT | wxALL, 0);
4564 auto *itemStaticText09 =
4565 new wxStaticText(itemPanelNotebook02, wxID_ANY, _(
"Boat speed units:"),
4566 wxDefaultPosition, wxDefaultSize, 0);
4567 itemFlexGridSizer04->Add(itemStaticText09, 0, wxEXPAND | wxALL, border_size);
4568 wxString m_SpeedUnitChoices[] = {_(
"Honor OpenCPN settings"), _(
"Kts"),
4569 _(
"mph"), _(
"km/h"), _(
"m/s")};
4570 int m_SpeedUnitNChoices =
sizeof(m_SpeedUnitChoices) /
sizeof(wxString);
4571 wxSize szSpeedUnit = wxDefaultSize;
4572 m_choice_speed_unit =
4573 new wxChoice(itemPanelNotebook02, wxID_ANY, wxDefaultPosition,
4574 szSpeedUnit, m_SpeedUnitNChoices, m_SpeedUnitChoices, 0);
4575 for (
auto const &iUnit : m_SpeedUnitChoices) {
4576 szSpeedUnit.IncTo(m_choice_speed_unit->GetTextExtent(iUnit));
4578 m_choice_speed_unit->SetSize(szSpeedUnit);
4579 m_choice_speed_unit->SetSelection(g_iDashSpeedUnit + 1);
4580 itemFlexGridSizer04->Add(m_choice_speed_unit, 0, wxALIGN_RIGHT | wxALL, 0);
4582 auto *itemStaticTextDepthU =
4583 new wxStaticText(itemPanelNotebook02, wxID_ANY, _(
"Depth units:"),
4584 wxDefaultPosition, wxDefaultSize, 0);
4585 itemFlexGridSizer04->Add(itemStaticTextDepthU, 0, wxEXPAND | wxALL,
4587 wxString m_DepthUnitChoices[] = {_(
"Meters"), _(
"Feet"), _(
"Fathoms"),
4588 _(
"Inches"), _(
"Centimeters")};
4589 int m_DepthUnitNChoices =
sizeof(m_DepthUnitChoices) /
sizeof(wxString);
4590 wxSize szDepthUnit = wxDefaultSize;
4591 m_choice_depth_unit =
4592 new wxChoice(itemPanelNotebook02, wxID_ANY, wxDefaultPosition,
4593 szDepthUnit, m_DepthUnitNChoices, m_DepthUnitChoices, 0);
4594 for (
auto const &iUnit : m_DepthUnitChoices) {
4595 szDepthUnit.IncTo(m_choice_depth_unit->GetTextExtent(iUnit));
4597 m_choice_depth_unit->SetSize(szDepthUnit);
4598 m_choice_depth_unit->SetSelection(g_iDashDepthUnit - 3);
4599 itemFlexGridSizer04->Add(m_choice_depth_unit, 0, wxALIGN_RIGHT | wxALL, 0);
4600 wxString dMess = wxString::Format(_(
"Depth Offset (%s):"),
4601 m_DepthUnitChoices[g_iDashDepthUnit - 3]);
4602 auto *itemStaticDepthO =
4603 new wxStaticText(itemPanelNotebook02, wxID_ANY, dMess, wxDefaultPosition,
4606 switch (g_iDashDepthUnit - 3) {
4608 DepthOffset = g_dDashDBTOffset * 3.2808399;
4611 DepthOffset = g_dDashDBTOffset * 0.54680665;
4614 DepthOffset = g_dDashDBTOffset * 39.3700787;
4617 DepthOffset = g_dDashDBTOffset * 100;
4620 DepthOffset = g_dDashDBTOffset;
4622 itemFlexGridSizer04->Add(itemStaticDepthO, 0, wxEXPAND | wxALL, border_size);
4623 m_spin_dbt_offset =
new wxSpinCtrlDouble(
4624 itemPanelNotebook02, wxID_ANY, wxEmptyString, wxDefaultPosition,
4625 wxDefaultSize, wxSP_ARROW_KEYS, -100, 100, DepthOffset, 0.1);
4626 itemFlexGridSizer04->Add(m_spin_dbt_offset, 0, wxALIGN_RIGHT | wxALL, 0);
4628 auto *itemStaticText0b =
4629 new wxStaticText(itemPanelNotebook02, wxID_ANY, _(
"Distance units:"),
4630 wxDefaultPosition, wxDefaultSize, 0);
4631 itemFlexGridSizer04->Add(itemStaticText0b, 0, wxEXPAND | wxALL, border_size);
4632 wxString m_DistanceUnitChoices[] = {_(
"Honor OpenCPN settings"),
4633 _(
"Nautical miles"), _(
"Statute miles"),
4634 _(
"Kilometers"), _(
"Meters")};
4635 wxSize szDistanceUnit = wxDefaultSize;
4636 int m_DistanceUnitNChoices =
sizeof(m_DistanceUnitChoices) /
sizeof(wxString);
4637 m_choice_distance_unit =
new wxChoice(
4638 itemPanelNotebook02, wxID_ANY, wxDefaultPosition, szDistanceUnit,
4639 m_DistanceUnitNChoices, m_DistanceUnitChoices, 0);
4640 for (
auto const &iUnit : m_DistanceUnitChoices) {
4641 szDistanceUnit.IncTo(m_choice_distance_unit->GetTextExtent(iUnit));
4643 m_choice_distance_unit->SetSize(szDistanceUnit);
4644 m_choice_distance_unit->SetSelection(g_iDashDistanceUnit + 1);
4645 itemFlexGridSizer04->Add(m_choice_distance_unit, 0, wxALIGN_RIGHT | wxALL, 0);
4646 m_choice_distance_unit->Connect(
4647 wxEVT_COMMAND_CHOICE_SELECTED,
4648 wxCommandEventHandler(DashboardPreferencesDialog::OnDistanceUnitSelect),
4651 auto *itemStaticText0a =
4652 new wxStaticText(itemPanelNotebook02, wxID_ANY, _(
"Wind speed units:"),
4653 wxDefaultPosition, wxDefaultSize, 0);
4654 itemFlexGridSizer04->Add(itemStaticText0a, 0, wxEXPAND | wxALL, border_size);
4655 wxString m_WSpeedUnitChoices[] = {_(
"Kts"), _(
"mph"), _(
"km/h"), _(
"m/s")};
4656 int m_WSpeedUnitNChoices =
sizeof(m_WSpeedUnitChoices) /
sizeof(wxString);
4657 wxSize szWSpeedUnit = wxDefaultSize;
4658 m_choice_wind_speed_unit =
4659 new wxChoice(itemPanelNotebook02, wxID_ANY, wxDefaultPosition,
4660 szWSpeedUnit, m_WSpeedUnitNChoices, m_WSpeedUnitChoices, 0);
4661 for (
auto const &iUnit : m_WSpeedUnitChoices) {
4662 szWSpeedUnit.IncTo(m_choice_wind_speed_unit->GetTextExtent(iUnit));
4664 m_choice_wind_speed_unit->SetSize(szWSpeedUnit);
4665 m_choice_wind_speed_unit->SetSelection(g_iDashWindSpeedUnit);
4666 itemFlexGridSizer04->Add(m_choice_wind_speed_unit, 0, wxALIGN_RIGHT | wxALL,
4669 auto *itemStaticText0c =
4670 new wxStaticText(itemPanelNotebook02, wxID_ANY, _(
"Temperature units:"),
4671 wxDefaultPosition, wxDefaultSize, 0);
4672 itemFlexGridSizer04->Add(itemStaticText0c, 0, wxEXPAND | wxALL, border_size);
4673 wxString m_TempUnitChoices[] = {_(
"Celsius"), _(
"Fahrenheit"), _(
"Kelvin")};
4674 int m_TempUnitNChoices =
sizeof(m_TempUnitChoices) /
sizeof(wxString);
4675 wxSize szTempUnit = wxDefaultSize;
4676 m_choice_temp_unit =
4677 new wxChoice(itemPanelNotebook02, wxID_ANY, wxDefaultPosition, szTempUnit,
4678 m_TempUnitNChoices, m_TempUnitChoices, 0);
4679 for (
auto const &iUnit : m_TempUnitChoices) {
4680 szTempUnit.IncTo(m_choice_temp_unit->GetTextExtent(iUnit));
4682 m_choice_temp_unit->SetSize(szTempUnit);
4683 m_choice_temp_unit->SetSelection(g_iDashTempUnit);
4684 itemFlexGridSizer04->Add(m_choice_temp_unit, 0, wxALIGN_RIGHT | wxALL, 0);
4688 auto *itemStaticBox05 =
4689 new wxStaticBox(itemPanelNotebook02, wxID_ANY, _(
"Other selections"));
4690 auto *itemStaticBoxSizer05 =
4691 new wxStaticBoxSizer(itemStaticBox05, wxHORIZONTAL);
4692 itemBoxSizer05->Add(itemStaticBoxSizer05, 0, wxEXPAND | wxALL, border_size);
4694 auto *itemFlexGridSizer05 =
new wxFlexGridSizer(3);
4695 itemFlexGridSizer05->AddGrowableCol(1);
4696 itemStaticBoxSizer05->Add(itemFlexGridSizer05, 1, wxEXPAND | wxALL, 0);
4698 m_use_intern_sum_log =
4699 new wxCheckBox(itemPanelNotebook02, wxID_ANY,
4700 _(
"Use internal Sumlog.") +
" " +
4701 _(
"Enter new value if desired"));
4702 itemFlexGridSizer05->Add(m_use_intern_sum_log, 1, wxALIGN_LEFT, border_size);
4703 m_use_intern_sum_log->SetValue(g_bUseInternSumLog);
4706 new wxStaticText(itemPanelNotebook02, wxID_ANY,
4708 wxDefaultPosition, wxDefaultSize, 0);
4709 itemFlexGridSizer05->Add(m_sum_log_unit, 1, wxALIGN_RIGHT, 0);
4711 m_sum_log_value =
new wxTextCtrl(itemPanelNotebook02, wxID_ANY,
"");
4712 itemFlexGridSizer05->Add(m_sum_log_value, 1, wxALIGN_LEFT, 1);
4713 m_sum_log_value->SetValue(wxString::Format(
4716 m_use_true_winddata =
4717 new wxCheckBox(itemPanelNotebook02, wxID_ANY,
4718 _(
"Use N2K & SignalK true wind data over "
4719 "ground.\n(Instead of through water)"));
4720 itemFlexGridSizer05->Add(m_use_true_winddata, 1, wxALIGN_LEFT, border_size);
4721 m_use_true_winddata->SetValue(g_bDBtrueWindGround);
4725 auto *itemStaticBox05 =
4726 new wxStaticBox(itemPanelNotebook02, wxID_ANY, _(
"Other selections"));
4727 auto *itemStaticBoxSizer05 =
4728 new wxStaticBoxSizer(itemStaticBox05, wxHORIZONTAL);
4729 itemBoxSizer05->Add(itemStaticBoxSizer05, 0, wxEXPAND | wxALL, border_size);
4731 auto *itemFlexGridSizer05 =
new wxFlexGridSizer(2);
4732 itemFlexGridSizer05->AddGrowableCol(1);
4733 itemStaticBoxSizer05->Add(itemFlexGridSizer05, 1, wxEXPAND | wxALL, 0);
4735 m_use_intern_sum_log =
new wxCheckBox(itemPanelNotebook02, wxID_ANY,
4736 _(
"Use internal Sumlog.") +
" ");
4737 itemFlexGridSizer05->Add(m_use_intern_sum_log, 0, wxALIGN_LEFT, border_size);
4738 m_use_intern_sum_log->SetValue(g_bUseInternSumLog);
4739 itemFlexGridSizer05->AddSpacer(0);
4742 new wxStaticText(itemPanelNotebook02, wxID_ANY,
4743 " " + _(
"Enter new value if desired") +
" ",
4744 wxDefaultPosition, wxDefaultSize, 0);
4745 itemFlexGridSizer05->Add(xtext, 1, wxALIGN_LEFT, 0);
4746 itemFlexGridSizer05->AddSpacer(0);
4748 m_sum_log_unit =
new wxStaticText(
4749 itemPanelNotebook02, wxID_ANY,
4751 wxDefaultPosition, wxDefaultSize, 0);
4752 itemFlexGridSizer05->Add(m_sum_log_unit, 1, wxALIGN_RIGHT, 0);
4754 m_sum_log_value =
new wxTextCtrl(itemPanelNotebook02, wxID_ANY,
"");
4755 itemFlexGridSizer05->Add(m_sum_log_value, 1, wxALIGN_LEFT, 1);
4756 m_sum_log_value->SetValue(wxString::Format(
4759 m_use_true_winddata =
4760 new wxCheckBox(itemPanelNotebook02, wxID_ANY,
4761 _(
"Use N2K & SignalK true wind data over "
4762 "ground.\n(Instead of through water)"));
4763 itemFlexGridSizer05->Add(m_use_true_winddata, 1, wxALIGN_LEFT, border_size);
4764 m_use_true_winddata->SetValue(g_bDBtrueWindGround);
4765 itemFlexGridSizer05->AddSpacer(0);
4767 auto xtext1 =
new wxStaticText(itemPanelNotebook02, wxID_ANY,
" ",
4768 wxDefaultPosition, wxDefaultSize, 0);
4769 itemFlexGridSizer05->Add(xtext1, 1, wxALIGN_LEFT, 0);
4770 itemFlexGridSizer05->AddSpacer(0);
4772 auto xtext2 =
new wxStaticText(itemPanelNotebook02, wxID_ANY,
" ",
4773 wxDefaultPosition, wxDefaultSize, 0);
4774 itemFlexGridSizer05->Add(xtext2, 1, wxALIGN_LEFT, 0);
4775 itemFlexGridSizer05->AddSpacer(0);
4780 for (
size_t i = 0; i < m_config.GetCount(); i++) {
4781 m_pListCtrlDashboards->InsertItem(i, 0);
4783 m_pListCtrlDashboards->SetItemData(i, i);
4785 m_pListCtrlDashboards->SetColumnWidth(0, wxLIST_AUTOSIZE);
4787 m_pListCtrlDashboards->SetItemState(0, wxLIST_STATE_SELECTED,
4788 wxLIST_STATE_SELECTED);
4791 UpdateDashboardButtonsState();
4792 UpdateButtonsState();
4799 SetMaxSize(wxSize(display_width, display_height));
4802 if (display_height < 600) {
4803 if (g_dashPrefWidth > 0 && g_dashPrefHeight > 0)
4804 SetSize(wxSize(g_dashPrefWidth, g_dashPrefHeight));
4806 SetSize(wxSize(canvas_size.x * 8 / 10, canvas_size.y * 8 / 10));
4808 if (g_dashPrefWidth > 0 && g_dashPrefHeight > 0)
4809 SetSize(wxSize(g_dashPrefWidth, g_dashPrefHeight));
4811 SetSize(wxSize(canvas_size.x * 3 / 4, canvas_size.y * 8 / 10));
4818void DashboardPreferencesDialog::RecalculateSize() {
4821 esize.x = GetCharWidth() * 110;
4822 esize.y = GetCharHeight() * 40;
4825 esize.y = wxMin(esize.y, dsize.y - (3 * GetCharHeight()));
4826 esize.x = wxMin(esize.x, dsize.x - (3 * GetCharHeight()));
4833void DashboardPreferencesDialog::OnCloseDialog(wxCloseEvent &event) {
4834 g_dashPrefWidth = GetSize().x;
4835 g_dashPrefHeight = GetSize().y;
4836 SaveDashboardConfig();
4840void DashboardPreferencesDialog::SaveDashboardConfig() {
4841 g_iDashSpeedMax = m_spin_speed_max->GetValue();
4842 g_iDashCOGDamp = m_spin_cog_damp->GetValue();
4843 g_iDashSOGDamp = m_spin_sog_damp->GetValue();
4844 g_iDashAWADamp = m_spin_awa_damp->GetValue();
4845 g_iDashAWSDamp = m_spin_aws_damp->GetValue();
4847 g_bUseInternSumLog = m_use_intern_sum_log->IsChecked();
4849 m_sum_log_value->GetValue().ToDouble(&ursDist);
4852 g_iUTCOffset = m_choice_utc_offset->GetSelection() - 24;
4853 g_iDashSpeedUnit = m_choice_speed_unit->GetSelection() - 1;
4854 double DashDBTOffset = m_spin_dbt_offset->GetValue();
4855 switch (g_iDashDepthUnit - 3) {
4857 g_dDashDBTOffset = DashDBTOffset / 3.2808399;
4860 g_dDashDBTOffset = DashDBTOffset / 0.54680665;
4863 g_dDashDBTOffset = DashDBTOffset / 39.3700787;
4866 g_dDashDBTOffset = DashDBTOffset / 100;
4869 g_dDashDBTOffset = DashDBTOffset;
4871 g_iDashDepthUnit = m_choice_depth_unit->GetSelection() + 3;
4872 g_iDashDistanceUnit = m_choice_distance_unit->GetSelection() - 1;
4873 g_iDashWindSpeedUnit = m_choice_wind_speed_unit->GetSelection();
4874 g_bDBtrueWindGround = m_use_true_winddata->GetValue();
4875 g_iDashTempUnit = m_choice_temp_unit->GetSelection();
4878 cont->m_bIsVisible = m_pCheckBoxIsVisible->IsChecked();
4879 cont->m_sCaption = m_pTextCtrlCaption->GetValue();
4880 cont->m_sOrientation =
4881 m_pChoiceOrientation->GetSelection() == 0 ?
"V" :
"H";
4882 cont->m_aInstrumentList.Clear();
4883 for (
int i = 0; i < m_pListCtrlInstruments->GetItemCount(); i++)
4884 cont->m_aInstrumentList.Add((
int)m_pListCtrlInstruments->GetItemData(i));
4888void DashboardPreferencesDialog::OnDashboardSelected(wxListEvent &event) {
4890 SaveDashboardConfig();
4891 UpdateDashboardButtonsState();
4894void DashboardPreferencesDialog::UpdateDashboardButtonsState() {
4896 item = m_pListCtrlDashboards->GetNextItem(item, wxLIST_NEXT_ALL,
4897 wxLIST_STATE_SELECTED);
4898 bool enable = (item != -1);
4902 bool delete_enable = enable;
4904 int sel = m_pListCtrlDashboards->GetItemData(item);
4907 if (dash_sel == GetParent()) delete_enable =
false;
4909 m_pButtonDeleteDashboard->Enable(delete_enable);
4911 m_pPanelDashboard->Enable(enable);
4914 curSel = m_pListCtrlDashboards->GetItemData(item);
4916 m_pCheckBoxIsVisible->SetValue(cont->m_bIsVisible);
4917 m_pTextCtrlCaption->SetValue(cont->m_sCaption);
4918 m_pChoiceOrientation->SetSelection(cont->m_sOrientation ==
"V" ? 0 : 1);
4919 m_pListCtrlInstruments->DeleteAllItems();
4920 for (
size_t i = 0; i < cont->m_aInstrumentList.GetCount(); i++) {
4922 getListItemForInstrument(item_, cont->m_aInstrumentList.Item(i));
4923 item_.SetId(m_pListCtrlInstruments->GetItemCount());
4924 m_pListCtrlInstruments->InsertItem(item_);
4927 m_pListCtrlInstruments->SetColumnWidth(0, wxLIST_AUTOSIZE);
4930 m_pCheckBoxIsVisible->SetValue(
false);
4931 m_pTextCtrlCaption->SetValue(
"");
4932 m_pChoiceOrientation->SetSelection(0);
4933 m_pListCtrlInstruments->DeleteAllItems();
4938void DashboardPreferencesDialog::OnDashboarddefaultFont(wxCommandEvent &event) {
4939 m_font_picker_title->SetSelectedFont(
4940 wxFont(10, wxFONTFAMILY_SWISS, wxFONTSTYLE_ITALIC, wxFONTWEIGHT_NORMAL));
4941 m_font_picker_title->SetSelectedColour(wxColour(0, 0, 0));
4942 m_font_picker_data->SetSelectedFont(
4943 wxFont(14, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));
4944 m_font_picker_data->SetSelectedColour(wxColour(0, 0, 0));
4945 m_font_picker_label->SetSelectedFont(
4946 wxFont(8, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));
4947 m_font_picker_label->SetSelectedColour(wxColour(0, 0, 0));
4948 m_font_picker_small->SetSelectedFont(
4949 wxFont(8, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));
4950 m_font_picker_small->SetSelectedColour(wxColour(0, 0, 0));
4951 double scaler = 1.0;
4954 scaler = wxMax(1.0, scaler);
4956 g_USFontTitle = *(m_font_picker_title->GetFontData());
4957 g_FontTitle = *g_pUSFontTitle;
4958 g_FontTitle.SetChosenFont(g_pUSFontTitle->GetChosenFont().Scaled(scaler));
4959 g_FontTitle.SetColour(g_pUSFontTitle->GetColour());
4960 g_USFontTitle = *g_pUSFontTitle;
4962 g_USFontData = *(m_font_picker_data->GetFontData());
4963 g_FontData = *g_pUSFontData;
4964 g_FontData.SetChosenFont(g_pUSFontData->GetChosenFont().Scaled(scaler));
4965 g_FontData.SetColour(g_pUSFontData->GetColour());
4966 g_USFontData = *g_pUSFontData;
4968 g_USFontLabel = *(m_font_picker_label->GetFontData());
4969 g_FontLabel = *g_pUSFontLabel;
4970 g_FontLabel.SetChosenFont(g_pUSFontLabel->GetChosenFont().Scaled(scaler));
4971 g_FontLabel.SetColour(g_pUSFontLabel->GetColour());
4972 g_USFontLabel = *g_pUSFontLabel;
4974 g_USFontSmall = *(m_font_picker_small->GetFontData());
4975 g_FontSmall = *g_pUSFontSmall;
4976 g_FontSmall.SetChosenFont(g_pUSFontSmall->GetChosenFont().Scaled(scaler));
4977 g_FontSmall.SetColour(g_pUSFontSmall->GetColour());
4978 g_USFontSmall = *g_pUSFontSmall;
4981void DashboardPreferencesDialog::OnDashboardAdd(wxCommandEvent &event) {
4982 int idx = m_pListCtrlDashboards->GetItemCount();
4983 m_pListCtrlDashboards->InsertItem(idx, 0);
4985 m_pListCtrlDashboards->SetItemData(idx, m_config.GetCount());
4987 wxArrayOfInstrumentProperties Property;
4990 dwc->m_bIsVisible =
true;
4994void DashboardPreferencesDialog::OnDashboardDelete(wxCommandEvent &event) {
4996 itemID = m_pListCtrlDashboards->GetNextItem(itemID, wxLIST_NEXT_ALL,
4997 wxLIST_STATE_SELECTED);
4999 int idx = m_pListCtrlDashboards->GetItemData(itemID);
5000 m_pListCtrlDashboards->DeleteItem(itemID);
5001 m_config.Item(idx)->m_bIsDeleted =
true;
5002 UpdateDashboardButtonsState();
5005void DashboardPreferencesDialog::OnInstrumentSelected(wxListEvent &event) {
5006 UpdateButtonsState();
5009void DashboardPreferencesDialog::UpdateButtonsState() {
5011 item = m_pListCtrlInstruments->GetNextItem(item, wxLIST_NEXT_ALL,
5012 wxLIST_STATE_SELECTED);
5013 bool enable = (item != -1);
5015 m_pButtonDelete->Enable(enable);
5016 m_pButtonEdit->Enable(enable);
5017 m_pButtonUp->Enable(item > 0);
5018 m_pButtonDown->Enable(item != -1 &&
5019 item < m_pListCtrlInstruments->GetItemCount() - 1);
5022void DashboardPreferencesDialog::OnInstrumentAdd(wxCommandEvent &event) {
5030 esize.x = GetCharWidth() * 110;
5031 esize.y = GetCharHeight() * 40;
5034 esize.y = wxMin(esize.y, dsize.y - (3 * GetCharHeight()));
5035 esize.x = wxMin(esize.x, dsize.x - (3 * GetCharHeight()));
5036 pdlg.SetSize(esize);
5038 pdlg.CentreOnScreen();
5041 if (pdlg.GetReturnCode() == wxID_OK) {
5043 getListItemForInstrument(item, pdlg.GetInstrumentAdded());
5044 item.SetId(m_pListCtrlInstruments->GetItemCount());
5045 m_pListCtrlInstruments->InsertItem(item);
5046 m_pListCtrlInstruments->SetColumnWidth(0, wxLIST_AUTOSIZE);
5047 UpdateButtonsState();
5051void DashboardPreferencesDialog::OnInstrumentDelete(wxCommandEvent &event) {
5052 long itemIDWindow = -1;
5053 itemIDWindow = m_pListCtrlDashboards->GetNextItem(
5054 itemIDWindow, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
5056 itemID = m_pListCtrlInstruments->GetNextItem(itemID, wxLIST_NEXT_ALL,
5057 wxLIST_STATE_SELECTED);
5059 m_config.Item(m_pListCtrlDashboards->GetItemData(itemIDWindow));
5063 for (
unsigned int i = 0; i < (cont->m_aInstrumentPropertyList.GetCount());
5065 Inst = cont->m_aInstrumentPropertyList.Item(i);
5066 if (Inst->m_aInstrument ==
5067 (
int)m_pListCtrlInstruments->GetItemData(itemID) &&
5068 Inst->m_Listplace == itemID) {
5069 cont->m_aInstrumentPropertyList.Remove(Inst);
5073 if (Inst->m_Listplace > itemID) Inst->m_Listplace--;
5077 m_pListCtrlInstruments->DeleteItem(itemID);
5079 cont->m_pDashboardWindow->SetInstrumentList(
5080 cont->m_aInstrumentList, &(cont->m_aInstrumentPropertyList));
5083 UpdateButtonsState();
5086inline void GetFontData(
OCPNFontButton *FontButton, wxFontData &UnScaledFont,
5087 wxFontData &ScaledFont,
double scaler) {
5088 UnScaledFont = *(FontButton->GetFontData());
5089 ScaledFont = UnScaledFont;
5090 ScaledFont.SetChosenFont(UnScaledFont.GetChosenFont().Scaled(scaler));
5093void DashboardPreferencesDialog::OnInstrumentEdit(wxCommandEvent &event) {
5096 long itemIDWindow = -1;
5097 itemIDWindow = m_pListCtrlDashboards->GetNextItem(
5098 itemIDWindow, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
5100 itemID = m_pListCtrlInstruments->GetNextItem(itemID, wxLIST_NEXT_ALL,
5101 wxLIST_STATE_SELECTED);
5107 m_config.Item(m_pListCtrlDashboards->GetItemData(itemIDWindow));
5110 for (
unsigned int i = 0; i < (cont->m_aInstrumentPropertyList.GetCount());
5112 Inst = cont->m_aInstrumentPropertyList.Item(
5114 if (Inst->m_aInstrument == (
int)m_pListCtrlInstruments->GetItemData(
5117 if (Inst->m_Listplace == itemID)
break;
5124 cont->m_aInstrumentPropertyList.Add(Inst);
5126 auto *Edit =
new EditDialog(
this, *Inst, wxID_ANY);
5128 bool DefaultFont =
false;
5129 if (Edit->ShowModal() == wxID_OK) {
5131 double scaler = 1.0;
5134 scaler = wxMax(1.0, scaler);
5135 if (Edit->m_fontPicker2->GetFont().Scaled(scaler) !=
5136 g_FontTitle.GetChosenFont() ||
5137 Edit->m_fontPicker2->GetSelectedColour() != g_FontTitle.GetColour())
5138 DefaultFont =
false;
5139 if (Edit->m_fontPicker4->GetFont().Scaled(scaler) !=
5140 g_FontData.GetChosenFont() ||
5141 Edit->m_fontPicker4->GetSelectedColour() != g_FontData.GetColour())
5142 DefaultFont =
false;
5143 if (Edit->m_fontPicker5->GetFont().Scaled(scaler) !=
5144 g_FontLabel.GetChosenFont() ||
5145 Edit->m_fontPicker5->GetSelectedColour() != g_FontLabel.GetColour())
5146 DefaultFont =
false;
5147 if (Edit->m_fontPicker6->GetFont().Scaled(scaler) !=
5148 g_FontSmall.GetChosenFont() ||
5149 Edit->m_fontPicker6->GetSelectedColour() != g_FontSmall.GetColour())
5150 DefaultFont =
false;
5152 GetGlobalColor(
"DASHL", &dummy);
5153 if (Edit->m_colourPicker1->GetColour() != dummy) DefaultFont =
false;
5154 GetGlobalColor(
"DASHB", &dummy);
5155 if (Edit->m_colourPicker2->GetColour() != dummy) DefaultFont =
false;
5156 GetGlobalColor(
"DASHN", &dummy);
5157 if (Edit->m_colourPicker3->GetColour() != dummy) DefaultFont =
false;
5158 GetGlobalColor(
"BLUE3", &dummy);
5159 if (Edit->m_colourPicker4->GetColour() != dummy) DefaultFont =
false;
5161 cont->m_aInstrumentPropertyList.Remove(Inst);
5163 GetFontData(Edit->m_fontPicker2, Inst->m_USTitleFont, Inst->m_TitleFont,
5165 GetFontData(Edit->m_fontPicker4, Inst->m_USDataFont, Inst->m_DataFont,
5167 GetFontData(Edit->m_fontPicker5, Inst->m_USLabelFont, Inst->m_LabelFont,
5169 GetFontData(Edit->m_fontPicker6, Inst->m_USSmallFont, Inst->m_SmallFont,
5171 Inst->m_DataBackgroundColour = Edit->m_colourPicker2->GetColour();
5172 Inst->m_TitleBackgroundColour = Edit->m_colourPicker1->GetColour();
5173 Inst->m_Arrow_First_Colour = Edit->m_colourPicker3->GetColour();
5174 Inst->m_Arrow_Second_Colour = Edit->m_colourPicker4->GetColour();
5178 if (cont->m_pDashboardWindow) {
5179 cont->m_pDashboardWindow->SetInstrumentList(
5180 cont->m_aInstrumentList, &(cont->m_aInstrumentPropertyList));
5182 if (DefaultFont)
delete Inst;
5185void DashboardPreferencesDialog::OnInstrumentUp(wxCommandEvent &event) {
5186 long itemIDWindow = -1;
5187 itemIDWindow = m_pListCtrlDashboards->GetNextItem(
5188 itemIDWindow, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
5190 itemID = m_pListCtrlInstruments->GetNextItem(itemID, wxLIST_NEXT_ALL,
5191 wxLIST_STATE_SELECTED);
5194 item.SetMask(wxLIST_MASK_TEXT | wxLIST_MASK_IMAGE | wxLIST_MASK_DATA);
5195 m_pListCtrlInstruments->GetItem(item);
5196 item.SetId(itemID - 1);
5200 m_config.Item(m_pListCtrlDashboards->GetItemData(itemIDWindow));
5203 for (
unsigned int i = 0; i < (cont->m_aInstrumentPropertyList.GetCount());
5205 Inst = cont->m_aInstrumentPropertyList.Item(i);
5206 if (Inst->m_Listplace == (itemID - 1)) Inst->m_Listplace = itemID;
5207 if (Inst->m_aInstrument ==
5208 (
int)m_pListCtrlInstruments->GetItemData(itemID) &&
5209 Inst->m_Listplace == itemID) {
5210 cont->m_aInstrumentPropertyList.Item(i)->m_Listplace = itemID - 1;
5214 m_pListCtrlInstruments->DeleteItem(itemID);
5215 m_pListCtrlInstruments->InsertItem(item);
5216 for (
int i = 0; i < m_pListCtrlInstruments->GetItemCount(); i++)
5217 m_pListCtrlInstruments->SetItemState(i, 0, wxLIST_STATE_SELECTED);
5219 m_pListCtrlInstruments->SetItemState(itemID - 1, wxLIST_STATE_SELECTED,
5220 wxLIST_STATE_SELECTED);
5222 UpdateButtonsState();
5225void DashboardPreferencesDialog::OnInstrumentDown(wxCommandEvent &event) {
5226 long itemIDWindow = -1;
5227 itemIDWindow = m_pListCtrlDashboards->GetNextItem(
5228 itemIDWindow, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
5230 itemID = m_pListCtrlInstruments->GetNextItem(itemID, wxLIST_NEXT_ALL,
5231 wxLIST_STATE_SELECTED);
5235 item.SetMask(wxLIST_MASK_TEXT | wxLIST_MASK_IMAGE | wxLIST_MASK_DATA);
5236 m_pListCtrlInstruments->GetItem(item);
5237 item.SetId(itemID + 1);
5241 m_config.Item(m_pListCtrlDashboards->GetItemData(itemIDWindow));
5244 for (
unsigned int i = 0; i < (cont->m_aInstrumentPropertyList.GetCount());
5246 Inst = cont->m_aInstrumentPropertyList.Item(i);
5247 if (Inst->m_Listplace == (itemID + 1) &&
5248 Inst->m_aInstrument !=
5249 (int)m_pListCtrlInstruments->GetItemData(itemID))
5250 Inst->m_Listplace = itemID;
5251 if (Inst->m_aInstrument ==
5252 (
int)m_pListCtrlInstruments->GetItemData(itemID) &&
5253 Inst->m_Listplace == itemID) {
5254 cont->m_aInstrumentPropertyList.Item(i)->m_Listplace = itemID + 1;
5259 m_pListCtrlInstruments->DeleteItem(itemID);
5260 m_pListCtrlInstruments->InsertItem(item);
5261 for (
int i = 0; i < m_pListCtrlInstruments->GetItemCount(); i++)
5262 m_pListCtrlInstruments->SetItemState(i, 0, wxLIST_STATE_SELECTED);
5264 m_pListCtrlInstruments->SetItemState(itemID + 1, wxLIST_STATE_SELECTED,
5265 wxLIST_STATE_SELECTED);
5267 UpdateButtonsState();
5270void DashboardPreferencesDialog::OnDistanceUnitSelect(wxCommandEvent &event) {
5272 g_iDashDistanceUnit = m_choice_distance_unit->GetSelection() - 1;
5275 m_sum_log_value->SetValue(wxString::Format(
5285AddInstrumentDlg::AddInstrumentDlg(wxWindow *pparent, wxWindowID
id)
5286 : wxDialog(pparent, id, _(
"Add instrument"), wxDefaultPosition,
5287 wxDefaultSize, wxDEFAULT_DIALOG_STYLE) {
5288 wxBoxSizer *itemBoxSizer01 =
new wxBoxSizer(wxVERTICAL);
5289 SetSizer(itemBoxSizer01);
5290 wxStaticText *itemStaticText01 =
5291 new wxStaticText(
this, wxID_ANY, _(
"Select instrument to add:"),
5292 wxDefaultPosition, wxDefaultSize, 0);
5293 itemBoxSizer01->Add(itemStaticText01, 0, wxEXPAND | wxALL, 5);
5297 wxImageList *imglist =
5298 new wxImageList(instImageRefSize, instImageRefSize,
true, 2);
5300 wxImage inst1 = wxBitmap(*_img_instrument).ConvertToImage();
5302 inst1.Scale(instImageRefSize, instImageRefSize, wxIMAGE_QUALITY_HIGH);
5303 imglist->Add(wxBitmap(inst1s));
5305 wxImage dial1 = wxBitmap(*_img_dial).ConvertToImage();
5307 dial1.Scale(instImageRefSize, instImageRefSize, wxIMAGE_QUALITY_HIGH);
5308 imglist->Add(wxBitmap(dial1s));
5311 int vsize = dsize.y * 50 / 100;
5315 wxDisplaySize(&dw, &dh);
5316 vsize = dh * 50 / 100;
5319 m_pListCtrlInstruments =
new wxListCtrl(
5320 this, wxID_ANY, wxDefaultPosition, wxSize(-1, vsize ),
5321 wxLC_REPORT | wxLC_NO_HEADER | wxLC_SINGLE_SEL | wxLC_SORT_ASCENDING);
5322 itemBoxSizer01->Add(m_pListCtrlInstruments, 0, wxEXPAND | wxALL, 5);
5323 m_pListCtrlInstruments->AssignImageList(imglist, wxIMAGE_LIST_SMALL);
5324 m_pListCtrlInstruments->InsertColumn(0, _(
"Instruments"));
5327 m_pListCtrlInstruments->SetFont(*pF);
5330 m_pListCtrlInstruments->GetHandle()->setStyleSheet(qtStyleSheet);
5334 wxStdDialogButtonSizer *DialogButtonSizer =
5335 CreateStdDialogButtonSizer(wxOK | wxCANCEL);
5336 itemBoxSizer01->Add(DialogButtonSizer, 0, wxALIGN_RIGHT | wxALL, 5);
5339 for (
unsigned int i = ID_DBP_I_POS; i < ID_DBP_LAST_ENTRY;
5343 if (IsObsolete(i))
continue;
5344 getListItemForInstrument(item, i);
5346 m_pListCtrlInstruments->InsertItem(item);
5350 m_pListCtrlInstruments->SetColumnWidth(0, wxLIST_AUTOSIZE);
5351 m_pListCtrlInstruments->SetItemState(0, wxLIST_STATE_SELECTED,
5352 wxLIST_STATE_SELECTED);
5356unsigned int AddInstrumentDlg::GetInstrumentAdded() {
5358 itemID = m_pListCtrlInstruments->GetNextItem(itemID, wxLIST_NEXT_ALL,
5359 wxLIST_STATE_SELECTED);
5361 return (
int)m_pListCtrlInstruments->GetItemData(itemID);
5371DashboardWindow::DashboardWindow(wxWindow *pparent, wxWindowID
id,
5374 : wxWindow(pparent, id, wxDefaultPosition, wxDefaultSize, 0) {
5380 m_Container = mycont;
5383 itemBoxSizer =
new wxBoxSizer(orient);
5384 SetSizer(itemBoxSizer);
5385 Connect(wxEVT_SIZE, wxSizeEventHandler(DashboardWindow::OnSize), NULL,
this);
5386 Connect(wxEVT_CONTEXT_MENU,
5387 wxContextMenuEventHandler(DashboardWindow::OnContextMenu), NULL,
5389 Connect(wxEVT_COMMAND_MENU_SELECTED,
5390 wxCommandEventHandler(DashboardWindow::OnContextMenuSelect), NULL,
5394 Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(DashboardWindow::OnMouseEvent));
5395 Connect(wxEVT_LEFT_UP, wxMouseEventHandler(DashboardWindow::OnMouseEvent));
5396 Connect(wxEVT_MOTION, wxMouseEventHandler(DashboardWindow::OnMouseEvent));
5398 GetHandle()->setAttribute(Qt::WA_AcceptTouchEvents);
5399 GetHandle()->grabGesture(Qt::PinchGesture);
5400 GetHandle()->grabGesture(Qt::PanGesture);
5402 Connect(wxEVT_QT_PINCHGESTURE,
5407 wxEVT_QT_PANGESTURE,
5408 (wxObjectEventFunction)(wxEventFunction)&DashboardWindow::OnEvtPanGesture,
5414 m_binResize =
false;
5418DashboardWindow::~DashboardWindow() {
5419 for (
size_t i = 0; i < m_ArrayOfInstrument.GetCount(); i++) {
5426void DashboardWindow::OnEvtPinchGesture(wxQT_PinchGestureEvent &event) {
5427 float zoom_gain = 0.3;
5429 float total_zoom_val;
5431 if (event.GetScaleFactor() > 1)
5432 zoom_val = ((
event.GetScaleFactor() - 1.0) * zoom_gain) + 1.0;
5434 zoom_val = 1.0 - ((1.0 -
event.GetScaleFactor()) * zoom_gain);
5436 if (event.GetTotalScaleFactor() > 1)
5437 total_zoom_val = ((event.GetTotalScaleFactor() - 1.0) * zoom_gain) + 1.0;
5439 total_zoom_val = 1.0 - ((1.0 -
event.GetTotalScaleFactor()) * zoom_gain);
5441 wxAuiPaneInfo &pane = m_pauimgr->GetPane(
this);
5443 wxSize currentSize = wxSize(pane.floating_size.x, pane.floating_size.y);
5444 double aRatio = (double)currentSize.y / (
double)currentSize.x;
5447 wxPoint par_pos = wxPoint(pane.floating_pos.x, pane.floating_pos.y);
5449 switch (event.GetState()) {
5450 case GestureStarted:
5454 case GestureUpdated:
5455 currentSize.y *= zoom_val;
5456 currentSize.x *= zoom_val;
5458 if ((par_pos.y + currentSize.y) > par_size.y)
5459 currentSize.y = par_size.y - par_pos.y;
5461 if ((par_pos.x + currentSize.x) > par_size.x)
5462 currentSize.x = par_size.x - par_pos.x;
5465 currentSize.x = currentSize.y / aRatio;
5467 currentSize.x = wxMax(currentSize.x, 150);
5468 currentSize.y = wxMax(currentSize.y, 150);
5470 pane.FloatingSize(currentSize);
5471 m_pauimgr->Update();
5475 case GestureFinished: {
5476 if (itemBoxSizer->GetOrientation() == wxVERTICAL) {
5477 currentSize.y *= total_zoom_val;
5478 currentSize.x = currentSize.y / aRatio;
5480 currentSize.x *= total_zoom_val;
5481 currentSize.y = currentSize.x * aRatio;
5485 if ((par_pos.y + currentSize.y) > par_size.y)
5486 currentSize.y = par_size.y - par_pos.y;
5488 if ((par_pos.x + currentSize.x) > par_size.x)
5489 currentSize.x = par_size.x - par_pos.x;
5492 currentSize.x = wxMax(currentSize.x, 150);
5493 currentSize.y = wxMax(currentSize.y, 150);
5498 if (itemBoxSizer->GetOrientation() == wxVERTICAL) {
5500 for (
unsigned int i = 0; i < m_ArrayOfInstrument.size(); i++) {
5502 m_ArrayOfInstrument.Item(i)->m_pInstrument;
5504 inst->GetSize(itemBoxSizer->GetOrientation(), currentSize);
5508 currentSize.y = total_y;
5511 pane.FloatingSize(currentSize);
5514 for (
unsigned int i = 0; i < m_ArrayOfInstrument.size(); i++) {
5519 m_pauimgr->Update();
5522 m_binResize =
false;
5527 case GestureCanceled:
5529 m_binResize =
false;
5537void DashboardWindow::OnEvtPanGesture(wxQT_PanGestureEvent &event) {
5538 if (m_binPinch)
return;
5540 if (m_binResize)
return;
5542 int x =
event.GetOffset().x;
5543 int y =
event.GetOffset().y;
5545 int lx =
event.GetLastOffset().x;
5546 int ly =
event.GetLastOffset().y;
5551 switch (event.GetState()) {
5552 case GestureStarted:
5553 if (m_binPan)
break;
5558 case GestureUpdated:
5561 wxPoint par_pos_old = ClientToScreen(wxPoint(0, 0));
5563 wxPoint par_pos = par_pos_old;
5567 par_pos.x = wxMax(par_pos.x, 0);
5568 par_pos.y = wxMax(par_pos.y, 0);
5570 wxSize mySize = GetSize();
5572 if ((par_pos.y + mySize.y) > par_size.y)
5573 par_pos.y = par_size.y - mySize.y;
5575 if ((par_pos.x + mySize.x) > par_size.x)
5576 par_pos.x = par_size.x - mySize.x;
5578 wxAuiPaneInfo &pane = m_pauimgr->GetPane(
this);
5579 pane.FloatingPosition(par_pos).Float();
5580 m_pauimgr->Update();
5584 case GestureFinished:
5591 case GestureCanceled:
5600void DashboardWindow::OnMouseEvent(wxMouseEvent &event) {
5601 if (m_binPinch)
return;
5604 wxAuiPaneInfo &pane = m_pauimgr->GetPane(
this);
5605 wxSize currentSize = wxSize(pane.floating_size.x, pane.floating_size.y);
5606 double aRatio = (double)currentSize.y / (
double)currentSize.x;
5609 wxPoint par_pos = wxPoint(pane.floating_pos.x, pane.floating_pos.y);
5611 if (event.LeftDown()) {
5612 m_resizeStartPoint =
event.GetPosition();
5613 m_resizeStartSize = currentSize;
5614 m_binResize2 =
true;
5618 if (event.Dragging()) {
5619 wxPoint p =
event.GetPosition();
5621 wxSize dragSize = m_resizeStartSize;
5623 dragSize.y += p.y - m_resizeStartPoint.y;
5624 dragSize.x += p.x - m_resizeStartPoint.x;
5627 if ((par_pos.y + dragSize.y) > par_size.y)
5628 dragSize.y = par_size.y - par_pos.y;
5630 if ((par_pos.x + dragSize.x) > par_size.x)
5631 dragSize.x = par_size.x - par_pos.x;
5637 dragSize.x = wxMax(dragSize.x, 150);
5638 dragSize.y = wxMax(dragSize.y, 150);
5640 pane.FloatingSize(dragSize);
5641 m_pauimgr->Update();
5644 if (event.LeftUp()) {
5645 wxPoint p =
event.GetPosition();
5647 wxSize dragSize = m_resizeStartSize;
5649 dragSize.y += p.y - m_resizeStartPoint.y;
5650 dragSize.x += p.x - m_resizeStartPoint.x;
5653 if ((par_pos.y + dragSize.y) > par_size.y)
5654 dragSize.y = par_size.y - par_pos.y;
5656 if ((par_pos.x + dragSize.x) > par_size.x)
5657 dragSize.x = par_size.x - par_pos.x;
5660 dragSize.x = wxMax(dragSize.x, 150);
5661 dragSize.y = wxMax(dragSize.y, 150);
5668 pane.FloatingSize(dragSize);
5669 m_pauimgr->Update();
5671 m_binResize =
false;
5672 m_binResize2 =
false;
5679void DashboardWindow::OnSize(wxSizeEvent &event) {
5681 for (
unsigned int i = 0; i < m_ArrayOfInstrument.size(); i++) {
5684 inst->GetSize(itemBoxSizer->GetOrientation(), GetClientSize()));
5689 this->m_Container->m_best_size =
event.GetSize();
5692void DashboardWindow::OnContextMenu(wxContextMenuEvent &event) {
5693 wxMenu *contextMenu =
new wxMenu();
5700 new wxMenuItem(contextMenu, ID_DASH_PREFS, _(
"Preferences..."));
5701 item1->SetFont(*pf);
5702 contextMenu->Append(item1);
5705 new wxMenuItem(contextMenu, ID_DASH_RESIZE, _(
"Resize..."));
5706 item2->SetFont(*pf);
5707 contextMenu->Append(item2);
5711 wxAuiPaneInfo &pane = m_pauimgr->GetPane(
this);
5712 if (pane.IsOk() && pane.IsDocked()) {
5713 contextMenu->Append(ID_DASH_UNDOCK, _(
"Undock"));
5715 wxMenuItem *btnVertical =
5716 contextMenu->AppendRadioItem(ID_DASH_VERTICAL, _(
"Vertical"));
5717 btnVertical->Check(itemBoxSizer->GetOrientation() == wxVERTICAL);
5718 wxMenuItem *btnHorizontal =
5719 contextMenu->AppendRadioItem(ID_DASH_HORIZONTAL, _(
"Horizontal"));
5720 btnHorizontal->Check(itemBoxSizer->GetOrientation() == wxHORIZONTAL);
5721 contextMenu->AppendSeparator();
5723 m_plugin->PopulateContextMenu(contextMenu);
5725 contextMenu->AppendSeparator();
5726 contextMenu->Append(ID_DASH_PREFS, _(
"Preferences..."));
5730 PopupMenu(contextMenu);
5734void DashboardWindow::OnContextMenuSelect(wxCommandEvent &event) {
5735 if (event.GetId() < ID_DASH_PREFS) {
5736 if (m_plugin->GetDashboardWindowShownCount() > 1 || event.IsChecked())
5737 m_plugin->ShowDashboard(event.GetId() - 1, event.IsChecked());
5739 m_plugin->ShowDashboard(event.GetId() - 1,
true);
5742 m_plugin->GetDashboardWindowShownCount() != 0);
5745 switch (event.GetId()) {
5746 case ID_DASH_PREFS: {
5747 wxAuiPaneInfo &pane = m_pauimgr->GetPane(
this);
5749 wxPoint fp = pane.floating_pos;
5757 if (!pane.IsDocked())
5758 ChangePaneOrientation(GetSizerOrientation(),
true, fp.x, fp.y);
5760 if (g_bUseInternSumLog) m_plugin->UpdateSumLog(
false);
5763 case ID_DASH_RESIZE: {
5774 case ID_DASH_VERTICAL: {
5775 ChangePaneOrientation(wxVERTICAL,
true);
5776 m_Container->m_sOrientation =
"V";
5779 case ID_DASH_HORIZONTAL: {
5780 ChangePaneOrientation(wxHORIZONTAL,
true);
5781 m_Container->m_sOrientation =
"H";
5784 case ID_DASH_UNDOCK: {
5785 ChangePaneOrientation(GetSizerOrientation(),
true);
5789 m_plugin->SaveConfig();
5796 wxColour col = g_BackgroundColor;
5798 if (!g_ForceBackgroundColor) GetGlobalColor(
"DASHL", &col);
5799 SetBackgroundColour(col);
5804void DashboardWindow::ChangePaneOrientation(
int orient,
bool updateAUImgr,
5806 m_pauimgr->DetachPane(
this);
5807 SetSizerOrientation(orient);
5808 bool vertical = orient == wxVERTICAL;
5810 wxSize sz = GetMinSize();
5812 m_Container->m_sName = MakeName();
5813 m_pauimgr->AddPane(
this, wxAuiPaneInfo()
5814 .Name(m_Container->m_sName)
5815 .Caption(m_Container->m_sCaption)
5816 .CaptionVisible(
true)
5817 .TopDockable(!vertical)
5818 .BottomDockable(!vertical)
5819 .LeftDockable(vertical)
5820 .RightDockable(vertical)
5824 .FloatingPosition(fpx, fpy)
5826 .Show(m_Container->m_bIsVisible));
5829 wxAuiPaneInfo &pane = m_pauimgr->GetPane(
this);
5830 pane.Dockable(
false);
5833 if (updateAUImgr) m_pauimgr->Update();
5836void DashboardWindow::SetSizerOrientation(
int orient) {
5837 itemBoxSizer->SetOrientation(orient);
5839 wxWindowListNode *node = GetChildren().GetFirst();
5841 node->GetData()->SetMinSize(wxDefaultSize);
5842 node = node->GetNext();
5844 SetMinSize(wxDefaultSize);
5846 SetMinSize(itemBoxSizer->GetMinSize());
5849int DashboardWindow::GetSizerOrientation() {
5850 return itemBoxSizer->GetOrientation();
5853bool isArrayIntEqual(
const wxArrayInt &l1,
const wxArrayOfInstrument &l2) {
5854 if (l1.GetCount() != l2.GetCount())
return false;
5856 for (
size_t i = 0; i < l1.GetCount(); i++)
5857 if (l1.Item(i) != l2.Item(i)->m_ID)
return false;
5862bool DashboardWindow::isInstrumentListEqual(
const wxArrayInt &list) {
5863 return isArrayIntEqual(list, m_ArrayOfInstrument);
5866void DashboardWindow::SetInstrumentList(
5867 wxArrayInt list, wxArrayOfInstrumentProperties *InstrumentPropertyList) {
5881 m_ArrayOfInstrument.Clear();
5882 itemBoxSizer->Clear(
true);
5883 for (
size_t i = 0; i < list.GetCount(); i++) {
5884 int id = list.Item(i);
5886 for (
size_t j = 0; j < InstrumentPropertyList->GetCount(); j++) {
5887 if (InstrumentPropertyList->Item(j)->m_aInstrument ==
id &&
5888 InstrumentPropertyList->Item(j)->m_Listplace == (
int)i) {
5889 Properties = InstrumentPropertyList->Item(j);
5897 this, wxID_ANY, getInstrumentCaption(
id), Properties);
5901 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5906 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5909 ->SetOptionLabel(g_iDashSpeedMax / 20 + 1, DIAL_LABEL_HORIZONTAL);
5913 ->SetOptionMarker(0.5, DIAL_MARKER_SIMPLE, 2);
5916 DIAL_POSITION_BOTTOMMIDDLE);
5920 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5923 ->SetOptionLabel(g_iDashSpeedMax / 20 + 1, DIAL_LABEL_HORIZONTAL);
5927 ->SetOptionMarker(0.5, DIAL_MARKER_SIMPLE, 2);
5930 DIAL_POSITION_BOTTOMMIDDLE);
5934 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5939 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5944 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5947 ->SetOptionMarker(5, DIAL_MARKER_SIMPLE, 2);
5949 ->SetOptionLabel(30, DIAL_LABEL_ROTATED);
5952 DIAL_POSITION_BOTTOMLEFT);
5956 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5959 ->SetOptionMarker(5, DIAL_MARKER_SIMPLE, 2);
5961 ->SetOptionLabel(30, DIAL_LABEL_ROTATED);
5964 DIAL_POSITION_BOTTOMLEFT);
5968 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5974 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5979 this, wxID_ANY, getInstrumentCaption(
id), Properties,
5985 getInstrumentCaption(
id),
5988 ->SetOptionMainValue(
"%.0f", DIAL_POSITION_BOTTOMLEFT);
5991 DIAL_POSITION_INSIDE);
5995 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6000 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6003 ->SetOptionLabel(5, DIAL_LABEL_HORIZONTAL);
6005 ->SetOptionMarker(1, DIAL_MARKER_SIMPLE, 5);
6007 ->SetOptionMainValue(
"A %.1f", DIAL_POSITION_BOTTOMLEFT);
6010 DIAL_POSITION_BOTTOMRIGHT);
6014 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6017 ->SetOptionMainValue(
"%.0f", DIAL_POSITION_BOTTOMLEFT);
6020 DIAL_POSITION_INSIDE);
6022 case ID_DBP_D_AWA_TWA:
6024 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6028 ->SetOptionMainValue(
"%.0f", DIAL_POSITION_NONE);
6036 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6039 ->SetOptionMainValue(
"%.0f", DIAL_POSITION_BOTTOMLEFT);
6042 DIAL_POSITION_INSIDE);
6046 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6051 this, wxID_ANY, getInstrumentCaption(
id), Properties);
6055 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6060 this, wxID_ANY, getInstrumentCaption(
id), Properties);
6064 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6069 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6074 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6077 ->SetOptionLabel(15, DIAL_LABEL_HORIZONTAL);
6079 ->SetOptionMarker(7.5, DIAL_MARKER_SIMPLE, 1);
6081 ->SetOptionMainValue(
"%5.1f", DIAL_POSITION_INSIDE);
6085 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6090 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6096 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6102 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6107 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6112 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6117 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6122 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6127 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6132 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6135 ->SetOptionLabel(1, DIAL_LABEL_HORIZONTAL);
6137 ->SetOptionMarker(0.5, DIAL_MARKER_SIMPLE, 2);
6140 DIAL_POSITION_BOTTOMLEFT);
6144 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6149 this, wxID_ANY, getInstrumentCaption(
id), Properties);
6153 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6158 this, wxID_ANY, getInstrumentCaption(
id), Properties);
6162 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6165 case ID_DBP_I_GPSUTC:
6167 this, wxID_ANY, getInstrumentCaption(
id), Properties);
6171 this, wxID_ANY, getInstrumentCaption(
id), Properties);
6175 this, wxID_ANY, getInstrumentCaption(
id), Properties);
6179 this, wxID_ANY, getInstrumentCaption(
id), Properties);
6183 this, wxID_ANY, getInstrumentCaption(
id), Properties);
6187 this, wxID_ANY, getInstrumentCaption(
id), Properties);
6189 case ID_DBP_I_PITCH:
6191 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6196 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6203 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6204 "%02i:%02i:%02i LCL");
6208 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6213 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6214 "%02i:%02i:%02i LCL");
6218 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6223 this, wxID_ANY, getInstrumentCaption(
id), Properties,
6228 instrument->instrumentTypeId = id;
6230 id, instrument, instrument->GetCapacity()));
6231 itemBoxSizer->Add(instrument, 0, wxEXPAND, 0);
6232 if (itemBoxSizer->GetOrientation() == wxHORIZONTAL) {
6233 itemBoxSizer->AddSpacer(5);
6244 wxSize Hint = wxSize(DefaultWidth, DefaultWidth);
6246 for (
unsigned int i = 0; i < m_ArrayOfInstrument.size(); i++) {
6248 inst->SetMinSize(inst->GetSize(itemBoxSizer->GetOrientation(), Hint));
6249 Hint = inst->GetMinSize();
6254 SetMinSize(itemBoxSizer->GetMinSize());
6257void DashboardWindow::SendSentenceToAllInstruments(
DASH_CAP st,
double value,
6259 for (
size_t i = 0; i < m_ArrayOfInstrument.GetCount(); i++) {
6260 if (m_ArrayOfInstrument.Item(i)->m_cap_flag.test(st))
6261 m_ArrayOfInstrument.Item(i)->m_pInstrument->SetData(st, value,
unit);
6265void DashboardWindow::SendSatInfoToAllInstruments(
int cnt,
int seq,
6268 for (
size_t i = 0; i < m_ArrayOfInstrument.GetCount(); i++) {
6271 m_ArrayOfInstrument.Item(i)->m_pInstrument))
6273 ->SetSatInfo(cnt, seq, talk, sats);
6277void DashboardWindow::SendUtcTimeToAllInstruments(wxDateTime value) {
6278 for (
size_t i = 0; i < m_ArrayOfInstrument.GetCount(); i++) {
6281 m_ArrayOfInstrument.Item(i)->m_pInstrument))
6289 ->SetUtcTime(value);
6305bool OCPNFontButton::Create(wxWindow *parent, wxWindowID
id,
6306 const wxFontData &initial,
const wxPoint &pos,
6307 const wxSize &size,
long style,
6308 const wxValidator &validator,
6309 const wxString &name) {
6310 wxString label = (style & wxFNTP_FONTDESC_AS_LABEL)
6316 if (!wxButton::Create(parent,
id, label, pos, size, style, validator, name)) {
6317 wxFAIL_MSG(
"OCPNFontButton creation failed");
6322 Connect(GetId(), wxEVT_BUTTON,
6323 wxCommandEventHandler(OCPNFontButton::OnButtonClick), NULL,
this);
6327 initial.GetChosenFont().IsOk() ? initial.GetChosenFont() : *wxNORMAL_FONT;
6333void OCPNFontButton::OnButtonClick(wxCommandEvent &WXUNUSED(ev)) {
6335 m_data.SetInitialFont(m_selectedFont);
6340 int display_height = wxGetDisplaySize().y;
6341 if (display_height < 800) {
6345 if (dlg.ShowModal() == wxID_OK) {
6346 m_data = dlg.GetFontData();
6347 m_selectedFont = m_data.GetChosenFont();
6349 wxFontPickerEvent event(
this, GetId(), m_selectedFont);
6350 GetEventHandler()->ProcessEvent(event);
6355 wxFontDialog dlg(
this, m_data);
6357 if (dlg.ShowModal() == wxID_OK) {
6358 m_data = dlg.GetFontData();
6359 m_selectedFont = m_data.GetChosenFont();
6361 wxFontPickerEvent event(
this, GetId(), m_selectedFont);
6362 GetEventHandler()->ProcessEvent(event);
6369 wxFontDialog dlg(
this, m_data);
6375 wxSize proposed_size = GetParent()->GetSize();
6377 float font_size = pF->GetPointSize();
6379 if ((proposed_size.y / font_size) < n_lines) {
6380 float new_font_size = proposed_size.y / n_lines;
6381 wxFont *smallFont =
new wxFont(*pF);
6382 smallFont->SetPointSize(new_font_size);
6383 dlg.SetFont(*smallFont);
6386 dlg.SetSize(GetParent()->GetSize());
6390 if (dlg.ShowModal() == wxID_OK) {
6391 m_data = dlg.GetFontData();
6392 m_selectedFont = m_data.GetChosenFont();
6395 wxFontPickerEvent event(
this, GetId(), m_selectedFont);
6396 GetEventHandler()->ProcessEvent(event);
6403void OCPNFontButton::UpdateFont() {
6404 if (!m_selectedFont.IsOk())
return;
6409 if (HasFlag(wxFNTP_USEFONT_FOR_LABEL)) {
6411 wxButton::SetFont(m_selectedFont);
6412 wxButton::SetForegroundColour(GetSelectedColour());
6416 wxString::Format(
"%s, %d", m_selectedFont.GetFaceName().c_str(),
6417 m_selectedFont.GetPointSize());
6419 if (HasFlag(wxFNTP_FONTDESC_AS_LABEL)) {
6423 auto minsize = GetTextExtent(label);
6426 GetParent()->Layout();
6433 wxWindowID
id,
const wxString &title,
const wxPoint &pos,
6434 const wxSize &size,
long style)
6435 : wxDialog(parent, id, title, pos, size, style) {
6436 this->SetSizeHints(wxDefaultSize, wxDefaultSize);
6438 wxBoxSizer *bSizer5;
6439 bSizer5 =
new wxBoxSizer(wxVERTICAL);
6441 wxFlexGridSizer *fgSizer2;
6442 fgSizer2 =
new wxFlexGridSizer(0, 2, 0, 0);
6443 fgSizer2->SetFlexibleDirection(wxBOTH);
6444 fgSizer2->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);
6446 m_staticText1 =
new wxStaticText(
this, wxID_ANY, _(
"Title:"),
6447 wxDefaultPosition, wxDefaultSize, 0);
6448 m_staticText1->Wrap(-1);
6449 fgSizer2->Add(m_staticText1, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
6451 m_fontPicker2 =
new wxFontPickerCtrl(
this, wxID_ANY, Properties.m_USTitleFont,
6452 wxDefaultPosition, wxDefaultSize);
6453 fgSizer2->Add(m_fontPicker2, 0, wxALL, 5);
6455 m_staticText5 =
new wxStaticText(
this, wxID_ANY, _(
"Title background color:"),
6456 wxDefaultPosition, wxDefaultSize, 0);
6457 m_staticText5->Wrap(-1);
6458 fgSizer2->Add(m_staticText5, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
6460 m_colourPicker1 =
new wxColourPickerCtrl(
6461 this, wxID_ANY, Properties.m_TitleBackgroundColour, wxDefaultPosition,
6462 wxDefaultSize, wxCLRP_DEFAULT_STYLE);
6463 fgSizer2->Add(m_colourPicker1, 0, wxALL, 5);
6465 m_staticText2 =
new wxStaticText(
this, wxID_ANY, _(
"Data:"),
6466 wxDefaultPosition, wxDefaultSize, 0);
6467 m_staticText2->Wrap(-1);
6468 fgSizer2->Add(m_staticText2, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
6470 m_fontPicker4 =
new wxFontPickerCtrl(
this, wxID_ANY, Properties.m_USDataFont,
6471 wxDefaultPosition, wxDefaultSize);
6472 fgSizer2->Add(m_fontPicker4, 0, wxALL, 5);
6474 m_staticText6 =
new wxStaticText(
this, wxID_ANY, _(
"Data background color:"),
6475 wxDefaultPosition, wxDefaultSize, 0);
6476 m_staticText6->Wrap(-1);
6477 fgSizer2->Add(m_staticText6, 0, wxALL, 5);
6479 m_colourPicker2 =
new wxColourPickerCtrl(
6480 this, wxID_ANY, Properties.m_DataBackgroundColour, wxDefaultPosition,
6481 wxDefaultSize, wxCLRP_DEFAULT_STYLE);
6482 fgSizer2->Add(m_colourPicker2, 0, wxALL, 5);
6484 m_staticText3 =
new wxStaticText(
this, wxID_ANY, _(
"Label:"),
6485 wxDefaultPosition, wxDefaultSize, 0);
6486 m_staticText3->Wrap(-1);
6487 fgSizer2->Add(m_staticText3, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
6489 m_fontPicker5 =
new wxFontPickerCtrl(
this, wxID_ANY, Properties.m_USLabelFont,
6490 wxDefaultPosition, wxDefaultSize);
6491 fgSizer2->Add(m_fontPicker5, 0, wxALL, 5);
6493 m_staticText4 =
new wxStaticText(
this, wxID_ANY, _(
"Small:"),
6494 wxDefaultPosition, wxDefaultSize, 0);
6495 m_staticText4->Wrap(-1);
6496 fgSizer2->Add(m_staticText4, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
6498 m_fontPicker6 =
new wxFontPickerCtrl(
this, wxID_ANY, Properties.m_USSmallFont,
6499 wxDefaultPosition, wxDefaultSize);
6500 fgSizer2->Add(m_fontPicker6, 0, wxALL, 5);
6502 m_staticText9 =
new wxStaticText(
this, wxID_ANY, _(
"Arrow 1 Color :"),
6503 wxDefaultPosition, wxDefaultSize, 0);
6504 m_staticText9->Wrap(-1);
6505 fgSizer2->Add(m_staticText9, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
6507 m_colourPicker3 =
new wxColourPickerCtrl(
6508 this, wxID_ANY, Properties.m_Arrow_First_Colour, wxDefaultPosition,
6509 wxDefaultSize, wxCLRP_DEFAULT_STYLE);
6510 fgSizer2->Add(m_colourPicker3, 0, wxALL, 5);
6512 m_staticText10 =
new wxStaticText(
this, wxID_ANY, _(
"Arrow 2 Color :"),
6513 wxDefaultPosition, wxDefaultSize, 0);
6514 m_staticText10->Wrap(-1);
6515 fgSizer2->Add(m_staticText10, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
6517 m_colourPicker4 =
new wxColourPickerCtrl(
6518 this, wxID_ANY, Properties.m_Arrow_Second_Colour, wxDefaultPosition,
6519 wxDefaultSize, wxCLRP_DEFAULT_STYLE);
6520 fgSizer2->Add(m_colourPicker4, 0, wxALL, 5);
6522 m_staticline1 =
new wxStaticLine(
this, wxID_ANY, wxDefaultPosition,
6523 wxDefaultSize, wxLI_HORIZONTAL);
6524 fgSizer2->Add(m_staticline1, 0, wxEXPAND | wxALL, 5);
6526 m_staticline2 =
new wxStaticLine(
this, wxID_ANY, wxDefaultPosition,
6527 wxDefaultSize, wxLI_HORIZONTAL);
6528 fgSizer2->Add(m_staticline2, 0, wxEXPAND | wxALL, 5);
6530 fgSizer2->Add(0, 5, 1, wxEXPAND, 5);
6532 fgSizer2->Add(0, 0, 1, wxEXPAND, 5);
6534 m_staticText7 =
new wxStaticText(
this, wxID_ANY, wxEmptyString,
6535 wxDefaultPosition, wxDefaultSize, 0);
6536 m_staticText7->Wrap(-1);
6537 fgSizer2->Add(m_staticText7, 0, wxALL, 5);
6539 m_button1 =
new wxButton(
this, wxID_ANY, _(
"Set default"), wxDefaultPosition,
6541 fgSizer2->Add(m_button1, 0, wxALL, 5);
6543 fgSizer2->Add(0, 5, 1, wxEXPAND, 5);
6545 fgSizer2->Add(5, 0, 1, wxEXPAND, 5);
6547 bSizer5->Add(fgSizer2, 1, wxALL | wxEXPAND, 5);
6549 m_sdbSizer3 =
new wxStdDialogButtonSizer();
6550 m_sdbSizer3OK =
new wxButton(
this, wxID_OK);
6551 m_sdbSizer3->AddButton(m_sdbSizer3OK);
6552 m_sdbSizer3Cancel =
new wxButton(
this, wxID_CANCEL);
6553 m_sdbSizer3->AddButton(m_sdbSizer3Cancel);
6554 m_sdbSizer3->Realize();
6556 bSizer5->Add(m_sdbSizer3, 0, 0, 1);
6558 bSizer5->Add(0, 10, 0, wxEXPAND, 5);
6560 this->SetSizer(bSizer5);
6564 this->Centre(wxBOTH);
6567 m_button1->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
6568 wxCommandEventHandler(EditDialog::OnSetdefault), NULL,
6572EditDialog::~EditDialog() {
6574 m_button1->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED,
6575 wxCommandEventHandler(EditDialog::OnSetdefault), NULL,
6579void EditDialog::OnSetdefault(wxCommandEvent &event) {
6580 m_fontPicker2->SetSelectedFont(g_USFontTitle.GetChosenFont());
6581 m_fontPicker2->SetSelectedColour(g_USFontTitle.GetColour());
6582 m_fontPicker4->SetSelectedFont(g_USFontData.GetChosenFont());
6583 m_fontPicker4->SetSelectedColour(g_USFontData.GetColour());
6584 m_fontPicker5->SetSelectedFont(g_USFontLabel.GetChosenFont());
6585 m_fontPicker5->SetSelectedColour(g_USFontLabel.GetColour());
6586 m_fontPicker6->SetSelectedFont(g_USFontSmall.GetChosenFont());
6587 m_fontPicker6->SetSelectedColour(g_USFontSmall.GetColour());
6589 GetGlobalColor(
"DASHL", &dummy);
6590 m_colourPicker1->SetColour(dummy);
6591 GetGlobalColor(
"DASHB", &dummy);
6592 m_colourPicker2->SetColour(dummy);
6593 GetGlobalColor(
"DASHN", &dummy);
6594 m_colourPicker3->SetColour(dummy);
6595 GetGlobalColor(
"BLUE3", &dummy);
6596 m_colourPicker4->SetColour(dummy);
6602void dashboard_pi::UpdateSumLog(
bool write) {
6604 g_dSumLogNM += d_tripNM;
6607 if (++confprint > 10) {
6608 wxFileConfig *logConf = (wxFileConfig *)m_pconfig;
6610 logConf->SetPath(
"/PlugIns/Dashboard");
6611 logConf->Write(
"SumLogNM", g_dSumLogNM);
6617 if (g_bUseInternSumLog) {
6618 SendSentenceToAllInstruments(
6622 m_log_watchdog = 70;
6627 SendSentenceToAllInstruments(
6631 m_log_watchdog = no_nav_watchdog_timeout_ticks;
Dashboard altitude instrument.
Dashboard barometer history instrument.
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 speedometer style control.
A dashboard instrument that displays sunrise and sunset times.
Custom event class for OpenCPN's notification system.
Extended position fix information.
int nSats
Number of satellites used in the fix.
double Var
Magnetic variation in degrees, typically from RMC message.
double Cog
Course over ground in degrees [0-360).
double Lat
Latitude in decimal degrees.
double Hdm
Heading magnetic in degrees [0-360).
time_t FixTime
UTC time of fix.
double Lon
Longitude in decimal degrees.
double Sog
Speed over ground in knots.
double Hdt
Heading true in degrees [0-360).
int GetAPIVersionMajor() override
Returns the major version number of the plugin API that this plugin supports.
void SetNMEASentence(wxString &sentence) override
Receive all NMEA 0183 sentences from OpenCPN.
void SetPositionFixEx(PlugIn_Position_Fix_Ex &pfix) override
Updates plugin with extended position fix data at regular intervals.
void UpdateAuiStatus() override
Updates AUI manager status.
int GetPlugInVersionMajor() override
Returns the major version number of the plugin itself.
bool DeInit() override
Clean up plugin resources.
void OnToolbarToolCallback(int id) override
Handles toolbar tool clicks.
wxString GetLongDescription() override
Get detailed plugin information.
void ShowPreferencesDialog(wxWindow *parent) override
Shows the plugin preferences dialog.
wxString GetCommonName() override
Get the plugin's common (short) name.
wxString GetShortDescription() override
Get a brief description of the plugin.
int Init() override
Initialize the plugin and declare its capabilities.
int GetPlugInVersionMinor() override
Returns the minor version number of the plugin itself.
int GetToolbarToolCount() override
Returns the number of toolbar tools this plugin provides.
int GetAPIVersionMinor() override
Returns the minor version number of the plugin API that this plugin supports.
void SetCursorLatLon(double lat, double lon) override
Receives cursor lat/lon position updates.
void SetColorScheme(PI_ColorScheme cs) override
Updates plugin color scheme.
wxBitmap * GetPlugInBitmap() override
Get the plugin's icon bitmap.
Base class for OpenCPN plugins.
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.
Dashboard clock instrument.
@ ID_DBP_I_GPSLCL
GNSS Clock formatted in local time.
@ ID_DBP_I_CPULCL
Computer Clock formatted in local time.
@ ID_DBP_I_SUNLCL
Sunrise/Sunset time formatted in local time.
Dashboard depth instrument.
Dashboard own ship data instrument.
Dashboard GPS instrument.
@ OCPN_DBP_STC_VLW1
Trip Log.
@ OCPN_DBP_STC_AWA
Apparent wind angle.
@ OCPN_DBP_STC_PITCH
Pitch.
@ OCPN_DBP_STC_RSA
Rudder angle.
@ OCPN_DBP_STC_AWS
Apparent wind speed.
@ OCPN_DBP_STC_STW
Speed through water.
@ OCPN_DBP_STC_VMGW
Velocity made good to windward.
@ OCPN_DBP_STC_PLA
Cursor latitude.
@ OCPN_DBP_STC_SAT
Satellite count in use.
@ OCPN_DBP_STC_HDT
Heading true North.
@ OCPN_DBP_STC_VMG
Velocity made good.
@ OCPN_DBP_STC_TWS2
True Wind Speed, same calculation as TWS.
@ OCPN_DBP_STC_ALTI
Altitude.
@ OCPN_DBP_STC_GPS
GPS status.
@ OCPN_DBP_STC_HDM
Heading magnetic North.
@ OCPN_DBP_STC_TWA
True wind angle.
@ OCPN_DBP_STC_SOG
Speed over ground.
@ OCPN_DBP_STC_VLW2
Sum Log.
@ OCPN_DBP_STC_LON
Longitude.
@ OCPN_DBP_STC_MCOG
Magnetic Course over Ground.
@ OCPN_DBP_STC_PLO
Cursor longitude.
@ OCPN_DBP_STC_HMV
Magnetic variation from NMEA device if available (not from WMM)
@ OCPN_DBP_STC_ATMP
Air Temperature.
@ OCPN_DBP_STC_MDA
Barometic pressure.
@ OCPN_DBP_STC_COG
Course over ground.
@ OCPN_DBP_STC_TWD
True Wind Direction (from NMEA device if available, otherwise TWA + magnetic variation)
@ OCPN_DBP_STC_TWS
True wind speed.
@ OCPN_DBP_STC_TMP
Water temperature.
@ OCPN_DBP_STC_HUM
Humidity.
@ OCPN_DBP_STC_WCC
Windlass.
@ OCPN_DBP_STC_LAT
Latitude.
Generic font dialog for OpenCPN.
#define WANTS_NMEA_EVENTS
Receive decoded NMEA events with parsed data.
PI_ColorScheme
Color schemes for different lighting conditions.
#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.
double toUsrTemp_Plugin(double cel_temp, int unit)
Converts Celsius to user's preferred temperature unit.
wxWindow * GetOCPNCanvasWindow()
Gets OpenCPN's main canvas window.
wxFont * OCPNGetFont(wxString TextElement, int default_size)
Gets a font for UI elements.
wxString getUsrDistanceUnit_Plugin(int unit)
Gets display string for user's preferred distance unit.
wxFileConfig * GetOCPNConfigObject()
Gets OpenCPN's configuration object.
wxBitmap GetBitmapFromSVGFile(wxString filename, unsigned int width, unsigned int height)
Creates bitmap from SVG file.
double toUsrDistance_Plugin(double nm_distance, int unit)
Converts nautical miles to user's preferred distance unit.
int InsertPlugInToolSVG(wxString label, wxString SVGfile, wxString SVGfileRollover, wxString SVGfileToggled, wxItemKind kind, wxString shortHelp, wxString longHelp, wxObject *clientData, int position, int tool_sel, opencpn_plugin *pplugin)
Adds a tool using SVG graphics.
wxString getUsrSpeedUnit_Plugin(int unit)
Gets display string for user's preferred speed unit.
wxString * GetpSharedDataLocation()
Gets shared application data location.
void DimeWindow(wxWindow *win)
Applies system color scheme to window.
double GetOCPNGUIToolScaleFactor_PlugIn()
Gets current global GUI scaling factor.
wxString getUsrTempUnit_Plugin(int unit)
Gets display string for user's preferred temperature unit.
wxString GetActiveStyleName()
Gets name of currently active style sheet.
bool DecodeSingleVDOMessage(const wxString &str, PlugIn_Position_Fix_Ex *pos, wxString *accumulator)
Decodes a single VDO (Own Ship AIS) message.
wxAuiManager * GetFrameAuiManager()
Gets main frame AUI manager.
double toUsrSpeed_Plugin(double kts_speed, int unit)
Converts knots to user's preferred speed unit.
std::vector< std::string > GetActivePriorityIdentifiers()
Gets list of active priority identifiers.
void SetToolbarItemState(int item, bool toggle)
Sets toolbar item toggle state.
double OCPN_GetWinDIPScaleFactor()
Gets Windows-specific DPI scaling factor.
bool AddLocaleCatalog(wxString catalog)
Adds a locale catalog for translations.
double fromUsrDistance_Plugin(double usr_distance, int unit)
Converts from user's preferred distance unit to nautical miles.
shared_ptr< ObservableListener > GetListener(NMEA2000Id id, wxEventType et, wxEvtHandler *eh)
Gets listener for NMEA 2000 messages.
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.
Dashboard compass instrument.
Identifier for NMEA 2000 message types.