30#include <wx/statline.h>
55#include "androidUTIL.h"
60extern GLenum g_texture_rectangle_format;
63#define ID_SCALE_CANCEL 8301
64#define ID_SCALE_OK 8302
65#define ID_SCALECTRL 8303
73static inline void IgnoreRetval(
size_t n) { (void)n; }
75static double getValue(
int animationType,
double t);
85 SetScaleDialog(wxWindow* parent, wxWindowID
id = SYMBOL_GOTOPOS_IDNAME,
86 const wxString& caption = _(
"Set scale"),
87 const wxPoint& pos = wxDefaultPosition,
88 const wxSize& size = wxDefaultSize,
89 long style = wxDEFAULT_DIALOG_STYLE);
94 bool Create(wxWindow* parent, wxWindowID
id = wxID_ANY,
95 const wxString& caption = _(
"Set scale"),
96 const wxPoint& pos = wxDefaultPosition,
97 const wxSize& size = wxDefaultSize,
98 long style = wxDEFAULT_DIALOG_STYLE);
100 void SetColorScheme(ColorScheme cs);
104 void OnSetScaleCancelClick(wxCommandEvent& event);
105 void OnSetScaleOKClick(wxCommandEvent& event);
110 wxButton* m_CancelButton;
111 wxButton* m_OKButton;
115EVT_BUTTON(ID_GOTOPOS_CANCEL, SetScaleDialog::OnSetScaleCancelClick)
116EVT_BUTTON(ID_GOTOPOS_OK, SetScaleDialog::OnSetScaleOKClick)
126 const wxString& caption,
const wxPoint& pos,
127 const wxSize& size,
long style) {
129 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxFRAME_FLOAT_ON_PARENT;
131 Create(parent,
id, caption, pos, size, wstyle);
134SetScaleDialog::~SetScaleDialog() {}
141 const wxString& caption,
const wxPoint& pos,
142 const wxSize& size,
long style) {
143 SetExtraStyle(GetExtraStyle() | wxWS_EX_BLOCK_EVENTS);
144 wxDialog::Create(parent,
id, caption, pos, size, style);
147 GetSizer()->SetSizeHints(
this);
160 wxBoxSizer* itemBoxSizer2 =
new wxBoxSizer(wxVERTICAL);
161 itemDialog1->SetSizer(itemBoxSizer2);
163 wxStaticBox* itemStaticBoxSizer4Static =
164 new wxStaticBox(itemDialog1, wxID_ANY, _(
"Chart Scale"));
166 wxStaticBoxSizer* itemStaticBoxSizer4 =
167 new wxStaticBoxSizer(itemStaticBoxSizer4Static, wxVERTICAL);
168 itemBoxSizer2->Add(itemStaticBoxSizer4, 0, wxEXPAND | wxALL, 5);
170 wxStaticText* itemStaticText5 =
new wxStaticText(
171 itemDialog1, wxID_STATIC,
"", wxDefaultPosition, wxDefaultSize, 0);
172 itemStaticBoxSizer4->Add(itemStaticText5, 0,
173 wxALIGN_LEFT | wxLEFT | wxRIGHT | wxTOP, 5);
175 m_ScaleCtl =
new wxTextCtrl(itemDialog1, ID_SCALECTRL,
"", wxDefaultPosition,
177 itemStaticBoxSizer4->Add(
178 m_ScaleCtl, 0, wxALIGN_LEFT | wxLEFT | wxRIGHT | wxBOTTOM | wxEXPAND, 5);
180 wxBoxSizer* itemBoxSizer16 =
new wxBoxSizer(wxHORIZONTAL);
181 itemBoxSizer2->Add(itemBoxSizer16, 0, wxALIGN_RIGHT | wxALL, 5);
183 m_CancelButton =
new wxButton(itemDialog1, ID_GOTOPOS_CANCEL, _(
"Cancel"),
184 wxDefaultPosition, wxDefaultSize, 0);
185 itemBoxSizer16->Add(m_CancelButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
187 m_OKButton =
new wxButton(itemDialog1, ID_GOTOPOS_OK, _(
"OK"),
188 wxDefaultPosition, wxDefaultSize, 0);
189 itemBoxSizer16->Add(m_OKButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
190 m_OKButton->SetDefault();
192 SetColorScheme((ColorScheme)0);
195void SetScaleDialog::SetColorScheme(ColorScheme cs) { DimeControl(
this); }
197void SetScaleDialog::OnSetScaleCancelClick(wxCommandEvent& event) {
202void SetScaleDialog::OnSetScaleOKClick(wxCommandEvent& event) {
203 SetReturnCode(wxID_OK);
213 wxSize DoGetBestSize()
const;
217 MUIButton(wxWindow* parent, wxWindowID
id = wxID_ANY,
218 float scale_factor = 1.0,
const wxString& bitmapState0 =
"",
219 const wxString& bitmapState1 =
"",
220 const wxString& bitmapState2 =
"",
221 const wxPoint& pos = wxDefaultPosition,
222 const wxSize& size = wxDefaultSize,
long style = wxNO_BORDER);
224 bool Create(wxWindow* parent, wxWindowID
id = wxID_ANY,
225 float scale_factor = 1.0,
const wxString& bitmapState0 =
"",
226 const wxString& bitmapState1 =
"",
227 const wxString& bitmapState2 =
"",
228 const wxPoint& pos = wxDefaultPosition,
229 const wxSize& size = wxDefaultSize,
long style = wxNO_BORDER);
234 void CreateControls();
236 void SetState(
int state);
237 int GetState() {
return mState; }
239 void SetColorScheme(ColorScheme cs);
240 void OnSize(wxSizeEvent& event);
241 void OnLeftDown(wxMouseEvent& event);
242 void OnLeftUp(wxMouseEvent& event);
244 wxBitmap GetBitmapResource(
const wxString& name);
246 wxIcon GetIconResource(
const wxString& name);
247 wxBitmap GetButtonBitmap() {
return m_bitmap; }
255 wxString m_bitmapFileState0;
256 wxString m_bitmapFileState1;
257 wxString m_bitmapFileState2;
259 wxBitmap m_bitmapState0;
260 wxBitmap m_bitmapState1;
261 wxBitmap m_bitmapState2;
265 wxSize m_styleToolSize;
269MUIButton::MUIButton() { Init(); }
271MUIButton::MUIButton(wxWindow* parent, wxWindowID
id,
float scale_factor,
272 const wxString& bitmap,
const wxString& bitmapState1,
273 const wxString& bitmapState2,
const wxPoint& pos,
274 const wxSize& size,
long style) {
277 Create(parent,
id, scale_factor, bitmap, bitmapState1, bitmapState2, pos,
281bool MUIButton::Create(wxWindow* parent, wxWindowID
id,
float scale_factor,
282 const wxString& bitmap,
const wxString& bitmapState1,
283 const wxString& bitmapState2,
const wxPoint& pos,
284 const wxSize& size,
long style) {
285 m_bitmapFileState0 = bitmap;
286 m_bitmapFileState1 = bitmapState1;
287 m_bitmapFileState2 = bitmapState2;
289 m_scaleFactor = scale_factor;
291 m_styleToolSize = g_StyleManager->GetCurrentStyle()->GetToolSize();
295 m_styleToolSize = wxSize(m_styleToolSize.x * 1.25, m_styleToolSize.y * 1.25);
297 m_size = wxSize(m_styleToolSize.x * m_scaleFactor,
298 m_styleToolSize.y * m_scaleFactor);
304MUIButton::~MUIButton() {}
306void MUIButton::Init() {
308 m_cs = (ColorScheme)-1;
311void MUIButton::CreateControls() {
321void MUIButton::SetColorScheme(ColorScheme cs) {
324 wxColour backColor = GetGlobalColor(
"GREY3");
329 wxBitmap bmp =
LoadSVG(m_bitmapFileState0, m_size.x, m_size.y);
330 m_bitmapState0 = style->SetBitmapBrightness(bmp, cs);
332 bmp =
LoadSVG(m_bitmapFileState1, m_size.x, m_size.y);
334 m_bitmapState1 = style->SetBitmapBrightness(bmp, cs);
336 m_bitmapState1 = m_bitmapState0;
338 bmp =
LoadSVG(m_bitmapFileState2, m_size.x, m_size.y);
340 m_bitmapState2 = style->SetBitmapBrightness(bmp, cs);
342 m_bitmapState2 = m_bitmapState0;
347 m_bitmap = m_bitmapState0;
351 m_bitmap = m_bitmapState1;
355 m_bitmap = m_bitmapState2;
366void MUIButton::SetState(
int state) {
370 m_bitmap = m_bitmapState0;
374 m_bitmap = m_bitmapState1;
378 m_bitmap = m_bitmapState2;
385void MUIButton::OnSize(wxSizeEvent& event) {
386 if (m_bitmap.IsOk()) {
387 if (event.GetSize() == m_bitmap.GetSize())
return;
390 if (!m_bitmapFileState0.IsEmpty())
392 LoadSVG(m_bitmapFileState0, event.GetSize().x, event.GetSize().y);
394 if (!m_bitmapFileState1.IsEmpty())
396 LoadSVG(m_bitmapFileState1, event.GetSize().x, event.GetSize().y);
397 if (!m_bitmapState1.IsOk() || m_bitmapFileState1.IsEmpty())
398 m_bitmapState1 = m_bitmapState0;
400 if (!m_bitmapFileState2.IsEmpty())
402 LoadSVG(m_bitmapFileState2, event.GetSize().x, event.GetSize().y);
403 if (!m_bitmapState2.IsOk() || m_bitmapFileState2.IsEmpty())
404 m_bitmapState2 = m_bitmapState0;
409 m_bitmap = m_bitmapState0;
413 m_bitmap = m_bitmapState1;
417 m_bitmap = m_bitmapState2;
422wxSize MUIButton::DoGetBestSize()
const {
427 return wxSize(m_styleToolSize.x * m_scaleFactor,
428 m_styleToolSize.y * m_scaleFactor);
434static std::unordered_map<char, ssfn_glyph_t*> ssfn_glyph_map;
440 char* fontdata = NULL;
444 unsigned char hdr[2];
448 f = fopen(filename,
"rb");
450 fprintf(stderr,
"unable to load %s\n", filename);
455 fread(&hdr, 2, 1, f);
456 if (hdr[0] == 0x1f && hdr[1] == 0x8b) {
457 fseek(f, -4L, SEEK_END);
458 fread(&size, 4, 1, f);
460 fseek(f, 0, SEEK_END);
464 g = gzopen(filename,
"r");
466 fseek(f, 0, SEEK_END);
468 fseek(f, 0, SEEK_SET);
471 fprintf(stderr,
"unable to load %s\n", filename);
474 fontdata = (
char*)malloc(size);
476 fprintf(stderr,
"memory allocation error\n");
480 gzread(g, fontdata, size);
483 IgnoreRetval(fread(fontdata, size, 1, f));
490bool RenderGlyphToImageBuffer(
unsigned char* buffer,
ssfn_glyph_t* glyph,
491 int x_offset,
int w,
int h,
int nominal_baseline,
492 wxColour& color, wxColour& back_color) {
493 unsigned char* src = glyph->data;
494 for (
int i = 0; i < h; i++) {
495 for (
int j = 0; j < glyph->w; j++) {
496 size_t index = i * w + j + x_offset;
497 index += (nominal_baseline - glyph->baseline) * w;
498 if (index > (
size_t)h * (w - 1))
continue;
499 size_t didx = index * 3;
501 size_t sidx = i * glyph->pitch + j;
502 unsigned char d = src[sidx];
504 buffer[didx] = (color.Red() * dn) + (back_color.Red() * (1 - dn));
505 buffer[didx + 1] = (color.Green() * dn) + (back_color.Green() * (1 - dn));
506 buffer[didx + 2] = (color.Blue() * dn) + (back_color.Blue() * (1 - dn));
512bool RenderStringToBuffer(
unsigned char* buffer, std::string s,
int wbox,
513 int hbox,
int nominal_baseline, wxColour color,
514 wxColour& back_color) {
516 for (
unsigned int i = 0; i < s.size(); i++) {
520 if (
auto findit = ssfn_glyph_map.find(key);
521 findit != ssfn_glyph_map.end()) {
522 glyph = findit->second;
525 ssfn_glyph_map[key] = glyph;
527 RenderGlyphToImageBuffer(buffer, glyph, xpos, wbox, hbox, nominal_baseline,
529 xpos += glyph->adv_x;
541 MUITextButton(wxWindow* parent, wxWindowID
id,
float scale_factor,
542 wxColor backColor,
const wxString& text =
"",
543 const wxPoint& pos = wxDefaultPosition,
544 const wxSize& size = wxDefaultSize,
long style = wxNO_BORDER);
546 bool Create(wxWindow* parent, wxWindowID
id,
float scale_factor = 1.0,
547 const wxString& text =
"",
const wxPoint& pos = wxDefaultPosition,
548 const wxSize& size = wxDefaultSize,
long style = wxNO_BORDER);
553 wxSize GetSize() {
return m_size; }
554 void SetState(
int state);
556 void SetColorScheme(ColorScheme cs);
557 void OnSize(wxSizeEvent& event);
558 void OnLeftDown(wxMouseEvent& event);
559 void OnLeftUp(wxMouseEvent& event);
560 void SetText(
const wxString& text);
562 wxBitmap GetButtonBitmap() {
return m_bitmap; }
574 wxSize m_styleToolSize;
578 wxColor m_backgrounColor;
581MUITextButton::MUITextButton() { Init(); }
583MUITextButton::MUITextButton(wxWindow* parent, wxWindowID
id,
584 float scale_factor, wxColor backColor,
585 const wxString& text,
const wxPoint& pos,
586 const wxSize& size,
long style) {
587 m_backgrounColor = backColor;
589 Create(parent,
id, scale_factor, text, pos, size, style);
592bool MUITextButton::Create(wxWindow* parent, wxWindowID
id,
float scale_factor,
593 const wxString& text,
const wxPoint& pos,
594 const wxSize& size,
long style) {
597 m_scaleFactor = scale_factor;
599 m_styleToolSize = g_StyleManager->GetCurrentStyle()->GetToolSize();
603 m_styleToolSize = wxSize(m_styleToolSize.x * 1.25, m_styleToolSize.y * 1.25);
605 int height_ref = m_styleToolSize.y;
608 memset(&ctx, 0,
sizeof(
ssfn_t));
609 wxString font_file = g_Platform->GetSharedDataDir() +
"ssfndata/FreeSans.sfn";
610 std::string sfont = font_file.ToStdString();
613 if (pssfn_font)
ssfn_load(&ctx, pssfn_font);
615 m_pixel_height = height_ref / 2;
616 m_pixel_height *= m_scaleFactor;
621 SSFN_STYLE_REGULAR, m_pixel_height,
628 if (m_ssfn_status == SSFN_OK) {
629 std::string t =
"1:888888";
630 ssfn_bbox(&ctx, (
char*)t.c_str(), 0, &wbox, &hbox);
633 m_size = wxSize(hbox * 1.5, m_styleToolSize.y);
634 m_size.y *= m_scaleFactor;
638MUITextButton::~MUITextButton() {
639 for (
const auto& [key, value] : ssfn_glyph_map) {
642 ssfn_glyph_map.clear();
645void MUITextButton::Init() {
647 m_cs = (ColorScheme)-1;
650void MUITextButton::SetText(
const wxString& text) {
651 if (!m_text.IsSameAs(text)) {
657void MUITextButton::SetColorScheme(ColorScheme cs) {
667void MUITextButton::SetState(
int state) { mState = state; }
669void MUITextButton::OnSize(wxSizeEvent& event) {
674void MUITextButton::BuildBitmap() {
675 int width = m_size.x;
676 int height = m_size.y;
678 if (m_ssfn_status != SSFN_OK)
return;
682 std::string t = m_text.ToStdString();
683 ssfn_bbox(&ctx, (
char*)t.c_str(), 0, &wbox, &hbox);
686 int baseline = glyph->baseline;
689 unsigned char* image_data = (
unsigned char*)calloc(1, wbox * hbox * 3);
690 for (
int i = 0; i < wbox * hbox; i++) {
692 image_data[idx] = m_backgrounColor.Red();
693 image_data[idx + 1] = m_backgrounColor.Green();
694 image_data[idx + 2] = m_backgrounColor.Blue();
697 RenderStringToBuffer(image_data, t, wbox, hbox, baseline,
698 GetGlobalColor(
"CHWHT"), m_backgrounColor);
700 wxImage fimage = wxImage(wbox, hbox, image_data);
701 wxSize clip_size = wxSize(wbox, baseline + 2);
702 wxRect clip_rect = wxRect(0, 0, clip_size.x, clip_size.y);
703 wxImage clip_image = fimage.GetSubImage(clip_rect);
705 m_bitmap = wxBitmap(clip_image);
708#define CANVAS_OPTIONS_ANIMATION_TIMER_1 800
709#define CANVAS_OPTIONS_TIMER 801
718MUIBar::MUIBar(
ChartCanvas* parent,
int orientation,
float size_factor,
719 wxWindowID
id,
const wxPoint& pos,
const wxSize& size,
720 long style,
const wxString& name) {
721 m_parentCanvas = parent;
722 m_orientation = orientation;
724 m_scaleFactor = size_factor;
725 m_cs = (ColorScheme)-1;
726 wxColour backColor = wxColor(*wxBLACK);
733 if (m_canvasOptions) {
734 m_canvasOptions->Destroy();
739 delete m_followButton;
741 delete m_scaleButton;
748 m_followButton = NULL;
750 m_scaleButton = NULL;
752 m_canvasOptions = NULL;
753 m_canvasOptionsAnimationTimer.SetOwner(
this,
754 CANVAS_OPTIONS_ANIMATION_TIMER_1);
755 m_backcolor = GetGlobalColor(
"GREY3");
756 m_capture_size_y = 0;
760 CanvasOptionTimer.SetOwner(
this, CANVAS_OPTIONS_TIMER);
761 m_coAnimateByBitmaps =
false;
767 m_end_margin = m_parentCanvas->GetCharWidth() / 2;
771void MUIBar::SetColorScheme(ColorScheme cs) {
773 if (m_zinButton) m_zinButton->SetColorScheme(cs);
774 if (m_zoutButton) m_zoutButton->SetColorScheme(cs);
775 if (m_followButton) m_followButton->SetColorScheme(cs);
776 if (m_menuButton) m_menuButton->SetColorScheme(cs);
778 if (m_scaleButton) m_scaleButton->SetColorScheme(cs);
784void MUIBar::InvalidateBitmap() {
785 m_bitmap = wxNullBitmap;
789 glDeleteTextures(1, &m_texture);
795bool MUIBar::MouseEvent(wxMouseEvent& event) {
797 event.GetPosition(&x, &y);
800 wxRect r = wxRect(m_screenPos, m_size);
801 if (r.Contains(x, y)) {
803 if (event.Moving() || event.Entering()) {
804 bool tooltipShown =
false;
807 if (m_followButton) {
808 wxRect rfollow(m_followButton->m_position.x,
809 m_followButton->m_position.y, m_followButton->m_size.x,
810 m_followButton->m_size.y);
811 rfollow.Offset(m_screenPos);
812 if (rfollow.Contains(x, y)) {
813 wxPoint screenPos = wxGetMousePosition();
817 m_parentCanvas, _(
"Follow Ship"), screenPos);
824 wxRect rmenu(m_menuButton->m_position.x, m_menuButton->m_position.y,
825 m_menuButton->m_size.x, m_menuButton->m_size.y);
826 rmenu.Offset(m_screenPos);
827 if (rmenu.Contains(x, y)) {
828 wxPoint screenPos = wxGetMousePosition();
832 m_parentCanvas, _(
"Options Menu"), screenPos);
838 if (!tooltipShown && g_bShowMuiZoomButtons) {
839 wxRect rzin(m_zinButton->m_position.x, m_zinButton->m_position.y,
840 m_zinButton->m_size.x, m_zinButton->m_size.y);
841 rzin.Offset(m_screenPos);
842 if (rzin.Contains(x, y)) {
843 wxPoint screenPos = wxGetMousePosition();
847 _(
"Zoom In"), screenPos);
850 wxRect rzout(m_zoutButton->m_position.x, m_zoutButton->m_position.y,
851 m_zoutButton->m_size.x, m_zoutButton->m_size.y);
852 rzout.Offset(m_screenPos);
853 if (rzout.Contains(x, y)) {
854 wxPoint screenPos = wxGetMousePosition();
858 m_parentCanvas, _(
"Zoom Out"), screenPos);
865 if (!tooltipShown && m_scaleButton) {
866 wxRect rscale(m_scaleButton->m_position.x, m_scaleButton->m_position.y,
867 m_scaleButton->m_size.x, m_scaleButton->m_size.y);
868 rscale.Offset(m_screenPos);
869 if (rscale.Contains(x, y)) {
870 wxPoint screenPos = wxGetMousePosition();
874 m_parentCanvas, _(
"Chart Scale"), screenPos);
881 if (event.LeftDown()) {
882 if (g_bShowMuiZoomButtons) {
883 wxRect rzin(m_zinButton->m_position.x, m_zinButton->m_position.y,
884 m_zinButton->m_size.x, m_zinButton->m_size.y);
885 rzin.Offset(m_screenPos);
886 if (rzin.Contains(x, y)) {
887 wxCommandEvent evt(wxEVT_COMMAND_MENU_SELECTED, ID_ZOOMIN);
888 m_parentCanvas->GetEventHandler()->AddPendingEvent(evt);
893 wxRect rzout(m_zoutButton->m_position.x, m_zoutButton->m_position.y,
894 m_zoutButton->m_size.x, m_zoutButton->m_size.y);
895 rzout.Offset(m_screenPos);
896 if (rzout.Contains(x, y)) {
897 wxCommandEvent evt(wxEVT_COMMAND_MENU_SELECTED, ID_ZOOMOUT);
898 m_parentCanvas->GetEventHandler()->AddPendingEvent(evt);
903 if (m_followButton) {
904 wxRect rfollow(m_followButton->m_position.x,
905 m_followButton->m_position.y, m_followButton->m_size.x,
906 m_followButton->m_size.y);
907 rfollow.Offset(m_screenPos);
908 if (rfollow.Contains(x, y)) {
909 wxCommandEvent evt(wxEVT_COMMAND_MENU_SELECTED, ID_FOLLOW);
910 m_parentCanvas->GetEventHandler()->AddPendingEvent(evt);
915 wxRect rmenu(m_menuButton->m_position.x, m_menuButton->m_position.y,
916 m_menuButton->m_size.x, m_menuButton->m_size.y);
917 rmenu.Offset(m_screenPos);
918 if (rmenu.Contains(x, y)) {
922 }
else if (event.LeftUp()) {
924 wxRect rscale(m_scaleButton->m_position.x, m_scaleButton->m_position.y,
925 m_scaleButton->m_size.x, m_scaleButton->m_size.y);
926 rscale.Offset(m_screenPos);
927 if (rscale.Contains(x, y)) {
928 OnScaleSelected(event);
935 if (event.Moving() || event.Leaving()) {
942void MUIBar::OnScaleSelected(wxMouseEvent& event) {
943 auto pcc =
dynamic_cast<ChartCanvas*
>(m_parentCanvas);
949 if (dlg.GetReturnCode() == wxID_OK) {
950 wxString newScale = dlg.m_ScaleCtl->GetValue();
951 if (newScale.Contains(
':')) newScale = newScale.AfterFirst(
':');
953 if (newScale.ToDouble(&dScale)) {
955 dScale = wxMin(dScale, 3e6);
956 dScale = wxMax(dScale, 1000);
957 double displayScaleNow = pcc->GetScaleValue();
958 double factor = displayScaleNow / dScale;
959 pcc->ZoomCanvasSimple(factor);
963 displayScaleNow = pcc->GetScaleValue();
964 factor = displayScaleNow / dScale;
965 pcc->ZoomCanvasSimple(factor);
970void MUIBar::SetCanvasENCAvailable(
bool avail) {
971 m_CanvasENCAvail = avail;
972 if (m_canvasOptions) m_canvasOptions->SetENCAvailable(avail);
975void MUIBar::CreateControls() {
976 wxString iconDir = g_Platform->GetSharedDataDir() +
"uidata/MUI_flat/";
980 iconDir +
"MUI_zoom-in.svg");
981 wxSize button_size = tb->m_size;
984 if (m_orientation == wxHORIZONTAL) {
988 if (g_bShowMuiZoomButtons) {
989 m_zinButton =
new MUIButton(m_parentCanvas, ID_ZOOMIN, m_scaleFactor,
990 iconDir +
"MUI_zoom-in.svg");
991 m_zinButton->m_position = wxPoint(xoff, 0);
992 xoff += m_zinButton->m_size.x;
994 m_zoutButton =
new MUIButton(m_parentCanvas, ID_ZOOMOUT, m_scaleFactor,
995 iconDir +
"MUI_zoom-out.svg");
996 m_zoutButton->m_position = wxPoint(xoff, 0);
997 xoff += m_zoutButton->m_size.x;
1003 m_scaleButton =
new MUITextButton(m_parentCanvas, wxID_ANY, m_scaleFactor,
1004 GetBackgroundColor(),
"1:400000");
1006 m_scaleButton->m_position = wxPoint(xoff, 0);
1007 if (m_scaleButton->GetButtonBitmap().IsOk()) {
1008 int bm_pos_y = (m_scaleButton->GetSize().y -
1009 m_scaleButton->GetButtonBitmap().GetHeight()) /
1011 m_scaleButton->m_position = wxPoint(xoff, bm_pos_y);
1013 xoff += m_scaleButton->m_size.x;
1016 m_parentCanvas, ID_FOLLOW, m_scaleFactor, iconDir +
"MUI_follow.svg",
1017 iconDir +
"MUI_follow_active.svg", iconDir +
"MUI_follow_ahead.svg");
1018 m_followButton->m_position = wxPoint(xoff, 0);
1019 xoff += m_followButton->m_size.x;
1022 m_menuButton =
new MUIButton(m_parentCanvas, ID_MUI_MENU, m_scaleFactor,
1023 iconDir +
"MUI_menu.svg");
1024 m_menuButton->m_position = wxPoint(xoff, 0);
1025 xoff += m_menuButton->m_size.x;
1027 m_size.y = button_size.y;
1033 if (g_bShowMuiZoomButtons) {
1034 m_zinButton =
new MUIButton(m_parentCanvas, ID_ZOOMIN, m_scaleFactor,
1035 iconDir +
"MUI_zoom-in.svg");
1036 m_zinButton->m_position = wxPoint(0, yoff);
1037 yoff += m_zinButton->m_size.y;
1039 m_zoutButton =
new MUIButton(m_parentCanvas, ID_ZOOMOUT, m_scaleFactor,
1040 iconDir +
"MUI_zoom-out.svg");
1041 m_zoutButton->m_position = wxPoint(0, yoff);
1042 yoff += m_zoutButton->m_size.y;
1047 m_parentCanvas, ID_FOLLOW, m_scaleFactor, iconDir +
"MUI_follow.svg",
1048 iconDir +
"MUI_follow_active.svg", iconDir +
"MUI_follow_ahead.svg");
1049 m_followButton->m_position = wxPoint(0, yoff);
1050 yoff += m_followButton->m_size.y;
1053 m_menuButton =
new MUIButton(m_parentCanvas, ID_MUI_MENU, m_scaleFactor,
1054 iconDir +
"MUI_menu.svg");
1055 m_menuButton->m_position = wxPoint(0, yoff);
1056 yoff += m_menuButton->m_size.y;
1059 m_size.x = button_size.x;
1063void MUIBar::SetBestPosition() {
1065 (m_parentCanvas->GetClientSize().x - (m_size.x + (m_end_margin) * 2.00));
1067 int bottomOffset = 6;
1069 int y = m_parentCanvas->GetClientSize().y - m_size.y - bottomOffset;
1074 wxPoint position = wxPoint(x, y);
1075 m_screenPos = position;
1077 if (m_canvasOptions) {
1078 m_canvasOptions->Destroy();
1079 m_canvasOptions = 0;
1083void MUIBar::UpdateDynamicValues() {
1084 if (!m_scaleButton)
return;
1086 wxString scaleString;
1087 int scale = m_parentCanvas->GetScaleValue();
1089 if (
scale != m_scale) InvalidateBitmap();
1093 scaleString.Printf(
"1:%d",
scale);
1095 scaleString.Printf(
"1:%4.1f M",
scale / 1e6);
1097 if (m_scaleButton) m_scaleButton->SetText(scaleString);
1100void MUIBar::SetFollowButtonState(
int state) {
1101 if (m_followButton && m_followButton->GetState() != state) {
1102 m_followButton->SetState(state);
1107void MUIBar::HandleMenuClick() {
1108 if (!m_canvasOptions) {
1113 wxPoint parentClientUpperRight =
1114 m_parentCanvas->ClientToScreen(wxPoint(m_parentCanvas->GetSize().x, 0));
1115 wxPoint muibar_top = m_parentCanvas->ClientToScreen(m_screenPos);
1116 int size_y = muibar_top.y - (parentClientUpperRight.y + m_COTopOffset);
1117 size_y -= m_parentCanvas->GetCharHeight();
1118 size_y = wxMax(size_y, 100);
1120 m_canvasOptions->SetSize(wxSize(-1, size_y));
1121 m_canvasOptionsFullSize = m_canvasOptions->GetSize();
1122 m_canvasOptionsFullSize.x +=
1123 m_canvasOptions->GetCharWidth();
1126 m_currentCOPos = m_parentCanvas->ClientToScreen(
1127 wxPoint(m_parentCanvas->GetSize().x, m_COTopOffset));
1129 m_canvasOptions->Move(m_currentCOPos);
1130 m_canvasOptions->Hide();
1133 m_canvasOptions->SetENCAvailable(m_CanvasENCAvail);
1135 if (m_canvasOptions->IsShown())
1136 PushCanvasOptions();
1140 if (m_coAnimateByBitmaps && m_capture_size_y) {
1141 int overShoot_x = m_canvasOptions->GetSize().x * 2 / 10;
1143 wxPoint(m_capturePoint.x - overShoot_x, m_capturePoint.y);
1145 m_backingBitmap = wxBitmap(m_canvasOptionsFullSize.x + overShoot_x,
1146 m_capture_size_y, -1);
1148 mdcb.SelectObject(m_backingBitmap);
1150 mdcb.Blit(0, 0, m_canvasOptionsFullSize.x + overShoot_x, m_capture_size_y,
1151 &sdc, m_capturePoint.x - overShoot_x, m_capturePoint.y, wxCOPY);
1152 mdcb.SelectObject(wxNullBitmap);
1154 PullCanvasOptions();
1158void MUIBar::CaptureCanvasOptionsBitmap() {
1160 CanvasOptionTimer.Start(100, wxTIMER_ONE_SHOT);
1163void MUIBar::CaptureCanvasOptionsBitmapChain(wxTimerEvent& event) {
1164 if (m_coSequence == 0) {
1165 if (!m_canvasOptions) m_canvasOptions =
new CanvasOptions(m_parentCanvas);
1167 wxPoint parentClientUpperRight =
1168 m_parentCanvas->ClientToScreen(wxPoint(m_parentCanvas->GetSize().x, 0));
1169 wxRect rmui = m_parentCanvas->GetMUIBarRect();
1170 int size_y = rmui.y - (parentClientUpperRight.y + m_COTopOffset);
1171 size_y -= m_parentCanvas->GetCharHeight();
1172 size_y = wxMax(size_y, 100);
1173 m_capture_size_y = size_y;
1175 m_canvasOptions->SetSize(wxSize(-1, size_y));
1177 m_capturePoint = m_parentCanvas->ClientToScreen(
1178 wxPoint(m_parentCanvas->GetSize().x, m_COTopOffset));
1179 m_canvasOptions->Move(m_capturePoint);
1180 m_canvasOptions->Show();
1183 CanvasOptionTimer.Start(1, wxTIMER_ONE_SHOT);
1186 else if (m_coSequence == 1) {
1187 m_capturePoint = m_parentCanvas->ClientToScreen(
1188 wxPoint(m_parentCanvas->GetSize().x - m_canvasOptionsFullSize.x,
1190 m_canvasOptions->Move(m_capturePoint);
1193 CanvasOptionTimer.Start(1, wxTIMER_ONE_SHOT);
1196 else if (m_coSequence == 2) {
1198 wxBitmap(m_canvasOptions->GetSize().x, m_capture_size_y, -1);
1199 wxMemoryDC mdc(m_animateBitmap);
1203 mdc.Blit(0, 0, m_canvasOptions->GetSize().x, m_capture_size_y, &sdc,
1204 m_capturePoint.x, m_capturePoint.y, wxCOPY);
1205 mdc.SelectObject(wxNullBitmap);
1212wxBitmap& MUIBar::CreateBitmap(
double displayScale) {
1213 if (m_bitmap.IsOk())
return m_bitmap;
1216 int width = m_size.x;
1217 int height = m_size.y;
1220 wxBitmap bm(width, height);
1221 mdc.SelectObject(bm);
1222 mdc.SetBackground(wxBrush(GetBackgroundColor()));
1227 if (g_bShowMuiZoomButtons) {
1228 wxBitmap bmd = m_zinButton->GetButtonBitmap();
1230 mdc.DrawBitmap(bmd, m_zinButton->m_position.x, m_zinButton->m_position.y,
1233 bmd = m_zoutButton->GetButtonBitmap();
1235 mdc.DrawBitmap(bmd, m_zoutButton->m_position.x,
1236 m_zoutButton->m_position.y,
false);
1239 if (m_scaleButton) {
1240 bmd = m_scaleButton->GetButtonBitmap();
1242 int bm_pos_y = (m_scaleButton->GetSize().y - bmd.GetHeight()) / 2;
1243 int bm_pos_x = m_scaleButton->m_position.x +
1244 (m_scaleButton->GetSize().x - bmd.GetWidth()) / 2;
1246 mdc.DrawBitmap(bmd, bm_pos_x, bm_pos_y,
false);
1250 if (m_followButton) {
1251 bmd = m_followButton->GetButtonBitmap();
1253 mdc.DrawBitmap(bmd, m_followButton->m_position.x,
1254 m_followButton->m_position.y,
false);
1258 bmd = m_menuButton->GetButtonBitmap();
1260 mdc.DrawBitmap(bmd, m_menuButton->m_position.x,
1261 m_menuButton->m_position.y,
false);
1264 mdc.SelectObject(wxNullBitmap);
1270void MUIBar::DrawGL(
ocpnDC& gldc,
double displayScale) {
1273 wxColour backColor = GetBackgroundColor();
1274 gldc.SetBrush(wxBrush(backColor));
1275 gldc.SetPen(wxPen(backColor));
1277 wxRect r = wxRect(m_screenPos, m_size);
1278 if (m_orientation == wxHORIZONTAL)
1279 gldc.DrawRoundedRectangle(
1280 (r.x - m_end_margin / 2) * displayScale, (r.y - 1) * displayScale,
1281 (r.width + m_end_margin) * displayScale, (r.height + 2) * displayScale,
1282 (m_end_margin * 1) * displayScale);
1284 gldc.DrawRoundedRectangle((r.x - 1) * displayScale,
1285 (r.y - m_end_margin / 2) * displayScale,
1286 (r.width + 2) * displayScale,
1287 (r.height + 2 * m_end_margin) * displayScale,
1288 (m_end_margin * 1.5) * displayScale);
1290 int width = m_size.x;
1291 int height = m_size.y;
1293 CreateBitmap(displayScale);
1297 glGenTextures(1, &m_texture);
1299 glBindTexture(g_texture_rectangle_format, m_texture);
1300 glTexParameterf(g_texture_rectangle_format, GL_TEXTURE_MIN_FILTER,
1302 glTexParameteri(g_texture_rectangle_format, GL_TEXTURE_MAG_FILTER,
1304 glTexParameteri(g_texture_rectangle_format, GL_TEXTURE_WRAP_S,
1306 glTexParameteri(g_texture_rectangle_format, GL_TEXTURE_WRAP_T,
1309 glBindTexture(g_texture_rectangle_format, m_texture);
1313 if (m_bitmap.IsOk()) {
1314 wxImage image = m_bitmap.ConvertToImage();
1316 unsigned char* d = image.GetData();
1318 unsigned char* e =
new unsigned char[4 * width * height];
1319 for (
int y = 0; y < height; y++)
1320 for (
int x = 0; x < width; x++) {
1321 int i = y * width + x;
1322 memcpy(e + 4 * i, d + 3 * i, 3);
1326 glTexImage2D(g_texture_rectangle_format, 0, GL_RGBA, width, height, 0,
1327 GL_RGBA, GL_UNSIGNED_BYTE, e);
1329 glDisable(g_texture_rectangle_format);
1330 glDisable(GL_BLEND);
1337 glEnable(g_texture_rectangle_format);
1338 glBindTexture(g_texture_rectangle_format, m_texture);
1341 int x0 = m_screenPos.x, x1 = x0 + width;
1342 int y0 = m_screenPos.y - 0, y1 = y0 + height;
1349 if (GL_TEXTURE_RECTANGLE_ARB == g_texture_rectangle_format)
1350 tx = width, ty = height;
1377 m_parentCanvas->GetglCanvas()->RenderTextures(gldc, coords, uv, 4,
1378 m_parentCanvas->GetpVP());
1380 glDisable(g_texture_rectangle_format);
1381 glBindTexture(g_texture_rectangle_format, 0);
1382 glDisable(GL_BLEND);
1389void MUIBar::DrawDC(
ocpnDC& dc,
double displayScale) {
1391 dc.DrawBitmap(m_bitmap, m_screenPos.x, m_screenPos.y,
false);
1394void MUIBar::ResetCanvasOptions() {
1395 delete m_canvasOptions;
1396 m_canvasOptions = NULL;
1399void MUIBar::PullCanvasOptions() {
1401 int cox = m_parentCanvas->GetSize().x - m_canvasOptionsFullSize.x;
1402 int coy = m_COTopOffset;
1403 m_targetCOPos = m_parentCanvas->ClientToScreen(wxPoint(cox, coy));
1406 m_canvasOptions->Move(m_targetCOPos);
1407 m_canvasOptions->Show();
1413 if (m_coAnimateByBitmaps && !m_animateBitmap.IsOk()) {
1414 m_canvasOptions->Move(m_targetCOPos);
1415 m_canvasOptions->Show();
1416 CaptureCanvasOptionsBitmap();
1422 m_startCOPos = m_canvasOptions->GetPosition();
1425 m_currentCOPos = m_startCOPos;
1428 m_animateSteps = 10;
1429 m_animationTotalTime = 200;
1432 auto pcc =
dynamic_cast<ChartCanvas*
>(m_parentCanvas);
1433 pcc->m_b_paint_enable =
false;
1437 m_canvasOptionsAnimationTimer.Start(10,
true);
1438 m_canvasOptions->Move(m_targetCOPos);
1439 m_canvasOptions->Hide();
1442void MUIBar::PushCanvasOptions() {
1444 m_canvasOptions->Hide();
1451 int cox = m_parentCanvas->GetSize().x;
1455 m_targetCOPos = m_parentCanvas->ClientToScreen(wxPoint(cox, coy));
1457 m_targetCOPos = wxPoint(cox, coy);
1460 m_startCOPos = m_canvasOptions->GetPosition();
1463 m_currentCOPos = m_startCOPos;
1468 m_animationTotalTime = 100;
1470 auto pcc =
dynamic_cast<ChartCanvas*
>(m_parentCanvas);
1474 m_canvasOptionsAnimationTimer.Start(10,
true);
1475 m_canvasOptions->Show();
1478void MUIBar::onCanvasOptionsAnimationTimerEvent(wxTimerEvent& event) {
1479 double progress = m_animateStep / (double)m_animateSteps;
1480 double valueX = getValue(m_animationType, progress);
1482 double dx = (m_targetCOPos.x - m_startCOPos.x) * valueX;
1484 wxPoint newPos = wxPoint(m_startCOPos.x + dx, m_currentCOPos.y);
1490 size_x = (m_targetCOPos.x - m_startCOPos.x) - abs(dx);
1492 if (!m_coAnimateByBitmaps) {
1493 m_canvasOptions->SetSize(newPos.x, newPos.y, size_x, wxDefaultCoord,
1494 wxSIZE_USE_EXISTING);
1496 m_canvasOptions->Show();
1498 m_canvasOptions->Hide();
1503 if (m_backingBitmap.IsOk()) {
1504 wxMemoryDC mdc_back(m_backingBitmap);
1505 sdc.Blit(m_backingPoint.x, m_backingPoint.y,
1506 m_backingBitmap.GetWidth() - size_x,
1507 m_backingBitmap.GetHeight(), &mdc_back, 0, 0, wxCOPY);
1511 wxMemoryDC mdc(m_animateBitmap);
1512 sdc.Blit(newPos.x, newPos.y, size_x, m_animateBitmap.GetHeight(), &mdc, 0,
1514 mdc.SelectObject(wxNullBitmap);
1517 m_currentCOPos = newPos;
1519 double dt = m_animationTotalTime / m_animateSteps;
1521 if (m_animateStep++ < m_animateSteps + 1) {
1522 m_canvasOptionsAnimationTimer.Start(dt,
true);
1524 m_currentCOPos = m_targetCOPos;
1525 m_canvasOptions->Show(m_pushPull ==
CO_PULL);
1527 auto pcc =
dynamic_cast<ChartCanvas*
>(m_parentCanvas);
1529 pcc->m_b_paint_enable =
true;
1532 delete m_canvasOptions;
1533 m_canvasOptions = NULL;
1536 if (m_pushPull ==
CO_PUSH) pcc->TriggerDeferredFocus();
1538 pcc->TriggerDeferredFocus();
1548double bounceMaker(
double t,
double c,
double a) {
1549 if (t == 1.0)
return c;
1550 if (t < (4 / 11.0)) {
1551 return c * (7.5625 * t * t);
1552 }
else if (t < (8 / 11.0)) {
1554 return -a * (1. - (7.5625 * t * t + .75)) + c;
1555 }
else if (t < (10 / 11.0)) {
1557 return -a * (1. - (7.5625 * t * t + .9375)) + c;
1560 return -a * (1. - (7.5625 * t * t + .984375)) + c;
1564double getValue(
int animationType,
double t) {
1568 switch (animationType) {
1575 value = tp * tp * tp + 1;
1580 value = tp * tp * tp + 1;
1583 value = bounceMaker(t, 1, s);
1588 value = tp * tp * ((s + 1) * tp + s) + 1;
Class CanvasOptions and helpers – Canvas options Window/Dialog.
ChartCanvas * g_focusCanvas
Global instance.
Generic Chart canvas base.
Represents the Canvas Options dialog.
ChartCanvas - Main chart display and interaction component.
bool Create(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &caption=_("Set scale"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxDEFAULT_DIALOG_STYLE)
Creation.
wxTextCtrl * m_ScaleCtl
Should we show tooltips?
SetScaleDialog()
Constructors.
Device context class that can use either wxDC or OpenGL for drawing.
Global color handling by name.
Global variables stored in configuration file.
Chart display details slider.
OpenGL chart rendering canvas.
GUI constant definitions.
ssfn_font_t * load_font(const char *filename)
Load a font.
MUI (Modern User Interface) Control bar.
@ CO_ANIMATION_CUBIC_REVERSE
Reversed cubic animation.
@ CO_ANIMATION_CUBIC_BACK_IN
Cubic animation with back-in effect.
@ CO_ANIMATION_CUBIC
Cubic animation.
@ CO_ANIMATION_CUBIC_BOUNCE_IN
Cubic animation with bounce-in effect.
@ CO_ANIMATION_LINEAR
Linear animation.
PlugInManager and helper classes – Mostly gui parts (dialogs) and plugin API stuff.
Scalable Screen Font renderer in a single ANSI C/C++ header.
int ssfn_select(ssfn_t *ctx, int family, char *name, int style, int size, int mode)
Set up rendering parameters.
int ssfn_load(ssfn_t *ctx, const ssfn_font_t *font)
Load a font or font collection into renderer context.
ssfn_glyph_t * ssfn_render(ssfn_t *ctx, uint32_t unicode)
Glyph renderer.
int ssfn_bbox(ssfn_t *ctx, char *str, int usekern, int *w, int *h)
Returns the bounding box of the rendered text.
wxBitmap LoadSVG(const wxString filename, const unsigned int width, const unsigned int height, wxBitmap *default_bitmap, bool use_cache)
Load SVG file and return it's bitmap representation of requested size In case file can't be loaded an...