1 /******************************************************************************
2 *
3 * Project: OpenCPN
4 * Purpose: GRIB Object
5 * Author: David Register
6 *
7 ***************************************************************************
8 * Copyright (C) 2010 by David S. Register *
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
19 * *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
24 ***************************************************************************
25 *
26 */
27 #include "grib_pi.h"
28
29 #include "folder.xpm"
30
31 extern int m_Altitude;
32 extern double m_cursor_lat, m_cursor_lon;
33 extern int m_DialogStyle;
34
35 enum SettingsDisplay {B_ARROWS, ISO_LINE, ISO_ABBR, D_ARROWS, OVERLAY, NUMBERS, PARTICLES};
36
37 //---------------------------------------------------------------------------------------
38 // GRIB Cursor Data implementation
39 //---------------------------------------------------------------------------------------
CursorData(wxWindow * window,GRIBUICtrlBar & parent)40 CursorData::CursorData( wxWindow *window, GRIBUICtrlBar &parent )
41 : CursorDataBase(window),m_gparent(parent)
42 {
43
44 //transform checkboxes ID to have a formal link to data type and set the initial value
45 wxWindowListNode *node = this->GetChildren().GetFirst();
46 while( node ) {
47 wxWindow *win = node->GetData();
48 if( win->IsKindOf(CLASSINFO(wxCheckBox)) ) {
49 int winId = ((wxCheckBox*) win )->GetId() - ID_CB_WIND;
50 if (m_gparent.InDataPlot(winId)) {
51 ((wxCheckBox*) win )->SetId( winId );
52 ((wxCheckBox*) win )->SetValue( m_gparent.m_bDataPlot[winId] );
53 }
54 }
55 node = node->GetNext();
56 }
57
58 m_bLeftDown = false;
59
60 m_tCursorTrackTimer.Connect(wxEVT_TIMER, wxTimerEventHandler( CursorData::OnCursorTrackTimer ), NULL, this);
61
62 DimeWindow( this );
63 }
64
OnCBAny(wxCommandEvent & event)65 void CursorData::OnCBAny( wxCommandEvent& event )
66 {
67 int id = event.GetId();
68 wxWindow *win = this->FindWindow( id );
69 if (m_gparent.InDataPlot(id))
70 m_gparent.m_bDataPlot[id] = ((wxCheckBox*) win )->IsChecked();
71 ResolveDisplayConflicts( id );
72 }
73
ResolveDisplayConflicts(int Id)74 void CursorData::ResolveDisplayConflicts( int Id )
75 {
76 //allow multi selection only if there is no display type superposition
77 for( int i = 0; i < GribOverlaySettings::GEO_ALTITUDE; i++ ) {
78 if( i != Id && m_gparent.m_bDataPlot[i] ) {
79 if( (m_gparent.m_OverlaySettings.Settings[Id].m_bBarbedArrows &&
80 m_gparent.m_OverlaySettings.Settings[i].m_bBarbedArrows)
81 || (m_gparent.m_OverlaySettings.Settings[Id].m_bDirectionArrows &&
82 m_gparent.m_OverlaySettings.Settings[i].m_bDirectionArrows)
83 || (m_gparent.m_OverlaySettings.Settings[Id].m_bIsoBars &&
84 m_gparent.m_OverlaySettings.Settings[i].m_bIsoBars)
85 || (m_gparent.m_OverlaySettings.Settings[Id].m_bNumbers &&
86 m_gparent.m_OverlaySettings.Settings[i].m_bNumbers)
87 || (m_gparent.m_OverlaySettings.Settings[Id].m_bOverlayMap &&
88 m_gparent.m_OverlaySettings.Settings[i].m_bOverlayMap)
89 || (m_gparent.m_OverlaySettings.Settings[Id].m_bParticles &&
90 m_gparent.m_OverlaySettings.Settings[i].m_bParticles) ) {
91 m_gparent.m_bDataPlot[i] = false;
92 wxWindow *win = FindWindow(i);
93 ((wxCheckBox*) win )->SetValue( false );
94 }
95 }
96 }
97 m_gparent.SetFactoryOptions(); // Reload the visibility options
98 }
99
AddTrackingControl(wxControl * ctrl1,wxControl * ctrl2,wxControl * ctrl3,wxControl * ctrl4,bool show,bool vertical,int wctrl2,int wctrl3_4)100 void CursorData::AddTrackingControl( wxControl *ctrl1, wxControl *ctrl2, wxControl *ctrl3, wxControl *ctrl4, bool show,
101 bool vertical, int wctrl2, int wctrl3_4)
102 {
103 if(show) {
104 m_fgTrackingControls->Add(ctrl1, 0, wxALL, 1);
105 ctrl1->Show();
106 if(ctrl2) {
107 m_fgTrackingControls->Add(ctrl2, 0, wxALL, 0);
108 ctrl2->SetMinSize(wxSize(wctrl2, -1));
109 ctrl2->Show();
110 } else
111 m_fgTrackingControls->Add(0, 0, 1, wxALL, 1); /* spacer */
112
113 if(ctrl3) {
114 long flag1 = wxALIGN_CENTER;
115 long flag = vertical? flag1: wxALL;
116 m_fgTrackingControls->Add(ctrl3, 0, flag, 0);
117 ctrl3->SetMinSize(wxSize(wctrl3_4, -1));
118 ctrl3->Show();
119 } else
120 if( !vertical ) m_fgTrackingControls->Add(0, 0, 1, wxALL, 1); /* spacer */
121
122 if(ctrl4) {
123 m_fgTrackingControls->Add(ctrl4, 0, wxALL, 0);
124 ctrl4->SetMinSize(wxSize(vertical? wctrl2: wctrl3_4, -1));
125 ctrl4->Show();
126 } else
127 if( !vertical ) m_fgTrackingControls->Add(0, 0, 1, wxALL, 1 ); /* spacer */
128
129 } else {
130 if(ctrl1) ctrl1->Hide();
131 if(ctrl2) ctrl2->Hide();
132 if(ctrl3) ctrl3->Hide();
133 if(ctrl4) ctrl4->Hide();
134 }
135 }
136
PopulateTrackingControls(bool vertical)137 void CursorData::PopulateTrackingControls( bool vertical )
138 {
139 m_fgTrackingControls->Clear();
140 if(!vertical){
141 wxFlexGridSizer *ps = (wxFlexGridSizer*)(m_gparent.GetSizer());
142 if(ps && (ps->GetCols() == 1))
143 m_fgTrackingControls->SetCols( 4 ); // compact mode
144 else
145 m_fgTrackingControls->SetCols( 12 );
146 }
147 else
148 m_fgTrackingControls->SetCols( 2 );
149
150 this->Fit();
151 //Get text controls sizing data
152 wxFont *font = OCPNGetFont(_("Dialog"), 10);
153 int wn, wd, ws,wl;
154 GetTextExtent( _T("abcdefghihjk"), &wn, NULL, 0, 0, font); // normal width text control size
155 GetTextExtent( _T("abcdef"), &ws, NULL, 0, 0, font); // short width text control size for direction only
156 GetTextExtent( _T("abcdefghijklmopq"), &wd, NULL, 0, 0, font); // long width text control size for double unit wind display
157 GetTextExtent( _T("abcdefghijklm"), &wl, NULL, 0, 0, font); // long width text control size for double unit wave display
158 //
159 //create a dummy textCtrl to be used as a "space" in vertical display
160 wxTextCtrl *dummy = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY|wxNO_BORDER );
161 //
162 bool bf = m_gparent.m_OverlaySettings.Settings[GribOverlaySettings::WIND].m_Units == GribOverlaySettings::BFS;
163 wd = vertical ? wn: bf? wn: wd;
164 wl = vertical? wn : wl;
165
166 AddTrackingControl(m_cbWind, m_tcWindSpeed, m_tcWindSpeedBf, m_tcWindDirection, false, vertical, 0, 0 ); //hide all wind's parameters
167 AddTrackingControl(m_cbWind, m_tcWindSpeed, vertical? (bf? dummy : m_tcWindSpeedBf): m_tcWindDirection, vertical? m_tcWindDirection: 0,
168 m_gparent.m_pTimelineSet && m_gparent.m_bGRIBActiveFile->m_GribIdxArray.Index(Idx_WIND_VX) != wxNOT_FOUND
169 && m_gparent.m_bGRIBActiveFile->m_GribIdxArray.Index(Idx_WIND_VY) != wxNOT_FOUND, vertical, wd, ws);
170 AddTrackingControl(m_cbWindGust, m_tcWindGust, 0, 0, m_gparent.m_pTimelineSet
171 && m_gparent.m_bGRIBActiveFile->m_GribIdxArray.Index(Idx_WIND_GUST) != wxNOT_FOUND
172 && m_Altitude == 0, vertical, wn);
173 AddTrackingControl(m_cbPressure, m_tcPressure, 0, 0, m_gparent.m_pTimelineSet
174 && m_gparent.m_bGRIBActiveFile->m_GribIdxArray.Index(Idx_PRESSURE) != wxNOT_FOUND
175 && m_Altitude == 0, vertical, wn);
176
177 /* tracking for wave is funky */
178 AddTrackingControl(m_cbWave, m_tcWaveHeight, m_tcWavePeriode, m_tcWaveDirection, false, vertical, 0, 0); //hide all waves's parameters
179 if(m_gparent.m_pTimelineSet && m_gparent.m_bGRIBActiveFile->m_GribIdxArray.Index(Idx_HTSIGW) != wxNOT_FOUND) {
180 if(m_gparent.m_bGRIBActiveFile->m_GribIdxArray.Index(Idx_WVDIR) != wxNOT_FOUND)
181 AddTrackingControl(m_cbWave, m_tcWaveHeight, vertical? m_tcWavePeriode: m_tcWaveDirection,
182 vertical? m_tcWaveDirection: 0 , m_Altitude == 0, vertical, wl, ws);
183 else
184 AddTrackingControl(m_cbWave, m_tcWaveHeight, 0, 0, m_Altitude == 0, vertical, wn );
185 } else {
186 if(m_gparent.m_pTimelineSet && m_gparent.m_bGRIBActiveFile->m_GribIdxArray.Index(Idx_WVDIR) != wxNOT_FOUND)
187 AddTrackingControl(m_cbWave, m_tcWaveDirection, 0, 0, m_Altitude == 0, vertical, wn );
188 }
189
190 AddTrackingControl(m_cbCurrent, m_tcCurrentVelocity, m_tcCurrentDirection, 0, false, vertical, 0, 0); //hide all current's parameters
191 AddTrackingControl(m_cbCurrent, m_tcCurrentVelocity, vertical? dummy: m_tcCurrentDirection, vertical? m_tcCurrentDirection: 0,
192 m_gparent.m_pTimelineSet && m_gparent.m_bGRIBActiveFile->m_GribIdxArray.Index(Idx_SEACURRENT_VX) != wxNOT_FOUND
193 && m_gparent.m_bGRIBActiveFile->m_GribIdxArray.Index(Idx_SEACURRENT_VY) != wxNOT_FOUND
194 && m_Altitude == 0, vertical, wn, ws);
195 AddTrackingControl(m_cbPrecipitation, m_tcPrecipitation, 0, 0,
196 m_gparent.m_pTimelineSet && m_gparent.m_bGRIBActiveFile->m_GribIdxArray.Index(Idx_PRECIP_TOT) != wxNOT_FOUND
197 && m_Altitude == 0, vertical, wn);
198 AddTrackingControl(m_cbCloud, m_tcCloud, 0, 0,
199 m_gparent.m_pTimelineSet && m_gparent.m_bGRIBActiveFile->m_GribIdxArray.Index(Idx_CLOUD_TOT) != wxNOT_FOUND
200 && m_Altitude == 0, vertical, wn);
201 AddTrackingControl(m_cbAirTemperature, m_tcAirTemperature, 0, 0,
202 m_gparent.m_pTimelineSet && m_gparent.m_bGRIBActiveFile->m_GribIdxArray.Index(Idx_AIR_TEMP) != wxNOT_FOUND
203 && m_Altitude == 0, vertical, wn);
204 AddTrackingControl(m_cbSeaTemperature, m_tcSeaTemperature, 0, 0,
205 m_gparent.m_pTimelineSet && m_gparent.m_bGRIBActiveFile->m_GribIdxArray.Index(Idx_SEA_TEMP) != wxNOT_FOUND
206 && m_Altitude == 0, vertical, wn);
207 AddTrackingControl(m_cbCAPE, m_tcCAPE, 0, 0,
208 m_gparent.m_pTimelineSet && m_gparent.m_bGRIBActiveFile->m_GribIdxArray.Index(Idx_CAPE) != wxNOT_FOUND
209 && m_Altitude == 0, vertical, wn);
210 AddTrackingControl(m_cbReflC, m_tcReflC, 0, 0,
211 m_gparent.m_pTimelineSet && m_gparent.m_bGRIBActiveFile->m_GribIdxArray.Index(Idx_COMP_REFL) != wxNOT_FOUND
212 && m_Altitude == 0, vertical, wn);
213 //
214 //init and show extra parameters for altitude tracking if necessary
215 AddTrackingControl(m_cbAltitude, m_tcAltitude, 0, 0,
216 m_gparent.m_pTimelineSet && m_gparent.m_bGRIBActiveFile->m_GribIdxArray.Index(Idx_GEOP_HGT + m_Altitude) != wxNOT_FOUND
217 && m_Altitude != 0, vertical, wn);
218 AddTrackingControl(m_cbTemp, m_tcTemp, 0, 0,
219 m_gparent.m_pTimelineSet && m_gparent.m_bGRIBActiveFile->m_GribIdxArray.Index(Idx_AIR_TEMP + m_Altitude) != wxNOT_FOUND
220 && m_Altitude != 0, vertical, wn);
221 AddTrackingControl(m_cbRelHumid, m_tcRelHumid, 0, 0,
222 m_gparent.m_pTimelineSet && m_gparent.m_bGRIBActiveFile->m_GribIdxArray.Index(Idx_HUMID_RE + m_Altitude) != wxNOT_FOUND
223 && m_Altitude != 0, vertical, wn);
224 //
225 m_stTrackingText->SetLabel( _("Data at cursor position") );
226 //add tooltips
227 wxString t; double lev;
228
229 lev = m_gparent.m_OverlaySettings.CalibrateValue(GribOverlaySettings::GEO_ALTITUDE, 10 ); //convert 10m in current altitude unit
230 t.Printf(
231 m_Altitude ? m_gparent.m_OverlaySettings.GetAltitudeFromIndex(
232 m_Altitude, m_gparent.m_OverlaySettings.Settings[GribOverlaySettings::PRESSURE].m_Units)
233 .Append( _T(" ") ).Append( m_gparent.m_OverlaySettings.GetUnitSymbol(GribOverlaySettings::PRESSURE) )
234 : wxString::Format( _T("%1.*f "), lev == (int) lev ? 0 : 1, lev )
235 .Append( m_gparent.m_OverlaySettings.GetUnitSymbol(GribOverlaySettings::GEO_ALTITUDE) )
236 );
237 wxString pre = _T(" ");
238 if( m_Altitude ) {
239 pre.Append(_("at Geopotential Height"));
240 pre.Append(_T(" "));
241 m_tcAltitude->SetToolTip( _("Altitude" ) + t );
242 m_tcTemp->SetToolTip( _("Temperature") + t );
243 m_tcRelHumid->SetToolTip( _("Relative Humidity") + t );
244 } else{
245 pre.Append(_("at"));
246 pre.Append(_T(" "));
247 }
248 t.Prepend(pre);
249
250 m_tcWindSpeed->SetToolTip( _("Wind Speed") + t );
251 m_tcWindSpeedBf->SetToolTip( _("Wind Speed in Bf") + t );
252 m_tcWindDirection->SetToolTip( _("Wind Direction") + t );
253
254 t.Printf( _T(" %1.*f ") + m_gparent.m_OverlaySettings.GetUnitSymbol(GribOverlaySettings::GEO_ALTITUDE), lev == (int) lev ? 0 : 1, lev );
255 m_tcWindGust->SetToolTip( _("Wind Gust at") + t );
256
257 if( m_gparent.m_pTimelineSet ) {
258 wxString s[] = { _T(" "), _("Air Temperature at"), _("surface level"), _("Sea Surface Temperature") };
259
260 lev = m_gparent.m_OverlaySettings.CalibrateValue(GribOverlaySettings::GEO_ALTITUDE, 2 ); //convert 2m in current altitude unit
261 t.Printf( m_gparent.m_bGRIBActiveFile->m_GribIdxArray.Index(1000 + NORWAY_METNO) != wxNOT_FOUND ? s[0] + s[2]
262 : _T(" %1.*f ") + m_gparent.m_OverlaySettings.GetUnitSymbol(GribOverlaySettings::GEO_ALTITUDE), lev == (int) lev ? 0 : 1, lev );
263 m_tcAirTemperature->SetToolTip(s[1] + t );
264
265 m_tcSeaTemperature->SetToolTip( m_gparent.m_bGRIBActiveFile->m_GribIdxArray.Index( 1000 + NOAA_GFS) != wxNOT_FOUND ? s[1] + s[0] + s[2] : s[3] );
266 }
267 dummy->Show( false );
268 }
269
UpdateTrackingControls(void)270 void CursorData::UpdateTrackingControls( void )
271 {
272 if( !m_gparent.m_pTimelineSet )
273 return;
274
275 GribRecord **RecordArray = m_gparent.m_pTimelineSet->m_GribRecordPtrArray;
276 // Update the wind control
277 double vkn, ang;
278 if(GribRecord::getInterpolatedValues(vkn, ang,
279 RecordArray[Idx_WIND_VX + m_Altitude],
280 RecordArray[Idx_WIND_VY + m_Altitude],
281 m_cursor_lon, m_cursor_lat)) {
282 double vk = m_gparent.m_OverlaySettings.CalibrateValue(GribOverlaySettings::WIND, vkn);
283
284 m_tcWindSpeed->SetValue( wxString::Format( _T("%3d ") + m_gparent.m_OverlaySettings.GetUnitSymbol
285 (GribOverlaySettings::WIND) , (int)round( vk )) );
286
287 //wind is a special case: if current unit is not bf ==> double speed display (current unit + bf)
288 if(m_gparent.m_OverlaySettings.Settings[GribOverlaySettings::WIND].m_Units != GribOverlaySettings::BFS) {
289 vk = m_gparent.m_OverlaySettings.GetmstobfFactor(vkn)* vkn;
290 if( m_DialogStyle == SEPARATED_VERTICAL )
291 m_tcWindSpeedBf->SetValue( wxString::Format( _T("%2d bf"), (int)round( vk )));
292 else
293 m_tcWindSpeed->SetValue(m_tcWindSpeed->GetValue().Append(_T(" - "))
294 .Append(wxString::Format(_T("%2d bf"), (int)round( vk))) );
295 }
296
297 m_tcWindDirection->SetValue( wxString::Format( _T("%03d\u00B0"), (int) ( ang ) ));
298 } else {
299 m_tcWindSpeed->SetValue( _("N/A") );
300 m_tcWindSpeedBf->SetValue( _("N/A") );
301 m_tcWindDirection->SetValue( _("N/A") );
302 }
303
304 // Update the Wind gusts control
305 if( RecordArray[Idx_WIND_GUST] ) {
306 double vkn = RecordArray[Idx_WIND_GUST]->
307 getInterpolatedValue(m_cursor_lon, m_cursor_lat, true );
308
309 if( vkn != GRIB_NOTDEF ) {
310 vkn = m_gparent.m_OverlaySettings.CalibrateValue(GribOverlaySettings::WIND_GUST, vkn);
311 m_tcWindGust->SetValue( wxString::Format(_T("%2d ") + m_gparent.m_OverlaySettings.GetUnitSymbol(GribOverlaySettings::WIND_GUST), (int)round( vkn )) );
312 } else
313 m_tcWindGust->SetValue( _("N/A") );
314 }
315
316 // Update the Pressure control
317 if( RecordArray[Idx_PRESSURE] ) {
318 double press = RecordArray[Idx_PRESSURE]->
319 getInterpolatedValue(m_cursor_lon, m_cursor_lat, true );
320
321 if( press != GRIB_NOTDEF ) {
322 press = m_gparent.m_OverlaySettings.CalibrateValue(GribOverlaySettings::PRESSURE, press);
323 int p = (m_gparent.m_OverlaySettings.Settings[GribOverlaySettings::PRESSURE].m_Units == 2) ? 2 : 1; // if PRESSURE & inHG = two decimals
324 m_tcPressure->SetValue( wxString::Format(_T("%2.*f ") + m_gparent.m_OverlaySettings.GetUnitSymbol(GribOverlaySettings::PRESSURE), p, ( press )) );
325 } else
326 m_tcPressure->SetValue( _("N/A") );
327 }
328
329 // Update the Sig Wave Height
330 if( RecordArray[Idx_HTSIGW] ) {
331 double height = RecordArray[Idx_HTSIGW]->
332 getInterpolatedValue(m_cursor_lon, m_cursor_lat, true );
333
334 if( height != GRIB_NOTDEF ) {
335 height = m_gparent.m_OverlaySettings.CalibrateValue(GribOverlaySettings::WAVE, height);
336 wxString w( wxString::Format( _T("%4.1f ") + m_gparent.m_OverlaySettings.GetUnitSymbol(GribOverlaySettings::WAVE), height ));
337 if( RecordArray[Idx_WVPER] ) {
338 double period = RecordArray[Idx_WVPER]->
339 getInterpolatedValue(m_cursor_lon, m_cursor_lat, true );
340 if( period != GRIB_NOTDEF ) {
341 if( m_DialogStyle == SEPARATED_VERTICAL )
342 m_tcWavePeriode->SetValue( wxString::Format(_T("%01ds") , (int) round(period)) );
343 else
344 w.Append( wxString::Format( _T(" - %01ds") , (int) round(period) ));
345 } else
346 m_tcWavePeriode->SetValue( _("N/A") );
347 } else
348 m_tcWavePeriode->SetValue( _("N/A") );
349
350 m_tcWaveHeight->SetValue(w);
351 } else
352 m_tcWaveHeight->SetValue( _("N/A") );
353 }
354
355 // Update the Wave direction
356 if( RecordArray[Idx_WVDIR] ) {
357 double direction = RecordArray[Idx_WVDIR]->
358 getInterpolatedValue(m_cursor_lon, m_cursor_lat, true, true );
359 if( direction != GRIB_NOTDEF )
360 m_tcWaveDirection->SetValue( wxString::Format( _T("%03d\u00B0"), (int)direction ));
361 else
362 m_tcWaveDirection->SetValue( _("N/A") );
363 }
364
365 // Update the Current control
366 if(GribRecord::getInterpolatedValues(vkn, ang,
367 RecordArray[Idx_SEACURRENT_VX],
368 RecordArray[Idx_SEACURRENT_VY],
369 m_cursor_lon, m_cursor_lat)) {
370
371 // Current direction is generally reported as the "flow" direction,
372 // which is opposite from wind convention.
373 // So, adjust.
374 ang += 180;
375 if(ang >= 360) ang -= 360;
376 if( ang < 0 ) ang += 360;
377
378 vkn = m_gparent.m_OverlaySettings.CalibrateValue(GribOverlaySettings::CURRENT, vkn);
379
380 m_tcCurrentVelocity->SetValue( wxString::Format( _T("%4.1f ") + m_gparent.m_OverlaySettings.GetUnitSymbol(GribOverlaySettings::CURRENT), vkn ) );
381
382 m_tcCurrentDirection->SetValue( wxString::Format( _T("%03d\u00B0"), (int) ( ang ) ) );
383 } else {
384 m_tcCurrentVelocity->SetValue( _("N/A") );
385 m_tcCurrentDirection->SetValue( _("N/A") );
386 }
387
388 // Update total rainfall control
389 if( RecordArray[Idx_PRECIP_TOT] ) {
390 double precip = RecordArray[Idx_PRECIP_TOT]->
391 getInterpolatedValue( m_cursor_lon, m_cursor_lat, true );
392
393 if( precip != GRIB_NOTDEF ) {
394 precip = m_gparent.m_OverlaySettings.CalibrateValue(GribOverlaySettings::PRECIPITATION, precip);
395 int p = precip < 10. ? 2 : precip < 100. ? 1 : 0;
396 p += m_gparent.m_OverlaySettings.Settings[GribOverlaySettings::PRECIPITATION].m_Units == 1 ? 1 : 0 ; // if PRESSURE & in = one decimal more
397 m_tcPrecipitation->SetValue( wxString::Format( _T("%4.*f ") + m_gparent.m_OverlaySettings.GetUnitSymbol(GribOverlaySettings::PRECIPITATION), p, precip ) );
398 } else
399 m_tcPrecipitation->SetValue( _("N/A") );
400 }
401
402 // Update total cloud control
403 if( RecordArray[Idx_CLOUD_TOT] ) {
404 double cloud = RecordArray[Idx_CLOUD_TOT]->
405 getInterpolatedValue( m_cursor_lon, m_cursor_lat, true );
406
407 if( cloud != GRIB_NOTDEF ) {
408 cloud = m_gparent.m_OverlaySettings.CalibrateValue(GribOverlaySettings::CLOUD, cloud);
409 wxString val( wxString::Format( _T("%5.0f "), cloud ) );
410 m_tcCloud->SetValue( val + m_gparent.m_OverlaySettings.GetUnitSymbol(GribOverlaySettings::CLOUD) );
411 } else
412 m_tcCloud->SetValue( _("N/A") );
413 }
414
415 // Update the Air Temperature
416 if( RecordArray[Idx_AIR_TEMP] ) {
417 double temp = RecordArray[Idx_AIR_TEMP]->
418 getInterpolatedValue( m_cursor_lon, m_cursor_lat, true );
419
420 if( temp != GRIB_NOTDEF ) {
421 temp = m_gparent.m_OverlaySettings.CalibrateValue(GribOverlaySettings::AIR_TEMPERATURE, temp);
422 m_tcAirTemperature->SetValue( wxString::Format( _T("%5.1f ") + m_gparent.m_OverlaySettings.GetUnitSymbol(GribOverlaySettings::AIR_TEMPERATURE), temp ) );
423 } else
424 m_tcAirTemperature->SetValue( _("N/A") );
425 }
426
427 // Update the Sea Surface Temperature
428 if( RecordArray[Idx_SEA_TEMP] ) {
429 double temp = RecordArray[Idx_SEA_TEMP]->
430 getInterpolatedValue( m_cursor_lon, m_cursor_lat, true );
431
432 if( temp != GRIB_NOTDEF ) {
433 temp = m_gparent.m_OverlaySettings.CalibrateValue(GribOverlaySettings::SEA_TEMPERATURE, temp);
434 m_tcSeaTemperature->SetValue( wxString::Format( _T("%5.1f ") + m_gparent.m_OverlaySettings.GetUnitSymbol(GribOverlaySettings::SEA_TEMPERATURE), temp ) );
435 } else
436 m_tcSeaTemperature->SetValue( _("N/A") );
437 }
438
439 // Update the Convective Available Potential Energy (CAPE)
440 if( RecordArray[Idx_CAPE] ) {
441 double cape = RecordArray[Idx_CAPE]->getInterpolatedValue( m_cursor_lon, m_cursor_lat, true );
442
443 if( cape != GRIB_NOTDEF ) {
444 cape = m_gparent.m_OverlaySettings.CalibrateValue(GribOverlaySettings::CAPE, cape);
445 m_tcCAPE->SetValue( wxString::Format( _T("%5.0f ")
446 +m_gparent.m_OverlaySettings.GetUnitSymbol(GribOverlaySettings::CAPE), cape ) );
447 } else
448 m_tcCAPE->SetValue( _("N/A") );
449 }
450 if( RecordArray[Idx_COMP_REFL] ) {
451 double c_refl = RecordArray[Idx_COMP_REFL]->getInterpolatedValue( m_cursor_lon, m_cursor_lat, true );
452
453 if( c_refl != GRIB_NOTDEF ) {
454 c_refl = m_gparent.m_OverlaySettings.CalibrateValue(GribOverlaySettings::COMP_REFL, c_refl);
455 m_tcReflC->SetValue( wxString::Format( _T("%5.0f ") + m_gparent.m_OverlaySettings.GetUnitSymbol(GribOverlaySettings::COMP_REFL), c_refl ) );
456 } else
457 m_tcReflC->SetValue( _("N/A") );
458 }
459 // Update extra data for altitude
460 // geopotential altitude
461 if( RecordArray[Idx_GEOP_HGT + m_Altitude] ) {
462 double geop = RecordArray[Idx_GEOP_HGT + m_Altitude]->
463 getInterpolatedValue( m_cursor_lon, m_cursor_lat, true );
464
465 if( geop != GRIB_NOTDEF ) {
466 geop = m_gparent.m_OverlaySettings.CalibrateValue(GribOverlaySettings::GEO_ALTITUDE, geop);
467 m_tcAltitude->SetValue( wxString::Format( _T("%5.0f "), geop ) + m_gparent.m_OverlaySettings.GetUnitSymbol(GribOverlaySettings::GEO_ALTITUDE) );
468 } else
469 m_tcAltitude->SetValue( _("N/A") );
470 }
471
472 // temperature
473 if( RecordArray[Idx_AIR_TEMP + m_Altitude] ) {
474 double temp = RecordArray[Idx_AIR_TEMP + m_Altitude]->
475 getInterpolatedValue( m_cursor_lon, m_cursor_lat, true );
476
477 if( temp != GRIB_NOTDEF ) {
478 temp = m_gparent.m_OverlaySettings.CalibrateValue(GribOverlaySettings::AIR_TEMPERATURE, temp);
479 m_tcTemp->SetValue( wxString::Format( _T("%5.1f "), temp ) + m_gparent.m_OverlaySettings.GetUnitSymbol(GribOverlaySettings::AIR_TEMPERATURE) );
480 } else
481 m_tcTemp->SetValue( _("N/A") );
482 }
483 // relative humidity
484 if( RecordArray[Idx_HUMID_RE + m_Altitude] ) {
485 double humi = RecordArray[Idx_HUMID_RE + m_Altitude]->
486 getInterpolatedValue( m_cursor_lon, m_cursor_lat, true );
487
488 if( humi != GRIB_NOTDEF ) {
489 humi = m_gparent.m_OverlaySettings.CalibrateValue(GribOverlaySettings::REL_HUMIDITY, humi);
490 m_tcRelHumid->SetValue( wxString::Format( _T("%5.0f "), humi ) + m_gparent.m_OverlaySettings.GetUnitSymbol(GribOverlaySettings::REL_HUMIDITY) );
491 } else
492 m_tcRelHumid->SetValue( _("N/A") );
493 }
494 }
495
OnMenuCallBack(wxMouseEvent & event)496 void CursorData::OnMenuCallBack( wxMouseEvent& event )
497 {
498 //populate menu
499 wxMenu* menu = new wxMenu();
500 int id = event.GetId();
501 switch( id ) {
502 case GribOverlaySettings::WIND:
503 MenuAppend( menu, B_ARROWS, _("Barbed Arrows"), id );
504 MenuAppend( menu, ISO_LINE, _("Display Isotachs"), id );
505 MenuAppend( menu, OVERLAY, _("OverlayMap"), id );
506 MenuAppend( menu, NUMBERS, _("Numbers"), id );
507 MenuAppend( menu, PARTICLES, _("Particle Map"), id );
508 break;
509 case GribOverlaySettings::WIND_GUST:
510 MenuAppend( menu, ISO_LINE, _("Display Isotachs"), id );
511 MenuAppend( menu, OVERLAY, _("OverlayMap"), id );
512 MenuAppend( menu, NUMBERS, _("Numbers"), id );
513 break;
514 case GribOverlaySettings::PRESSURE:
515 MenuAppend( menu, ISO_LINE, _("Display Isobars"), id );
516 MenuAppend( menu, ISO_ABBR, _("Abbreviated Isobars Numbers"), id );
517 MenuAppend( menu, NUMBERS, _("Numbers"), id );
518 break;
519 case GribOverlaySettings::AIR_TEMPERATURE:
520 case GribOverlaySettings::SEA_TEMPERATURE:
521 MenuAppend( menu, ISO_LINE, _("Display Isotherms"), id );
522 // fall through
523 case GribOverlaySettings::CLOUD:
524 case GribOverlaySettings::PRECIPITATION:
525 MenuAppend( menu, OVERLAY, _("OverlayMap"), id );
526 MenuAppend( menu, NUMBERS, _("Numbers"), id );
527 break;
528 case GribOverlaySettings::CAPE:
529 MenuAppend( menu, ISO_LINE, _("Display Iso CAPE"), id );
530 MenuAppend( menu, OVERLAY, _("OverlayMap"), id );
531 MenuAppend( menu, NUMBERS, _("Numbers"), id );
532 break;
533 case GribOverlaySettings::COMP_REFL:
534 MenuAppend( menu, ISO_LINE, _("Display Iso Reflectivity"), id );
535 MenuAppend( menu, OVERLAY, _("OverlayMap"), id );
536 MenuAppend( menu, NUMBERS, _("Numbers"), id );
537 break;
538 case GribOverlaySettings::WAVE:
539 MenuAppend( menu, D_ARROWS, _("Direction Arrows"), id );
540 MenuAppend( menu, OVERLAY, _("OverlayMap"), id );
541 MenuAppend( menu, NUMBERS, _("Numbers"), id );
542 break;
543 case GribOverlaySettings::CURRENT:
544 MenuAppend( menu, D_ARROWS, _("Direction Arrows"), id );
545 MenuAppend( menu, OVERLAY, _("OverlayMap"), id );
546 MenuAppend( menu, NUMBERS, _("Numbers"), id );
547 MenuAppend( menu, PARTICLES, _("Particle Map"), id );
548 }
549
550 PopupMenu( menu );
551
552 //apply new config
553 wxwxMenuItemListNode *node = menu->GetMenuItems().GetFirst();
554 while( node ) {
555 wxMenuItem *it = node->GetData();
556 switch( it->GetId() ) {
557 case B_ARROWS:
558 m_gparent.m_OverlaySettings.Settings[id].m_bBarbedArrows = it->IsChecked();
559 break;
560 case ISO_LINE:
561 m_gparent.m_OverlaySettings.Settings[id].m_bIsoBars = it->IsChecked();
562 break;
563 case ISO_ABBR:
564 m_gparent.m_OverlaySettings.Settings[id].m_bAbbrIsoBarsNumbers = it->IsChecked();
565 break;
566 case D_ARROWS:
567 m_gparent.m_OverlaySettings.Settings[id].m_bDirectionArrows = it->IsChecked();
568 break;
569 case OVERLAY:
570 m_gparent.m_OverlaySettings.Settings[id].m_bOverlayMap = it->IsChecked();
571 break;
572 case NUMBERS:
573 m_gparent.m_OverlaySettings.Settings[id].m_bNumbers = it->IsChecked();
574 break;
575 case PARTICLES:
576 m_gparent.m_OverlaySettings.Settings[id].m_bParticles = it->IsChecked();
577 }
578 node = node->GetNext();
579 }
580
581 //if the current parameter type is selected then resolve display conflicts
582 if( m_gparent.InDataPlot(id) && m_gparent.m_bDataPlot[id] )
583 ResolveDisplayConflicts( id );
584
585 //save new config
586 m_gparent.m_OverlaySettings.Write();
587
588 delete menu;
589 }
590
MenuAppend(wxMenu * menu,int id,wxString label,int setting)591 void CursorData::MenuAppend( wxMenu *menu, int id, wxString label, int setting)
592 {
593 wxMenuItem *item = new wxMenuItem(menu, id, label, _T(""), wxITEM_CHECK);
594
595 #ifdef __WXMSW__
596 wxFont *qFont = OCPNGetFont( _("Menu"), 10 );
597 item->SetFont(*qFont);
598 #endif
599
600 menu->Append(item);
601
602 bool check;
603 if( id == B_ARROWS )
604 check = m_gparent.m_OverlaySettings.Settings[setting].m_bBarbedArrows;
605 else if( id == ISO_LINE )
606 check = m_gparent.m_OverlaySettings.Settings[setting].m_bIsoBars;
607 else if( id == ISO_ABBR )
608 check = m_gparent.m_OverlaySettings.Settings[setting].m_bAbbrIsoBarsNumbers;
609 else if( id == D_ARROWS )
610 check = m_gparent.m_OverlaySettings.Settings[setting].m_bDirectionArrows;
611 else if( id == OVERLAY )
612 check = m_gparent.m_OverlaySettings.Settings[setting].m_bOverlayMap;
613 else if( id == NUMBERS )
614 check = m_gparent.m_OverlaySettings.Settings[setting].m_bNumbers;
615 else if( id == PARTICLES )
616 check = m_gparent.m_OverlaySettings.Settings[setting].m_bParticles;
617 else
618 check = false;
619 item->Check( check );
620 }
621
OnMouseEvent(wxMouseEvent & event)622 void CursorData::OnMouseEvent( wxMouseEvent &event )
623 {
624 if( event.RightDown() ) {
625 if( m_DialogStyle >> 1 == ATTACHED ) {
626 wxMouseEvent evt(event);
627 m_gparent.OnMouseEvent( evt );
628 }
629 return;
630 }
631
632 static wxPoint s_gspt;
633 int x, y;
634
635 event.GetPosition( &x, &y );
636 wxPoint spt = wxPoint( x, y );
637 if( event.GetId() != 1000 )
638 spt = ClientToScreen( spt );
639 else
640 spt = GetParent()->ClientToScreen( spt );
641
642 #ifdef __WXOSX__
643 if (!m_bLeftDown && event.LeftIsDown())
644 {
645 m_bLeftDown = true;
646 s_gspt = spt;
647 if (!HasCapture()) CaptureMouse();
648 }
649 else if (m_bLeftDown && !event.LeftIsDown())
650 {
651 // GetParent()->Move( GetParent()->GetPosition() );
652 m_bLeftDown = false;
653 if (HasCapture()) ReleaseMouse();
654 }
655 #else
656
657 if( event.LeftDown() ) {
658 s_gspt = spt;
659 if (!HasCapture()) CaptureMouse();
660 }
661
662 if( event.LeftUp() ) {
663 //GetParent()->Move( GetParent()->GetPosition() );
664 if( HasCapture() ) ReleaseMouse();
665 }
666 #endif
667
668 if( event.Dragging() ) {
669
670 wxPoint par_pos_old = GetParent()->GetPosition();
671
672 wxPoint par_pos = par_pos_old;
673 par_pos.x += spt.x - s_gspt.x;
674 par_pos.y += spt.y - s_gspt.y;
675
676 wxPoint pos_in_parent = GetOCPNCanvasWindow()->ScreenToClient( par_pos );
677 wxPoint pos_in_parent_old = GetOCPNCanvasWindow()->ScreenToClient( par_pos_old );
678
679 // X
680 if( pos_in_parent.x < pos_in_parent_old.x ) { // moving left
681 if( pos_in_parent.x < 10 ) {
682 pos_in_parent.x = 0;
683 }
684 } else
685 if( pos_in_parent.x > pos_in_parent_old.x ) { // moving right
686 int max_right = GetOCPNCanvasWindow()->GetClientSize().x - GetParent()->GetSize().x;
687 if( pos_in_parent.x > ( max_right - 10 ) ) {
688 pos_in_parent.x = max_right;
689 }
690 }
691
692 // Y
693 if( pos_in_parent.y < pos_in_parent_old.y ) { // moving up
694 if( pos_in_parent.y < 10 ) {
695 pos_in_parent.y = 0;
696 }
697 } else
698 if( pos_in_parent.y > pos_in_parent_old.y ) { // moving dow
699 int max_down = GetOCPNCanvasWindow()->GetClientSize().y - GetParent()->GetSize().y;
700 if( pos_in_parent.y > ( max_down - 10 ) ) {
701 pos_in_parent.y = max_down;
702 }
703 }
704
705 wxPoint final_pos = GetOCPNCanvasWindow()->ClientToScreen( pos_in_parent );
706
707 GetParent()->Move( final_pos );
708
709 s_gspt = spt;
710
711 }
712 }
713