OpenCPN Partial API docs
Loading...
Searching...
No Matches
grib_pi.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * Copyright (C) 2010 by David S. Register *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
18 ***************************************************************************/
23#include "wx/wxprec.h"
24
25#ifndef WX_PRECOMP
26#include "wx/wx.h"
27
28#include "pi_gl.h"
29
30#ifdef ocpnUSE_GL
31#include <wx/glcanvas.h>
32#endif
33#endif // precompiled headers
34
35#include <wx/fileconf.h>
36#include <wx/stdpaths.h>
37
38#include "grib_pi.h"
39
40#ifdef __WXQT__
41#include "qdebug.h"
42#endif
43
44double g_ContentScaleFactor;
45
46// the class factories, used to create and destroy instances of the PlugIn
47
48extern "C" DECL_EXP opencpn_plugin *create_pi(void *ppimgr) {
49 return new grib_pi(ppimgr);
50}
51
52extern "C" DECL_EXP void destroy_pi(opencpn_plugin *p) { delete p; }
53
54extern int m_DialogStyle;
55
56grib_pi *g_pi;
57bool g_bpause;
58
59//---------------------------------------------------------------------------------------------------------
60//
61// Grib PlugIn Implementation
62//
63//---------------------------------------------------------------------------------------------------------
64
65#include "icons.h"
66
67//---------------------------------------------------------------------------------------------------------
68//
69// PlugIn initialization and de-init
70//
71//---------------------------------------------------------------------------------------------------------
72
73grib_pi::grib_pi(void *ppimgr) : opencpn_plugin_116(ppimgr) {
74 // Create the PlugIn icons
75 initialize_images();
76
77 wxString shareLocn = *GetpSharedDataLocation() + _T("plugins") +
78 wxFileName::GetPathSeparator() + _T("grib_pi") +
79 wxFileName::GetPathSeparator() + _T("data") +
80 wxFileName::GetPathSeparator();
81 wxImage panelIcon(shareLocn + _T("grib_panel_icon.png"));
82 if (panelIcon.IsOk())
83 m_panelBitmap = wxBitmap(panelIcon);
84 else
85 wxLogMessage(_T(" GRIB panel icon NOT loaded"));
86
87 m_pLastTimelineSet = nullptr;
88 m_bShowGrib = false;
89 m_GUIScaleFactor = -1.;
90 g_pi = this;
91}
92
93grib_pi::~grib_pi(void) {
94 delete _img_grib_pi;
95 delete _img_grib;
96 delete m_pLastTimelineSet;
97}
98
99int grib_pi::Init(void) {
100 AddLocaleCatalog(_T("opencpn-grib_pi"));
101
102 // Set some default private member parameters
103 m_CtrlBarxy = wxPoint(0, 0);
104 m_CursorDataxy = wxPoint(0, 0);
105
106 m_pGribCtrlBar = nullptr;
107 m_pGRIBOverlayFactory = nullptr;
108
109 ::wxDisplaySize(&m_display_width, &m_display_height);
110
111 m_DialogStyleChanged = false;
112
113 // Get a pointer to the opencpn configuration object
114 m_pconfig = GetOCPNConfigObject();
115
116 // And load the configuration items
117 LoadConfig();
118
119 // Get a pointer to the opencpn display canvas, to use as a parent for the
120 // GRIB dialog
121 m_parent_window = GetOCPNCanvasWindow();
122
123 g_ContentScaleFactor = m_parent_window->GetContentScaleFactor();
124
125 // int m_height = GetChartbarHeight();
126 // This PlugIn needs a CtrlBar icon, so request its insertion if enabled
127 // locally
128 wxString shareLocn = *GetpSharedDataLocation() + _T("plugins") +
129 wxFileName::GetPathSeparator() + _T("grib_pi") +
130 wxFileName::GetPathSeparator() + _T("data") +
131 wxFileName::GetPathSeparator();
132 // Initialize catalog file
133 wxString local_grib_catalog = "sources.json";
134 wxString data_path = *GetpPrivateApplicationDataLocation() +
135 wxFileName::GetPathSeparator() + "grib_pi";
136 if (!wxDirExists(data_path)) {
137 wxMkdir(data_path);
138 }
139 m_local_sources_catalog =
140 data_path + wxFileName::GetPathSeparator() + local_grib_catalog;
141 if (!wxFileExists(m_local_sources_catalog)) {
142 wxCopyFile(shareLocn + local_grib_catalog, m_local_sources_catalog);
143 }
144 if (m_bGRIBShowIcon) {
145 wxString normalIcon = shareLocn + _T("grib.svg");
146 wxString toggledIcon = shareLocn + _T("grib_toggled.svg");
147 wxString rolloverIcon = shareLocn + _T("grib_rollover.svg");
148
149 // For journeyman styles, we prefer the built-in raster icons which match
150 // the rest of the toolbar.
151 if (GetActiveStyleName().Lower() != _T("traditional")) {
152 normalIcon = _T("");
153 toggledIcon = _T("");
154 rolloverIcon = _T("");
155 }
156
157 wxLogMessage(normalIcon);
158 m_leftclick_tool_id = InsertPlugInToolSVG(
159 _T(""), normalIcon, rolloverIcon, toggledIcon, wxITEM_CHECK, _("Grib"),
160 _T(""), nullptr, GRIB_TOOL_POSITION, 0, this);
161 }
162
163 if (!QualifyCtrlBarPosition(m_CtrlBarxy, m_CtrlBar_Sizexy)) {
164 m_CtrlBarxy = wxPoint(20, 60); // reset to the default position
165 m_CursorDataxy = wxPoint(20, 170);
166 }
167
168 return (WANTS_OVERLAY_CALLBACK | WANTS_OPENGL_OVERLAY_CALLBACK |
172}
173
174bool grib_pi::DeInit(void) {
175 if (m_pGribCtrlBar) {
176 m_pGribCtrlBar->Close();
177 delete m_pGribCtrlBar;
178 m_pGribCtrlBar = nullptr;
179 }
180
181 delete m_pGRIBOverlayFactory;
182 m_pGRIBOverlayFactory = nullptr;
183
184 return true;
185}
186
187int grib_pi::GetAPIVersionMajor() { return MY_API_VERSION_MAJOR; }
188
189int grib_pi::GetAPIVersionMinor() { return MY_API_VERSION_MINOR; }
190
191int grib_pi::GetPlugInVersionMajor() { return PLUGIN_VERSION_MAJOR; }
192
193int grib_pi::GetPlugInVersionMinor() { return PLUGIN_VERSION_MINOR; }
194
195wxBitmap *grib_pi::GetPlugInBitmap() { return &m_panelBitmap; }
196
197wxString grib_pi::GetCommonName() { return _T("GRIB"); }
198
199wxString grib_pi::GetShortDescription() { return _("GRIB PlugIn for OpenCPN"); }
200
201wxString grib_pi::GetLongDescription() {
202 return _(
203 "GRIB PlugIn for OpenCPN\n\
204Provides basic GRIB file overlay capabilities for several GRIB file types\n\
205and a request function to get GRIB files by eMail.\n\n\
206Supported GRIB data include:\n\
207- wind direction and speed (at 10 m)\n\
208- wind gust\n\
209- surface pressure\n\
210- rainfall\n\
211- cloud cover\n\
212- significant wave height and direction\n\
213- air surface temperature (at 2 m)\n\
214- sea surface temperature\n\
215- surface current direction and speed\n\
216- Convective Available Potential Energy (CAPE)\n\
217- wind, altitude, temperature and relative humidity at 300, 500, 700, 850 hPa.");
218}
219
220void grib_pi::SetDefaults(void) {}
221
222int grib_pi::GetToolBarToolCount(void) { return 1; }
223
224bool grib_pi::MouseEventHook(wxMouseEvent &event) {
225 if ((m_pGribCtrlBar && m_pGribCtrlBar->pReq_Dialog))
226 return m_pGribCtrlBar->pReq_Dialog->MouseEventHook(event);
227 return false;
228}
229
230void grib_pi::ShowPreferencesDialog(wxWindow *parent) {
232
233 DimeWindow(Pref); // aplly global colours scheme
234 SetDialogFont(Pref); // Apply global font
235
236 Pref->m_cbUseHiDef->SetValue(m_bGRIBUseHiDef);
237 Pref->m_cbUseGradualColors->SetValue(m_bGRIBUseGradualColors);
238 Pref->m_cbDrawBarbedArrowHead->SetValue(m_bDrawBarbedArrowHead);
239 Pref->m_cZoomToCenterAtInit->SetValue(m_bZoomToCenterAtInit);
240 Pref->m_cbCopyFirstCumulativeRecord->SetValue(m_bCopyFirstCumRec);
241 Pref->m_cbCopyMissingWaveRecord->SetValue(m_bCopyMissWaveRec);
242 Pref->m_rbTimeFormat->SetSelection(m_bTimeZone);
243 Pref->m_rbLoadOptions->SetSelection(m_bLoadLastOpenFile);
244 Pref->m_rbStartOptions->SetSelection(m_bStartOptions);
245
246 wxFileConfig *pConf = GetOCPNConfigObject();
247 if (pConf) {
248 wxString l_grib_dir;
249 pConf->SetPath(_T ( "/Directories" ));
250 pConf->Read(_T ( "GRIBDirectory" ), &l_grib_dir);
251 Pref->m_grib_dir_sel = l_grib_dir;
252 }
253
254#ifdef __WXMSW__
255 int val = (m_GribIconsScaleFactor * 10.) - 10;
256 Pref->m_sIconSizeFactor->SetValue(val);
257#endif
258
259#ifdef __OCPN__ANDROID__
260 if (m_parent_window) {
261 int xmax = m_parent_window->GetSize().GetWidth();
262 int ymax = m_parent_window->GetParent()
263 ->GetSize()
264 .GetHeight(); // This would be the Options dialog itself
265 Pref->SetSize(xmax, ymax);
266 Pref->Layout();
267 Pref->Move(0, 0);
268 }
269 Pref->Show();
270#else
271 // Constrain size on small displays
272
273 int display_width, display_height;
274 wxDisplaySize(&display_width, &display_height);
275 int char_width = GetOCPNCanvasWindow()->GetCharWidth();
276 int char_height = GetOCPNCanvasWindow()->GetCharHeight();
277 if (display_height < 600) {
278 wxSize canvas_size = GetOCPNCanvasWindow()->GetSize();
279 Pref->SetMaxSize(GetOCPNCanvasWindow()->GetSize());
280 Pref->SetSize(wxSize(60 * char_width, canvas_size.x * 8 / 10));
281 Pref->CentreOnScreen();
282 } else {
283 Pref->SetMaxSize(GetOCPNCanvasWindow()->GetSize());
284 Pref->SetSize(wxSize(60 * char_width, 32 * char_height));
285 }
286
287 Pref->ShowModal();
288#endif
289}
290
291void grib_pi::UpdatePrefs(GribPreferencesDialog *Pref) {
292 m_bGRIBUseHiDef = Pref->m_cbUseHiDef->GetValue();
293 m_bGRIBUseGradualColors = Pref->m_cbUseGradualColors->GetValue();
294 m_bLoadLastOpenFile = Pref->m_rbLoadOptions->GetSelection();
295 m_bDrawBarbedArrowHead = Pref->m_cbDrawBarbedArrowHead->GetValue();
296 m_bZoomToCenterAtInit = Pref->m_cZoomToCenterAtInit->GetValue();
297#ifdef __WXMSW__
298 double val = Pref->m_sIconSizeFactor->GetValue();
299 m_GribIconsScaleFactor = 1. + (val / 10);
300#endif
301
302 if (m_pGRIBOverlayFactory)
303 m_pGRIBOverlayFactory->SetSettings(m_bGRIBUseHiDef, m_bGRIBUseGradualColors,
304 m_bDrawBarbedArrowHead);
305
306 int updatelevel = 0;
307
308 if (m_bStartOptions != Pref->m_rbStartOptions->GetSelection()) {
309 m_bStartOptions = Pref->m_rbStartOptions->GetSelection();
310 updatelevel = 1;
311 }
312
313 if (m_bTimeZone != Pref->m_rbTimeFormat->GetSelection()) {
314 m_bTimeZone = Pref->m_rbTimeFormat->GetSelection();
315 if (m_pGRIBOverlayFactory) m_pGRIBOverlayFactory->SetTimeZone(m_bTimeZone);
316 updatelevel = 2;
317 }
318
319 bool copyrec = Pref->m_cbCopyFirstCumulativeRecord->GetValue();
320 bool copywave = Pref->m_cbCopyMissingWaveRecord->GetValue();
321 if (m_bCopyFirstCumRec != copyrec || m_bCopyMissWaveRec != copywave) {
322 m_bCopyFirstCumRec = copyrec;
323 m_bCopyMissWaveRec = copywave;
324 updatelevel = 3;
325 }
326
327 if (m_pGribCtrlBar) {
328 switch (updatelevel) {
329 case 0:
330 break;
331 case 3:
332 // rebuild current activefile with new parameters and rebuil data list
333 // with current index
334 m_pGribCtrlBar->CreateActiveFileFromNames(
335 m_pGribCtrlBar->m_bGRIBActiveFile->GetFileNames());
336 m_pGribCtrlBar->PopulateComboDataList();
337 m_pGribCtrlBar->TimelineChanged();
338 break;
339 case 2:
340 // only rebuild data list with current index and new timezone
341 m_pGribCtrlBar->PopulateComboDataList();
342 m_pGribCtrlBar->TimelineChanged();
343 break;
344 case 1:
345 // only re-compute the best forecast
346 m_pGribCtrlBar->ComputeBestForecastForNow();
347 break;
348 }
349 if (Pref->m_grib_dir_sel.Length()) {
350 m_pGribCtrlBar->m_grib_dir = Pref->m_grib_dir_sel;
351 m_pGribCtrlBar->m_file_names.Clear();
352 }
353 }
354
355 if (Pref->m_grib_dir_sel.Length()) {
356 wxFileConfig *pConf = GetOCPNConfigObject();
357 if (pConf) {
358 pConf->SetPath(_T ( "/Directories" ));
359 pConf->Write(_T ( "GRIBDirectory" ), Pref->m_grib_dir_sel);
360 pConf->DeleteGroup(_T ( "/Settings/GRIB/FileNames" ));
361 pConf->Flush();
362 }
363 }
364 SaveConfig();
365}
366
367bool grib_pi::QualifyCtrlBarPosition(
368 wxPoint position,
369 wxSize size) { // Make sure drag bar (title bar) or grabber always screen
370 bool b_reset_pos = false;
371#ifdef __WXMSW__
372 // Support MultiMonitor setups which an allow negative window positions.
373 // If the requested window does not intersect any installed monitor,
374 // then default to simple primary monitor positioning.
375 RECT frame_title_rect;
376 frame_title_rect.left = position.x;
377 frame_title_rect.top = position.y;
378 frame_title_rect.right = position.x + size.x;
379 frame_title_rect.bottom = m_DialogStyle == ATTACHED_HAS_CAPTION
380 ? position.y + 30
381 : position.y + size.y;
382
383 if (nullptr == MonitorFromRect(&frame_title_rect, MONITOR_DEFAULTTONULL))
384 b_reset_pos = true;
385#else
386 wxRect window_title_rect; // conservative estimate
387 window_title_rect.x = position.x;
388 window_title_rect.y = position.y;
389 window_title_rect.width = size.x;
390 window_title_rect.height =
391 m_DialogStyle == ATTACHED_HAS_CAPTION ? 30 : size.y;
392
393 wxRect ClientRect = wxGetClientDisplayRect();
394 if (!ClientRect.Intersects(window_title_rect)) b_reset_pos = true;
395
396#endif
397 return !b_reset_pos;
398}
399
400void grib_pi::MoveDialog(wxDialog *dialog, wxPoint position) {
401 // Use the application frame to bound the control bar position.
402 wxApp *app = wxTheApp;
403
404 wxWindow *frame =
405 app->GetTopWindow(); // or GetOCPNCanvasWindow()->GetParent();
406 if (!frame) return;
407
408 wxPoint p = frame->ScreenToClient(position);
409 // Check and ensure there is always a "grabb" zone always visible wathever the
410 // dialoue size is.
411 if (p.x + dialog->GetSize().GetX() > frame->GetClientSize().GetX())
412 p.x = frame->GetClientSize().GetX() - dialog->GetSize().GetX();
413 if (p.y + dialog->GetSize().GetY() > frame->GetClientSize().GetY())
414 p.y = frame->GetClientSize().GetY() - dialog->GetSize().GetY();
415
416#ifdef __WXGTK__
417 dialog->Move(0, 0);
418#endif
419 dialog->Move(frame->ClientToScreen(p));
420}
421
422void grib_pi::OnToolbarToolCallback(int id) {
423 // if( !::wxIsBusy() ) ::wxBeginBusyCursor();
424
425 bool starting = false;
426
427 double scale_factor =
428 GetOCPNGUIToolScaleFactor_PlugIn() * OCPN_GetWinDIPScaleFactor();
429#ifdef __WXMSW__
430 scale_factor *= m_GribIconsScaleFactor;
431#endif
432 if (scale_factor != m_GUIScaleFactor) starting = true;
433
434 if (!m_pGribCtrlBar) {
435 starting = true;
436 long style = m_DialogStyle == ATTACHED_HAS_CAPTION
437 ? wxCAPTION | wxCLOSE_BOX | wxSYSTEM_MENU
438 : wxBORDER_NONE | wxSYSTEM_MENU;
439#ifdef __WXOSX__
440 style |= wxSTAY_ON_TOP;
441#endif
442 m_pGribCtrlBar =
443 new GRIBUICtrlBar(m_parent_window, wxID_ANY, wxEmptyString,
444 wxDefaultPosition, wxDefaultSize, style, this);
445 m_pGribCtrlBar->SetScaledBitmap(scale_factor);
446
447 wxMenu *dummy = new wxMenu(_T("Plugin"));
448 wxMenuItem *table =
449 new wxMenuItem(dummy, wxID_ANY, wxString(_("Weather table")),
450 wxEmptyString, wxITEM_NORMAL);
451 /* Menu font do not work properly for MSW (wxWidgets 3.2.1)
452 #ifdef __WXMSW__
453 wxFont *qFont = OCPNGetFont(_("Menu"), 0);
454 table->SetFont(*qFont);
455 #endif
456 */
457 m_MenuItem = AddCanvasContextMenuItem(table, this);
458 SetCanvasContextMenuItemViz(m_MenuItem, false);
459
460 // Create the drawing factory
461 m_pGRIBOverlayFactory = new GRIBOverlayFactory(*m_pGribCtrlBar);
462 m_pGRIBOverlayFactory->SetMessageFont();
463 m_pGRIBOverlayFactory->SetTimeZone(m_bTimeZone);
464 m_pGRIBOverlayFactory->SetParentSize(m_display_width, m_display_height);
465 m_pGRIBOverlayFactory->SetSettings(m_bGRIBUseHiDef, m_bGRIBUseGradualColors,
466 m_bDrawBarbedArrowHead);
467
468 m_pGribCtrlBar->OpenFile(m_bLoadLastOpenFile == 0);
469 }
470
471 // Toggle GRIB overlay display
472 m_bShowGrib = !m_bShowGrib;
473
474 // Toggle dialog?
475 if (m_bShowGrib) {
476 // A new file could have been added since grib plugin opened
477 if (!starting && m_bLoadLastOpenFile == 0) {
478 m_pGribCtrlBar->OpenFile(true);
479 starting = true;
480 }
481 // the dialog font could have been changed since grib plugin opened
482 if (m_pGribCtrlBar->GetFont() != *OCPNGetFont(_("Dialog"), 0))
483 starting = true;
484 if (starting) {
485 m_pGRIBOverlayFactory->SetMessageFont();
486 SetDialogFont(m_pGribCtrlBar);
487 m_GUIScaleFactor = scale_factor;
488 m_pGribCtrlBar->SetScaledBitmap(m_GUIScaleFactor);
489 m_pGribCtrlBar->SetDialogsStyleSizePosition(true);
490 m_pGribCtrlBar->Refresh();
491 } else {
492 MoveDialog(m_pGribCtrlBar, GetCtrlBarXY());
493 if (m_DialogStyle >> 1 == SEPARATED) {
494 MoveDialog(m_pGribCtrlBar->GetCDataDialog(), GetCursorDataXY());
495 m_pGribCtrlBar->GetCDataDialog()->Show(m_pGribCtrlBar->m_CDataIsShown);
496 }
497#ifdef __OCPN__ANDROID__
498 m_pGribCtrlBar->SetDialogsStyleSizePosition(true);
499 m_pGribCtrlBar->Refresh();
500#endif
501 }
502 m_pGribCtrlBar->Show();
503 if (m_pGribCtrlBar->m_bGRIBActiveFile) {
504 if (m_pGribCtrlBar->m_bGRIBActiveFile->IsOK()) {
505 ArrayOfGribRecordSets *rsa =
506 m_pGribCtrlBar->m_bGRIBActiveFile->GetRecordSetArrayPtr();
507 if (rsa->GetCount() > 1) {
508 SetCanvasContextMenuItemViz(m_MenuItem, true);
509 }
510 if (rsa->GetCount() >= 1) { // XXX Should be only on Show
511 SendTimelineMessage(m_pGribCtrlBar->TimelineTime());
512 }
513 }
514 }
515 // Toggle is handled by the CtrlBar but we must keep plugin manager b_toggle
516 // updated to actual status to ensure correct status upon CtrlBar rebuild
517 SetToolbarItemState(m_leftclick_tool_id, m_bShowGrib);
518
519 // Do an automatic "zoom-to-center" on the overlay canvas if set in
520 // Preferences
521 if (m_pGribCtrlBar && m_bZoomToCenterAtInit) {
522 m_pGribCtrlBar->DoZoomToCenter();
523 }
524
525 RequestRefresh(m_parent_window); // refresh main window
526 } else
527 m_pGribCtrlBar->Close();
528}
529
530void grib_pi::OnGribCtrlBarClose() {
531 m_bShowGrib = false;
532 SetToolbarItemState(m_leftclick_tool_id, m_bShowGrib);
533
534 m_pGribCtrlBar->Hide();
535
536 SaveConfig();
537
538 SetCanvasContextMenuItemViz(m_MenuItem, false);
539
540 RequestRefresh(m_parent_window); // refresh main window
541
542 if (::wxIsBusy()) ::wxEndBusyCursor();
543
544#ifdef __OCPN__ANDROID__
545 m_DialogStyleChanged = true; // Force a delete of the control bar dialog
546#endif
547
548 if (m_DialogStyleChanged) {
549 m_pGribCtrlBar->Destroy();
550 m_pGribCtrlBar = nullptr;
551 m_DialogStyleChanged = false;
552 }
553}
554
555bool grib_pi::RenderOverlay(wxDC &dc, PlugIn_ViewPort *vp) { return false; }
556
557bool grib_pi::DoRenderOverlay(wxDC &dc, PlugIn_ViewPort *vp, int canvasIndex) {
558 if (!m_pGribCtrlBar || !m_pGribCtrlBar->IsShown() || !m_pGRIBOverlayFactory)
559 return false;
560
561 m_pGRIBOverlayFactory->RenderGribOverlay(dc, vp);
562
563 if (GetCanvasByIndex(canvasIndex) == GetCanvasUnderMouse()) {
564 m_pGribCtrlBar->SetViewPort(vp);
565 if (m_pGribCtrlBar->pReq_Dialog)
566 m_pGribCtrlBar->pReq_Dialog->RenderZoneOverlay(dc);
567 }
568 if (::wxIsBusy()) ::wxEndBusyCursor();
569 return true;
570}
571
572bool grib_pi::RenderGLOverlay(wxGLContext *pcontext, PlugIn_ViewPort *vp) {
573 return false;
574}
575
576bool grib_pi::DoRenderGLOverlay(wxGLContext *pcontext, PlugIn_ViewPort *vp,
577 int canvasIndex) {
578 if (!m_pGribCtrlBar || !m_pGribCtrlBar->IsShown() || !m_pGRIBOverlayFactory)
579 return false;
580
581 m_pGRIBOverlayFactory->RenderGLGribOverlay(pcontext, vp);
582
583 if (GetCanvasByIndex(canvasIndex) == GetCanvasUnderMouse()) {
584 m_pGribCtrlBar->SetViewPort(vp);
585 if (m_pGribCtrlBar->pReq_Dialog)
586 m_pGribCtrlBar->pReq_Dialog->RenderGlZoneOverlay();
587 }
588
589 if (::wxIsBusy()) ::wxEndBusyCursor();
590
591#ifdef __OCPN__ANDROID__
592 m_pGribCtrlBar->Raise(); // Control bar should always be visible
593#endif
594
595 return true;
596}
597
598bool grib_pi::RenderGLOverlayMultiCanvas(wxGLContext *pcontext,
599 PlugIn_ViewPort *vp, int canvasIndex) {
600 return DoRenderGLOverlay(pcontext, vp, canvasIndex);
601}
602
603bool grib_pi::RenderOverlayMultiCanvas(wxDC &dc, PlugIn_ViewPort *vp,
604 int canvasIndex) {
605 return DoRenderOverlay(dc, vp, canvasIndex);
606}
607
608void grib_pi::SetCursorLatLon(double lat, double lon) {
609 if (m_pGribCtrlBar && m_pGribCtrlBar->IsShown())
610 m_pGribCtrlBar->SetCursorLatLon(lat, lon);
611}
612
613void grib_pi::OnContextMenuItemCallback(int id) {
614 if (!m_pGribCtrlBar->m_bGRIBActiveFile) return;
615 m_pGribCtrlBar->ContextMenuItemCallback(id);
616}
617
618void grib_pi::SetDialogFont(wxWindow *dialog, wxFont *font) {
619 dialog->SetFont(*font);
620 wxWindowList list = dialog->GetChildren();
621 wxWindowListNode *node = list.GetFirst();
622 for (size_t i = 0; i < list.GetCount(); i++) {
623 wxWindow *win = node->GetData();
624 win->SetFont(*font);
625 node = node->GetNext();
626 }
627 dialog->Fit();
628 dialog->Refresh();
629}
630
631void grib_pi::SetPluginMessage(wxString &message_id, wxString &message_body) {
632 if (message_id == _T("GRIB_VALUES_REQUEST")) {
633 if (!m_pGribCtrlBar) OnToolbarToolCallback(0);
634
635 // lat, lon, time, what
636 wxJSONReader r;
637 wxJSONValue v;
638 r.Parse(message_body, &v);
639 if (!v.HasMember(_T("Day"))) {
640 // bogus or loading grib
641 SendPluginMessage(wxString(_T("GRIB_VALUES")), _T(""));
642 return;
643 }
644 wxDateTime time(v[_T("Day")].AsInt(),
645 (wxDateTime::Month)v[_T("Month")].AsInt(),
646 v[_T("Year")].AsInt(), v[_T("Hour")].AsInt(),
647 v[_T("Minute")].AsInt(), v[_T("Second")].AsInt());
648 double lat = v[_T("lat")].AsDouble();
649 double lon = v[_T("lon")].AsDouble();
650
651 if (m_pGribCtrlBar) {
652 if (v.HasMember(_T("WIND SPEED"))) {
653 double vkn, ang;
654 if (m_pGribCtrlBar->getTimeInterpolatedValues(
655 vkn, ang, Idx_WIND_VX, Idx_WIND_VY, lon, lat, time) &&
656 vkn != GRIB_NOTDEF) {
657 v[_T("Type")] = wxT("Reply");
658 v[_T("WIND SPEED")] = vkn;
659 v[_T("WIND DIR")] = ang;
660 } else {
661 v.Remove(_T("WIND SPEED"));
662 v.Remove(_T("WIND DIR"));
663 }
664 }
665 if (v.HasMember(_T("CURRENT SPEED"))) {
666 double vkn, ang;
667 if (m_pGribCtrlBar->getTimeInterpolatedValues(
668 vkn, ang, Idx_SEACURRENT_VX, Idx_SEACURRENT_VY, lon, lat,
669 time) &&
670 vkn != GRIB_NOTDEF) {
671 v[_T("Type")] = wxT("Reply");
672 v[_T("CURRENT SPEED")] = vkn;
673 v[_T("CURRENT DIR")] = ang;
674 } else {
675 v.Remove(_T("CURRENT SPEED"));
676 v.Remove(_T("CURRENT DIR"));
677 }
678 }
679 if (v.HasMember(_T("GUST"))) {
680 double vkn = m_pGribCtrlBar->getTimeInterpolatedValue(Idx_WIND_GUST,
681 lon, lat, time);
682 if (vkn != GRIB_NOTDEF) {
683 v[_T("Type")] = wxT("Reply");
684 v[_T("GUST")] = vkn;
685 } else
686 v.Remove(_T("GUST"));
687 }
688 if (v.HasMember(_T("SWELL"))) {
689 double vkn = m_pGribCtrlBar->getTimeInterpolatedValue(Idx_HTSIGW, lon,
690 lat, time);
691 if (vkn != GRIB_NOTDEF) {
692 v[_T("Type")] = wxT("Reply");
693 v[_T("SWELL")] = vkn;
694 } else
695 v.Remove(_T("SWELL"));
696 }
697
698 wxJSONWriter w;
699 wxString out;
700 w.Write(v, out);
701 SendPluginMessage(wxString(_T("GRIB_VALUES")), out);
702 }
703 } else if (message_id == _T("GRIB_VERSION_REQUEST")) {
704 wxJSONValue v;
705 v[_T("GribVersionMinor")] = GetAPIVersionMinor();
706 v[_T("GribVersionMajor")] = GetAPIVersionMajor();
707
708 wxJSONWriter w;
709 wxString out;
710 w.Write(v, out);
711 SendPluginMessage(wxString(_T("GRIB_VERSION")), out);
712 } else if (message_id == _T("GRIB_TIMELINE_REQUEST")) {
713 // local time
714 SendTimelineMessage(m_pGribCtrlBar ? m_pGribCtrlBar->TimelineTime()
715 : wxDateTime::Now());
716 } else if (message_id == _T("GRIB_TIMELINE_RECORD_REQUEST")) {
717 wxJSONReader r;
718 wxJSONValue v;
719 r.Parse(message_body, &v);
720 wxDateTime time(v[_T("Day")].AsInt(),
721 (wxDateTime::Month)v[_T("Month")].AsInt(),
722 v[_T("Year")].AsInt(), v[_T("Hour")].AsInt(),
723 v[_T("Minute")].AsInt(), v[_T("Second")].AsInt());
724
725 if (!m_pGribCtrlBar) OnToolbarToolCallback(0);
726
728 m_pGribCtrlBar ? m_pGribCtrlBar->GetTimeLineRecordSet(time) : nullptr;
729
730 char ptr[64];
731 snprintf(ptr, sizeof ptr, "%p", set);
732
733 v[_T("GribVersionMajor")] = PLUGIN_VERSION_MAJOR;
734 v[_T("GribVersionMinor")] = PLUGIN_VERSION_MINOR;
735 v[_T("TimelineSetPtr")] = wxString::From8BitData(ptr);
736
737 wxJSONWriter w;
738 wxString out;
739 w.Write(v, out);
740 SendPluginMessage(wxString(_T("GRIB_TIMELINE_RECORD")), out);
741 delete m_pLastTimelineSet;
742 m_pLastTimelineSet = set;
743 }
744
745 else if (message_id == _T("GRIB_APPLY_JSON_CONFIG")) {
746 wxLogMessage(_T("Got GRIB_APPLY_JSON_CONFIG"));
747
748 if (m_pGribCtrlBar) {
749 m_pGribCtrlBar->OpenFileFromJSON(message_body);
750
751 m_pGribCtrlBar->m_OverlaySettings.JSONToSettings(message_body);
752 m_pGribCtrlBar->m_OverlaySettings.Write();
753 m_pGribCtrlBar->SetDialogsStyleSizePosition(true);
754 }
755 }
756}
757
758bool grib_pi::LoadConfig(void) {
759 wxFileConfig *pConf = (wxFileConfig *)m_pconfig;
760
761 if (!pConf) return false;
762
763 pConf->SetPath(_T( "/PlugIns/GRIB" ));
764 pConf->Read(_T( "LoadLastOpenFile" ), &m_bLoadLastOpenFile, 0);
765 pConf->Read(_T("OpenFileOption" ), &m_bStartOptions, 1);
766 pConf->Read(_T( "GRIBUseHiDef" ), &m_bGRIBUseHiDef, 0);
767 pConf->Read(_T( "GRIBUseGradualColors" ), &m_bGRIBUseGradualColors, 0);
768 pConf->Read(_T( "DrawBarbedArrowHead" ), &m_bDrawBarbedArrowHead, 1);
769 pConf->Read(_T( "ZoomToCenterAtInit"), &m_bZoomToCenterAtInit, 1);
770 pConf->Read(_T( "ShowGRIBIcon" ), &m_bGRIBShowIcon, 1);
771 pConf->Read(_T( "GRIBTimeZone" ), &m_bTimeZone, 1);
772 pConf->Read(_T( "CopyFirstCumulativeRecord" ), &m_bCopyFirstCumRec, 1);
773 pConf->Read(_T( "CopyMissingWaveRecord" ), &m_bCopyMissWaveRec, 1);
774#ifdef __WXMSW__
775 pConf->Read(_T("GribIconsScaleFactor"), &m_GribIconsScaleFactor, 1);
776#endif
777
778 m_CtrlBar_Sizexy.x = pConf->Read(_T ( "GRIBCtrlBarSizeX" ), 1400L);
779 m_CtrlBar_Sizexy.y = pConf->Read(_T ( "GRIBCtrlBarSizeY" ), 800L);
780 m_CtrlBarxy.x = pConf->Read(_T ( "GRIBCtrlBarPosX" ), 20L);
781 m_CtrlBarxy.y = pConf->Read(_T ( "GRIBCtrlBarPosY" ), 60L);
782 m_CursorDataxy.x = pConf->Read(_T ( "GRIBCursorDataPosX" ), 20L);
783 m_CursorDataxy.y = pConf->Read(_T ( "GRIBCursorDataPosY" ), 170L);
784
785 pConf->Read(_T ( "GribCursorDataDisplayStyle" ), &m_DialogStyle, 0);
786 if (m_DialogStyle > 3)
787 m_DialogStyle = 0; // ensure validity of the .conf value
788
789 return true;
790}
791
792bool grib_pi::SaveConfig(void) {
793 wxFileConfig *pConf = (wxFileConfig *)m_pconfig;
794
795 if (!pConf) return false;
796
797 pConf->SetPath(_T( "/PlugIns/GRIB" ));
798
799 pConf->Write(_T ( "LoadLastOpenFile" ), m_bLoadLastOpenFile);
800 pConf->Write(_T ( "OpenFileOption" ), m_bStartOptions);
801 pConf->Write(_T ( "ShowGRIBIcon" ), m_bGRIBShowIcon);
802 pConf->Write(_T ( "GRIBUseHiDef" ), m_bGRIBUseHiDef);
803 pConf->Write(_T ( "GRIBUseGradualColors" ), m_bGRIBUseGradualColors);
804 pConf->Write(_T ( "GRIBTimeZone" ), m_bTimeZone);
805 pConf->Write(_T ( "CopyFirstCumulativeRecord" ), m_bCopyFirstCumRec);
806 pConf->Write(_T ( "CopyMissingWaveRecord" ), m_bCopyMissWaveRec);
807 pConf->Write(_T ( "DrawBarbedArrowHead" ), m_bDrawBarbedArrowHead);
808 pConf->Write(_T ( "ZoomToCenterAtInit"), m_bZoomToCenterAtInit);
809#ifdef __WXMSW__
810 pConf->Write(_T("GribIconsScaleFactor"), m_GribIconsScaleFactor);
811#endif
812
813 pConf->Write(_T ( "GRIBCtrlBarSizeX" ), m_CtrlBar_Sizexy.x);
814 pConf->Write(_T ( "GRIBCtrlBarSizeY" ), m_CtrlBar_Sizexy.y);
815 pConf->Write(_T ( "GRIBCtrlBarPosX" ), m_CtrlBarxy.x);
816 pConf->Write(_T ( "GRIBCtrlBarPosY" ), m_CtrlBarxy.y);
817 pConf->Write(_T ( "GRIBCursorDataPosX" ), m_CursorDataxy.x);
818 pConf->Write(_T ( "GRIBCursorDataPosY" ), m_CursorDataxy.y);
819
820 return true;
821}
822
823void grib_pi::SetColorScheme(PI_ColorScheme cs) {
824 DimeWindow(m_pGribCtrlBar);
825 if (m_pGribCtrlBar) {
826 if (m_pGRIBOverlayFactory) m_pGRIBOverlayFactory->ClearCachedLabel();
827 if (m_pGribCtrlBar->pReq_Dialog) m_pGribCtrlBar->pReq_Dialog->Refresh();
828 m_pGribCtrlBar->Refresh();
829 // m_pGribDialog->SetDataBackGroundColor();
830 }
831}
832
833void grib_pi::SendTimelineMessage(wxDateTime time) {
834 if (!m_pGribCtrlBar) return;
835
836 wxJSONValue v;
837 if (time.IsValid()) {
838 v[_T("Day")] = time.GetDay();
839 v[_T("Month")] = time.GetMonth();
840 v[_T("Year")] = time.GetYear();
841 v[_T("Hour")] = time.GetHour();
842 v[_T("Minute")] = time.GetMinute();
843 v[_T("Second")] = time.GetSecond();
844 } else {
845 v[_T("Day")] = -1;
846 v[_T("Month")] = -1;
847 v[_T("Year")] = -1;
848 v[_T("Hour")] = -1;
849 v[_T("Minute")] = -1;
850 v[_T("Second")] = -1;
851 }
852 wxJSONWriter w;
853 wxString out;
854 w.Write(v, out);
855 SendPluginMessage(wxString(_T("GRIB_TIMELINE")), out);
856}
857
858void grib_pi::SetPositionFixEx(PlugIn_Position_Fix_Ex &pfix) {
859 m_boat_cog = pfix.Cog;
860 m_boat_sog = pfix.Sog;
861 m_boat_lat = pfix.Lat;
862 m_boat_lon = pfix.Lon;
863 if (pfix.FixTime != 0) {
864 m_boat_time = pfix.FixTime;
865 } else {
866 m_boat_time = wxDateTime::Now().GetTicks();
867 }
868}
869
870//----------------------------------------------------------------------------------------------------------
871// Prefrence dialog Implementation
872//----------------------------------------------------------------------------------------------------------
873void GribPreferencesDialog::OnStartOptionChange(wxCommandEvent &event) {
874 if (m_rbStartOptions->GetSelection() == 2) {
875 OCPNMessageBox_PlugIn(
876 this,
877 _("You have chosen to authorize interpolation.\nDon't forget that data "
878 "displayed at current time will not be real but Recomputed\nThis can "
879 "decrease accuracy!"),
880 _("Warning!"));
881 }
882}
883
884void GribPreferencesDialog::OnOKClick(wxCommandEvent &event) {
885 if (g_pi) g_pi->UpdatePrefs(this);
886 Close();
887}
@ Idx_WIND_GUST
Wind gust speed at surface.
@ Idx_WIND_VX
Surface wind velocity X component.
@ Idx_HTSIGW
Significant wave height.
@ Idx_SEACURRENT_VY
Sea current velocity Y component.
@ Idx_WIND_VY
Surface wind velocity Y component.
@ Idx_SEACURRENT_VX
Sea current velocity X component.
ArrayOfGribRecordSets * GetRecordSetArrayPtr(void)
Gets pointer to array of record sets organized by timestamp.
wxArrayString & GetFileNames(void)
Gets the list of source filenames being used.
bool IsOK(void)
Checks if file loading and parsing was successful.
Factory class for creating and managing GRIB data visualizations.
GribOverlaySettings m_OverlaySettings
Settings that control how GRIB data is displayed and overlaid.
wxString m_grib_dir
Directory containing GRIB files.
GRIBFile * m_bGRIBActiveFile
Currently active GRIB file being displayed.
wxArrayString m_file_names
List of GRIB filenames being displayed.
GribTimelineRecordSet * GetTimeLineRecordSet(wxDateTime time)
Retrieves or creates a temporally interpolated GRIB record set for a specific timestamp.
A specialized GribRecordSet that represents temporally interpolated weather data with isobar renderin...
wxBitmap * GetPlugInBitmap()
FIXME static wxBitmap* LoadSVG(const wxString filename, unsigned int width, ...
Definition grib_pi.cpp:195
The JSON parser.
Definition jsonreader.h:50
int Parse(const wxString &doc, wxJSONValue *val)
Parse the JSON document.
The JSON value class implementation.
Definition jsonval.h:84
bool Remove(int index)
Remove the item at the specified index or key.
Definition jsonval.cpp:1551
bool HasMember(unsigned index) const
Return TRUE if the object contains an element at the specified index.
Definition jsonval.cpp:1298
double AsDouble() const
Return the stored value as a double.
Definition jsonval.cpp:827
The JSON document writer.
Definition jsonwriter.h:50
void Write(const wxJSONValue &value, wxString &str)
Write the JSONvalue object to a JSON text.
GRIB Weather Data Plugin for OpenCPN.
#define WANTS_NMEA_EVENTS
Receive decoded NMEA events with parsed data.
#define WANTS_ONPAINT_VIEWPORT
Receive callbacks during chart viewport painting.
#define WANTS_MOUSE_EVENTS
Receive mouse events (clicks, movement, etc).
#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.
Definition ocpn_plugin.h:90
#define WANTS_TOOLBAR_CALLBACK
Receive notification when user left-clicks plugin's toolbar buttons.
#define WANTS_OVERLAY_CALLBACK
Receive callbacks to render custom overlay graphics on the chart.
Definition ocpn_plugin.h:86
wxFont * OCPNGetFont(wxString TextElement, int default_size)
Gets a font for UI elements.
OpenGL Platform Abstraction Layer.