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);
953 if (dlg.GetReturnCode() == wxID_OK) {
954 wxString newScale = dlg.m_ScaleCtl->GetValue();
955 if (newScale.Contains(
':')) newScale = newScale.AfterFirst(
':');
957 if (newScale.ToDouble(&dScale)) {
959 dScale = wxMin(dScale, 3e6);
960 dScale = wxMax(dScale, 1000);
961 double displayScaleNow = pcc->GetScaleValue();
962 double factor = displayScaleNow / dScale;
963 pcc->ZoomCanvasSimple(factor);
967 displayScaleNow = pcc->GetScaleValue();
968 factor = displayScaleNow / dScale;
969 pcc->ZoomCanvasSimple(factor);
974void MUIBar::SetCanvasENCAvailable(
bool avail) {
975 m_CanvasENCAvail = avail;
976 if (m_canvasOptions) m_canvasOptions->SetENCAvailable(avail);
979void MUIBar::CreateControls() {
980 wxString iconDir = g_Platform->GetSharedDataDir() +
"uidata/MUI_flat/";
984 iconDir +
"MUI_zoom-in.svg");
985 wxSize button_size = tb->m_size;
988 if (m_orientation == wxHORIZONTAL) {
992 if (g_bShowMuiZoomButtons) {
993 m_zinButton =
new MUIButton(m_parentCanvas, ID_ZOOMIN, m_scaleFactor,
994 iconDir +
"MUI_zoom-in.svg");
995 m_zinButton->m_position = wxPoint(xoff, 0);
996 xoff += m_zinButton->m_size.x;
998 m_zoutButton =
new MUIButton(m_parentCanvas, ID_ZOOMOUT, m_scaleFactor,
999 iconDir +
"MUI_zoom-out.svg");
1000 m_zoutButton->m_position = wxPoint(xoff, 0);
1001 xoff += m_zoutButton->m_size.x;
1007 m_scaleButton =
new MUITextButton(m_parentCanvas, wxID_ANY, m_scaleFactor,
1008 GetBackgroundColor(),
"1:400000");
1010 m_scaleButton->m_position = wxPoint(xoff, 0);
1011 if (m_scaleButton->GetButtonBitmap().IsOk()) {
1012 int bm_pos_y = (m_scaleButton->GetSize().y -
1013 m_scaleButton->GetButtonBitmap().GetHeight()) /
1015 m_scaleButton->m_position = wxPoint(xoff, bm_pos_y);
1017 xoff += m_scaleButton->m_size.x;
1020 m_parentCanvas, ID_FOLLOW, m_scaleFactor, iconDir +
"MUI_follow.svg",
1021 iconDir +
"MUI_follow_active.svg", iconDir +
"MUI_follow_ahead.svg");
1022 m_followButton->m_position = wxPoint(xoff, 0);
1023 xoff += m_followButton->m_size.x;
1026 m_menuButton =
new MUIButton(m_parentCanvas, ID_MUI_MENU, m_scaleFactor,
1027 iconDir +
"MUI_menu.svg");
1028 m_menuButton->m_position = wxPoint(xoff, 0);
1029 xoff += m_menuButton->m_size.x;
1031 m_size.y = button_size.y;
1037 if (g_bShowMuiZoomButtons) {
1038 m_zinButton =
new MUIButton(m_parentCanvas, ID_ZOOMIN, m_scaleFactor,
1039 iconDir +
"MUI_zoom-in.svg");
1040 m_zinButton->m_position = wxPoint(0, yoff);
1041 yoff += m_zinButton->m_size.y;
1043 m_zoutButton =
new MUIButton(m_parentCanvas, ID_ZOOMOUT, m_scaleFactor,
1044 iconDir +
"MUI_zoom-out.svg");
1045 m_zoutButton->m_position = wxPoint(0, yoff);
1046 yoff += m_zoutButton->m_size.y;
1051 m_parentCanvas, ID_FOLLOW, m_scaleFactor, iconDir +
"MUI_follow.svg",
1052 iconDir +
"MUI_follow_active.svg", iconDir +
"MUI_follow_ahead.svg");
1053 m_followButton->m_position = wxPoint(0, yoff);
1054 yoff += m_followButton->m_size.y;
1057 m_menuButton =
new MUIButton(m_parentCanvas, ID_MUI_MENU, m_scaleFactor,
1058 iconDir +
"MUI_menu.svg");
1059 m_menuButton->m_position = wxPoint(0, yoff);
1060 yoff += m_menuButton->m_size.y;
1063 m_size.x = button_size.x;
1067void MUIBar::SetBestPosition() {
1069 (m_parentCanvas->GetClientSize().x - (m_size.x + (m_end_margin) * 2.00));
1071 int bottomOffset = 6;
1073 int y = m_parentCanvas->GetClientSize().y - m_size.y - bottomOffset;
1078 wxPoint position = wxPoint(x, y);
1079 m_screenPos = position;
1081 if (m_canvasOptions) {
1082 m_canvasOptions->Destroy();
1083 m_canvasOptions = 0;
1087void MUIBar::UpdateDynamicValues() {
1088 if (!m_scaleButton)
return;
1090 wxString scaleString;
1091 int scale = m_parentCanvas->GetScaleValue();
1093 if (
scale != m_scale) InvalidateBitmap();
1097 scaleString.Printf(
"1:%d",
scale);
1099 scaleString.Printf(
"1:%4.1f M",
scale / 1e6);
1101 if (m_scaleButton) m_scaleButton->SetText(scaleString);
1104void MUIBar::SetFollowButtonState(
int state) {
1105 if (m_followButton && m_followButton->GetState() != state) {
1106 m_followButton->SetState(state);
1111void MUIBar::HandleMenuClick() {
1112 if (!m_canvasOptions) {
1117 wxPoint parentClientUpperRight =
1118 m_parentCanvas->ClientToScreen(wxPoint(m_parentCanvas->GetSize().x, 0));
1119 wxPoint muibar_top = m_parentCanvas->ClientToScreen(m_screenPos);
1120 int size_y = muibar_top.y - (parentClientUpperRight.y + m_COTopOffset);
1121 size_y -= m_parentCanvas->GetCharHeight();
1122 size_y = wxMax(size_y, 100);
1124 m_canvasOptions->SetSize(wxSize(-1, size_y));
1125 m_canvasOptionsFullSize = m_canvasOptions->GetSize();
1126 m_canvasOptionsFullSize.x +=
1127 m_canvasOptions->GetCharWidth();
1130 m_currentCOPos = m_parentCanvas->ClientToScreen(
1131 wxPoint(m_parentCanvas->GetSize().x, m_COTopOffset));
1133 m_canvasOptions->Move(m_currentCOPos);
1134 m_canvasOptions->Hide();
1137 m_canvasOptions->SetENCAvailable(m_CanvasENCAvail);
1139 if (m_canvasOptions->IsShown())
1140 PushCanvasOptions();
1144 if (m_coAnimateByBitmaps && m_capture_size_y) {
1145 int overShoot_x = m_canvasOptions->GetSize().x * 2 / 10;
1147 wxPoint(m_capturePoint.x - overShoot_x, m_capturePoint.y);
1149 m_backingBitmap = wxBitmap(m_canvasOptionsFullSize.x + overShoot_x,
1150 m_capture_size_y, -1);
1152 mdcb.SelectObject(m_backingBitmap);
1154 mdcb.Blit(0, 0, m_canvasOptionsFullSize.x + overShoot_x, m_capture_size_y,
1155 &sdc, m_capturePoint.x - overShoot_x, m_capturePoint.y, wxCOPY);
1156 mdcb.SelectObject(wxNullBitmap);
1158 PullCanvasOptions();
1162void MUIBar::CaptureCanvasOptionsBitmap() {
1164 CanvasOptionTimer.Start(100, wxTIMER_ONE_SHOT);
1167void MUIBar::CaptureCanvasOptionsBitmapChain(wxTimerEvent& event) {
1168 if (m_coSequence == 0) {
1169 if (!m_canvasOptions) m_canvasOptions =
new CanvasOptions(m_parentCanvas);
1171 wxPoint parentClientUpperRight =
1172 m_parentCanvas->ClientToScreen(wxPoint(m_parentCanvas->GetSize().x, 0));
1173 wxRect rmui = m_parentCanvas->GetMUIBarRect();
1174 int size_y = rmui.y - (parentClientUpperRight.y + m_COTopOffset);
1175 size_y -= m_parentCanvas->GetCharHeight();
1176 size_y = wxMax(size_y, 100);
1177 m_capture_size_y = size_y;
1179 m_canvasOptions->SetSize(wxSize(-1, size_y));
1181 m_capturePoint = m_parentCanvas->ClientToScreen(
1182 wxPoint(m_parentCanvas->GetSize().x, m_COTopOffset));
1183 m_canvasOptions->Move(m_capturePoint);
1184 m_canvasOptions->Show();
1187 CanvasOptionTimer.Start(1, wxTIMER_ONE_SHOT);
1190 else if (m_coSequence == 1) {
1191 m_capturePoint = m_parentCanvas->ClientToScreen(
1192 wxPoint(m_parentCanvas->GetSize().x - m_canvasOptionsFullSize.x,
1194 m_canvasOptions->Move(m_capturePoint);
1197 CanvasOptionTimer.Start(1, wxTIMER_ONE_SHOT);
1200 else if (m_coSequence == 2) {
1202 wxBitmap(m_canvasOptions->GetSize().x, m_capture_size_y, -1);
1203 wxMemoryDC mdc(m_animateBitmap);
1207 mdc.Blit(0, 0, m_canvasOptions->GetSize().x, m_capture_size_y, &sdc,
1208 m_capturePoint.x, m_capturePoint.y, wxCOPY);
1209 mdc.SelectObject(wxNullBitmap);
1216wxBitmap& MUIBar::CreateBitmap(
double displayScale) {
1217 if (m_bitmap.IsOk())
return m_bitmap;
1220 int width = m_size.x;
1221 int height = m_size.y;
1224 wxBitmap bm(width, height);
1225 mdc.SelectObject(bm);
1226 mdc.SetBackground(wxBrush(GetBackgroundColor()));
1231 if (g_bShowMuiZoomButtons) {
1232 wxBitmap bmd = m_zinButton->GetButtonBitmap();
1234 mdc.DrawBitmap(bmd, m_zinButton->m_position.x, m_zinButton->m_position.y,
1237 bmd = m_zoutButton->GetButtonBitmap();
1239 mdc.DrawBitmap(bmd, m_zoutButton->m_position.x,
1240 m_zoutButton->m_position.y,
false);
1243 if (m_scaleButton) {
1244 bmd = m_scaleButton->GetButtonBitmap();
1246 int bm_pos_y = (m_scaleButton->GetSize().y - bmd.GetHeight()) / 2;
1247 int bm_pos_x = m_scaleButton->m_position.x +
1248 (m_scaleButton->GetSize().x - bmd.GetWidth()) / 2;
1250 mdc.DrawBitmap(bmd, bm_pos_x, bm_pos_y,
false);
1254 if (m_followButton) {
1255 bmd = m_followButton->GetButtonBitmap();
1257 mdc.DrawBitmap(bmd, m_followButton->m_position.x,
1258 m_followButton->m_position.y,
false);
1262 bmd = m_menuButton->GetButtonBitmap();
1264 mdc.DrawBitmap(bmd, m_menuButton->m_position.x,
1265 m_menuButton->m_position.y,
false);
1268 mdc.SelectObject(wxNullBitmap);
1274void MUIBar::DrawGL(
ocpnDC& gldc,
double displayScale) {
1277 wxColour backColor = GetBackgroundColor();
1278 gldc.SetBrush(wxBrush(backColor));
1279 gldc.SetPen(wxPen(backColor));
1281 wxRect r = wxRect(m_screenPos, m_size);
1282 if (m_orientation == wxHORIZONTAL)
1283 gldc.DrawRoundedRectangle(
1284 (r.x - m_end_margin / 2) * displayScale, (r.y - 1) * displayScale,
1285 (r.width + m_end_margin) * displayScale, (r.height + 2) * displayScale,
1286 (m_end_margin * 1) * displayScale);
1288 gldc.DrawRoundedRectangle((r.x - 1) * displayScale,
1289 (r.y - m_end_margin / 2) * displayScale,
1290 (r.width + 2) * displayScale,
1291 (r.height + 2 * m_end_margin) * displayScale,
1292 (m_end_margin * 1.5) * displayScale);
1294 int width = m_size.x;
1295 int height = m_size.y;
1297 CreateBitmap(displayScale);
1301 glGenTextures(1, &m_texture);
1303 glBindTexture(g_texture_rectangle_format, m_texture);
1304 glTexParameterf(g_texture_rectangle_format, GL_TEXTURE_MIN_FILTER,
1306 glTexParameteri(g_texture_rectangle_format, GL_TEXTURE_MAG_FILTER,
1308 glTexParameteri(g_texture_rectangle_format, GL_TEXTURE_WRAP_S,
1310 glTexParameteri(g_texture_rectangle_format, GL_TEXTURE_WRAP_T,
1313 glBindTexture(g_texture_rectangle_format, m_texture);
1317 if (m_bitmap.IsOk()) {
1318 wxImage image = m_bitmap.ConvertToImage();
1320 unsigned char* d = image.GetData();
1322 unsigned char* e =
new unsigned char[4 * width * height];
1323 for (
int y = 0; y < height; y++)
1324 for (
int x = 0; x < width; x++) {
1325 int i = y * width + x;
1326 memcpy(e + 4 * i, d + 3 * i, 3);
1330 glTexImage2D(g_texture_rectangle_format, 0, GL_RGBA, width, height, 0,
1331 GL_RGBA, GL_UNSIGNED_BYTE, e);
1333 glDisable(g_texture_rectangle_format);
1334 glDisable(GL_BLEND);
1341 glEnable(g_texture_rectangle_format);
1342 glBindTexture(g_texture_rectangle_format, m_texture);
1345 int x0 = m_screenPos.x, x1 = x0 + width;
1346 int y0 = m_screenPos.y - 0, y1 = y0 + height;
1353 if (GL_TEXTURE_RECTANGLE_ARB == g_texture_rectangle_format)
1354 tx = width, ty = height;
1381 m_parentCanvas->GetglCanvas()->RenderTextures(gldc, coords, uv, 4,
1382 m_parentCanvas->GetpVP());
1384 glDisable(g_texture_rectangle_format);
1385 glBindTexture(g_texture_rectangle_format, 0);
1386 glDisable(GL_BLEND);
1393void MUIBar::DrawDC(
ocpnDC& dc,
double displayScale) {
1395 dc.DrawBitmap(m_bitmap, m_screenPos.x, m_screenPos.y,
false);
1398void MUIBar::ResetCanvasOptions() {
1399 delete m_canvasOptions;
1400 m_canvasOptions = NULL;
1403void MUIBar::PullCanvasOptions() {
1405 int cox = m_parentCanvas->GetSize().x - m_canvasOptionsFullSize.x;
1406 int coy = m_COTopOffset;
1407 m_targetCOPos = m_parentCanvas->ClientToScreen(wxPoint(cox, coy));
1410 m_canvasOptions->Move(m_targetCOPos);
1411 m_canvasOptions->Show();
1417 if (m_coAnimateByBitmaps && !m_animateBitmap.IsOk()) {
1418 m_canvasOptions->Move(m_targetCOPos);
1419 m_canvasOptions->Show();
1420 CaptureCanvasOptionsBitmap();
1426 m_startCOPos = m_canvasOptions->GetPosition();
1429 m_currentCOPos = m_startCOPos;
1432 m_animateSteps = 10;
1433 m_animationTotalTime = 200;
1436 auto pcc =
dynamic_cast<ChartCanvas*
>(m_parentCanvas);
1437 pcc->m_b_paint_enable =
false;
1441 m_canvasOptionsAnimationTimer.Start(10,
true);
1442 m_canvasOptions->Move(m_targetCOPos);
1443 m_canvasOptions->Hide();
1446void MUIBar::PushCanvasOptions() {
1448 m_canvasOptions->Hide();
1455 int cox = m_parentCanvas->GetSize().x;
1459 m_targetCOPos = m_parentCanvas->ClientToScreen(wxPoint(cox, coy));
1461 m_targetCOPos = wxPoint(cox, coy);
1464 m_startCOPos = m_canvasOptions->GetPosition();
1467 m_currentCOPos = m_startCOPos;
1472 m_animationTotalTime = 100;
1474 auto pcc =
dynamic_cast<ChartCanvas*
>(m_parentCanvas);
1478 m_canvasOptionsAnimationTimer.Start(10,
true);
1479 m_canvasOptions->Show();
1482void MUIBar::onCanvasOptionsAnimationTimerEvent(wxTimerEvent& event) {
1483 double progress = m_animateStep / (double)m_animateSteps;
1484 double valueX = getValue(m_animationType, progress);
1486 double dx = (m_targetCOPos.x - m_startCOPos.x) * valueX;
1488 wxPoint newPos = wxPoint(m_startCOPos.x + dx, m_currentCOPos.y);
1494 size_x = (m_targetCOPos.x - m_startCOPos.x) - abs(dx);
1496 if (!m_coAnimateByBitmaps) {
1497 m_canvasOptions->SetSize(newPos.x, newPos.y, size_x, wxDefaultCoord,
1498 wxSIZE_USE_EXISTING);
1500 m_canvasOptions->Show();
1502 m_canvasOptions->Hide();
1507 if (m_backingBitmap.IsOk()) {
1508 wxMemoryDC mdc_back(m_backingBitmap);
1509 sdc.Blit(m_backingPoint.x, m_backingPoint.y,
1510 m_backingBitmap.GetWidth() - size_x,
1511 m_backingBitmap.GetHeight(), &mdc_back, 0, 0, wxCOPY);
1515 wxMemoryDC mdc(m_animateBitmap);
1516 sdc.Blit(newPos.x, newPos.y, size_x, m_animateBitmap.GetHeight(), &mdc, 0,
1518 mdc.SelectObject(wxNullBitmap);
1521 m_currentCOPos = newPos;
1523 double dt = m_animationTotalTime / m_animateSteps;
1525 if (m_animateStep++ < m_animateSteps + 1) {
1526 m_canvasOptionsAnimationTimer.Start(dt,
true);
1528 m_currentCOPos = m_targetCOPos;
1529 m_canvasOptions->Show(m_pushPull ==
CO_PULL);
1531 auto pcc =
dynamic_cast<ChartCanvas*
>(m_parentCanvas);
1533 pcc->m_b_paint_enable =
true;
1536 delete m_canvasOptions;
1537 m_canvasOptions = NULL;
1540 if (m_pushPull ==
CO_PUSH) pcc->TriggerDeferredFocus();
1542 pcc->TriggerDeferredFocus();
1552double bounceMaker(
double t,
double c,
double a) {
1553 if (t == 1.0)
return c;
1554 if (t < (4 / 11.0)) {
1555 return c * (7.5625 * t * t);
1556 }
else if (t < (8 / 11.0)) {
1558 return -a * (1. - (7.5625 * t * t + .75)) + c;
1559 }
else if (t < (10 / 11.0)) {
1561 return -a * (1. - (7.5625 * t * t + .9375)) + c;
1564 return -a * (1. - (7.5625 * t * t + .984375)) + c;
1568double getValue(
int animationType,
double t) {
1572 switch (animationType) {
1579 value = tp * tp * tp + 1;
1584 value = tp * tp * tp + 1;
1587 value = bounceMaker(t, 1, s);
1592 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...