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