31#include <wx/dcbuffer.h>
32#include <wx/listctrl.h>
57extern ColorScheme global_color_scheme;
63 SetMinSize(wxSize(400, 200));
64 Bind(wxEVT_PAINT, &TideChartPanel::OnPaint,
this);
65 Bind(wxEVT_MOTION, &TideChartPanel::OnMouseMove,
this);
66 SetBackgroundStyle(wxBG_STYLE_CUSTOM);
70 void OnPaint(wxPaintEvent &event) {
74 dc.SetBackground(wxBrush(GetBackgroundColour()));
78 wxSize panelSize = GetClientSize();
79 if (panelSize.GetWidth() <= 0 || panelSize.GetHeight() <= 0) {
85 int other_margins = 5;
86 int chart_width = panelSize.GetWidth() - left_margin - other_margins;
87 int chart_height = panelSize.GetHeight() - (2 * other_margins);
90 int bottom_text_space = 50;
91 chart_height -= bottom_text_space;
92 chart_width = wxMax(chart_width, 300);
93 chart_height = wxMax(chart_height, 150);
94 wxRect chartRect(left_margin, other_margins, chart_width, chart_height);
97 m_tcWin->PaintChart(dc, chartRect);
100 void OnMouseMove(wxMouseEvent &event) {
101 wxPoint panelPos =
event.GetPosition();
102 wxPoint mainWindowPos = panelPos + GetPosition();
103 m_tcWin->HandleChartMouseMove(mainWindowPos.x, mainWindowPos.y, panelPos);
110enum { ID_TCWIN_NX, ID_TCWIN_PR };
112enum { TIDE_PLOT, CURRENT_PLOT };
114BEGIN_EVENT_TABLE(
TCWin, wxWindow)
115EVT_PAINT(TCWin::OnPaint)
116EVT_SIZE(TCWin::OnSize)
117EVT_MOTION(TCWin::MouseEvent)
118EVT_BUTTON(wxID_OK, TCWin::OKEvent)
119EVT_BUTTON(ID_TCWIN_NX, TCWin::NXEvent)
120EVT_BUTTON(ID_TCWIN_PR, TCWin::PREvent)
121EVT_CLOSE(TCWin::OnCloseWindow)
122EVT_TIMER(TCWININF_TIMER, TCWin::OnTCWinPopupTimerEvent)
123EVT_TIMER(TCWIN_TIME_INDICATOR_TIMER, TCWin::OnTimeIndicatorTimer)
132 m_pTCRolloverWin = NULL;
134 long wstyle = wxCLIP_CHILDREN | wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER |
135 wxFRAME_FLOAT_ON_PARENT;
145 pConfig->SetPath(
"/Settings/Others");
146 pConfig->Read(
"TCWindowTimeZone", &m_tzoneDisplay, 0);
149 wxFrame::Create(parent, wxID_ANY, wxString(
""), m_position, m_tc_size,
159 if (strchr(
"Tt", pIDX->IDX_type)) {
160 m_plot_type = TIDE_PLOT;
161 SetTitle(wxString(_(
"Tide")));
164 m_plot_type = CURRENT_PLOT;
165 SetTitle(wxString(_(
"Current")));
169 GetClientSize(&sx, &sy);
177 m_graph_rect = wxRect(0, 0, 400, 200);
180 wxButton *test_button =
181 new wxButton(
this, wxID_OK, _(
"OK"), wxPoint(-1, -1), wxDefaultSize);
182 test_button->GetSize(&m_tsx, &m_tsy);
185 m_TCWinPopupTimer.SetOwner(
this, TCWININF_TIMER);
188 m_TimeIndicatorTimer.SetOwner(
this, TCWIN_TIME_INDICATOR_TIMER);
189 m_TimeIndicatorTimer.Start(60000,
false);
194 dc.GetTextExtent(
"W", NULL, &text_height);
195 m_refTextHeight = text_height;
196 m_button_height = m_tsy;
200 wxFont *dlg_font = FontMgr::Get().
GetFont(_(
"Dialog"));
201 int dlg_font_size = dlg_font->GetPointSize();
202#if defined(__WXOSX__) || defined(__WXGTK3__)
204 dlg_font_size /= GetContentScaleFactor();
208 dlg_font_size - 2, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL,
209 wxFONTWEIGHT_NORMAL, FALSE, wxString(
"Arial"));
211 dlg_font_size - 1, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL,
212 wxFONTWEIGHT_NORMAL, FALSE, wxString(
"Arial"));
214 dlg_font_size, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD,
215 FALSE, wxString(
"Arial"));
217 dlg_font_size + 1, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL,
218 wxFONTWEIGHT_BOLD, FALSE, wxString(
"Arial"));
221 pblack_1 = wxThePenList->FindOrCreatePen(
222 this->GetForegroundColour(), wxMax(1, (
int)(m_tcwin_scaler + 0.5)),
225 pblack_2 = wxThePenList->FindOrCreatePen(
226 this->GetForegroundColour(), wxMax(2, (
int)(2 * m_tcwin_scaler + 0.5)),
229 pblack_3 = wxThePenList->FindOrCreatePen(
230 wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW),
231 wxMax(1, (
int)(m_tcwin_scaler + 0.5)), wxPENSTYLE_SOLID);
234 pred_2 = wxThePenList->FindOrCreatePen(
235 wxColor(230, 54, 54), wxMax(4, (
int)(4 * m_tcwin_scaler + 0.5)),
239 pred_time = wxThePenList->FindOrCreatePen(
240 wxColour(0, 100, 255), wxMax(4, (
int)(4 * m_tcwin_scaler + 0.5)),
243 pltgray = wxTheBrushList->FindOrCreateBrush(this->GetBackgroundColour(),
246 pltgray2 = wxTheBrushList->FindOrCreateBrush(this->GetBackgroundColour(),
248 pgraph = wxThePenList->FindOrCreatePen(
249 wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT),
250 wxMax(1, (
int)(m_tcwin_scaler + 0.5)), wxPENSTYLE_SOLID);
255 InitializeStationText();
259 m_TimeIndicatorTimer.Stop();
260 pParent->Refresh(
false);
263void TCWin::CreateLayout() {
265 wxBoxSizer *mainSizer =
new wxBoxSizer(wxVERTICAL);
268 m_topPanel =
new wxPanel(
this, wxID_ANY);
269 wxBoxSizer *topSizer =
new wxBoxSizer(wxHORIZONTAL);
273 new wxTextCtrl(m_topPanel, -1,
"", wxDefaultPosition, wxDefaultSize,
274 wxTE_MULTILINE | wxTE_READONLY | wxTE_DONTWRAP);
275 m_ptextctrl->SetMinSize(wxSize(200, 120));
278 m_tList =
new wxListCtrl(m_topPanel, -1, wxDefaultPosition, wxDefaultSize,
279 wxLC_REPORT | wxLC_NO_HEADER);
280 m_tList->SetMinSize(wxSize(150, 120));
286 col0.SetAlign(wxLIST_FORMAT_LEFT);
288 m_tList->InsertColumn(0, col0);
291 topSizer->Add(m_ptextctrl, 2, wxEXPAND | wxALL,
293 topSizer->Add(m_tList, 1, wxEXPAND | wxALL, 5);
295 m_topPanel->SetSizer(topSizer);
298 m_chartPanel =
new TideChartPanel(
this);
301 m_buttonPanel =
new wxPanel(
this, wxID_ANY);
302 wxBoxSizer *buttonSizer =
new wxBoxSizer(wxHORIZONTAL);
305 PR_button =
new wxButton(m_buttonPanel, ID_TCWIN_PR, _(
"Prev"));
306 NX_button =
new wxButton(m_buttonPanel, ID_TCWIN_NX, _(
"Next"));
307 OK_button =
new wxButton(m_buttonPanel, wxID_OK, _(
"OK"));
310 wxString choiceOptions[] = {_(
"LMT@Station"), _(
"UTC")};
311 int numChoices =
sizeof(choiceOptions) /
sizeof(wxString);
312 m_choiceTimezone =
new wxChoice(m_buttonPanel, wxID_ANY, wxDefaultPosition,
313 wxDefaultSize, numChoices, choiceOptions);
314 m_choiceTimezone->SetSelection(m_tzoneDisplay);
315 m_choiceTimezone->SetToolTip(
316 _(
"Select whether tide times are shown in UTC or Local Mean Time (LMT) "
320 buttonSizer->Add(PR_button, 0, wxALL, 5);
321 buttonSizer->Add(NX_button, 0, wxALL, 5);
322 buttonSizer->AddStretchSpacer(1);
323 buttonSizer->Add(m_choiceTimezone, 0, wxALL | wxALIGN_CENTER_VERTICAL, 5);
324 buttonSizer->AddSpacer(10);
325 buttonSizer->Add(OK_button, 0, wxALL, 5);
327 m_buttonPanel->SetSizer(buttonSizer);
330 mainSizer->Add(m_topPanel, 0, wxEXPAND | wxLEFT | wxRIGHT | wxTOP,
332 mainSizer->Add(m_chartPanel, 1, wxEXPAND | wxLEFT | wxRIGHT,
334 mainSizer->Add(m_buttonPanel, 0, wxEXPAND | wxALL,
341 m_choiceTimezone->Connect(wxEVT_COMMAND_CHOICE_SELECTED,
342 wxCommandEventHandler(TCWin::TimezoneOnChoice),
346void TCWin::InitializeStationText() {
348 m_ptextctrl->Clear();
351 wxString locna, locnb;
352 if (locn.Contains(wxString(
","))) {
353 locna = locn.BeforeFirst(
',');
354 locnb = locn.AfterFirst(
',');
362 style.SetFont(*pLFont);
363 m_ptextctrl->SetDefaultStyle(style);
365 m_ptextctrl->AppendText(locna);
366 m_ptextctrl->AppendText(
"\n");
368 style.SetFont(*pSMFont);
369 m_ptextctrl->SetDefaultStyle(style);
371 if (!locnb.IsEmpty()) m_ptextctrl->AppendText(locnb);
372 m_ptextctrl->AppendText(
"\n");
379 m_ptextctrl->AppendText(_(
"Reference Station :"));
380 m_ptextctrl->AppendText(
"\n");
382 m_ptextctrl->AppendText(mref);
383 m_ptextctrl->AppendText(
"\n");
386 m_ptextctrl->AppendText(
"\n");
391 dsource.Prepend(
" ");
393 m_ptextctrl->AppendText(_(
"Data Source :"));
394 m_ptextctrl->AppendText(
"\n");
396 m_ptextctrl->AppendText(dsource);
398 m_ptextctrl->ShowPosition(0);
401void TCWin::PaintChart(wxDC &dc,
const wxRect &chartRect) {
407 wxRect originalGraphRect = m_graph_rect;
408 m_graph_rect = chartRect;
415 if (m_graph_rect.x == 0) {
416 m_graph_rect = originalGraphRect;
422 GetClientSize(&x, &y);
425 pblack_1->SetColour(this->GetForegroundColour());
426 pblack_2->SetColour(this->GetForegroundColour());
427 pltgray->SetColour(this->GetBackgroundColour());
428 pltgray2->SetColour(this->GetBackgroundColour());
430 GetGlobalColor(
"URED"));
431 pred_time->SetColour(
432 GetGlobalColor(
"UINFB"));
435 dc.SetPen(*pblack_1);
436 dc.SetBrush(*pltgray);
437 dc.DrawRectangle(m_graph_rect.x, m_graph_rect.y, m_graph_rect.width,
438 m_graph_rect.height);
443 const int hour_delta = 4;
445 const int hour_delta = 1;
452 for (i = 0; i < 25; i++) {
453 int xd = m_graph_rect.x + ((i)*m_graph_rect.width / 25);
454 if (hour_delta != 1) {
455 if (i % hour_delta == 0) {
456 dc.SetPen(*pblack_2);
457 dc.DrawLine(xd, m_graph_rect.y, xd,
458 m_graph_rect.y + m_graph_rect.height + 5);
460 int hour_show = hour_start + i;
461 if (hour_show >= 24) hour_show -= 24;
462 sprintf(sbuf,
"%02d", hour_show);
464 dc.DrawText(wxString(sbuf, wxConvUTF8),
465 xd + x_shim + (m_graph_rect.width / 25) / 2,
466 m_graph_rect.y + m_graph_rect.height + 8);
468 dc.SetPen(*pblack_1);
469 dc.DrawLine(xd, m_graph_rect.y, xd,
470 m_graph_rect.y + m_graph_rect.height + 5);
473 dc.SetPen(*pblack_1);
474 dc.DrawLine(xd, m_graph_rect.y, xd,
475 m_graph_rect.y + m_graph_rect.height + 5);
477 sst.Printf(
"%02d", i);
478 dc.DrawRotatedText(sst, xd + (m_graph_rect.width / 25) / 2,
479 m_graph_rect.y + m_graph_rect.height + 8, 270.);
484 wxDateTime system_now = wxDateTime::Now();
485 wxDateTime this_now = gTimeSource;
486 bool cur_time = !gTimeSource.IsValid();
487 if (cur_time) this_now = wxDateTime::Now();
490 time_t t_system_now = system_now.GetTicks();
491 t_system_now -= m_diff_mins * 60;
492 if (m_tzoneDisplay == 0)
493 t_system_now += m_stationOffset_mins * 60;
495 float t_system_ratio =
496 m_graph_rect.width * (t_system_now - m_t_graphday_GMT) / (25 * 3600.0f);
497 int x_system = (t_system_ratio < 0 || t_system_ratio > m_graph_rect.width)
499 : m_graph_rect.x + (int)t_system_ratio;
503 dc.DrawLine(x_system, m_graph_rect.y, x_system,
504 m_graph_rect.y + m_graph_rect.height);
509 if (gTimeSource.IsValid()) {
510 time_t t_selected_time = gTimeSource.GetTicks();
511 if (abs(t_selected_time - t_system_now) > 300) {
512 t_selected_time -= m_diff_mins * 60;
513 if (m_tzoneDisplay == 0)
514 t_selected_time += m_stationOffset_mins * 60;
516 float t_selected_time_ratio = m_graph_rect.width *
517 (t_selected_time - m_t_graphday_GMT) /
519 int x_selected_time = (t_selected_time_ratio < 0 ||
520 t_selected_time_ratio > m_graph_rect.width)
522 : m_graph_rect.x + (int)t_selected_time_ratio;
524 if (x_selected_time >= 0) {
525 dc.SetPen(*pred_time);
526 dc.DrawLine(x_selected_time, m_graph_rect.y, x_selected_time,
527 m_graph_rect.y + m_graph_rect.height);
531 dc.SetPen(*pblack_1);
539 m_tList->DeleteAllItems();
547 int tt_localtz = m_t_graphday_GMT + (m_diff_mins * 60);
549 if (m_tzoneDisplay == 0)
550 tt_localtz -= m_stationOffset_mins * 60;
553 ptcmgr->GetTideFlowSens(tt_localtz, BACKWARD_TEN_MINUTES_STEP,
556 for (i = 0; i < 26; i++) {
557 int tt = tt_localtz + (i * FORWARD_ONE_HOUR_STEP);
565 int unit_c = TCDataFactory::findunit(pmsd->unit);
567 tcv[i] = tcv[i] * TCDataFactory::known_units[unit_c].conv_factor;
573 if (tcv[i] > tcmax) tcmax = tcv[i];
574 if (tcv[i] < tcmin) tcmin = tcv[i];
576 if (TIDE_PLOT == m_plot_type) {
577 if (!((tcv[i] > val) == wt) && (i > 0)) {
580 ptcmgr->GetHightOrLowTide(tt, BACKWARD_TEN_MINUTES_STEP,
581 BACKWARD_ONE_MINUTES_STEP, tcv[i], wt,
583 if (tctime > tt_localtz) {
587 tcd.Set(tctime - (m_diff_mins * 60));
588 if (m_tzoneDisplay == 0)
589 tcd.Set(tctime + (m_stationOffset_mins - m_diff_mins) * 60);
591 s.Printf(tcd.Format(
"%H:%M "));
595 double tcvalue_converted = tcvalue;
599 int unit_c = TCDataFactory::findunit(pmsd->unit);
603 TCDataFactory::known_units[unit_c].conv_factor;
606 tcvalue_converted =
toUsrHeight(tcvalue_converted);
609 s1.Printf(
"%05.2f ", tcvalue_converted);
613 (wt) ? s.Append(_(
"HW")) : s.Append(_(
"LW"));
616 li.SetId(list_index);
617 li.SetAlign(wxLIST_FORMAT_LEFT);
620 m_tList->InsertItem(li);
627 if (CURRENT_PLOT == m_plot_type) {
630 thx.Set((time_t)tt - (m_diff_mins * 60));
631 if (m_tzoneDisplay == 0)
632 thx.Set((time_t)tt + (m_stationOffset_mins - m_diff_mins) * 60);
634 s.Printf(thx.Format(
"%H:%M "));
639 s1.Printf(
" %03.0f", dir);
643 li.SetId(list_index);
644 li.SetAlign(wxLIST_FORMAT_LEFT);
647 m_tList->InsertItem(li);
655 if (CURRENT_PLOT == m_plot_type) {
656 it = std::max(abs((
int)tcmin - 1), abs((
int)tcmax + 1));
659 m_plot_y_offset = m_graph_rect.height / 2;
663 if (tcmin < 0) ib -= 1;
666 m_plot_y_offset = (m_graph_rect.height * (it - ib)) / im;
673 dc.GetTextExtent(
"1", NULL, &height_stext);
674 float available_lines = (float)m_graph_rect.height / height_stext;
675 i_skip = (int)ceil(im / available_lines);
677 if (CURRENT_PLOT == m_plot_type && i_skip != 1) {
685 for (
auto it = m_sList.begin(); it != m_sList.end(); it++)
delete (*it);
688 for (i = 0; i < 26; i++) {
689 wxPoint *pp =
new wxPoint;
690 pp->x = m_graph_rect.x + ((i)*m_graph_rect.width / 25);
691 pp->y = m_graph_rect.y + (m_plot_y_offset) -
692 (
int)((tcv[i] - val_off) * m_graph_rect.height / im);
693 m_sList.push_back(pp);
700 dc.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
705 int yd = m_graph_rect.y + (m_plot_y_offset) -
706 ((i - val_off) * m_graph_rect.height / im);
707 if ((m_plot_y_offset + m_graph_rect.y) == yd)
708 dc.SetPen(*pblack_2);
710 dc.SetPen(*pblack_1);
712 dc.DrawLine(m_graph_rect.x, yd, m_graph_rect.x + m_graph_rect.width, yd);
713 snprintf(sbuf, 99,
"%d", i);
714 dc.DrawText(wxString(sbuf, wxConvUTF8), m_graph_rect.x - 20, yd - 5);
720 for (
auto &p : m_sList) list.Append(p);
724 dc.DrawSpline(&list);
730 if (m_tzoneDisplay == 0) {
731 int station_offset =
ptcmgr->GetStationTimeOffset(pIDX);
732 int h = station_offset / 60;
733 int m = station_offset - (h * 60);
734 if (m_graphday.IsDST()) h += 1;
735 m_stz.Printf(
"UTC %+03d:%02d", h, m);
739 double lat =
ptcmgr->GetStationLat(pIDX);
742 switch (
ptcmgr->GetStationTimeOffset(pIDX)) {
754 if (m_graphday.IsDST()) mtz[1] =
'D';
764 dc.GetTextExtent(m_stz, &w, &h);
766 dc.DrawText(m_stz, m_graph_rect.x + (m_graph_rect.width / 2) - (w / 2),
767 m_graph_rect.y + m_graph_rect.height + 35);
770 if (g_locale ==
"en_US")
771 sdate = m_graphday.Format(
"%A %b %d, %Y");
773 sdate = m_graphday.Format(
"%A %d %b %Y");
776 dc.GetTextExtent(sdate, &w, &h);
778 dc.DrawText(sdate, m_graph_rect.x + (m_graph_rect.width / 2) - (w / 2),
779 m_graph_rect.y + m_graph_rect.height + 15);
785 dc.GetTextExtent(height_unit, &w, &h);
786 dc.DrawRotatedText(height_unit, 5,
787 m_graph_rect.y + m_graph_rect.height / 2 + w / 2, 90.);
795 dc.DrawText(fdir, m_graph_rect.x + m_graph_rect.width + 4,
796 m_graph_rect.y + m_graph_rect.height * 1 / 4);
800 dc.DrawText(edir, m_graph_rect.x + m_graph_rect.width + 4,
801 m_graph_rect.y + m_graph_rect.height * 3 / 4);
805 if ((m_button_height * 15) < x && cur_time) {
807 int day = m_graphday.GetDayOfYear();
808 if (m_graphday.GetYear() == this_now.GetYear()) {
809 if (day == this_now.GetDayOfYear())
810 sday.Append(_(
"Today"));
811 else if (day == this_now.GetDayOfYear() + 1)
812 sday.Append(_(
"Tomorrow"));
814 sday.Append(m_graphday.GetWeekDayName(m_graphday.GetWeekDay()));
815 }
else if (m_graphday.GetYear() == this_now.GetYear() + 1 &&
816 day == this_now.Add(wxTimeSpan::Day()).GetDayOfYear())
817 sday.Append(_(
"Tomorrow"));
820 dc.GetTextExtent(sday, &w, &h);
822 dc.DrawText(sday, m_graph_rect.x,
823 m_graph_rect.y + m_graph_rect.height + 15);
827 double spotDim = 4 * g_Platform->GetDisplayDPmm();
828 dc.SetBrush(*wxTheBrushList->FindOrCreateBrush(GetGlobalColor(
"YELO1"),
829 wxBRUSHSTYLE_SOLID));
830 dc.SetPen(wxPen(GetGlobalColor(
"URED"),
831 wxMax(2, 0.5 * g_Platform->GetDisplayDPmm())));
832 dc.DrawRoundedRectangle(xSpot - spotDim / 2, ySpot - spotDim / 2, spotDim,
833 spotDim, spotDim / 2);
835 dc.SetBrush(*wxTheBrushList->FindOrCreateBrush(GetGlobalColor(
"UBLCK"),
836 wxBRUSHSTYLE_SOLID));
837 dc.SetPen(wxPen(GetGlobalColor(
"UBLCK"), 1));
838 double ispotDim = spotDim / 5.;
839 dc.DrawRoundedRectangle(xSpot - ispotDim / 2, ySpot - ispotDim / 2, ispotDim,
840 ispotDim, ispotDim / 2);
843 m_graph_rect = originalGraphRect;
846void TCWin::SetTimeFactors() {
848 wxDateTime this_now = gTimeSource;
849 bool cur_time = !gTimeSource.IsValid();
852 this_now = wxDateTime::Now();
854 wxDateTime this_gmt = this_now.ToGMT();
856#if wxCHECK_VERSION(2, 6, 2)
857 wxTimeSpan diff = this_now.Subtract(this_gmt);
859 wxTimeSpan diff = this_gmt.Subtract(this_now);
862 m_diff_mins = diff.GetMinutes();
867#if wxCHECK_VERSION(3, 0, 2)
868 if (m_diff_mins == 0 && this_now.IsDST()) m_diff_mins += 60;
871 int station_offset =
ptcmgr->GetStationTimeOffset(pIDX);
873 m_stationOffset_mins = station_offset;
874 if (this_now.IsDST()) {
875 m_stationOffset_mins += 60;
881#if wxCHECK_VERSION(3, 0, 2)
888 m_graphday = this_gmt;
890 int day_gmt = this_gmt.GetDayOfYear();
892 time_t ttNow = this_now.GetTicks();
893 time_t tt_at_station =
894 ttNow - (m_diff_mins * 60) + (m_stationOffset_mins * 60);
895 wxDateTime atStation(tt_at_station);
896 int day_at_station = atStation.GetDayOfYear();
898 if (day_gmt > day_at_station) {
899 wxTimeSpan dt(24, 0, 0, 0);
900 m_graphday.Subtract(dt);
901 }
else if (day_gmt < day_at_station) {
902 wxTimeSpan dt(24, 0, 0, 0);
906 wxDateTime graphday_00 = m_graphday;
907 graphday_00.ResetTime();
908 time_t t_graphday_00 = graphday_00.GetTicks();
914 m_t_graphday_GMT = t_graphday_00;
919void TCWin::TimezoneOnChoice(wxCommandEvent &event) {
920 m_tzoneDisplay = m_choiceTimezone->GetSelection();
926void TCWin::RecalculateSize() {
927 wxSize parent_size(2000, 2000);
928 if (pParent) parent_size = pParent->GetClientSize();
930 int unscaledheight = 600;
931 int unscaledwidth = 650;
937 g_tcwin_scale = wxMax(g_tcwin_scale, 10);
938 m_tcwin_scaler = g_Platform->GetDisplayDPmm() * 0.254 * g_tcwin_scale / 100.0;
940 m_tc_size.x = (int)(unscaledwidth * m_tcwin_scaler + 0.5);
941 m_tc_size.y = (int)(unscaledheight * m_tcwin_scaler + 0.5);
943 m_tc_size.x = wxMin(m_tc_size.x, parent_size.x);
944 m_tc_size.y = wxMin(m_tc_size.y, parent_size.y);
951 if ((m_x + 8 + m_tc_size.x) > parent_size.x) xc = xc - m_tc_size.x - 16;
952 if ((m_y + m_tc_size.y) > parent_size.y) yc = yc - m_tc_size.y;
958 if (pParent) pParent->ClientToScreen(&xc, &yc);
959 m_position = wxPoint(xc, yc);
967void TCWin::OKEvent(wxCommandEvent &event) {
971 if (pParent && pParent->pCwin ==
this) {
972 pParent->pCwin = NULL;
977 delete m_pTCRolloverWin;
978 m_pTCRolloverWin = NULL;
983 pParent->Refresh(
false);
988 pConfig->SetPath(
"/Settings/Others");
989 pConfig->Write(
"TCWindowTimeZone", m_tzoneDisplay);
995void TCWin::OnCloseWindow(wxCloseEvent &event) {
999 if (pParent && pParent->pCwin ==
this) {
1000 pParent->pCwin = NULL;
1005 delete m_pTCRolloverWin;
1006 m_pTCRolloverWin = NULL;
1012 pConfig->SetPath(
"/Settings/Others");
1013 pConfig->Write(
"TCWindowTimeZone", m_tzoneDisplay);
1019void TCWin::NXEvent(wxCommandEvent &event) {
1020 wxTimeSpan dt(24, 0, 0, 0);
1022 wxDateTime dm = m_graphday;
1024 wxDateTime graphday_00 = dm.ResetTime();
1025 time_t t_graphday_00 = graphday_00.GetTicks();
1027 if (!graphday_00.IsDST() && m_graphday.IsDST()) t_graphday_00 -= 3600;
1028 if (graphday_00.IsDST() && !m_graphday.IsDST()) t_graphday_00 += 3600;
1030 m_t_graphday_GMT = t_graphday_00;
1036void TCWin::PREvent(wxCommandEvent &event) {
1037 wxTimeSpan dt(-24, 0, 0, 0);
1039 wxDateTime dm = m_graphday;
1041 wxDateTime graphday_00 = dm.ResetTime();
1042 time_t t_graphday_00 = graphday_00.GetTicks();
1044 if (!graphday_00.IsDST() && m_graphday.IsDST()) t_graphday_00 -= 3600;
1045 if (graphday_00.IsDST() && !m_graphday.IsDST()) t_graphday_00 += 3600;
1047 m_t_graphday_GMT = t_graphday_00;
1053void TCWin::RePosition() {
1060 pParent->ClientToScreen(&r.x, &r.y);
1064void TCWin::OnPaint(wxPaintEvent &event) {
1076 dc.SetBrush(wxBrush(GetBackgroundColour()));
1077 dc.SetPen(wxPen(GetBackgroundColour()));
1078 wxSize size = GetClientSize();
1079 dc.DrawRectangle(0, 0, size.GetWidth(), size.GetHeight());
1085void TCWin::OnSize(wxSizeEvent &event) {
1086 if (!m_created)
return;
1093 m_chartPanel->Refresh();
1103void TCWin::MouseEvent(wxMouseEvent &event) {
1106 event.GetPosition(&curs_x, &curs_y);
1108 if (!m_TCWinPopupTimer.IsRunning())
1109 m_TCWinPopupTimer.Start(20, wxTIMER_ONE_SHOT);
1112void TCWin::HandleChartMouseMove(
int mainWindowX,
int mainWindowY,
1113 const wxPoint &chartPanelPos) {
1116 curs_x = mainWindowX;
1117 curs_y = mainWindowY;
1122 wxSize panelSize = m_chartPanel->GetClientSize();
1123 int left_margin = 50;
1124 int other_margins = 5;
1125 int chart_width = panelSize.GetWidth() - left_margin - other_margins;
1126 int chart_height = panelSize.GetHeight() - (2 * other_margins);
1127 int bottom_text_space = 50;
1128 chart_height -= bottom_text_space;
1129 chart_width = wxMax(chart_width, 300);
1130 chart_height = wxMax(chart_height, 150);
1133 wxPoint chartPanelPos = m_chartPanel->GetPosition();
1135 wxRect(chartPanelPos.x + left_margin, chartPanelPos.y + other_margins,
1136 chart_width, chart_height);
1139 if (!m_TCWinPopupTimer.IsRunning())
1140 m_TCWinPopupTimer.Start(20, wxTIMER_ONE_SHOT);
1143void TCWin::OnTCWinPopupTimerEvent(wxTimerEvent &event) {
1147 GetClientSize(&x, &y);
1148 wxRegion cursorarea(m_graph_rect);
1149 if (cursorarea.Contains(curs_x, curs_y)) {
1150 ShowRollover =
true;
1151 SetCursor(*pParent->pCursorCross);
1152 if (NULL == m_pTCRolloverWin) {
1153 m_pTCRolloverWin =
new RolloverWin(
this, -1,
false);
1157 m_pTCRolloverWin->SetMousePropogation(1);
1158 m_pTCRolloverWin->Hide();
1166 (float)(curs_x - m_graph_rect.x) / (float)m_graph_rect.width;
1167 t = relativeX * 25.0f;
1170 t = wxMax(0.0f, wxMin(25.0f, t));
1172 int tt = m_t_graphday_GMT + (int)(t * 3600);
1177 p.Printf(thd.Format(
"%Hh %Mmn"));
1182 int tt_localtz = m_t_graphday_GMT + (m_diff_mins * 60);
1184 int ttv = tt_localtz + (int)(t * 3600);
1185 if (m_tzoneDisplay == 0) {
1186 ttv -= m_stationOffset_mins * 60;
1195 double t_converted = (t < 0 && CURRENT_PLOT == m_plot_type) ? -t : t;
1199 int unit_c = TCDataFactory::findunit(pmsd->unit);
1202 t_converted * TCDataFactory::known_units[unit_c].conv_factor;
1208 s.Printf(
"%3.2f ", t_converted);
1215 if (CURRENT_PLOT == m_plot_type) {
1216 s.Printf(
"%3.0f%c", d, 0x00B0);
1223 win_size.Set(x * 90 / 100, y * 80 / 100);
1225 m_pTCRolloverWin->SetString(p);
1226 m_pTCRolloverWin->SetBestPosition(curs_x, curs_y, 1, 1, TC_ROLLOVER,
1228 m_pTCRolloverWin->SetBitmap(TC_ROLLOVER);
1229 m_pTCRolloverWin->Refresh();
1230 m_pTCRolloverWin->Show();
1238 for (
int i = 0; i < 26; i++) {
1239 float ppx = m_graph_rect.x + ((i)*m_graph_rect.width / 25.f);
1246 if (m_sList.size() > 0 && idx > 0 && idx < (int)m_sList.size()) {
1248 auto it_a = m_sList.begin();
1249 std::advance(it_a, idx - 1);
1250 auto it_b = m_sList.begin();
1251 std::advance(it_b, idx);
1256 float pct = (curs_x - a->x) / (
float)((b->x - a->x));
1257 float dy = pct * (b->y - a->y);
1264 ySpot = m_graph_rect.y + m_graph_rect.height / 2;
1270 SetCursor(*pParent->pCursorArrow);
1271 ShowRollover =
false;
1274 if (m_pTCRolloverWin && m_pTCRolloverWin->IsShown() && !ShowRollover) {
1275 m_pTCRolloverWin->Hide();
1279void TCWin::OnTimeIndicatorTimer(wxTimerEvent &event) {
Generic Chart canvas base.
ChartCanvas - Main chart display and interaction component.
bool GetCanvasPointPix(double rlat, double rlon, wxPoint *r)
Convert latitude/longitude to canvas pixel coordinates (physical pixels) rounded to nearest integer.
wxFont * FindOrCreateFont(int point_size, wxFontFamily family, wxFontStyle style, wxFontWeight weight, bool underline=false, const wxString &facename=wxEmptyString, wxFontEncoding encoding=wxFONTENCODING_DEFAULT)
Creates or finds a matching font in the font cache.
wxFont * GetFont(const wxString &TextElement, int requested_font_size=0)
Get a font object for a UI element.
Represents an index entry for tidal and current data.
char IDX_type
Entry type identifier "TCtcIUu".
char IDX_reference_name[MAXNAMELEN]
Name of the reference station.
int IDX_flood_dir
Flood current direction (in degrees)
char IDX_station_name[MAXNAMELEN]
Name of the tidal or current station.
char source_ident[MAXNAMELEN]
Identifier of the source (typically file name)
int IDX_ebb_dir
Ebb current direction (in degrees)
double IDX_lat
Latitude of the station (in degrees, +North)
double IDX_lon
Longitude of the station (in degrees, +East)
Station_Data * pref_sta_data
Pointer to the reference station data.
int IDX_rec_num
Record number for multiple entries with same name.
Global variables stored in configuration file.
Extern C linked utilities.
wxFont * GetOCPNScaledFont(wxString item, int default_size)
Retrieves a font from FontMgr, optionally scaled for physical readability.
General purpose GUI support.
Miscellaneous globals primarely used by gui layer, not persisted in configuration file.
wxString getUsrHeightUnit(int unit)
Get the abbreviation for the preferred height unit.
double toUsrHeight(double m_height, int unit)
Convert height from meters to preferred height units.
Tide and current data container.
Tide and currents window.
TCMgr * ptcmgr
Global instance.
Tide and Current Manager @TODO Add original author copyright.
Timer identification constants.