1 /******************************************************************************
2  *
3  * Project:  OpenCPN
4  *
5  ***************************************************************************
6  *   Copyright (C) 2013 by David S. Register                               *
7  *                                                                         *
8  *   This program is free software; you can redistribute it and/or modify  *
9  *   it under the terms of the GNU General Public License as published by  *
10  *   the Free Software Foundation; either version 2 of the License, or     *
11  *   (at your option) any later version.                                   *
12  *                                                                         *
13  *   This program is distributed in the hope that it will be useful,       *
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
16  *   GNU General Public License for more details.                          *
17  *                                                                         *
18  *   You should have received a copy of the GNU General Public License     *
19  *   along with this program; if not, write to the                         *
20  *   Free Software Foundation, Inc.,                                       *
21  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,  USA.         *
22  ***************************************************************************
23  */
24 
25 #include "wx/wxprec.h"
26 
27 #include <wx/bitmap.h>
28 #include <wx/dcmemory.h>
29 #include <wx/dcscreen.h>
30 
31 #include "ocpndc.h"
32 #include "RolloverWin.h"
33 #include "timers.h"
34 #include "chart1.h"
35 #include "navutil.h"
36 #include "FontMgr.h"
37 #include "ocpn_plugin.h"
38 
39 #ifdef ocpnUSE_GL
40 #include "glChartCanvas.h"
41 #include "chcanv.h"
42 #endif
43 
44 
45 extern bool             g_bopengl;
46 #ifdef ocpnUSE_GL
47 extern GLenum       g_texture_rectangle_format;
48 #endif
49 
BEGIN_EVENT_TABLE(RolloverWin,wxWindow)50 BEGIN_EVENT_TABLE(RolloverWin, wxWindow) EVT_PAINT(RolloverWin::OnPaint)
51     EVT_TIMER(ROLLOVER_TIMER, RolloverWin::OnTimer)
52     EVT_MOUSE_EVENTS ( RolloverWin::OnMouseEvent )
53 
54 END_EVENT_TABLE()
55 
56 // Define a constructor
57 RolloverWin::RolloverWin( wxWindow *parent, int timeout, bool maincanvas ) :
58 wxWindow( parent, wxID_ANY, wxPoint( 0, 0 ), wxSize( 1, 1 ), wxNO_BORDER ),
59     m_bmaincanvas(maincanvas)
60 {
61     m_pbm = NULL;
62 
63     m_timer_timeout.SetOwner( this, ROLLOVER_TIMER );
64     m_timeout_sec = timeout;
65     m_mmouse_propogate = 0;
66     isActive = false;
67     m_plabelFont = NULL;
68     m_texture = 0;
69     Hide();
70 }
71 
~RolloverWin()72 RolloverWin::~RolloverWin()
73 {
74     delete m_pbm;
75     glDeleteTextures(1, &m_texture);
76 
77 }
OnTimer(wxTimerEvent & event)78 void RolloverWin::OnTimer( wxTimerEvent& event )
79 {
80     if( IsActive() ){
81         Hide();
82         GetParent()->Refresh( true );
83         IsActive(false);
84     }
85 }
86 
OnMouseEvent(wxMouseEvent & event)87 void RolloverWin::OnMouseEvent( wxMouseEvent& event )
88 {
89     //    If directed, send mouse events up the window family tree,
90     //    until some parent window does NOT call event.Skip()
91     if( m_mmouse_propogate ) {
92         event.ResumePropagation( m_mmouse_propogate );
93         event.Skip();
94     }
95 }
96 
97 
SetBitmap(int rollover)98 void RolloverWin::SetBitmap( int rollover )
99 {
100     wxMemoryDC mdc;
101     delete m_pbm;
102     m_pbm = new wxBitmap( m_size.x, m_size.y );
103     mdc.SelectObject( *m_pbm );
104 
105     mdc.SetBackground( wxBrush( GetGlobalColor( _T ( "YELO1" ) ) ) );
106     mdc.Clear();
107 #ifdef ocpnUSE_GL
108     bool usegl = g_bopengl && g_texture_rectangle_format;
109 
110 #ifdef __WXOSX__
111     usegl = false;
112 #endif
113 
114 #else
115     bool usegl = false;
116 #endif
117     if(!usegl) {
118         if(m_bmaincanvas){
119             wxDC* cdc = new wxScreenDC();
120             int cpx = 0, cpy = 0;
121             GetParent()->ClientToScreen(&cpx, &cpy);
122             mdc.Blit( 0, 0, m_size.x, m_size.y, cdc,m_position.x + cpx, m_position.y + cpy);
123             delete cdc;
124         }
125     }
126 
127     ocpnDC dc( mdc );
128 
129     wxString text;
130     double radius = 6.0;
131     switch( rollover ) {
132         case AIS_ROLLOVER: text = _("AISRollover");   break;
133         case TC_ROLLOVER:  text = _("TideCurrentGraphRollover"), radius = 0; break;
134         default:
135         case LEG_ROLLOVER: text = _("RouteLegInfoRollover");  break;
136     }
137 
138     if(m_bmaincanvas)
139         AlphaBlending( dc, 0, 0, m_size.x, m_size.y, radius, GetGlobalColor( _T ( "YELO1" ) ), 172 );
140 
141     mdc.SetTextForeground( FontMgr::Get().GetFontColor( text ) );
142 
143     if(m_plabelFont && m_plabelFont->IsOk()) {
144 
145         //    Draw the text
146         mdc.SetFont( *m_plabelFont );
147 
148         mdc.DrawLabel( m_string, wxRect( 0, 0, m_size.x, m_size.y ), wxALIGN_CENTRE_HORIZONTAL | wxALIGN_CENTRE_VERTICAL);
149     }
150 
151     mdc.SelectObject( wxNullBitmap );
152 
153     SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
154 
155     #ifdef ocpnUSE_GL
156     if(usegl) {
157         if(!m_texture) {
158             glGenTextures( 1, &m_texture );
159             wxString msg;
160             msg.Printf(_T("New texture  %d"), m_texture);
161             wxLogMessage(msg);
162 
163             glBindTexture( g_texture_rectangle_format, m_texture );
164             glTexParameterf( g_texture_rectangle_format, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
165             glTexParameteri( g_texture_rectangle_format, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
166             glTexParameteri( g_texture_rectangle_format, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
167             glTexParameteri( g_texture_rectangle_format, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
168 
169         } else
170             glBindTexture( g_texture_rectangle_format, m_texture );
171 
172         wxString msg;
173         msg.Printf(_T("Render texture  %d"), m_texture);
174         wxLogMessage(msg);
175 
176         // make texture data
177         wxImage image = m_pbm->ConvertToImage();
178 
179         unsigned char *d = image.GetData();
180         unsigned char *e = new unsigned char[4*m_size.x*m_size.y];
181         for(int y = 0; y<m_size.y; y++)
182             for(int x = 0; x<m_size.x; x++) {
183                 int i = y * m_size.x + x;
184                 memcpy(e+4*i, d+3*i, 3);
185                 e[4*i+3] = 255 - d[3*i+2];
186             }
187         glTexImage2D( g_texture_rectangle_format, 0, GL_RGBA,
188                       m_size.x, m_size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, e );
189         delete [] e;
190         glDisable(g_texture_rectangle_format);
191         glDisable(GL_BLEND);
192 
193     }
194     #endif
195 
196     // Retrigger the auto timeout
197     if( m_timeout_sec > 0 ){
198         m_timer_timeout.Start( m_timeout_sec * 1000, wxTIMER_ONE_SHOT );
199     }
200 }
201 
202 
203 #if 0
204 
205 void RolloverWin::SetBitmap( int rollover )
206 {
207     wxMemoryDC mdc;
208     delete m_pbm;
209     m_pbm = new wxBitmap( m_size.x, m_size.y );
210     mdc.SelectObject( *m_pbm );
211 
212     int usegl = g_bopengl &&
213 #ifdef ocpnUSE_GL
214         g_texture_rectangle_format &&
215 #endif
216         m_bmaincanvas;
217     if(!usegl) {
218         wxDC* cdc = new wxScreenDC();
219         int cpx = 0, cpy = 0;
220         GetParent()->ClientToScreen(&cpx, &cpy);
221         mdc.Blit( 0, 0, m_size.x, m_size.y, cdc,
222                   m_position.x + cpx, m_position.y + cpy);
223         delete cdc;
224     } else
225         mdc.Clear();
226 
227     ocpnDC dc( mdc );
228 
229     wxString text;
230     double radius = 6.0;
231     switch( rollover ) {
232     case AIS_ROLLOVER: text = _("AISRollover");   break;
233     case TC_ROLLOVER:  text = _("TideCurrentGraphRollover"), radius = 0; break;
234     default:
235     case LEG_ROLLOVER: text = _("RouteLegInfoRollover");  break;
236     }
237 
238     AlphaBlending( dc, 0, 0, m_size.x, m_size.y, radius,
239                    GetGlobalColor( _T ( "YELO1" ) ), usegl ? 255 : 172 );
240     mdc.SetTextForeground( FontMgr::Get().GetFontColor( text ) );
241 
242     if(m_plabelFont && m_plabelFont->IsOk()) {
243 
244     //    Draw the text
245         mdc.SetFont( *m_plabelFont );
246 
247         mdc.DrawLabel( m_string, wxRect( 0, 0, m_size.x, m_size.y ), wxALIGN_CENTRE_HORIZONTAL | wxALIGN_CENTRE_VERTICAL);
248     }
249 
250     SetSize( m_position.x, m_position.y, m_size.x, m_size.y );   // Assumes a nominal 32 x 32 cursor
251 
252 #ifdef ocpnUSE_GL
253     if(usegl) {
254         if(!m_texture) {
255             glGenTextures( 1, &m_texture );
256             glBindTexture( g_texture_rectangle_format, m_texture );
257             glTexParameterf( g_texture_rectangle_format, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
258             glTexParameteri( g_texture_rectangle_format, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
259         } else
260             glBindTexture( g_texture_rectangle_format, m_texture );
261         mdc.SelectObject( wxNullBitmap );
262 
263         // make texture data
264         wxImage image = m_pbm->ConvertToImage();
265 
266         unsigned char *d = image.GetData();
267         unsigned char *e = new unsigned char[4*m_size.x*m_size.y];
268         for(int y = 0; y<m_size.y; y++)
269             for(int x = 0; x<m_size.x; x++) {
270                 int i = y * m_size.x + x;
271                 memcpy(e+4*i, d+3*i, 3);
272                 e[4*i+3] = 255 - d[3*i+2];
273             }
274         glTexImage2D( g_texture_rectangle_format, 0, GL_RGBA,
275                       m_size.x, m_size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, e );
276         delete [] e;
277     }
278 #endif
279 
280     // Retrigger the auto timeout
281     if( m_timeout_sec > 0 ) m_timer_timeout.Start( m_timeout_sec * 1000, wxTIMER_ONE_SHOT );
282 }
283 
284 #endif
285 
OnPaint(wxPaintEvent & event)286 void RolloverWin::OnPaint( wxPaintEvent& event )
287 {
288     int width, height;
289     GetClientSize( &width, &height );
290     wxPaintDC dc( this );
291 
292     if( m_string.Len() ) {
293         wxMemoryDC mdc;
294         mdc.SelectObject( *m_pbm );
295         dc.Blit( 0, 0, width, height, &mdc, 0, 0 );
296     }
297 }
298 
Draw(ocpnDC & dc)299 void RolloverWin::Draw(ocpnDC &dc)
300 {
301     if(!IsActive())
302         return;
303 #ifdef ocpnUSE_GL
304 //#ifndef __WXOSX__
305     if(g_bopengl && m_texture) {
306         wxString msg;
307         msg.Printf(_T("Draw texture  %d"), m_texture);
308         wxLogMessage(msg);
309 
310         glEnable(g_texture_rectangle_format);
311         glBindTexture( g_texture_rectangle_format, m_texture );
312         glEnable(GL_BLEND);
313 
314         int x0 = m_position.x, x1 = x0 + m_size.x;
315         int y0 = m_position.y, y1 = y0 + m_size.y;
316         float tx, ty;
317         if( GL_TEXTURE_RECTANGLE_ARB == g_texture_rectangle_format )
318             tx = m_size.x, ty = m_size.y;
319         else
320             tx = ty = 1;
321 
322 #ifndef USE_ANDROID_GLES2
323 
324         glColor3f(1, 1, 1);
325         glBegin(GL_QUADS);
326         glTexCoord2f(0,  0);  glVertex2i(x0, y0);
327         glTexCoord2f(tx, 0);  glVertex2i(x1, y0);
328         glTexCoord2f(tx, ty); glVertex2i(x1, y1);
329         glTexCoord2f(0,  ty); glVertex2i(x0, y1);
330         glEnd();
331 #else
332         float coords[8];
333         float uv[8];
334 
335         //normal uv
336         uv[0] = 0; uv[1] = 0; uv[2] = tx; uv[3] = 0;
337         uv[4] = tx; uv[5] = ty; uv[6] = 0; uv[7] = ty;
338 
339         // pixels
340         coords[0] = x0; coords[1] = y0; coords[2] = x1; coords[3] = y0;
341         coords[4] = x1; coords[5] = y1; coords[6] = x0; coords[7] = y1;
342 
343         ChartCanvas *pCanvas = wxDynamicCast(GetParent(), ChartCanvas);
344         if(pCanvas)
345             pCanvas->GetglCanvas()->RenderTextures(coords, uv, 4, pCanvas->GetpVP());
346 
347 #endif
348         glDisable(g_texture_rectangle_format);
349         glDisable(GL_BLEND);
350     } else
351 //#endif
352 #endif
353     dc.DrawBitmap( *m_pbm, m_position.x, m_position.y, false );
354 }
355 
SetBestPosition(int x,int y,int off_x,int off_y,int rollover,wxSize parent_size)356 void RolloverWin::SetBestPosition( int x, int y, int off_x, int off_y, int rollover,
357                                    wxSize parent_size )
358 {
359     int h, w;
360 
361     wxFont *dFont;
362     switch( rollover ) {
363 
364     case AIS_ROLLOVER:
365         dFont = FontMgr::Get().GetFont( _("AISRollover") );
366         break;
367 
368     case TC_ROLLOVER:
369         dFont = FontMgr::Get().GetFont( _("TideCurrentGraphRollover") );
370         break;
371 
372     default:
373     case LEG_ROLLOVER:
374         dFont = FontMgr::Get().GetFont( _("RouteLegInfoRollover") );
375         break;
376 
377     }
378 
379     int font_size = wxMax(8, dFont->GetPointSize());
380     m_plabelFont = FontMgr::Get().FindOrCreateFont( font_size, dFont->GetFamily(),
381                          dFont->GetStyle(), dFont->GetWeight(), false, dFont->GetFaceName() );
382 
383     if(m_plabelFont && m_plabelFont->IsOk()) {
384 #ifdef __WXMAC__
385         wxScreenDC sdc;
386         sdc.SetFont(*m_plabelFont);
387         sdc.GetMultiLineTextExtent(m_string, &w, &h, NULL, m_plabelFont);
388 #else
389         wxClientDC cdc( GetParent() );
390         cdc.SetFont(*m_plabelFont);
391         cdc.GetMultiLineTextExtent( m_string, &w, &h, NULL, m_plabelFont );
392 #endif
393     }
394     else {
395         w = 10;
396         h = 10;
397     }
398 
399     m_size.x = w + 8;
400     m_size.y = h + 8;
401 
402     int xp, yp;
403     if( ( x + off_x + m_size.x ) > parent_size.x ) {
404         xp = x - ( off_x / 2 ) - m_size.x;
405         xp = wxMax(0, xp);
406     } else
407         xp = x + off_x;
408 
409     if( ( y + off_y + m_size.y ) > parent_size.y ) {
410         yp = y - ( off_y / 2 ) - m_size.y;
411     } else
412         yp = y + off_y;
413 
414     SetPosition( wxPoint( xp, yp ) );
415 
416 }
417 
418