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
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: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
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.