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