42#include "wx/tokenzr.h" 
   44#ifdef __OCPN__ANDROID__ 
   48double rad2deg(
double angle) { 
return angle * 180.0 / M_PI; }
 
   49double deg2rad(
double angle) { 
return angle / 180.0 * M_PI; }
 
   51DashboardInstrument_Dial::DashboardInstrument_Dial(
 
   52    wxWindow* parent, wxWindowID 
id, wxString title,
 
   54    int r_angle, 
int s_value, 
int e_value)
 
   56  m_AngleStart = s_angle;
 
   57  m_AngleRange = r_angle;
 
   58  m_MainValueMin = s_value;
 
   59  m_MainValueMax = e_value;
 
   60  m_MainValueCap = cap_flag;
 
   62  m_MainValue = s_value;
 
   64  m_MainValueFormat = _T(
"%d");
 
   65  m_MainValueUnit = _T(
"");
 
   66  m_MainValueOption = DIAL_POSITION_NONE;
 
   67  m_ExtraValueFormat = _T(
"%d");
 
   68  m_ExtraValueUnit = _T(
"");
 
   69  m_ExtraValueOption = DIAL_POSITION_NONE;
 
   70  m_MarkerOption = DIAL_MARKER_SIMPLE;
 
   74  m_LabelOption = DIAL_LABEL_HORIZONTAL;
 
   77wxSize DashboardInstrument_Dial::GetSize(
int orient, wxSize hint) {
 
   79  InitTitleAndDataPosition(DefaultWidth);
 
   81  if (orient == wxHORIZONTAL) {
 
   82    w = wxMax(hint.y, GetFullHeight(DefaultWidth));
 
   83    return wxSize(w - m_TitleHeight, w);
 
   85    w = wxMax(hint.x, DefaultWidth);
 
   86    return wxSize(w, GetFullHeight(w));
 
   90void DashboardInstrument_Dial::SetData(DASH_CAP st, 
double data,
 
   92  if (st == m_MainValueCap) {
 
   94    m_MainValueUnit = 
unit;
 
   95  } 
else if (st == m_ExtraValueCap) {
 
   97    m_ExtraValueUnit = 
unit;
 
  102void DashboardInstrument_Dial::Draw(wxGCDC* bdc) {
 
  105        GetColourSchemeBackgroundColour(m_Properties->m_DataBackgroundColour));
 
  106    bdc->SetBackground(b1);
 
  109    GetGlobalColor(_T(
"DASHB"), &c1);
 
  111    bdc->SetBackground(b1);
 
  115  wxSize size = GetClientSize();
 
  117  int availableHeight = GetDataBottom(size.y) - m_DataTop;
 
  118  InitTitleAndDataPosition(availableHeight);
 
  119  availableHeight -= 6;
 
  123    f = m_Properties->m_LabelFont.GetChosenFont();
 
  125    f = g_pFontLabel->GetChosenFont();
 
  126  bdc->GetTextExtent(_T(
"000"), &width, &height, 0, 0, &f);
 
  127  m_cy = m_DataTop + 2;
 
  128  m_cy += availableHeight / 2;
 
  129  m_radius = availableHeight / 2;
 
  135  DrawData(bdc, m_MainValue, m_MainValueUnit, m_MainValueFormat,
 
  137  DrawData(bdc, m_ExtraValue, m_ExtraValueUnit, m_ExtraValueFormat,
 
  142void DashboardInstrument_Dial::DrawFrame(wxGCDC* dc) {
 
  143  wxSize size = GetClientSize();
 
  146    cl = GetColourSchemeBackgroundColour(m_Properties->m_TitleBackgroundColour);
 
  148    GetGlobalColor(_T(
"DASHL"), &cl);
 
  150  dc->SetTextForeground(cl);
 
  151  dc->SetBrush(*wxTRANSPARENT_BRUSH);
 
  153  int penwidth = 1 + size.x / 100;
 
  154  wxPen pen(cl, penwidth, wxPENSTYLE_SOLID);
 
  156  if (m_MarkerOption == DIAL_MARKER_REDGREENBAR) {
 
  157    pen.SetWidth(penwidth * 2);
 
  158    GetGlobalColor(_T(
"DASHR"), &cl);
 
  161    double angle1 = deg2rad(270);  
 
  162    double angle2 = deg2rad(90);   
 
  163    int radi = m_radius - 1 - penwidth;
 
  164    wxCoord x1 = m_cx + ((radi)*cos(angle1));
 
  165    wxCoord y1 = m_cy + ((radi)*sin(angle1));
 
  166    wxCoord x2 = m_cx + ((radi)*cos(angle2));
 
  167    wxCoord y2 = m_cy + ((radi)*sin(angle2));
 
  168    dc->DrawArc(x1, y1, x2, y2, m_cx, m_cy);
 
  170    GetGlobalColor(_T(
"DASHG"), &cl);
 
  173    angle1 = deg2rad(89);   
 
  174    angle2 = deg2rad(271);  
 
  175    x1 = m_cx + ((radi)*cos(angle1));
 
  176    y1 = m_cy + ((radi)*sin(angle1));
 
  177    x2 = m_cx + ((radi)*cos(angle2));
 
  178    y2 = m_cy + ((radi)*sin(angle2));
 
  179    dc->DrawArc(x1, y1, x2, y2, m_cx, m_cy);
 
  183    GetGlobalColor(_T(
"DASHF"), &cl);
 
  184    pen.SetWidth(penwidth);
 
  188    angle2 = deg2rad(180);
 
  191    x1 = m_cx + ((radi)*cos(angle1));
 
  192    y1 = m_cy + ((radi)*sin(angle1));
 
  193    x2 = m_cx + ((radi)*cos(angle2));
 
  194    y2 = m_cy + ((radi)*sin(angle2));
 
  195    dc->DrawArc(x1, y1, x2, y2, m_cx, m_cy);
 
  196    dc->DrawArc(x2, y2, x1, y1, m_cx, m_cy);
 
  199    GetGlobalColor(_T(
"DASHF"), &cl);
 
  202    dc->DrawCircle(m_cx, m_cy, m_radius);
 
  206void DashboardInstrument_Dial::DrawMarkers(wxGCDC* dc) {
 
  207  if (m_MarkerOption == DIAL_MARKER_NONE) 
return;
 
  210  GetGlobalColor(_T(
"DASHF"), &cl);
 
  211  int penwidth = GetClientSize().x / 100;
 
  212  wxPen pen(cl, penwidth, wxPENSTYLE_SOLID);
 
  215  int diff_angle = m_AngleStart + m_AngleRange - ANGLE_OFFSET;
 
  217  double abm = m_AngleRange * m_MarkerStep / (m_MainValueMax - m_MainValueMin);
 
  219  if (m_AngleRange == 360) diff_angle -= abm;
 
  222  for (
double angle = m_AngleStart - ANGLE_OFFSET; angle <= diff_angle;
 
  224    if (m_MarkerOption == DIAL_MARKER_REDGREEN) {
 
  225      int a = int(angle + ANGLE_OFFSET) % 360;
 
  227        GetGlobalColor(_T(
"DASHR"), &cl);
 
  228      else if ((a > 0) && (a < 180))
 
  229        GetGlobalColor(_T(
"DASHG"), &cl);
 
  231        GetGlobalColor(_T(
"DASHF"), &cl);
 
  238    if (offset % m_MarkerOffset) {
 
  243    dc->DrawLine(m_cx + ((m_radius - 1) * size * cos(deg2rad(angle))),
 
  244                 m_cy + ((m_radius - 1) * size * sin(deg2rad(angle))),
 
  245                 m_cx + ((m_radius - 1) * cos(deg2rad(angle))),
 
  246                 m_cy + ((m_radius - 1) * sin(deg2rad(angle))));
 
  249  if (m_MarkerOption == DIAL_MARKER_REDGREEN) {
 
  250    GetGlobalColor(_T(
"DASHF"), &cl);
 
  251    pen.SetStyle(wxPENSTYLE_SOLID);
 
  257void DashboardInstrument_Dial::DrawLabels(wxGCDC* dc) {
 
  258  if (m_LabelOption == DIAL_LABEL_NONE) 
return;
 
  263  GetGlobalColor(_T(
"DASHF"), &cl);
 
  266    dc->SetFont(m_Properties->m_SmallFont.GetChosenFont());
 
  267    dc->SetTextForeground(
 
  268        GetColourSchemeFont(m_Properties->m_SmallFont.GetColour()));
 
  270    dc->SetFont(g_pFontSmall->GetChosenFont());
 
  271    dc->SetTextForeground(GetColourSchemeFont(g_pFontSmall->GetColour()));
 
  273  int diff_angle = m_AngleStart + m_AngleRange - ANGLE_OFFSET;
 
  275  double abm = m_AngleRange * m_LabelStep / (m_MainValueMax - m_MainValueMin);
 
  277  if (m_AngleRange == 360) diff_angle -= abm;
 
  280  int value = m_MainValueMin;
 
  283  for (
double angle = m_AngleStart - ANGLE_OFFSET; angle <= diff_angle;
 
  286        (m_LabelArray.GetCount() ? m_LabelArray.Item(offset)
 
  287                                 : wxString::Format(_T(
"%d"), value));
 
  289      f = m_Properties->m_SmallFont.GetChosenFont();
 
  291      f = g_pFontSmall->GetChosenFont();
 
  292    dc->GetTextExtent(label, &width, &height, 0, 0, &f);
 
  293    double halfW = width / 2;
 
  294    if (m_LabelOption == DIAL_LABEL_HORIZONTAL) {
 
  295      double halfH = height / 2;
 
  297      double delta = sqrt(halfW * halfW + halfH * halfH);
 
  299          m_cx + ((m_radius * 0.90) - delta) * cos(deg2rad(angle)) - halfW;
 
  301          m_cy + ((m_radius * 0.90) - delta) * sin(deg2rad(angle)) - halfH;
 
  302      dc->DrawText(label, TextPoint);
 
  304    } 
else if (m_LabelOption == DIAL_LABEL_ROTATED) {
 
  309      long double tmpangle = angle - rad2deg(asin(halfW / (0.90 * m_radius)));
 
  310      TextPoint.x = m_cx + m_radius * 0.90 * cos(deg2rad(tmpangle));
 
  311      TextPoint.y = m_cy + m_radius * 0.90 * sin(deg2rad(tmpangle));
 
  312      dc->DrawRotatedText(label, TextPoint, -90 - angle);
 
  315    value += m_LabelStep;
 
  319void DashboardInstrument_Dial::DrawBackground(wxGCDC* dc) {
 
  324void DashboardInstrument_Dial::DrawData(wxGCDC* dc, 
double value, wxString 
unit,
 
  326                                        DialPositionOption position) {
 
  327  if (position == DIAL_POSITION_NONE) 
return;
 
  330    dc->SetFont(m_Properties->m_LabelFont.GetChosenFont());
 
  331    dc->SetTextForeground(
 
  332        GetColourSchemeFont(m_Properties->m_LabelFont.GetColour()));
 
  334    dc->SetFont(g_pFontLabel->GetChosenFont());
 
  335    dc->SetTextForeground(GetColourSchemeFont(g_pFontLabel->GetColour()));
 
  339  wxSize size = GetClientSize();
 
  342  if (!std::isnan(value)) {
 
  343    if (
unit == _T(
"\u00B0"))
 
  344      text = wxString::Format(format, value) + DEGREE_SIGN;
 
  345    else if (
unit == _T(
"\u00B0L"))  
 
  347      text = wxString::Format(format, value) + DEGREE_SIGN;
 
  350      text = wxString::Format(format, value) + DEGREE_SIGN;
 
  351    else if (
unit == _T(
"\u00B0T"))
 
  352      text = wxString::Format(format, value) + DEGREE_SIGN + _T(
"T");
 
  353    else if (
unit == _T(
"\u00B0M"))
 
  354      text = wxString::Format(format, value) + DEGREE_SIGN + _T(
"M");
 
  355    else if (
unit == _T(
"N"))  
 
  356      text = wxString::Format(format, value) + _T(
" Kts");
 
  358      text = wxString::Format(format, value) + _T(
" ") + 
unit;
 
  365    f = m_Properties->m_LabelFont.GetChosenFont();
 
  367    f = g_pFontLabel->GetChosenFont();
 
  368  dc->GetMultiLineTextExtent(text, &width, &height, NULL, &f);
 
  371  TextPoint.width = width;
 
  372  TextPoint.height = height;
 
  374    case DIAL_POSITION_NONE:
 
  378    case DIAL_POSITION_INSIDE: {
 
  379      TextPoint.x = m_cx - (width / 2) - 1;
 
  380      TextPoint.y = ((size.y - m_InstrumentSpacing) * .75) - height;
 
  381      if ((g_TitleAlignment & wxALIGN_BOTTOM) != 0)
 
  382        TextPoint.y -= m_TitleHeight;
 
  384        cl = GetColourSchemeBackgroundColour(
 
  385            m_Properties->m_TitleBackgroundColour);
 
  387        GetGlobalColor(_T(
"DASHL"), &cl);
 
  388      int penwidth = size.x / 100;
 
  390          wxThePenList->FindOrCreatePen(cl, penwidth, wxPENSTYLE_SOLID);
 
  393        cl = GetColourSchemeBackgroundColour(
 
  394            m_Properties->m_DataBackgroundColour);
 
  396        GetGlobalColor(_T(
"DASHB"), &cl);
 
  400      dc->DrawRoundedRectangle(TextPoint.x - 2, TextPoint.y - 2, width + 4,
 
  404    case DIAL_POSITION_TOPLEFT:
 
  406      TextPoint.y = m_DataTop;
 
  408    case DIAL_POSITION_TOPRIGHT:
 
  409      TextPoint.x = size.x - width - 1;
 
  410      TextPoint.y = m_DataTop;
 
  412    case DIAL_POSITION_BOTTOMLEFT:
 
  414      TextPoint.y = GetDataBottom(size.y) - height;
 
  416    case DIAL_POSITION_BOTTOMRIGHT:
 
  417      TextPoint.x = size.x - width - 1;
 
  418      TextPoint.y = GetDataBottom(size.y) - height;
 
  420    case DIAL_POSITION_BOTTOMMIDDLE:
 
  421      if (!std::isnan(value)) {
 
  422        TextPoint.x = m_cx - (width / 2) - 1;
 
  423        TextPoint.y = GetDataBottom(size.y) - height;
 
  426        dc->DrawRoundedRectangle(TextPoint.x - 2, TextPoint.y - 2, width + 4,
 
  435  GetGlobalColor(_T(
"DASHF"), &c3);
 
  437  wxStringTokenizer tkz(text, _T(
"\n"));
 
  440  token = tkz.GetNextToken();
 
  441  while (token.Length()) {
 
  443      f = m_Properties->m_LabelFont.GetChosenFont();
 
  445      f = g_pFontLabel->GetChosenFont();
 
  446    dc->GetTextExtent(token, &width, &height, NULL, NULL, &f);
 
  447    dc->DrawText(token, TextPoint.x, TextPoint.y);
 
  448    TextPoint.y += height;
 
  449    token = tkz.GetNextToken();
 
  453void DashboardInstrument_Dial::DrawForeground(wxGCDC* dc) {
 
  456  GetGlobalColor(_T(
"DASH2"), &cl);
 
  458  pen1.SetStyle(wxPENSTYLE_SOLID);
 
  462  GetGlobalColor(_T(
"DASH1"), &cl);
 
  464  brush1.SetStyle(wxBRUSHSTYLE_SOLID);
 
  465  brush1.SetColour(cl);
 
  466  dc->SetBrush(brush1);
 
  467  dc->DrawCircle(m_cx, m_cy, m_radius / 8);
 
  469  dc->SetPen(*wxTRANSPARENT_PEN);
 
  471    cl = GetColourSchemeFont(m_Properties->m_Arrow_First_Colour);
 
  473    GetGlobalColor(_T(
"DASHN"), &cl);
 
  475  brush.SetStyle(wxBRUSHSTYLE_SOLID);
 
  482  if (m_MainValueUnit == _T(
"\u00B0L"))
 
  483    data = 360 - m_MainValue;
 
  489  if (data < m_MainValueMin)
 
  490    val = m_MainValueMin;
 
  491  else if (data > m_MainValueMax)
 
  492    val = m_MainValueMax;
 
  496  double value = deg2rad((val - m_MainValueMin) * m_AngleRange /
 
  497                         (m_MainValueMax - m_MainValueMin)) +
 
  498                 deg2rad(m_AngleStart - ANGLE_OFFSET);
 
  501  points[0].x = m_cx + (m_radius * 0.95 * cos(value - .010));
 
  502  points[0].y = m_cy + (m_radius * 0.95 * sin(value - .010));
 
  503  points[1].x = m_cx + (m_radius * 0.95 * cos(value + .015));
 
  504  points[1].y = m_cy + (m_radius * 0.95 * sin(value + .015));
 
  505  points[2].x = m_cx + (m_radius * 0.22 * cos(value + 2.8));
 
  506  points[2].y = m_cy + (m_radius * 0.22 * sin(value + 2.8));
 
  507  points[3].x = m_cx + (m_radius * 0.22 * cos(value - 2.8));
 
  508  points[3].y = m_cy + (m_radius * 0.22 * sin(value - 2.8));
 
  509  dc->DrawPolygon(4, points, 0, 0);
 
  513void DrawCompassRose(wxGCDC* dc, 
int cx, 
int cy, 
int radius, 
int startangle,
 
  515  wxPoint pt, points[3];
 
  518  wxString CompassArray[] = {_(
"N"),  _(
"NE"), _(
"E"),  _(
"SE"), _(
"S"),
 
  519                             _(
"SW"), _(
"W"),  _(
"NW"), _(
"N")};
 
  521    dc->SetFont((Properties->m_SmallFont.GetChosenFont()));
 
  523    dc->SetFont((g_pFontSmall->GetChosenFont()));
 
  527  GetGlobalColor(_T(
"DASH2"), &cl);
 
  528  pen = wxThePenList->FindOrCreatePen(cl, 1, wxPENSTYLE_SOLID);
 
  529  wxBrush* b2 = wxTheBrushList->FindOrCreateBrush(cl);
 
  531  GetGlobalColor(_T(
"DASH1"), &cl);
 
  532  wxBrush* b1 = wxTheBrushList->FindOrCreateBrush(cl);
 
  535  dc->SetTextForeground(cl);
 
  540  for (
double tmpangle = startangle - ANGLE_OFFSET;
 
  541       tmpangle < startangle + 360 - ANGLE_OFFSET; tmpangle += 90) {
 
  543      Value = CompassArray[offset];
 
  545        f = Properties->m_SmallFont.GetChosenFont();
 
  546        dc->GetTextExtent(Value, &width, &height, 0, 0, &f);
 
  548        f = g_pFontSmall->GetChosenFont();
 
  549        dc->GetTextExtent(Value, &width, &height, 0, 0, &f);
 
  551      double x = width / 2;
 
  552      long double anglefortext = tmpangle - rad2deg(asin((x / radius)));
 
  553      pt.x = cx + radius * cos(deg2rad(anglefortext));
 
  554      pt.y = cy + radius * sin(deg2rad(anglefortext));
 
  555      dc->DrawRotatedText(Value, pt.x, pt.y, -90 - tmpangle);
 
  556      Value = CompassArray[offset + 1];
 
  558        f = Properties->m_SmallFont.GetChosenFont();
 
  559        dc->GetTextExtent(Value, &width, &height, 0, 0, &f);
 
  561        f = g_pFontSmall->GetChosenFont();
 
  562        dc->GetTextExtent(Value, &width, &height, 0, 0, &f);
 
  565      anglefortext = tmpangle - rad2deg(asin((x / radius))) + 45;
 
  566      pt.x = cx + radius * cos(deg2rad(anglefortext));
 
  567      pt.y = cy + radius * sin(deg2rad(anglefortext));
 
  568      dc->DrawRotatedText(Value, pt.x, pt.y, -135 - tmpangle);
 
  572    points[1].x = cx + radius * 0.15 * cos(deg2rad(tmpangle));
 
  573    points[1].y = cy + radius * 0.15 * sin(deg2rad(tmpangle));
 
  574    points[2].x = cx + radius * 0.6 * cos(deg2rad(tmpangle + 45));
 
  575    points[2].y = cy + radius * 0.6 * sin(deg2rad(tmpangle + 45));
 
  576    dc->DrawPolygon(3, points, 0, 0);
 
  577    points[1].x = cx + radius * 0.15 * cos(deg2rad(tmpangle + 90));
 
  578    points[1].y = cy + radius * 0.15 * sin(deg2rad(tmpangle + 90));
 
  580    dc->DrawPolygon(3, points, 0, 0);
 
  581    points[2].x = cx + radius * 0.8 * cos(deg2rad(tmpangle));
 
  582    points[2].y = cy + radius * 0.8 * sin(deg2rad(tmpangle));
 
  583    points[1].x = cx + radius * 0.15 * cos(deg2rad(tmpangle + 45));
 
  584    points[1].y = cy + radius * 0.15 * sin(deg2rad(tmpangle + 45));
 
  585    dc->DrawPolygon(3, points, 0, 0);
 
  586    points[2].x = cx + radius * 0.8 * cos(deg2rad(tmpangle + 90));
 
  587    points[2].y = cy + radius * 0.8 * sin(deg2rad(tmpangle + 90));
 
  589    dc->DrawPolygon(3, points, 0, 0);
 
  594void DrawBoat(wxGCDC* dc, 
int cx, 
int cy, 
int radius) {
 
  597  GetGlobalColor(_T(
"DASH2"), &cl);
 
  598  wxPen* pen = wxThePenList->FindOrCreatePen(cl, 1, wxPENSTYLE_SOLID);
 
  600  GetGlobalColor(_T(
"DASH1"), &cl);
 
  618  points[0].y = cy - radius * .60;  
 
  619  points[1].x = cx + radius * .15;
 
  620  points[1].y = cy - radius * .08;
 
  621  points[2].x = cx + radius * .15;
 
  622  points[2].y = cy + radius * .12;
 
  623  points[3].x = cx + radius * .10;
 
  624  points[3].y = cy + radius * .40;
 
  625  points[4].x = cx - radius * .10;
 
  626  points[4].y = cy + radius * .40;
 
  627  points[5].x = cx - radius * .15;
 
  628  points[5].y = cy + radius * .12;
 
  629  points[6].x = cx - radius * .15;
 
  630  points[6].y = cy - radius * .08;
 
  632  dc->DrawPolygon(7, points, 0, 0);