36#include "model/config_vars.h"
37#include "model/cutil.h"
38#include "model/wx28compat.h"
46#include "OCPNPlatform.h"
47#include "color_handler.h"
49#include "ocpn_frame.h"
51#ifdef __OCPN__ANDROID__
53#include "androidUTIL.h"
57#include "glChartCanvas.h"
60#include <wx/arrimpl.cpp>
61WX_DEFINE_OBJARRAY(RectArray);
68extern int g_GUIScaleFactor;
70extern float g_toolbar_scalefactor;
79BEGIN_EVENT_TABLE(
Piano, wxEvtHandler)
80EVT_TIMER(PIANO_EVENT_TIMER, Piano::onTimerEvent)
85 m_parentCanvas = parent;
90 m_hover_icon_last = -1;
94 m_gotPianoDown =
false;
102 m_pVizIconBmp = NULL;
103 m_pInVizIconBmp = NULL;
104 m_pPolyIconBmp = NULL;
105 m_pSkewIconBmp = NULL;
106 m_pTmercIconBmp = NULL;
108 SetColorScheme(GLOBAL_COLOR_SCHEME_RGB);
110 m_eventTimer.SetOwner(
this, PIANO_EVENT_TIMER);
112 m_tex = m_tex_piano_height = 0;
113 m_piano_mode = PIANO_MODE_LEGACY;
117 if (m_pInVizIconBmp)
delete m_pInVizIconBmp;
118 if (m_pPolyIconBmp)
delete m_pPolyIconBmp;
119 if (m_pSkewIconBmp)
delete m_pSkewIconBmp;
120 if (m_pTmercIconBmp)
delete m_pTmercIconBmp;
121 if (m_pVizIconBmp)
delete m_pVizIconBmp;
124void Piano::Paint(
int y, wxDC &dc, wxDC *shapeDC) {
126 Paint(y, odc, shapeDC);
129void Piano::Paint(
int y,
ocpnDC &dc, wxDC *shapeDC) {
131 shapeDC->SetBackground(*wxBLACK_BRUSH);
132 shapeDC->SetBrush(*wxWHITE_BRUSH);
133 shapeDC->SetPen(*wxWHITE_PEN);
138 if (!style->chartStatusWindowTransparent) {
139 dc.SetPen(*wxTRANSPARENT_PEN);
140 dc.SetBrush(m_backBrush);
141 dc.DrawRectangle(0, y, m_parentCanvas->GetClientSize().x, GetHeight());
146 int nKeys = m_composite_array.size();
148 wxPen ppPen(GetGlobalColor(_T(
"CHBLK")), 1, wxPENSTYLE_SOLID);
151 for (
int i = 0; i < nKeys; i++) {
152 int chart_family = m_composite_array[i].chart_family;
153 int chart_type = m_composite_array[i].chart_type;
155 bool selected = IsAnyActiveChartInPianoKeyElement(m_composite_array[i]);
157 if (chart_type == CHART_TYPE_CM93 || chart_type == CHART_TYPE_CM93COMP) {
159 dc.SetBrush(m_scBrush);
161 dc.SetBrush(m_cBrush);
162 }
else if (chart_type == CHART_TYPE_MBTILES) {
164 dc.SetBrush(m_tileBrush);
166 dc.SetBrush(m_utileBrush);
167 }
else if (chart_family == CHART_FAMILY_VECTOR) {
169 dc.SetBrush(m_svBrush);
171 dc.SetBrush(m_vBrush);
174 dc.SetBrush(m_srBrush);
176 dc.SetBrush(m_rBrush);
179 if (m_bBusy) dc.SetBrush(m_unavailableBrush);
181 wxRect box = KeyRect[i];
185 dc.DrawRoundedRectangle(box.x, box.y, box.width, box.height,
188 shapeDC->DrawRoundedRectangle(box.x, box.y, box.width, box.height,
191 dc.DrawRectangle(box.x, box.y, box.width, box.height);
192 if (shapeDC) shapeDC->DrawRectangle(box);
195 if (IsAllEclipsedChartInPianoKeyElement(m_composite_array[i])) {
197 dc.SetBrush(m_backBrush);
199 dc.DrawRoundedRectangle(box.x + w, box.y + w, box.width - (2 * w),
200 box.height - (2 * w), box.height / 5 - 1);
205 if (InArray(m_noshow_index_array, key_db_index) && m_pInVizIconBmp &&
206 m_pInVizIconBmp->IsOk())
207 dc.DrawBitmap(ConvertTo24Bit(dc.GetBrush().GetColour(), *m_pInVizIconBmp),
208 box.x + 4, box.y + 3,
false);
211 if (InArray(m_skew_index_array, key_db_index) && m_pSkewIconBmp &&
212 m_pSkewIconBmp->IsOk())
213 dc.DrawBitmap(ConvertTo24Bit(dc.GetBrush().GetColour(), *m_pSkewIconBmp),
214 box.x + box.width - m_pSkewIconBmp->GetWidth() - 4,
218 if (InArray(m_tmerc_index_array, key_db_index) && m_pTmercIconBmp &&
219 m_pTmercIconBmp->IsOk())
220 dc.DrawBitmap(ConvertTo24Bit(dc.GetBrush().GetColour(), *m_pTmercIconBmp),
221 box.x + box.width - m_pTmercIconBmp->GetWidth() - 4,
225 if (InArray(m_poly_index_array, key_db_index) && m_pPolyIconBmp &&
226 m_pPolyIconBmp->IsOk())
227 dc.DrawBitmap(ConvertTo24Bit(dc.GetBrush().GetColour(), *m_pPolyIconBmp),
228 box.x + box.width - m_pPolyIconBmp->GetWidth() - 4,
235static void SetColor(
unsigned char color[4],
const wxBrush &brush)
237 const wxColour &c = brush.GetColour();
238 color[0] = c.Red(), color[1] = c.Green(), color[2] = c.Blue(), color[3] = 255;
245void Piano::BuildGLTexture() {
249 if (!m_pInVizIconBmp || !m_pTmercIconBmp || !m_pSkewIconBmp ||
257 if (style->chartStatusWindowTransparent)
258 tbackBrush = wxColour(1, 1, 1);
260 tbackBrush = m_backBrush;
262 wxBrush brushes[] = {m_scBrush, m_cBrush, m_svBrush,
263 m_vBrush, m_srBrush, m_rBrush,
264 m_tileBrush, m_utileBrush, m_unavailableBrush};
269 m_texPitch = ((2 * m_ref) + (2 * m_pad));
271 m_tex_piano_height = h;
272 m_texw = m_texPitch * 3;
274 m_texh = ((
sizeof brushes) / (
sizeof *brushes)) * h;
277 m_texh = NextPow2(m_texh);
278 m_texw = NextPow2(m_texw);
280 if (!m_tex) glGenTextures(1, (GLuint *)&m_tex);
282 glBindTexture(GL_TEXTURE_2D, m_tex);
283 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
284 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
286 wxBitmap bmp(m_texw, m_texh);
289 dc.SetPen(*wxTRANSPARENT_PEN);
290 dc.SetBrush(tbackBrush);
291 dc.DrawRectangle(0, 0, m_texw, m_texh);
294 double nominal_line_width_pix = floor(g_Platform->GetDisplayDPmm() / 2.0);
295 nominal_line_width_pix *= OCPN_GetWinDIPScaleFactor();
296 nominal_line_width_pix = wxMax(1.0, nominal_line_width_pix);
299 wxPen ppPen(GetGlobalColor(_T(
"CHBLK")), nominal_line_width_pix,
302 for (
unsigned int b = 0; b < (
sizeof brushes) / (
sizeof *brushes); b++) {
303 unsigned int x = 0, y = h * b;
305 dc.SetBrush(brushes[b]);
308 dc.DrawRectangle(x + m_pad, y + v, 2 * m_ref, h - 2 * v);
311 dc.DrawRoundedRectangle(x + m_pad, y + v, 2 * m_ref, h - 2 * v, m_radius);
316 dc.DrawRoundedRectangle(x + m_pad, y + v, 2 * m_ref, h - 2 * v, m_radius);
317 dc.SetBrush(m_backBrush);
318 dc.DrawRoundedRectangle(x + m_pad + w, y + v + w, (2 * m_ref) - (2 * w),
320 m_radius * (h - 2 * v - 2 * w) /
324 dc.SelectObject(wxNullBitmap);
326 wxImage image = bmp.ConvertToImage();
328 unsigned char *data =
new unsigned char[4 * m_texw * m_texh], *d = data,
329 *e = image.GetData(), *a = image.GetAlpha();
330 for (
unsigned int i = 0; i < m_texw * m_texh; i++) {
331 if (style->chartStatusWindowTransparent && e[0] == 1 && e[1] == 1 &&
337 memcpy(d, e, 3), d += 4, e += 3;
340 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_texw, m_texh, 0, GL_RGBA,
341 GL_UNSIGNED_BYTE, data);
345 wxBitmap *bitmaps[] = {m_pInVizIconBmp, m_pTmercIconBmp, m_pSkewIconBmp,
348 for (
unsigned int i = 0; i < 4; i++) {
349 int iw = bitmaps[i]->GetWidth(), ih = bitmaps[i]->GetHeight();
351 wxImage im = bitmaps[i]->ConvertToImage();
352 unsigned char *data =
new unsigned char[4 * iw * ih], *d = data,
353 *e = im.GetData(), *a = im.GetAlpha();
354 for (
int j = 0; j < iw * ih; j++) {
355 memcpy(d, e, 3), d += 3, e += 3;
359 int off = ((
sizeof brushes) / (
sizeof *brushes)) * h + m_ref * i;
360 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, off, iw, ih, GL_RGBA, GL_UNSIGNED_BYTE,
367void Piano::DrawGL(
int off) {
return DrawGLSL(off); }
368void Piano::DrawGLSL(
int off) {
370 unsigned int w = m_parentCanvas->GetClientSize().x *
371 m_parentCanvas->GetContentScaleFactor();
373 unsigned int endx = 0;
375 if (
static_cast<int>(m_tex_piano_height) != h) BuildGLTexture();
377 if (
static_cast<int>(m_tex_piano_height) != h)
return;
379 int y1 = off, y2 = y1 + h;
381 int nKeys = m_composite_array.size();
385 float *texcoords =
new float[(nKeys * 3 + 1) * 4 * 2],
386 *coords =
new float[(nKeys * 3 + 1) * 4 * 2];
391 for (
int i = 0; i < nKeys; i++) {
393 int chart_family = m_composite_array[i].chart_family;
394 int chart_type = m_composite_array[i].chart_type;
396 if (chart_type == CHART_TYPE_CM93 || chart_type == CHART_TYPE_CM93COMP)
398 else if (chart_type == CHART_TYPE_MBTILES)
400 else if (chart_family == CHART_FAMILY_VECTOR)
405 if (!IsAnyActiveChartInPianoKeyElement(m_composite_array[i]))
408 wxRect box = KeyRect[i];
409 float y = h * b, v1 = (y + .5) / m_texh, v2 = (y + h - .5) / m_texh;
413 const float texcord[6] = {0,
418 (float)m_texPitch - 1};
422 if (IsAllEclipsedChartInPianoKeyElement(m_composite_array[i]))
431 int x1 = box.x, x2 = x1 + box.width, w = 2 * uindex + 1;
432 while (x1 + w > x2 - w && uindex > 0) uindex--, w -= 2;
436 int x[6] = {x1 - 3, x1 + m_ref, x2 - m_ref, x2 + 3};
440 int avg = (x[1] + x[2]) / 2;
444 for (
int i = 0; i < 3; i++) {
445 float u1 = ((uindex * m_texPitch) + texcord[2 * i] + .5) / m_texw,
446 u2 = ((uindex * m_texPitch) + texcord[2 * i + 1] + .5) / m_texw;
447 int x1 = x[i], x2 = x[i + 1];
448 texcoords[tc++] = u1, texcoords[tc++] = v1, coords[vc++] = x1,
450 texcoords[tc++] = u2, texcoords[tc++] = v1, coords[vc++] = x2,
452 texcoords[tc++] = u2, texcoords[tc++] = v2, coords[vc++] = x2,
454 texcoords[tc++] = u1, texcoords[tc++] = v2, coords[vc++] = x1,
462 if (!style->chartStatusWindowTransparent && endx < w) {
463 texcoords[tc++] = 0, texcoords[tc++] = 0, coords[vc++] = endx,
465 texcoords[tc++] = 0, texcoords[tc++] = 0, coords[vc++] = w,
467 texcoords[tc++] = 0, texcoords[tc++] = 0, coords[vc++] = w,
469 texcoords[tc++] = 0, texcoords[tc++] = 0, coords[vc++] = endx,
473 glBindTexture(GL_TEXTURE_2D, m_tex);
475 glEnable(GL_TEXTURE_2D);
478 m_parentCanvas->GetglCanvas()->RenderTextures(
479 m_parentCanvas->GetglCanvas()->m_gldc, coords, texcoords, vc / 2,
480 m_parentCanvas->GetpVP());
486 if (GetPianoMode() == PIANO_MODE_LEGACY) {
488 for (
int i = 0; i < nKeys; i++) {
489 int key_db_index = m_composite_array[i].dbindex_list[0];
491 if (-1 == key_db_index)
continue;
493 wxRect box = KeyRect[i];
495 wxBitmap *bitmaps[] = {m_pInVizIconBmp, m_pTmercIconBmp, m_pSkewIconBmp,
498 if (InArray(m_noshow_index_array, key_db_index))
501 if (InArray(m_skew_index_array, key_db_index))
503 else if (InArray(m_tmerc_index_array, key_db_index))
505 else if (InArray(m_poly_index_array, key_db_index))
511 int x1, y1, iw = bitmaps[index]->GetWidth(),
512 ih = bitmaps[index]->GetHeight();
513 if (InArray(m_noshow_index_array, key_db_index))
514 x1 = box.x + 4, y1 = box.y + 3;
516 x1 = box.x + box.width - iw - 4, y1 = box.y + 2;
519 int x2 = x1 + iw, y2 = y1 + ih;
521 wxBrush brushes[] = {m_scBrush, m_cBrush, m_svBrush,
522 m_vBrush, m_srBrush, m_rBrush,
523 m_tileBrush, m_utileBrush, m_unavailableBrush};
525 float yoff = ((
sizeof brushes) / (
sizeof *brushes)) * h + 16 * index;
526 float u1 = 0, u2 = (float)iw / m_texw;
527 float v1 = yoff / m_texh, v2 = (yoff + ih) / m_texh;
529 texcoords[tc++] = u1, texcoords[tc++] = v1, coords[vc++] = x1,
531 texcoords[tc++] = u2, texcoords[tc++] = v1, coords[vc++] = x2,
533 texcoords[tc++] = u2, texcoords[tc++] = v2, coords[vc++] = x2,
535 texcoords[tc++] = u1, texcoords[tc++] = v2, coords[vc++] = x1,
538 glEnable(GL_TEXTURE_2D);
539 glBindTexture(GL_TEXTURE_2D, m_tex);
542 m_parentCanvas->GetglCanvas()->RenderTextures(
543 m_parentCanvas->GetglCanvas()->m_gldc, coords, texcoords, vc / 2,
544 m_parentCanvas->GetpVP());
549 glDisable(GL_TEXTURE_2D);
555void Piano::SetColorScheme(ColorScheme cs) {
558 m_backBrush = wxBrush(GetGlobalColor(_T(
"UIBDR")), wxBRUSHSTYLE_SOLID);
560 m_rBrush = wxBrush(GetGlobalColor(_T(
"BLUE2")),
563 wxBrush(GetGlobalColor(_T(
"BLUE1")), wxBRUSHSTYLE_SOLID);
565 m_vBrush = wxBrush(GetGlobalColor(_T(
"GREEN2")),
567 m_svBrush = wxBrush(GetGlobalColor(_T(
"GREEN1")),
570 m_utileBrush = wxBrush(GetGlobalColor(_T(
"VIO01")),
573 wxBrush(GetGlobalColor(_T(
"VIO02")), wxBRUSHSTYLE_SOLID);
575 m_cBrush = wxBrush(GetGlobalColor(_T(
"YELO2")),
578 wxBrush(GetGlobalColor(_T(
"YELO1")), wxBRUSHSTYLE_SOLID);
580 m_unavailableBrush = wxBrush(GetGlobalColor(_T(
"UINFD")),
583 m_tex_piano_height = 0;
586void Piano::ShowBusy(
bool busy) {
593 for (
auto &index : m_active_index_array) {
594 auto found = find(pke.dbindex_list.begin(), pke.dbindex_list.end(), index);
595 if (found != pke.dbindex_list.end())
return true;
601 bool bfound_all =
true;
602 for (
auto &index : pke.dbindex_list) {
603 auto found = find(m_eclipsed_index_array.begin(),
604 m_eclipsed_index_array.end(), index);
605 if (found == m_eclipsed_index_array.end()) bfound_all =
false;
610void Piano::SetKeyArray(std::vector<int> ¢er_array,
611 std::vector<int> &full_array) {
614 if (center_array.size()) {
615 int refd = m_parentCanvas->GetCharWidth();
617 int nkeys = center_array.size();
618 int key_width = (m_width_avail / refd) / nkeys;
620 m_piano_mode = PIANO_MODE_COMPOSITE;
621 m_key_array = full_array;
623 m_piano_mode = PIANO_MODE_LEGACY;
624 m_key_array = center_array;
627 m_piano_mode = PIANO_MODE_LEGACY;
632 m_composite_array.clear();
634 if (m_piano_mode == PIANO_MODE_COMPOSITE) {
635 for (
size_t i = 0; i < m_key_array.size(); i++) {
637 ChartData->GetChartTableEntry(m_key_array[i]);
638 int scale = cte.GetScale();
639 auto order = std::pow(10, std::floor(std::log10(
scale)));
642 int chart_type = cte.GetChartType();
643 int chart_family = cte.GetChartFamily();
649 if ((cte.GetChartFamily() == CHART_FAMILY_VECTOR) ||
650 ((cte.GetChartFamily() == CHART_FAMILY_RASTER) &&
651 (cte.GetChartType() != CHART_TYPE_MBTILES))) {
653 return ((
scale == pke.chart_scale) &&
654 (chart_family == pke.chart_family));
656 auto found = find_if(m_composite_array.begin(), m_composite_array.end(),
658 if (found == m_composite_array.end()) {
660 new_pke.chart_scale =
scale;
661 new_pke.chart_family = (ChartFamilyEnum)cte.GetChartFamily();
662 new_pke.chart_type = (ChartTypeEnum)cte.GetChartType();
663 new_pke.dbindex_list.push_back(m_key_array[i]);
664 m_composite_array.push_back(new_pke);
667 ex_pke.dbindex_list.push_back(m_key_array[i]);
671 new_pke.chart_scale =
scale;
672 new_pke.chart_family = (ChartFamilyEnum)cte.GetChartFamily();
673 new_pke.chart_type = (ChartTypeEnum)cte.GetChartType();
674 new_pke.dbindex_list.push_back(m_key_array[i]);
675 m_composite_array.push_back(new_pke);
679 for (
size_t i = 0; i < m_key_array.size(); i++) {
681 ChartData->GetChartTableEntry(m_key_array[i]);
682 int scale = cte.GetScale();
683 int chart_type = cte.GetChartType();
685 new_pke.chart_scale =
scale;
686 new_pke.chart_family = (ChartFamilyEnum)cte.GetChartFamily();
687 new_pke.chart_type = (ChartTypeEnum)cte.GetChartType();
688 new_pke.dbindex_list.push_back(m_key_array[i]);
689 m_composite_array.push_back(new_pke);
694 std::sort(m_composite_array.begin(), m_composite_array.end(),
696 return a.chart_scale < b.chart_scale;
700void Piano::SetNoshowIndexArray(std::vector<int> array) {
701 m_noshow_index_array = array;
704void Piano::AddNoshowIndexArray(std::vector<int> array) {
705 for (
unsigned int i = 0; i < array.size(); i++) {
706 m_noshow_index_array.push_back(array[i]);
710void Piano::SetActiveKeyArray(std::vector<int> array) {
711 m_active_index_array = array;
714void Piano::SetEclipsedIndexArray(std::vector<int> array) {
715 m_eclipsed_index_array = array;
718void Piano::SetSkewIndexArray(std::vector<int> array) {
719 m_skew_index_array = array;
722void Piano::SetTmercIndexArray(std::vector<int> array) {
723 m_tmerc_index_array = array;
726void Piano::SetPolyIndexArray(std::vector<int> array) {
727 m_poly_index_array = array;
730bool Piano::InArray(std::vector<int> &array,
int key) {
731 for (
unsigned int ino = 0; ino < array.size(); ino++)
732 if (array[ino] == key)
return true;
736wxString Piano::GetStateHash() {
739 for (
unsigned int i = 0; i < m_key_array.size(); i++) {
741 a.Printf(_T(
"%dK"), m_key_array[i]);
744 for (
unsigned int i = 0; i < m_noshow_index_array.size(); i++) {
746 a.Printf(_T(
"%dN"), m_noshow_index_array[i]);
749 for (
unsigned int i = 0; i < m_active_index_array.size(); i++) {
751 a.Printf(_T(
"%dA"), m_active_index_array[i]);
754 for (
unsigned int i = 0; i < m_eclipsed_index_array.size(); i++) {
756 a.Printf(_T(
"%dE"), m_eclipsed_index_array[i]);
759 for (
unsigned int i = 0; i < m_skew_index_array.size(); i++) {
761 a.Printf(_T(
"%dW"), m_skew_index_array[i]);
764 for (
unsigned int i = 0; i < m_tmerc_index_array.size(); i++) {
766 a.Printf(_T(
"%dM"), m_tmerc_index_array[i]);
769 for (
unsigned int i = 0; i < m_poly_index_array.size(); i++) {
771 a.Printf(_T(
"%dP"), m_poly_index_array[i]);
778wxString &Piano::GenerateAndStoreNewHash() {
779 m_hash = GetStateHash();
783wxString &Piano::GetStoredHash() {
return m_hash; }
785void Piano::FormatKeys(
void) {
787 int width = m_parentCanvas->GetClientSize().x;
789 if (g_bopengl) width *= m_parentCanvas->GetContentScaleFactor();
791 width *= m_parentCanvas->GetContentScaleFactor();
795 wxSize mui_tool_size = g_StyleManager->GetCurrentStyle()->GetToolSize();
797 mui_tool_size = wxSize(mui_tool_size.x * 1.25, mui_tool_size.y * 1.25);
799 int mui_bar_width_est = mui_tool_size.x * 8 * g_toolbar_scalefactor;
801 if (m_parentCanvas->GetClientSize().x < m_parentCanvas->GetClientSize().y) {
812 m_width_avail = width;
814 int height = GetHeight();
816 int nKeys = m_composite_array.size();
817 int kw = style->chartStatusIconWidth;
819 if (!kw) kw = width / nKeys;
828 for (
int i = 0; i < nKeys; i++) {
829 wxRect r((i * kw) + 3, 2, kw - 6, height - 4);
830 KeyRect.push_back(r);
831 m_width = r.x + r.width;
837wxPoint Piano::GetKeyOrigin(
int key_index) {
838 if ((key_index >= 0) && (key_index <= (
int)m_key_array.size() - 1)) {
839 wxRect box = KeyRect[key_index];
840 return wxPoint(box.x, box.y);
842 return wxPoint(-1, -1);
845bool Piano::MouseEvent(wxMouseEvent &event) {
847 event.GetPosition(&x, &y);
850 x *= OCPN_GetDisplayContentScaleFactor();
851 y *= OCPN_GetDisplayContentScaleFactor();
854 y *= OCPN_GetDisplayContentScaleFactor();
856 int ytop = m_parentCanvas->GetCanvasHeight() - GetHeight();
858 if (!g_bopengl) ytop = m_parentCanvas->GetClientSize().y - GetHeight();
861 if (event.Leaving() || (y < ytop) || (x > GetWidth())) {
862 if (m_bleaving)
return false;
870 int sel_dbindex = -1;
872 for (
int i = 0; i < m_nRegions; i++) {
873 if (KeyRect[i].Contains(x, 6)) {
875 sel_dbindex = m_key_array[i];
881 if (event.LeftDown()) {
882 if (-1 != sel_index) {
883 m_action = DEFERRED_KEY_CLICK_DOWN;
885 m_eventTimer.Start(10, wxTIMER_ONE_SHOT);
888 if (event.LeftUp()) {
889 if (-1 != sel_index) {
890 m_click_sel_index = sel_index;
891 if (!m_eventTimer.IsRunning()) {
892 m_action = DEFERRED_KEY_CLICK_UP;
893 m_eventTimer.Start(10, wxTIMER_ONE_SHOT);
896 }
else if (event.RightDown()) {
897 if (sel_index != m_hover_last) {
899 m_parentCanvas->HandlePianoRollover(
900 sel_index, m_composite_array[sel_index].dbindex_list,
901 m_composite_array[sel_index].dbindex_list.size(),
902 m_composite_array[sel_index].chart_scale);
903 m_hover_last = sel_index;
908 }
else if (event.ButtonUp()) {
909 m_parentCanvas->ClearPianoRollover();
914 m_parentCanvas->ClearPianoRollover();
916 }
else if (event.LeftDown()) {
917 if (-1 != sel_index) {
918 m_parentCanvas->HandlePianoClick(
919 sel_index, m_composite_array[sel_index].dbindex_list);
921 m_parentCanvas->Raise();
924 }
else if (event.RightDown()) {
925 if (-1 != sel_index) {
926 m_parentCanvas->HandlePianoRClick(
927 x, y, sel_index, m_composite_array[sel_index].dbindex_list);
928 m_parentCanvas->Raise();
931 }
else if (!event.ButtonUp()) {
932 if (sel_index != m_hover_last) {
934 m_parentCanvas->HandlePianoRollover(
935 sel_index, m_composite_array[sel_index].dbindex_list,
936 m_composite_array[sel_index].dbindex_list.size(),
937 m_composite_array[sel_index].chart_scale);
939 m_hover_last = sel_index;
958void Piano::ResetRollover(
void) {
960 m_hover_icon_last = -1;
962 m_gotPianoDown =
false;
965int Piano::GetHeight() {
968 if (g_bopengl) height *= m_parentCanvas->GetContentScaleFactor();
971 double size_mult = exp(g_GUIScaleFactor * 0.0953101798043);
973 height = wxMin(height, 100);
974 height = wxMax(height, 10);
976 height *= g_Platform->GetDisplayDensityFactor();
978#ifdef __OCPN__ANDROID__
979 height = wxMax(height, 4 * g_Platform->GetDisplayDPmm());
987int Piano::GetWidth() {
return m_width; }
989void Piano::onTimerEvent(wxTimerEvent &event) {
991 case DEFERRED_KEY_CLICK_DOWN:
992 m_gotPianoDown =
true;
994 case DEFERRED_KEY_CLICK_UP:
996 if ((m_hover_last >= 0) || !m_gotPianoDown) {
997 m_parentCanvas->ClearPianoRollover();
1000 m_parentCanvas->HandlePianoClick(
1002 m_composite_array[m_click_sel_index].dbindex_list);
1003 m_gotPianoDown =
false;
1006 case INFOWIN_TIMEOUT:
1007 m_parentCanvas->ClearPianoRollover();
Manages the chart database and provides access to chart data.
Device context class that can use either wxDC or OpenGL for drawing.
PlugIn Object Definition/API.
Represents an entry in the chart table, containing information about a single chart.