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
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
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_rbLoadOptions->SetSelection(m_bLoadLastOpenFile);
243 Pref->m_rbStartOptions->SetSelection(m_bStartOptions);
244
245 wxFileConfig *pConf = GetOCPNConfigObject();
246 if (pConf) {
247 wxString l_grib_dir;
248 pConf->SetPath(_T ( "/Directories" ));
249 pConf->Read(_T ( "GRIBDirectory" ), &l_grib_dir);
250 Pref->m_grib_dir_sel = l_grib_dir;
251 }
252
253#ifdef __WXMSW__
254 int val = (m_GribIconsScaleFactor * 10.) - 10;
255 Pref->m_sIconSizeFactor->SetValue(val);
256#endif
257
258#ifdef __OCPN__ANDROID__
259 if (m_parent_window) {
260 int xmax = m_parent_window->GetSize().GetWidth();
261 int ymax = m_parent_window->GetParent()
262 ->GetSize()
263 .GetHeight(); // This would be the Options dialog itself
264 Pref->SetSize(xmax, ymax);
265 Pref->Layout();
266 Pref->Move(0, 0);
267 }
268 Pref->Show();
269#else
270 // Constrain size on small displays
271
272 int display_width, display_height;
273 wxDisplaySize(&display_width, &display_height);
274 int char_width = GetOCPNCanvasWindow()->GetCharWidth();
275 int char_height = GetOCPNCanvasWindow()->GetCharHeight();
276 if (display_height < 600) {
277 wxSize canvas_size = GetOCPNCanvasWindow()->GetSize();
278 Pref->SetMaxSize(GetOCPNCanvasWindow()->GetSize());
279 Pref->SetSize(wxSize(60 * char_width, canvas_size.x * 8 / 10));
280 Pref->CentreOnScreen();
281 } else {
282 Pref->SetMaxSize(GetOCPNCanvasWindow()->GetSize());
283 Pref->SetSize(wxSize(60 * char_width, 32 * char_height));
284 }
285
286 Pref->ShowModal();
287#endif
288}
289
290void grib_pi::UpdatePrefs(GribPreferencesDialog *Pref) {
291 m_bGRIBUseHiDef = Pref->m_cbUseHiDef->GetValue();
292 m_bGRIBUseGradualColors = Pref->m_cbUseGradualColors->GetValue();
293 m_bLoadLastOpenFile = Pref->m_rbLoadOptions->GetSelection();
294 m_bDrawBarbedArrowHead = Pref->m_cbDrawBarbedArrowHead->GetValue();
295 m_bZoomToCenterAtInit = Pref->m_cZoomToCenterAtInit->GetValue();
296#ifdef __WXMSW__
297 double val = Pref->m_sIconSizeFactor->GetValue();
298 m_GribIconsScaleFactor = 1. + (val / 10);
299#endif
300
301 if (m_pGRIBOverlayFactory)
302 m_pGRIBOverlayFactory->SetSettings(m_bGRIBUseHiDef, m_bGRIBUseGradualColors,
303 m_bDrawBarbedArrowHead);
304
305 int updatelevel = 0;
306
307 if (m_bStartOptions != Pref->m_rbStartOptions->GetSelection()) {
308 m_bStartOptions = Pref->m_rbStartOptions->GetSelection();
309 updatelevel = 1;
310 }
311
312 bool copyrec = Pref->m_cbCopyFirstCumulativeRecord->GetValue();
313 bool copywave = Pref->m_cbCopyMissingWaveRecord->GetValue();
314 if (m_bCopyFirstCumRec != copyrec || m_bCopyMissWaveRec != copywave) {
315 m_bCopyFirstCumRec = copyrec;
316 m_bCopyMissWaveRec = copywave;
317 updatelevel = 3;
318 }
319
320 if (m_pGribCtrlBar) {
321 switch (updatelevel) {
322 case 0:
323 break;
324 case 3:
325 // rebuild current activefile with new parameters and rebuil data list
326 // with current index
327 m_pGribCtrlBar->CreateActiveFileFromNames(
328 m_pGribCtrlBar->m_bGRIBActiveFile->GetFileNames());
329 m_pGribCtrlBar->PopulateComboDataList();
330 m_pGribCtrlBar->TimelineChanged();
331 break;
332 case 2:
333 // only rebuild data list with current index and new timezone
334 // This no longer applicable because the timezone is set in the
335 // OpenCPN core global settings (Options -> Display -> General)
336 m_pGribCtrlBar->PopulateComboDataList();
337 m_pGribCtrlBar->TimelineChanged();
338 break;
339 case 1:
340 // only re-compute the best forecast
341 m_pGribCtrlBar->ComputeBestForecastForNow();
342 break;
343 }
344 if (Pref->m_grib_dir_sel.Length()) {
345 m_pGribCtrlBar->m_grib_dir = Pref->m_grib_dir_sel;
346 m_pGribCtrlBar->m_file_names.Clear();
347 }
348 }
349
350 if (Pref->m_grib_dir_sel.Length()) {
351 wxFileConfig *pConf = GetOCPNConfigObject();
352 if (pConf) {
353 pConf->SetPath(_T ( "/Directories" ));
354 pConf->Write(_T ( "GRIBDirectory" ), Pref->m_grib_dir_sel);
355 pConf->DeleteGroup(_T ( "/Settings/GRIB/FileNames" ));
356 pConf->Flush();
357 }
358 }
359 SaveConfig();
360}
361
362bool grib_pi::QualifyCtrlBarPosition(
363 wxPoint position,
364 wxSize size) { // Make sure drag bar (title bar) or grabber always screen
365 bool b_reset_pos = false;
366#ifdef __WXMSW__
367 // Support MultiMonitor setups which an allow negative window positions.
368 // If the requested window does not intersect any installed monitor,
369 // then default to simple primary monitor positioning.
370 RECT frame_title_rect;
371 frame_title_rect.left = position.x;
372 frame_title_rect.top = position.y;
373 frame_title_rect.right = position.x + size.x;
374 frame_title_rect.bottom = m_DialogStyle == ATTACHED_HAS_CAPTION
375 ? position.y + 30
376 : position.y + size.y;
377
378 if (nullptr == MonitorFromRect(&frame_title_rect, MONITOR_DEFAULTTONULL))
379 b_reset_pos = true;
380#else
381 wxRect window_title_rect; // conservative estimate
382 window_title_rect.x = position.x;
383 window_title_rect.y = position.y;
384 window_title_rect.width = size.x;
385 window_title_rect.height =
386 m_DialogStyle == ATTACHED_HAS_CAPTION ? 30 : size.y;
387
388 wxRect ClientRect = wxGetClientDisplayRect();
389 if (!ClientRect.Intersects(window_title_rect)) b_reset_pos = true;
390
391#endif
392 return !b_reset_pos;
393}
394
395void grib_pi::MoveDialog(wxDialog *dialog, wxPoint position) {
396 // Use the application frame to bound the control bar position.
397 wxApp *app = wxTheApp;
398
399 wxWindow *frame =
400 app->GetTopWindow(); // or GetOCPNCanvasWindow()->GetParent();
401 if (!frame) return;
402
403 wxPoint p = frame->ScreenToClient(position);
404 // Check and ensure there is always a "grabb" zone always visible wathever the
405 // dialoue size is.
406 if (p.x + dialog->GetSize().GetX() > frame->GetClientSize().GetX())
407 p.x = frame->GetClientSize().GetX() - dialog->GetSize().GetX();
408 if (p.y + dialog->GetSize().GetY() > frame->GetClientSize().GetY())
409 p.y = frame->GetClientSize().GetY() - dialog->GetSize().GetY();
410
411#ifdef __WXGTK__
412 dialog->Move(0, 0);
413#endif
414 dialog->Move(frame->ClientToScreen(p));
415}
416
418 // if( !::wxIsBusy() ) ::wxBeginBusyCursor();
419
420 bool starting = false;
421
422 double scale_factor =
424#ifdef __WXMSW__
425 scale_factor *= m_GribIconsScaleFactor;
426#endif
427 if (scale_factor != m_GUIScaleFactor) starting = true;
428
429 if (!m_pGribCtrlBar) {
430 starting = true;
431 long style = m_DialogStyle == ATTACHED_HAS_CAPTION
432 ? wxCAPTION | wxCLOSE_BOX | wxSYSTEM_MENU
433 : wxBORDER_NONE | wxSYSTEM_MENU;
434#ifdef __WXOSX__
435 style |= wxSTAY_ON_TOP;
436#endif
437 m_pGribCtrlBar = new GRIBUICtrlBar(m_parent_window, wxID_ANY, wxEmptyString,
438 wxDefaultPosition, wxDefaultSize, style,
439 this, scale_factor);
440 m_pGribCtrlBar->SetScaledBitmap(scale_factor);
441
442 wxMenu *dummy = new wxMenu(_T("Plugin"));
443 wxMenuItem *table =
444 new wxMenuItem(dummy, wxID_ANY, wxString(_("Weather table")),
445 wxEmptyString, wxITEM_NORMAL);
446 /* Menu font do not work properly for MSW (wxWidgets 3.2.1)
447 #ifdef __WXMSW__
448 wxFont *qFont = OCPNGetFont(_("Menu"));
449 table->SetFont(*qFont);
450 #endif
451 */
452 m_MenuItem = AddCanvasContextMenuItem(table, this);
453 SetCanvasContextMenuItemViz(m_MenuItem, false);
454
455 // Create the drawing factory
456 m_pGRIBOverlayFactory = new GRIBOverlayFactory(*m_pGribCtrlBar);
457 m_pGRIBOverlayFactory->SetMessageFont();
458 m_pGRIBOverlayFactory->SetParentSize(m_display_width, m_display_height);
459 m_pGRIBOverlayFactory->SetSettings(m_bGRIBUseHiDef, m_bGRIBUseGradualColors,
460 m_bDrawBarbedArrowHead);
461
462 m_pGribCtrlBar->OpenFile(m_bLoadLastOpenFile == 0);
463 }
464
465 // Toggle GRIB overlay display
466 m_bShowGrib = !m_bShowGrib;
467
468 // Toggle dialog?
469 if (m_bShowGrib) {
470 // A new file could have been added since grib plugin opened
471 if (!starting && m_bLoadLastOpenFile == 0) {
472 m_pGribCtrlBar->OpenFile(true);
473 starting = true;
474 }
475 // the dialog font could have been changed since grib plugin opened
476 if (m_pGribCtrlBar->GetFont() != *OCPNGetFont(_("Dialog"))) starting = true;
477 if (starting) {
478 m_pGRIBOverlayFactory->SetMessageFont();
479 SetDialogFont(m_pGribCtrlBar);
480 m_GUIScaleFactor = scale_factor;
481 m_pGribCtrlBar->SetScaledBitmap(m_GUIScaleFactor);
482 m_pGribCtrlBar->SetDialogsStyleSizePosition(true);
483 m_pGribCtrlBar->Refresh();
484 } else {
485 MoveDialog(m_pGribCtrlBar, GetCtrlBarXY());
486 if (m_DialogStyle >> 1 == SEPARATED) {
487 MoveDialog(m_pGribCtrlBar->GetCDataDialog(), GetCursorDataXY());
488 m_pGribCtrlBar->GetCDataDialog()->Show(m_pGribCtrlBar->m_CDataIsShown);
489 }
490#ifdef __OCPN__ANDROID__
491 m_pGribCtrlBar->SetDialogsStyleSizePosition(true);
492 m_pGribCtrlBar->Refresh();
493#endif
494 }
495 m_pGribCtrlBar->Show();
496 if (m_pGribCtrlBar->m_bGRIBActiveFile) {
497 if (m_pGribCtrlBar->m_bGRIBActiveFile->IsOK()) {
498 ArrayOfGribRecordSets *rsa =
499 m_pGribCtrlBar->m_bGRIBActiveFile->GetRecordSetArrayPtr();
500 if (rsa->GetCount() > 1) {
501 SetCanvasContextMenuItemViz(m_MenuItem, true);
502 }
503 if (rsa->GetCount() >= 1) { // XXX Should be only on Show
504 SendTimelineMessage(m_pGribCtrlBar->TimelineTime());
505 }
506 }
507 }
508 // Toggle is handled by the CtrlBar but we must keep plugin manager b_toggle
509 // updated to actual status to ensure correct status upon CtrlBar rebuild
510 SetToolbarItemState(m_leftclick_tool_id, m_bShowGrib);
511
512 // Do an automatic "zoom-to-center" on the overlay canvas if set in
513 // Preferences
514 if (m_pGribCtrlBar && m_bZoomToCenterAtInit) {
515 m_pGribCtrlBar->DoZoomToCenter();
516 }
517
518 RequestRefresh(m_parent_window); // refresh main window
519 } else
520 m_pGribCtrlBar->Close();
521}
522
523void grib_pi::OnGribCtrlBarClose() {
524 m_bShowGrib = false;
525 SetToolbarItemState(m_leftclick_tool_id, m_bShowGrib);
526
527 m_pGribCtrlBar->Hide();
528
529 SaveConfig();
530
531 SetCanvasContextMenuItemViz(m_MenuItem, false);
532
533 RequestRefresh(m_parent_window); // refresh main window
534
535 if (::wxIsBusy()) ::wxEndBusyCursor();
536
537#ifdef __OCPN__ANDROID__
538 m_DialogStyleChanged = true; // Force a delete of the control bar dialog
539#endif
540
541 if (m_DialogStyleChanged) {
542 m_pGribCtrlBar->Destroy();
543 m_pGribCtrlBar = nullptr;
544 m_DialogStyleChanged = false;
545 }
546}
547
548bool grib_pi::RenderOverlay(wxDC &dc, PlugIn_ViewPort *vp) { return false; }
549
550bool grib_pi::DoRenderOverlay(wxDC &dc, PlugIn_ViewPort *vp, int canvasIndex) {
551 if (!m_pGribCtrlBar || !m_pGribCtrlBar->IsShown() || !m_pGRIBOverlayFactory)
552 return false;
553
554 m_pGRIBOverlayFactory->RenderGribOverlay(dc, vp);
555 if (PluginGetFocusCanvas() == GetCanvasByIndex(canvasIndex)) {
556 m_pGribCtrlBar->SetViewPortWithFocus(vp);
557 }
558
559 if (GetCanvasByIndex(canvasIndex) == GetCanvasUnderMouse()) {
560 m_pGribCtrlBar->SetViewPortUnderMouse(vp);
561 if (m_pGribCtrlBar->pReq_Dialog &&
563 m_pGribCtrlBar->pReq_Dialog->GetBoundingBoxCanvasIndex()) {
564 m_pGribCtrlBar->pReq_Dialog->RenderZoneOverlay(dc);
565 }
566 }
567 if (::wxIsBusy()) ::wxEndBusyCursor();
568 return true;
569}
570
571bool grib_pi::RenderGLOverlay(wxGLContext *pcontext, PlugIn_ViewPort *vp) {
572 return false;
573}
574
575bool grib_pi::DoRenderGLOverlay(wxGLContext *pcontext, PlugIn_ViewPort *vp,
576 int canvasIndex) {
577 if (!m_pGribCtrlBar || !m_pGribCtrlBar->IsShown() || !m_pGRIBOverlayFactory)
578 return false;
579
580 m_pGRIBOverlayFactory->RenderGLGribOverlay(pcontext, vp);
581 if (PluginGetFocusCanvas() == GetCanvasByIndex(canvasIndex)) {
582 m_pGribCtrlBar->SetViewPortWithFocus(vp);
583 }
584
585 if (GetCanvasByIndex(canvasIndex) == GetCanvasUnderMouse()) {
586 m_pGribCtrlBar->SetViewPortUnderMouse(vp);
587 if (m_pGribCtrlBar->pReq_Dialog &&
589 m_pGribCtrlBar->pReq_Dialog->GetBoundingBoxCanvasIndex()) {
590 m_pGribCtrlBar->pReq_Dialog->RenderGlZoneOverlay();
591 }
592 }
593
594 if (::wxIsBusy()) ::wxEndBusyCursor();
595
596#ifdef __OCPN__ANDROID__
597 m_pGribCtrlBar->Raise(); // Control bar should always be visible
598#endif
599
600 return true;
601}
602
603bool grib_pi::RenderGLOverlayMultiCanvas(wxGLContext *pcontext,
604 PlugIn_ViewPort *vp, int canvasIndex) {
605 return DoRenderGLOverlay(pcontext, vp, canvasIndex);
606}
607
609 int canvasIndex) {
610 return DoRenderOverlay(dc, vp, canvasIndex);
611}
612
613void grib_pi::SetCursorLatLon(double lat, double lon) {
614 if (m_pGribCtrlBar && m_pGribCtrlBar->IsShown())
615 m_pGribCtrlBar->SetCursorLatLon(lat, lon);
616}
617
619 if (!m_pGribCtrlBar->m_bGRIBActiveFile) return;
620 m_pGribCtrlBar->ContextMenuItemCallback(id);
621}
622
623void grib_pi::SetDialogFont(wxWindow *dialog, wxFont *font) {
624 dialog->SetFont(*font);
625 wxWindowList list = dialog->GetChildren();
626 wxWindowListNode *node = list.GetFirst();
627 for (size_t i = 0; i < list.GetCount(); i++) {
628 wxWindow *win = node->GetData();
629 win->SetFont(*font);
630 node = node->GetNext();
631 }
632 dialog->Fit();
633 dialog->Refresh();
634}
635
636void grib_pi::SetPluginMessage(wxString &message_id, wxString &message_body) {
637 if (message_id == _T("GRIB_VALUES_REQUEST")) {
638 if (!m_pGribCtrlBar) OnToolbarToolCallback(0);
639
640 // lat, lon, time, what
641 wxJSONReader r;
642 wxJSONValue v;
643 r.Parse(message_body, &v);
644 if (!v.HasMember(_T("Day"))) {
645 // bogus or loading grib
646 SendPluginMessage(wxString(_T("GRIB_VALUES")), _T(""));
647 return;
648 }
649 wxDateTime time(v[_T("Day")].AsInt(),
650 (wxDateTime::Month)v[_T("Month")].AsInt(),
651 v[_T("Year")].AsInt(), v[_T("Hour")].AsInt(),
652 v[_T("Minute")].AsInt(), v[_T("Second")].AsInt());
653 double lat = v[_T("lat")].AsDouble();
654 double lon = v[_T("lon")].AsDouble();
655
656 if (m_pGribCtrlBar) {
657 if (v.HasMember(_T("WIND SPEED"))) {
658 double vkn, ang;
659 if (m_pGribCtrlBar->getTimeInterpolatedValues(
660 vkn, ang, Idx_WIND_VX, Idx_WIND_VY, lon, lat, time) &&
661 vkn != GRIB_NOTDEF) {
662 v[_T("Type")] = wxT("Reply");
663 v[_T("WIND SPEED")] = vkn;
664 v[_T("WIND DIR")] = ang;
665 } else {
666 v.Remove(_T("WIND SPEED"));
667 v.Remove(_T("WIND DIR"));
668 }
669 }
670 if (v.HasMember(_T("CURRENT SPEED"))) {
671 double vkn, ang;
672 if (m_pGribCtrlBar->getTimeInterpolatedValues(
673 vkn, ang, Idx_SEACURRENT_VX, Idx_SEACURRENT_VY, lon, lat,
674 time) &&
675 vkn != GRIB_NOTDEF) {
676 v[_T("Type")] = wxT("Reply");
677 v[_T("CURRENT SPEED")] = vkn;
678 v[_T("CURRENT DIR")] = ang;
679 } else {
680 v.Remove(_T("CURRENT SPEED"));
681 v.Remove(_T("CURRENT DIR"));
682 }
683 }
684 if (v.HasMember(_T("GUST"))) {
685 double vkn = m_pGribCtrlBar->getTimeInterpolatedValue(Idx_WIND_GUST,
686 lon, lat, time);
687 if (vkn != GRIB_NOTDEF) {
688 v[_T("Type")] = wxT("Reply");
689 v[_T("GUST")] = vkn;
690 } else
691 v.Remove(_T("GUST"));
692 }
693 if (v.HasMember(_T("SWELL"))) {
694 double vkn = m_pGribCtrlBar->getTimeInterpolatedValue(Idx_HTSIGW, lon,
695 lat, time);
696 if (vkn != GRIB_NOTDEF) {
697 v[_T("Type")] = wxT("Reply");
698 v[_T("SWELL")] = vkn;
699 } else
700 v.Remove(_T("SWELL"));
701 }
702
703 wxJSONWriter w;
704 wxString out;
705 w.Write(v, out);
706 SendPluginMessage(wxString(_T("GRIB_VALUES")), out);
707 }
708 } else if (message_id == _T("GRIB_VERSION_REQUEST")) {
709 wxJSONValue v;
710 v[_T("GribVersionMinor")] = GetAPIVersionMinor();
711 v[_T("GribVersionMajor")] = GetAPIVersionMajor();
712
713 wxJSONWriter w;
714 wxString out;
715 w.Write(v, out);
716 SendPluginMessage(wxString(_T("GRIB_VERSION")), out);
717 } else if (message_id == _T("GRIB_TIMELINE_REQUEST")) {
718 // local time
719 SendTimelineMessage(m_pGribCtrlBar ? m_pGribCtrlBar->TimelineTime()
720 : wxDateTime::Now());
721 } else if (message_id == _T("GRIB_TIMELINE_RECORD_REQUEST")) {
722 wxJSONReader r;
723 wxJSONValue v;
724 r.Parse(message_body, &v);
725 wxDateTime time(v[_T("Day")].AsInt(),
726 (wxDateTime::Month)v[_T("Month")].AsInt(),
727 v[_T("Year")].AsInt(), v[_T("Hour")].AsInt(),
728 v[_T("Minute")].AsInt(), v[_T("Second")].AsInt());
729
730 if (!m_pGribCtrlBar) OnToolbarToolCallback(0);
731
733 m_pGribCtrlBar ? m_pGribCtrlBar->GetTimeLineRecordSet(time) : nullptr;
734
735 char ptr[64];
736 snprintf(ptr, sizeof ptr, "%p", set);
737
738 v[_T("GribVersionMajor")] = PLUGIN_VERSION_MAJOR;
739 v[_T("GribVersionMinor")] = PLUGIN_VERSION_MINOR;
740 v[_T("TimelineSetPtr")] = wxString::From8BitData(ptr);
741
742 wxJSONWriter w;
743 wxString out;
744 w.Write(v, out);
745 SendPluginMessage(wxString(_T("GRIB_TIMELINE_RECORD")), out);
746 delete m_pLastTimelineSet;
747 m_pLastTimelineSet = set;
748 }
749
750 else if (message_id == _T("GRIB_APPLY_JSON_CONFIG")) {
751 wxLogMessage(_T("Got GRIB_APPLY_JSON_CONFIG"));
752
753 if (m_pGribCtrlBar) {
754 m_pGribCtrlBar->OpenFileFromJSON(message_body);
755
756 m_pGribCtrlBar->m_OverlaySettings.JSONToSettings(message_body);
757 m_pGribCtrlBar->m_OverlaySettings.Write();
758 m_pGribCtrlBar->SetDialogsStyleSizePosition(true);
759 }
760 }
761}
762
763bool grib_pi::LoadConfig(void) {
764 wxFileConfig *pConf = (wxFileConfig *)m_pconfig;
765
766 if (!pConf) return false;
767
768 pConf->SetPath(_T( "/PlugIns/GRIB" ));
769 pConf->Read(_T( "LoadLastOpenFile" ), &m_bLoadLastOpenFile, 0);
770 pConf->Read(_T("OpenFileOption" ), &m_bStartOptions, 1);
771 pConf->Read(_T( "GRIBUseHiDef" ), &m_bGRIBUseHiDef, 0);
772 pConf->Read(_T( "GRIBUseGradualColors" ), &m_bGRIBUseGradualColors, 0);
773 pConf->Read(_T( "DrawBarbedArrowHead" ), &m_bDrawBarbedArrowHead, 1);
774 pConf->Read(_T( "ZoomToCenterAtInit"), &m_bZoomToCenterAtInit, 1);
775 pConf->Read(_T( "ShowGRIBIcon" ), &m_bGRIBShowIcon, 1);
776 pConf->Read(_T( "CopyFirstCumulativeRecord" ), &m_bCopyFirstCumRec, 1);
777 pConf->Read(_T( "CopyMissingWaveRecord" ), &m_bCopyMissWaveRec, 1);
778#ifdef __WXMSW__
779 pConf->Read(_T("GribIconsScaleFactor"), &m_GribIconsScaleFactor, 1);
780#endif
781
782 m_CtrlBar_Sizexy.x = pConf->Read(_T ( "GRIBCtrlBarSizeX" ), 1400L);
783 m_CtrlBar_Sizexy.y = pConf->Read(_T ( "GRIBCtrlBarSizeY" ), 800L);
784 m_CtrlBarxy.x = pConf->Read(_T ( "GRIBCtrlBarPosX" ), 20L);
785 m_CtrlBarxy.y = pConf->Read(_T ( "GRIBCtrlBarPosY" ), 60L);
786 m_CursorDataxy.x = pConf->Read(_T ( "GRIBCursorDataPosX" ), 20L);
787 m_CursorDataxy.y = pConf->Read(_T ( "GRIBCursorDataPosY" ), 170L);
788
789 pConf->Read(_T ( "GribCursorDataDisplayStyle" ), &m_DialogStyle, 0);
790 if (m_DialogStyle > 3)
791 m_DialogStyle = 0; // ensure validity of the .conf value
792
793 return true;
794}
795
796bool grib_pi::SaveConfig(void) {
797 wxFileConfig *pConf = (wxFileConfig *)m_pconfig;
798
799 if (!pConf) return false;
800
801 pConf->SetPath(_T( "/PlugIns/GRIB" ));
802
803 pConf->Write(_T ( "LoadLastOpenFile" ), m_bLoadLastOpenFile);
804 pConf->Write(_T ( "OpenFileOption" ), m_bStartOptions);
805 pConf->Write(_T ( "ShowGRIBIcon" ), m_bGRIBShowIcon);
806 pConf->Write(_T ( "GRIBUseHiDef" ), m_bGRIBUseHiDef);
807 pConf->Write(_T ( "GRIBUseGradualColors" ), m_bGRIBUseGradualColors);
808 pConf->Write(_T ( "CopyFirstCumulativeRecord" ), m_bCopyFirstCumRec);
809 pConf->Write(_T ( "CopyMissingWaveRecord" ), m_bCopyMissWaveRec);
810 pConf->Write(_T ( "DrawBarbedArrowHead" ), m_bDrawBarbedArrowHead);
811 pConf->Write(_T ( "ZoomToCenterAtInit"), m_bZoomToCenterAtInit);
812#ifdef __WXMSW__
813 pConf->Write(_T("GribIconsScaleFactor"), m_GribIconsScaleFactor);
814#endif
815
816 pConf->Write(_T ( "GRIBCtrlBarSizeX" ), m_CtrlBar_Sizexy.x);
817 pConf->Write(_T ( "GRIBCtrlBarSizeY" ), m_CtrlBar_Sizexy.y);
818 pConf->Write(_T ( "GRIBCtrlBarPosX" ), m_CtrlBarxy.x);
819 pConf->Write(_T ( "GRIBCtrlBarPosY" ), m_CtrlBarxy.y);
820 pConf->Write(_T ( "GRIBCursorDataPosX" ), m_CursorDataxy.x);
821 pConf->Write(_T ( "GRIBCursorDataPosY" ), m_CursorDataxy.y);
822
823 return true;
824}
825
827 DimeWindow(m_pGribCtrlBar);
828 if (m_pGribCtrlBar) {
829 if (m_pGRIBOverlayFactory) m_pGRIBOverlayFactory->ClearCachedLabel();
830 if (m_pGribCtrlBar->pReq_Dialog) m_pGribCtrlBar->pReq_Dialog->Refresh();
831 m_pGribCtrlBar->Refresh();
832 // m_pGribDialog->SetDataBackGroundColor();
833 }
834}
835
836void grib_pi::SendTimelineMessage(wxDateTime time) {
837 if (!m_pGribCtrlBar) return;
838
839 wxJSONValue v;
840 if (time.IsValid()) {
841 v[_T("Day")] = time.GetDay();
842 v[_T("Month")] = time.GetMonth();
843 v[_T("Year")] = time.GetYear();
844 v[_T("Hour")] = time.GetHour();
845 v[_T("Minute")] = time.GetMinute();
846 v[_T("Second")] = time.GetSecond();
847 } else {
848 v[_T("Day")] = -1;
849 v[_T("Month")] = -1;
850 v[_T("Year")] = -1;
851 v[_T("Hour")] = -1;
852 v[_T("Minute")] = -1;
853 v[_T("Second")] = -1;
854 }
855 wxJSONWriter w;
856 wxString out;
857 w.Write(v, out);
858 SendPluginMessage(wxString(_T("GRIB_TIMELINE")), out);
859}
860
862 m_boat_cog = pfix.Cog;
863 m_boat_sog = pfix.Sog;
864 m_boat_lat = pfix.Lat;
865 m_boat_lon = pfix.Lon;
866 if (pfix.FixTime != 0) {
867 m_boat_time = pfix.FixTime;
868 } else {
869 m_boat_time = wxDateTime::Now().GetTicks();
870 }
871}
872
873//----------------------------------------------------------------------------------------------------------
874// Prefrence dialog Implementation
875//----------------------------------------------------------------------------------------------------------
876void GribPreferencesDialog::OnStartOptionChange(wxCommandEvent &event) {
877 if (m_rbStartOptions->GetSelection() == 2) {
878 OCPNMessageBox_PlugIn(
879 this,
880 _("You have chosen to authorize interpolation.\nDon't forget that data "
881 "displayed at current time will not be real but Recomputed\nThis can "
882 "decrease accuracy!"),
883 _("Warning!"));
884 }
885}
886
887void GribPreferencesDialog::OnOKClick(wxCommandEvent &event) {
888 if (g_pi) g_pi->UpdatePrefs(this);
889 Close();
890}
@ Idx_WIND_GUST
Wind gust speed at surface in m/s.
@ Idx_WIND_VX
Surface wind velocity X component in m/s.
@ Idx_HTSIGW
Significant wave height in meters.
@ Idx_SEACURRENT_VY
Sea current velocity Y component in m/s.
@ Idx_WIND_VY
Surface wind velocity Y component in m/s.
@ Idx_SEACURRENT_VX
Sea current velocity X component in m/s.
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.
void SetViewPortWithFocus(PlugIn_ViewPort *vp)
Set the ViewPort that has the focus.
GribOverlaySettings m_OverlaySettings
Settings that control how GRIB data is displayed and overlaid.
void SetViewPortUnderMouse(PlugIn_ViewPort *vp)
Set the ViewPort under the mouse.
wxString m_grib_dir
Directory containing GRIB files.
GRIBFile * m_bGRIBActiveFile
Currently active GRIB file being displayed.
wxDateTime TimelineTime()
Returns the selected time in the GRIB timeline widget.
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.
bool RenderGlZoneOverlay()
Renders the GRIB area selection overlay using OpenGL.
bool RenderZoneOverlay(wxDC &dc)
Renders the GRIB area selection overlay using standard device context.
bool MouseEventHook(wxMouseEvent &event)
Intercepts mouse events to handle GRIB area selection.
A specialized GribRecordSet that represents temporally interpolated weather data with isobar renderin...
Extended position fix information.
double Cog
Course over ground in degrees.
double Lat
Latitude in decimal degrees.
time_t FixTime
UTC time of fix.
double Lon
Longitude in decimal degrees.
double Sog
Speed over ground in knots.
Contains view parameters and status information for a chart display viewport.
void SetCursorLatLon(double lat, double lon)
Receives cursor lat/lon position updates.
Definition grib_pi.cpp:613
bool RenderGLOverlay(wxGLContext *pcontext, PlugIn_ViewPort *vp)
Renders plugin overlay graphics in OpenGL mode.
Definition grib_pi.cpp:571
wxString GetCommonName()
Get the plugin's common (short) name.
Definition grib_pi.cpp:197
bool DeInit(void)
Clean up plugin resources.
Definition grib_pi.cpp:174
void OnContextMenuItemCallback(int id)
Handles context menu item selection.
Definition grib_pi.cpp:618
int Init(void)
Initialize the plugin and declare its capabilities.
Definition grib_pi.cpp:99
void SetPositionFixEx(PlugIn_Position_Fix_Ex &pfix)
Updates plugin with extended position fix data.
Definition grib_pi.cpp:861
int GetAPIVersionMinor()
Returns the minor version number of the plugin API that this plugin supports.
Definition grib_pi.cpp:189
int GetPlugInVersionMinor()
Returns the minor version number of the plugin itself.
Definition grib_pi.cpp:193
void SetColorScheme(PI_ColorScheme cs)
Updates plugin color scheme.
Definition grib_pi.cpp:826
void OnToolbarToolCallback(int id)
Handles toolbar tool clicks.
Definition grib_pi.cpp:417
int GetPlugInVersionMajor()
Returns the major version number of the plugin itself.
Definition grib_pi.cpp:191
bool MouseEventHook(wxMouseEvent &event)
Handles mouse events from chart window.
Definition grib_pi.cpp:224
wxString GetShortDescription()
Get a brief description of the plugin.
Definition grib_pi.cpp:199
void ShowPreferencesDialog(wxWindow *parent)
Shows the plugin preferences dialog.
Definition grib_pi.cpp:230
void SetDefaults(void)
Sets plugin default options.
Definition grib_pi.cpp:220
wxBitmap * GetPlugInBitmap()
Get the plugin's icon bitmap.
Definition grib_pi.cpp:195
bool RenderOverlayMultiCanvas(wxDC &dc, PlugIn_ViewPort *vp, int canvasIndex)
Renders plugin overlay graphics with canvas selection.
Definition grib_pi.cpp:608
bool RenderGLOverlayMultiCanvas(wxGLContext *pcontext, PlugIn_ViewPort *vp, int canvasIndex)
Renders plugin overlay graphics in OpenGL mode with canvas selection.
Definition grib_pi.cpp:603
wxString GetLongDescription()
Get detailed plugin information.
Definition grib_pi.cpp:201
int GetAPIVersionMajor()
Returns the major version number of the plugin API that this plugin supports.
Definition grib_pi.cpp:187
Base class for OpenCPN plugins.
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.
PI_ColorScheme
Enumeration of color schemes.
#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:91
#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:87
wxString * GetpSharedDataLocation(void)
Gets shared application data location.
wxWindow * PluginGetFocusCanvas()
Gets the currently focused chart canvas.
wxWindow * GetOCPNCanvasWindow()
Gets OpenCPN's main canvas window.
void SetCanvasContextMenuItemViz(int item, bool viz)
Temporarily changes context menu item visibility.
wxFont * OCPNGetFont(wxString TextElement, int default_size)
Gets a font for UI elements.
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.
int GetCanvasIndexUnderMouse(void)
Gets index of chart canvas under mouse cursor.
wxWindow * GetCanvasUnderMouse(void)
Gets canvas window under mouse cursor.
void DimeWindow(wxWindow *win)
Applies system color scheme to window.
double GetOCPNGUIToolScaleFactor_PlugIn()
Gets current global GUI scaling factor.
int AddCanvasContextMenuItem(wxMenuItem *pitem, opencpn_plugin *pplugin)
Adds item to chart canvas context menu.
wxString GetActiveStyleName()
Gets name of currently active style sheet.
void SetToolbarItemState(int item, bool toggle)
Sets toolbar item toggle state.
wxWindow * GetCanvasByIndex(int canvasIndex)
Gets chart canvas window by index.
double OCPN_GetWinDIPScaleFactor()
Gets Windows-specific DPI scaling factor.
void SendPluginMessage(wxString message_id, wxString message_body)
Sends message to other plugins.
void RequestRefresh(wxWindow *win)
Requests window refresh.
bool AddLocaleCatalog(wxString catalog)
Adds a locale catalog for translations.
wxFileConfig * GetOCPNConfigObject(void)
Gets OpenCPN's configuration object.
OpenGL Platform Abstraction Layer.
wxString * GetpPrivateApplicationDataLocation(void)
Gets private application data directory.