void
WaypointListRenderer::Draw(Canvas &canvas, const PixelRect rc,
                           const Waypoint &waypoint, const GeoVector *vector,
                           const DialogLook &dialog_look,
                           const WaypointLook &look,
                           const WaypointRendererSettings &settings)
{
  const PixelScalar line_height = rc.bottom - rc.top;

  const Font &name_font = *dialog_look.list.font;
  const Font &small_font = *dialog_look.small_font;

  Buffer buffer;

  // Y-Coordinate of the second row
  PixelScalar top2 = rc.top + name_font.GetHeight() + Layout::FastScale(4);

  // Use small font for details
  canvas.Select(small_font);

  // Draw leg distance
  UPixelScalar leg_info_width = 0;
  if (vector) {
    FormatUserDistanceSmart(vector->distance, buffer.buffer(), true);
    UPixelScalar width = leg_info_width = canvas.CalcTextWidth(buffer.c_str());
    canvas.text(rc.right - Layout::FastScale(2) - width,
                rc.top + Layout::FastScale(2) +
                (name_font.GetHeight() - small_font.GetHeight()) / 2,
                buffer.c_str());

    // Draw leg bearing
    FormatBearing(buffer.buffer(), buffer.MAX_SIZE, vector->bearing);
    width = canvas.CalcTextWidth(buffer.c_str());
    canvas.text(rc.right - Layout::FastScale(2) - width, top2, buffer.c_str());

    if (width > leg_info_width)
      leg_info_width = width;

    leg_info_width += Layout::FastScale(2);
  }

  // Draw details line
  FormatWaypointDetails(buffer, waypoint);

  PixelScalar left = rc.left + line_height + Layout::FastScale(2);
  canvas.text_clipped(left, top2, rc.right - leg_info_width - left,
                      buffer.c_str());

  // Draw waypoint name
  canvas.Select(name_font);
  canvas.text_clipped(left, rc.top + Layout::FastScale(2),
                      rc.right - leg_info_width - left, waypoint.name.c_str());

  // Draw icon
  RasterPoint pt = { (PixelScalar)(rc.left + line_height / 2),
                     (PixelScalar)(rc.top + line_height / 2) };
  WaypointIconRenderer wir(settings, look, canvas);
  wir.Draw(waypoint, pt);
}
Beispiel #2
0
void
TaskStatusPanel::Refresh()
{
  if (protected_task_manager == NULL)
    return;

  const DerivedInfo &calculated = CommonInterface::Calculated();
  const TaskStats &task_stats = calculated.ordered_task_stats;

  TCHAR Temp[80];

  SetRowVisible(TaskTime, task_stats.has_targets);
  if (task_stats.has_targets) {
    FormatSignedTimeHHMM(Temp, (int)protected_task_manager->GetOrderedTaskSettings().aat_min_time);
    SetText(TaskTime, Temp);
  }

  int ete_time(task_stats.GetEstimatedTotalTime());
  FormatSignedTimeHHMM(Temp, ete_time);
  SetText(ETETime, Temp);

  FormatSignedTimeHHMM(Temp, (int)task_stats.total.time_remaining_now);
  SetText(RemainingTime, Temp);

  if (task_stats.total.planned.IsDefined()) {
    FormatUserDistanceSmart(task_stats.total.planned.GetDistance(),
                              Temp, ARRAY_SIZE(Temp));
    SetText(TaskDistance, Temp);
  } else
    SetText(TaskDistance, _T(""));

  if (task_stats.total.remaining.IsDefined()) {
    FormatUserDistanceSmart(task_stats.total.remaining.GetDistance(),
                              Temp, ARRAY_SIZE(Temp));
    SetText(RemainingDistance, Temp);
  }

  if (task_stats.total.planned.IsDefined()) {
    FormatUserTaskSpeed(task_stats.total.planned.GetSpeed(),
                               Temp, ARRAY_SIZE(Temp));
    SetText(EstimatedSpeed, Temp);
  } else
    SetText(EstimatedSpeed, _T(""));

  if (task_stats.total.travelled.IsDefined()) {
    FormatUserTaskSpeed(task_stats.total.travelled.GetSpeed(),
                               Temp, ARRAY_SIZE(Temp));
    SetText(AverageSpeed, Temp);
  } else
    SetText(AverageSpeed, _T(""));
}
Beispiel #3
0
void
TeamCodeWidget::Update(const MoreData &basic, const DerivedInfo &calculated)
{
  const TeamInfo &teamcode_info = calculated;
  const TeamCodeSettings &settings =
    CommonInterface::GetComputerSettings().team_code;

  SetText(RELATIVE_BEARING,
          teamcode_info.teammate_available && basic.track_available
          ? FormatAngleDelta(teamcode_info.teammate_vector.bearing - basic.track).c_str()
          : _T("---"));

  if (teamcode_info.teammate_available) {
    SetText(BEARING,
            FormatBearing(teamcode_info.teammate_vector.bearing).c_str());

    SetText(RANGE,
            FormatUserDistanceSmart(teamcode_info.teammate_vector.distance));
  }

  SetText(OWN_CODE, teamcode_info.own_teammate_code.GetCode());
  SetText(MATE_CODE, settings.team_code.GetCode());
  SetText(FLARM_LOCK,
          settings.team_flarm_id.IsDefined()
          ? settings.team_flarm_callsign.c_str()
          : _T(""));
}
Beispiel #4
0
void
InfoBoxData::SetValueFromDistance(fixed new_value)
{
  Unit distance_unit =
    FormatUserDistanceSmart(new_value, value.buffer(), false);
  SetValueUnit(distance_unit);
}
Beispiel #5
0
void
FlightStatusPanel::Refresh()
{
  const NMEAInfo &basic = CommonInterface::Basic();
  const DerivedInfo &calculated = CommonInterface::Calculated();

  if (basic.location_available)
    SetText(Location, FormatGeoPoint(basic.location));
  else
    ClearText(Location);

  if (basic.gps_altitude_available)
    SetText(Altitude, FormatUserAltitude(basic.gps_altitude));
  else
    ClearText(Altitude);

  SetText(MaxHeightGain, FormatUserAltitude(calculated.max_height_gain));

  if (nearest_waypoint) {
    GeoVector vec(basic.location,
                  nearest_waypoint->location);

    SetText(Near, nearest_waypoint->name.c_str());

    SetText(Bearing, FormatBearing(vec.bearing).c_str());

    SetText(Distance, FormatUserDistanceSmart(vec.distance));
  } else {
    SetText(Near, _T("-"));
    SetText(Bearing, _T("-"));
    SetText(Distance, _T("-"));
  }
}
Beispiel #6
0
gcc_const
static inline StringBuffer<TCHAR, 32>
FormatUserDistanceSmart(double value)
{
  StringBuffer<TCHAR, 32> buffer;
  FormatUserDistanceSmart(value, buffer.data());
  return buffer;
}
Beispiel #7
0
void
TaskEditPanel::OnPaintItem(Canvas &canvas, const PixelRect rc,
                           unsigned DrawListIndex)
{
  assert(DrawListIndex <= ordered_task->TaskSize());

  const unsigned padding = Layout::GetTextPadding();
  const unsigned line_height = rc.bottom - rc.top;

  TCHAR buffer[120];

  // Draw "Add turnpoint" label
  if (DrawListIndex == ordered_task->TaskSize()) {
    row_renderer.DrawFirstRow(canvas, rc, _("Add Turnpoint"));
    return;
  }

  const OrderedTaskPoint &tp = ordered_task->GetTaskPoint(DrawListIndex);
  GeoVector leg = tp.GetNominalLegVector();
  bool show_leg_info = leg.distance > fixed(0.01);

  PixelRect text_rc = rc;
  text_rc.left += line_height + padding;

  if (show_leg_info) {
    // Draw leg distance
    FormatUserDistanceSmart(leg.distance, buffer, true);
    const int x1 = row_renderer.DrawRightFirstRow(canvas, rc, buffer);

    // Draw leg bearing
    FormatBearing(buffer, ARRAY_SIZE(buffer), leg.bearing);
    const int x2 = row_renderer.DrawRightSecondRow(canvas, rc, buffer);

    text_rc.right = std::min(x1, x2);
  }

  // Draw details line
  OrderedTaskPointRadiusLabel(tp.GetObservationZone(), buffer);
  if (!StringIsEmpty(buffer))
    row_renderer.DrawSecondRow(canvas, text_rc, buffer);

  // Draw turnpoint name
  OrderedTaskPointLabel(tp.GetType(), tp.GetWaypoint().name.c_str(),
                        DrawListIndex, buffer);
  row_renderer.DrawFirstRow(canvas, text_rc, buffer);

  // Draw icon
  const RasterPoint pt(rc.left + line_height / 2,
                       rc.top + line_height / 2);

  const unsigned radius = line_height / 2 - padding;
  OZPreviewRenderer::Draw(canvas, tp.GetObservationZone(),
                          pt, radius, task_look,
                          CommonInterface::GetMapSettings().airspace,
                          airspace_look);
}
Beispiel #8
0
static void
DisplayParsedMETAR(const NOAAStore::Item &station)
{
  if (!station.parsed_metar_available) {
    printf("METAR parsing failed!\n");;
    return;
  }

  const ParsedMETAR &parsed = station.parsed_metar;

  printf("Parsed Data:\n");

  if (parsed.name_available)
    _tprintf(_T("Name: %s\n"), parsed.name.c_str());

  if (parsed.location_available) {
    TCHAR buffer[256];
    FormatGeoPoint(parsed.location, buffer, ARRAY_SIZE(buffer),
                   CoordinateFormat::DDMMSS);
    _tprintf(_T("Location: %s\n"), buffer);
  }

  if (parsed.qnh_available) {
    TCHAR buffer[256];
    FormatUserPressure(parsed.qnh, buffer, ARRAY_SIZE(buffer));
    _tprintf(_T("QNH: %s\n"), buffer);
  }

  if (parsed.wind_available) {
    TCHAR buffer[256];
    FormatUserWindSpeed(parsed.wind.norm, buffer, ARRAY_SIZE(buffer));
    _tprintf(_T("Wind: %.0f" DEG " %s\n"),
             (double)parsed.wind.bearing.Degrees(), buffer);
  }

  if (parsed.temperatures_available) {
    TCHAR buffer[256];
    FormatUserTemperature(parsed.temperature, buffer, ARRAY_SIZE(buffer));
    _tprintf(_T("Temperature: %s\n"), buffer);
    FormatUserTemperature(parsed.dew_point, buffer, ARRAY_SIZE(buffer));
    _tprintf(_T("Dew point: %s\n"), buffer);
  }

  if (parsed.visibility_available) {
    TCHAR buffer[256];
    if (parsed.visibility >= 9999)
      _tcscpy(buffer, _T("unlimited"));
    else {
      fixed visibility(parsed.visibility);
      FormatUserDistanceSmart(visibility, buffer, ARRAY_SIZE(buffer));
    }
    _tprintf(_T("Visibility: %s\n"), buffer);
  }

  printf("\n");
}
void
WaypointListRenderer::Draw(Canvas &canvas, const PixelRect rc,
                           const Waypoint &waypoint, fixed distance,
                           fixed arrival_altitude,
                           const DialogLook &dialog_look,
                           const WaypointLook &look,
                           const WaypointRendererSettings &settings)
{
  const PixelScalar line_height = rc.bottom - rc.top;

  const Font &name_font = *dialog_look.list.font;
  const Font &small_font = *dialog_look.small_font;

  // Y-Coordinate of the second row
  PixelScalar top2 = rc.top + name_font.GetHeight() + Layout::FastScale(4);

  // Use small font for details
  canvas.Select(small_font);

  // Draw distance and arrival altitude
  StaticString<256> buffer;
  TCHAR dist[20], alt[20], radio[20];
  FormatUserDistanceSmart(distance, dist, true);
  FormatRelativeUserAltitude(arrival_altitude, alt, true);
  buffer.Format(_T("%s: %s - %s: %s"), _("Distance"), dist,
                _("Arrival Alt"), alt);

  if (waypoint.radio_frequency.IsDefined()) {
    waypoint.radio_frequency.Format(radio, ARRAY_SIZE(radio));
    buffer.AppendFormat(_T(" - %s MHz"), radio);
  }

  UPixelScalar left = rc.left + line_height + Layout::FastScale(2);
  canvas.text_clipped(left, top2, rc, buffer);

  // Draw waypoint name
  canvas.Select(name_font);
  canvas.text_clipped(left, rc.top + Layout::FastScale(2), rc,
                      waypoint.name.c_str());

  // Draw icon
  RasterPoint pt = { PixelScalar(rc.left + line_height / 2),
                     PixelScalar(rc.top + line_height / 2) };

  WaypointIconRenderer::Reachability reachable =
      positive(arrival_altitude) ?
      WaypointIconRenderer::ReachableTerrain : WaypointIconRenderer::Unreachable;

  WaypointIconRenderer wir(settings, look, canvas);
  wir.Draw(waypoint, pt, reachable);
}
Beispiel #10
0
/**
 * Paints the radar circle on the given canvas
 * @param canvas The canvas to paint on
 */
void
FlarmTrafficWindow::PaintRadarBackground(Canvas &canvas) const
{
  canvas.SelectHollowBrush();
  canvas.Select(look.radar_pen);
  canvas.SetTextColor(look.radar_color);

  // Paint circles
  canvas.circle(radar_mid.x, radar_mid.y, radius);
  canvas.circle(radar_mid.x, radar_mid.y, radius / 2);

  PaintRadarPlane(canvas);

  if (small)
    return;

  // Paint zoom strings
  canvas.Select(look.label_font);
  canvas.SetBackgroundOpaque();
  canvas.SetBackgroundColor(look.background_color);

  TCHAR distance_string[10];
  FormatUserDistanceSmart(distance, distance_string,
                            ARRAY_SIZE(distance_string));
  PixelSize s = canvas.CalcTextSize(distance_string);
  canvas.text(radar_mid.x - s.cx / 2,
              radar_mid.y + radius - s.cy * 0.75, distance_string);

  FormatUserDistanceSmart(distance / 2, distance_string,
                            ARRAY_SIZE(distance_string));
  s = canvas.CalcTextSize(distance_string);
  canvas.text(radar_mid.x - s.cx / 2,
              radar_mid.y + radius / 2 - s.cy * 0.75, distance_string);

  canvas.SetBackgroundTransparent();

  PaintNorth(canvas);
}
/**
 * Updates all the dialogs fields, that are changing frequently.
 * e.g. climb speed, distance, height
 */
void
FlarmTrafficDetailsWidget::UpdateChanging(const MoreData &basic)
{
  TCHAR tmp[40];
  const TCHAR *value;

  const FlarmTraffic* target =
    basic.flarm.traffic.FindTraffic(target_id);

  bool target_ok = target && target->IsDefined();

  // Fill distance/direction field
  if (target_ok) {
    FormatUserDistanceSmart(target->distance, tmp, 20, fixed(1000));
    TCHAR *p = tmp + _tcslen(tmp);
    *p++ = _T(' ');
    FormatAngleDelta(p, 20, target->Bearing() - basic.track);
    value = tmp;
  } else
    value = _T("--");

  SetText(DISTANCE, value);

  // Fill altitude field
  if (target_ok) {
    TCHAR *p = tmp;
    if (target->altitude_available) {
      FormatUserAltitude(target->altitude, p, 20);
      p += _tcslen(p);
      *p++ = _T(' ');
    }

    Angle dir = Angle::FromXY(target->distance, target->relative_altitude);
    FormatVerticalAngleDelta(p, 20, dir);

    value = tmp;
  } else
    value = _T("--");

  SetText(ALTITUDE, value);

  // Fill climb speed field
  if (target_ok && target->climb_rate_avg30s_available) {
    FormatUserVerticalSpeed(target->climb_rate_avg30s, tmp, 20);
    value = tmp;
  } else
    value = _T("--");

  SetText(VARIO, value);
}
Beispiel #12
0
/**
 * Updates all the dialogs fields, that are changing frequently.
 * e.g. climb speed, distance, height
 */
static void
UpdateChanging()
{
  TCHAR tmp[20];
  const FlarmTraffic* target =
    XCSoarInterface::Basic().flarm.traffic.FindTraffic(target_id);

  bool target_ok = target && target->IsDefined();

  // Fill distance field
  if (target_ok)
    FormatUserDistanceSmart(target->distance, tmp, 20, fixed(1000));
  else
    _tcscpy(tmp, _T("--"));
  SetFormValue(*wf, _T("prpDistance"), tmp);

  // Fill horizontal direction field
  if (target_ok)
    FormatAngleDelta(tmp, ARRAY_SIZE(tmp),
                     target->Bearing() - CommonInterface::Basic().track);
  else
    _tcscpy(tmp, _T("--"));
  SetFormValue(*wf, _T("prpDirectionH"), tmp);

  // Fill altitude field
  if (target_ok && target->altitude_available)
    FormatUserAltitude(target->altitude, tmp, 20);
  else
    _tcscpy(tmp, _T("--"));
  SetFormValue(*wf, _T("prpAltitude"), tmp);

  // Fill vertical direction field
  if (target_ok) {
    Angle dir = Angle::Radians((fixed)atan2(target->relative_altitude,
                                            target->distance)).AsDelta();
    FormatVerticalAngleDelta(tmp, ARRAY_SIZE(tmp), dir);
  } else
    _tcscpy(tmp, _T("--"));
  SetFormValue(*wf, _T("prpDirectionV"), tmp);

  // Fill climb speed field
  if (target_ok && target->climb_rate_avg30s_available)
    FormatUserVerticalSpeed(target->climb_rate_avg30s, tmp, 20);
  else
    _tcscpy(tmp, _T("--"));
  SetFormValue(*wf, _T("prpVSpeed"), tmp);
}
void
AirspaceListRenderer::Draw(Canvas &canvas, const PixelRect rc,
                           const AbstractAirspace &airspace,
                           const GeoVector &vector,
                           const DialogLook &dialog_look,
                           const AirspaceLook &look,
                           const AirspaceRendererSettings &renderer_settings)
{
  StaticString<256> comment(AirspaceFormatter::GetClass(airspace));

  TCHAR dist[20], bearing[20];
  FormatUserDistanceSmart(vector.distance, dist, true);
  FormatBearing(bearing, ARRAY_SIZE(bearing), vector.bearing);
  comment.AppendFormat(_T(" - %s - %s"), dist, bearing);

  Draw(canvas, rc, airspace, comment, dialog_look,
       look, renderer_settings);
}
Beispiel #14
0
void
FlightStatusPanel::Refresh()
{
  const NMEAInfo &basic = CommonInterface::Basic();
  const DerivedInfo &calculated = CommonInterface::Calculated();

  StaticString<32> buffer;

  if (basic.location_available) {
    FormatGeoPoint(basic.location, buffer.buffer(), buffer.MAX_SIZE);
    SetText(Location, buffer);
  } else
    SetText(Location, _T(""));

  if (basic.gps_altitude_available) {
    FormatUserAltitude(basic.gps_altitude,
                              buffer.buffer(), buffer.MAX_SIZE);
    SetText(Altitude, buffer);
  } else
    SetText(Altitude, _T(""));

  FormatUserAltitude(calculated.max_height_gain,
                            buffer.buffer(), buffer.MAX_SIZE);
  SetText(MaxHeightGain, buffer);

  if (nearest_waypoint) {
    GeoVector vec(basic.location,
                  nearest_waypoint->location);

    SetText(Near, nearest_waypoint->name.c_str());

    FormatBearing(buffer.buffer(), buffer.MAX_SIZE, vec.bearing, _T(""));
    SetText(Bearing, buffer);

    FormatUserDistanceSmart(vec.distance, buffer.buffer(), buffer.MAX_SIZE);
    SetText(Distance, buffer);
  } else {
    SetText(Near, _T("-"));
    SetText(Bearing, _T("-"));
    SetText(Distance, _T("-"));
  }
}
Beispiel #15
0
void
FlarmTrafficControl::PaintDistance(Canvas &canvas, PixelRect rc,
                                   fixed distance) const
{
  // Format distance
  TCHAR buffer[20];
  Unit unit = FormatUserDistanceSmart(distance, buffer, false, fixed(1000));

  // Calculate unit size
  canvas.Select(look.info_units_font);
  const unsigned unit_width = UnitSymbolRenderer::GetSize(canvas, unit).cx;
  const unsigned unit_height =
      UnitSymbolRenderer::GetAscentHeight(look.info_units_font, unit);

  const unsigned space_width = unit_width / 3;

  // Calculate value size
  canvas.Select(look.info_values_font);
  const unsigned value_height = look.info_values_font.GetAscentHeight();
  const unsigned value_width = canvas.CalcTextSize(buffer).cx;

  // Calculate positions
  const unsigned max_height = std::max(unit_height, value_height);

  // Paint value
  canvas.DrawText(rc.left, rc.bottom - value_height, buffer);

  // Paint unit
  canvas.Select(look.info_units_font);
  UnitSymbolRenderer::Draw(canvas,
                           RasterPoint(rc.left + value_width + space_width,
                                       rc.bottom - unit_height),
                           unit, look.unit_fraction_pen);


  // Paint label
  canvas.Select(look.info_labels_font);
  canvas.DrawText(rc.left,
                  rc.bottom - max_height - look.info_labels_font.GetHeight(),
                  _("Distance"));
}
Beispiel #16
0
void
MapItemListRenderer::Draw(Canvas &canvas, const PixelRect rc,
                          const LocationMapItem &item,
                          const DialogLook &dialog_look)
{
  const Font &name_font = *dialog_look.list.font_bold;
  const Font &small_font = *dialog_look.small_font;

  PixelScalar left = rc.left + Layout::FastScale(2);

  TCHAR info_buffer[256], distance_buffer[32], direction_buffer[32];
  if (item.vector.IsValid()) {
    FormatUserDistanceSmart(item.vector.distance, distance_buffer, 32);
    FormatBearing(direction_buffer, ARRAY_SIZE(direction_buffer),
                  item.vector.bearing);
    _stprintf(info_buffer, _T("%s: %s, %s: %s"),
              _("Distance"), distance_buffer,
              _("Direction"), direction_buffer);
  } else {
    _stprintf(info_buffer, _T("%s: %s, %s: %s"),
              _("Distance"), _T("???"), _("Direction"), _T("???"));
  }

  canvas.Select(name_font);

  canvas.DrawClippedText(left, rc.top + Layout::FastScale(2), rc, info_buffer);


  TCHAR elevation_buffer[32];
  if (!RasterBuffer::IsSpecial(item.elevation)) {
    FormatUserAltitude(fixed(item.elevation), elevation_buffer, 32);
    _stprintf(info_buffer, _T("%s: %s"), _("Elevation"), elevation_buffer);
  } else {
    _stprintf(info_buffer, _T("%s: %s"), _("Elevation"), _T("???"));
  }

  canvas.Select(small_font);
  canvas.DrawClippedText(left,
                         rc.top + name_font.GetHeight() + Layout::FastScale(4),
                         rc, info_buffer);
}
Beispiel #17
0
static void
Draw(Canvas &canvas, const PixelRect rc,
     const LocationMapItem &item,
     const TwoTextRowsRenderer &row_renderer)
{
  TCHAR info_buffer[256];
  if (item.vector.IsValid())
    StringFormatUnsafe(info_buffer, _T("%s: %s, %s: %s"),
                       _("Distance"),
                       FormatUserDistanceSmart(item.vector.distance).c_str(),
                       _("Direction"),
                       FormatBearing(item.vector.bearing).c_str());
  else
    StringFormatUnsafe(info_buffer, _T("%s: %s, %s: %s"),
                       _("Distance"), _T("???"), _("Direction"), _T("???"));

  row_renderer.DrawFirstRow(canvas, rc, info_buffer);

  StringFormatUnsafe(info_buffer, _T("%s: %s"), _("Elevation"),
                     item.HasElevation()
                     ? FormatUserAltitude(item.elevation).c_str()
                     : _T("???"));
  row_renderer.DrawSecondRow(canvas, rc, info_buffer);
}
Beispiel #18
0
static bool
FormatDecodedMETARLine(const TCHAR *line, unsigned length,
                       const ParsedMETAR &parsed, tstring &output)
{
  const TCHAR *end = line + length;

  const TCHAR *colon = (const TCHAR *)memchr(line, _T(':'), length);
  if (!colon)
    return false;

  unsigned title_length = colon - line;
  if (title_length == 0)
    return false;

  const TCHAR *value = colon + 1;
  while (*value == _T(' '))
    value++;

  unsigned value_length = end - value;

  if (CheckTitle(line, title_length, _T("Wind"))) {
    StaticString<256> buffer;

    if (!parsed.wind_available) {
      buffer.Format(_T("%s: "), _("Wind"));
      buffer.append(value, value_length);
    } else {
      TCHAR wind_speed_buffer[16];
      FormatUserWindSpeed(parsed.wind.norm, wind_speed_buffer,
                                 ARRAY_SIZE(wind_speed_buffer));

      buffer.Format(_T("%s: %.0f" DEG " %s"), _("Wind"),
                    (double)parsed.wind.bearing.Degrees(), wind_speed_buffer);
    }
    output += buffer;
    output += '\n';
    return true;
  }

  if (CheckTitle(line, title_length, _T("Temperature"))) {
    StaticString<256> buffer;

    if (!parsed.temperatures_available) {
      buffer.Format(_T("%s: "), _("Temperature"));
      buffer.append(value, value_length);
    } else {
      TCHAR temperature_buffer[16];
      FormatUserTemperature(parsed.temperature, temperature_buffer,
                                   ARRAY_SIZE(temperature_buffer));

      buffer.Format(_T("%s: %s"), _("Temperature"), temperature_buffer);
    }
    output += buffer;
    output += '\n';
    return true;
  }

  if (CheckTitle(line, title_length, _T("Dew Point"))) {
    StaticString<256> buffer;

    if (!parsed.temperatures_available) {
      buffer.Format(_T("%s: "), _("Dew Point"));
      buffer.append(value, value_length);
    } else {
      TCHAR temperature_buffer[16];
      FormatUserTemperature(parsed.dew_point, temperature_buffer,
                                   ARRAY_SIZE(temperature_buffer));

      buffer.Format(_T("%s: %s"), _("Dew Point"), temperature_buffer);
    }
    output += buffer;
    output += '\n';
    return true;
  }

  if (CheckTitle(line, title_length, _T("Pressure (altimeter)"))) {
    StaticString<256> buffer;

    if (!parsed.qnh_available) {
      buffer.Format(_T("%s: "), _("Pressure"));
      buffer.append(value, value_length);
    } else {
      TCHAR qnh_buffer[16];
      FormatUserPressure(parsed.qnh, qnh_buffer, ARRAY_SIZE(qnh_buffer));

      buffer.Format(_T("%s: %s"), _("Pressure"), qnh_buffer);
    }
    output += buffer;
    output += '\n';
    return true;
  }

  if (CheckTitle(line, title_length, _T("Visibility"))) {
    StaticString<256> buffer;

    buffer.Format(_T("%s: "), _("Visibility"));
    if (!parsed.qnh_available) {
      buffer.append(value, value_length);
    } else {
      TCHAR vis_buffer[32];
      if (parsed.visibility >= 9999) {
        FormatUserDistanceSmart(fixed(10000),
                                  vis_buffer, ARRAY_SIZE(vis_buffer));

        buffer.AppendFormat(_("more than %s"), vis_buffer);
      } else {
        FormatUserDistanceSmart(fixed(parsed.visibility),
                                  vis_buffer, ARRAY_SIZE(vis_buffer));
        buffer += vis_buffer;
      }
    }
    output += buffer;
    output += '\n';
    return true;
  }

  if (CheckTitle(line, title_length, _T("Sky conditions"))) {
    StaticString<256> buffer;
    buffer.Format(_T("%s: "), _("Sky Conditions"));

    StaticString<64> _value;
    _value.set(value, value_length);

    buffer += gettext(_value);

    output += buffer;
    output += '\n';
    return true;
  }

  if (CheckTitle(line, title_length, _T("Weather"))) {
    StaticString<256> buffer;
    buffer.Format(_T("%s: "), _("Weather"));

    StaticString<64> _value;
    _value.set(value, value_length);

    buffer += gettext(_value);

    output += buffer;
    output += '\n';
    return true;
  }

  StaticString<64> title;
  title.set(line, title_length);

  StaticString<256> buffer;
  buffer.Format(_T("%s: "), gettext(title.c_str()));
  buffer.append(value, value_length);

  output += buffer;
  output += '\n';

  return true;
}
Beispiel #19
0
void
WaypointInfoWidget::Prepare(ContainerWindow &parent, const PixelRect &rc)
{
  RowFormWidget::Prepare(parent, rc);

  const MoreData &basic = CommonInterface::Basic();
  const DerivedInfo &calculated = CommonInterface::Calculated();
  const ComputerSettings &settings = CommonInterface::GetComputerSettings();

  StaticString<64> buffer;

  if (!waypoint.comment.empty())
    AddMultiLine(waypoint.comment.c_str());

  if (waypoint.radio_frequency.IsDefined() &&
      waypoint.radio_frequency.Format(buffer.buffer(),
                                      buffer.MAX_SIZE) != NULL) {
    buffer += _T(" MHz");
    AddReadOnly(_("Radio frequency"), NULL, buffer);
  }

  if (waypoint.runway.IsDirectionDefined())
    buffer.UnsafeFormat(_T("%02u"), waypoint.runway.GetDirectionName());
  else
    buffer.clear();

  if (waypoint.runway.IsLengthDefined()) {
    if (!buffer.empty())
      buffer += _T("; ");

    TCHAR length_buffer[16];
    FormatSmallUserDistance(length_buffer,
                                   fixed(waypoint.runway.GetLength()));
    buffer += length_buffer;
  }

  if (!buffer.empty())
    AddReadOnly(_("Runway"), NULL, buffer);

  if (FormatGeoPoint(waypoint.location,
                     buffer.buffer(), buffer.MAX_SIZE) != NULL)
    AddReadOnly(_("Location"), NULL, buffer);

  FormatUserAltitude(waypoint.elevation,
                            buffer.buffer(), buffer.MAX_SIZE);
  AddReadOnly(_("Elevation"), NULL, buffer);

  if (basic.time_available) {
    const SunEphemeris::Result sun =
      SunEphemeris::CalcSunTimes(waypoint.location, basic.date_time_utc,
                                 fixed(GetUTCOffset()) / 3600);

    const unsigned sunrisehours = (int)sun.time_of_sunrise;
    const unsigned sunrisemins = (int)((sun.time_of_sunrise - fixed(sunrisehours)) * 60);
    const unsigned sunset_hour = (int)sun.time_of_sunset;
    const unsigned sunset_minute = (int)((sun.time_of_sunset - fixed(sunset_hour)) * 60);

    buffer.UnsafeFormat(_T("%02u:%02u - %02u:%02u"), sunrisehours, sunrisemins, sunset_hour, sunset_minute);
    AddReadOnly(_("Daylight time"), NULL, buffer);
  }

  if (basic.location_available) {
    const GeoVector vector = basic.location.DistanceBearing(waypoint.location);

    TCHAR distance_buffer[32];
    FormatUserDistanceSmart(vector.distance, distance_buffer,
                                   ARRAY_SIZE(distance_buffer));

    FormatBearing(buffer.buffer(), buffer.MAX_SIZE,
                  vector.bearing, distance_buffer);
    AddReadOnly(_("Bearing and Distance"), NULL, buffer);
  }

  if (basic.location_available && basic.NavAltitudeAvailable() &&
      settings.polar.glide_polar_task.IsValid()) {
    const GlideState glide_state(basic.location.DistanceBearing(waypoint.location),
                                 waypoint.elevation + settings.task.safety_height_arrival,
                                 basic.nav_altitude,
                                 calculated.GetWindOrZero());

    GlidePolar gp0 = settings.polar.glide_polar_task;
    gp0.SetMC(fixed(0));
    AddGlideResult(_("Alt. diff. MC 0"),
                   MacCready::Solve(settings.task.glide,
                                    gp0, glide_state));

    AddGlideResult(_("Alt. diff. MC safety"),
                   MacCready::Solve(settings.task.glide,
                                    calculated.glide_polar_safety,
                                    glide_state));

    AddGlideResult(_("Alt. diff. MC current"),
                   MacCready::Solve(settings.task.glide,
                                    settings.polar.glide_polar_task,
                                    glide_state));
  }
}
Beispiel #20
0
void
InfoBoxData::SetCommentFromDistance(fixed new_value)
{
  FormatUserDistanceSmart(new_value, comment.buffer());
}
Beispiel #21
0
void
TaskStatusPanel::Refresh()
{
  if (protected_task_manager == nullptr)
    return;

  const DerivedInfo &calculated = CommonInterface::Calculated();
  const TaskStats &task_stats = calculated.ordered_task_stats;

  SetRowVisible(TaskTime, task_stats.has_targets);
  if (task_stats.has_targets)
    SetText(TaskTime,
            FormatSignedTimeHHMM((int)protected_task_manager->GetOrderedTaskSettings().aat_min_time));

  SetText(ETETime,
          FormatSignedTimeHHMM((int)task_stats.GetEstimatedTotalTime()));

  SetText(RemainingTime,
          FormatSignedTimeHHMM((int)task_stats.total.time_remaining_now));

  if (task_stats.total.planned.IsDefined())
    SetText(TaskDistance,
            FormatUserDistanceSmart(task_stats.total.planned.GetDistance()));
  else
    ClearText(TaskDistance);

  if (task_stats.total.remaining.IsDefined())
    SetText(RemainingDistance,
            FormatUserDistanceSmart(task_stats.total.remaining.GetDistance()));

  if (task_stats.total.planned.IsDefined())
    SetText(EstimatedSpeed,
            FormatUserTaskSpeed(task_stats.total.planned.GetSpeed()));
  else
    ClearText(EstimatedSpeed);

  if (task_stats.total.travelled.IsDefined())
    SetText(AverageSpeed,
            FormatUserTaskSpeed(task_stats.total.travelled.GetSpeed()));
  else
    ClearText(AverageSpeed);

  LoadValue(MC,
            CommonInterface::GetComputerSettings().polar.glide_polar_task.GetMC(),
            UnitGroup::VERTICAL_SPEED);

  if (task_stats.total.planned.IsDefined()) {
    auto rMax = task_stats.distance_max;
    auto rMin = task_stats.distance_min;

    if (rMin < rMax) {
      auto range = 2 * (task_stats.total.planned.GetDistance() - rMin) / (rMax - rMin) - 1;
      LoadValue(RANGE, range * 100);
    } else
      ClearValue(RANGE);
  } else
    ClearValue(RANGE);

  if (task_stats.total.remaining_effective.IsDefined())
    LoadValue(SPEED_REMAINING, task_stats.total.remaining_effective.GetSpeed(),
              UnitGroup::TASK_SPEED);
  else
    ClearValue(SPEED_REMAINING);

  LoadValue(EFFECTIVE_MC, task_stats.effective_mc, UnitGroup::VERTICAL_SPEED);

  if (task_stats.total.travelled.IsDefined())
    LoadValue(SPEED_ACHIEVED, task_stats.total.travelled.GetSpeed(),
              UnitGroup::TASK_SPEED);
  else
    ClearValue(SPEED_ACHIEVED);

  LoadValue(CRUISE_EFFICIENCY, task_stats.cruise_efficiency * 100);
}
Beispiel #22
0
/**
 * Paints the basic info for the selected target on the given canvas
 * @param canvas The canvas to paint on
 */
void
FlarmTrafficControl2::PaintTrafficInfo(Canvas &canvas) const
{
  // Don't paint numbers if no plane selected
  if (selection == -1 && !WarningMode())
    return;

  // Shortcut to the selected traffic
  FlarmTraffic traffic = data.list[WarningMode() ? warning : selection];
  assert(traffic.IsDefined());

  // Temporary string
  TCHAR tmp[20];
  // Temporary string size
  PixelSize sz;

  PixelRect rc;
  rc.left = padding;
  rc.top = padding;
  rc.right = canvas.get_width() - padding;
  rc.bottom = canvas.get_height() - padding;

  // Set the text color and background
  switch (traffic.alarm_level) {
  case FlarmTraffic::AlarmType::LOW:
  case FlarmTraffic::AlarmType::INFO_ALERT:
    canvas.SetTextColor(look.warning_color);
    break;
  case FlarmTraffic::AlarmType::IMPORTANT:
  case FlarmTraffic::AlarmType::URGENT:
    canvas.SetTextColor(look.alarm_color);
    break;
  case FlarmTraffic::AlarmType::NONE:
    canvas.SetTextColor(look.default_color);
    break;
  }

  canvas.SetBackgroundTransparent();

  // Climb Rate
  if (!WarningMode() && traffic.climb_rate_avg30s_available) {
    FormatUserVerticalSpeed(traffic.climb_rate_avg30s, tmp, 20);
    canvas.Select(look.info_values_font);
    sz = canvas.CalcTextSize(tmp);
    canvas.text(rc.right - sz.cx, rc.top + look.info_labels_font.GetHeight(), tmp);

    canvas.Select(look.info_labels_font);
    sz = canvas.CalcTextSize(_("Vario"));
    canvas.text(rc.right - sz.cx, rc.top, _("Vario"));
  }

  // Distance
  FormatUserDistanceSmart(traffic.distance, tmp, 20, fixed(1000));
  canvas.Select(look.info_values_font);
  sz = canvas.CalcTextSize(tmp);
  canvas.text(rc.left, rc.bottom - sz.cy, tmp);

  canvas.Select(look.info_labels_font);
  canvas.text(rc.left,
              rc.bottom - look.info_values_font.GetHeight() - look.info_labels_font.GetHeight(),
              _("Distance"));

  // Relative Height
  FormatRelativeUserAltitude(traffic.relative_altitude, tmp, 20);
  canvas.Select(look.info_values_font);
  sz = canvas.CalcTextSize(tmp);
  canvas.text(rc.right - sz.cx, rc.bottom - sz.cy, tmp);

  canvas.Select(look.info_labels_font);
  sz = canvas.CalcTextSize(_("Rel. Alt."));
  canvas.text(rc.right - sz.cx,
              rc.bottom - look.info_values_font.GetHeight() - look.info_labels_font.GetHeight(),
              _("Rel. Alt."));

  // ID / Name
  unsigned font_size;
  if (traffic.HasName()) {
    canvas.Select(look.call_sign_font);
    font_size = look.call_sign_font.GetHeight();

    if (!traffic.HasAlarm())
      canvas.SetTextColor(look.selection_color);

    _tcscpy(tmp, traffic.name);
  } else {
    font_size = look.info_labels_font.GetHeight();
    traffic.id.Format(tmp);
  }

  if (!WarningMode()) {
    // Team color dot
    FlarmFriends::Color team_color = FlarmFriends::GetFriendColor(traffic.id);

    // If no color found but target is teammate
    if (team_color == FlarmFriends::Color::NONE &&
        settings.team_flarm_tracking &&
        traffic.id == settings.team_flarm_id)
      // .. use yellow color
      team_color = FlarmFriends::Color::GREEN;

    // If team color found -> draw a colored circle around the target
    if (team_color != FlarmFriends::Color::NONE) {
      switch (team_color) {
      case FlarmFriends::Color::GREEN:
        canvas.Select(look.team_brush_green);
        break;
      case FlarmFriends::Color::BLUE:
        canvas.Select(look.team_brush_blue);
        break;
      case FlarmFriends::Color::YELLOW:
        canvas.Select(look.team_brush_green);
        break;
      case FlarmFriends::Color::MAGENTA:
        canvas.Select(look.team_brush_magenta);
        break;
      default:
        break;
      }

      canvas.SelectNullPen();
      canvas.DrawCircle(rc.left + Layout::FastScale(7), rc.top + (font_size / 2),
                    Layout::FastScale(7));

      rc.left += Layout::FastScale(16);
    }
  }

  canvas.text(rc.left, rc.top, tmp);
}
Beispiel #23
0
void
TrafficListWidget::OnPaintItem(Canvas &canvas, PixelRect rc,
                               unsigned index)
{
  assert(index < items.size());
  Item &item = items[index];

  assert(item.IsFlarm()
#ifdef HAVE_SKYLINES_TRACKING_HANDLER
         || item.IsSkyLines()
#endif
         );

  item.AutoLoad();

  const FlarmNetRecord *record = item.record;
  const TCHAR *callsign = item.callsign;

  const DialogLook &look = UIGlobals::GetDialogLook();
  const Font &name_font = *look.list.font_bold;
  const Font &small_font = look.small_font;

  const unsigned text_padding = Layout::GetTextPadding();
  const unsigned frame_padding = text_padding / 2;

  TCHAR tmp_id[10];
  item.id.Format(tmp_id);

  canvas.Select(name_font);

  StaticString<256> tmp;

  if (item.IsFlarm()) {
    if (record != nullptr)
      tmp.Format(_T("%s - %s - %s"),
                 callsign, record->registration.c_str(), tmp_id);
    else if (callsign != nullptr)
      tmp.Format(_T("%s - %s"), callsign, tmp_id);
    else
      tmp.Format(_T("%s"), tmp_id);
#ifdef HAVE_SKYLINES_TRACKING_HANDLER
  } else if (item.IsSkyLines()) {
    if (!item.name.empty())
      tmp = item.name.c_str();
    else
      tmp.UnsafeFormat(_T("SkyLines %u"), item.skylines_id);
#endif
  } else {
    tmp = _T("?");
  }

  if (item.color != FlarmColor::NONE) {
    const TrafficLook &traffic_look = UIGlobals::GetLook().traffic;

    switch (item.color) {
    case FlarmColor::NONE:
    case FlarmColor::COUNT:
      gcc_unreachable();

    case FlarmColor::GREEN:
      canvas.Select(traffic_look.team_pen_green);
      break;
    case FlarmColor::BLUE:
      canvas.Select(traffic_look.team_pen_blue);
      break;
    case FlarmColor::YELLOW:
      canvas.Select(traffic_look.team_pen_yellow);
      break;
    case FlarmColor::MAGENTA:
      canvas.Select(traffic_look.team_pen_magenta);
      break;
    }

    canvas.SelectHollowBrush();

    const PixelSize size = canvas.CalcTextSize(tmp);
    canvas.Rectangle(rc.left + row_renderer.GetX() - frame_padding,
                     rc.top + row_renderer.GetFirstY() - frame_padding,
                     rc.left + row_renderer.GetX() + size.cx + frame_padding,
                     rc.top + row_renderer.GetFirstY() + size.cy + frame_padding);
  }

  row_renderer.DrawFirstRow(canvas, rc, tmp);

  canvas.Select(small_font);

  /* draw bearing and distance on the right */
  if (item.vector.IsValid()) {
    row_renderer.DrawRightFirstRow(canvas, rc,
                                            FormatUserDistanceSmart(item.vector.distance).c_str());

    // Draw leg bearing
    rc.right = row_renderer.DrawRightSecondRow(canvas, rc,
                                               FormatBearing(item.vector.bearing).c_str());
  }

  if (record != nullptr) {
    tmp.clear();

    if (!record->pilot.empty())
      tmp = record->pilot.c_str();

    if (!record->plane_type.empty()) {
      if (!tmp.empty())
        tmp.append(_T(" - "));

      tmp.append(record->plane_type);
    }

    if (!record->airfield.empty()) {
      if (!tmp.empty())
        tmp.append(_T(" - "));

      tmp.append(record->airfield);
    }

    if (!tmp.empty())
      row_renderer.DrawSecondRow(canvas, rc, tmp);
#ifdef HAVE_SKYLINES_TRACKING_HANDLER
  } else if (item.IsSkyLines()) {
    if (CommonInterface::Basic().time_available) {
      tmp.UnsafeFormat(_("%u minutes ago"),
                       SinceInMinutes(CommonInterface::Basic().time,
                                      item.time_of_day_ms));
    } else
      tmp.clear();

    if (!item.near_name.empty())
      tmp.AppendFormat(_T(" near %s (%s)"),
                       item.near_name.c_str(),
                       FormatUserDistanceSmart(item.near_distance).c_str());

    if (!tmp.empty())
      tmp.append(_T("; "));
    tmp.append(FormatUserAltitude(item.altitude));

    if (!tmp.empty())
      row_renderer.DrawSecondRow(canvas, rc, tmp);
#endif
  }
}
Beispiel #24
0
void
TrafficListWidget::OnPaintItem(Canvas &canvas, const PixelRect rc,
                               unsigned index)
{
  assert(index < items.size());
  Item &item = items[index];

  assert(item.IsFlarm()
#ifdef HAVE_SKYLINES_TRACKING_HANDLER
         || item.IsSkyLines()
#endif
         );

  item.AutoLoad();

  const FlarmNetRecord *record = item.record;
  const TCHAR *callsign = item.callsign;

  const DialogLook &look = UIGlobals::GetDialogLook();
  const Font &name_font = *look.list.font_bold;
  const Font &small_font = *look.small_font;

  const unsigned text_padding = Layout::GetTextPadding();
  const unsigned frame_padding = text_padding / 2;

  TCHAR tmp_id[10];
  item.id.Format(tmp_id);

  canvas.Select(name_font);

  StaticString<256> tmp;

  if (item.IsFlarm()) {
    if (record != NULL)
      tmp.Format(_T("%s - %s - %s"),
                 callsign, record->registration.c_str(), tmp_id);
    else if (callsign != NULL)
      tmp.Format(_T("%s - %s"), callsign, tmp_id);
    else
      tmp.Format(_T("%s"), tmp_id);
#ifdef HAVE_SKYLINES_TRACKING_HANDLER
  } else if (item.IsSkyLines()) {
    tmp.UnsafeFormat(_T("SkyLines %u"), item.skylines_id);
#endif
  } else {
    tmp = _T("?");
  }

  const int name_x = rc.left + text_padding, name_y = rc.top + text_padding;

  if (item.color != FlarmColor::NONE) {
    const TrafficLook &traffic_look = UIGlobals::GetLook().traffic;

    switch (item.color) {
    case FlarmColor::NONE:
    case FlarmColor::COUNT:
      gcc_unreachable();

    case FlarmColor::GREEN:
      canvas.Select(traffic_look.team_pen_green);
      break;
    case FlarmColor::BLUE:
      canvas.Select(traffic_look.team_pen_blue);
      break;
    case FlarmColor::YELLOW:
      canvas.Select(traffic_look.team_pen_yellow);
      break;
    case FlarmColor::MAGENTA:
      canvas.Select(traffic_look.team_pen_magenta);
      break;
    }

    canvas.SelectHollowBrush();

    const PixelSize size = canvas.CalcTextSize(tmp);
    canvas.Rectangle(name_x - frame_padding,
                     name_y - frame_padding,
                     name_x + size.cx + frame_padding,
                     name_y + size.cy + frame_padding);
  }

  canvas.DrawText(name_x, name_y, tmp);

  if (record != NULL) {
    tmp.clear();

    if (!record->pilot.empty())
      tmp = record->pilot.c_str();

    if (!record->plane_type.empty()) {
      if (!tmp.empty())
        tmp.append(_T(" - "));

      tmp.append(record->plane_type);
    }

    if (!record->airfield.empty()) {
      if (!tmp.empty())
        tmp.append(_T(" - "));

      tmp.append(record->airfield);
    }

    if (!tmp.empty()) {
      canvas.Select(small_font);
      canvas.DrawText(rc.left + text_padding,
                      rc.bottom - small_font.GetHeight() - text_padding,
                      tmp);
    }
  }

  /* draw bearing and distance on the right */
  if (item.vector.IsValid()) {
    FormatUserDistanceSmart(item.vector.distance, tmp.buffer(), true);
    unsigned width = canvas.CalcTextWidth(tmp.c_str());
    canvas.DrawText(rc.right - text_padding - width,
                    name_y +
                    (name_font.GetHeight() - small_font.GetHeight()) / 2,
                    tmp.c_str());

    // Draw leg bearing
    FormatBearing(tmp.buffer(), tmp.MAX_SIZE, item.vector.bearing);
    width = canvas.CalcTextWidth(tmp.c_str());
    canvas.DrawText(rc.right - text_padding - width,
                    rc.bottom - small_font.GetHeight() - text_padding,
                    tmp.c_str());
  }

}
Beispiel #25
0
void
TaskEditPanel::OnPaintItem(Canvas &canvas, const PixelRect rc,
                           unsigned DrawListIndex)
{
  assert(DrawListIndex <= ordered_task->TaskSize());

  const PixelScalar line_height = rc.bottom - rc.top;

  TCHAR buffer[120];

  const Font &name_font = *dialog.GetLook().list.font_bold;
  const Font &small_font = *dialog.GetLook().small_font;

  // Draw "Add turnpoint" label
  if (DrawListIndex == ordered_task->TaskSize()) {
    canvas.Select(name_font);
    canvas.SetTextColor(COLOR_BLACK);
    _stprintf(buffer, _T("  (%s)"), _("Add Turnpoint"));
    canvas.DrawText(rc.left + line_height + Layout::FastScale(2),
                    rc.top + line_height / 2 - name_font.GetHeight() / 2,
                    buffer);
    return;
  }

  const OrderedTaskPoint &tp = ordered_task->GetTaskPoint(DrawListIndex);
  GeoVector leg = tp.GetNominalLegVector();
  bool show_leg_info = leg.distance > fixed(0.01);

  // Draw icon
  const RasterPoint pt(rc.left + line_height / 2,
                       rc.top + line_height / 2);

  PixelScalar radius = std::min(PixelScalar(line_height / 2
                                            - Layout::FastScale(4)),
                                Layout::FastScale(10));

  OZPreviewRenderer::Draw(canvas, tp.GetObservationZone(),
                          pt, radius, task_look,
                          CommonInterface::GetMapSettings().airspace,
                          airspace_look);

  // Y-Coordinate of the second row
  PixelScalar top2 = rc.top + name_font.GetHeight() + Layout::FastScale(4);

  // Use small font for details
  canvas.Select(small_font);
  canvas.SetTextColor(COLOR_BLACK);

  UPixelScalar leg_info_width = 0;
  if (show_leg_info) {
    // Draw leg distance
    FormatUserDistanceSmart(leg.distance, buffer, true);
    UPixelScalar width = leg_info_width = canvas.CalcTextWidth(buffer);
    canvas.DrawText(rc.right - Layout::FastScale(2) - width,
                    rc.top + Layout::FastScale(2) +
                    (name_font.GetHeight() - small_font.GetHeight()) / 2,
                    buffer);

    // Draw leg bearing
    FormatBearing(buffer, ARRAY_SIZE(buffer), leg.bearing);
    width = canvas.CalcTextWidth(buffer);
    canvas.DrawText(rc.right - Layout::FastScale(2) - width, top2, buffer);

    if (width > leg_info_width)
      leg_info_width = width;

    leg_info_width += Layout::FastScale(2);
  }

  // Draw details line
  PixelScalar left = rc.left + line_height + Layout::FastScale(2);
  OrderedTaskPointRadiusLabel(tp.GetObservationZone(), buffer);
  if (!StringIsEmpty(buffer))
    canvas.DrawClippedText(left, top2, rc.right - leg_info_width - left,
                           buffer);

  // Draw turnpoint name
  canvas.Select(name_font);
  OrderedTaskPointLabel(tp.GetType(), tp.GetWaypoint().name.c_str(),
                        DrawListIndex, buffer);
  canvas.DrawClippedText(left, rc.top + Layout::FastScale(2),
                         rc.right - leg_info_width - left, buffer);
}
Beispiel #26
0
void
WaypointInfoWidget::Prepare(ContainerWindow &parent, const PixelRect &rc)
{
  RowFormWidget::Prepare(parent, rc);

  const MoreData &basic = CommonInterface::Basic();
  const DerivedInfo &calculated = CommonInterface::Calculated();
  const ComputerSettings &settings = CommonInterface::GetComputerSettings();

  StaticString<64> buffer;

  if (!waypoint.comment.empty())
    AddMultiLine(waypoint.comment.c_str());

  if (waypoint.radio_frequency.IsDefined() &&
      waypoint.radio_frequency.Format(buffer.buffer(),
                                      buffer.MAX_SIZE) != nullptr) {
    buffer += _T(" MHz");
    AddReadOnly(_("Radio frequency"), nullptr, buffer);
  }

  if (waypoint.runway.IsDirectionDefined())
    buffer.UnsafeFormat(_T("%02u"), waypoint.runway.GetDirectionName());
  else
    buffer.clear();

  if (waypoint.runway.IsLengthDefined()) {
    if (!buffer.empty())
      buffer += _T("; ");

    TCHAR length_buffer[16];
    FormatSmallUserDistance(length_buffer,
                                   fixed(waypoint.runway.GetLength()));
    buffer += length_buffer;
  }

  if (!buffer.empty())
    AddReadOnly(_("Runway"), nullptr, buffer);

  if (FormatGeoPoint(waypoint.location,
                     buffer.buffer(), buffer.MAX_SIZE) != nullptr)
    AddReadOnly(_("Location"), nullptr, buffer);

  FormatUserAltitude(waypoint.elevation,
                            buffer.buffer(), buffer.MAX_SIZE);
  AddReadOnly(_("Elevation"), nullptr, buffer);

  if (basic.time_available && basic.date_time_utc.IsDatePlausible()) {
    const SunEphemeris::Result sun =
      SunEphemeris::CalcSunTimes(waypoint.location, basic.date_time_utc,
                                 settings.utc_offset);

    const BrokenTime sunrise = BreakHourOfDay(sun.time_of_sunrise);
    const BrokenTime sunset = BreakHourOfDay(sun.time_of_sunset);

    buffer.UnsafeFormat(_T("%02u:%02u - %02u:%02u"),
                        sunrise.hour, sunrise.minute,
                        sunset.hour, sunset.minute);
    AddReadOnly(_("Daylight time"), nullptr, buffer);
  }

  if (basic.location_available) {
    const GeoVector vector = basic.location.DistanceBearing(waypoint.location);

    TCHAR distance_buffer[32];
    FormatUserDistanceSmart(vector.distance, distance_buffer,
                                   ARRAY_SIZE(distance_buffer));

    FormatBearing(buffer.buffer(), buffer.MAX_SIZE,
                  vector.bearing, distance_buffer);
    AddReadOnly(_("Bearing and Distance"), nullptr, buffer);
  }

  if (basic.location_available && basic.NavAltitudeAvailable() &&
      settings.polar.glide_polar_task.IsValid()) {
    const GlideState glide_state(basic.location.DistanceBearing(waypoint.location),
                                 waypoint.elevation + settings.task.safety_height_arrival,
                                 basic.nav_altitude,
                                 calculated.GetWindOrZero());

    GlidePolar gp0 = settings.polar.glide_polar_task;
    gp0.SetMC(fixed(0));
    AddGlideResult(_("Alt. diff. MC 0"),
                   MacCready::Solve(settings.task.glide,
                                    gp0, glide_state));

    AddGlideResult(_("Alt. diff. MC safety"),
                   MacCready::Solve(settings.task.glide,
                                    calculated.glide_polar_safety,
                                    glide_state));

    AddGlideResult(_("Alt. diff. MC current"),
                   MacCready::Solve(settings.task.glide,
                                    settings.polar.glide_polar_task,
                                    glide_state));
  }

  if (basic.location_available && basic.NavAltitudeAvailable()) {
    const TaskBehaviour &task_behaviour =
      CommonInterface::GetComputerSettings().task;

    const fixed safety_height = task_behaviour.safety_height_arrival;
    const fixed target_altitude = waypoint.elevation + safety_height;
    const fixed delta_h = basic.nav_altitude - target_altitude;
    if (positive(delta_h)) {
      const fixed distance = basic.location.Distance(waypoint.location);
      const fixed gr = distance / delta_h;
      if (GradientValid(gr)) {
        buffer.UnsafeFormat(_T("%.1f"), (double)gr);
        AddReadOnly(_("Required glide ratio"), nullptr, buffer);
      }
    }
  }
}