1 /******************************************************************************
2 *
3 * Project: OpenCPN
4 * Purpose: MUI Control Bar
5 * Author: David Register
6 *
7 ***************************************************************************
8 * Copyright (C) 2018 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 */
28
29 #include "wx/wxprec.h"
30
31 #ifndef WX_PRECOMP
32 #include "wx/wx.h"
33 #endif //precompiled headers
34
35 #include <wx/statline.h>
36
37 #include "dychart.h"
38
39 #include "chcanv.h"
40 #include "MUIBar.h"
41 #include "OCPNPlatform.h"
42 #include "CanvasOptions.h"
43 #include "styles.h"
44 #include "navutil.h"
45
46 #ifdef ocpnUSE_SVG
47 #include "wxSVG/svg.h"
48 #endif // ocpnUSE_SVG
49
50 #ifdef __OCPN__ANDROID__
51 #include "androidUTIL.h"
52 #include "qdebug.h"
53 #endif
54
55
56
57 //------------------------------------------------------------------------------
58 // External Static Storage
59 //------------------------------------------------------------------------------
60
61 extern OCPNPlatform *g_Platform;
62 extern ChartCanvas *g_focusCanvas;
63 extern ocpnStyle::StyleManager* g_StyleManager;
64 extern bool g_bShowMuiZoomButtons;
65
66 // Helper utilities
LoadSVG(const wxString filename,unsigned int width,unsigned int height)67 static wxBitmap LoadSVG( const wxString filename, unsigned int width, unsigned int height )
68 {
69 #ifdef ocpnUSE_SVG
70 #ifdef __OCPN__ANDROID__
71 return loadAndroidSVG( filename, width, height );
72 #else
73 wxSVGDocument svgDoc;
74 if( svgDoc.Load(filename) )
75 return wxBitmap( svgDoc.Render( width, height, NULL, true, true ) );
76 else
77 return wxBitmap(width, height);
78 #endif
79 #else
80 return wxBitmap(width, height);
81 #endif // ocpnUSE_SVG
82 }
83
84 double getValue(int animationType, double t);
85
86
87 // Helper classes
88
89
90 #define ID_SCALE_CANCEL 8301
91 #define ID_SCALE_OK 8302
92 #define ID_SCALECTRL 8303
93
94 class SetScaleDialog: public wxDialog
95 {
96 DECLARE_EVENT_TABLE()
97
98 public:
99 /// Constructors
100 SetScaleDialog( );
101 SetScaleDialog( wxWindow* parent, wxWindowID id = SYMBOL_GOTOPOS_IDNAME,
102 const wxString& caption = _("Set scale"),
103 const wxPoint& pos = wxDefaultPosition,
104 const wxSize& size = wxDefaultSize,
105 long style = wxDEFAULT_DIALOG_STYLE );
106
107 ~SetScaleDialog();
108
109 /// Creation
110 bool Create( wxWindow* parent, wxWindowID id = wxID_ANY,
111 const wxString& caption = _("Set scale"),
112 const wxPoint& pos = wxDefaultPosition,
113 const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE );
114
115 void SetColorScheme(ColorScheme cs);
116
117 void CreateControls();
118
119 void OnSetScaleCancelClick( wxCommandEvent& event );
120 void OnSetScaleOKClick( wxCommandEvent& event );
121
122 /// Should we show tooltips?
123
124 wxTextCtrl* m_ScaleCtl;
125 wxButton* m_CancelButton;
126 wxButton* m_OKButton;
127
128 };
129
BEGIN_EVENT_TABLE(SetScaleDialog,wxDialog)130 BEGIN_EVENT_TABLE( SetScaleDialog, wxDialog )
131 EVT_BUTTON( ID_GOTOPOS_CANCEL, SetScaleDialog::OnSetScaleCancelClick )
132 EVT_BUTTON( ID_GOTOPOS_OK, SetScaleDialog::OnSetScaleOKClick )
133 END_EVENT_TABLE()
134
135 /*!
136 * SetScaleDialog constructors
137 */
138
139 SetScaleDialog::SetScaleDialog()
140 {
141 }
142
SetScaleDialog(wxWindow * parent,wxWindowID id,const wxString & caption,const wxPoint & pos,const wxSize & size,long style)143 SetScaleDialog::SetScaleDialog( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
144 {
145 long wstyle = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxFRAME_FLOAT_ON_PARENT;
146
147 Create( parent, id, caption, pos, size, wstyle );
148
149 }
150
~SetScaleDialog()151 SetScaleDialog::~SetScaleDialog()
152 {
153 }
154
155 /*!
156 * SetScaleDialog creator
157 */
158
Create(wxWindow * parent,wxWindowID id,const wxString & caption,const wxPoint & pos,const wxSize & size,long style)159 bool SetScaleDialog::Create( wxWindow* parent, wxWindowID id, const wxString& caption,
160 const wxPoint& pos, const wxSize& size, long style )
161 {
162 SetExtraStyle( GetExtraStyle() | wxWS_EX_BLOCK_EVENTS );
163 wxDialog::Create( parent, id, caption, pos, size, style );
164
165 CreateControls();
166 GetSizer()->SetSizeHints( this );
167 Centre();
168
169 return TRUE;
170 }
171
172 /*!
173 * Control creation for GoToPositionDialog
174 */
175
CreateControls()176 void SetScaleDialog::CreateControls()
177 {
178 SetScaleDialog* itemDialog1 = this;
179
180 wxBoxSizer* itemBoxSizer2 = new wxBoxSizer( wxVERTICAL );
181 itemDialog1->SetSizer( itemBoxSizer2 );
182
183 wxStaticBox* itemStaticBoxSizer4Static = new wxStaticBox( itemDialog1, wxID_ANY,
184 _("Chart Scale") );
185
186 wxStaticBoxSizer* itemStaticBoxSizer4 = new wxStaticBoxSizer( itemStaticBoxSizer4Static,
187 wxVERTICAL );
188 itemBoxSizer2->Add( itemStaticBoxSizer4, 0, wxEXPAND | wxALL, 5 );
189
190 wxStaticText* itemStaticText5 = new wxStaticText( itemDialog1, wxID_STATIC, _(""),
191 wxDefaultPosition, wxDefaultSize, 0 );
192 itemStaticBoxSizer4->Add( itemStaticText5, 0,
193 wxALIGN_LEFT | wxLEFT | wxRIGHT | wxTOP, 5 );
194
195 m_ScaleCtl = new wxTextCtrl( itemDialog1, ID_SCALECTRL, _T(""), wxDefaultPosition, wxSize( 180, -1 ), 0 );
196 itemStaticBoxSizer4->Add( m_ScaleCtl, 0, wxALIGN_LEFT | wxLEFT | wxRIGHT | wxBOTTOM | wxEXPAND, 5 );
197
198 wxBoxSizer* itemBoxSizer16 = new wxBoxSizer( wxHORIZONTAL );
199 itemBoxSizer2->Add( itemBoxSizer16, 0, wxALIGN_RIGHT | wxALL, 5 );
200
201 m_CancelButton = new wxButton( itemDialog1, ID_GOTOPOS_CANCEL, _("Cancel"), wxDefaultPosition,
202 wxDefaultSize, 0 );
203 itemBoxSizer16->Add( m_CancelButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
204
205 m_OKButton = new wxButton( itemDialog1, ID_GOTOPOS_OK, _("OK"), wxDefaultPosition,
206 wxDefaultSize, 0 );
207 itemBoxSizer16->Add( m_OKButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
208 m_OKButton->SetDefault();
209
210 SetColorScheme( (ColorScheme) 0 );
211 }
212
SetColorScheme(ColorScheme cs)213 void SetScaleDialog::SetColorScheme( ColorScheme cs )
214 {
215 DimeControl( this );
216 }
217
218
OnSetScaleCancelClick(wxCommandEvent & event)219 void SetScaleDialog::OnSetScaleCancelClick( wxCommandEvent& event )
220 {
221 Close();
222 event.Skip();
223 }
224
OnSetScaleOKClick(wxCommandEvent & event)225 void SetScaleDialog::OnSetScaleOKClick( wxCommandEvent& event )
226 {
227 SetReturnCode(wxID_OK);
228 EndModal(wxID_OK);
229 return;
230 }
231
232
233
234 //------------------------------------------------------------------------------
235 // MUIButton Static Storage
236 //------------------------------------------------------------------------------
237
238 class MUIButton: public wxWindow
239 {
240 DECLARE_DYNAMIC_CLASS( MUIButton )
241 DECLARE_EVENT_TABLE()
242
243 wxSize DoGetBestSize() const;
244 public:
245 MUIButton();
246 MUIButton(wxWindow* parent, wxWindowID id = wxID_ANY, float scale_factor = 1.0,
247 const wxString & bitmapState0 = wxEmptyString, const wxString & bitmapState1 = wxEmptyString, const wxString & bitmapState2 = wxEmptyString,
248 const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxNO_BORDER);
249
250 bool Create(wxWindow* parent, wxWindowID id = wxID_ANY, float scale_factor = 1.0,
251 const wxString & bitmapState0 = wxEmptyString, const wxString & bitmapState1 = wxEmptyString, const wxString & bitmapState2 = wxEmptyString,
252 const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxNO_BORDER);
253
254 ~MUIButton();
255
256 void Init();
257 void CreateControls();
258
259 void SetState( int state);
260
261 void SetColorScheme( ColorScheme cs );
262 void OnSize( wxSizeEvent& event );
263 void OnPaint( wxPaintEvent& event );
264 void OnLeftDown( wxMouseEvent& event );
265 void OnLeftUp( wxMouseEvent& event );
266
267
268 wxBitmap GetBitmapResource( const wxString& name );
269
270 wxIcon GetIconResource( const wxString& name );
271
272 /// Should we show tooltips?
273 static bool ShowToolTips();
274
275 private:
276 wxString m_bitmapFileState0;
277 wxString m_bitmapFileState1;
278 wxString m_bitmapFileState2;
279 wxBitmap m_bitmap;
280 wxBitmap m_bitmapState0;
281 wxBitmap m_bitmapState1;
282 wxBitmap m_bitmapState2;
283
284 int mState;
285 float m_scaleFactor;
286 wxSize m_styleToolSize;
287 ColorScheme m_cs;
288 };
289
290
IMPLEMENT_DYNAMIC_CLASS(MUIButton,wxWindow)291 IMPLEMENT_DYNAMIC_CLASS( MUIButton, wxWindow )
292
293
294
295 BEGIN_EVENT_TABLE( MUIButton, wxWindow )
296
297 EVT_SIZE( MUIButton::OnSize )
298 EVT_PAINT( MUIButton::OnPaint )
299 EVT_LEFT_DOWN( MUIButton::OnLeftDown )
300 EVT_LEFT_UP( MUIButton::OnLeftUp )
301
302 END_EVENT_TABLE()
303
304
305 MUIButton::MUIButton()
306 {
307 Init();
308 }
309
MUIButton(wxWindow * parent,wxWindowID id,float scale_factor,const wxString & bitmap,const wxString & bitmapState1,const wxString & bitmapState2,const wxPoint & pos,const wxSize & size,long style)310 MUIButton::MUIButton(wxWindow* parent, wxWindowID id, float scale_factor,
311 const wxString & bitmap, const wxString & bitmapState1,const wxString & bitmapState2,
312 const wxPoint& pos, const wxSize& size, long style)
313 {
314 Init();
315 Create(parent, id, scale_factor, bitmap, bitmapState1, bitmapState2, pos, size, style);
316 }
317
318
Create(wxWindow * parent,wxWindowID id,float scale_factor,const wxString & bitmap,const wxString & bitmapState1,const wxString & bitmapState2,const wxPoint & pos,const wxSize & size,long style)319 bool MUIButton::Create(wxWindow* parent, wxWindowID id, float scale_factor,
320 const wxString & bitmap, const wxString & bitmapState1, const wxString & bitmapState2,
321 const wxPoint& pos, const wxSize& size, long style)
322 {
323 wxWindow::Create(parent, id, pos, size, style);
324 m_bitmapFileState0 = bitmap;
325 m_bitmapFileState1 = bitmapState1;
326 m_bitmapFileState2 = bitmapState2;
327
328
329 m_scaleFactor = scale_factor;
330
331 m_styleToolSize = g_StyleManager->GetCurrentStyle()->GetToolSize();
332
333 // Arbitrarily boost the MUIButton default size above the style defined size. No good reason.....
334 m_styleToolSize = wxSize(m_styleToolSize.x * 1.25, m_styleToolSize.y * 1.25);
335
336 CreateControls();
337 return true;
338 }
339
340
~MUIButton()341 MUIButton::~MUIButton()
342 {
343 }
344
345
Init()346 void MUIButton::Init()
347 {
348 mState = 0;
349 m_cs = (ColorScheme)-1; //GLOBAL_COLOR_SCHEME_RGB;
350 }
351
352
CreateControls()353 void MUIButton::CreateControls()
354 {
355 this->SetForegroundColour(wxColour(255, 255, 255));
356
357 wxColour backColor = GetGlobalColor( _T("GREY3"));
358 SetBackgroundColour(backColor);
359
360 this->SetFont(wxFont(8, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxT("Tahoma")));
361 }
362
363
SetColorScheme(ColorScheme cs)364 void MUIButton::SetColorScheme(ColorScheme cs)
365 {
366 if(m_cs != cs){
367
368 wxColour backColor = GetGlobalColor( _T("GREY3"));
369 SetBackgroundColour(backColor);
370
371 ocpnStyle::Style* style = g_StyleManager->GetCurrentStyle();
372
373 wxBitmap bmp = LoadSVG( m_bitmapFileState0, GetSize().x, GetSize().y );
374 m_bitmapState0 = style->SetBitmapBrightness(bmp, cs);
375
376 bmp = LoadSVG( m_bitmapFileState1, GetSize().x, GetSize().y );
377 if(bmp.IsOk())
378 m_bitmapState1 = style->SetBitmapBrightness(bmp, cs);
379 else
380 m_bitmapState1 = m_bitmapState0;
381
382 bmp = LoadSVG( m_bitmapFileState2, GetSize().x, GetSize().y );
383 if(bmp.IsOk())
384 m_bitmapState2 = style->SetBitmapBrightness(bmp, cs);
385 else
386 m_bitmapState2 = m_bitmapState0;
387
388
389 switch(mState){
390 case 0:
391 default:
392 m_bitmap = m_bitmapState0;
393 break;
394
395 case 1:
396 m_bitmap = m_bitmapState1;
397 break;
398
399 case 2:
400 m_bitmap = m_bitmapState2;
401 break;
402 }
403
404 m_cs = cs;
405 }
406
407 }
408
409
ShowToolTips()410 bool MUIButton::ShowToolTips()
411 {
412 return true;
413 }
414
SetState(int state)415 void MUIButton::SetState( int state)
416 {
417 switch(state){
418 case 0:
419 default:
420 m_bitmap = m_bitmapState0;
421 break;
422
423 case 1:
424 m_bitmap = m_bitmapState1;
425 break;
426
427 case 2:
428 m_bitmap = m_bitmapState2;
429 break;
430 }
431
432 mState = state;
433
434 Refresh();
435 }
436
437
OnSize(wxSizeEvent & event)438 void MUIButton::OnSize( wxSizeEvent& event )
439 {
440 if(m_bitmap.IsOk()){
441 if( event.GetSize() == m_bitmap.GetSize())
442 return;
443 }
444
445 if(!m_bitmapFileState0.IsEmpty())
446 m_bitmapState0 = LoadSVG( m_bitmapFileState0, event.GetSize().x, event.GetSize().y );
447
448 if(!m_bitmapFileState1.IsEmpty())
449 m_bitmapState1 = LoadSVG( m_bitmapFileState1, event.GetSize().x, event.GetSize().y );
450 if(!m_bitmapState1.IsOk() || m_bitmapFileState1.IsEmpty())
451 m_bitmapState1 = m_bitmapState0;
452
453 if(!m_bitmapFileState2.IsEmpty())
454 m_bitmapState2 = LoadSVG( m_bitmapFileState2, event.GetSize().x, event.GetSize().y );
455 if(!m_bitmapState2.IsOk() || m_bitmapFileState2.IsEmpty())
456 m_bitmapState2 = m_bitmapState0;
457
458 switch(mState){
459 case 0:
460 default:
461 m_bitmap = m_bitmapState0;
462 break;
463
464 case 1:
465 m_bitmap = m_bitmapState1;
466 break;
467
468 case 2:
469 m_bitmap = m_bitmapState2;
470 break;
471 }
472 }
473
GetBitmapResource(const wxString & name)474 wxBitmap MUIButton::GetBitmapResource( const wxString& name )
475 {
476 // Bitmap retrieval
477 wxUnusedVar(name);
478 return wxNullBitmap;
479 }
480
GetIconResource(const wxString & name)481 wxIcon MUIButton::GetIconResource( const wxString& name )
482 {
483 // Icon retrieval
484 wxUnusedVar(name);
485 return wxNullIcon;
486 }
487
DoGetBestSize() const488 wxSize MUIButton::DoGetBestSize() const
489 {
490 // wxSize labelSize = wxDefaultSize;
491 // GetTextExtent(m_Label, &labelSize.x, &labelSize.y);
492 // return wxSize(wxMax(40, labelSize.x + 20), wxMax(20, labelSize.y + 10));
493 return wxSize(m_styleToolSize.x * m_scaleFactor, m_styleToolSize.y * m_scaleFactor);
494 }
495
496
OnPaint(wxPaintEvent & event)497 void MUIButton::OnPaint( wxPaintEvent& event )
498 {
499 wxPaintDC dc( this );
500
501 if(m_bitmap.IsOk()){
502 dc.DrawBitmap(m_bitmap, 0, 0, true);
503 }
504
505
506 #if 0
507 wxBufferedPaintDC dc(this);
508
509 wxRect clientRect = GetClientRect();
510 wxRect gradientRect = clientRect;
511 gradientRect.SetHeight(gradientRect.GetHeight()/2 + ((GetCapture() == this) ? 1 : 0));
512 if(GetCapture() != this)
513 {
514 dc.GradientFillLinear(gradientRect,
515 m_GradientTopStartColour, m_GradientTopEndColour, wxSOUTH);
516 }
517 else
518 {
519 dc.SetPen(wxPen(m_PressedColourTop));
520 dc.SetBrush(wxBrush(m_PressedColourTop));
521 dc.DrawRectangle(gradientRect);
522 }
523
524 gradientRect.Offset(0, gradientRect.GetHeight());
525
526 if(GetCapture() != this)
527 {
528 dc.GradientFillLinear(gradientRect,
529 m_GradientBottomStartColour, m_GradientBottomEndColour, wxSOUTH);
530 }
531 else
532 {
533 dc.SetPen(wxPen(m_PressedColourBottom));
534 dc.SetBrush(wxBrush(m_PressedColourBottom));
535 dc.DrawRectangle(gradientRect);
536 }
537 dc.SetPen(wxPen(GetBackgroundColour()));
538 dc.SetBrush(*wxTRANSPARENT_BRUSH);
539 dc.DrawRectangle(0, 0, clientRect.GetWidth(), clientRect.GetHeight());
540 dc.SetFont(GetFont());
541 dc.SetTextForeground(GetForegroundColour());
542 if(GetCapture() == this)
543 {
544 clientRect.Offset(1, 1);
545 }
546 dc.DrawLabel(m_Label, clientRect, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL);
547 #endif
548 }
549
550
551 #if 1
OnLeftDown(wxMouseEvent & event)552 void MUIButton::OnLeftDown( wxMouseEvent& event )
553 {
554 event.Skip();
555 }
556
557
OnLeftUp(wxMouseEvent & event)558 void MUIButton::OnLeftUp( wxMouseEvent& event )
559 {
560 if(GetClientRect().Contains(event.GetPosition())){
561 wxCommandEvent evt(wxEVT_COMMAND_MENU_SELECTED, GetId());
562 GetParent()->GetEventHandler()->AddPendingEvent( evt );
563 }
564 event.Skip();
565 }
566 #endif
567
568
569
570
571
572
573 #define CANVAS_OPTIONS_ANIMATION_TIMER_1 800
574 #define CANVAS_OPTIONS_TIMER 801
575
576 //------------------------------------------------------------------------------
577 // MUIBar Window Implementation
578 //------------------------------------------------------------------------------
BEGIN_EVENT_TABLE(MUIBar,wxFrame)579 BEGIN_EVENT_TABLE(MUIBar, wxFrame)
580 EVT_TIMER ( CANVAS_OPTIONS_ANIMATION_TIMER_1, MUIBar::onCanvasOptionsAnimationTimerEvent )
581 //EVT_PAINT ( MUIBar::OnPaint )
582 EVT_SIZE( MUIBar::OnSize )
583 EVT_MENU(-1, MUIBar::OnToolLeftClick)
584 EVT_TIMER(CANVAS_OPTIONS_TIMER, MUIBar::CaptureCanvasOptionsBitmapChain)
585
586 END_EVENT_TABLE()
587
588 // Define a constructor
589 MUIBar::MUIBar()
590 {
591 }
592
MUIBar(ChartCanvas * parent,int orientation,float size_factor,wxWindowID id,const wxPoint & pos,const wxSize & size,long style,const wxString & name)593 MUIBar::MUIBar(ChartCanvas* parent, int orientation, float size_factor, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name)
594 {
595 m_parentCanvas = parent;
596 m_orientation = orientation;
597
598 //SetBackgroundStyle( wxBG_STYLE_TRANSPARENT );
599 //wxWindow::Create(parent, id, pos, size, style, name);
600 //long mstyle = wxSIMPLE_BORDER;
601 long mstyle = wxNO_BORDER | wxFRAME_NO_TASKBAR | wxFRAME_SHAPED | wxFRAME_FLOAT_ON_PARENT;
602
603 m_scaleFactor = size_factor;
604 m_cs = (ColorScheme)-1;
605
606 wxFrame::Create(parent, id, _T(""), pos, size, mstyle, name);
607 Init();
608 CreateControls();
609 //Show();
610 }
611
612
613
614
~MUIBar()615 MUIBar::~MUIBar()
616 {
617 if(m_canvasOptions){
618 m_canvasOptions->Destroy();
619 m_canvasOptions = 0;
620 }
621 if(m_scaleTextBox)
622 m_scaleTextBox->Unbind(wxEVT_LEFT_DOWN, &MUIBar::OnScaleSelected, this);
623
624 }
625
Init()626 void MUIBar::Init()
627 {
628 m_zinButton = NULL;
629 m_zoutButton = NULL;
630 m_followButton = NULL;
631 m_menuButton = NULL;
632
633 m_canvasOptions = NULL;
634 m_canvasOptionsAnimationTimer.SetOwner(this, CANVAS_OPTIONS_ANIMATION_TIMER_1);
635 m_backcolorString = _T("GREY3");
636 m_scaleTextBox = NULL;
637 m_capture_size_y = 0;
638
639 m_COTopOffset = 60; // TODO should be below GPS/Compass
640
641 CanvasOptionTimer.SetOwner( this, CANVAS_OPTIONS_TIMER );
642 m_coAnimateByBitmaps = false;
643 m_bEffects = true;
644 #ifdef __OCPN__ANDROID__
645 m_bEffects =false;
646 #endif
647
648 }
649
SetColorScheme(ColorScheme cs)650 void MUIBar::SetColorScheme( ColorScheme cs )
651 {
652 if( m_cs != cs ){
653 wxColour backColor = GetGlobalColor( m_backcolorString );
654 SetBackgroundColour(backColor);
655
656 if(m_zinButton)
657 m_zinButton->SetColorScheme(cs);
658 if(m_zoutButton)
659 m_zoutButton->SetColorScheme(cs);
660 if(m_followButton)
661 m_followButton->SetColorScheme(cs);
662 if(m_menuButton)
663 m_menuButton->SetColorScheme(cs);
664
665 if(m_scaleTextBox){
666 wxColour textbackColor = GetGlobalColor( _T("GREY1") );
667 m_scaleTextBox->SetForegroundColour(textbackColor);
668 }
669 Refresh();
670 m_cs = cs;
671 }
672 }
673
OnScaleSelected(wxMouseEvent & event)674 void MUIBar::OnScaleSelected( wxMouseEvent &event )
675 {
676 ChartCanvas *pcc = wxDynamicCast(m_parent, ChartCanvas);
677 if(!pcc) return;
678
679 SetScaleDialog dlg(pcc);
680 dlg.Centre();
681 dlg.ShowModal();
682 if( dlg.GetReturnCode() == wxID_OK ) {
683 wxString newScale = dlg.m_ScaleCtl->GetValue();
684 if(newScale.Contains(':'))
685 newScale = newScale.AfterFirst(':');
686 double dScale;
687 if(newScale.ToDouble(&dScale)){
688 // Try to constrain the scale to something reasonable
689 dScale = wxMin(dScale, 3e6);
690 dScale = wxMax(dScale, 1000);
691 double displayScaleNow = pcc->GetScaleValue();
692 double factor = displayScaleNow / dScale;
693 pcc->DoZoomCanvas( factor );
694
695 // Run the calculation again, to reduce roundoff error in large scale jumps.
696 displayScaleNow = pcc->GetScaleValue();
697 factor = displayScaleNow / dScale;
698 pcc->DoZoomCanvas( factor );
699
700 }
701 }
702 }
703
SetCanvasENCAvailable(bool avail)704 void MUIBar::SetCanvasENCAvailable(bool avail)
705 {
706 m_CanvasENCAvail = avail;
707 if(m_canvasOptions)
708 m_canvasOptions->SetENCAvailable( avail );
709 }
710
711
CreateControls()712 void MUIBar::CreateControls()
713 {
714 //SetBackgroundStyle( wxBG_STYLE_TRANSPARENT );
715
716 wxColour backColor = GetGlobalColor( m_backcolorString );
717 SetBackgroundColour(backColor);
718 wxBoxSizer *topSizer;
719
720 wxString iconDir = g_Platform->GetSharedDataDir() + _T("uidata/MUI_flat/");
721
722 if(m_orientation == wxHORIZONTAL){
723 topSizer = new wxBoxSizer(wxVERTICAL);
724 SetSizer(topSizer);
725
726 wxBoxSizer *barSizer = new wxBoxSizer(wxHORIZONTAL);
727 topSizer->Add(barSizer, 0, wxEXPAND );
728
729 // Buttons
730
731 if(g_bShowMuiZoomButtons){
732 m_zinButton = new MUIButton( this, ID_ZOOMIN, m_scaleFactor, iconDir + _T("MUI_zoom-in.svg"));
733 barSizer->Add(m_zinButton, 0, wxSHAPED);
734
735 m_zoutButton = new MUIButton( this, ID_ZOOMOUT, m_scaleFactor, iconDir + _T("MUI_zoom-out.svg"));
736 barSizer->Add(m_zoutButton, 0, wxSHAPED);
737
738 barSizer->AddSpacer(2);
739 }
740
741 #ifndef __OCPN__ANDROID__
742 // Scale
743 m_scaleTextBox = new wxStaticText(this, wxID_ANY, _("1:400000"));
744 wxColour textbackColor = GetGlobalColor( _T("GREY1") );
745 m_scaleTextBox->SetForegroundColour(textbackColor);
746 barSizer->Add(m_scaleTextBox, 0, wxALIGN_CENTER_VERTICAL );
747 m_scaleTextBox->Bind(wxEVT_LEFT_DOWN, &MUIBar::OnScaleSelected, this);
748
749 barSizer->AddSpacer(5);
750
751 m_followButton = new MUIButton( this, ID_FOLLOW, m_scaleFactor,
752 iconDir + _T("MUI_follow.svg"), iconDir + _T("MUI_follow_active.svg"), iconDir + _T("MUI_follow_ahead.svg"));
753 barSizer->Add(m_followButton, 0, wxSHAPED);
754
755 barSizer->AddSpacer(2);
756 #endif
757 m_menuButton = new MUIButton( this, ID_MUI_MENU, m_scaleFactor, iconDir + _T("MUI_menu.svg"));
758 barSizer->Add(m_menuButton, 0, wxSHAPED);
759 }
760 else{
761 topSizer = new wxBoxSizer(wxVERTICAL);
762 SetSizer(topSizer);
763
764 wxBoxSizer *barSizer = new wxBoxSizer(wxVERTICAL);
765 topSizer->Add(barSizer, 0, wxEXPAND );
766
767 // Buttons
768 if(g_bShowMuiZoomButtons){
769 m_zinButton = new MUIButton( this, ID_ZOOMIN, m_scaleFactor, iconDir + _T("MUI_zoom-in.svg"));
770 barSizer->Add(m_zinButton, 1, wxSHAPED);
771
772 m_zoutButton = new MUIButton( this, ID_ZOOMOUT, m_scaleFactor, iconDir + _T("MUI_zoom-out.svg"));
773 barSizer->Add(m_zoutButton, 1, wxSHAPED);
774
775 barSizer->AddSpacer(5);
776 }
777
778 #ifndef __OCPN__ANDROID__
779 m_followButton = new MUIButton( this, ID_FOLLOW, m_scaleFactor,
780 iconDir + _T("MUI_follow.svg"), iconDir + _T("MUI_follow_active.svg"), iconDir + _T("MUI_follow_ahead.svg"));
781 barSizer->Add(m_followButton, 1, wxSHAPED);
782
783 barSizer->AddSpacer(5);
784 #endif
785
786 m_menuButton = new MUIButton( this, ID_MUI_MENU, m_scaleFactor, iconDir + _T("MUI_menu.svg"));
787 barSizer->Add(m_menuButton, 1, wxALIGN_RIGHT | wxSHAPED);
788
789
790 }
791
792
793 //topSizer->SetSizeHints( this );
794 topSizer->Fit( this );
795
796
797 }
798
SetBestPosition(void)799 void MUIBar::SetBestPosition( void )
800 {
801 #if 0 // for wxWindow
802 int x = (m_parent->GetClientSize().x - GetSize().x) / 2;
803 if(x > 0){
804 int bottomOffset = 0;
805
806 ChartCanvas *pcc = wxDynamicCast(m_parent, ChartCanvas);
807 bottomOffset += pcc->GetPianoHeight();
808
809 int y = m_parent->GetClientSize().y - GetSize().y - bottomOffset;
810 SetSize(x, y, -1, -1, wxSIZE_USE_EXISTING);
811 }
812
813 #else // for wxDialog
814 int x = (m_parent->GetClientSize().x - (GetSize().x * 1.00));
815
816 #ifndef __WXGTK__ // Adjust for wxNO_BORDER canvas window style
817 x -= 2;
818 #endif
819
820 //if(x > 0)
821 {
822 int bottomOffset = 2;
823
824 ChartCanvas *pcc = wxDynamicCast(m_parent, ChartCanvas);
825 // bottomOffset += pcc->GetPianoHeight();
826
827 int y = m_parent->GetClientSize().y - GetSize().y - bottomOffset;
828
829 wxPoint m_position = wxPoint(x,y);
830 wxPoint screenPos = pcc->ClientToScreen( m_position );
831
832 // GTK sometimes has trouble with ClientToScreen() if executed in the context of an event handler
833 // The position of the window is calculated incorrectly if a deferred Move() has not been processed yet.
834 // So work around this here...
835
836 #ifdef __WXGTK__
837 wxPoint pp = m_parent->GetPosition();
838 wxPoint ppg = m_parent->GetParent()->GetScreenPosition();
839 wxPoint screen_pos_fix = ppg + pp + m_position;
840 screenPos.x = screen_pos_fix.x;
841 #endif
842
843 Move( screenPos );
844
845 if(m_canvasOptions){
846 m_canvasOptions->Destroy();
847 m_canvasOptions = 0;
848 }
849 Show();
850
851 }
852 #endif
853 }
854
OnSize(wxSizeEvent & event)855 void MUIBar::OnSize( wxSizeEvent& event )
856 {
857 //int buttonSize = event.GetSize().y / 2;
858 Layout();
859
860 #if !defined(__WXMAC__) && !defined(__OCPN__ANDROID__)
861 if(1) {
862 wxBitmap m_MaskBmp = wxBitmap( GetSize().x, GetSize().y );
863 wxMemoryDC sdc( m_MaskBmp );
864 sdc.SetBackground( *wxWHITE_BRUSH );
865 sdc.Clear();
866 sdc.SetBrush( *wxBLACK_BRUSH );
867 sdc.SetPen( *wxBLACK_PEN );
868 sdc.DrawRoundedRectangle( 0, 0, m_MaskBmp.GetWidth(), m_MaskBmp.GetHeight(), 5 );
869 sdc.SelectObject( wxNullBitmap );
870 SetShape( wxRegion( m_MaskBmp, *wxWHITE, 0 ) );
871 }
872 #endif
873
874 }
875
UpdateDynamicValues()876 void MUIBar::UpdateDynamicValues()
877 {
878 if(!m_scaleTextBox)
879 return;
880
881 wxString scaleString;
882 int scale = m_parentCanvas->GetScaleValue();
883 if(scale < 1e6)
884 scaleString.Printf(_T("1:%d"), scale);
885 else
886 scaleString.Printf(_T("1:%4.1f MM"), scale / 1e6);
887
888 if(m_scaleTextBox)
889 m_scaleTextBox->SetLabel(scaleString);
890 }
891
SetFollowButtonState(int state)892 void MUIBar::SetFollowButtonState( int state )
893 {
894 if(m_followButton)
895 m_followButton->SetState( state );
896 }
897
OnToolLeftClick(wxCommandEvent & event)898 void MUIBar::OnToolLeftClick( wxCommandEvent& event )
899 {
900 // Handle the MUIButton clicks here
901 ChartCanvas *pcc = wxDynamicCast(m_parent, ChartCanvas);
902
903 switch( event.GetId() ){
904
905 case ID_ZOOMIN:
906 case ID_ZOOMOUT:
907 {
908 wxCommandEvent evt(wxEVT_COMMAND_MENU_SELECTED, event.GetId());
909 GetParent()->GetEventHandler()->AddPendingEvent( evt );
910
911 if(g_focusCanvas)
912 g_focusCanvas->TriggerDeferredFocus();
913 break;
914 }
915
916 case ID_FOLLOW:
917 {
918 wxCommandEvent evt(wxEVT_COMMAND_MENU_SELECTED, event.GetId());
919 GetParent()->GetEventHandler()->AddPendingEvent( evt );
920
921 if(g_focusCanvas)
922 g_focusCanvas->TriggerDeferredFocus();
923 break;
924 }
925
926 case ID_MUI_MENU:
927 {
928 if(!m_canvasOptions){
929 m_canvasOptions = new CanvasOptions(m_parent);
930
931 // calculate best size for CanvasOptions dialog
932
933 wxPoint parentClientUpperRight = m_parent->ClientToScreen(wxPoint( m_parent->GetSize().x, 0));
934 wxRect rmui = m_parentCanvas->GetMUIBarRect();
935 int size_y = rmui.y - (parentClientUpperRight.y + m_COTopOffset);
936 size_y -= GetCharHeight();
937 size_y = wxMax(size_y, 100); // ensure always big enough to see
938
939 m_canvasOptions->SetSize(wxSize(-1, size_y));
940 m_canvasOptionsFullSize = m_canvasOptions->GetSize();
941 m_canvasOptionsFullSize.x += m_canvasOptions->GetCharWidth(); // Allow for scroll bar, since sizer won't do it.
942
943 if(1)
944 m_currentCOPos = m_parent->ClientToScreen(wxPoint( m_parent->GetSize().x, m_COTopOffset));
945 else
946 m_currentCOPos = wxPoint( m_parent->GetSize().x, 20);
947
948 m_canvasOptions->Move(m_currentCOPos);
949 m_canvasOptions->Hide();
950 }
951
952 m_canvasOptions->SetENCAvailable(m_CanvasENCAvail);
953
954 if(m_canvasOptions->IsShown())
955 PushCanvasOptions(); // hide it
956 else{
957 // Grab the backing bitmap, if available
958
959 if(m_coAnimateByBitmaps && m_capture_size_y){
960 int overShoot_x = m_canvasOptions->GetSize().x * 2 / 10; //20%
961 m_backingPoint = wxPoint(m_capturePoint.x - overShoot_x, m_capturePoint.y);
962
963 m_backingBitmap = wxBitmap(m_canvasOptionsFullSize.x + overShoot_x, m_capture_size_y, -1);
964 wxMemoryDC mdcb;
965 mdcb.SelectObject(m_backingBitmap);
966 wxScreenDC sdc;
967 mdcb.Blit(0, 0, m_canvasOptionsFullSize.x + overShoot_x, m_capture_size_y, &sdc, m_capturePoint.x - overShoot_x, m_capturePoint.y, wxCOPY);
968 mdcb.SelectObject(wxNullBitmap);
969 }
970 PullCanvasOptions();
971 }
972
973 break;
974 }
975
976 default:
977 break;
978 }
979 //event.Skip();
980 }
981
CaptureCanvasOptionsBitmap()982 void MUIBar::CaptureCanvasOptionsBitmap()
983 {
984 m_coSequence = 0;
985 CanvasOptionTimer.Start(100, wxTIMER_ONE_SHOT );
986 }
987
988
989
CaptureCanvasOptionsBitmapChain(wxTimerEvent & event)990 void MUIBar::CaptureCanvasOptionsBitmapChain( wxTimerEvent& event )
991 {
992 if(m_coSequence == 0){
993
994
995 if(!m_canvasOptions)
996 m_canvasOptions = new CanvasOptions(m_parent);
997
998 wxPoint parentClientUpperRight = m_parent->ClientToScreen(wxPoint( m_parent->GetSize().x, 0));
999 wxRect rmui = m_parentCanvas->GetMUIBarRect();
1000 int size_y = rmui.y - (parentClientUpperRight.y + m_COTopOffset);
1001 size_y -= GetCharHeight();
1002 size_y = wxMax(size_y, 100); // ensure always big enough to see
1003 m_capture_size_y = size_y;
1004
1005 m_canvasOptions->SetSize(wxSize(-1, size_y));
1006
1007 m_capturePoint = m_parent->ClientToScreen(wxPoint( m_parent->GetSize().x, m_COTopOffset));
1008 m_canvasOptions->Move(m_capturePoint);
1009 m_canvasOptions->Show();
1010
1011 m_coSequence++;
1012 CanvasOptionTimer.Start(1, wxTIMER_ONE_SHOT );
1013 }
1014
1015 else if(m_coSequence == 1){
1016 m_capturePoint = m_parent->ClientToScreen(wxPoint( m_parent->GetSize().x - m_canvasOptionsFullSize.x, m_COTopOffset));
1017 m_canvasOptions->Move(m_capturePoint);
1018
1019 m_coSequence++;
1020 CanvasOptionTimer.Start(1, wxTIMER_ONE_SHOT );
1021 }
1022
1023 else if(m_coSequence == 2){
1024 m_animateBitmap = wxBitmap(m_canvasOptions->GetSize().x, m_capture_size_y, -1);
1025 wxMemoryDC mdc(m_animateBitmap);
1026
1027 wxScreenDC sdc;
1028
1029 mdc.Blit(0, 0, m_canvasOptions->GetSize().x, m_capture_size_y, &sdc, m_capturePoint.x, m_capturePoint.y, wxCOPY);
1030 mdc.SelectObject(wxNullBitmap);
1031
1032 //delete m_canvasOptions;
1033 //m_canvasOptions = NULL;
1034 }
1035
1036 }
1037
1038
1039
1040
OnEraseBackground(wxEraseEvent & event)1041 void MUIBar::OnEraseBackground( wxEraseEvent& event )
1042 {
1043 }
1044
1045
OnPaint(wxPaintEvent & event)1046 void MUIBar::OnPaint( wxPaintEvent& event )
1047 {
1048 return;
1049
1050 int width, height;
1051 GetClientSize( &width, &height );
1052 wxPaintDC dc( this );
1053
1054 // dc.SetBackgroundMode(wxTRANSPARENT);
1055 // dc.SetBackground(*wxTRANSPARENT_BRUSH);
1056
1057 // dc.SetPen( *wxTRANSPARENT_PEN );
1058 // dc.SetBrush( *wxTRANSPARENT_BRUSH );
1059 // dc.DrawRectangle( 0, 0, width, height);
1060
1061 wxColour backColor = GetGlobalColor( m_backcolorString );
1062
1063
1064 dc.SetBrush( wxBrush( backColor/*wxColour(200, 200, 200)*/) );
1065 dc.SetPen( wxPen( backColor) );
1066 dc.DrawRoundedRectangle( 0, 0, width - 10, height - 10, 8 );
1067 }
1068
ResetCanvasOptions()1069 void MUIBar::ResetCanvasOptions()
1070 {
1071 delete m_canvasOptions;
1072 m_canvasOptions = NULL;
1073 }
1074
PullCanvasOptions()1075 void MUIBar::PullCanvasOptions()
1076 {
1077 // Target position
1078 int cox = m_parent->GetSize().x - m_canvasOptionsFullSize.x;
1079 int coy = m_COTopOffset;
1080 m_targetCOPos = m_parent->ClientToScreen(wxPoint(cox, coy));
1081
1082 if(!m_bEffects){
1083 m_canvasOptions->Move(m_targetCOPos);
1084 m_canvasOptions->Show();
1085 return;
1086 }
1087
1088 // Capture the animation bitmap, if required..
1089
1090 if(m_coAnimateByBitmaps && !m_animateBitmap.IsOk() ){
1091 m_canvasOptions->Move(m_targetCOPos);
1092 m_canvasOptions->Show();
1093 CaptureCanvasOptionsBitmap();
1094 return;
1095 }
1096
1097
1098
1099 // Setup animation parameters
1100 // Start Position
1101 m_startCOPos = m_canvasOptions->GetPosition();
1102
1103 // Present Position
1104 m_currentCOPos = m_startCOPos;
1105
1106 m_animationType = CO_ANIMATION_CUBIC_REVERSE; //CO_ANIMATION_CUBIC_BACK_IN;
1107 m_animateSteps = 10;
1108 m_animationTotalTime = 200; // msec
1109
1110 m_pushPull = CO_PULL;
1111 ChartCanvas *pcc = wxDynamicCast(m_parent, ChartCanvas);
1112 pcc->m_b_paint_enable = false;
1113
1114 // Start the animation....
1115 m_animateStep = 0;
1116 m_canvasOptionsAnimationTimer.Start(10, true);
1117 m_canvasOptions->Move(m_targetCOPos);
1118 m_canvasOptions->Hide();
1119
1120 }
1121
1122
1123
PushCanvasOptions()1124 void MUIBar::PushCanvasOptions()
1125 {
1126 if(!m_bEffects){
1127 m_canvasOptions->Hide();
1128 return;
1129 }
1130
1131 // Setup animation parameters
1132
1133 // Target position
1134 int cox = m_parent->GetSize().x;
1135 int coy = 20;
1136
1137 if(1)
1138 m_targetCOPos = m_parent->ClientToScreen(wxPoint(cox, coy));
1139 else
1140 m_targetCOPos = wxPoint(cox, coy);
1141
1142 // Start Position
1143 m_startCOPos = m_canvasOptions->GetPosition();
1144
1145 // Present Position
1146 m_currentCOPos = m_startCOPos;
1147
1148 // Animation type
1149 m_animationType = CO_ANIMATION_LINEAR;
1150 m_animateSteps = 5;
1151 m_animationTotalTime = 100; // msec
1152 m_pushPull = CO_PUSH;
1153 ChartCanvas *pcc = wxDynamicCast(m_parent, ChartCanvas);
1154
1155 // Start the animation....
1156 m_animateStep = 0;
1157 m_canvasOptionsAnimationTimer.Start(10, true);
1158 m_canvasOptions->Show();
1159
1160 }
1161
onCanvasOptionsAnimationTimerEvent(wxTimerEvent & event)1162 void MUIBar::onCanvasOptionsAnimationTimerEvent( wxTimerEvent &event )
1163 {
1164 double progress = m_animateStep / (double) m_animateSteps;
1165 double valueX = getValue(m_animationType, progress);
1166
1167 double dx = (m_targetCOPos.x - m_startCOPos.x) * valueX;
1168
1169 wxPoint newPos = wxPoint(m_startCOPos.x + dx, m_currentCOPos.y);
1170
1171 int size_x;
1172 if(m_pushPull == CO_PULL)
1173 size_x = abs(dx);
1174 else
1175 size_x = (m_targetCOPos.x - m_startCOPos.x) - abs(dx);
1176
1177 if(!m_coAnimateByBitmaps){
1178 m_canvasOptions->SetSize(newPos.x, newPos.y, size_x, wxDefaultCoord, wxSIZE_USE_EXISTING);
1179 //m_canvasOptions->GetSizer()->Layout();
1180 m_canvasOptions->Show();
1181 }
1182 else{
1183 m_canvasOptions->Hide();
1184 wxScreenDC sdc;
1185
1186 if(1/*m_pushPull == CO_PULL*/){
1187 // restore Backing bitmap, to cover any overshoot
1188 if(m_backingBitmap.IsOk()){
1189 wxMemoryDC mdc_back(m_backingBitmap);
1190 sdc.Blit(m_backingPoint.x, m_backingPoint.y, m_backingBitmap.GetWidth() - size_x, m_backingBitmap.GetHeight(), &mdc_back, 0, 0, wxCOPY);
1191 }
1192 }
1193
1194 wxMemoryDC mdc(m_animateBitmap);
1195 sdc.Blit(newPos.x, newPos.y, size_x, m_animateBitmap.GetHeight(), &mdc, 0, 0, wxCOPY);
1196 mdc.SelectObject(wxNullBitmap);
1197
1198 }
1199
1200 m_currentCOPos = newPos;
1201
1202 double dt = m_animationTotalTime / m_animateSteps;
1203
1204 if(m_animateStep++ < m_animateSteps + 1){
1205 m_canvasOptionsAnimationTimer.Start(dt, true);
1206 }
1207 else{
1208 m_currentCOPos = m_targetCOPos;
1209 m_canvasOptions->Show(m_pushPull == CO_PULL);
1210
1211 ChartCanvas *pcc = wxDynamicCast(m_parent, ChartCanvas);
1212 if(pcc){
1213 pcc->m_b_paint_enable = true;
1214
1215 if(m_pushPull == CO_PUSH){
1216 delete m_canvasOptions;
1217 m_canvasOptions = NULL;
1218 }
1219 #ifdef __WXOSX__
1220 if(m_pushPull == CO_PUSH)
1221 pcc->TriggerDeferredFocus();
1222 #else
1223 pcc->TriggerDeferredFocus();
1224 #endif
1225
1226 pcc->Refresh();
1227 }
1228
1229 }
1230
1231 }
1232
1233 // Animation support
1234
bounceMaker(double t,double c,double a)1235 double bounceMaker(double t, double c, double a)
1236 {
1237 if (t == 1.0) return c;
1238 if (t < (4/11.0)) {
1239 return c*(7.5625*t*t);
1240 } else if (t < (8/11.0)) {
1241 t -= (6/11.0);
1242 return -a * (1. - (7.5625*t*t + .75)) + c;
1243 } else if (t < (10/11.0)) {
1244 t -= (9/11.0);
1245 return -a * (1. - (7.5625*t*t + .9375)) + c;
1246 } else {
1247 t -= (21/22.0);
1248 return -a * (1. - (7.5625*t*t + .984375)) + c;
1249 }
1250 }
1251
getValue(int animationType,double t)1252 double getValue(int animationType, double t)
1253 {
1254 double value = 0;
1255 double s = 1;
1256 double tp;
1257 switch (animationType){
1258 case CO_ANIMATION_LINEAR:
1259 default:
1260 value = t;
1261 break;
1262 case CO_ANIMATION_CUBIC:
1263 tp = t - 1.0;
1264 value = tp*tp*tp + 1;
1265 //value = t*t*t;
1266 break;
1267 case CO_ANIMATION_CUBIC_REVERSE:
1268 tp = t - 1.0;
1269 value = tp*tp*tp + 1;
1270 break;
1271 case CO_ANIMATION_CUBIC_BOUNCE_IN:
1272 value = bounceMaker(t, 1, s);
1273 break;
1274
1275 case CO_ANIMATION_CUBIC_BACK_IN:
1276 tp = t - 1.0;
1277 value = tp*tp*((s+1)*tp+ s) + 1;
1278 break;
1279
1280 }
1281
1282 return value;
1283 }
1284