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