1 /******************************************************************************
2 *
3 * Project: OpenCPN
4 * Purpose: OpenCPN Main wxWidgets Program
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 "wx/wxprec.h"
28 #ifndef WX_PRECOMP
29 #include "wx/wx.h"
30 #endif //precompiled headers
31 #include "ocpn_types.h"
32 #include "compasswin.h"
33 #include "chcanv.h"
34 #include "styles.h"
35 #include "wx28compat.h"
36
37 BEGIN_EVENT_TABLE(ocpnFloatingCompassWindow, wxWindow) EVT_PAINT ( ocpnFloatingCompassWindow::OnPaint )
38 EVT_LEFT_DOWN ( ocpnFloatingCompassWindow::MouseEvent )
39 END_EVENT_TABLE()
40
41 extern ocpnStyle::StyleManager* g_StyleManager;
42 extern bool bGPSValid;
43 extern bool g_bSatValid;
44 extern int g_SatsInView;
45 extern bool g_bCourseUp;
46 extern bool g_bskew_comp;
47 extern MyFrame *gFrame;
48
ocpnFloatingCompassWindow(wxWindow * parent)49 ocpnFloatingCompassWindow::ocpnFloatingCompassWindow( wxWindow *parent )
50 {
51 m_pparent = parent;
52 long wstyle = wxNO_BORDER | wxFRAME_NO_TASKBAR | wxFRAME_SHAPED;
53 #ifdef __WXMAC__
54 wstyle |= wxSTAY_ON_TOP;
55 #endif
56 wxDialog::Create( parent, -1, _T(""), wxPoint( 0, 0 ), wxSize( -1, -1 ), wstyle );
57
58 ocpnStyle::Style* style = g_StyleManager->GetCurrentStyle();
59 _img_compass = style->GetIcon( _T("CompassRose") );
60 _img_gpsRed = style->GetIcon( _T("gpsRed") );
61
62 m_rose_angle = -999; // force a refresh when first used
63
64 m_pStatBoxToolStaticBmp = NULL;
65
66 m_scale = 1.0;
67 SetSize(
68 m_scale * ( ( _img_compass.GetWidth() + _img_gpsRed.GetWidth() ) + style->GetCompassLeftMargin() * 2
69 + style->GetToolSeparation()),
70 m_scale * (_img_compass.GetHeight() + style->GetCompassTopMargin() + style->GetCompassBottomMargin()) );
71
72 m_xoffset = style->GetCompassXOffset();
73 m_yoffset = style->GetCompassYOffset();
74 }
75
~ocpnFloatingCompassWindow()76 ocpnFloatingCompassWindow::~ocpnFloatingCompassWindow()
77 {
78 delete m_pStatBoxToolStaticBmp;
79 }
80
OnPaint(wxPaintEvent & event)81 void ocpnFloatingCompassWindow::OnPaint( wxPaintEvent& event )
82 {
83 int width, height;
84 GetClientSize( &width, &height );
85 wxPaintDC dc( this );
86
87 dc.DrawBitmap( m_StatBmp, 0, 0, false );
88 }
89
MouseEvent(wxMouseEvent & event)90 void ocpnFloatingCompassWindow::MouseEvent( wxMouseEvent& event )
91 {
92 gFrame->ToggleCourseUp();
93 }
94
SetColorScheme(ColorScheme cs)95 void ocpnFloatingCompassWindow::SetColorScheme( ColorScheme cs )
96 {
97 wxColour back_color = GetGlobalColor( _T("GREY2") );
98
99 // Set background
100 SetBackgroundColour( back_color );
101 ClearBackground();
102
103 UpdateStatus( true );
104
105 }
106
UpdateStatus(bool bnew)107 void ocpnFloatingCompassWindow::UpdateStatus( bool bnew )
108 {
109 if( bnew ) m_lastgpsIconName.Clear(); // force an update to occur
110
111 wxBitmap statbmp = CreateBmp( bnew );
112 if( statbmp.IsOk() ) m_StatBmp = statbmp;
113
114 Show();
115 Refresh( false );
116 }
117
SetScaleFactor(float factor)118 void ocpnFloatingCompassWindow::SetScaleFactor( float factor)
119 {
120 // qDebug() << m_scale << factor;
121 ocpnStyle::Style* style = g_StyleManager->GetCurrentStyle();
122
123 if(factor > 0.1)
124 m_scale = factor;
125 else
126 m_scale = 1.0;
127
128 SetSize(
129 m_scale * ( ( _img_compass.GetWidth() + _img_gpsRed.GetWidth() ) + style->GetCompassLeftMargin() * 2
130 + style->GetToolSeparation()),
131 m_scale * (_img_compass.GetHeight() + style->GetCompassTopMargin() + style->GetCompassBottomMargin()) );
132
133 }
134
135
CreateBmp(bool newColorScheme)136 wxBitmap ocpnFloatingCompassWindow::CreateBmp( bool newColorScheme )
137 {
138 wxString gpsIconName;
139 ocpnStyle::Style* style = g_StyleManager->GetCurrentStyle();
140
141 // In order to draw a horizontal compass window when the toolbar is vertical, we
142 // need to save away the sizes and backgrounds for the two icons.
143
144 static wxBitmap compassBg, gpsBg;
145 static wxSize toolsize;
146 static int topmargin, leftmargin, radius;
147
148 if( ! compassBg.IsOk() || newColorScheme ) {
149 int orient = style->GetOrientation();
150 style->SetOrientation( wxTB_HORIZONTAL );
151 if( style->HasBackground() ) {
152 compassBg = style->GetNormalBG();
153 style->DrawToolbarLineStart( compassBg );
154 compassBg = style->SetBitmapBrightness( compassBg );
155 gpsBg = style->GetNormalBG();
156 style->DrawToolbarLineEnd( gpsBg );
157 gpsBg = style->SetBitmapBrightness( gpsBg );
158
159 if(fabs(m_scale-1.0) > 0.1){
160 wxImage bg_img = compassBg.ConvertToImage();
161 bg_img.Rescale(compassBg.GetWidth() * m_scale, compassBg.GetHeight() *m_scale, wxIMAGE_QUALITY_NORMAL);
162 compassBg = wxBitmap( bg_img );
163
164 bg_img = gpsBg.ConvertToImage();
165 bg_img.Rescale(gpsBg.GetWidth() * m_scale, gpsBg.GetHeight() *m_scale, wxIMAGE_QUALITY_NORMAL);
166 gpsBg = wxBitmap( bg_img );
167 }
168 }
169
170 leftmargin = style->GetCompassLeftMargin();
171 topmargin = style->GetCompassTopMargin();
172 toolsize = style->GetToolSize();
173 toolsize.x *= 2;
174 radius = style->GetCompassCornerRadius();
175
176 if( orient ) style->SetOrientation( wxTB_VERTICAL );
177 }
178
179 bool b_need_refresh = false;
180
181 if( bGPSValid ) {
182 if( g_bSatValid ) {
183 gpsIconName = _T("gps3Bar");
184 if( g_SatsInView <= 8 ) gpsIconName = _T("gps2Bar");
185 if( g_SatsInView <= 4 ) gpsIconName = _T("gps1Bar");
186 if( g_SatsInView < 0 ) gpsIconName = _T("gpsGry");
187
188 } else
189 gpsIconName = _T("gpsGrn");
190 } else
191 gpsIconName = _T("gpsRed");
192
193 if( m_lastgpsIconName != gpsIconName ) b_need_refresh = true;
194
195 double rose_angle = -999.;
196
197 if( ( fabs( cc1->GetVPRotation() ) > .01 ) || ( fabs( cc1->GetVPSkew() ) > .01 ) ) {
198 rose_angle = -cc1->GetVPRotation();
199
200 if( !g_bCourseUp && !g_bskew_comp )
201 rose_angle -= cc1->GetVPSkew();
202
203 } else
204 rose_angle = 0.;
205
206 if( fabs( m_rose_angle - rose_angle ) > .1 )
207 b_need_refresh = true;
208
209 if( b_need_refresh ) {
210 wxBitmap StatBmp;
211
212 StatBmp.Create(
213 m_scale * ( ( _img_compass.GetWidth() + _img_gpsRed.GetWidth() ) + style->GetCompassLeftMargin() * 2
214 + style->GetToolSeparation()),
215 m_scale * (_img_compass.GetHeight() + style->GetCompassTopMargin() + style->GetCompassBottomMargin()) );
216
217 if( StatBmp.IsOk() ) {
218
219 wxMemoryDC mdc;
220 mdc.SelectObject( StatBmp );
221 mdc.SetBackground( wxBrush( GetGlobalColor( _T("GREY2") ), wxBRUSHSTYLE_SOLID ) );
222 mdc.Clear();
223
224 mdc.SetPen( wxPen( GetGlobalColor( _T("UITX1") ), 1 ) );
225 mdc.SetBrush( wxBrush( GetGlobalColor( _T("UITX1") ), wxBRUSHSTYLE_TRANSPARENT ) );
226
227 mdc.DrawRoundedRectangle( 0, 0, StatBmp.GetWidth(), StatBmp.GetHeight(),
228 m_scale * style->GetCompassCornerRadius() );
229
230 wxPoint offset( style->GetCompassLeftMargin(), style->GetCompassTopMargin() );
231
232 wxBitmap iconBm;
233
234
235 // Build Compass Rose, rotated...
236 wxBitmap BMPRose;
237 wxPoint after_rotate;
238
239 if( g_bCourseUp )
240 BMPRose = style->GetIcon( _T("CompassRose") );
241 else
242 BMPRose = style->GetIcon( _T("CompassRoseBlue") );
243
244 if( ( fabs( cc1->GetVPRotation() ) > .01 ) || ( fabs( cc1->GetVPSkew() ) > .01 ) || (fabs(m_scale-1.0) > 0.1) ) {
245 int width = BMPRose.GetWidth() * m_scale;
246 int height = BMPRose.GetHeight() * m_scale;
247
248 wxImage rose_img = BMPRose.ConvertToImage();
249
250 if(fabs(m_scale-1.0) > 0.1)
251 rose_img.Rescale(width, height, wxIMAGE_QUALITY_NORMAL);
252
253
254 if(fabs(rose_angle) > 0.01){
255 wxPoint rot_ctr( width / 2, height / 2 );
256 wxImage rot_image = rose_img.Rotate( rose_angle, rot_ctr, true, &after_rotate );
257 BMPRose = wxBitmap( rot_image ).GetSubBitmap( wxRect( -after_rotate.x, -after_rotate.y, width, height) );
258 }
259 else
260 BMPRose = wxBitmap( rose_img );
261
262 }
263
264
265 if( style->HasBackground() ) {
266 iconBm = MergeBitmaps( compassBg, BMPRose, wxSize( 0, 0 ) );
267 } else {
268 iconBm = BMPRose;
269 }
270
271 mdc.DrawBitmap( iconBm, offset );
272 offset.x += iconBm.GetWidth();
273
274 m_rose_angle = rose_angle;
275
276 // GPS Icon
277 wxBitmap gicon = style->GetIcon( gpsIconName );
278 if(fabs(m_scale-1.0) > 0.1){
279 int width = gicon.GetWidth() * m_scale;
280 int height = gicon.GetHeight() * m_scale;
281
282 wxImage gps_img = gicon.ConvertToImage();
283 gps_img.Rescale(width, height, wxIMAGE_QUALITY_NORMAL);
284 gicon = wxBitmap( gps_img );
285 }
286
287 if( style->HasBackground() ) {
288 iconBm = MergeBitmaps( gpsBg, gicon, wxSize( 0, 0 ) );
289 } else {
290 iconBm = gicon;
291 }
292 mdc.DrawBitmap( iconBm, offset );
293 mdc.SelectObject( wxNullBitmap );
294 m_lastgpsIconName = gpsIconName;
295 }
296
297 #if !defined(__WXMAC__) && !defined(__OCPN__ANDROID__)
298 if( style->marginsInvisible ) {
299 m_MaskBmp = wxBitmap( StatBmp.GetWidth(), StatBmp.GetHeight() );
300 wxMemoryDC sdc( m_MaskBmp );
301 sdc.SetBackground( *wxWHITE_BRUSH );
302 sdc.Clear();
303 sdc.SetBrush( *wxBLACK_BRUSH );
304 sdc.SetPen( *wxBLACK_PEN );
305 sdc.DrawRoundedRectangle( wxPoint( leftmargin, topmargin ), toolsize, radius );
306 sdc.SelectObject( wxNullBitmap );
307 SetShape( wxRegion( m_MaskBmp, *wxWHITE, 0 ) );
308 }
309 else if(radius) {
310 m_MaskBmp = wxBitmap( GetSize().x, GetSize().y );
311 wxMemoryDC sdc( m_MaskBmp );
312 sdc.SetBackground( *wxWHITE_BRUSH );
313 sdc.Clear();
314 sdc.SetBrush( *wxBLACK_BRUSH );
315 sdc.SetPen( *wxBLACK_PEN );
316 sdc.DrawRoundedRectangle( 0, 0, m_MaskBmp.GetWidth(), m_MaskBmp.GetHeight(), radius );
317 sdc.SelectObject( wxNullBitmap );
318 SetShape( wxRegion( m_MaskBmp, *wxWHITE, 0 ) );
319 }
320 #endif
321
322 return StatBmp;
323 }
324
325 else
326 return wxNullBitmap;
327 }
328
329