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