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